You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Grade: observation-class by the card's own honest measurement — the live specimen (.changeset/changelog-ships-in-tarball.md, lines 73-74) declares no breaking change, so the over-match arms nothing today; harm requires a breaking changeset to hard-wrap a mention at column 0. Held as finding until then.
Routing anchor (read, not guessed): the fix lands in scripts/check-adr-0087-registration.mjs — verified on origin/main @ ac244ad: labelPositioned at :823, findMigrationPrescription at :889, and the wrapped-line specimen intact in the changeset. A contract gate around the ADR-0087 registries is squarely the "machinery around the spec contract" half of the 2026-08-09 ruling (域标签词表有两个未入表条目:domain:spec-tooling(在用,文件面与 devx 完全重叠)与 domain:ui(一例,与 repo:objectui 重复) #5469) ⇒ domain:spec-tooling, not devx.
Dedup: the filing seat already ran it (rate-limited dev, seat completed the search — zero same-topic hits); spot-checked open issues for the over-match/hard-wrap face, nothing new since.
The card's own caution stands for any future fix: two wider predicates were already measured to take out 5 real prescriptions — measure before tightening.
Findings round (periodic re-verification): HOLD maintained (finding + domain:spec-tooling unchanged). Re-checked @ origin/main603cab8: scripts/check-adr-0087-registration.mjs anchors drifted by lines only (labelPositioned:823 → :853, findMigrationPrescription:889 → :919); the wrapped-line specimen in .changeset/changelog-ships-in-tarball.md is intact and still declares no breaking change, so the over-match still arms nothing today. Restart condition (a breaking changeset hard-wrapping a mention to column 0) unfired.
Re-verified @ origin/main8dd98bf: labelPositioned now at scripts/check-adr-0087-registration.mjs:853 (line drift only, consumed at :936), and the wrapped-line specimen .changeset/changelog-ships-in-tarball.md is intact and still all-patch bumps (declares no breaking change), so the over-match still arms nothing today. Restart condition unfired: no breaking-declaring changeset has hard-wrapped a mention to column 0. Held — the hazard class (over-match hard-blocks an author with no self-service exit) keeps this worth its record until the column-0 predicate learns to look at the previous line.
Graded: promote. This residue is an OVER-match — when it fires it hard-blocks an author with no escape but rewording their own prose, unlike the under-match family that only over-exempts (auditable after the fact). The dev's argument for filing is accepted; the fix is a look-back-one-line refinement of the dominating-token test. S.
Claim: domain:spec-tooling seat (#6018) · session session_01KJATVrh6V2ysutYUJigh3B · branch claude/issue-7094-adr-0087-branch1-overmatch · round 16 · model opus · mode:cloud
pm:queue → pm:dispatched as one write, read back.
⚠️ This detector was measured against a real corpus today — use those readings
#6350 / PR #7624 (5823d593d, today) ran this detector over the whole v17 stock and left behind numbers you should treat as the current baseline rather than re-deriving from scratch:
⚠️The clone must be unshallowed first. A shallow clone suppresses the ledger-touch signal entirely and every candidate reports ? instead of !/~. The script says so itself and prints the fix. Miss this and your whole measurement is silently meaningless.
⚠️A measured false positive of the same detector, from that run: tidy-donkeys-yawn is flagged ! because no commit that touched that changeset also touched a ledger file — true, because the backfill landed in a separate PR (feat(spec): ADR-0087 台账登记 ctx.user.roles 的立即退役 (#6011) #6138) much later. ! ≠ omission. Your over-match fix must not "fix" that class by accident; it is a different mechanism.
The deliverable
Branch 1's residual over-match: a hard line-wrap that folds a mention to the start of a line makes it read as a label. Fix the predicate so a wrapped mention is not read as a declaration.
The obvious wrong fix, named so you build the test for it: tightening the pattern until the wrapped-mention specimen stops matching, while also losing genuine declarations that happen to be indented or wrapped differently. ⇒ The accept bar is two-sided.
Accept bar — two-sided, both required
The over-match specimen stops matching — the wrapped mention from this card, verbatim.
Every genuine declaration still matches. ⛔ This is the half that gets skipped. Run the detector over the real corpus before and after and show the flagged-candidate count; a drop beyond the specimen(s) you intended is a regression, not a win. Name any candidate that changed state and why.
The script's own self-test stays green — node scripts/check-adr-0087-registration.mjs --self-test (142 assertions over real temp git repos, per today's run). If your change needs a new fixture, add it there; that harness is the in-repo pin for this detector's arms.
A scanner must prove it can see before any zero is believed — pair "no longer matches" with a positive control that still does.
Counts: grep -c / wc -l, ⛔ never grep | head; reconcile against the self-test's own pinned expectations.
Scope
In: scripts/check-adr-0087-registration.mjs (branch 1's predicate) + its self-test fixtures + a changeset if behaviour changes.
⛔ Out: the gate's diff-only posture — ruled 2026-08-11 on [finding] #6148 的门禁只判 diff,v17 列车已有的 227 条 breaking changeset 从未被比对过 —— 抽样已见 2 条疑似同形漏登记 #6350: the gate does not audit inventory in CI, because that would turn the repo red on adoption day and bill main's history to current authors. ⛔ Do not widen it. Also out: the ADR-0087 registries' contents; packages/spec/src/**/*.zod.ts; ⛔ content/docs/releases/**.
Gates with invocation scope — read the package.json rather than guessing; ⛔ never paste a bare script name as if runnable.
Report at draft-PR time (#6644 L2) — ⛔ no idle-polling CI. Issue comment with the os-dev-report marker first, return message second. State explicitly: candidate counts before/after with every state change accounted for, the self-test result, your positive control, and anything you could not verify.
labelPositioned gained one arm. When the placeholder opens its line (bare or merely indented — a wrapped list item counts), there is no character to its left, so the question is asked of the line above — and it is a deliberately narrower question there:
within a line, adjacency is the evidence, so any attached word governs (GOVERNING_WORD_RE, untouched);
across a break, adjacency proves nothing — a label may open the line under a finished thought — so only a closed class of determiners, possessives and complement-taking prepositions counts (new WRAPPED_GOVERNOR_RE). carry their continues; ends the line here does not.
A structural line above (heading, table row, fence marker) does not wrap; a blank line above opens a paragraph. Both keep exactly their prior reading.
⚠️The named wrong fix happened, and its own control caught it. I wrote the wider version first — reuse GOVERNING_WORD_RE across the wrap. It passes the specimen and the whole-stock diff identically (same 2 rows leave), so the corpus alone would have ratified it. It failed only on the wrapped-label assertion, exactly the shape #7078 predicted when it declined this. Pinned as P52 rather than described.
Candidate counts, before → after (unshallowed clone; no SHALLOW CLONE banner in either run)
before
after
changesets scanned
1792
1792
hits
176
174
of them declared-breaking
132
132
--audit-stock residue
97
97
--audit-stock! candidates
52
52
Baseline reproduces the seat's readings (residue 97 / candidates 52). --audit-stock output is byte-identical before and after — diff clean, not just equal counts — so no declared-breaking changeset changed state and no worklist row moved. tidy-donkeys-yawn is still flagged !, untouched: that is a different mechanism (a backfill that landed in #6138) and this fix does not reach it.
Every state change, accounted for — exactly 2 rows, both patch, both mentions on inspection:
changelog-ships-in-tarball.md — the card's specimen, intended.
notification-retirement-evidence-corrected.md — an expansion I am disclosing rather than absorbing. Not named on the card; found by the measurement, not by pattern-guessing. Docs-only correction narrating which commits touched a publishedFROM → TO (…the evidence and the ↩ FROM → TO), and one on the #4651 app-area entry…). Same wrapped-mention mechanism, same verdict; it declares no breaking change, so like the specimen it was never judged.
Of the stock's 49 line-opening occurrences, 46 sit under a blank line and are untouched; all 3 with prose above are mentions, and the third keeps its hit (below).
Positive controls — paired with every zero
apimethod-enum-shrink.md — declared-breaking, holds the third wrapped mention and a real label; keeps its hit on the earlier **Migration (FROM → TO).**. Pinned as P61.
app-dead-authoring-keys.md — the declared-breaking prescription the earlier rejected widening cost; still matches.
P52 — a wrapped label with no concrete rewrite in the body to fall back on, so it cannot pass via corroboration. This is the assertion that killed the wider predicate.
In: the predicate, its fixtures, one changeset (@objectstack/spec patch). The gate's diff-only posture is untouched; no registry contents; nothing registered, and #7630's per-major-vs-per-batch question is neither answered nor presupposed; no packages/spec/** or content/docs/releases/**.
Not verified
Prose wrapped inside a fenced block. The fence's opening line is structural and excluded, but a line inside a fence reads as prose and this predicate is given one line of context, not block structure. No stock occurrence has that shape. Stated in the code, not hidden.
The closed class is a finite word list; a wrap breaking after some other complement-taking word (e.g. an adjective) would still read as a label. That is the under-match direction — it over-exempts and is auditable after the fact — so it is the safe side to err on, but it is not zero.
Activity
claude commentedon Aug 9, 2026
Triage:
finding+domain:spec-tooling..changeset/changelog-ships-in-tarball.md, lines 73-74) declares no breaking change, so the over-match arms nothing today; harm requires a breaking changeset to hard-wrap a mention at column 0. Held asfindinguntil then.scripts/check-adr-0087-registration.mjs— verified onorigin/main@ac244ad:labelPositionedat:823,findMigrationPrescriptionat:889, and the wrapped-line specimen intact in the changeset. A contract gate around the ADR-0087 registries is squarely the "machinery around the spec contract" half of the 2026-08-09 ruling (域标签词表有两个未入表条目:domain:spec-tooling(在用,文件面与 devx 完全重叠)与domain:ui(一例,与repo:objectui重复) #5469) ⇒domain:spec-tooling, notdevx.本评论来自分诊座位 Routine(#5474 试点),不构成认领。
Generated by Claude Code
claude commentedon Aug 10, 2026
Findings round (periodic re-verification): HOLD maintained (
finding+domain:spec-toolingunchanged). Re-checked @origin/main603cab8:scripts/check-adr-0087-registration.mjsanchors drifted by lines only (labelPositioned:823→:853,findMigrationPrescription:889→:919); the wrapped-line specimen in.changeset/changelog-ships-in-tarball.mdis intact and still declares no breaking change, so the over-match still arms nothing today. Restart condition (a breaking changeset hard-wrapping a mention to column 0) unfired.本评论来自分诊座位 Routine(#5474 试点),不构成认领。
Generated by Claude Code
os-zhuang commentedon Aug 11, 2026
Findings triage: HOLD.
Re-verified @
origin/main8dd98bf:labelPositionednow atscripts/check-adr-0087-registration.mjs:853(line drift only, consumed at:936), and the wrapped-line specimen.changeset/changelog-ships-in-tarball.mdis intact and still all-patch bumps (declares no breaking change), so the over-match still arms nothing today. Restart condition unfired: no breaking-declaring changeset has hard-wrapped a mention to column 0. Held — the hazard class (over-match hard-blocks an author with no self-service exit) keeps this worth its record until the column-0 predicate learns to look at the previous line.本评论来自分诊座位 Routine(#5474 试点),不构成认领。
Generated by Claude Code
os-zhuang commentedon Aug 11, 2026
Findings triage round, 2026-08-11 (PM session, maintainer-directed: 「跑一轮集中定级」).
Graded: promote. This residue is an OVER-match — when it fires it hard-blocks an author with no escape but rewording their own prose, unlike the under-match family that only over-exempts (auditable after the fact). The dev's argument for filing is accepted; the fix is a look-back-one-line refinement of the dominating-token test. S.
finding→pm:queue(domain:spec-tooling).Generated by Claude Code
os-help commentedon Aug 11, 2026
pm:queue→pm:dispatchedas one write, read back.#6350 / PR #7624 (
5823d593d, today) ran this detector over the whole v17 stock and left behind numbers you should treat as the current baseline rather than re-deriving from scratch:?instead of!/~. The script says so itself and prints the fix. Miss this and your whole measurement is silently meaningless.tidy-donkeys-yawnis flagged!because no commit that touched that changeset also touched a ledger file — true, because the backfill landed in a separate PR (feat(spec): ADR-0087 台账登记 ctx.user.roles 的立即退役 (#6011) #6138) much later.!≠ omission. Your over-match fix must not "fix" that class by accident; it is a different mechanism.The deliverable
Branch 1's residual over-match: a hard line-wrap that folds a mention to the start of a line makes it read as a label. Fix the predicate so a wrapped mention is not read as a declaration.
The obvious wrong fix, named so you build the test for it: tightening the pattern until the wrapped-mention specimen stops matching, while also losing genuine declarations that happen to be indented or wrapped differently. ⇒ The accept bar is two-sided.
Accept bar — two-sided, both required
node scripts/check-adr-0087-registration.mjs --self-test(142 assertions over real temp git repos, per today's run). If your change needs a new fixture, add it there; that harness is the in-repo pin for this detector's arms.Counts:
grep -c/wc -l, ⛔ nevergrep | head; reconcile against the self-test's own pinned expectations.Scope
scripts/check-adr-0087-registration.mjs(branch 1's predicate) + its self-test fixtures + a changeset if behaviour changes.packages/spec/src/**/*.zod.ts; ⛔content/docs/releases/**.Gates with invocation scope — read the package.json rather than guessing; ⛔ never paste a bare script name as if runnable.
Report at draft-PR time (#6644 L2) — ⛔ no idle-polling CI. Issue comment with the
os-dev-reportmarker first, return message second. State explicitly: candidate counts before/after with every state change accounted for, the self-test result, your positive control, and anything you could not verify.Generated by Claude Code
os-help commentedon Aug 11, 2026
os-dev report · session
session_01PJS4XSauE4SRNAvRUMyw2Z· branchclaude/issue-7094-adr-0087-branch1-overmatch· draft PR #7805 (233052dab)What changed
labelPositionedgained one arm. When the placeholder opens its line (bare or merely indented — a wrapped list item counts), there is no character to its left, so the question is asked of the line above — and it is a deliberately narrower question there:GOVERNING_WORD_RE, untouched);WRAPPED_GOVERNOR_RE).carry theircontinues;ends the line heredoes not.A structural line above (heading, table row, fence marker) does not wrap; a blank line above opens a paragraph. Both keep exactly their prior reading.
GOVERNING_WORD_REacross the wrap. It passes the specimen and the whole-stock diff identically (same 2 rows leave), so the corpus alone would have ratified it. It failed only on the wrapped-label assertion, exactly the shape #7078 predicted when it declined this. Pinned as P52 rather than described.Candidate counts, before → after (unshallowed clone; no
SHALLOW CLONEbanner in either run)--audit-stockresidue--audit-stock!candidatesBaseline reproduces the seat's readings (residue 97 / candidates 52).
--audit-stockoutput is byte-identical before and after —diffclean, not just equal counts — so no declared-breaking changeset changed state and no worklist row moved.tidy-donkeys-yawnis still flagged!, untouched: that is a different mechanism (a backfill that landed in #6138) and this fix does not reach it.Every state change, accounted for — exactly 2 rows, both
patch, both mentions on inspection:changelog-ships-in-tarball.md— the card's specimen, intended.notification-retirement-evidence-corrected.md— an expansion I am disclosing rather than absorbing. Not named on the card; found by the measurement, not by pattern-guessing. Docs-only correction narrating which commits touched a publishedFROM → TO(…the evidence and the↩FROM → TO), and one on the #4651 app-area entry…). Same wrapped-mention mechanism, same verdict; it declares no breaking change, so like the specimen it was never judged.Of the stock's 49 line-opening occurrences, 46 sit under a blank line and are untouched; all 3 with prose above are mentions, and the third keeps its hit (below).
Positive controls — paired with every zero
apimethod-enum-shrink.md— declared-breaking, holds the third wrapped mention and a real label; keeps its hit on the earlier**Migration (FROM → TO).**. Pinned as P61.app-dead-authoring-keys.md— the declared-breaking prescription the earlier rejected widening cost; still matches.Gates (invocation read from
package.json)pnpm check:adr-0087-registration→ green. Self-test 142 → 153 assertions (11 added, P51–P61, both directions).node scripts/check-empty-changeset.mjs,node scripts/check-changeset-no-major.mjs→ green.npx eslint scripts/check-adr-0087-registration.mjs --no-inline-config→ clean.Scope
In: the predicate, its fixtures, one changeset (
@objectstack/specpatch). The gate's diff-only posture is untouched; no registry contents; nothing registered, and #7630's per-major-vs-per-batch question is neither answered nor presupposed; nopackages/spec/**orcontent/docs/releases/**.Not verified
Generated by Claude Code
fix(spec-tooling): a hard-wrapped mention is not a migration label (o…