bp-136 — AP3: the halt list is a total predicate, and every unknown halts - #1
Open
ascalva wants to merge 2 commits into
Open
bp-136 — AP3: the halt list is a total predicate, and every unknown halts#1ascalva wants to merge 2 commits into
ascalva wants to merge 2 commits into
Conversation
dn-autopilot-and-delegated-blessing §2.6's H1-H8 become a total classifier over
an explicitly declared run state (bp-136 Items 9-13).
`scripts/autopilot_halt.py` — a pure decision function, `classify(state) -> Verdict`,
over the sixteen-key run-state document bp-136 §6 defines. Every absent, null,
ill-typed, extra, or unresolvable input returns HALT, not CONTINUE: invariant 7
("ambiguity always resolves toward halting") implemented as an H0 floor rather
than assumed. Precedence is the pinned H0->H6->H7->H3->H1->H2->H5->H4->H8.
Three things worth the reviewer's attention:
- EXIT 1 MEANS HALT, the safe outcome. The inversion is deliberate; a caller that
reads non-zero as "the tool broke" and proceeds has inverted the mechanism. The
`explain` subcommand exists so that inversion is one command from being caught.
- H8 is a HALT, and the module has no verdict code meaning "merge", "deskcheck" or
"done". Non-goals 5 and 6 are enforced by the ABSENCE of the vocabulary, asserted
at source level by an AST test over every Verdict construction.
- No grant validity is computed and nothing from bp-138 is imported. `grant_valid`
is data, which is what lets the halt list ship before the grant's cryptography.
The module has no writer at all, so "budget is not self-extendable" is structural.
`.claude/skills/autopilot/SKILL.md` — the supervisor's operating contract: the
classifier decides, the session acts. Carries the five halt actions verbatim, both
audit gates and their dissent semantics, and the six §1.2 non-goals. It LINKS the
graduate skill's session-sizing heuristic rather than restating it (a drifted copy
would route design-scale work into autopilot); a test pins the duplication at zero.
Falsifiers drilled, not asserted: the run state was hand-assembled from observable
facts and classified against the real repo (zero fields needed a guess); H1 was
measured against the real findings corpus and halts on 93% of the last 30 — the
rule was NOT softened, the number is filed as finding-0272 for an owner ruling; and
a three-mutant campaign on the load-bearing legs was caught 8/1/1.
Findings: finding-0271 (H1's pass set reconciled across the two disjoint ftype
vocabularies), finding-0272 (the 93% measurement -> orchestrator), finding-0273
(H2's intent-vs-mechanism layer is only half-determinable from bp-135 §6's schema;
conservative fallback applied and stated).
Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GTYQT2QsWskJW4HmgobyrV
finding-0271 (spec-fidelity, builder-resolved) — Item 10's two acceptance clauses are not literally consistent; H1's pass set is the builder lane named across BOTH live ftype vocabularies, gated on an explicit `route: builder`. Carried forward to whichever plan implements oq-0047 rather than re-derived there. finding-0272 (design -> orchestrator) — the conservative H1 reading was MEASURED against the real corpus: 28/30 recent findings (93%) and 199/243 overall (82%) would halt a run. Per §10 the rule was not softened on builder authority; the number is filed for an owner ruling. The load-bearing detail: 7 of the 28 carry a builder-lane ftype but `route: orchestrator`, so `route:` dominates and oq-0047's implementation will not move this number without a corpus sweep. finding-0273 (spec-fidelity, builder-resolved) — H2's intent-vs-mechanism split is HALF determinable: `gate: A|B` is the layer at the top level, but §2.5's "intent-level CONCERNS at Gate B" has no field. Conservative fallback applied and stated; two residual gaps named with a two-option re-entry condition. Journal carries the falsifier drills, the mutation campaign, the green-gate legs, and the stash-probe that established all six pytest failures are pre-existing.
ascalva
added a commit
that referenced
this pull request
Jul 28, 2026
…identity, and merge is not separable
Three measured facts defeat the obvious implementation of tonight's ruling.
The agent's credential IS the owner's, with repo admin: it can merge, force-push
main, and delete the branch protection meant to stop it. Merge is not a separable
permission — PUT /pulls/{n}/merge sits under Contents:write, the same permission
needed to push a branch, so a token that can push builder branches can merge them.
And the agent is indistinguishable from the owner (PR #1's author is ascalva),
which makes every identity-based rule vacuous: "require an approval" deadlocks
because you cannot approve your own PR, and "restrict merge to the owner" is no
restriction when the agent is the owner.
Remedy is a partition, not a stack — omit any one and a different leg fails:
separate identity (else approval deadlocks), ruleset on main (else merge stays
possible), scoped token without Administration (else the agent deletes the rule
binding it). Ordering matters and is easy to get backwards: install the ruleset
while the over-privileged credential still exists, swap the credential after.
Two escalations found while specifying it. Merge now triggers AWS deploy, so
merge capability is deploy capability — the gap ships to production rather than
merely landing code. And git operations use SSH, not the PAT, so scoping the
token constrains the REST API and NOTHING about a local merge plus `git push
origin main` — the exact act the rule forbids. The server-side ruleset is the
load-bearing control; the token only reduces blast radius.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this builds
bp-136(AP3), against ratifieddn-autopilot-and-delegated-blessing. A total classifier over a declared 16-key run state — every unknown halts rather than passing. PrecedenceH0→H6→H7→H3→H1→H2→H5→H4→H8.scripts/autopilot_halt.py·tests/unit/test_autopilot_halt.py(150 tests) ·.claude/skills/autopilot/SKILL.mdAcceptance — actually run, not claimed
uv run pytest tests/unit/test_autopilot_halt.py -q→ 150 passed in 0.32suv run scripts/autopilot_halt.py classifyagainst the real repo, three states:H7(exit 1) →CONTINUE(exit 0) →H1: finding-0270 is not unambiguously builder-routed(exit 1).explainprints all codes (exit 0).Green gate — five legs, run separately
ruff
All checks passed!· scoped mypyno issues in 263 source files· argless mypyFound 69 errors— baseline exactly 69, unmoved · type_gate OK · pytest6 failed, 2567 passed.The 6 were proved pre-existing:
git stash push -u, re-ran on the pristine tree, all 6 failed identically, restored.⚑ A falsifier fired, and the rule was NOT softened
Item 10's named falsifier — "H1 fires on essentially every run" — fires. Measured on the real corpus: 28/30 (93%) of recent findings would halt; 199/243 (82%) overall.
Per the plan's §10 the builder did not loosen the halt list to make autopilot usable. It recorded the number and routed the ruling to the owner as
finding-0272.Its honest reading: 93% is not automatically disqualifying, because the measured population is orchestrator/full-ceremony builds — precisely what §2.4 excludes from autopilot. What it does establish is the sharp form of §2.6's own claim: any autopilot run that files any finding halts.
⚑ 7 of the 28 carry a builder-lane
ftypebutroute: orchestrator— soroute:dominates, and the two fields disagree in ~25% of halting cases. Implementingoq-0047will not move this without a corpus sweep.Findings filed
finding-0272— design → needs an owner ruling (the 93% above)finding-0271,finding-0273— spec-fidelity, builder-resolvedScope
Seven files, all inside
write_scope+ own journal + new findings. Verified by the orchestrator against the plan's declared scope — with no hook enforcing it, since the hook layer was disabled by owner ruling the same evening.Reviewer notes
Cost: 184k by harness accounting, against a 200k estimate. (The builder self-reported ~370k; per the delegate skill, self-reports are not evidence — the harness figure is.)
Left undone, stated:
verdict_recordparticipates in no halt condition (finding-0273); no integration coverage against a real bp-135 audit record (none exists yet);oq-0047not implemented (§9 non-goal 4).Merge before the bp-137 PR — this branch owns
finding-0271–0273.