feat(agent): fail-closed seat resolution under MOSAIC_AGENTS_DIR override (#46)

Owner decision after live verification of M18: an explicit agents-dir
override that cannot resolve the named seat now refuses the launch
(exit 4, names the seat and dir) instead of launching seatless and
unbounded. Unsetting the override keeps the M13 plain governed TUI.
MOSAIC_ROLES_DIR needs no symmetric change - the M18 gate already
refuses unresolvable role contracts.

Task suite 88 -> 90 (refusal + refusal-names-the-seat). TOOLS.md Agent
section documents the refusal.

Suites 24/90/14/17 + verify green.
This commit is contained in:
2026-09-03 19:45:10 -05:00
parent ca8135d70c
commit d1d7b5598d
7 changed files with 52 additions and 2 deletions
+8
View File
@@ -57,6 +57,14 @@ fi
# The seat's SOUL.md overrides the contract persona; governance contracts
# are never overridden.
AGENTS_DIR="${MOSAIC_AGENTS_DIR:-agents}"
# Fail closed (owner decision, #46): an explicit agents-dir override that
# cannot resolve the named seat refuses the launch - a seatless launch has
# no identity, no SOUL, and no role ceiling to bind. Unset the override for
# the M13 plain governed TUI.
if [ -n "${MOSAIC_AGENTS_DIR:-}" ] && [ ! -f "$AGENTS_DIR/$NAME/agent.json" ]; then
echo "agent: no seat definition for '$NAME' in overridden agents dir: $AGENTS_DIR (unset MOSAIC_AGENTS_DIR for a plain governed TUI)" >&2
exit 4
fi
ROLE=""
DEFCAPS=""
AGENT_DEF_SKILLS=""
+14
View File
@@ -299,6 +299,20 @@ EOF
grep -q "nothing in common -> tool-free seat" "$SANDBOX/roleseat-stderr.txt" 2>/dev/null \
&& check "tool-free outcome recorded loudly" 0 || check "tool-free outcome recorded loudly" 1
# fail-closed seat resolution (#46, owner decision): an explicit
# agents-dir override that cannot resolve the named seat refuses.
env MOSAIC_CONFIG="$SANDBOX/mock-config.json" MOSAIC_AGENTS_DIR="$SANDBOX/agents" \
scripts/agent.sh nobody </dev/null >"$SANDBOX/nobody-stdout.txt" 2>"$SANDBOX/nobody-stderr.txt"
RC=$?
if [ "$RC" -eq 4 ]; then
PASS=$((PASS+1)); echo "${C_OK}OK${C_RESET} overridden agents dir without seat definition refuses (exit 4)"
else
FAIL=$((FAIL+1)); echo "${C_FAIL}FAIL${C_RESET} overridden agents dir without seat definition refuses (exit $RC)" >&2
echo "NOBODY stderr:" >&2; cat "$SANDBOX/nobody-stderr.txt" >&2
fi
grep -q "no seat definition for 'nobody'" "$SANDBOX/nobody-stderr.txt" 2>/dev/null \
&& check "seat-resolution refusal names the seat" 0 || check "seat-resolution refusal names the seat" 1
# capability policy (M9): least-privilege intersection
POL="$SANDBOX/data/workspaces"; mkdir -p "$POL"
pol_run() { # missionTools(ABSENT|json) taskTools(ABSENT|json) -> stderr MOSAIC_TOOLS value