Skip to content

bp-136 — AP3: the halt list is a total predicate, and every unknown halts - #1

Open
ascalva wants to merge 2 commits into
mainfrom
worktree-agent-ab9c7248af96ebef3
Open

bp-136 — AP3: the halt list is a total predicate, and every unknown halts#1
ascalva wants to merge 2 commits into
mainfrom
worktree-agent-ab9c7248af96ebef3

Conversation

@ascalva

@ascalva ascalva commented Jul 28, 2026

Copy link
Copy Markdown
Owner

What this builds

bp-136 (AP3), against ratified dn-autopilot-and-delegated-blessing. A total classifier over a declared 16-key run state — every unknown halts rather than passing. Precedence H0→H6→H7→H3→H1→H2→H5→H4→H8.

scripts/autopilot_halt.py · tests/unit/test_autopilot_halt.py (150 tests) · .claude/skills/autopilot/SKILL.md

Acceptance — actually run, not claimed

  • uv run pytest tests/unit/test_autopilot_halt.py -q150 passed in 0.32s
  • uv run scripts/autopilot_halt.py classify against the real repo, three states: H7 (exit 1) → CONTINUE (exit 0) → H1: finding-0270 is not unambiguously builder-routed (exit 1). explain prints all codes (exit 0).

Green gate — five legs, run separately

ruff All checks passed! · scoped mypy no issues in 263 source files · argless mypy Found 69 errors — baseline exactly 69, unmoved · type_gate OK · pytest 6 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 ftype but route: orchestrator — so route: dominates, and the two fields disagree in ~25% of halting cases. Implementing oq-0047 will 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-resolved

Scope

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_record participates in no halt condition (finding-0273); no integration coverage against a real bp-135 audit record (none exists yet); oq-0047 not implemented (§9 non-goal 4).

Merge before the bp-137 PR — this branch owns finding-02710273.

ascalva and others added 2 commits July 27, 2026 19:38
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.
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