Skip to content

tooling(pm): the claim-side readers — a bulleted Branch: governs, and a Refs-only landing is not H8's full delivery - #16202

Draft
claude[bot] wants to merge 2 commits into
mainfrom
claude/issue-16036-claim-readers
Draft

tooling(pm): the claim-side readers — a bulleted Branch: governs, and a Refs-only landing is not H8's full delivery#16202
claude[bot] wants to merge 2 commits into
mainfrom
claude/issue-16036-claim-readers

Conversation

@claude

@claude claude Bot commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

Fixes #16036
Fixes #16170
Fixes #16037

One file, scripts/pm/check-half-states.mjs. No new rows; the family markers are untouched.

#16170 — a bulleted Branch: line governs again

claimedBranches now admits an optional markdown list marker before the directive:

^\s*(?:[-*+]\s+)?>?\s*Branch(?:es)?\s*:

Measured live on #15511, whose claim comment is the malignant MIXED shape: an
undecorated Claim: line (so CLAIM_COMMENT_MARKER, which has no list marker
either, matched and the comment IS a claim) with the branch written as
- Branch: ... under it (so this reader returned nothing and the claim GOVERNED
nothing). The two anchors failed at different points on one comment, and nothing
in the artefact looked wrong.

The claim MARKER is deliberately NOT widened with it. When BOTH lines carry a
bullet the marker misses too, the comment is not a claim to any reader in this
file, and "no comment on the card's thread is a claim comment" is then the TRUE
reading — so only the mixed shape was malignant, and admitting the marker here is
what removes it. Widening Claim: itself is the 2026-08-11 ruling's territory
(不放宽谓词), not this reader's; the self-test pins the marker still false on a
bulleted Claim:.

The refusal message is NOT edited here, and the reason is reported rather than
acted on.
The sentence the card quotes — "no comment on the card's thread is a
claim comment" — lives in scripts/pm/check-clause2-carriers.mjs (the absent
limb of cardDeclaration), which this flight does not touch by ruling. Reading
that limb: it ALREADY distinguishes the two states the card asks for, and the
predicate that separates them is CLAIM_COMMENT_MARKER, not the branch parse —
missing says the claim comment is there and the declaration line is what is
owed, absent says no claim comment exists. On the measured #15511 shape
claimRows is non-empty, so that thread lands on missing, whose sentence is
accurate. See the report comment on #16170 for the full reading and the open
question it leaves.

#16036 — a Refs-only landing is not H8's full delivery

H8's MERGED side now reads a second, narrower predicate, prFullyDeliversCard:

export function prFullyDeliversCard(pr, n) {
  if (!prDeliversCard(pr, n)) return false;
  return refsOnlyLinksFor([pr], n).length === 0;
}

refsOnlyLinksFor is H49's own predicate, CALLED rather than restated, so what
H49 owns is exactly what H8 excludes and the two cannot drift into a gap or an
overlap.

The shared prDeliversCard relation is untouched, deliberately: H8's OPEN side,
H31's carrier comparison, claimDelivery and the pairing check-clause2-carriers
derives all want the wide "is there a PR on this card" reading, because a Refs
half still open is live work. Narrowing the shared relation would make that half
invisible to the rows that exist to see it — the #10468 harm, run backwards. The
open-side branch-fallback pin is unchanged and still green.

Pins, all three from the dispatch ruling: a Refs-only merged PR on a card-named
branch leaves H8 clean; a closing-keyword body fires as before; a body-silent
merged PR on a card-named branch fires as before (the fallback's original #10757
population). Refs #N BESIDE a delivery does not make it partial, and a Refs
for another card narrows nothing about this one — bound per card number, as H7
binds.

#16037 — three line-number citations deleted

The header inventory's H1 entry (SKILL.md line 109, SAME write (line 465)) and
selfTest's RELEASE_RULE_LINE comment (SKILL.md line 465, VERBATIM). Numbers
out, quoted text kept, in the same style PR #16040 used for the two ruled
docblocks. git grep for line 109 / line 465 / line 493 over this file now
returns nothing.

Verification

All exit codes captured before any pipe.

Self-testnode scripts/pm/check-half-states.mjs --self-test, exit 0:
2535 cases before, 2553 after. Case-name diff: 20 added, 2 removed, both
forced by the ruling that flips H8's verdict on one fixture and each with a named
successor on the same input:

removed successor
H49 adjacency: on a head NAMED for the card H8 fires through its branch fallback H49 adjacency: on a head NAMED for the card H8 is silent too, since #16036
H49 adjacency: …and this row fires beside it — two readings, no double silence H49 adjacency: …and this row fires there — one reading now, and no silence

Two names survive on a moved subject and are named here rather than left to be
found: H8 branch: a Refs #N-only body delivers via its branch name now asserts
the unchanged prDeliversCard relation (still true of that input), and
H8 branch: …and the finding names the delivering PR now asserts on the
body-silent specimen, which is the case that still produces a finding.

Ablations — on a scratch copy outside the worktree, byte-pinned to the HEAD
blob before each run and restored by blob-hash comparison after it. Each mutation
was confirmed on disk by removed-text and injected-text occurrence counts plus a
blob-hash change, before the run was read:

The first ablation initially died on a TypeError naming neither row nor mutation;
the second commit on this branch adds the ?? [] row wrapper H34's own note
prescribes, so the reverse run reports NAMED cases. That is why the ablation
numbers above are from the re-run.

Gatesnode scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack
derived 33 commands at commit c493f98f22; all 33 run, all exit 0;
--ran reconciles: 33 derived famil(ies) accounted for — 33 run, 0 NOT-MEASURED,
exit 0. node scripts/pm/check-governed-merges.mjs --test scripts/pm/check-half-states.mjs
exit 0 — NOT governed — ordinary queue landing applies.

The 8 artifact-roster families whose roster sits under scripts/ or scripts/pm/
(where the derivation's silent verdict is evidence in neither direction) were
run too: 6 green; check:published-readme-exports and check:dts-closure both
exit 3 = PREREQUISITE NOT MET (no package has a dist/ in this worktree),
which is NOT MEASURED rather than red — this diff touches no package source, so
neither can reach it, and CI builds the closure and runs both.

Lint — whole-repo pnpm lint (eslint . --no-inline-config) through
bash scripts/pm/os-verify-lock.sh -c with slot issue-16036:
VERDICT command-exit 0 · held the lock 73s · waited 1s.

Live sweeps, read-only, both boards, before and after. Two scratch trees, one
pinned to the merge-base blob and one to the HEAD blob, both verified by
git hash-object before running.

board before after rows removed by this diff
objectstack-ai/objectstack 299 301 0
objectstack-ai/objectui 173 182 0

Every difference is board drift over the minutes between the paired runs, and
each one is accounted for rather than waved at:

One open question, left to the seat rather than decided here

The ruled anchor puts the list marker BEFORE the optional blockquote, so
- > Branch: reads and > - Branch: — the natural markdown for a bulleted line
INSIDE a blockquote, and arguably what "blockquote + bullet" names — does not.
Implemented exactly as ruled, with the residual pinned as a measured fact and
flagged in the report comment. Say the word and it is a one-character move.

skip-changeset: scripts/pm/** publishes nothing from any package.

🤖 Generated with Claude Code

Generated by Claude Code


Generated by Claude Code

…nd a `Refs`-only landing is not H8's full delivery

Three same-file cards, one flight.

#16170 — `claimedBranches` admits an optional markdown list marker before the
directive (`- Branch: …`). Measured live on #15511: `CLAIM_COMMENT_MARKER` has no
list marker either, so on a claim whose first line was an undecorated `Claim:`
and whose branch hung under it in a bullet list the two anchors failed at
different points — the comment WAS a claim and GOVERNED nothing, with nothing in
the artefact looking wrong. The claim marker is deliberately NOT widened with it
(2026-08-11, 不放宽谓词): when both lines carry a bullet the marker misses too and
"no claim comment" is then the true reading, so only the MIXED shape was
malignant and admitting the marker here is what removes it.

#16036 — H8's merged side stops reading a merged `Refs #N`-only PR on a
card-named branch as a FULL delivery. Under the partial-dispatch rule that PR is
a partial landing whose remainder is lawfully re-dispatched, and H8, which reads
no thread, was prescribing "drop `pm:dispatched`" against a card a second dev
holds. A second, narrower reader (`prFullyDeliversCard`) calls H49's own
`refsOnlyLinksFor`, so what H49 owns is exactly what H8 excludes. The shared
`prDeliversCard` relation is untouched: H8's OPEN side, H31 and `claimDelivery`
all need the wide reading, because a `Refs` half still open is live work.

#16037 — the three remaining SKILL.md line-number citations deleted, quoted text
kept, no other sentence moved.

Self-test 2535 -> 2553.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019RfFHiRCSs3JXLK4cwcfox
…-shape claim goes null

The ablation of the #16170 anchor died on a TypeError that named neither the row
nor the mutation — H34's row-wrapper lesson, applied to the governing-claim
cases the widening added.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019RfFHiRCSs3JXLK4cwcfox
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment