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]>
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
landHeldcall on every launch, answering false; - the working repository's new seed:
refs/heads/root, withmainfollowing only by fast-forward; - land-work.sh, which already runs from the canonical checkout at
18aee8fa1, still landing Sage's work onrefactor; - 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'snot-authorized. No session can send alandline withoutland_work, and the capability never reaches the model.prepareLand, the gate underbus-host/land/<id>/,finishLandandrecordLand.- The "as its arbiter, via the broker" Resolved line.
- The RESULT messages, and the
land-busy,base-moved,gate-failed,host-closingandrollback-failedpaths.
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)
- 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
landHeldbefore 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.
- The launcher calls the host op
- No role definition grants git.merge.protected.
grep -l git.merge.protected <copy>/roles/*.jsonfinds nothing. The live business file's roles name only those definitions (definitionkeys).- 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.
- If the grep finds a definition with git.merge.protected under
- 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-rolerow. This is the answer to "which live role can hold one today": none.
- Before row 139, git.merge.protected was a hard wait, so any existing row should be
bus.testeristruefor the business.- 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 projectstack'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/mainandrefs/heads/work/...refs, with norefs/heads/root. Before 137 the seed fetched the root straight intomain, forced. - Call the recorded
mainM0 and the root commit R0.
- the project root's checked-out commit:
- 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.jsonhas noland_work, and the bundle'sprompt.mdhas no "Landing:" line. - Pass: the session's
session.jsonnamesgitSocketonly for the roles that held it before 137: those whose definition holds git.push.working or review.verdict (coder and reviewer inroles/). 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
mainto R1. That movesmainin 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,
mainstays at M0 (working.mjs:172) and onlyrootmoves.
After it, run the same for-each-ref:
- Pass:
refs/heads/rootexists and equals the root's checked-out commit at the push. Checkgit -C <root> rev-parse HEAD, if the root hasn't moved since. - Pass:
git --git-dir=<repo> merge-base --is-ancestor M0 refs/heads/mainexits 0.mainis M0, or the fast-forward toroot, and was never forced. - Pass: the push or fetch succeeded. Its trail shows the
action.allowedfor git.push.working, or the reviewer got its bundle. - Pass: the project root's
git statusand 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'smosaic 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
yesby 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.jsontypedhas noland_work, and<dataRoot>/bus-host/land/still doesn't exist.
- Pass: its
Notes for Mos:
<test task ref>must be a task ref (vikunja:<project>/<task>), sincelandHeldreads 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:
landHeldskips any class butcross-role,checkLandrefuses itnot-authorized, and its class can't change, since#authorityForrequires the stored class to equal the current one. land-work refuses itnot-human. If Mos would rather not leave an approved merge decision in the store, resolve itno. 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
refactorhasResolved <choice> by <by> via the CLI at <time>. - Pass: the land-work log shows read.mjs's output parsed. Its new
via cliline is ignored, because land-work.sh'svalue()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
landline.
Evidence
Mos keeps:
- A:
manifest.jsontyped, and whether each launched role'ssession.jsonnamesgitSocket. - B: the
for-each-refoutput before and after, with R0, R1 and the merge-base exit status. - C, if run: the
talk --followoutput,trail --json, and the relaunched coder'styped. - D: the squash's Resolved line.
Findings from writing this plan, for Sage
- The live smoke for 137 can't reach a landing. No definition in
roles/grants git.merge.protected, so every merge decision isgatedandlandHeldis 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
mainin 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.
- Row 149's smoke plan should carry the first live landing. That landing moves
- The seed declines silently. When
mainisn't an ancestor of the root's commit, working.mjs:172 returns with no log line, event or refusal, andmainkeeps an older base.- That is the intended effect after a landing, since
mainis ahead ofroot. - It also happens when the owner moves the root backward or checks out another branch there.
Before 137 that case reset
mainto 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
mainandrootwould close it. Follow-up, not a 137 blocker.
- That is the intended effect after a landing, since
- 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.