feat(framework): P4 (2/2) — TS installer parity + fixtures + fail-closed init
Some checks failed
ci/woodpecker/pr/ci Pipeline failed
ci/woodpecker/push/ci Pipeline was successful

Mirror install.sh's upgrade-safe migration in the npm/TS install path and lock it
with CI-gating fixtures:
- file-adapter.ts: FRAMEWORK_OWNED_FILES (overwrite, backup-once to
  .pre-constitution.bak) vs USER_SEEDED_FILES (seed-if-absent); CONSTITUTION.md
  added to preserve; reconcile mirrors reconcile_framework_files() in install.sh
- file-adapter.test.ts: 5 migration fixtures (overwrite framework-owned + backup,
  idempotent backup-once, preserve SOUL/credentials, preserve user-seeded TOOLS);
  updated the prior "preserve AGENTS" test that P4 intentionally inverts
- mosaic-init: fail-closed persona — --name is REQUIRED in --non-interactive mode
  (no silent agent named "Assistant"); verified exit 1 + clear error
- verify-sanitized.sh self-test: prove the identity scan actually covers
  *.yaml/*.service config formats (Claude review ticket)

Both installers now behave identically. install.sh fixture suite 14/14 green;
gate green; mosaic-init fail-closed verified.

Refs #542

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-21 17:56:01 -05:00
parent d2d0279e92
commit 1064427c6d
4 changed files with 79 additions and 18 deletions

View File

@@ -274,6 +274,13 @@ detect_existing_config
echo "[mosaic-init] Generating SOUL.md — agent identity contract"
echo ""
# Fail-closed persona: in non-interactive mode the agent NAME must be supplied
# explicitly (--name) — never silently ship an agent named "Assistant".
if [[ $NON_INTERACTIVE -eq 1 && -z "$AGENT_NAME" ]]; then
echo "[mosaic-init] ERROR: --name (agent name) is required in non-interactive mode." >&2
exit 1
fi
prompt_if_empty AGENT_NAME "What name should agents use" "Assistant"
prompt_if_empty ROLE_DESCRIPTION "Agent role description" "execution partner and visibility engine"