You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
autonomy: align the isolation ladder, work classes and merge caps with ADRs 0049 and 0050 #6140
PR #6139 adds ADRs that amend autonomy rules for CI lanes. Until the autonomy plugin and the loop-lane convention change to match, the two sources disagree.
ADR 0049: CI lanes on GitHub-hosted runners may run unattended without default-deny egress when five conditions hold (trusted actors only, same-repository PRs, one-hour scoped App tokens, kill switch, fresh runner per job). Conflicts with plugins/autonomy/reference/guardrails/isolation-ladder.md:15-17 and the fail-closed rule at :70-75.
ADR 0050: drop the vendor-hosted merge cap (plugins/autonomy/reference/trigger-dispatch.md:200-201); make C4 promotable by a merged config change with three checkers including Claude and Codex judges and a decided post-merge response (plugins/autonomy/reference/guardrails/work-classes.md:35-37, docs/conventions/loop-lane/README.md:50-52); C5 stays human.
Done when
The isolation ladder names the CI-lane surface and its five conditions, citing ADR 0049.
work-classes.md, trigger-dispatch.md and the loop-lane autonomy ladder state the ADR 0050 rules.
The pr-pipeline schema (docs/conventions/pr-pipeline/pr-pipeline.schema.json) gains the C4 rung in the same change or right after.
Blocked by #6139 (a human merges it: it changes lane powers).
Still unaligned (Basis: verified, origin/main 698960d):
The isolation ladder still makes L2 with default-deny egress "the minimum for any unattended run" and blocks dispatch fail-closed where L2 is unavailable; no ADR 0049 surface is named (plugins/autonomy/reference/guardrails/isolation-ladder.md:15-17, :70-75).
The vendor-hosted executor merge cap is still stated (plugins/autonomy/reference/trigger-dispatch.md:200-201).
The loop-lane convention still says C4 and C5 stay human-gated "unconditionally: no rung, no tracked config, and no invocation argument ever reaches them" (docs/conventions/loop-lane/README.md:50-52), and work-classes.md still says C4 needs human merge always.
The pr-pipeline schema's merge-rung description says "C4 and C5 need a human" (docs/conventions/pr-pipeline/pr-pipeline.schema.json:226). Only docs/conventions/pr-pipeline/README.md cites the two ADRs today.
Type: Task Summary: bring the autonomy guardrail contract, the loop-lane convention and the pr-pipeline schema into line with accepted ADRs 0049 and 0050.
Current behavior:
The accepted ADRs allow CI lanes on GitHub-hosted runners to run unattended without default-deny egress under five stated conditions, drop the vendor-hosted merge cap, and make C4 merge promotable by a merged config change with three agreeing checkers. The autonomy contract, the loop-lane autonomy ladder and the pipeline schema still state the older absolutes, so the sources disagree.
Desired behavior:
The isolation ladder names the CI-lane surface and its five conditions and cites ADR 0049; the fail-closed rule carves out that surface without weakening it elsewhere.
The executor-class merge cap is gone from the dispatch contract, citing ADR 0050.
The work-class contract and the loop-lane ladder state that C4 may be promoted only by a merged pipeline-config change with the ADR 0050 checker and post-merge-response requirements, and that C5 stays human.
The pr-pipeline schema accepts and documents a C4 rung consistently with the convention text.
Acceptance criteria:
Each changed statement cites the ADR it implements.
No remaining text in the autonomy plugin, the loop-lane convention or the pr-pipeline convention states a rule ADR 0049 or 0050 overturned.
C5 remains human-merge-only everywhere.
Schema validation and the repository's convention tests pass.
Out of scope:
Changing any lane's configured rung or enabling C4 merges in any repository.
Why human-gated: work class C4 (structural). It changes the contract that decides what unattended lanes may run and merge, so human review and human merge are required regardless of the decision already recorded in the ADRs. No decision is open; the gate is the class.
Two pieces of planned work from the 2,000-PRs effort overlap this issue. Neither will be built separately;
this comment hands their content here so the files change once.
Dropping the vendor-hosted merge cap duplicates this issue's trigger-dispatch.md:200-201 edit. Other
places ADR 0050's "matching changes" may need to reach:
The cap is also stated in plugins/autonomy/reference/runner.md:49-55, the lifecycle, seams, topology
and routines references, and 11 routine leaf pages.
check-security-binding.mjs rejects merge_policy: auto under a vendor-hosted executor. Once C4 is
promotable, decide what the checker does with C4 auto: the effort planned a fixture, vendor-hosted-c4-auto.json, that must fail. Also decide whether promotion ratification and unanimity
apply to every binding.
check-signal-envelope.mjs carries the same cap.
executor_class caps nothing once the cap goes. The effort planned to make it optional and ignored
rather than remove it, because removing it would fail existing bindings closed and touch 186 fixtures.
ADR 0050's sentence "Merge authority comes from the work class, the evidence gates and the repository's
configured rung" is the replacement text.
The loop-lane "Autonomy ladder (merge authority)" section is the one this issue rewrites. Content for
that rewrite:
Both merge authorities, the local babysit lane and pr-merge, read merge.rung from docs/conventions/pr-pipeline.yaml, and a repository has one (pr-pipeline README:204).
The per-run raise autopilot --merge c3-this-run (loop-lane README:72-96) and its pre-escalation
dispatch (:120-136) conflict with "a rung rises only through a merged change to the config file"
(pr-pipeline README:198), and should retire.
C5 (untrusted provenance) stays human at every rung. The effort proposes that the local lane refuse C4
even when the rung allows it, because ADR 0050's three checkers, including a Codex judge, run only in CI
lanes.
work-classes.md:114-126, the C4/C5 promotion row, changes along with :35-37.
The local-lane work that would read this text waits for the pipeline lanes. It is listed, with its design,
in #6202.
Decision recorded. The owner accepted the adjudicated recommendation on 2026-10-12.
Do the text alignment now. Keep merge.rung at off/C2/C3 in this change and state ADR 0050's C4 rule and its unmet gates in the schema description and README; add the C4 enum value, the binding checker's acceptance of merge_policy.C4 "auto" and the vendor-hosted-c4-auto fixture together in one follow-up, gated on pr-merge's merge activity existing and the post-merge remedy being decided. Make executor_class optional, deprecated and ignored (four code sites plus the schema), never removed.
Why: The owner's newest decision (#6202 amendment, 2026-10-12) says 'no C4 rung is added', and even on its narrowest reading nothing can honour a C4 value yet: pr-merge's merge activity is unbuilt (pr-pipeline README:430-433), ADR 0050's precondition of a decided post-merge remedy is still 'Not settled yet' (README:497), no org pr-pipeline.yaml sets a rung, and babysit_merge_policy.py:507-510 reads any rung outside off/C2/C3 as off with a note, so the value would have no consumer and one footgun. executor_class optional-and-ignored is the owner's planned approach (#6140 comment 2026-10-04T06:41Z) and keeps the 189 fixture files valid, but it needs check-signal-envelope.mjs:131-132 relaxed and three sites in check-security-binding.mjs (:548, :1880-1883, :2032), not the two the seed record assumed. The checker's rejection of merge_policy.C4 'auto' is a security boundary, so under precedence rule 1 it stays in this change and only its message changes to name ADR 0050's unmet gates; the GitHub pages read this run justify three small tightenings to the ADR 0049 ladder text.
Precedence applied: Rule 2 (newest owner decision: #6202 amendment 2026-10-12 'no C4 rung is added', with the done-when's 'or right after' reconciling it against the 2026-10-04 issue text) decided the C4 rung timing; rule 1 (a security boundary never weakens without the owner's explicit decision) kept the binding checker rejecting C4 'auto' in this change; rule 3 (ADR 0050 consequences, which permit but do not require a rung once the text lands) confirmed no conflict; rule 4 (GitHub docs fetched this run) supplied the three ladder tightenings. Researcher B's 'add C4 now with an if/then' loses under rule 2 and under 'build only what someone acts on': no org config sets a rung and no merge authority can honour C4 yet.
Sources:
gh issue view 6202, '## Amendment (auto-merge-safe-prs)': 'C2 only at launch... C4 stays human-gated and C5 human-merged; no C4 rung is added'; 'Input 8: accepted. C4 is refused locally'; 'pr-merge is not deployed in this repository'; 'Item 25: ... c3-this-run can no longer widen an unattended merge' (kyle-sexton, updated 2026-10-12T21:57Z)
gh issue view 6140 body (kyle-sexton 2026-10-04T00:57Z): done-when 'gains the C4 rung in the same change or right after'; comment 2026-10-04T06:41Z: executor_class optional and ignored, 186 fixtures, C4 'auto' checker question, c3-this-run retires
docs/adr/0050-...md:23-37 (decision), :53-56 ('offers no C4 rung until those changes land'; 'no repository can raise to C4 before it has' a post-merge response), origin/main 736fb71
docs/adr/0049-...md:40-44 (five conditions, 'amends the L2 floor for this surface only'), :63-64 (ladder needs a matching change)
docs/conventions/pr-pipeline/README.md:305-307 (schema adds no C4 rung until autonomy plugin and loop-lane carry the change), :430-433 (merge activity enforces 'when pr-merge is built'), :497-498 (post-merge remedy not settled)
docs/conventions/pr-pipeline/pr-pipeline.schema.json:296-302 (if/then on authority local-babysit), :305-308 (rung enum off/C2/C3, 'C4 and C5 need a human')
Next: One draft PR on #6140 (C4 structural: human review, human merge), plus one follow-up issue. PR content: (1) isolation-ladder.md: name the CI-lane surface on GitHub-hosted runners with ADR 0049's five conditions, carve it out of 'Unattended floor' and 'Fail-closed where L2 is unavailable' for that surface only, and add three upstream-backed notes: condition 2 excludes pull_request_target and workflow_run triggers; condition 3 requires explicit permission-* inputs and forbids skip-token-revoke on create-github-app-token; condition 5 excludes single-CPU hosted runners, which share a VM. (2) Drop the vendor-hosted merge cap, citing ADR 0050's replacement sentence, from trigger-dispatch.md:199-202, runner.md:49-56, runner/lifecycle.md, seams.md, topology.md, routines.md, the 11 routine leaves, the two setup context slices, the two setup templates, and the binding schema description at :20. (3) work-classes.md:35-37 and :126: C4 is promotable only by a merged pipeline-config change meeting ADR 0050's three checkers (Claude and Codex judges), a decided post-merge response and every C3 gate; C5 human always. (4) loop-lane README:46-53: replace 'unconditionally' with: C5 human at every rung; C4 refused by the local babysit lane (#6202 Input 8) and reachable only under pr-merge per ADR 0050; retire the c3-this-run raise and its pre-escalation dispatch (:77-102, #6202 Item 25), and update the source-control text that restates it (config-resolution.md:318-378, babysit-loop SKILL.md, cycle-shape.md, pre-escalation-dispatch.md, promotion-evidence-resolution.md:21, babysit-loop evals.json) in the same PR since the rule is one rule. (5) pr-pipeline.schema.json:308 and README:305-307: keep enum off/C2/C3; describe C4 as promotable under ADR 0050 once pr-merge's merge activity exists and the post-merge remedy is decided, and C5 as human always. (6) executor_class: remove it from 'required' at schema:10, add "deprecated": true and a description saying it is ignored; delete the required-key entry at check-security-binding.mjs:548 and the vendor-hosted branch at :1875-1883; drop the '!== "vendor-hosted"' term at :2032 so promotion ratification applies to every binding; drop the non-empty gate at check-signal-envelope.mjs:131-133; reword the :1886 message for C4 to cite ADR 0050's unmet gates instead of 'C4/C5 merge is human always' while still rejecting C4 'auto'; update the vendor-hosted-auto.json fixture and manifest expectation. (7) Run the convention tests and schema validation. Follow-up issue (the done-when's 'right after'): add C4 to merge.rung with an if/then rejecting rung C4 when authority is local-babysit, make babysit_merge_policy.py refuse C4 explicitly rather than reading it as off, accept merge_policy.C4 'auto' in check-security-binding.mjs only when verification_topology meets the C4 row at :409 and promotion_state is ratified, and add the vendor-hosted-c4-auto fixture; blocked on pr-merge's merge activity and the post-merge remedy decision (README:497).
Researched by two independent agents (local evidence and upstream docs) and adjudicated by a third.
Activity
github-actions commentedon Oct 4, 2026
Thanks for the report. Automated triage handed this issue to a maintainer.
Automated triage. A maintainer reviews it.
kyle-sexton commentedon Oct 4, 2026
This was generated by AI during triage.
Triage
L2with default-deny egress "the minimum for any unattended run" and blocks dispatch fail-closed whereL2is unavailable; no ADR 0049 surface is named (plugins/autonomy/reference/guardrails/isolation-ladder.md:15-17,:70-75).plugins/autonomy/reference/trigger-dispatch.md:200-201).docs/conventions/loop-lane/README.md:50-52), andwork-classes.mdstill says C4 needs human merge always.docs/conventions/pr-pipeline/pr-pipeline.schema.json:226). Onlydocs/conventions/pr-pipeline/README.mdcites the two ADRs today.Agent Brief
Type: Task
Summary: bring the autonomy guardrail contract, the loop-lane convention and the pr-pipeline schema into line with accepted ADRs 0049 and 0050.
Current behavior:
The accepted ADRs allow CI lanes on GitHub-hosted runners to run unattended without default-deny egress under five stated conditions, drop the vendor-hosted merge cap, and make C4 merge promotable by a merged config change with three agreeing checkers. The autonomy contract, the loop-lane autonomy ladder and the pipeline schema still state the older absolutes, so the sources disagree.
Desired behavior:
Acceptance criteria:
Out of scope:
Why human-gated: work class C4 (structural). It changes the contract that decides what unattended lanes may run and merge, so human review and human merge are required regardless of the decision already recorded in the ADRs. No decision is open; the gate is the class.
kyle-sexton commentedon Oct 4, 2026
Two pieces of planned work from the 2,000-PRs effort overlap this issue. Neither will be built separately;
this comment hands their content here so the files change once.
Dropping the vendor-hosted merge cap duplicates this issue's
trigger-dispatch.md:200-201edit. Otherplaces ADR 0050's "matching changes" may need to reach:
plugins/autonomy/reference/runner.md:49-55, the lifecycle, seams, topologyand routines references, and 11 routine leaf pages.
check-security-binding.mjsrejectsmerge_policy: autounder a vendor-hosted executor. Once C4 ispromotable, decide what the checker does with C4
auto: the effort planned a fixture,vendor-hosted-c4-auto.json, that must fail. Also decide whether promotion ratification and unanimityapply to every binding.
check-signal-envelope.mjscarries the same cap.executor_classcaps nothing once the cap goes. The effort planned to make it optional and ignoredrather than remove it, because removing it would fail existing bindings closed and touch 186 fixtures.
configured rung" is the replacement text.
The loop-lane "Autonomy ladder (merge authority)" section is the one this issue rewrites. Content for
that rewrite:
pr-merge, readmerge.rungfromdocs/conventions/pr-pipeline.yaml, and a repository has one (pr-pipeline README:204).autopilot --merge c3-this-run(loop-lane README:72-96) and its pre-escalationdispatch (
:120-136) conflict with "a rung rises only through a merged change to the config file"(pr-pipeline README:198), and should retire.
even when the rung allows it, because ADR 0050's three checkers, including a Codex judge, run only in CI
lanes.
work-classes.md:114-126, the C4/C5 promotion row, changes along with:35-37.The local-lane work that would read this text waits for the pipeline lanes. It is listed, with its design,
in #6202.
kyle-sexton commentedon Oct 13, 2026
Decision recorded. The owner accepted the adjudicated recommendation on 2026-10-12.
Do the text alignment now. Keep merge.rung at off/C2/C3 in this change and state ADR 0050's C4 rule and its unmet gates in the schema description and README; add the C4 enum value, the binding checker's acceptance of merge_policy.C4 "auto" and the vendor-hosted-c4-auto fixture together in one follow-up, gated on pr-merge's merge activity existing and the post-merge remedy being decided. Make executor_class optional, deprecated and ignored (four code sites plus the schema), never removed.
Why: The owner's newest decision (#6202 amendment, 2026-10-12) says 'no C4 rung is added', and even on its narrowest reading nothing can honour a C4 value yet: pr-merge's merge activity is unbuilt (pr-pipeline README:430-433), ADR 0050's precondition of a decided post-merge remedy is still 'Not settled yet' (README:497), no org pr-pipeline.yaml sets a rung, and babysit_merge_policy.py:507-510 reads any rung outside off/C2/C3 as off with a note, so the value would have no consumer and one footgun. executor_class optional-and-ignored is the owner's planned approach (#6140 comment 2026-10-04T06:41Z) and keeps the 189 fixture files valid, but it needs check-signal-envelope.mjs:131-132 relaxed and three sites in check-security-binding.mjs (:548, :1880-1883, :2032), not the two the seed record assumed. The checker's rejection of merge_policy.C4 'auto' is a security boundary, so under precedence rule 1 it stays in this change and only its message changes to name ADR 0050's unmet gates; the GitHub pages read this run justify three small tightenings to the ADR 0049 ladder text.
Precedence applied: Rule 2 (newest owner decision: #6202 amendment 2026-10-12 'no C4 rung is added', with the done-when's 'or right after' reconciling it against the 2026-10-04 issue text) decided the C4 rung timing; rule 1 (a security boundary never weakens without the owner's explicit decision) kept the binding checker rejecting C4 'auto' in this change; rule 3 (ADR 0050 consequences, which permit but do not require a rung once the text lands) confirmed no conflict; rule 4 (GitHub docs fetched this run) supplied the three ladder tightenings. Researcher B's 'add C4 now with an if/then' loses under rule 2 and under 'build only what someone acts on': no org config sets a rung and no merge authority can honour C4 yet.
Sources:
Next: One draft PR on #6140 (C4 structural: human review, human merge), plus one follow-up issue. PR content: (1) isolation-ladder.md: name the CI-lane surface on GitHub-hosted runners with ADR 0049's five conditions, carve it out of 'Unattended floor' and 'Fail-closed where L2 is unavailable' for that surface only, and add three upstream-backed notes: condition 2 excludes pull_request_target and workflow_run triggers; condition 3 requires explicit permission-* inputs and forbids skip-token-revoke on create-github-app-token; condition 5 excludes single-CPU hosted runners, which share a VM. (2) Drop the vendor-hosted merge cap, citing ADR 0050's replacement sentence, from trigger-dispatch.md:199-202, runner.md:49-56, runner/lifecycle.md, seams.md, topology.md, routines.md, the 11 routine leaves, the two setup context slices, the two setup templates, and the binding schema description at :20. (3) work-classes.md:35-37 and :126: C4 is promotable only by a merged pipeline-config change meeting ADR 0050's three checkers (Claude and Codex judges), a decided post-merge response and every C3 gate; C5 human always. (4) loop-lane README:46-53: replace 'unconditionally' with: C5 human at every rung; C4 refused by the local babysit lane (#6202 Input 8) and reachable only under pr-merge per ADR 0050; retire the c3-this-run raise and its pre-escalation dispatch (:77-102, #6202 Item 25), and update the source-control text that restates it (config-resolution.md:318-378, babysit-loop SKILL.md, cycle-shape.md, pre-escalation-dispatch.md, promotion-evidence-resolution.md:21, babysit-loop evals.json) in the same PR since the rule is one rule. (5) pr-pipeline.schema.json:308 and README:305-307: keep enum off/C2/C3; describe C4 as promotable under ADR 0050 once pr-merge's merge activity exists and the post-merge remedy is decided, and C5 as human always. (6) executor_class: remove it from 'required' at schema:10, add "deprecated": true and a description saying it is ignored; delete the required-key entry at check-security-binding.mjs:548 and the vendor-hosted branch at :1875-1883; drop the '!== "vendor-hosted"' term at :2032 so promotion ratification applies to every binding; drop the non-empty gate at check-signal-envelope.mjs:131-133; reword the :1886 message for C4 to cite ADR 0050's unmet gates instead of 'C4/C5 merge is human always' while still rejecting C4 'auto'; update the vendor-hosted-auto.json fixture and manifest expectation. (7) Run the convention tests and schema validation. Follow-up issue (the done-when's 'right after'): add C4 to merge.rung with an if/then rejecting rung C4 when authority is local-babysit, make babysit_merge_policy.py refuse C4 explicitly rather than reading it as off, accept merge_policy.C4 'auto' in check-security-binding.mjs only when verification_topology meets the C4 row at :409 and promotion_state is ratified, and add the vendor-hosted-c4-auto fixture; blocked on pr-merge's merge activity and the post-merge remedy decision (README:497).
Researched by two independent agents (local evidence and upstream docs) and adjudicated by a third.