Files
stack/docs/plans/HARVEST.md
T

4.3 KiB

HARVEST — patterns from mosaicstack/stack + the live fleet runtime

Sources surveyed 2026-09-03 (owner-authorized):

  • ~/src/mosaic-stack (drifted) and fresh clone at ~/src/mosaic-stack-worktrees/v2-harvest (branch next @ 0db2d19a, "mosaic doctor structure-anchor provisioning check (T51 WP0b)")
  • ~/.mosaic/fleet/ — live fleet runtime: bin/, roles/ (+-ng), agents/<seat>/, auth/, roster.yaml, SEAT-CUTOVER.md

Rule honored: nothing pulled whole-cloth. This file is the pattern ledger; each adoption lands through its own milestone with tests.

Pattern ledger

# Pattern (source) Verdict Destination
1 Channel dispatcherfleet/bin/mosaic: shipped npm CLI is default; dev worktree opt-in via MOSAIC_CLI_WORKTREE health-checked with --version; MOSAIC_FLEET_CLI_OFF forces pass-through; launcher never writes to user dirs steal M20 unified mosaic CLI
2 Single canonical launcher + per-seat envbin/launch-seat.sh is the only launcher; per-seat variation lives in launch.env ("per-seat copies drift") steal M20 CLI + agent.sh stays thin
3 Refuse-rather-than-guess provisioningbin/new-seat.sh: seat classes, --adopt never overwrites real identity files, --mint fails closed (unminted = git writes fail closed), --dry-run steal seat instantiation (M15 evolution)
4 Role manifest schema v3roles/code-ng/mosaic-core.manifest.json: capability bindings (id/effect/binding/status), tools[], forbiddenTools[], shell.mode: denied, credentials policy, evidence journaling, digestRules postcondition (active-set-exact, sha256 over manifest) adapt progressively M18 seat-role restriction
5 Per-seat git identityMOSAIC_GIT_IDENTITY=<seat> + GIT_AUTHOR_NAME/EMAIL; incident 2026-08-19: seven seats committed as the wrong identity via directory git config steal M18/M20 (we have no per-seat git writes yet — adopt before we do)
6 Auth slots + symlink sharesfleet/auth/<provider>/<account>/ credential dirs; seat .pi/agent/ symlinks auth.json settings.json models-store.json bin skills adapt M19 auth tooling
7 Launch-time pre-flight probes — every consumed path checked before start; pi's existsSync silently appends literal path strings as prompt text (documented trap) steal M19 launch check + our existing refusal style
8 Prompt ordering doctrine — estate context first, seat SOUL/AGENTS last ("closest to the task wins") matches ours document in adapters/README
9 --check mode on launchers (verify provisioning without launching) steal agent.sh / release ensure
10 ENTITY.md per seat — identity record incl. git identity, explicitly secret-free steal seat records (extend seat.json or add ENTITY.md)
11 mosaic doctor — structure-anchor provisioning check (T51) adapt M20 mosaic --check
12 packages/ anatomy on next: mosaic (CLI), auth, agent, config, forge, quality-rails, comms, macp reference map M18/M19/M20 deep reads

Skips (for now)

  • tmux comms watchers, lanes/, board/, memory/, journal/ — L5/L6 fleet territory; our conductor loop is deliberately not a resident service.
  • openbao/swarm/coolify compose stacks — deployment, far future.
  • roster.yaml + roster.schema.json — superseded by our agents/ definitions for now; revisit when fleet registration returns.

Owner-corrected design points (2026-09-03)

  • M17 revised: skills must reach non-conductor seats as role-scoped subsets — agents invent tooling when the right tool isn't supplied. Role contracts will declare skill sets; the runner loads them explicitly (mock-verified --skill + --no-skills coexistence pending).
  • M19 revised (owner's own diagnosis): auth selection was symlinks from agents/<seat>/.pi into fleet/auth, and a missing symlink silently fell back to defaults. Our design: the launcher reads the seat's declared account, ensures the symlink/auth selection before TUI launch, and refuses loudly on mismatch — check + fix, never silent default.
  • Unified mosaic CLI is directional (mosaic tui, mosaic yolo <harness>, mosaic --check): tracked as M20, harvested from pattern #1 and stack packages/mosaic.