Repository navigation
Commit 0a5851d
fix(scripts): refuse
Fixes #18845
Clause-②: no
`defineCorpus` took `pathlessLineCitations: true` from any corpus, so
the prose-vs-data
distinction that declaration rests on was advisory: the next corpus
author either remembered it
or did not. This makes it mechanical. A corpus that declares a
`docProjection` may not declare
`pathlessLineCitations: true`; the refusal fires at registration and
names the corpus id and both
declarations, so the author is told which of the two to drop.
## The reading this rests on, re-taken first
The card's cost basis — 222 + 23 hits on the prose corpora, "essentially
all false positives" —
was #18592's dev's reading, transcribed onto the card and into two
script headers, and never run
twice. Re-taken here on `b0b5f31cc6`, through the extractor as it ships
(fences skipped,
de-duplicated against the path-anchored passes), over each corpus's own
declared population and
its own projection:
| corpus | projection | docs | admitted | colon form | `L` pin |
|---|---|---|---|---|---|
| `docs/adr/**` | none | 139 | 17 | 5 | 12 |
| `scripts/**` | `commentProse` | 264 | 50 | 38 | 12 |
| `packages/spec/src/**` | `commentProse` | 1458 | 70 | 69 | 1 |
| the system-context page | none | 1 | 0 | 0 | 0 |
**137 (112 + 25), not 245.** The gap is METHOD, not tree drift: re-run
against the very commit
the original names, PR head `88172978c7`, the extractor still admits 112
+ 25. Counting RAW REGEX
MATCHES over the same projected text — no fence skip, no de-duplication
— gives 230 + 25 on that
same tree, which is the figure that travelled. So the transcribed number
overstates what the
option actually admits by about a half, and it has now been corrected in
this module's header
with the commit it was taken against.
**The sharper half, and the one that makes this a rule rather than
advice: of the 120 hits in the
two projected corpora, ZERO inherit a path this tree tracks.** Both of
those corpora declare
`judgeUntrackedLineAnchors: false`, so every one of the 120 is DECLINED,
not judged. Opting in
there buys unjudged residual — the `scripts/**` gate's own waived count
goes 15 to 65, measured —
and not one finding an author could act on, at exit 0, with nothing red
to notice it by. A
projected corpus that opts in does not break; it quietly stops meaning
what its numbers say.
Sampled by hand, the character of the 120 is: this module's own header
teaching the spellings it
bans (23 hits across three gate headers, including 15 in
`scripts/symbol-anchors.mjs` itself), a
scenario label (`L11`, `L12`), a docker tag tail, a count after a colon
in a quoted ruling, and —
in `packages/spec/src/ui/component.zod.ts` and its test — dated read
positions inside a SIBLING
repository's renderer at a pinned sha, which are real line pointers but
name nothing this tree
holds. So "essentially all false positives" reproduces for `scripts/**`;
for
`packages/spec/src/**` the honest restatement is "real but unresolvable,
every one of them". The
cost is the same either way, and it is silent.
## The boundary, and what the other arm would have cost
The card left one call to the dev: refuse on ANY `docProjection`, or
only on
`docProjection === commentProse`. Both readings name the same two
corpora today (every projection
in the tree is `commentProse`), so no measurement separates them — it is
a choice about whom the
rule governs later.
**Chosen: any projection.** A projection is the corpus saying the judged
text is authored prose
carved out of something else; that is exactly the premise the option
contradicts. And the two
failure directions are not symmetric. An identity test is evaded by a
wrapper around the same
function — `(src) => commentProse(src)` — or by the next projection of
the same kind, silently,
with nobody deciding it; a self-test case pins that wrapper as refused
here. This arm's failure is
the opposite shape: a hypothetical projected DATA corpus is over-refused
LOUDLY, at registration,
by a message that names the exit the module's own ruling already
prescribes — widen the core, with
the maintainer, rather than fork the rule.
**What the narrow arm would have bought, and what it costs:** it would
let a future
data-shaped projection (say, one that carves JSON string values out of a
data file) opt in without
a conversation. The price is that the rule's reach then changes silently
whenever a projection is
renamed, wrapped or copied, and a governance rule keyed to one
function's identity is a rule whose
population nobody is tracking.
## Evidence
**LIT — it must fire, both legs on the real corpus file.**
`pathlessLineCitations: true` was
injected into the `scripts/**` corpus registration (byte-identical
mutation in both legs, blob
`06d4eb83dc`):
- before the change: `node scripts/check-scripts-symbol-anchors.mjs`
exits 0, accepts silently,
and reports its waived count rising 15 to 65 — the silent cost above,
observed;
- after the change: exits 1, and the first line of the refusal is
```
defineCorpus: corpus `scripts` declares a `docProjection` AND `pathlessLineCitations: true`.
```
Both legs restored with `git checkout HEAD -- PATH` and proven restored
by bytes: on-disk hash
back to the HEAD blob `68940d132c`, `git diff HEAD` empty, `git status
--porcelain` empty.
**DARK — it must not fire on the one live opt-in.**
`scripts/check-platform-checklist.mjs`
registers the tree's only `pathlessLineCitations: true`, and it declares
no projection. Its
whole-tree output is byte-identical before and after — same sha256
`f1abe15388f9`, same exit 0 —
which is what says the new rule bites projected corpora only. (That gate
was measured
deterministic first: two consecutive pre-change runs are
byte-identical.)
**The other four corpora are unmoved.** `check-scripts-symbol-anchors`,
`check-spec-docblock-symbol-anchors`, `check-adr-symbol-anchors` and
`check-system-context-census`
all exit 0, and the two whose summary lines were captured before the
change print byte-identical
summaries after it.
**Self-test.** Seven cases added in a new block 11f — the refusal, the
two things its message must
name, the wrapped-projection row that pins the rule to the declaration
rather than to one
function's identity, and three controls: the live DATA opt-in shape, a
projected corpus that never
mentions the option, and the option declared OFF beside a projection.
The battery floor is raised
149 to 156 with its ledger line. The count was read from the instrument,
not assumed: with the
floor temporarily pinned at 9999 the battery reports `registered 156
case(s)`. The cases ride this
file's ONE battery deliberately — its roster is per section banner and
this file carries none,
which is why a single hoisted battery is its landed shape.
**Gate families.** `node scripts/pm/dispatch-gates.mjs --commands --repo
objectstack-ai/objectstack`
derives 30 commands for this diff; 29 ran green, with the 30th
(`pnpm check:pm-dispatch-gates`, a several-minute self-test) recorded in
the report. The
derivation was taken at HEAD `ed9b43360d` while `origin/main` stood at
`0b31d90fb3`; the tool
flags one derivation input as stale across that range and the derived
command list is identical
either way.
## Acceptance notes
- `scripts/check-platform-checklist.mjs` carries the same transcribed
figure in its own corpus
ledger comment ("these two turned on corpus-wide fire 245 times"). It is
read-only for this
card, so it still carries a number this PR proves wrong by about a half.
Noted, not filed; the
successor is whichever PR next touches that ledger's line-citation
binding block.
- `docs/adr/**` declares no projection, so this rule leaves it free to
opt in — and there the
option is not harmless: 2 of its 17 hits are dev-server ports, and one
inherits a tracked path
and would become a red finding. The boundary is deliberately about who
has DECLARED their
documents to be prose, not about where the option happens to be a bad
idea.
---
_Generated by [Claude
Code](https://claude.ai/code/session_01JbZnqu8bt6YqfJsr9vaFb3)_
Co-authored-by: Claude <noreply@anthropic.com>pathlessLineCitations on a corpus that declares a doc projection (#18884)1 parent 1fb36ca commit 0a5851d
1 file changed
Lines changed: 103 additions & 14 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
115 | 115 | | |
116 | 116 | | |
117 | 117 | | |
118 | | - | |
119 | | - | |
120 | | - | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
121 | 123 | | |
122 | 124 | | |
123 | 125 | | |
| |||
399 | 401 | | |
400 | 402 | | |
401 | 403 | | |
402 | | - | |
403 | | - | |
404 | | - | |
405 | | - | |
406 | | - | |
407 | | - | |
408 | | - | |
409 | | - | |
410 | | - | |
411 | | - | |
| 404 | + | |
| 405 | + | |
| 406 | + | |
| 407 | + | |
| 408 | + | |
| 409 | + | |
| 410 | + | |
| 411 | + | |
| 412 | + | |
| 413 | + | |
| 414 | + | |
| 415 | + | |
| 416 | + | |
| 417 | + | |
| 418 | + | |
| 419 | + | |
| 420 | + | |
| 421 | + | |
| 422 | + | |
| 423 | + | |
| 424 | + | |
| 425 | + | |
| 426 | + | |
| 427 | + | |
| 428 | + | |
| 429 | + | |
| 430 | + | |
412 | 431 | | |
413 | 432 | | |
414 | 433 | | |
| |||
812 | 831 | | |
813 | 832 | | |
814 | 833 | | |
| 834 | + | |
| 835 | + | |
| 836 | + | |
| 837 | + | |
| 838 | + | |
| 839 | + | |
| 840 | + | |
| 841 | + | |
| 842 | + | |
| 843 | + | |
| 844 | + | |
| 845 | + | |
| 846 | + | |
| 847 | + | |
| 848 | + | |
| 849 | + | |
| 850 | + | |
| 851 | + | |
| 852 | + | |
| 853 | + | |
| 854 | + | |
| 855 | + | |
| 856 | + | |
| 857 | + | |
| 858 | + | |
| 859 | + | |
| 860 | + | |
815 | 861 | | |
816 | 862 | | |
817 | 863 | | |
| |||
1131 | 1177 | | |
1132 | 1178 | | |
1133 | 1179 | | |
| 1180 | + | |
| 1181 | + | |
| 1182 | + | |
| 1183 | + | |
| 1184 | + | |
| 1185 | + | |
| 1186 | + | |
| 1187 | + | |
| 1188 | + | |
1134 | 1189 | | |
1135 | | - | |
| 1190 | + | |
1136 | 1191 | | |
1137 | 1192 | | |
1138 | 1193 | | |
| |||
1551 | 1606 | | |
1552 | 1607 | | |
1553 | 1608 | | |
| 1609 | + | |
| 1610 | + | |
| 1611 | + | |
| 1612 | + | |
| 1613 | + | |
| 1614 | + | |
| 1615 | + | |
| 1616 | + | |
| 1617 | + | |
| 1618 | + | |
| 1619 | + | |
| 1620 | + | |
| 1621 | + | |
| 1622 | + | |
| 1623 | + | |
| 1624 | + | |
| 1625 | + | |
| 1626 | + | |
| 1627 | + | |
| 1628 | + | |
| 1629 | + | |
| 1630 | + | |
| 1631 | + | |
| 1632 | + | |
| 1633 | + | |
| 1634 | + | |
| 1635 | + | |
| 1636 | + | |
| 1637 | + | |
| 1638 | + | |
| 1639 | + | |
| 1640 | + | |
| 1641 | + | |
| 1642 | + | |
1554 | 1643 | | |
1555 | 1644 | | |
1556 | 1645 | | |
| |||
0 commit comments