Files
stack/docs/scratchpads/issue-766-exact-fleet-comms.md
Jarvis dd7f8a77a0
All checks were successful
ci/woodpecker/pr/ci Pipeline was successful
fix(fleet): bind secure reads to descriptors
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 19:08:29 -05:00

13 KiB

Issue 766 — exact cross-harness fleet comms targeting

  • Issue: #766
  • Branch: fix/766-exact-fleet-comms
  • Worktree: /home/jarvis/src/stack-issue-766
  • Delivery boundary: source/tests/docs only; no live tmux, session, or fleet actions; leave uncommitted for independent review.

Objective

Replace inference-prone fleet onboarding guidance with one roster-resolved contract that gives Claude Code, Codex, OpenCode, and Pi the same authoritative local identity and exact executable command for every known peer.

Plan

  1. Add issue-specific normative requirements to docs/PRD.md before source changes; do not modify orchestrator-owned docs/TASKS.md.
  2. Extract the existing v1 roster parsing/normalization into one lightweight shared resolver used by both fleet commands and runtime comms composition.
  3. Write failing contract tests for explicit SSH-only cross-host targeting, global/default socket authority, authoritative identity, unknown-peer failure, no operational metavariables, and four-harness parity.
  4. Make source TOOLS.md non-operational and marker-versioned; prove fresh installation preserves that exact contract and composition detects a stale installed copy without rewriting it.
  5. Render a deterministic comms generation and document comparison/relaunch handling; never rewrite an active session.
  6. Run focused Vitest and shell exact-target tests, then package/repository typecheck, lint, format, test, and build gates as relevant.
  7. Reconstruct the exact uncommitted tree, including untracked files, for independent review and remediate findings without committing.

Contract decisions

  • tmux.socket_name is the one supported socket authority for every local fleet session. A per-agent socket, when present for compatibility, must equal that global value; independent per-agent sockets fail closed because the runtime does not provision them. A named socket renders -L, while the empty literal default renders no -L.
  • A peer is same-host only when its resolved host equals the current roster member's resolved host. Every host-omitted member resolves against the stable local fleet-host baseline, never against the viewer's explicit host. Same-host rows never render -H.
  • A cross-host row requires that peer's explicit roster ssh; absence is a contract error. Never substitute host as an SSH target.
  • The current member's explicit roster host wins; otherwise the local machine's short hostname is the baseline for host-omitted local members.
  • Unknown members/peers return a deterministic error listing exact known names and an exact self-scoped discovery command. No fuzzy session lookup.
  • Exact command fields are structurally constrained to safe targeting grammars and shell-rendered as individual arguments. Unsafe host/SSH/socket values fail roster normalization rather than entering executable guidance.
  • Existing installed TOOLS.md remains user-owned during ordinary keep-mode updates. Currency requires the expected source and installed marker/version plus bounded SHA-256 byte identity. Explicit mosaic update --repair-tools is the supported current-version recovery path: it makes a digest-qualified no-clobber backup, restores the contract and regular executable helper, and does not rewrite active context.
  • The v1 resolver preserves and validates tmux, discord, and matrix connector blocks in YAML and JSON; conflicting snake/camel aliases fail closed unless their values are identical.
  • JSON roster fallback occurs only when roster.yaml is absent. Keep-mode reseed preserves both formats, and relaunch discovery uses the same canonical resolver.
  • The helper is inspected without following symlinks and must be a regular executable file. Missing, directory, symlink, and non-executable installations fail closed with deterministic repair guidance.
  • Active contexts carry a deterministic comms generation. Operators compare it to mosaic agent comms-block <exact-agent> output; mismatch means stale and requires an explicit exact-agent relaunch.

Risks

  • Import cycles if runtime composition imports the command-heavy fleet.ts; mitigate with a lightweight shared roster module and re-export compatibility.
  • Existing schema prose allowed independent per-agent sockets even though runtime provisioning used one global socket; constrain compatibility declarations to the global value and preserve empty-global default behavior.
  • Remote inventory may be incomplete. Fail composition closed for an unreachable cross-host row rather than generating a guessed command.
  • TOOLS.md is user-seeded and intentionally preserved. Detect/report drift instead of overwriting custom content.

Planned evidence

  • comms-onboarding.spec.ts: resolver/renderer/failure/generation contracts.
  • compose-contract.spec.ts: identical authoritative comms section for all four harnesses and stale installed-contract reporting without mutation.
  • file-adapter.test.ts: source-to-fresh-install byte equality and preservation of customized installed TOOLS.md.
  • Existing agent-send.test.sh, socket isolation, and tmux runtime transport tests.
  • Repository quality gates and independent uncommitted-tree review.

Evidence log

  • Preflight collision scan: no issue-766 local/remote branch, worktree, or open PR collision before branch creation.
  • Isolated branch created from fetched origin/main at 4990905; original checkout not edited.
  • One strict v1 resolver now serves fleet commands and communications composition; roster writes preserve host, ssh, and socket.
  • Exact renderer covers authoritative self identity, global/default socket authority, rejected independent sockets, stable hostless-peer resolution, same-host omission of -H, explicit-SSH-only cross-host rows, shell-safe argv rendering, deterministic generations, and fail-closed unknown/missing targets.
  • Real framework defaults/TOOLS.md is tested byte-equal through a fresh FileConfigAdapter install, the installed helper is executable, and the final Pi contract contains the same source contract plus exact generated command; separate parity coverage proves byte-equivalent comms sections for Claude Code, Codex, OpenCode, and Pi.
  • Second review remediation adds strict connector/alias coverage, full-semantic generation coverage, ENOENT-only fallback, no-follow helper validation, unconditional current-version repair, digest-qualified no-clobber backups, and marker/version-gated currency.
  • The helper, roster, installed TOOLS, and framework source files are read with canonical containment, every existing ancestor and target rejected if symlinked, O_NOFOLLOW descriptor reads, inode stability checks, and effective-identity execute access. Read-only TOOLS status treats source/installed symlinks as unavailable without following or rewriting them.
  • Explicit repair validates both bundled inputs before destination creation, stages backup/TOOLS/helper plus exact-mode rollback files before any persistent file commit, revalidates destination identity at each commit boundary, installs the digest backup without clobber, and removes or exactly rolls back every committed output on injected failure. changed: false is returned only after full cleanup; cleanup/rollback failure is reported as changed: true.
  • Connector schema and runtime normalization require kind-matching settings and reject inactive connector blocks. Keep-mode installers preserve only exact roster.yaml, roster.json, agents/, and run/ paths while refreshing framework roster.schema.json; shell evidence covers byte preservation and schema refresh.
  • Solo contracts render normalized role/class plus explicit no-peer/no-remote authority boundaries; composed-contract evidence keeps role Mandate/Boundaries before Fleet Comms.
  • Operational documentation and CLI metavariable now use mosaic agent comms-block <exact-member>; historical issue-633 scratchpad text remains historical.
  • The latest independent review rejected synthetic tree 556ae4ea04f2715a4e9d381f3cafaf4c8b991b2e on three mandatory findings: installed TOOLS.md could be read through target/ancestor symlinks before unsafe status was reported; ambient class/tool-policy state could split identity authority from the canonical roster member; and the connector schema admitted empty or whitespace-only Discord/Matrix strings rejected by runtime parsing.
  • Red-first reproduction proved all three findings with 20 failures and 79 passes. Remediation routes installed TOOLS.md through the bounded secure regular-file reader before composition, resolves one exact canonical fleet identity for persona/tool policy/normalized class/Fleet Comms, rejects canonicalized ambient class mismatches, canonicalizes compatibility classes during roster parsing, and aligns parser/schema non-whitespace requirements.
  • Four-runtime coverage proves unsafe target and ancestor symlink content is omitted without mutation, while Claude Code, Codex, OpenCode, and Pi all project the same canonical member authority. Connector parser/schema coverage includes empty and whitespace-only Discord channel_id and Matrix homeserver_url, user_id, and room_id values.
  • Remediated focused gates passed: 99/99 across the two finding-focused suites plus connector schema regression PASS; the six changed-suite matrix passed 341/341; secure-file/transaction coverage remains green, including 28/28 transactional repair tests; installer migration passed 21/21.
  • Mosaic package suite passed 906/906. Shell/runtime regressions passed: agent-send.test.sh PASS=11 FAIL=0; named-socket isolation; matrix/tmux transport 12/12 (Matrix 5/5, tmux 7/7).
  • Final repository gates passed: format check; typecheck 42/42 tasks; lint 23/23; tests 42/42 tasks (Mosaic 906/906, gateway 628 passed/12 skipped); build 23/23.
  • A subsequent immutable review of tree aa6414123643a504145fce6ac1d66f0b535feb5e found one roster-authority blocker: a canonical member with omitted tool_policy inherited ambient MOSAIC_AGENT_TOOL_POLICY. Red-first four-runtime coverage failed 4/39 specifically on the leaked operator-interaction policy. Composition now branches on canonical membership: fleet launches use only canonicalMember.toolPolicy (including canonical absence), while genuinely non-fleet launches retain ambient fallback.
  • Final remediated gates passed: four-runtime regression 39/39; six changed-suite matrix 345/345; connector schema regression PASS; Mosaic package 910/910; installer migration 21/21; agent-send.test.sh 11/11; named-socket isolation PASS; Matrix/tmux transport 12/12; repository format PASS; typecheck 42/42 tasks; lint 23/23 tasks; tests 42/42 tasks; build 23/23 tasks.
  • No live tmux/session/fleet mutation, commit, push, PR mutation, issue mutation, context mutation, or reviewer launch performed.
  • Exact synthetic-tree reconstruction and frozen evidence are included in the coordinator handoff.
  • Sole-remediation preflight reverified the clean committed checkout at head 0dc47cac92c93a3ffd39ba9dd6685ac4165f6361, tree 538de6ccce1f8c44ba288a7493286e63a3413e75, branch fix/766-exact-fleet-comms; issue and PR state were read only through Mosaic wrappers.
  • Deterministic red-first ancestor substitution swapped validated root/tools for an external symlink immediately after lstat; current head returned external marker (1 failed, 4 passed) before implementation.
  • Secure reads now hold / and every root/descendant directory descriptor, traverse appended components through Linux /proc/self/fd with O_DIRECTORY|O_NOFOLLOW, and read plus effective-identity execute-check the same final descriptor. Non-Linux or unavailable proc-fd capability fails closed; stable errors redact managed paths while retaining Node code compatibility for missing/non-executable repair behavior.
  • Added deterministic root-selection, descendant-ancestor, and final-target substitution coverage. All return trusted descriptor-bound bytes after rename/symlink replacement; the race suite passed 50/50 repeated runs.
  • Isolated CLI verification drove mosaic agent --mosaic-home <fixture> comms-block self while repeatedly swapping fleet/ with an external symlink: trusted=2 fail_closed=10 external_marker=0; a persistent symlink ancestor exited 1 with a redacted unsafe-ancestor error. No live fleet state was used or mutated.
  • Remediation gates: focused secure-file/comms/launch/tmux/Matrix 110/110; full @mosaicstack/mosaic 914/914; package and repository typecheck pass (42/42 repository tasks); package and repository lint pass (23/23 repository tasks); repository format check and git diff --check pass.
  • Independent review found one production hardening blocker (nonblocking final open), one redacted-error blocker, and a deterministic ancestor-test gap. Remediation added O_NONBLOCK, normalized execute errors while preserving errno, proved the ancestor hook fires, and added final-target substitution coverage; post-remediation review evidence is clean on the production invariant.