diff --git a/BUILD-LOG.md b/BUILD-LOG.md index 57c46026..92061792 100644 --- a/BUILD-LOG.md +++ b/BUILD-LOG.md @@ -3800,3 +3800,7 @@ Correction, 2026-10-09 22:58Z, Sage: my push after the rows 40-41 briefing went ### 2026-10-09 — Sage, mosaic-bus@mosaic-stack running against tasks.mosaicstack.dev (lead decision 76) Before: no business file, no project file, no bus host. After: `~/.config/mosaic-dev/businesses/mosaic-stack.json` written from the shipped example (bot ids 6-10, token paths, dates 2027-01-07, tracker.baseUrl https://tasks.mosaicstack.dev), and `business validate mosaic-stack` passes with project stack valid. `.mosaic/project.json` (tracker.project 32) sits in the working tree, waiting for Darkwing's review. `scripts/bus-service.sh install`, then `systemctl --user start mosaic-bus@mosaic-stack`: active, host pid 2483366, socket present, writer lock held, notifier off (binding null). Bus store after the first reconcile: 1 task snapshot, 1 `task.changed.external` event (the live-run task 144). The `mosaic` human CLI refuses inside an agent session, by design, so Jason runs `mosaic tasks` and `mosaic agents` from his own shell. + +### 2026-10-09 — Filbert, row 41 slice 1 S6 started (meta-harness and launching, #1523) + +Before: no harness package, no Claude adapter, and the PM runs in Sage's T3 thread. Row 41 is in-progress (rev 241). Plan: `agents/filbert/work/s6/PLAN.md`. The launcher lives in the trusted bus host, so the build also touches `packages/bus` (IPC ops identity, authorize, refuse, endLaunch and credentialStatus, plus `Broker.endLaunch`) and `packages/cli` (a host launch socket and `bus start --pm`). It adds no socket verb, no event kind and no schema change. Each managed session gets its own PID namespace, which closes the decision 62 `setsid` gap for the ancestry proof; its limits will be recorded. The build happens in a detached worktree, and the packet is build.patch plus a candidate manifest. The recorded PM→coder run uses a scratch data root, not the live unit, and nothing runs on Astra. No push. diff --git a/agents/filbert/work/s6/PLAN.md b/agents/filbert/work/s6/PLAN.md new file mode 100644 index 00000000..90ff3653 --- /dev/null +++ b/agents/filbert/work/s6/PLAN.md @@ -0,0 +1,88 @@ +# Row 41, slice 1 S6: build plan (Filbert) + +Issue #1523. Brief: `docs/plans/2026-10-04_slice-1.md` § Slice 1 S6, blob +`72d11de2`. Base `915e00e5`. Built in a detached worktree; the packet is +`build.patch` plus `candidate-manifest.sha256`, as in Rocko's +`agents/rocko/work/s4-follow-up/`. Filbert doesn't commit the candidate +source and doesn't push. + +## Shape + +The launcher has to live in the trusted bus host (`packages/cli/src/host.mjs`). +Only the host holds the IPC channel that binds a launch, and only the broker +can authorize `role.launch`. So: + +``` +PM session --(launch tool: cap, instance, model)--> host launch socket +host --IPC identity/authorize--> broker (action.allowed or refusal evidence) +host: instance list, family capacity, credential status, then spawn +host --IPC bindLaunch--> broker (session.launched) +host writes the cap file; the runner reads it, role.claim +session exit --IPC endLaunch--> broker (session.ended, claim released) +``` + +A managed session is a runner (`packages/harness/src/runner.mjs`) inside +`unshare --user --map-current-user --pid --fork --kill-child --mount-proc`. +The runner claims the role, loops on `message.receive`, runs one harness +turn per batch through the adapter (persistent session directory), and +sends the turn's answer back to the sender. A wall clock bounds each turn +(S0 line 4). + +## Pieces + +| Piece | Where | What | +|---|---|---| +| Bundle | `packages/harness/src/bundle.mjs` | prompt, policy, skills list, typed tools, manifest from `resolveInstance` output; per harness files (Pi: extension args; Claude: settings with the wrapped gate, MCP config) | +| Typed tools | `packages/harness/src/tools.mjs` | vocabulary action → tool; only actions the instance holds, plus reads | +| Pi extension | `packages/harness/src/pi-extension.mjs` | registers the typed tools; `tool_call` gate blocks tools outside the policy (S0 lines 1-3) | +| Claude gate and MCP server | `packages/harness/src/claude-gate.mjs`, `mcp-server.mjs` | PreToolUse command hook, wrapped `timeout -k 2 10 node gate || exit 2`, hook timeout 20 (S0 lines 1-4); minimal stdio MCP server for the typed tools | +| Runner | `packages/harness/src/runner.mjs` | the managed process; founder-credential stop (REQ-CRED-2) | +| Claude adapter | `adapters/claude/adapter.sh` | adapter contract, plus the bundle's settings and MCP files | +| Pi adapter | `adapters/pi/adapter.sh` | takes `MOSAIC_EXTENSIONS` (`-e`), still `--no-extensions` | +| Session launcher | `packages/seat/src/session.mjs` | spawn under unshare, registry file, launch log, stop | +| CLI | `packages/seat/src/cli.mjs` | `mosaic talk`, `mosaic stop `, `mosaic launches off|on|status` | +| Host | `packages/cli/src/host.mjs`, `cli.mjs` | launch socket; `mosaic bus start --pm :` launches the PM without a window | +| Broker | `packages/bus/src/{broker,runtime,process}.mjs` | IPC ops `identity`, `authorize`, `refuse`, `endLaunch`, `credentialStatus`; `Broker.endLaunch` | + +## Choices and tradeoffs (consequential) + +1. **Outside the brief's file list:** `packages/bus` (three IPC ops and one + trusted method, the counterpart of `bindLaunch`) and `packages/cli` + (host launch socket, `--pm`). The brief says the PM launches "through the + broker", and the bus README leaves spawning, allowlists and capacity to + S6; neither can happen without these. No socket verb is added to the + broker, no event kind and no schema change. +2. **`mosaic launch` name:** `mosaic launch ` stays the T3 seat + launcher. Role sessions are started by the host (the PM at boot, with + `--pm`) and by the PM's `launch` tool. `mosaic stop` and `mosaic talk` + are new verbs; `mosaic launches off` is Jason's one word (the broker's + `launch.revoke`). +3. **Capability handoff:** a 0600 file in the run directory, written after + the bind (the launch record needs the pid first). Weaker than an + inherited fd; same-UID either way. +4. **Lead decision 62 gap:** each session gets its own PID namespace, so a + `setsid -f env -i` child reparents to the runner, which is still under + the launch record's pid, and the human CLI's ancestry check refuses it. + Limits stay: the broker socket is shared, and a same-UID agent can still + ask something outside its tree (a systemd user manager, an existing tmux + server) to run a command. Recorded, not called a wall. +5. **Capacity:** families are the keys of `launch.max`; the family is the + model name containing `opus` or `sonnet`. A model in no listed family is + refused. The count includes every live managed session, the PM's too. +6. **Founder credentials (REQ-CRED-2):** the session environment is an + allowlist, so `GITEA_TOKEN` and friends never pass. The host puts the + broker's credential status (metadata only) for the instance in the + policy. The runner stops before claiming if a service the role needs has + no usable role token, or if a known founder credential variable reached + its environment. + +## Gate + +- Suites: `packages/harness`, `packages/seat`, every node suite, every + `scripts/test-*.sh`, sequential, teed, Docker pointed at a missing + socket. +- Recorded run: a scratch data root and a test business with fixture + tokens (no tracker), host started with `--pm`, `mosaic talk` asks the PM + to launch a coder, `mosaic agents` shows both claims. Not on Astra (R26), + and not against the live `mosaic-bus@mosaic-stack` unit. +- Darkwing approves on #1523. diff --git a/docs/SESSIONS.md b/docs/SESSIONS.md index cf19926d..6a843fbc 100644 --- a/docs/SESSIONS.md +++ b/docs/SESSIONS.md @@ -544,3 +544,4 @@ are never rewritten or removed; corrections are new entries. 2026-10-09T22:48:44Z | Sage (T3 Claude Code, thread 1ef1e4f8) | Jason: tasks.mosaicstack.dev operational with agents; row 35 (#1517) sections 2-3 | lead decision 75; backup plus tested restore, infra PR #325 Vikunja 2.7.0 (counts held), sections 2-3 by API: owner id 4, svc id 5, project 32, bots 6-10, tokens to 2027-01-07 at 0600, isolation and round-trip probes pass; OIDC broken since the 2026-04-27 netpol, PR #326 with ops-01; cert fix and annotation slip recorded; infra PRs now get independent review (Mos) 2026-10-09T22:53:27Z | sage | row 35 S3 live run on tasks.mosaicstack.dev, rows 40-41 dispatched | startup ready, 17/17 steps; row 35 at waiting-on-jason 2026-10-09T22:58:48Z | sage | business file, mosaic-bus@mosaic-stack started, decision 76 | host active against tasks.mosaicstack.dev; project file awaiting darkwing +2026-10-09T23:02:55Z | filbert | row 41 (#1523) slice 1 S6 started | plan agents/filbert/work/s6/PLAN.md; launcher in the bus host, bus/cli touch recorded; INFO to sage