Skip to content

tooling(pm): H48 — a governed PR at ACCEPT that is missing its label or its maintainer brief - #15956

Merged
os-steve merged 2 commits into
mainfrom
claude/issue-15895-half-states-governed-pr-brief-row
Sep 5, 2026
Merged

tooling(pm): H48 — a governed PR at ACCEPT that is missing its label or its maintainer brief#15956
os-steve merged 2 commits into
mainfrom
claude/issue-15895-half-states-governed-pr-brief-row

Conversation

@claude

@claude claude Bot commented Sep 5, 2026

Copy link
Copy Markdown
Contributor

Fixes #15895

One new report-only row in scripts/pm/check-half-states.mjsH48, band state. One file; nothing else moves.

What the row reads

A seat's verdict on a governed-surface PR is a handoff, not a merge: Prime Directive 14 reserves the landing for the maintainer, so what a seat owes at ACCEPT is a complete handoff — and the rule that landed today makes that one act with two writes. The needs-user-decision label puts the PR in the maintainer's review inbox; a ## 维护者速读 comment is what makes reading it a two-minute job rather than a diff review.

One act with two writes has exactly two ways to come apart, and this row is both of them:

state what a reader gets
verdict, no label accepted and unfindable — the inbox filter that lists what is waiting never lists it
verdict, no brief findable and unread — a governed diff with nothing saying what is being asked
verdict, neither ONE finding, naming both halves and both remedies

No verdict at all is CLEAN, deliberately: a governed PR no seat has accepted yet is not the maintainer's, and nothing here asks anyone to hurry a verdict.

The ## 维护者速读(草稿) section a dev may carry in the PR body never satisfies the brief half — the draft is written before the review happened, while the brief is the seat's own word after it. The row reads comment threads and nothing else, and says so in its own sentence where a reader would otherwise assume a bug.

Population, and the fetch class it declares

Population is the open PRs the sweep already lists from /pulls, narrowed by the imported governedPathsIn matcher over the changed-file pages H36 already fetched — never a hand list of paths, and never a third matcher beside the one the queue guard enforces. A draft is IN (a governed draft is the correct terminal state of that regime and still half a handoff); merged and closed are out (the handoff is over and nothing here is fixable after it).

The verdict and the brief both live on the PR's issue-comment thread, and that is a genuinely new fetch class: commentCache holds CARD threads only — every listing feeding it filters !i.pull_request, which is the same fact H44's clause states from the other side. So it is declared exactly as H36 and H43 declare theirs:

GET /repos/{owner}/{repo}/issues/{pr}/comments?per_page=100   (paged, ceiling 5)

bought one thread per governed open PR — 10 of 33 on the board this landed against, one page each — and cached in prCommentCache so a future PR-comment reader pays nothing for a thread this row already bought. A thread that failed, or was still full at the page ceiling, is UNJUDGED rather than short: a partial read can only invent a missing half, never miss one, and #4690's rule is that an input which could not be read must never render as one that was clean.

Two bounds ride in the summary clause rather than in a comment nobody reads: a PR whose changed-file page went unread is not in this population at all, and a register that will not load (a sibling-repo install carries no governed pair) puts the whole row at NOT MEASURED, as H43 already does.

Markers

ACCEPT_VERDICT_MARKER and MAINTAINER_BRIEF_MARKER mirror CLAIM_COMMENT_MARKER / RELEASE_COMMENT_MARKER in three properties — line-anchored with the m flag, an optional leading blockquote, and no g flag — and deliberately not in the fourth. There is no i flag, for the reason RELEASE_COMMENT_MARKER states in its own docblock: a rule that landed with no dialect behind it starts at the canonical spelling and nothing wider, so an unbolded ACCEPT, a lowercase **Accept**, **ACCEPTED** (a word about a different act) and a ### sub-heading are malformed writes rather than unrecognised dialects. Each of those is pinned as a case.

Evidence

Union re-run on the final tree, at ea5b4f3912.

  • node scripts/pm/check-half-states.mjs --self-test2341 → 2414 cases, 0 failures. The two case-name sets were diffed: 73 added, 0 dropped.
  • node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack derives 32 families for this file list; all 32 run, all exit 0; --ran reconciles: ✓ dispatch-gates --ran: 32 derived famil(ies) accounted for — 32 run, 0 NOT-MEASURED.
  • node scripts/pm/check-governed-merges.mjs --test scripts/pm/check-half-states.mjs → exit 0, ✅ NOT governed.
  • Whole-repo pnpm lint through scripts/pm/os-verify-lock.sh (slot issue-15895): VERDICT command-exit 0.
  • The self-tests of every script that imports or pins this file also run green: check-clause2-carriers, ci-failure, check-governed-merges, dispatch-gates, check-test-completeness, check-partof-closing-keyword.

Ablation — three legs, each restored and proved by blob hash

Every leg asserts the tree is at the HEAD blob before mutating, proves the mutation landed by counting the anchor text it meant to change in both directions, then restores with git checkout HEAD -- PATH and proves the restore by blob-hash equality and an empty git diff HEAD.

leg mutation expected observed
A the predicate always declines every firing case red 19 red, all of them H48 firing cases; no clean-direction case moved
B the findings.push removed registry-coverage red 3 redemitted.includes('H48'), and the registry invariant from both sides (no band names a family the sweep never emits)
C the summary clause deleted the generic summary invariants red 11 red — anchor uniqueness, declared-order-is-rendered-order, the per-window PRESENT control, and every H48 clause case

Restore proof, identical on all three legs: RESTORED_BLOB=ea5a25afd032d963db10b3c50d3285487ddbb2d1 = the HEAD blob, git diff HEAD --quiet exit 0. There is no build leg: this script is run directly from source by node, with no dist/ on the resolution path.

Live sweeps, read-only, before and after

repo before after H48 rows
objectstack-ai/objectstack 297 findings 295 findings 0Maintainer briefs (H48): 11 of 11 governed open PRs judged
objectstack-ai/objectui 170 findings 166 findings 0Maintainer briefs (H48): 1 of 1 governed open PRs judged

The other families move a little between the two runs because the live board moved (two governed PRs merged mid-session); no family's movement is attributable to this diff, which adds one row and touches no other predicate.

The zero is a measured zero, not a quiet one. Reading the ten governed open PRs in the population one by one, with the shipped predicate over their real comment threads:

Deliberately left out

Whether a governed PR carrying needs-user-decision with no verdict behind it is itself a half-state — the 代读 shape, live on two PRs today — is not this card, and it is not implemented here. It looks worth a card to me: the label is a claim on the maintainer's attention, and one placed without a seat verdict behind it is a different assertion from the one this row patrols. Filing it is the PM's call, not a fix to smuggle into this diff.

skip-changeset: this file publishes nothing from any package.


Generated by Claude Code

…r its 维护者速读 brief

The seat's verdict on a governed PR is a HANDOFF, not a merge, and the handoff
is one act with two writes: `needs-user-decision` puts the PR in the
maintainer's review inbox, and a `## 维护者速读` comment makes reading it a
two-minute job. One act with two writes has exactly two ways to come apart, and
this report-only row is both of them — accepted and unfindable, or findable and
unread.

Population is the open PRs the sweep already lists, narrowed by the imported
`governedPathsIn` matcher over the changed-file pages H36 already fetched —
never a hand list of paths. Drafts are IN (a governed draft is the correct
terminal state of that regime and still half a handoff); merged and closed are
out. A governed PR with no verdict is CLEAN: it is not the maintainer's yet.

The brief and the verdict are read from the PR's own issue-comment thread, and
that is a NEW fetch class: `commentCache` holds card threads only (every
listing feeding it filters `!i.pull_request`). It is declared as H36 and H43
declare theirs, bought one thread per GOVERNED OPEN PR — 11 of 31 on the board
this landed against — and cached so a future PR-comment reader pays nothing. A
thread that failed or reached the page ceiling is UNJUDGED rather than short: a
partial read can only invent a missing half.

The `## 维护者速读(草稿)` section in a PR BODY is the dev's draft, written
before the review happened, and never satisfies the brief half — the row reads
comments only and says so in its own sentence.

Markers mirror `CLAIM_COMMENT_MARKER`/`RELEASE_COMMENT_MARKER` in three
properties (line-anchored `m`, optional leading blockquote, no `g`) and
deliberately not in the fourth: no `i` flag, for the reason
`RELEASE_COMMENT_MARKER` states — a rule that landed with no dialect behind it
starts at the canonical spelling and nothing wider.

Self-test 2341 -> 2414 cases, none dropped.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019RfFHiRCSs3JXLK4cwcfox
@github-actions github-actions Bot added the size/m label Sep 5, 2026
@claude claude Bot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Sep 5, 2026

os-steve commented Sep 5, 2026

Copy link
Copy Markdown
Collaborator

ACCEPT — lands #15895 as ruled. Pure code (one file under scripts/pm/, governed-surface predicate exit 0), so ready + SQUASH auto-merge follow in this same act.

What the seat verified, at head ea5b4f3912, in its own compare worktree

  • One file, +415/−0. H48 is report-only, band state, and speaks only about governed OPEN PRs — governed by the imported governedPathsIn matcher over the changed-file pages the loop already holds, never a hand list; drafts in, merged and closed out.
  • The three readings are the ruled ones: ACCEPT_VERDICT_MARKER (line-anchored **ACCEPT**, optional leading blockquote, deliberately no case-folding — stricter than the claim marker, and rightly so), MAINTAINER_BRIEF_MARKER (## 维护者速读 at line start), the label on the PR. Fires on verdict ∧ (¬label ∨ ¬brief), names the missing half with its remedy; no verdict ⇒ clean.
  • The new fetch class is declared where the others are (one paged issue-comment thread per governed open PR, prCommentCache, a five-page ceiling that reports UNREADABLE rather than clean), and the summary clause says so in words. CLAIM_COMMENT_MARKER and RELEASE_COMMENT_MARKER are referenced in comments only, not modified.
  • Self-test: 2414 cases green in the seat's own run (2341 on the merge base); the dev's name-set diff reads +73/−0.
  • Ablation legs A/B/C as the dev states them, each proved on disk and restored by blob hash; live sweeps read 0 H48 rows with "11 of 11 governed open PRs judged" on objectstack and "1 of 1" on objectui — and the zero is measured, not quiet: the two complete handoffs (PR agents(os-dev): measured PR-body footer reading and the dev-draft half of the maintainer brief #15923, PR fix(hooks): a linked worktree is one whose git-dir differs from its git-common-dir #15924) read all three and pass, and a synthetic ACCEPT on any of the six verdict-less governed drafts makes the row fire.
  • CI, seat's read 16:3xZ: 35 check runs, 24 success, 11 skipped, none failing, none pending; Live half-state sweep green on the modified file.
  • Body line 1 Fixes #15895; skip-changeset present.

The out-of-scope item, declined as a card: a governed PR carrying needs-user-decision and a 速读 with no seat verdict behind it is the 代读 shape the seat placed on purpose on other lanes' PRs already approved and awaiting the maintainer — the label's PR meaning is "awaiting the maintainer's review", which those PRs are; a verdict from a seat that did not review them is not owed. If that shape ever appears without a 速读, H48's sibling would be the row; today nothing on either board has it.

Next: #15899 (same file) dispatches when this lands.

Implemented-by: os-dev executor, flight #15895, branch claude/issue-15895-half-states-governed-pr-brief-row
Reviewed-by: pm-dispatch skills seat, https://claude.ai/code/session_019RfFHiRCSs3JXLK4cwcfox


Generated by Claude Code

@os-steve
os-steve marked this pull request as ready for review September 5, 2026 16:35
@os-steve
os-steve enabled auto-merge September 5, 2026 16:35
@os-steve
os-steve added this pull request to the merge queue Sep 5, 2026
Merged via the queue into main with commit aa6ba06 Sep 5, 2026
37 checks passed
@os-steve
os-steve deleted the claude/issue-15895-half-states-governed-pr-brief-row branch September 5, 2026 17:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/m skip-changeset PR has no user-facing published change; bypasses the changeset gate

Projects

None yet

2 participants