Skip to content

autonomy: align the isolation ladder, work classes and merge caps with ADRs 0049 and 0050 #6140

Open

Description

@kyle-sexton

Problem

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).

Activity

  1. added theissue type on Oct 4, 2026
  2. added
    needs-triageNot yet classified. Floor until a type and one priority tier are set.
    on Oct 4, 2026
  3. github-actions commented on Oct 4, 2026

    @github-actions
    Contributor

    Thanks for the report. Automated triage handed this issue to a maintainer.

    Automated triage. A maintainer reviews it.

  4. added
    needs-humanHuman-in-the-loop required; autonomous sessions must not resolve items carrying this.
    on Oct 4, 2026
  5. kyle-sexton commented on Oct 4, 2026

    @kyle-sexton
    ContributorAuthor

    This was generated by AI during triage.

    Triage

    • Blocker cleared: docs(conventions): add the pr-pipeline convention, config schema and lane ADRs #6139 merged 2026-10-04T02:29Z, and ADRs 0049 and 0050 are on main with status accepted.
    • 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.
    • Redundancy: no other open item carries this alignment. Related, not the same decision: babysit-loop: wire inline promotion evidence into the CI pr-merge lane #4588 (lane merge authority, human-gated) and autonomy: decide whether to build a mod that approves babysit-lane actions through tool.check #6154 (a mod approving lane actions).

    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:

    • 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:

    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.

  6. added
    priority: mediumReal value, no hard deadline; normal backlog flow.
    work-class: structuralRefactors, migrations, contract changes; cross-cutting and hard to reverse.
    and removed
    needs-triageNot yet classified. Floor until a type and one priority tier are set.
    on Oct 4, 2026
  7. kyle-sexton commented on Oct 4, 2026

    @kyle-sexton
    ContributorAuthor

    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.

  8. kyle-sexton commented on Oct 13, 2026

    @kyle-sexton
    ContributorAuthor

    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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    needs-humanHuman-in-the-loop required; autonomous sessions must not resolve items carrying this.priority: mediumReal value, no hard deadline; normal backlog flow.work-class: structuralRefactors, migrations, contract changes; cross-cutting and hard to reverse.

    Type

    Fields

    No fields configured for Task.

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions