Claude Code saves credentials by writing a sibling temp file and rename()-ing
it over the target. rename(2) replaces a symlink rather than following it, so
the managed link W-F1/W-F2 planted at <seat>/.claude/.credentials.json is
destroyed by the first token refresh and the seat silently forks its
credentials. The in-place fallback arm opens with O_NOFOLLOW and would refuse
the link anyway. Evidence, quoting the 2.1.232 binary:
docs/reports/harness/claude-credential-write-path-2026-08-14.md (jarvis-brain).
CLAUDE_SECURESTORAGE_CONFIG_DIR resolves the credential directory
independently of CLAUDE_CONFIG_DIR, so the temp file and the rename both land
inside the bundle. That is the property the design wanted -- share the
credential, never the transcripts -- with no symlink and no privileges.
- new fleet/credential-sharing.ts owns the harness -> credential-file and
harness -> credential-directory-variable maps, so scaffold and launch cannot
disagree about the mechanism. It also removes the duplicate credential-file
name table the two already carried.
- launch composes CLAUDE_SECURESTORAGE_CONFIG_DIR from the resolved bundle
directory and plans no credential link for Claude. The value is always the
absolute bundle path: Claude reads an empty value as ~/.claude, which is the
operator's own account.
- scaffold stops emitting the credential symlink and its manifest entry for
Claude, and tolerates one left by an earlier scaffold rather than reporting
it as a foreign file or rewriting it.
- FIRST_AUTH_REFUSAL still fires when a real file occupies the seat path.
- Harnesses absent from the map (pi, codex, opencode) keep managed links; the
containment specs now exercise them on pi.
Answers promotion gate #1 negatively for the frozen mechanism and positively
for the replacement. E3.3 (two seats refreshing one bundle at once) is still
open.
AMD1213-C: repair stale array consumer, fail closed on foreign link provenance, validate manifests before mutation, and exercise the fleet MCP preflight call path.
Claude Code writes installed_plugins.json and other metadata files into
the seat's plugins directory during a session, so refusing every real
entry made composition fail on each seat's second launch. Only a real
directory is an unmanaged entry the pruner would orphan; plain files are
harness state and pass through untouched. Found by the in-box hour-gate
relaunch of the probe seat.
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Dtdjx4Gxude9fwyLezCrhh
The installed ~/.config/mosaic home flattens the repo's
packages/mosaic/framework/ prefix: the real file is
<home>/runtime/<harness>/settings.json, exactly as launch.ts already
resolves it everywhere. The fleet launch composition leaked the repo
layout (framework/runtime/...) into the system layer path, so a real
installed home failed with COMPOSITION_FAILED while the temp-fixture
specs (which mirrored the same wrong prefix) stayed green. Found by the
in-box hour-gate dry-run against the installed mos-dev-stage home.
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Dtdjx4Gxude9fwyLezCrhh
Integration adjudication (fred, W-F1): the general arrays-replace merge rule
conflicts with the gap-7 base/overlay split — base and lease overlay share
the PreToolUse and Stop events, so replace semantics would silently drop the
base QA hooks from every gated seat. Ruling: hook event arrays directly
under the top-level hooks key concatenate (base first); all other arrays
keep replace semantics; null tombstones still delete an event.
- mutator-gate acceptance now asserts lease wiring against the COMPOSED
gated settings (base + lease-overlay via the launcher's own merge),
matching the post-split contract.
- fleet subcommand canary gains the intended new 'agent' surface from T3.
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Dtdjx4Gxude9fwyLezCrhh
Integration reconciliation of T2/T3 seams on feat/wf-fleet-mvp:
- fleet launch now resolves the user root through defaultFleetDataHome()
(MOSAIC_DATA_HOME), the same seam fleet agent new uses, instead of a
divergent MOSAIC_USER_HOME variable.
- Launching an unscaffolded name raises AGENT_NOT_SCAFFOLDED with the
actionable message pointing at 'mosaic fleet agent new <name>' (acceptance
carried over from the T3 card after the roster-v2 reconciliation moved it
onto the launch path).
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Dtdjx4Gxude9fwyLezCrhh