Files
jason.woltjeandClaude Opus 5.5 22dbc2b281 dewey: row 137 live smoke plan packet (#1631)
SMOKE.md for the shared 139/137 re-pin window (sage-0613), from the code at
18aee8fa1. Doc only; nothing run.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-16 16:01:59 -05:00

11 KiB

Row 137 live smoke plan (#1631): not run

Written by Dewey for Sage (sage-0613), from the code at 18aee8fa1 and the row 137 packets. Mos ruled that rows 139 and 137 share one re-pin window and run both smokes in it (row 139's plan: agents/dewey/work/queue-139/SMOKE.md). It runs only on Mos's go, and only from the tester path: scripts/mosaic ... --tester, with every talk text starting [mos test]. Dewey doesn't run it. Target: business "stack", project stack.

What a live smoke can and can't exercise before row 149

No role can land today. land_work reaches a session only when the broker's landHeld finds, for that role and thread, a cross-role git.merge.protected decision, resolved with its approval option and unspent (broker.mjs:914-932). A decision's class is set at the raise from the raiser's role definition (#classification, broker.mjs:508-520). None of the role definitions in roles/ lists git.merge.protected under withinRole or crossRole. So every live merge raise is gated, and no role and thread can ever hold a landable decision. Granting it is a role-file change, a reviewed commit (invariant 7), not a smoke step. The merge-gate role arrives in row 149.

So before 149 a live smoke can show:

  • the launcher's new landHeld call on every launch, answering false;
  • the working repository's new seed: refs/heads/root, with main following only by fast-forward;
  • land-work.sh, which already runs from the canonical checkout at 18aee8fa1, still landing Sage's work on refactor;
  • optionally, REQ-LAND-1 at the binding: an approved gated merge decision doesn't give the raiser land_work.

It can't show any part of a landing:

  • checkLand's refusals, including REQ-LAND-1's not-authorized. No session can send a land line without land_work, and the capability never reaches the model.
  • prepareLand, the gate under bus-host/land/<id>/, finishLand and recordLand.
  • The "as its arbiter, via the broker" Resolved line.
  • The RESULT messages, and the land-busy, base-moved, gate-failed, host-closing and rollback-failed paths.

The bus, seat, cli and harness suites cover those, and Sage's landing gate ran them on 435d1c616 plus the candidate. The first live landing belongs in row 149's smoke plan.

Preconditions (each checked by Mos, read-only)

  1. Row 137 is live. Row 137 has landed and the live tree contains it: since row 85 the host, bus and role sessions run from copies/. Check with ps that the bus host, its bus child and every role session run from a copy that includes f1ee9a989.
    • The launcher calls the host op landHeld before every launch (launcher.mjs:262). The host starts the bus from its own tree (host.mjs:26), so the two can't disagree on it.
    • Row 137 adds no store migration, so the re-pin needs no schema step for it.
  2. No role definition grants git.merge.protected. grep -l git.merge.protected <copy>/roles/*.json finds nothing. The live business file's roles name only those definitions (definition keys).
    • If the grep finds a definition with git.merge.protected under crossRole, stop. A role of that definition could then hold a landable decision, and this plan doesn't cover a landing.
  3. No decision a landing could use exists. In the live store, opened read-only, no git.merge.protected decision has class cross-role:
    SELECT id, class, raised_by_role FROM decisions WHERE action='git.merge.protected';
    
    • Before row 139, git.merge.protected was a hard wait, so any existing row should be gated.
    • Expected: no cross-role row. This is the answer to "which live role can hold one today": none.
  4. bus.tester is true for the business.
  5. A record of the working repository before the window. Mos records:
    • the project root's checked-out commit: git -C <root> rev-parse HEAD, where <root> is project stack's root in the business file;
    • the working repository's refs: git --git-dir=<dataRoot>/working/stack/stack.git for-each-ref --format='%(refname) %(objectname)'.
    • Expected: refs/heads/main and refs/heads/work/... refs, with no refs/heads/root. Before 137 the seed fetched the root straight into main, forced.
    • Call the recorded main M0 and the root commit R0.
  6. There is no landing directory: <dataRoot>/bus-host/land/ doesn't exist.

Steps

A. Every launch binds without land_work (precondition 1, row 137's launcher). It needs no talk of its own: the relaunches the re-pin needs, and row 139's precondition 4, produce it.

For each role session launched after the re-pin, the launch log's event:launch names bundle/manifest.json by path. Read that file:

  • Pass: the launch succeeded (no host-op refusal in the launch log).
  • Pass: jq '.typed' manifest.json has no land_work, and the bundle's prompt.md has no "Landing:" line.
  • Pass: the session's session.json names gitSocket only for the roles that held it before 137: those whose definition holds git.push.working or review.verdict (coder and reviewer in roles/). For every other role it's absent, the same as before.

B. The seed keeps main, and fills refs/heads/root (REQ-LAND-1's prerequisite: a landed main survives the next push).

This needs one push or review fetch through the git socket after the re-pin. Use the first one the work makes anyway. Don't induce a push for this step alone.

Before it runs, compare M0 with the root's commit at that moment (R1):

  • If M0 equals R1, the seed moves nothing in main.
  • If M0 is an ancestor of R1, the first push or fetch fast-forwards main to R1. That moves main in a live working repository, so it needs Jason's agreement beforehand. The code before 137 did the same, forced, on every push.
  • If M0 isn't an ancestor of R1, main stays at M0 (working.mjs:172) and only root moves.

After it, run the same for-each-ref:

  • Pass: refs/heads/root exists and equals the root's checked-out commit at the push. Check git -C <root> rev-parse HEAD, if the root hasn't moved since.
  • Pass: git --git-dir=<repo> merge-base --is-ancestor M0 refs/heads/main exits 0. main is M0, or the fast-forward to root, and was never forced.
  • Pass: the push or fetch succeeded. Its trail shows the action.allowed for git.push.working, or the reviewer got its bundle.
  • Pass: the project root's git status and HEAD are as they were. The root is only read.

C. Optional: an approved gated merge decision gives no land_work (REQ-LAND-1 at the binding).

scripts/mosaic talk coder "[mos test] row 137 smoke, binding only; nothing lands. Call read_spec for project stack and tell me the file commit and whether it is confirmed. Then raise a non-blocking decision: action git.merge.protected, target <test task ref>, project stack, spec_path spec/north-star.md, spec_commit that file commit, options yes/no, recommendation no, question '[mos test] row 137 REQ-LAND-1 smoke; nothing can land; the delivery arbiter resolves yes only to test the binding'. Reply with the decision id." --tester --follow
scripts/mosaic trail <decision-id> --tester --json
  • Pass: the trail shows gated git.merge.protected → pm, or the live delivery arbiter, with the citation. It is not in Jason's mosaic inbox. This is the same route as row 139's step A.
  • Then: scripts/mosaic talk pm "[mos test] resolve decision <id> with yes, note 'row 137 binding smoke'" --tester --follow.
  • Pass: the trail shows it resolved yes by pm, via broker.
  • Then the coder's next launch in the decision's thread. Tools are fixed at launch, so asking the running coder what tools it has proves nothing.
    • Pass: its manifest.json typed has no land_work, and <dataRoot>/bus-host/land/ still doesn't exist.

Notes for Mos:

  • <test task ref> must be a task ref (vikunja:<project>/<task>), since landHeld reads only a decision whose raise targeted one. Use an existing [mos test] task. If there is none, skip C rather than create one.
  • The relaunch is Mos's call. The Q134 limit on coder relaunches may still apply.
  • The approved decision stays resolved and unspent. That is inert: landHeld skips any class but cross-role, checkLand refuses it not-authorized, and its class can't change, since #authorityFor requires the stored class to equal the current one. land-work refuses it not-human. If Mos would rather not leave an approved merge decision in the store, resolve it no. Then C shows only that a refused decision gives no tool, which is weaker.

D. land-work.sh still lands Sage's work (the human-only path, unchanged in intent).

This isn't tied to the re-pin: land-work.sh and scripts/land-work/read.mjs run from the canonical checkout, which has had 137 since f1ee9a989. Use Sage's next ordinary landing. It needs the decision Jason already resolves through the CLI for every landing, and adds no inbox item.

  • Pass: the landing completes, and the squash on refactor has Resolved <choice> by <by> via the CLI at <time>.
  • Pass: the land-work log shows read.mjs's output parsed. Its new via cli line is ignored, because land-work.sh's value() matches keys exactly (land-work.sh:113).
  • Not live: land-work refusing an arbiter-resolved decision (not-human). The land-work suite covers it (86 tests at the landing gate), and a live attempt would need a second decision.

I left out:

  • any step that lands, since none can before 149;
  • an uncited gated merge raise, which goes to Jason's inbox and shows nothing C doesn't;
  • any live land line.

Evidence

Mos keeps:

  • A: manifest.json typed, and whether each launched role's session.json names gitSocket.
  • B: the for-each-ref output before and after, with R0, R1 and the merge-base exit status.
  • C, if run: the talk --follow output, trail --json, and the relaunched coder's typed.
  • D: the squash's Resolved line.

Findings from writing this plan, for Sage

  1. The live smoke for 137 can't reach a landing. No definition in roles/ grants git.merge.protected, so every merge decision is gated and landHeld is false for every role. That holds until row 149 adds merge-gate.
    • Row 149's smoke plan should carry the first live landing. That landing moves main in the live working repository, so it needs Jason's agreement beforehand.
    • The plan should also check the squash's "as its arbiter, via the broker" line and the RESULT message.
  2. The seed declines silently. When main isn't an ancestor of the root's commit, working.mjs:172 returns with no log line, event or refusal, and main keeps an older base.
    • That is the intended effect after a landing, since main is ahead of root.
    • It also happens when the owner moves the root backward or checks out another branch there. Before 137 that case reset main to the root.
    • After 137, a coder's next push and a reviewer's next fetch are based on the old main, and nothing says so.
    • No safety problem: nothing is forced, and a landing still checks its base. It's a visibility gap; a host log line naming main and root would close it. Follow-up, not a 137 blocker.
  3. An approved gated merge decision is inert, but it stays approved. Step C leaves one in the store. Nothing can use it (see C).
    • The trail will show an approved, unspent git.merge.protected decision indefinitely.
    • If that would confuse a later reader of the trail, resolve it no, or skip C.