feat(fleet): onboarding-injection — comms cheat-sheet + peer roster per agent #621

Merged
jason.woltje merged 2 commits from feat/fleet-comms-onboarding into main 2026-06-22 17:54:55 +00:00
Owner

Fleet onboarding-injection — comms cheat-sheet + peer roster (closes #620)

Root cause of a spawned agent's failed first send: fleet agents are born not knowing how to reach their peers. This injects a # Fleet Comms block into each fleet agent's system prompt via composeContract — the runtime-agnostic path every mosaic yolo <runtime> agent hits — so it can reach the orchestrator + peers from its first turn. No-op for non-fleet launches.

Acceptance criteria (Mos) — all met + tested

# Criterion Where
1 Address-aware boot: own [host:session] + agent-send path + peer roster intro line + peer table
2 Cross-host: local → -s <session> (no -H); remote → -H <ssh> -s <session> renderPeerReach; concrete coder0-0@dragon-lin = -H jwoltje@10.1.10.37 -s coder0-0
5a Socket (Mos recon): named → -L <socket>; default/unset → no -L (matches LIVE socket, not roster-pinned mosaic-factory) renderPeerReach socket branch
3 Reply rule: FLIP-the-preamble Conventions
4 Receipts: agent send --verify = ACCEPTED (not injected) Conventions
5b No-regression: default socket (no -L); matches live tooling default render path

Implementation

  • src/fleet/comms-onboarding.ts (standalone — no fleet.ts coupling): parseRosterAgents (name/class/host/ssh/socket), renderPeerReach (data-driven command), buildFleetCommsBlock, readFleetCommsBlock ('' when not a fleet member).
  • launch.ts composeContract appends the block only when MOSAIC_AGENT_NAME is set + the agent is in the roster.
  • roster.schema.json: optional per-agent host / ssh / socket (cross-host + socket addressing; manual cross-host listing is a documented pre-federation stopgap — W1 auto-discovers later).

Verification

  • 14 onboarding + 9 composeContract tests: parse (incl. socket); render local/remote/ssh-fallback/equal-host/socket-none/named/combined -L+-H; build (self excluded, orchestrator flagged); situational readFleetCommsBlock; and the end-to-end composeContract injection (correct cross-host + socket addresses; no-op when MOSAIC_AGENT_NAME unset). tsc/eslint/prettier/sanitize clean.
  • Post-merge validation (Mos + enhancer): spawn a real w-jarvis agent → first-try reach to coder0-0@dragon-lin and a local peer.

Cheap under #619 gating (packages/mosaic + docs only → 0 image builds).

🤖 Generated with Claude Code

## Fleet onboarding-injection — comms cheat-sheet + peer roster (closes #620) **Root cause** of a spawned agent's failed first send: fleet agents are born not knowing how to reach their peers. This injects a `# Fleet Comms` block into each fleet agent's system prompt via **`composeContract`** — the runtime-agnostic path every `mosaic yolo <runtime>` agent hits — so it can reach the orchestrator + peers from its first turn. No-op for non-fleet launches. ### Acceptance criteria (Mos) — all met + tested | # | Criterion | Where | |---|-----------|-------| | 1 | Address-aware boot: own `[host:session]` + agent-send path + peer roster | intro line + peer table | | 2 | **Cross-host**: local → `-s <session>` (no `-H`); remote → `-H <ssh> -s <session>` | `renderPeerReach`; concrete `coder0-0@dragon-lin` = `-H jwoltje@10.1.10.37 -s coder0-0` | | 5a | **Socket** (Mos recon): named → `-L <socket>`; default/unset → no `-L` (matches LIVE socket, not roster-pinned `mosaic-factory`) | `renderPeerReach` socket branch | | 3 | Reply rule: FLIP-the-preamble | Conventions | | 4 | Receipts: `agent send --verify` = ACCEPTED (not injected) | Conventions | | 5b | No-regression: default socket (no `-L`); matches live tooling | default render path | ### Implementation - **`src/fleet/comms-onboarding.ts`** (standalone — no `fleet.ts` coupling): `parseRosterAgents` (name/class/**host/ssh/socket**), `renderPeerReach` (data-driven command), `buildFleetCommsBlock`, `readFleetCommsBlock` (`''` when not a fleet member). - **`launch.ts` `composeContract`** appends the block only when `MOSAIC_AGENT_NAME` is set + the agent is in the roster. - **`roster.schema.json`**: optional per-agent `host` / `ssh` / `socket` (cross-host + socket addressing; manual cross-host listing is a documented **pre-federation stopgap** — W1 auto-discovers later). ### Verification - **14 onboarding + 9 `composeContract`** tests: parse (incl. socket); render local/remote/ssh-fallback/equal-host/socket-none/named/**combined `-L`+`-H`**; build (self excluded, orchestrator flagged); situational `readFleetCommsBlock`; and the end-to-end `composeContract` injection (correct cross-host + socket addresses; no-op when `MOSAIC_AGENT_NAME` unset). tsc/eslint/prettier/**sanitize** clean. - **Post-merge validation** (Mos + enhancer): spawn a real w-jarvis agent → first-try reach to `coder0-0@dragon-lin` **and** a local peer. Cheap under #619 gating (`packages/mosaic` + docs only → 0 image builds). 🤖 Generated with [Claude Code](https://claude.com/claude-code)
jason.woltje added 1 commit 2026-06-22 17:03:28 +00:00
feat(fleet): onboarding-injection — comms cheat-sheet + peer roster per agent (#620)
Some checks failed
ci/woodpecker/push/ci Pipeline was canceled
ci/woodpecker/pr/ci Pipeline was canceled
30ef9ed66b
Root cause of a spawned agent's failed first send: fleet agents are born not
knowing how to reach their peers. Inject a comms cheat-sheet + peer roster into
each fleet agent's system prompt via composeContract (the runtime-agnostic path
every `mosaic yolo <runtime>` agent hits), so it can reach the orchestrator and
peers from its first turn.

- src/fleet/comms-onboarding.ts (standalone, no fleet.ts coupling):
  parseRosterAgents (name/class/host/ssh/socket), renderPeerReach (data-driven
  agent-send command), buildFleetCommsBlock (own [host:session] identity +
  agent-send path + peer table + FLIP-to-reply + `agent send --verify`=ACCEPTED),
  readFleetCommsBlock (reads roster.yaml; '' when not a member).
- launch.ts composeContract appends it only when MOSAIC_AGENT_NAME is set + the
  agent is in the roster (no-op for non-fleet launches).
- roster.schema.json: optional per-agent host/ssh/socket (cross-host + socket
  addressing; manual cross-host listing is a pre-federation stopgap).

Address rendering is fully data-driven per Mos's acceptance criteria:
- cross-host: local → `-s <session>` (no -H); remote → `-H <ssh> -s <session>`.
- socket: named → `-L <socket>`; unset → default socket (no -L) — matches the
  LIVE socket, never blindly inherits the roster's tmux.socket_name.

Verified: 14 onboarding + 9 composeContract tests (parse, render local/remote/
fallback/equal-host/socket-none/named/combined, build, situational read +
composeContract injection w/ correct cross-host+socket addrs, no-op when
MOSAIC_AGENT_NAME unset). tsc/eslint/prettier/sanitize clean.

Refs #620

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EsgTQzV5YUGk1JtCLP4B83
jason.woltje added 1 commit 2026-06-22 17:06:47 +00:00
fix(fleet): remove duplicate workingDirectory key in roster.schema.json
All checks were successful
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/pr/ci Pipeline was successful
3d8bd3be1e
Edit artifact from the host/ssh addition left a third workingDirectory block in
the agent-items properties (duplicate JSON keys are last-wins, so prettier/CI did
not flag it). Keep exactly one workingDirectory + one working_directory.

Refs #620

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EsgTQzV5YUGk1JtCLP4B83
jason.woltje merged commit 095e19443b into main 2026-06-22 17:54:55 +00:00
jason.woltje deleted branch feat/fleet-comms-onboarding 2026-06-22 17:54:55 +00:00
Sign in to join this conversation.
No Reviewers
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: mosaicstack/stack#621