Skip to content

check-adr-0087-registration reads a governed MENTION as a label whenever a framing word sits between the governor and the placeholder #17864

Description

@os-bill

Filed by the os-dev round on PR #17862 (card #17357), session_01MkQhmuuJAVDjmeWNixwDDH,
2026-09-12. ⛔ Unclaimed. No domain:* label and no pm:* state — both are the triage seat's to
produce.

The shape

findMigrationPrescription's branch 1 distinguishes a placeholder that is used as the
convention's label from one that is merely mentioned by asking whether an ordinary word
directly governs it. When the word immediately left of the placeholder is a framing word
(Migration, 迁移, rename, upgrade, …), that word frames rather than governs, so the
predicate strips it and asks the question of what stands behind it.

It never asks. Stripping the framing tail leaves the space the framing word sat behind, and
the governance test is end-anchored, so it can no longer match anything — and the occurrence is
read as a label.

inserting a framing word between the governor and the placeholder flips a mention into a
label
, which is the #6967 false-positive direction the script's own header calls out as worth a
rule of its own: a false positive here does not merely misreport, it hard-blocks a PR.

Reproduction, with both controls lit

Run against findMigrationPrescription exported from
scripts/check-adr-0087-registration.mjs, on objectstack-ai/objectstack at d87a6936ef:

input result
probethe Migration FROM → TO is documented elsewhere { branch: 'from-to-label' }
control A, the same sentence with the framing word removed — the FROM → TO is documented elsewhere null (correctly a mention: the governs)
control B, the framing word with no governor in front — Migration FROM → TO: delete the block { branch: 'from-to-label' } (correctly a label)

Control A is what makes the probe a reading rather than an assertion: the only difference between
it and the probe is one framing word, and the verdict flips. Control B shows the label arm has not
simply stopped working.

Where the mechanism is — re-derive by symbol, ⛔ not by line

  • labelPositioned, its in-line arm — the expression that strips FRAMING_TAIL_RE from the
    prefix and hands the result to GOVERNING_WORD_RE.
  • FRAMING_TAIL_RE's own docblock states the intent explicitly: a framing word frames the
    placeholder and does not govern it. The strip exists to expose the word behind it; nothing
    re-trims, so that word is never reached.
  • GOVERNING_WORD_RE is end-anchored on a letter or the attributive particle, neither of which a
    trailing space can be.

Why this is filed rather than folded into #17357

#17357 repairs the heading arm's missing polarity, and PR #17862 does exactly that and no
more. This is the same false-positive direction in a different arm, and that arm carries its
own measured history — its first draft used the wider rule "no letters anywhere in the prefix" and
took five real prescriptions with it, app-dead-authoring-keys.md among them. Repairing it
therefore needs its own measurement over the changeset stock before it is believed, which is not
something to ride along on another card's diff.

⚠️ Note the direction before choosing a repair: today's behaviour is the conservative one
(more hits ⇒ more refusals), so the cost is a blocked author rather than a missed retirement. A
repair that simply re-trims must be measured for what it stops flagging.

Dedup

Targeted enumeration read 2026-09-12 over labels=domain:spec&state=all, 100 rows, grepped for
adr-0087|prescription|FROM|mention|from-to|framing: 10 title hits, none of them this mechanism.
Lit control: 100 of 100 rows match a lowercase letter. Dark control: a fabricated token matches 0.

Not duplicates, and each worth reading first: #17357 (the heading arm, repaired in PR #17862),
#16787 (type-surface-only unclaimable by its own class — same gate, same shape of defect),
#6967 (the narrowing that introduced the mention/label distinction this card extends).

Source

card #17357 · PR #17862 · scripts/check-adr-0087-registration.mjs at d87a6936ef


Generated by Claude Code

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions