Skip to content

docs: regen inventory blocks - #1623

Closed
github-actions[bot] wants to merge 1 commit into
mainfrom
docs/auto-regen-inventory
Closed

docs: regen inventory blocks#1623
github-actions[bot] wants to merge 1 commit into
mainfrom
docs/auto-regen-inventory

Conversation

@github-actions

Copy link
Copy Markdown
Contributor

Auto-generated inventory update

Triggered by a push to main that touched a source of truth
for the inventory blocks in memory/glossary.md and
memory/projects/golfhelm.md.

What changed: the auto-regenerated sections between
<!-- AUTOGEN:* --> markers. Hand-curated narrative outside
those markers is preserved.

What to do: review the diff. If it looks sane, squash-merge.
If something looks wrong, the script lives at
scripts/regen-docs.mjs.

See .github/workflows/docs-regen.yml and the
"Auto-regen inventory docs" section of CLAUDE.md.

🤖 Generated by GitHub Actions

@github-actions github-actions Bot added automated docs Documentation labels Aug 26, 2026
@vercel

vercel Bot commented Aug 26, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
helmv3 Ignored Ignored Preview Aug 28, 2026 11:44pm

Request Review

@supabase

supabase Bot commented Aug 26, 2026

Copy link
Copy Markdown

This pull request has been ignored for the connected project qmnssrrolpinvwjjnufo because there are no changes detected in supabase directory. You can change this behaviour in Project Integrations Settings ↗︎.


Preview Branches by Supabase.
Learn more about Supabase Branching ↗︎.

@github-actions
github-actions Bot force-pushed the docs/auto-regen-inventory branch 9 times, most recently from e69d35f to b71dbca Compare August 28, 2026 22:36
Auto-generated by .github/workflows/docs-regen.yml.
Sources: src/lib/types/database.ts, src/app/**/page.tsx,
src/app/**/actions/**/*.ts, src/hooks/**/*.ts.
@github-actions
github-actions Bot force-pushed the docs/auto-regen-inventory branch from b71dbca to df16b1f Compare August 28, 2026 23:43
njrini99-code added a commit that referenced this pull request Aug 29, 2026
)

Two days of repairs left the pieces better and unable to check each other. This
makes drift observable, so the next forensic pass is a command instead of a
week.

THE PATTERN, STATED ONCE

    control written -> documented -> assumed -> stops running -> docs remain
    -> agent trusts docs -> failure

Observed, all of it:

    guard-bash.sh        existed, unwired, deleted
    guard-sql.sh         existed, unwired, deleted
    retire-worktrees.sh  existed, never invoked
    four rule files      claimed hooks that were gone
    worktree GC          keyed on a ref GitHub deletes on merge
    Docs Regen           opened a PR that sat open while main went stale
    a fixture test       operated on the real repository

Not one was a missing control. Every one was a control that stopped running
while its documentation stayed put.

WHAT THIS ADDS

npm run control-plane:verify           static + runtime
npm run control-plane:verify:static    CI-safe, wired as its own required job

READ-ONLY by construction. It regenerates nothing, deletes nothing, mutates no
config. The previous docs gate re-ran the generator and diffed, so the only way
to learn the docs were stale was to have already fixed them — a verifier that
repairs what it inspects cannot tell you what was wrong.

    0  VERIFIED           passed, or a named acknowledged gap
    1  CONTROL FAILURE    a control that should hold does not
    2  UNKNOWN            a required state could not be established

UNKNOWN outranks FAIL and never becomes PASS. If something could not be
established, "these specific things are broken" would imply everything else was
checked.

ACKNOWLEDGED GAP != UNKNOWN. Four gaps carry an id, an owner, a date, a reason
and a closing condition in config/control-plane-gaps.json, and every run prints
them so they cannot fade.

MUTATION BUDGET, ENFORCED BEFORE ALLOCATION

HELM_MAX_MUTATION_WORKTREES defaults to 1. Refused before `git worktree add`
and before any install, so a refusal costs nothing. Classification FAILS TOWARD
MUTATION: an unreadable or undeclared workspace counts. A declared release
workspace escapes the budget only if it is ALSO detached — on a branch it can
still be committed to.

The disk reserve stopped a catastrophe; it never stopped waste. Six worktrees in
one day was a concurrency problem that only became visible as a disk problem.

BRANCH-GC AUTHORIZATION, RECORDED IN THE TOOL ITSELF

Verdict renamed DELETE_SAFE -> DELETE_MERGED_EXACT so it states its own
evidence, and the grant lives in the authority, not in a paragraph elsewhere:

    PR MERGED + local tip === PR head OID + not protected + not checked out

Nine verdicts are explicitly excluded. The sharpest is new:
NO_UPSTREAM_UNIQUE_WORK. Measured — ten branches hold up to 19 commits with no
upstream, existing nowhere else. Folding those into UNKNOWN_PR conflated "the
lookup failed" with "this is the only copy", and only one of those is permanent.

THE GATE-LIE FROM #1672, ACTUALLY CLOSED

#1672 raised the timeout and its own PR said that makes the unknown RARER, not
DISTINGUISHABLE. The eleven repo sweeps now run in a dedicated `guards` project
under scripts/repo-guards.mjs:

    PASS                    ran, found nothing
    POLICY_FAILURE          ran, found violations        exit 1
    INFRASTRUCTURE_FAILURE  did not finish — UNKNOWN     exit 2

Proven end to end by injecting a real 200s hang into a real guard: exit 2, never
reported as a violation.

The guards are UNTOUCHED. They are 116-357 lines of bespoke matching logic each;
rewriting them to fix a REPORTING defect would risk weakening the guards
themselves. The lie was at the reporting boundary and is fixed there.

Worth recording: vitest's JSON reporter does not carry the timeout text — a real
timeout arrives as `Error: STACK_TRACE_ERROR`. A first draft scraped the
human-readable stream to recover it. That did not match, and it was the wrong
idea: parsing a tool's console output to make a safety decision is the
brittle-regex pattern this repo has already deleted guards for. The guarantee is
the DEFAULT — an unrecognised failure is INFRASTRUCTURE_FAILURE — not a pattern.

TOOL AUTHORITY, AND EVIDENCE THAT EXPIRES

docs/TOOL_AUTHORITY_MATRIX.md, generated. Five words that are not synonyms:
CONFIGURED, CONNECTED, EXPOSED, ALLOWED, EXERCISED. ET-4 lost two days reading
the first as the last.

Probed live, not inferred:

    Sentry   BOTH namespaces connected, find_organizations byte-identical.
             Redundant -> mcp__claude_ai_Sentry__* is authority, plugin denied.
             Reversible: one deny line restores it.
    Vercel   plugin exposes ONLY authenticate -> CONFIGURED, not CONNECTED.
             Account connector is authority; dead namespace denied.
    GitHub   the gh CLI is the lifecycle path, exercised three ways: MERGED
             #1676, OPEN #1659, and a branch with no PR. A failed lookup stays
             UNKNOWN_PR (#1668).
    Supabase sanctioned mcp__supabase__* is installed but NOT connected.

Every observation carries a fingerprint of the configuration that produced it.
Change a deny rule and the matching EXERCISED claims become STALE on the next
regeneration. Nobody has to remember to invalidate them.

Two bugs found by running it: Sentry and GitHub produced an IDENTICAL
fingerprint (both slices empty), which would have made drift undetectable for
both; and a service governed by nothing now says `ungoverned` rather than
implying coverage it does not have.

SUPABASE — A STRUCTURAL FINDING

Starting the sanctioned server's OAuth flow shows its requested scopes:

    organizations:read projects:read database:read analytics:read
    secrets:read edge_functions:read environment:read storage:read

Every scope is :read. That is connector-enforced capability restriction — real
evidence, not a URL string, and obtainable without any write probe.

It also means mcp__supabase__apply_migration almost certainly CANNOT function
under this grant, while an explicit owner authorization says it may. Surfaced as
gap SUPABASE_MIGRATION_GRANT_VS_READ_SCOPES rather than resolved, because
resolving it means attempting a production migration to answer a documentation
question.

USER-GLOBAL, UNDER EXPLICIT AUTHORIZATION AND WITH A BACKUP

    removed  mcp__plugin_supabase_supabase__{execute_sql,apply_migration}
             — no such plugin is installed; a grant waiting to activate on
               install is a trap, not a capability
    removed  mcp__claude_ai_Supabase__apply_migration
             — account-WIDE mutation nobody authorized
    kept     mcp__supabase__apply_migration — the owner's explicit grant
    kept     mcp__claude_ai_Supabase__execute_sql as TEMPORARY_FALLBACK, named
             UNENFORCED, because it is the only working query path until the
             sanctioned one connects
    fixed    the autoMode prose claiming a PreToolUse hook blocks destructive
             SQL. It never did; it had been copied from this repo's own docs.

SANDBOX — MEASURED, NOT ASSUMED, AND NOT ENABLED

Ten disposable probes: writes inside the project, outside it, into
.claude/settings.json and .claude/hooks, reads of .env.local, and ../ traversal
ALL SUCCEEDED — including paths the config lists under denyRead and
denyWithinAllow. sandbox.filesystem.disabled is true and authoritative. Network
sandboxing IS enforced (observed: deny network-outbound analytics.brew.sh:443).

NOT enabled. The configured allowWrite covers /private/tmp/helmv3-*, ~/.npm and
~/Library/Caches/deno — not the repository — so flipping it as configured would
block every worktree write, user-globally, for every project and any concurrent
session. Recorded as gap SANDBOX_FILESYSTEM_DISABLED with the closing condition.
No fake Bash parser was added as compensation.

DOCS REGEN — created != integrated

#1623 existed because main carried a stale route count (234 vs 235, after
/admin/self-heal shipped) and the fix lived in a bot PR that nothing merged.
That workflow's own header recorded that GITHUB_TOKEN PRs may receive no
required CI, so it could not be merged confidently either.

regen-docs.mjs gains a genuinely NON-MUTATING --check that computes expected
blocks, diffs them, names the first differing line, and leaves the tree
byte-identical. It is now a required PR-time gate. The auto-PR workflow is
verification-only and creates nothing. #1623's diff is byte-for-byte what
regeneration produces here, so it closes as superseded.

FAILURE INJECTION — 15 cases, every one in a disposable COPY

    delete a configured hook                      -> FAIL
    point a hook at a nonexistent script          -> FAIL
    break the blocking hook's matcher             -> FAIL
    reintroduce a false safety claim              -> FAIL
    the same claim, QUOTED                        -> PASS (corrections stay writable)
    declare a namespace never observed            -> FAIL
    move the budget check after allocation        -> FAIL
    remove the budget check                       -> FAIL
    change a service's config                     -> its observations STALE
    change one service                            -> others NOT staled
    a service governed by nothing                 -> ungoverned, not fresh
    inject a real 200s guard hang                 -> INFRASTRUCTURE_FAILURE, exit 2
    inject a real banned import                   -> POLICY_FAILURE, exit 1

Plus a SENTINEL proving the injections cannot reach the live checkout. That is
the direct regression for #1676, where a fixture test resolved its target back
to the real repository and parked a live worktree.

THREE THINGS THE VERIFIER CAUGHT IN ITS OWN AUTHORS' WORK

  1. It reported mutation-budget-enforced FAIL against a correctly-ordered
     script, because indexOf matched `git worktree add` in the script's own HELP
     TEXT at line 15. Substring is not mechanism — the same error the
     enforcement generator made on its first run. Now line-based and
     comment-aware.
  2. The matrix rendered the whole Supabase namespace as DENIED when only its
     ten mutators are, and folded DENIED_BY_POLICY and NOT_EXERCISED into
     "FAILED" — which reads as "we tried and it broke", untrue of both.
  3. #1672's own test asserted `unit` must be no stricter than its siblings,
     because `unit` held the sweeps. They moved. The failure was the premise
     announcing itself, and the test now pins the invariant that survives:
     whichever project runs the sweeps must be the most generous.

DELIBERATELY NOT DONE

No UNKNOWN or no-upstream branch deleted. No production SQL write as a probe. No
regex Bash/SQL pseudo-guard. #1638 not merged. sandbox.filesystem not enabled.
The Repair LaunchAgent not re-armed — a green control plane is not evidence
about a different unresolved runtime problem.

Verified: npm run preflight 0; npm test 1265 files / 12049 passed;
control-plane:verify 0 (20 pass, 0 fail, 0 unknown, 1 acknowledged gap);
control-plane:verify:static 0; enforcement:check 0; docs:inventory-check 0;
tool-authority:check 0; guards 32/32; check:cycles 0; shellcheck 0;
repo:doctor 0.


Claude-Session: https://claude.ai/code/session_01NbDxyygyXRUEERuGocpZZH

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
@njrini99-code

Copy link
Copy Markdown
Owner

Superseded by #1677.

Your diff was 234 routes -> 235 routes in memory/projects/golfhelm.md. #1677 contains byte-for-byte the same regeneration, committed alongside the source change rather than in a follow-up PR.

The architecture that created you is gone: generated-inventory drift is now a REQUIRED PR-time check (npm run docs:inventory-check, non-mutating), and the Docs Regen workflow is verification-only and creates nothing. A correction that lives in an unmerged PR is not a correction — this one sat open while main carried the stale count.

njrini99-code added a commit that referenced this pull request Aug 30, 2026
…lsof's silence (#1683)

* fix(lifecycle): an OPEN PR's checkout needs its owner's consent, not lsof's silence

Reproduced 2026-08-30: `npm run worktrees:retire` removed a concurrent
session's checkout (agent/round-type-reclassify, PR #1681, OPEN). Every
mechanical signal said disposable — clean, tip identical to its pushed
remote, and no process whose cwd `lsof` could see. Nothing was lost, because
parking is defined to keep the branch and PARKABLE already required the tip
to match its remote. But the checkout had an owner and the tool could not
tell, so this is a classifier defect, not a slip.

The unsound step is reading silence as absence. `lsof +D` samples one
instant:

    hasLiveProcess === true    proof of activity        — a sound veto
    hasLiveProcess === false   NOT proof of inactivity  — an agent session
                               between two tool calls has no visible cwd

classifyWorktree's own header stated the defect as design — "parking does
NOT consult the PR at all" — so the comment is rewritten in the same commit.
A file whose prose contradicts its code is the failure this program exists
to remove.

WHAT CHANGED

New worktree verdict KEEP_PR_OWNER_INTENT_REQUIRED, deliberately neither
ACTIVE (nothing proved anyone is using it) nor UNKNOWN (the PR read fine;
what is missing is a decision). It is in REQUIRES_HUMAN_VERDICTS, so the
standing authorization already excludes it.

config/open-pr-dispositions.json gains `worktree_policy`, because the
disposition LABEL was being asked to imply an ACTION readers had to infer:

    KEEP                  never parked automatically
    PARK_IF_REPRODUCIBLE  park once clean and pushed; the branch stays

A missing row, an unrecognised policy, or a disposition of ACTIVE/UNKNOWN
all KEEP. #1659 — an open PR waiting on a physical-device test — is released
explicitly by its owner and stays parkable, which is the case the park/retire
split exists for.

The registry is now current state in BOTH directions. It carried ACTIVE rows
for #1623, #1638, #1679 and #1680 after they closed or merged; control-plane
-verify now fails on a stale row as well as a missing one, and on a
worktree_policy outside the vocabulary. That vocabulary check lives in the
verifier because the lifecycle tool must fail SAFE on a malformed entry
(unrecognised policy => KEEP) and would therefore never report one.

#1681's row is recorded ACTIVE/KEEP, transcribed from observable state — PR
OPEN, worktree checked out — by this session and not by its owner, who
should confirm it. Recorded rather than left blank because leaving it blank
is exactly what let --retire park it.

WHAT THIS DOES NOT COVER

A worktree whose branch has NO PR is still parked on reproducibility alone —
the same defect class, with no PR to key a disposition on. Requiring recorded
intent for every branch would make --park unable to act at all, which defeats
the reason parking exists. Registered as WORKTREE_PARK_NO_PR_OWNERSHIP rather
than quietly accepted.

VERIFIED

preflight 0 · 1269 files / 12,101 tests 0 · docs:check 0 · knowledge:check 0
· markdown ratchet 30515, unchanged · control-plane:verify VERIFIED exit 0
(was CONTROL FAILURE on open-pr-residue) · lifecycle suite 60 passed.

Failure injection: disabling the ownership gate turns 8 of them red,
including the end-to-end CLI case where --park refuses a fixture worktree
whose PR is OPEN with no disposition. The lib was restored from a hashed
backup and re-verified byte-identical.

Assumption stated once: this ran in the canonical checkout rather than a
worktree. HELM_MAX_MUTATION_WORKTREES=1 and the other session holds the only
mutation workspace, so new-worktree.sh refuses by design; AGENTS.md permits a
single session in canonical, and the concurrency hazard the worktree rule
addresses does not apply because the other session is isolated in its own.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NbDxyygyXRUEERuGocpZZH

* chore(dispositions): record this PR's own row — the new rule's first cost

Opening #1683 made control-plane:verify red on open-pr-residue immediately,
because the key set must now equal the live open-PR set exactly. That is the
chosen tradeoff, not a surprise: a PR number does not exist until the PR does,
so the row can only ever land in a follow-up commit.

KEEP rather than PARK_IF_REPRODUCIBLE: this work runs in the canonical
checkout, which classifyWorktree holds ACTIVE before consulting anything else.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NbDxyygyXRUEERuGocpZZH

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
njrini99-code added a commit that referenced this pull request Aug 30, 2026
The registry is CURRENT STATE, so a merge makes its own row stale — this is the
two-ended cost ADR-2026-08-30 records, paid on schedule. control-plane:verify
reported it as a CONTROL FAILURE the moment #1687 merged (open-pr-residue:
"disposition rows for PRs no longer open: #1687"), which is the check working:
a current-state registry that only failed on MISSING rows would have carried an
ACTIVE row for a merged PR indefinitely, exactly as this file did for #1623,
#1638, #1679 and #1680 before this run.

After: 3 open PRs (#1659, #1678, #1681), all owned elsewhere, all classified.
control-plane:verify VERIFIED, exit 0 — 21 pass, 0 fail, 0 unknown.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NbDxyygyXRUEERuGocpZZH
njrini99-code added a commit that referenced this pull request Aug 30, 2026
…e merge

Found by running the acceptance test for the first half. After merging, a row
whose PR has landed is stale until someone pushes — fixed by exact merge
identity. BEFORE merging, the mirror image: a row that lives in its own PR is
absent from main for the PR's entire flight, so `open PRs with no recorded
disposition` fails main from the moment such a PR opens.

Observed directly: with #1688 open, control-plane:verify from canonical reported
CONTROL FAILURE — "open PRs with no recorded disposition: 1688". Adding the row
in an EARLIER PR only moves the problem one PR back; pushing it straight to main
is the bypass this whole change exists to remove. Both exits were closed on one
side and open on the other.

Second exception, proved the same way — by identity, not assumption:

    the row is absent from the verified checkout
    AND it IS present in config/open-pr-dispositions.json at that PR's OWN head
         -> IN FLIGHT, not unclassified

Absent at the head, or unreadable there, still FAILS. That is the line between
"arriving" and "missing", and it is the same line as everywhere else in this
check: #1623 sat open for weeks with no row anywhere and must stay caught.

Verified against the live PR rather than only in fixtures: deleting #1688's row
from the working tree while the PR head still carried it produced

    PASS  4 open PR(s) ... | in flight (row present at the PR's own head): #1688

and restoring it returned the file byte-identical. Injection: treating an
unproven row as in-flight turns two tests red, and the script restored
byte-identical (sha256). preflight 0, 45 tests in this file, verifier VERIFIED.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NbDxyygyXRUEERuGocpZZH
njrini99-code added a commit that referenced this pull request Aug 30, 2026
…hes (#1688)

* fix(control-plane): close the two routes that produced the direct pushes

Two unreviewed commits reached main on 2026-08-30. Neither was a lapse of
judgement in isolation — each was the only exit from a control that had no
other one. Both exits are now closed.

1. THE DISPOSITION CLOSING TRAP

A PR that carries its own open-pr-dispositions row makes main fail
`open-pr-residue` the instant it merges: the row is now stale by the file's own
current-state rule. The only ways out were a second PR — which needs its own
row, so the same thing happens again — or a direct push. A control whose only
escape is bypassing another control is a defect in the first one.

The exception is the narrowest thing that closes it:

    row's PR is no longer OPEN
    AND GitHub says MERGED
    AND merge_commit_sha === the verified checkout's HEAD
         -> TRANSITIONALLY CLOSED

Exact merge IDENTITY, never "merged recently"/"today"/"within N commits" — those
widen silently as history grows. This one narrows on its own: one more commit on
main and HEAD moves, so the row fails again. It survives its own merge and
nothing more; the next ordinary PR clears it while adding its own row. A
transitional row is named in the check's output, so nobody has to remember it.

Every other stale shape still fails, including the ones where the evidence for
the exception is missing: closed-but-unmerged, unreadable merge state, MERGED
with no merge commit, unreadable local HEAD, and any second stale row. Refusing
a RELAXATION on unproven evidence is the safe direction — distinct from the
open-PR LISTING failing, which stays UNKNOWN, because there we cannot establish
what is open at all.

2. THE STANDING ADMIN BYPASS

New runtime check `github/main-branch-protection`. main is protected and
requires six contexts, but enforce_admins is off, so ordinary agent credentials
push straight past both the PR requirement and the checks.

It reads BOTH mechanisms. Classic protection reports enforce_admins; repository
RULESETS are a separate system with their own bypass_actors and report on
/rulesets. This repo has classic protection and zero rulesets today — but the
bypass message GitHub printed is ruleset wording, and a check reading only the
first endpoint would report PASS against a bypass reinstated in the second. That
is the difference between a real check and a decorative one.

It cannot fix itself, by design: branch protection is repository SETTINGS, and
an agent credential able to relax its own gate is not a gate. So the condition
is registered as MAIN_ADMIN_BYPASS_AVAILABLE and reported as ACKNOWLEDGED_GAP —
and a known condition is a gap only while it is REGISTERED. Bypass present with
no gap entry is a FAIL, never a quiet excuse.

3. THE GAP COUNT WAS COUNTING THE WRONG THING

The final line printed the number of CHECKS returning ACKNOWLEDGED_GAP (1)
labelled as the acknowledged-gap count, against five registered gaps. Four
owned, dated, closing-condition-bearing gaps were invisible on the one line
anybody reads. summarise() now exposes registered_gap_count and
gap_state_check_count separately, in text and in --json. Exit precedence is
untouched: gaps never move it, UNKNOWN still outranks FAIL.

VERIFIED — 21 pass, 0 fail, 0 unknown
REGISTERED OPEN GAPS — 6   (checks reporting GAP state this run: 2)

Verified: three failure injections, each red for its own reason — unwiring the
new check, replacing exact merge identity with "always true", and ignoring
rulesets — and the script restored byte-identical (sha256 checked). preflight 0,
202 tests across src/test/scripts, docs:check 0, knowledge:check 0, ratchet
unchanged. `gh` is stubbed in the wiring tests, so no test reaches GitHub.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NbDxyygyXRUEERuGocpZZH

* chore(control-plane): record #1688's own disposition row

The row this PR's exception exists to let survive its own merge. After it
merges, main HEAD === #1688's merge commit, so open-pr-residue reports it
TRANSITIONALLY CLOSED instead of failing — which is the acceptance test for the
defect, run from canonical without touching this file.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NbDxyygyXRUEERuGocpZZH

* fix(control-plane): the disposition trap has a second half, before the merge

Found by running the acceptance test for the first half. After merging, a row
whose PR has landed is stale until someone pushes — fixed by exact merge
identity. BEFORE merging, the mirror image: a row that lives in its own PR is
absent from main for the PR's entire flight, so `open PRs with no recorded
disposition` fails main from the moment such a PR opens.

Observed directly: with #1688 open, control-plane:verify from canonical reported
CONTROL FAILURE — "open PRs with no recorded disposition: 1688". Adding the row
in an EARLIER PR only moves the problem one PR back; pushing it straight to main
is the bypass this whole change exists to remove. Both exits were closed on one
side and open on the other.

Second exception, proved the same way — by identity, not assumption:

    the row is absent from the verified checkout
    AND it IS present in config/open-pr-dispositions.json at that PR's OWN head
         -> IN FLIGHT, not unclassified

Absent at the head, or unreadable there, still FAILS. That is the line between
"arriving" and "missing", and it is the same line as everywhere else in this
check: #1623 sat open for weeks with no row anywhere and must stay caught.

Verified against the live PR rather than only in fixtures: deleting #1688's row
from the working tree while the PR head still carried it produced

    PASS  4 open PR(s) ... | in flight (row present at the PR's own head): #1688

and restoring it returned the file byte-identical. Injection: treating an
unproven row as in-flight turns two tests red, and the script restored
byte-identical (sha256). preflight 0, 45 tests in this file, verifier VERIFIED.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NbDxyygyXRUEERuGocpZZH

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

automated docs Documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant