mosaic launch <seat>: seat registration the control board reads #1504

Open
opened 2026-09-12 15:32:56 +00:00 by jason.woltje · 2 comments
Owner

Follows #1503 (control board MVP). Brief from the professor session with Jason's go (2026-09-12).

Definition: a seat started through mosaic launch <seat> runs its existing launch script unchanged and leaves one registration record the board reads instead of guessing.

Scope, in order:

  1. mosaic launch <seat>: resolves the seat's launch script (agents/<seat>/launch.sh in mosaic-stack; a seat dir path for the ~/.mosaic fleet layout), runs it unchanged, and writes one registration record: seat, project, task (empty unless --task), workspace, tmux session, harness, started at, pid. Per seat under the data root, not under board/. Rewritten on relaunch.
  2. mosaic seat task <seat> <text>: updates only the task field.
  3. Scanner: a registration's task, project and workspace override the derived values and the row says which source it used. No registration, unchanged behaviour.
  4. The four mosaic-stack launch scripts (darkwing, dewey, rocko, filbert) go through mosaic launch. Fleet launchers are not edited here; the one-line change is written in the plan page.
  5. Tests for the record write, the task update, the scanner override, and one launch script end to end. Step 3 log entry on the plan page. CURRENT.md updated.

Not in scope: auth/provider registry, roster.yaml schema changes, multiple sessions per seat, stopping or killing seats, UI polish.

Follows #1503 (control board MVP). Brief from the professor session with Jason's go (2026-09-12). Definition: a seat started through `mosaic launch <seat>` runs its existing launch script unchanged and leaves one registration record the board reads instead of guessing. Scope, in order: 1. `mosaic launch <seat>`: resolves the seat's launch script (`agents/<seat>/launch.sh` in mosaic-stack; a seat dir path for the `~/.mosaic` fleet layout), runs it unchanged, and writes one registration record: seat, project, task (empty unless `--task`), workspace, tmux session, harness, started at, pid. Per seat under the data root, not under `board/`. Rewritten on relaunch. 2. `mosaic seat task <seat> <text>`: updates only the task field. 3. Scanner: a registration's task, project and workspace override the derived values and the row says which source it used. No registration, unchanged behaviour. 4. The four mosaic-stack launch scripts (darkwing, dewey, rocko, filbert) go through `mosaic launch`. Fleet launchers are not edited here; the one-line change is written in the plan page. 5. Tests for the record write, the task update, the scanner override, and one launch script end to end. Step 3 log entry on the plan page. CURRENT.md updated. Not in scope: auth/provider registry, roster.yaml schema changes, multiple sessions per seat, stopping or killing seats, UI polish.
Author
Owner

Landed in commit 69f99323 on refactor (follows the Gate A fix in #1503).

What

  • scripts/mosaic launch <seat|seat-dir> [--task ..] [-- args] (new package packages/seat): writes <dataRoot>/seats/<layout>/<seat>/registration.json (seat, project, task, workspace, tmux, harness, startedAt, pid; plus sessionsDir, seatDir, launchScript, layout, updatedAt, version, reasons in the README) and then replaces itself with the seat's launch.sh unchanged via process.execve, so pid, terminal, exit code and the tmux foreground command are the script's own. Rewritten on every launch.
  • scripts/mosaic seat task <seat> <text> edits the task only.
  • Board: registrations are read on every scan, matched by sessions directory (not name), and a registered task/project/workspace overrides the derived value; taskSource / activeProjectSource / workspaceSource say registration. The page shows a "registered" tag and a Registered detail line. Rows without a registration are unchanged.
  • agents/{darkwing,dewey,filbert,rocko}/launch.sh register themselves unless MOSAIC_LAUNCH_REGISTERED is set or --check is passed. rocko registers but stays off the board (no pi session log). Fleet launchers untouched; the one-line change for orch-01 is on the plan page.

Evidence: seat 15/15, control-board 89/89 (was 79), launch-script suites 5/5 (each real launch.sh in a fixture that is its own data root), registry 69/69, config 24/24. Live: real agents/darkwing/launch.sh through the launcher against a temp data root, scratch board on 7332 showed the registered task, both source tags, the Registered line, and a seat task update.

Review: sonnet found the record keyed by seat name alone (repo and fleet darkwing would collide); fixed by keying on layout, seat task refuses an ambiguous bare name unless --layout is given. Second pass APPROVED.

Found on the way: Jason's own launch refused on the Pi pin; node_modules held 0.84.4 after 557aba0f moved the pin to 0.85.1. npm ci fixed it; the refusal now names both versions. The pin is canon and stays unless Jason rules otherwise.

Landed in commit 69f99323 on `refactor` (follows the Gate A fix in #1503). **What** - `scripts/mosaic launch <seat|seat-dir> [--task ..] [-- args]` (new package `packages/seat`): writes `<dataRoot>/seats/<layout>/<seat>/registration.json` (seat, project, task, workspace, tmux, harness, startedAt, pid; plus sessionsDir, seatDir, launchScript, layout, updatedAt, version, reasons in the README) and then replaces itself with the seat's `launch.sh` unchanged via `process.execve`, so pid, terminal, exit code and the tmux foreground command are the script's own. Rewritten on every launch. - `scripts/mosaic seat task <seat> <text>` edits the task only. - Board: registrations are read on every scan, matched by sessions directory (not name), and a registered task/project/workspace overrides the derived value; `taskSource` / `activeProjectSource` / `workspaceSource` say `registration`. The page shows a "registered" tag and a Registered detail line. Rows without a registration are unchanged. - `agents/{darkwing,dewey,filbert,rocko}/launch.sh` register themselves unless `MOSAIC_LAUNCH_REGISTERED` is set or `--check` is passed. rocko registers but stays off the board (no pi session log). Fleet launchers untouched; the one-line change for orch-01 is on the plan page. **Evidence**: seat 15/15, control-board 89/89 (was 79), launch-script suites 5/5 (each real `launch.sh` in a fixture that is its own data root), registry 69/69, config 24/24. Live: real `agents/darkwing/launch.sh` through the launcher against a temp data root, scratch board on 7332 showed the registered task, both source tags, the Registered line, and a `seat task` update. **Review**: sonnet found the record keyed by seat name alone (repo and fleet `darkwing` would collide); fixed by keying on layout, `seat task` refuses an ambiguous bare name unless `--layout` is given. Second pass APPROVED. **Found on the way**: Jason's own launch refused on the Pi pin; `node_modules` held 0.84.4 after 557aba0f moved the pin to 0.85.1. `npm ci` fixed it; the refusal now names both versions. The pin is canon and stays unless Jason rules otherwise.
Author
Owner

Follow-up landed in 17153fe1 (pushed to refactor). Two defects in 69f99323, reported by the professor session and verified here.

  1. Test leak. The darkwing launch test's flock-contention spawn ran without the fixture config, so launch.sh re-entered scripts/mosaic against the real data root and wrote fixture records for darkwing, dewey and filbert there (dead pids, /tmp workspaces), overwriting the live darkwing record. Fix: that spawn names the fixture config, and both launch test files set MOSAIC_CONFIG to a nonexistent path and clear MOSAIC_LAUNCH_REGISTERED process-wide, so a spawn that forgets fails instead of polluting. The fixture records and the old flat-path record were deleted by hand; the next darkwing launch writes the real one.

  2. Stale records. A registration is written before the launch script's own checks, so a refused launch (the Pi pin refusal) left a record with a dead pid that the board honoured. The scanner now probes the recorded pid on every pass; a gone pid makes the record stale: still on the Registered line, marked stale with registered.alive false, but derived task, project and workspace win. Index gains registrationStale; the CLI summary a stale count.

Per Jason: fleet seats stay on the old launchers; the orch-01 one-liner on the plan page is marked not planned.

Tests: board 90/90 (was 89), seat 15/15, launch scripts 5/5, real data root untouched by the run. Sonnet review APPROVED.

Follow-up landed in 17153fe1 (pushed to `refactor`). Two defects in 69f99323, reported by the professor session and verified here. 1. **Test leak.** The darkwing launch test's flock-contention spawn ran without the fixture config, so `launch.sh` re-entered `scripts/mosaic` against the real data root and wrote fixture records for darkwing, dewey and filbert there (dead pids, `/tmp` workspaces), overwriting the live darkwing record. Fix: that spawn names the fixture config, and both launch test files set `MOSAIC_CONFIG` to a nonexistent path and clear `MOSAIC_LAUNCH_REGISTERED` process-wide, so a spawn that forgets fails instead of polluting. The fixture records and the old flat-path record were deleted by hand; the next darkwing launch writes the real one. 2. **Stale records.** A registration is written before the launch script's own checks, so a refused launch (the Pi pin refusal) left a record with a dead pid that the board honoured. The scanner now probes the recorded pid on every pass; a gone pid makes the record stale: still on the Registered line, marked stale with `registered.alive` false, but derived task, project and workspace win. Index gains `registrationStale`; the CLI summary a stale count. Per Jason: fleet seats stay on the old launchers; the orch-01 one-liner on the plan page is marked not planned. Tests: board 90/90 (was 89), seat 15/15, launch scripts 5/5, real data root untouched by the run. Sonnet review APPROVED.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: mosaicstack/stack#1504