Skip to content

fix(pm): H19's summary clause ends its own sentence - #13677

Merged
zhuangjianguo merged 1 commit into
mainfrom
claude/issue-13650-h19-clause-terminator
Aug 31, 2026
Merged

fix(pm): H19's summary clause ends its own sentence#13677
zhuangjianguo merged 1 commit into
mainfrom
claude/issue-13650-h19-clause-terminator

Conversation

@zhuangjianguo

Copy link
Copy Markdown
Collaborator

Fixes #13650

summaryLine's H19 clause carried its terminating . inside the cross-repo branch
alone, so the ONE rendering that ended the sentence was the one where an unrelated
optional probe happened to fire. On an ordinary healthy pass — no shortfall AND no probe
— the clause stopped at card(s) and a lone space joined it straight onto H20's lead-in,
so two disclosures read as one sentence and the boundary was findable only by a reader who
already knew the row inventory.

What changed

One file: scripts/pm/check-half-states.mjs.

  • H19's clause now terminates unconditionally, with the same . every other clause
    on the line uses.
  • The two optional branches (shortfall, cross-repo) contribute only their own text. The
    cross-repo branch already ended in a period of its own, so its leading space and the
    join's trailing space move into the terminator rather than adding a second one: the
    probe shape renders resolves them. , never a doubled .. .

Everything else on the line is byte-identical

Rendered at the base commit and at head over the same six shapes, then diffed character by
character. Nothing is removed on any shape, and the single inserted character sits in
H19's terminator region on all six:

shape base → head delta
healthy (no shortfall, no probe) 3247 → 3248 one inserted .
shortfall, no probe 3583 → 3584 one inserted .
cross-repo probe, no shortfall 3498 → 3499 one inserted .
shortfall + probe 3834 → 3835 one inserted .
summaryLine({}, 0) 3283 → 3284 one inserted .
every optional sub-clause firing 5287 → 5288 one inserted .

The clause-boundary extractor is unmoved: the partition control (every window's clause
length summing to the whole line's length — no gap, no overlap) holds on all six shapes at
head, so adding the terminator inside H19's clause moved no boundary.

Live read-only fire, at this PR's head commit

PM_SWEEP_REPO=objectstack-ai/objectstack node scripts/pm/check-half-states.mjs at
59d5c22bb, exit 0, read-only. The H19 to H20 boundary now reads:

Blocker liveness (H19): targets resolved on 27 of 27 distinct `Blocked-by:` target(s)
named by open `pm:blocked` card(s). Dispatch liveness (H20 + H27): remote branch read on
8 of 8 distinct claimed branch(es) …

A no-shortfall, no-probe pass — the exact shape that used to run on. The old adjacency
card(s) Dispatch liveness occurs 0 times in that run's output.

Pins

Scoped to H19 via the clause extractor, so no neighbour's text can satisfy them. Eight
cases: the clause ends . on the healthy, shortfall, probe and both-branches shapes;
the probe shape carries no doubled period and closes exactly once; and two deliberately
whole-line cases on the boundary itself, because the adjacency between two clauses has no
single window to scope it to.

All four shapes are pinned rather than one, because the defect WAS that the shapes
disagreed — a pin written on the probe shape alone would have been green for the whole
life of the bug. The neighbouring whole-line endsWith('not a gate verdict.') cases could
not see this at all: they pin where the SENTENCE ends, which is H37's business, not where
this clause ends.

Ablations

Both legs mutated on disk with the anchor hit-count asserted (a zero-hit edit refuses
loudly instead of measuring an unmutated tree), and restored against HEAD with the
restored blob hash compared to the HEAD blob and git diff HEAD proven empty.

  • Reverting only the terminator to its previous shape: exactly 4 of 1791 cases red —
    the healthy and shortfall terminator cases and both boundary cases. The two probe-shape
    cases stayed green, which is the measurement that shows why one shape was not enough.
  • Deleting H19's clause outright: 22 red, including
    summaryClause: h19Blockers opens its own clause on every run. H19's presence control
    is still red under its own ablation and the other 16 windows' presence controls stayed
    green, so the per-window contract is intact.

Verification

Self-test, quoting its own verdict lines: ✓ check-half-states self-test: 1783 cases pass.
at the base commit, ✓ check-half-states self-test: 1791 cases pass. at head (+8).

Gate family derived from the actual diff with
node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack, run at
59d5c22bb — 17 path-derived families plus the 2 convention-triggered ones this change
kind incurs (it edits a gate script). All green, each read from the gate's own verdict
line with the exit code captured before any pipe, except two that decline to measure
locally and say so themselves:

  • node scripts/check-test-completeness.mjsPREREQUISITE NOT MET, exit 3: it grades a
    saved turbo run test log and there is none locally. NOT MEASURED, not a red; its own
    text says so.
  • node scripts/check-partof-closing-keyword.mjs with no PR context — NOT WIRED,
    exit 2. Its self-test spelling (pnpm check:partof-closing-keyword, 28 cases) is green,
    and the gate was additionally run against this body with PR_BODY set before the PR was
    opened.

No changeset: nothing here is published from any package — the diff is scripts/pm/**
only, so the PR carries skip-changeset.

Notes for the reviewer

Card relationships, stated once here and carried by no commit trailer (this branch
squashes): the scoped-assertion scaffolding these pins are built on came from #13654, and
its adjudicated default was that the rendered summary line must not change — this card is
the one sanctioned rendered-line change deferred out of it. Nothing from #13654 or #13628
is undone here. The shortfall wording and the cross-repo branch, both from #11218, are
untouched apart from the whitespace that moved into the terminator.

Generated by Claude Code


Generated by Claude Code

`summaryLine`'s H19 clause carried its terminating `. ` inside the
cross-repo branch alone, so the only rendering that ended the sentence
was the one where an unrelated optional probe had fired. On an ordinary
healthy pass -- no shortfall and no probe -- the clause stopped at
`card(s)` and a lone space joined it straight onto H20's lead-in, which
the live 2026-08-31 patrol rendered as
`...card(s) Dispatch liveness (H20 + H27): ...`.

Terminate the clause unconditionally and let the two optional branches
contribute only their own text. The cross-repo branch already ended in a
period of its own, so its leading space and the join's trailing space
move into the terminator rather than adding a second one: across every
rendered shape the whole line differs from base by exactly one inserted
`.`, inside H19's terminator region and nowhere else.

Pin it with the #13654 scoped-assertion scaffolding: `saidBy('h19Blockers',
...)` cases assert the clause ends `. ` on the healthy, shortfall, probe
and both-branches shapes, plus that the probe shape does not render
`resolves them.. `. The neighbouring whole-line `endsWith('not a gate
verdict.')` cases could not see this -- they pin where the SENTENCE ends,
not where this clause does.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EXxTW8mvPBhoHxmyPZ63de
@zhuangjianguo zhuangjianguo added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Aug 31, 2026 — with Claude
@zhuangjianguo
zhuangjianguo marked this pull request as ready for review August 31, 2026 06:09
@zhuangjianguo
zhuangjianguo added this pull request to the merge queue Aug 31, 2026
Merged via the queue into main with commit ac8dfbe Aug 31, 2026
35 checks passed
@zhuangjianguo
zhuangjianguo deleted the claude/issue-13650-h19-clause-terminator branch August 31, 2026 06:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

summaryLine: H19's clause has no sentence-terminating period unless a cross-repo probe fired, so it runs into H20's clause

2 participants