Add mosaic launch <seat> with seat registration for the control board (#1504)

New package packages/seat and wrapper scripts/mosaic. `launch <seat>` writes
<dataRoot>/seats/<layout>/<seat>/registration.json and then execs the seat's
launch.sh unchanged; `seat task <seat> <text>` edits the task only. The board
reads registrations, matches by sessions directory, and lets a registered
task, project or workspace override the derived value with a source tag.
The four repository launch scripts register themselves unless already
registered or run with --check. Fleet launchers untouched; one-liner on the
plan page.

Review found the record path keyed by seat name alone (repo and fleet
"darkwing" would collide); fixed by keying on layout. Also: the Pi pin
refusal now names installed and required versions.

Tests: seat 15, control-board 89, launch scripts 5, registry 69, config 24.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
This commit is contained in:
2026-09-12 10:56:17 -05:00
co-authored by Claude Fable 5.1
parent 01d9a19612
commit 69f99323c7
25 changed files with 1766 additions and 46 deletions
+39
View File
@@ -2063,3 +2063,42 @@ a live pane, the rest from the log; every fleet seat reads `.mosaic` as
its active project because `~/.mosaic` is a git checkout and the roster
names no project. Missing launcher signals are listed in the plan page
Step 3 log. Sonnet review: APPROVED, no findings.
## 2026-09-12 — Seat registration: `mosaic launch <seat>` (#1504)
Before: the board derived task, project and workspace from the session log
and tmux, and had no way to know what a seat was actually told to do.
Launch scripts left no record.
After: `scripts/mosaic launch <seat|seat-dir> [--task ..] [-- args]`
(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) and then replaces itself with the
seat's launch.sh via `process.execve`, so pid, terminal, exit code and the
tmux foreground command are the script's own. `scripts/mosaic seat task
<seat> <text>` edits the task only. The board reads every registration on
each scan, matches by sessions directory, and lets a registered task,
project or workspace override the derived value with `taskSource` /
`activeProjectSource` / `workspaceSource` = `registration`; the page shows a
"registered" tag and a Registered detail line. The four repository launch
scripts re-enter through the launcher unless `MOSAIC_LAUNCH_REGISTERED` is
set or `--check` is passed; fleet launchers are untouched, their one-line
change is on the plan page for orch-01.
Verification: seat suite 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: the real `agents/darkwing/launch.sh`
through the launcher against a temporary data root, then a scratch board on
7332 reading it; the darkwing row showed the registered task, both source
tags and the Registered line, and a `seat task` change appeared with its
update time.
Corrections: sonnet review (first pass) found the record path keyed by seat
name alone, which would have made the repo and fleet "darkwing" overwrite
each other; fixed by keying on layout and seat, `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 because
`node_modules` still held 0.84.4 after commit 557aba0f moved the pin to
0.85.1; `npm ci` fixed it and the refusal message now names both versions.
The pin is canon and stays unless Jason decides otherwise.