Skip to content

docs(loop-lane): route the five guardrail escalation classes to lanes and name the intake injection hold - #13021

Merged
kyle-sexton merged 7 commits into
mainfrom
fix/12968-replacement
Nov 4, 2026
Merged

kyle-sexton merged 7 commits into
mainfrom
fix/12968-replacement

Conversation

@kyle-sexton

@kyle-sexton kyle-sexton commented Nov 4, 2026 •

Copy link
Copy Markdown
Member

Refs: #11024

Replaces #12968.

Summary

Part 6 of #10517. The guardrail escalation contract (plugins/autonomy/reference/guardrails.md#escalation) gains a "Stops for a person" column and a stop rule: gate-failure, verification-divergence and demotion go to the lane that owns the follow-up, an audited admission-rejection stays final on the audit trail, structural-plan-approval stops only when the plan changes intent or the primary design, and untrusted-provenance still always stops. Loop-lane §2 is amended to match, and "When work stops for the owner" names intake's hold on text addressed to the triage run as a kept trust control, with its reason; that hold's behavior is unchanged.

This carries #12968's change (head 92b6dcc1, merged in unchanged) plus fixes for its open review threads.

Fix

From #12968:

  • plugins/autonomy/reference/guardrails.md: "Stops for a person" column, stop rule, routing obligation and mechanism; matrix escalation cells for C2 to C4 read "owning lane".
  • plugins/autonomy/reference/guardrails/verification-topology.md: a dissent raises verification-divergence, routed by the stop rule.
  • plugins/autonomy/reference/runner/escalation.md: gate-failed files on the gate-failure route; fan-out reaches people only on a human-gated item.
  • docs/contracts/loop-lane/README.md and CHANGELOG.md (17.0.0, major per the file's bump rule).
  • .github/scripts/intake-triage/apply-verdict.test.mjs: the escalated-run test also asserts the kept injection hold is not refused.

New in this PR:

  • docs/contracts/loop-lane/README.md §2: the "aligning those records is separate work" note is replaced by the post-merge demotion alert's record rules as fix\(pr-pipeline\): align every needs-human path with the owner stop rule - part 4 of 6 #11022 set them (merged in feat(source-control): lift canary, revert and read-back demotion records on lane evidence #12905): a red-main record carries no label and clears on a later green main; a canary, revert or read-back record keeps needs-human only until it lifts on its own lane-verifiable condition; and a fix or quarantine issue intake did not receive, or a red-main record whose failing check got no fix issue, gets needs-human because no lane retries that delivery. The CHANGELOG 17.0.0 entry says the same.
  • plugins/autonomy/reference/runner/escalation.md: a lane-route item no lane claims within the staleness window re-escalates once as a new signal to intake, one severity level up, so a disabled, stopped or unpolled lane cannot hold a failed gate unseen. Intake's own rules decide whether it stops for a person, so the backstop adds no needs-human outside the stop rule. The changelog fragment says so.

Verification

  • node --test .github/scripts/intake-triage/apply-verdict.test.mjs: 232 passed, 0 failed (the kept injection hold still stops for a person).
  • scripts/check-changelog-fragments.sh --check: all 39 fragments valid.
  • scripts/check-affected.sh: 12 passed, 3 skipped over 7 changed files.
  • The demotion records' routing and lift conditions are tested by feat(source-control): lift canary, revert and read-back demotion records on lane evidence #12905's suites (.github/scripts/post-merge-demotion-alert/workflow.test.mjs, scripts/post-merge-demotion-alert.test.sh, test_babysit_lift.py, test_babysit_merge_policy.py, test_babysit_postmerge.py).
  • The other four classes are contract text with no executable router in this repository: the security binding carries one route string per class, which check-security-binding.mjs validates, and no script applies needs-human from these class names (git grep over *.mjs, *.py, *.sh). No test was added for them, since it could only assert the markdown text.
  • claude-security-review on docs(loop-lane): route the five guardrail escalation classes to lanes and name the intake injection hold #12968's head 92b6dcc1 reported 0 findings.

Remaining

Issue 11024 stays open after this merges; two of its done-when items remain:

Related

🤖 Generated with Claude Code

https://claude.ai/code/session_01MWmASPDSoP4Ps23JPiGyZV

melodic-automation-lanes Bot and others added 5 commits November 3, 2026 22:27
Lane-Activity: work-resolve-issue/resolve-issue
Lane-Activity: pr-unblock/address-feedback
Lane-Thread: PRRT_kwDOTCGFQM6zXKJr
…nclaimed-item backstop

Replaces the "separate work" note on the post-merge demotion alert with the
record rules #11022 set: canary, revert and read-back records keep
needs-human only until they lift, and an issue intake did not receive gets
it because no lane retries that delivery.

A lane-route escalation item that no lane claims within the staleness window
now re-escalates once to intake, one severity level up, so a stopped or
unpolled lane cannot hold a failed gate unseen.

Refs: #11024

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01MWmASPDSoP4Ps23JPiGyZV
@kyle-sexton
kyle-sexton marked this pull request as ready for review November 4, 2026 01:13
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Nov 4, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-11-04T01:15:07.902280Z ba48546 Draft marked ready
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@github-actions

github-actions Bot commented Nov 4, 2026 •

Copy link
Copy Markdown
Contributor

claude-security-review reviewed a7db53e19c18e9b7a98e2e487353c8fcfa888d00: read 7 of 7 changed file(s); 0 finding(s), 0 as inline comments.

Security review: no security issues found

I read every hunk of all 7 changed files in .claude-lane/pr.diff. Six are contract and reference prose:

  • the changelog fragment
  • the loop-lane README.md and CHANGELOG.md
  • guardrails.md
  • verification-topology.md
  • runner/escalation.md

The seventh is .github/scripts/intake-triage/apply-verdict.test.mjs, which changes one existing test and adds one new test. The PR changes no executable code, workflow, action, plugin manifest or trusted-path file.

What I checked

  • Instruction-surface lens. The diff narrows when an escalation stops for a person:

    • The matrix cells for C2 to C4 change from "→ human" to "→ owning lane".
    • A dissent under the unanimity rule (in guardrails.md and verification-topology.md) now raises verification-divergence instead of handing the item to the human gate.
    • The runner's gate-failed outcome is filed on the gate-failure route.

    Each removed rule is a person-approval hold, one of the owner's named friction holds, so the throughput-phase owner threat model exempts it. The new stop rule still sends any HIGH or CRITICAL security or cost risk to a person.

  • Controls that still stop for a person.

    • untrusted-provenance, the hold on untrusted provenance, is kept as "always: a kept trust control".
    • C5 still requires a human merge every time.
    • The intake injection hold, for text addressed to the triage run, is now named in "When work stops for the owner" as a kept trust control. Its behavior does not change.
    • The new re-escalation backstop in runner/escalation.md sends an unclaimed lane-route item to intake. That adds a path; it removes no check.
  • No code behind the routing. The diff does not touch merge-holds.mjs, babysit_risk.py, apply-verdict.mjs, intake-triage.yml, resolve-config or the security binding.

  • Tests. The changed test now sets holdSetters to the Actions bot and asserts that refused is empty and the escalation reason is present. The new test covers an escalated verdict with Flags: none and all three dimensions, and asserts the needs-human hold is neither refused nor removed. Both tests strengthen the check that the injection hold still stops for a person.

  • Trust controls. Nothing here widens who is trusted, what a token may do, the kill switch, a merge gate, or the untrusted text that reaches a lane.

  • Settled thread. The thread on apply-verdict.test.mjs lines 400-403 is settled by an owner reply, with no lines changed since resolution. I am not re-raising it.

  • PR context. It contains no embedded directives aimed at this lane.

Owner friction hold narrowed (throughput phase, not a finding): the contract text in guardrails.md, runner/escalation.md and loop-lane §2 narrows the person-approval hold on gate-failure, verification-divergence and demotion escalations.

critical-findings: 0

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

claude-review: 1 inline finding(s) on ba48546631766ee9baa099b0b8caaafc2456cf80; the summary is in this lane's pull request comment.

claude-lane: claude-review

@github-actions

github-actions Bot commented Nov 4, 2026 •

Copy link
Copy Markdown
Contributor

claude-review reviewed a7db53e19c18e9b7a98e2e487353c8fcfa888d00: read 7 of 7 changed file(s); 1 finding(s), 0 as inline comments.

Code review: #13021 at a7db53e1

I read all 7 changed files in the diff. Most of the change is contract text: the guardrails escalation table and stop rule, verification-topology, runner escalation, loop-lane §2 and its changelog, and the autonomy changelog fragment. One test file also changed. The wording agrees across the four docs. The matrix cells, the unanimity rule and the runner's gate-failed outcome now route to the owning lane, and untrusted-provenance stays a kept control in each one. I checked the new test (apply-verdict.test.mjs L48-L57) against parseVerdict and planWrites in apply-verdict.mjs. An escalated verdict with Flags: none and all three dimensions parses to escalated: true, flags: [] and non-null dimensions. Two things keep it from being refused: the escalated reason at L258-L259 and the guard at L351. So the new test exercises the property the README states.

I ran nothing. The PR's Verification results (232/233 tests passed, fragments valid, check-affected) are the author's claims and I have not checked them.

Settled

  • The earlier inline thread on apply-verdict.test.mjs L400-L403 is settled. The owner replied with the fix (the new fixture) and with their reasoning about the two guards. Those lines have not changed since, so I am not raising it again.

Findings

  1. Closing issue fix\(pr-pipeline\): align every needs-human path with the owner stop rule - part 6 of 6 #11024, criterion not met with a test (restated; it is a summary finding with no line anchor): "Each changed path has a test or check showing the new routing." (also worded "A test or check per changed path shows the new routing.")

Closing-issue criteria (other items)

  • The five classes route to a lane or are named as kept controls: met in guardrails.md and loop-lane §2.
  • Intake injection hold named as a kept trust control, with its reason: met in README "When work stops for the owner".
  • Kept trust control behavior unchanged, with a test showing it still stops: met. The existing escalated-run test and the new Flags: none test both assert that needs-human is held and not refused.
  • Security-review pass at the head: that is the security lane's job, outside this lane's scope.

Other notes

  • Embedded text: none found in the PR context, settled-threads or prior-findings files.
  • Manifests: no plugin.json or marketplace.json changes, so there are no manifest lines. The .changes/autonomy fragment's bump: minor and loop-lane 17.0.0 (major, per that file's own bump rule) match the change.
  • Spend: none. The PR changes no lane runtime, schedule, model or billing.

kyle-sexton and others added 2 commits November 3, 2026 20:27
…ads Flags: none

The existing escalated fixture has no Flags line, so it never reached the
refusal candidates. This one carries Flags: none and every dimension, the
shape the loop-lane README describes, and asserts needs-human stays.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01MWmASPDSoP4Ps23JPiGyZV
Co-Authored-By: Claude Opus 5.5 <[email protected]>
@kyle-sexton
kyle-sexton added this pull request to the merge queue Nov 4, 2026
Merged via the queue into main with commit 47c42a1 Nov 4, 2026
60 checks passed
@kyle-sexton
kyle-sexton deleted the fix/12968-replacement branch November 4, 2026 01:42
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