CB-WP-0046: the rule the placement encodes, and a log that names its rules
Some checks failed
ci / check (push) Failing after 4s
Some checks failed
ci / check (push) Failing after 4s
CB-WP-0045 left "nothing explains what a scope does" open and gave a FALSE reason: that scoping is our Variant so no printed sentence exists. The H2 package ships Rules_Text.csv -- twenty-two passages of player-facing rules -- and nothing in clay-borg had ever read the file. A wrong reason for an open item is worse than an open item; it retires the question. Filed as F26 against ground-game: a package that adds a FILE is invisible where one that adds a column is not. The scope rule now renders under the table in the edition's own words, only when a non-global scope is in play, matched by heading rather than row number, and absent (never paraphrased) if the edition drops it. The trial log stamps its variant on the begin marker -- a session property, not an eighth column -- read off state.variant rather than the --variant flag, because a bare `state.variant = v` leaves H2 inert and a flag-stamped log would put false provenance on real player words. An unstamped log reports `unrecorded`, never `ground-darvo-r0`. Six mutations, six red. The sixth is the finding: every trials.py fixture built its marker out of BEGIN, so nine checks followed BEGIN away from what hotseat.rs writes and stayed green while real logs broke. A fixture built from the constant under test cannot test the constant -- the control is now a literal, asserted from both sides. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
df65e2dee1
commit
de25c4cae0
10 changed files with 986 additions and 12 deletions
128
workplans/CB-WP-0046-the-rule-the-placement-encodes.md
Normal file
128
workplans/CB-WP-0046-the-rule-the-placement-encodes.md
Normal file
|
|
@ -0,0 +1,128 @@
|
|||
---
|
||||
id: CB-WP-0046
|
||||
kind: product
|
||||
title: "The rule the placement encodes"
|
||||
status: done
|
||||
---
|
||||
|
||||
# Purpose
|
||||
|
||||
```
|
||||
structural tier S (one new edition reader, one rendered passage, one
|
||||
marker attribute -- no rule, no dependency moved)
|
||||
declared tier S
|
||||
```
|
||||
|
||||
Closes the two gaps [CB-WP-0045](CB-WP-0045-the-table-names-what-it-shows.md)
|
||||
named as *not done*.
|
||||
|
||||
## The gap, and the wrong reason given for it
|
||||
|
||||
CB-WP-0045 recorded:
|
||||
|
||||
> *"Nothing explains what a scope does … it is a `ground-game` question
|
||||
> first: the scope rule is ours (Variant), not the edition's, so there is
|
||||
> no vendored sentence to render."*
|
||||
|
||||
**The premise was false.** `editions/experiments/h2-scoped-problem-stress/`
|
||||
ships `Rules_Text.csv`, and its `Problems / Stress scope` passage is the
|
||||
rule verbatim:
|
||||
|
||||
> *"Each Problem has stress_scope. global: every seat. personal: the
|
||||
> assigned owner only. bond: the owner and every seat connected to the
|
||||
> owner through one or more Bonds (the Bond network). If the owner has no
|
||||
> Bonds, bond scope behaves as personal. Rivalries do not expand bond
|
||||
> scope. Multiple unclaimed Problems stack (+1 each) for seats in their
|
||||
> scopes."*
|
||||
|
||||
**Nothing in clay-borg had ever read the file.** Twenty-two passages of
|
||||
player-facing rules, in the repo, unreachable by a player — a whole
|
||||
rulebook, where CB-WP-0045 found single columns.
|
||||
|
||||
**Third instance of F18's shape in two passes**, and the largest. The
|
||||
pattern is now specific enough to name: *when a package adds a file rather
|
||||
than a column, nothing notices.* `edition-check` verifies the digest and
|
||||
freshness of files it knows; a file no reader mentions is not stale, it is
|
||||
invisible. Recorded as a finding for `ground-game` rather than fixed here.
|
||||
|
||||
**The escalation is the part worth keeping.** CB-WP-0045 did not just
|
||||
leave a gap; it *explained* the gap with an argument that would have
|
||||
stopped the next reader from looking. A wrong reason for an open item is
|
||||
worse than an open item, because it retires the question.
|
||||
|
||||
## The log said nothing about which rules were played
|
||||
|
||||
`2026-08-08-1734`: *"Well, i did not notice any difference, maybe i did
|
||||
not start the H2 variation?"* **The log cannot answer that** — and neither
|
||||
could we, a week later, from the file.
|
||||
|
||||
The variant rides the **begin marker**, not an eighth column:
|
||||
|
||||
```
|
||||
<!-- trial-log:begin variant=h2-scoped-problem-stress -->
|
||||
```
|
||||
|
||||
It is a property of the **session** (fixed at startup, constant across
|
||||
`play again`), so a per-row column would repeat one fact on every line and
|
||||
force a third accepted row width on a parser whose docstring is about
|
||||
exactly that hazard (CB-WP-0032). The table shape is untouched.
|
||||
|
||||
**Stamped from `state.variant`, never from the `--variant` flag.** Three
|
||||
call sites once wrote `state.variant = v` directly instead of
|
||||
`with_variant()`, which leaves H2 inert; a log stamped from the flag would
|
||||
have recorded `h2` for a session that played the baseline. **A false
|
||||
provenance on real player words is worse than no provenance** — which is
|
||||
also why an unstamped log reports `unrecorded` and not `ground-darvo-r0`.
|
||||
|
||||
## Task: render the rule, stamp the log
|
||||
|
||||
```task
|
||||
id: CB-WP-0046-T01
|
||||
status: done
|
||||
priority: high
|
||||
```
|
||||
|
||||
**Controls, all mutation-proven:**
|
||||
|
||||
| mutation | what went red |
|
||||
|---|---|
|
||||
| the scope rule never renders | *"Problems are placed by scope and nothing says what a scope does"* |
|
||||
| it renders always, baseline included | *"the baseline table explains a scope distinction that is not in play"* |
|
||||
| our paraphrase instead of the passage | *"the scope explanation is not the edition's own words"* |
|
||||
| the writer drops the attribute | *"the log does not say which rules were played"* |
|
||||
| unstamped parses as `ground-darvo-r0` | *"an unstamped log says NOTHING, not 'baseline'"* |
|
||||
| `BEGIN` back to an exact match | *"the bytes hotseat.rs writes are the bytes this parses"* |
|
||||
|
||||
**The last mutation is the finding.** It went green the first time. Every
|
||||
`trials.py` fixture composed its marker out of `BEGIN`, so all of them
|
||||
**followed `BEGIN` wherever it went** — including away from what
|
||||
`hotseat.rs` actually writes. Nine checks about the marker, and reverting
|
||||
the marker broke every real stamped log with all nine still green.
|
||||
|
||||
The format is shared across two languages, so the control has to be a
|
||||
**literal**: the exact bytes the writer emits, asserted from the reading
|
||||
side, with the writer's own test asserting the same string from the other.
|
||||
A fixture built from the constant under test cannot test the constant.
|
||||
|
||||
`stress_scope_rule()` matches on the **heading**, not on row 20 — a row
|
||||
number is a property of today's file, a heading is a property of the rule
|
||||
— and returns `None` if the edition stops carrying it (ADR-0018: an absent
|
||||
explanation is reported absent, never replaced by ours).
|
||||
|
||||
**Done 2026-08-08.** `make all` green; `cargo test`: 80 render + 35 play;
|
||||
24 `trials.py` checks. Verified on a live `make ground VARIANT=h2` page.
|
||||
|
||||
## Not done here
|
||||
|
||||
- **The other 21 passages are still unread.** `h2_rules_text()` returns
|
||||
the whole rulebook and one caller uses one row of it. The Round-step
|
||||
passages in particular are the account of the sequence the player is
|
||||
standing in, and there is nowhere on the page that says it.
|
||||
- **The baseline has no `Rules_Text.csv` at all**, so this explains only
|
||||
the experiment. A baseline player still gets no rulebook — the reverse
|
||||
of the usual gap, and a `ground-game` question.
|
||||
- **The 11 existing notes stay `unrecorded` forever.** Their variant was
|
||||
never written down; inventing one is the defect this pass exists to
|
||||
avoid. `2026-08-08-1818`'s three notes are almost certainly H2 on the
|
||||
internal evidence of what they say, and *almost certainly* is not a
|
||||
provenance.
|
||||
Loading…
Add table
Add a link
Reference in a new issue