3 Commits
Author SHA1 Message Date
slaguru666andClaude Opus 5 6171d1e9b9 CLEAN GROUND v0.19 — the outcome where somebody holds
Applies desk pass 8's five fixes, and adopts R-292's TAG_OPEN.

1. Step 5 now has all three of its outcomes. opposedContestFor returns taken,
   held and unsettled; the document printed the first and the third. "They
   hold" is 48.1% against the default target, 52.4% against Braithwaite and
   74.3% against an Ashcroft who refused — which v0.17 established is what
   most tables have, so the middle column is the one they will play. It gets
   its own countdown row, its own table, and read-aloud of its own, and the
   COMES TO NOTHING paragraph is now explicitly the unsettled case so it can
   stop being the nearest text to an outcome it is not about. The reason
   they held is the case's own argument arriving as good news: a person with
   a life on the record is a difficult document to overwrite. Every figure
   re-enumerated over all 10,000 roll pairs before writing.
2. EXPOSURE's five things are six, in order, under a heading that says six.
   Introduced in my own v0.16 and survived two versions; asserting a unique
   match protects against editing the wrong text and not against inserting in
   the wrong place.
3. EXPOSURE opens with a one-minute box. The body is untouched — nothing in
   it is padding — but 3,176 words is sixteen minutes about the encounter the
   document exists to prevent, and a GM with thirty minutes of prep now has
   somewhere to stop.
4. The stale open question is closed. Braithwaite has not been on the
   critical path since v0.14 un-gated the tell, and pass 6 ran the act with
   the Xenology and the Psychology both failed.
5. Act Four's Psychology has a special: which file it thinks it is, and how
   recently it read it. It corrects them on Prichard's service history — it
   is not remembering, it is citing.

Coverage 6 -> 7 specials, so the cited figure moved 85% -> 83.7% and
check-cited caught the prose before I did, which is what it is for.

R-292 adopted: outcome-coverage now composes its body onto check-scenarios'
TAG_OPEN through tagRe, so the two readers cannot drift on what starts a tag
while keeping the different bodies they need — and tagRe's fresh matcher per
call avoids the shared-lastIndex defect, this file being the second caller
that would have found it. Verified identical across all seven spellings.

npm run check: 19 guards pass.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-13 16:04:32 +01:00
slaguru666andClaude Opus 5 8a051f7f2b R-291 follow-up: one tag pattern, so the two readers cannot disagree
R-291 measured check-scenarios' tagsIn against this file's readers and found
them apart on three spellings. tagsIn was widened for case and spacing around
the colon; outcome-coverage's strict half still carried the case-sensitive
literal, so `[cus: Spot — x]` was READ by one guard and reported unparseable
by the other. The build failed, which is the safe direction, but it failed
saying the tag could not be read while another guard had just read it.

beatsIn and beatLikeIn now share one TAG pattern, widened to agree with
tagsIn. Measured across seven spellings: the five both strict readers accept
now agree in all three, and `[CUS Spot]` and `[CUS= Spot]` are still refused
by both and still named by the loose counter, so the canary keeps its teeth.

Verified on the real document that this is a spelling fix and nothing else —
beats 21, quoted 1, unparsed 0, stated 18/6/6, session figures unchanged, so
the baseline is untouched. A lowercase tag planted in the acts is now read by
check-outcomes, check-scenarios and check-rollable alike; the file was
restored byte-identical after the test. R-291's own assertion still passes.

Found by the peer session measuring my file rather than trusting it, which is
the fourth reader this session to be caught describing or reading its own
format wrongly.

npm run check: 19 guards pass.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-13 15:52:11 +01:00
slaguru666andClaude Opus 5 9c2ce9d905 R-290: check-outcomes — a beat that names a roll must say what it does
Desk pass 7's finding, turned into the nineteenth guard. check-rollable asks
whether a skill is reachable at 25% by the declared cast; pass 5 found that
is rollability, not competence; pass 7 found it is also not coverage. A beat
could be reachable, well-rated and silent about every band but the one the GM
improvises, and the whole suite stayed green.

tools/outcome-coverage.mjs measures. Beats are located structurally — the
bullet that owns the tag and its children, ending at the next bullet of the
same or shallower indent or the next heading, because R-287 is what an
unbounded scope does. Band widths are counted by grading all 100 results
through gradeRoll, never by arithmetic on fumbleStart, which is off by one
and was written wrongly twice this session before being caught. Ratings come
from the declared cast via R-286's reader, best-in-cast per skill, because
that is the die a table actually rolls.

tools/check-outcomes.mjs holds it, in two kinds:

  RATCHET — stated failure/fumble/special counts may improve and may not
  regress; unwritten-band exposure may fall and may not rise. --update
  re-records these, because freezing them would make every improvement fail.

  HARD CLAIMS — read from what is measured NOW, never from the baseline, so
  --update cannot silence them: a floor of 18 beats (check-cited once passed
  with zero citations), no beat bare of every band, every scope structurally
  bounded and none over 5% of the file, no unparseable tag, no beat naming a
  skill the cast has no rating for.

Verified by breaking it: a stripped beat, a broken tag regex, an unparseable
tag and a removed failure case each turn it red; the file and baseline were
restored byte-identical after each; and --update with a bare beat present
re-records the baseline and still fails.

Two bare beats found and filled while building it — the six at the back, and
the Insight that is deliberately indistinguishable on a success and a miss,
which now says so rather than saying nothing. Coverage 16/21 failure, 5
fumble, 4 special at the start; 18/21, 6 and 6 now.

The three figures are cited against the artifact rather than typed, which was
the peer session's condition and the right one: pass 7 hand-counted 22 beats
where there are 21 (Act Three's warning QUOTES a beat, and a hand count reads
the quotation as one — R-286 in the other direction), and its other three
counts were stale within one commit.

Its first catch was its author: the STATUS line announcing this guard
contained a beat-shaped tag and was counted as a beat. The reader was not
changed — prose shaped like a beat is what this file is for — and the error
message now names the fenced block as the place to write an example. Minutes
later check-cited refused a citation-shaped comment in the post-pass about
citations. Three readers, three authors describing their own format inside
it, each caught by a guard built for a different pass.

CLEAN GROUND v0.18. npm run check: 19 guards pass.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-13 15:47:25 +01:00