Skip to content

feat(merge): make the trust trail's instrument a data field so /premerge output is landable - #792

Open
TheFJK wants to merge 12 commits into
mainfrom
worktree-turbox-issue-716
Open

TheFJK wants to merge 12 commits into
mainfrom
worktree-turbox-issue-716

Conversation

@TheFJK

@TheFJK TheFJK commented Aug 24, 2026

Copy link
Copy Markdown
Collaborator

Generalises /merge's Phase 1.4 trust gate so the trail's instrument is a data field — Reviewed-by: uberdev/<instrument>@<sha> over the closed set {review-pr, premerge} — instead of a hardcoded uberdev/review-pr@ prefix. /premerge emits that trail on a green clean gate.

Implements the ## Steer (2026-08-24) direction on #716: relax the gate's strictness rather than bolt on a parallel PATH_3. The literal PATH_3 was in fact unbuildable — two guards in tests/merge.test.sh red the build if that token appears in the extracted Phase 1.4 body (:673 and :903 on main; :730 and :1040 on this branch, which adds 137 lines to that file).

Refs #716 — this PR does NOT close it

Two blocking findings survive, both confirmed by execution. Closing #716 on this PR would be a false claim, so it deliberately says Refs rather than Closes.

BLOCKER 1 — the emitted trail is unreadable by /merge on /premerge's own default path

### 5-trail emits the anchor, then ### 5a lands chore(release): vX.Y.Z on top of it. /merge can only read a trailer buried under a release commit when release-anchor.sh returns tolerated; on this repo's CHANGELOG style it returns none.

Measured against real history — 2c6db441 (the v0.56.0 release commit, itself produced by a /premerge stack run) gives RELEASE_ANCHOR=none RELEASE_ANCHOR_REASON=diff_too_large, and four older release commits give none for changelog_shape / non_version_paths. Cause: RELEASE_ANCHOR_MAX_DIFF_LINES=400 plus the added-line shape predicate, which admits only bump-version.sh's bare stub — and 5a explicitly replaces that stub with real notes.

TRUST_HEAD therefore falls back to the release commit, which carries no Reviewed-by:, and the gate fails trust_trail_trailer_missing. The stack PR is structurally unlandable again, which is the condition #716 exists to remove.

The obvious workaround is foreclosed: emitting after the bump makes the gate fence's HEAD binding return TRAIL=skipped REASON=head_moved, publishing nothing. This needs a design decision — widen release-anchor.sh's tolerance to this repo's CHANGELOG shape, have 5a amend rather than stack, or re-gate after the bump — not a patch.

BLOCKER 2 — a deferred-CRITICAL trail can now land without --accept-critical-deferred

Admitting uberdev-approved-with-concerns as a review-pr-instrument label moves a YELLOW PR from refuse-at-(a) to evaluate-at-(c). The Phase 2.5 gate that should then catch it is inert whenever the audit JSON is not locally discoverable: (c.0) defaults PHASE2_5_AUDIT_STATE=absent with PHASE2_5_CRITICAL_COUNT=0, the evaluator's absent arm skips the Phase 2.5 gate, and (d)'s ABSENT path emits gate_pass.

Concretely: /review-pr runs in a solver worktree under /tmp/uberdev-solve-* and defers 2 CRITICAL findings; /merge runs from the main checkout (the documented split); the discovery helper searches only repo-root-relative layouts, finds nothing, and the PR lands with 2 unresolved CRITICAL findings and no flag.

This relaxation is orthogonal to #716's stated scope — it arrived bundled with the instrument generalisation. /review-pr already writes severity=critical-deferred count=N into the trailer and (b.5) already parses it into $TRAILER_SUFFIX, but nothing reads it; gating on that suffix would close the hole using the same reasoning already applied one tier over. Reverting the label admission is the other option.

Also unfixed (review budget exhausted)

The fix round could not be dispatched — TB2 hit 24/24, in part because a session-limit outage killed five review agents at their first tool call and the counter charged those seats again on re-dispatch.

  • references/phase-contracts.md:191 — defines PREMERGE_ATTEMPT for the gate fence as the last CONVERGE ledger row, but Phase 4c advances the counter and writes gate-<N+1>.json while writing no ledger row. A controller following the contract passes N, the fence reads a gate stamped with the pre-simplify HEAD, prints REASON=head_moved and exits 0 — a green stack silently gets no trail on the default path. The same section contradicts itself at :196.
  • merge-pipeline/SKILL.md:862 — PATH_2's terminal instruction stamps uberdev_review_trail unconditionally, so every premerge trail on a fresh clone records the wrong anchor, defeating tier distinguishability. Mirrored at agents/trust-trail-evaluator.md:157.
  • merge-pipeline/SKILL.md:533 — the (a.5) release-anchor paragraph asserts the anchor is "unchanged" uberdev_review_trail, on what D8 makes the primary premerge path.
  • merge-pipeline/SKILL.md:1002, :1734 — PATH_2 mirrors still enumerate only a /review-pr trail, against the file's own editors' note at :1004 requiring all five mirrors to move together. Mirror 5 is in using-uberdev/SKILL.md and is unowned.
  • agents/trust-trail-evaluator.md:29 — the Reviewed-base bullet still hardcodes uberdev/review-pr@ and says null when absent; read literally it sends every premerge trail to the STALE arm.
  • merge-pipeline/SKILL.md:59 — UBERDEV_APPROVED_LABEL's "Used by" cell still says "label presence check", the mechanism (a) replaced.
  • A dual-labelled stack PR deadlocks at (a): the case matches premerge-approved first, so running /review-pr on a stale-trailed stack PR (which /merge's own diagnostic suggests) yields a permanent gate_fail until the label is removed by hand.
  • The half-emitted trail (push succeeds, gh pr edit --add-label fails) has no re-entry path: re-running the gate returns head_moved. Moving the idempotent gh label create --force above the push would close the window.

What was verified

The integration pass ran the full authoritative list from .github/workflows/test.yml on this exact tree — 132 run_one rows, 0 reds, on macOS. Reported per-suite there: merge 550/0, premerge 275/0, premerge-phase5 85/0, trust-trail-base-identity 117/0, trust-trail-evaluator 40/0, skill-size 49/0, prkit-publish 11/0, docs-accuracy 309/0, vendor-provenance 63/0, findings-to-issues 202/0.

The delivery pass independently re-ran the seven suites this change actually touches, reading each exit code directly: merge 550/0, premerge 275/0, premerge-phase5 85/0, trust-trail-base-identity 117/0, trust-trail-evaluator 40/0, vendor-provenance 63/0, skill-size 49/0 — all rc=0, every count matching the integration pass.

The macOS smoke job's 8 fixtures are all members of the shape-checks list and were covered by that run. Windows is not covered and was not reproducible locally; 4 Windows-only argv shapes ran as Darwin proxies and code-fixer-contract-windows.test.py refuses to run off native Windows. Git Bash CR handling and MSYS path translation are untested until CI.

The new gate and emit fences are extracted and executed under both bash and zsh, not transcribed — including a recording git/gh PATH shim proving the skip path makes no call at all, with a control run proving the shim is not blind. Every new assertion row was mutation-tested to confirm it can actually fail.

Invariants held

/merge still never merges without an explicit operator command for that PR; /premerge never merges anything (0 merge or auto-merge verbs across all 1097 added lines); head-SHA binding, base-identity equivalence and force-push detection untouched; /premerge cannot claim the review-pr instrument (P10 retargeted, not weakened, and mutation-proved to red on four separate forgeries); /goal unaffected, since it reads uberdev-approved by exact equality; no version surface moved.

Refs #716

@coderabbitai

coderabbitai Bot commented Aug 24, 2026

Copy link
Copy Markdown

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 2fac4452-16a5-4754-8d35-d9158a0666b4


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@TheFJK

TheFJK commented Aug 24, 2026

Copy link
Copy Markdown
Collaborator Author

Superseded for review by #793; the trust trail will be emitted there.

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