R-287: assert the scope anchors in check-behaviour, and end them structurally
indexOf returns -1 for a name that is gone and slice(0, -1) is everything but one character, so a scope anchored on a moved name does not shrink or fail -- it becomes the file. Renaming the end anchor took one test's body from 3,184 characters to 30,825 with the assertion still passing. The other site windowed burstAttack at 4,000 characters over a function that runs 4,305. bodyOf asserts the anchor and ends at the next top-level function. A missing anchor now says which anchor and what would have happened, where the old code reported "burstAttack still calls rollWeaponDamage" -- a claim about a call when the truth was a claim about a name. Also records the rest of the sweep, including the guards deliberately left alone. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
0453255ecc
commit
f3caaab04d
@@ -6690,3 +6690,65 @@ nothing to check.
|
||||
Five cases in a worktree: two decoys (fail here, pass at R-284, the pass confirmed by running
|
||||
HEAD's copy against the same tree), a reword inside the section, the renamed heading, and the
|
||||
clean control.
|
||||
|
||||
## R-286 — a declaration and a mention of one look identical to a regex
|
||||
|
||||
Swept the other seventeen guards for the page-wide match R-285 removed from check-powers.
|
||||
Most are already scoped or have nothing to scope. Two are not, and the first is live.
|
||||
|
||||
`CLEAN_GROUND.md` contains **two** things matching `<!-- cast: ... -->`: the declaration
|
||||
under `## Casting`, and — ten lines below it — the warning that explains it, which quotes
|
||||
`` `<!-- cast: -->` `` inside backticks and matches the same pattern with an empty capture.
|
||||
`check-rollable` and `declared-cast.mjs` both used `.match()`, first hit wins. **The whole
|
||||
arrangement has been correct because the declaration happens to come first.**
|
||||
|
||||
Move that warning above the list and `check-rollable` reads a cast of nobody, falls back to
|
||||
`ROSTER_BEST`, and goes green having held every skill in the document to the full duty roster
|
||||
instead of the declared six — the identical OK line, the scope silently widened. Instrumented
|
||||
and read off, not reasoned about:
|
||||
|
||||
[scope] docs/scenarios/CLEAN_GROUND.md -> the duty roster (warning moved above)
|
||||
[scope] docs/scenarios/CLEAN_GROUND.md -> its declared cast of 6 (as the file stands)
|
||||
|
||||
`check-firstblood` fails on the same page, but says *"CLEAN GROUND now casts 0"* — describing
|
||||
a scenario that casts six, which sends a reader to the cast list rather than to the two
|
||||
markers. R-268 had this bug from the other side, when a tools file's own example was read as
|
||||
a real declaration; this is the same defect facing inward, and the marker that triggers it was
|
||||
added to the document by the warning telling everyone how load-bearing the marker is.
|
||||
|
||||
`castMarkersIn` now blanks code spans and fenced blocks before scanning — padded, so line
|
||||
numbers still point at the source — and more than one surviving marker is fatal with every
|
||||
line named. `check-rollable` imports it rather than carrying a second regex, so the guard that
|
||||
checks the cast and the guards that measure the fight cannot disagree about who is in it.
|
||||
|
||||
**Disclosed to c0 the same minute.** The comparison that found this was meant to run in a
|
||||
throwaway worktree; `git worktree add` failed on a stale registration, the heredoc ran on in
|
||||
the shared tree, and it moved one line of c0's uncommitted `CLEAN_GROUND.md`. Reverted by
|
||||
hand, `## Casting` block diffed byte-identical against HEAD, c0 told what to check and why
|
||||
before anything else was done. A `test -d` on the worktree now guards the pattern.
|
||||
|
||||
## R-287 — a scope anchored on a name that has moved is the whole file
|
||||
|
||||
`check-behaviour` scopes three source assertions with `indexOf`. For a name that is gone
|
||||
`indexOf` returns -1 and `slice(0, -1)` is everything-but-one-character, so the scope does not
|
||||
shrink or fail — it becomes the file. Renaming the end anchor took one test's body from
|
||||
**3,184 characters to 30,825** with the assertion still passing: a test that reads like a
|
||||
statement about `rollWeaponDamage` making a statement about all of `ringbrp.mjs`.
|
||||
|
||||
The other site windowed `burstAttack` at 4,000 characters. The function runs 4,305, so the
|
||||
window was already short of its own subject, and one edit the other way would have had it
|
||||
testing whatever came next for a `locate: false` that belongs to a different call.
|
||||
|
||||
`bodyOf` now asserts the anchor and ends structurally, at the next top-level function. A
|
||||
missing anchor says so — *check-behaviour scopes a test to "export async function burstAttack"
|
||||
and ringbrp.mjs no longer contains it. Fix the anchor: unfixed, the test would read the whole
|
||||
file and pass* — where the old code reported *"burstAttack still calls rollWeaponDamage"*,
|
||||
which is a claim about a call when the truth is a claim about a name.
|
||||
|
||||
**The rest of the sweep, so the negative result is on the record.** check-cited resolves each
|
||||
citation positionally and already refuses markers it cannot read. check-handouts matches each
|
||||
almanac row's note against the whole scenario (`md.includes(note)`); the notes are distinctive
|
||||
sentences and there is no smaller slice that owns them, so it is left alone deliberately
|
||||
rather than overlooked. check-rules builds its covered-set from labels it generates, not from
|
||||
searching a document. check-lang, check-creatures, check-templates, check-kits and the
|
||||
baseline guards do no document matching at all.
|
||||
|
||||
Reference in New Issue
Block a user