Skip to content

fix(star): close the #66 wiring and mechanize the model-id collision - #81

Merged
kevin-agrology merged 2 commits into
mainfrom
fix/session-root-wiring-and-collision
Aug 11, 2026
Merged

fix(star): close the #66 wiring and mechanize the model-id collision#81
kevin-agrology merged 2 commits into
mainfrom
fix/session-root-wiring-and-collision

Conversation

@kevin-agrology

Copy link
Copy Markdown
Contributor

TL;DR: Three things the audit found that the earlier PRs said they'd fix and didn't. Two are wiring bugs where the command tells the primary to do the exact thing another section of the same file forbids; the third replaces a prose warning with an actual check, for a failure that leaves a review permanently stuck.

Completes #66's wiring. Relates to #71/#47.

1. ensure-skill took the wrong root

The Arm section forbids inlining $(git rev-parse --show-toplevel) for --session-root, with a paragraph explaining why. Fan-out step 3 then instructed exactly that substitution for ensure-skill --repo.

They resolve differently in precisely the case #66 is about: by fan-out the egress guard has pushed the primary into the repo that owns the doc, while the dispatched subagent inherits the session cwd. So the skill bundle materializes into a repo the reviewer never sees, and the round dies as a wait-bound timeout whose reason describes the symptom.

Now takes the captured <session-root>. The flag also keeps its value on the same line — it was wrapped such that an agent copying the runnable line would copy a bare --repo. My own guard caught that, which is a decent sign it's checking the right thing.

2. The capture came after the thing that destroys it

Capture the session root FIRST was the sixth Arm bullet. The egress guard that forces the directory change was the first.

A primary executing bullets in order has already lost the original cwd by the time it reads the instruction — and git rev-parse then returns the doc's repo, which is the wrong value, silently. Ordering is the guarantee here, so the capture is now the first bullet and says why.

3. The collision deadlock was defended by prose

The self-response guard is parse-fatal by design, but it fires only once the colliding response is already written. _table underlies _structural_consistency, so from that moment merge's pre-check, verify, gate-summary, round-stats and compose-review all fail. The review is stuck in both directions: you can't respond without tripping the guard, and can't converge without responding. Recovery means hand-editing the doc or disclosing a false id.

This is not operator error waiting to happen — it's a supported configuration. fable is a selectable session model, so a fable-powered primary discloses exactly the string its floor secondary does. The only defense was one sentence of prose.

New subcommand, run before the first response of a primary turn:

multi-review-star.sh check-primary-id "<doc>" "<primary-model-id>"     # exit 3 on collision

It reads the raiser's disclosure only — the > — via immediately after a > [finding: — never just any > — via in the doc, because the primary's own responses carry one and matching those would refuse every round after the first. That case is explicitly asserted.

Guards

entry covers
command/ensure-skill-session-root an inlined substitution returns
command/session-root-first-claim the ordering claim disappears
command/check-primary-id-gate the gate degrades back to prose
star/check-primary-id-raiser-only the check reads any via instead of the raiser's

All four verified caught.

One is named for less than it sounds like. A single-line replace cannot actually reorder two bullets, so session-root-first-claim covers the claim's presence, not the order. The order itself is asserted by comparing line numbers, which only a real reordering exercises. Named for what it covers rather than what I'd like it to cover.

core.sh mutation coverage: attempted, withdrawn, recorded

I tried to close the last zero-coverage file and could not do it honestly. Two blockers, both measured:

  1. core.sh is vendored into .agents/skills/multi-review/scripts/. Any mutation to the source makes multi-review-reviewer-bundle.test.sh fail first with bundled script missing/drifted — a real guard firing for an unrelated reason. Every core.sh mutation is therefore MISCREDITED: the gate goes red, but never via the assertion being claimed.
  2. Independently, multi-review-core.test.sh stayed green with the duplicate-marker guard ((( n > 1 ))) mutated — so that line has no coverage in its own suite either, and the marker fails with duplicate markers assertion is satisfied by a different mechanism.

Rather than credit either entry via the drift message — which is exactly the "credited by the wrong evidence" failure the runner exists to prevent — both are withdrawn and the reason is recorded in the table, the same way the #37 egress gap is. Fixing it needs the runner to mirror a mutation into the vendored copy (or exempt it), which is its own change.

Verification

check result
scripts/*.test.sh (15 suites) all pass
4 mutation entries all caught
multi-review-version-check.sh 1.19.0 → 1.21.0 (ok)

Minor version: check-primary-id is a new subcommand.

Not run locally: shellcheck (not installed here); CI covers it plus the bash 3.2 leg and the full sweep.


🤖 Generated with Claude Code

https://claude.ai/code/session_01Nm3hNXA4WHbgKjFbxX7VUE

kevin-agrology and others added 2 commits August 11, 2026 10:37
Three defects the audit named and the earlier PRs did not deliver, plus the
last file with no mutation coverage.

ENSURE-SKILL TOOK THE WRONG ROOT. The Arm section forbids inlining
`$(git rev-parse --show-toplevel)` for `--session-root`, and fan-out step 3
then instructed exactly that substitution for `ensure-skill --repo`. The two
resolve differently in precisely the case #66 is about: by fan-out the egress
guard has pushed the primary into the repo that owns the doc, while the
dispatched subagent inherits the SESSION cwd — so the skill bundle materializes
into a repo the reviewer never sees and the round dies as a wait-bound timeout.
Now takes the captured `<session-root>`, and the flag keeps its value on the
same line so an agent copying the runnable line does not copy a bare flag.

THE CAPTURE CAME TOO LATE. "Capture the session root FIRST" was the sixth Arm
bullet; the egress guard that forces the directory change was the first. A
primary executing bullets in order has already lost the original cwd by the
time it reads the instruction, and `git rev-parse` then returns the doc's repo
— the wrong value, silently. Ordering IS the guarantee, so the capture is now
the first bullet and says why.

THE COLLISION WAS DEFENDED BY PROSE. The self-response guard is parse-fatal by
design, but it fires only once the colliding response is already written — and
`_table` underlies `_structural_consistency`, so from that moment merge's
pre-check, verify, gate-summary, round-stats and compose-review all fail too.
The review is stuck in both directions: the primary cannot respond without
tripping the guard, and cannot converge without responding. Recovery means
hand-editing the doc or disclosing a false id.

The trigger is a SUPPORTED configuration, not operator error: `fable` is a
selectable session model, so a fable-powered primary discloses exactly the
string its floor secondary does.

New `check-primary-id <doc> <primary-model-id>` (exit 3 on collision) is run
before the first response of a primary turn. It reads the RAISER's disclosure
only — the `> — via` immediately after a `> [finding:` — never any `> — via` in
the doc, because the primary's own responses carry one and matching those would
refuse every round after the first. That case is asserted.

Guards: six entries. Four for the above, and the first two for core.sh, which
had none despite being the marker engine every other script parses through.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Nm3hNXA4WHbgKjFbxX7VUE
Three conflicts, all resolved by keeping both sides — the branches added
independent test blocks and mutation entries, not competing edits.

One needed care: the conflict boundary in multi-review-packaging.test.sh cut
through this branch's #66 guard block, leaving its two closing `fi`s on the
other side. Keeping both sides verbatim dropped them and the file stopped
parsing. Restored, and every guard from BOTH branches verified to still fire —
a merge that swallows a closing brace is exactly how a guard goes silent while
the suite still looks plausible.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Nm3hNXA4WHbgKjFbxX7VUE
@kevin-agrology
kevin-agrology merged commit 66e4c28 into main Aug 11, 2026
4 checks passed
@kevin-agrology
kevin-agrology deleted the fix/session-root-wiring-and-collision branch August 11, 2026 20:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant