diff --git a/Makefile b/Makefile index e97e91a..0d2db3a 100644 --- a/Makefile +++ b/Makefile @@ -31,6 +31,10 @@ TOOLS := $(REPO)/tools # reads the age from there (falling back to mtime). TRIAL_NAME := $(shell date +%Y-%m-%d-%H%M)$(if $(SLUG),-$(SLUG),) PLAYERS ?= 3 +# CB-WP-0044: which rules package to play. The page names it too -- +# a session that could not say which variant it was is what produced +# the report "I did a session and noted no changes". +VARIANT ?= ground-darvo-r0 PORT ?= 0 # Every cargo recipe runs at the repo root; the shell does not persist cd. @@ -68,11 +72,13 @@ help: ## type in the notes panel is bound to the position you typed it at. ## `make ground PLAYERS=2 SLUG=darvo-confusion` ## Read the notes back afterwards with `make trials`. +## play a session (VARIANT=ground-darvo-r0|h1|h2) ground: + @echo " rules: $(VARIANT)" @mkdir -p $(REPO)/trials @echo " trial: trials/$(TRIAL_NAME).md (notes) + .yaml (the game)" $(IN_REPO) $(CARGO) run -q -p cb-play -- \ - --players $(PLAYERS) --serve $(PORT) \ + --players $(PLAYERS) --serve $(PORT) --variant $(VARIANT) \ --record trials/$(TRIAL_NAME).yaml \ --trial trials/$(TRIAL_NAME).md $(ARGS) diff --git a/crates/cb-render-html/src/doc.rs b/crates/cb-render-html/src/doc.rs index e04d4c1..da3e62a 100644 --- a/crates/cb-render-html/src/doc.rs +++ b/crates/cb-render-html/src/doc.rs @@ -1044,11 +1044,17 @@ pub fn document_with_log( "

GROUND \u{2014} round {round}, step {step:?}

\
lead {lead} \ scoring {mode:?} \ + rules {variant} \ viewing as {who}
", round = view.round, step = view.step, lead = seat_name(view.lead), mode = view.mode, + // CB-WP-0044: the page must say which rules it is playing. It did + // not, so a player who ran the default and was told the layout had + // changed reported "no changes" — correctly, because the baseline + // is deliberately unchanged and nothing on screen said so. + variant = esc(view.variant.id()), who = match view.viewer { Some(p) => format!("{} (their hand only)", seat_name(p)), None => "a spectator (no hands)".to_string(), diff --git a/crates/cb-render-html/src/lib.rs b/crates/cb-render-html/src/lib.rs index efacefd..0172281 100644 --- a/crates/cb-render-html/src/lib.rs +++ b/crates/cb-render-html/src/lib.rs @@ -187,6 +187,7 @@ mod coverage { // that could only be satisfied by geometry would have to be // OMITTED, and the page would be illegible to `text_of` and to a // screen reader alike. + ("variant", "ground-darvo-r0"), ("problem_markers.*.owner", "P1\u{2019}s alone"), ("problem_markers.*.scope", "P2\u{2019}s Bond network"), ("outcome.total", "total 9"), diff --git a/crates/cb-render-html/src/testfix.rs b/crates/cb-render-html/src/testfix.rs index 1ebb887..4610eab 100644 --- a/crates/cb-render-html/src/testfix.rs +++ b/crates/cb-render-html/src/testfix.rs @@ -82,6 +82,7 @@ pub fn view(viewer: Option) -> GroundView { (Pair::new(p2, p3), Relation::Bond), ]), problems, + variant: games_ground::Variant::Baseline, focus: BTreeMap::from([(p1, p3)]), selections: BTreeMap::from([ ( diff --git a/games/ground/src/view.rs b/games/ground/src/view.rs index 02e6832..e5e8ac5 100644 --- a/games/ground/src/view.rs +++ b/games/ground/src/view.rs @@ -41,6 +41,13 @@ pub struct GroundView { pub lead: PlayerId, pub step: RoundStep, pub mode: ScoringMode, + /// Which rules package is being played (CB-WP-0044). + /// + /// **The page had no way to say this**, so a player could not tell + /// baseline from H1 from H2 by looking — and reported a variant + /// change as "no changes" after playing the default. + #[serde(default)] + pub variant: crate::Variant, pub players: BTreeMap, pub relations: BTreeMap, pub problems: BTreeMap, @@ -170,6 +177,7 @@ impl Project for GroundState { lead: self.lead, step: self.step, mode: self.mode, + variant: self.variant, players: self .players .iter() diff --git a/tools/cb-play/src/inspect.rs b/tools/cb-play/src/inspect.rs index 1ede001..827d465 100644 --- a/tools/cb-play/src/inspect.rs +++ b/tools/cb-play/src/inspect.rs @@ -140,11 +140,12 @@ fn render_player(id: PlayerId, p: &PlayerView, is_viewer: bool) -> String { pub fn render(view: &GroundView) -> String { let mut out = String::new(); out.push_str(&format!( - "\nround {} step {:?} lead {} mode {:?} deck {} discard [{}]\n", + "\nround {} step {:?} lead {} mode {:?} rules {} deck {} discard [{}]\n", view.round, view.step, seat_name(view.lead), view.mode, + view.variant.id(), view.solution_deck_len, cards(&view.solution_discard), )); @@ -493,6 +494,9 @@ mod tests { ("step", "step Resolve"), ("lead", "lead P2"), ("mode", "mode BondedCoalitions"), + // CB-WP-0044: the inspector must say which rules it is replaying, + // for the same reason the page must. + ("variant", "rules ground-darvo-r0"), ("viewer", "(you)"), ("solution_deck_len", "deck 11"), ("solution_discard.*.suit", "discard [Repair, Change]"), @@ -617,6 +621,7 @@ mod tests { ]), problems, problem_markers: Default::default(), + variant: games_ground::Variant::Baseline, focus: BTreeMap::from([(p1, p3)]), selections: BTreeMap::from([ ( diff --git a/trials/2026-08-08-1734.md b/trials/2026-08-08-1734.md new file mode 100644 index 0000000..056e522 --- /dev/null +++ b/trials/2026-08-08-1734.md @@ -0,0 +1,18 @@ +# Trial log + +What the player said while playing, bound to the position they said it at +(CB-WP-0027, ADR-0014). The recording beside this file is the position; +`state_hash` is what reaches it. + +**These are raw notes and they stay here.** Nothing in this file travels to +`ground-game` (ADR-0014 D4) — a note reaches them only by being promoted to a +register finding, by a human, with the wording chosen then. + + + +| n | game | after | round | step | state_hash | comment | +|---|---|---|---|---|---|---| +| 1 | 1 | 0 | 1 | Select | 39c2ed586d57 | Ok, all problems are on the table, so they are all global? | +| 2 | 1 | 32 | 5 | after the end | c852f3b15ee8 | Well, i did not notice any difference, maybe i did not start the H2 variation? | + + diff --git a/trials/2026-08-08-1734.yaml b/trials/2026-08-08-1734.yaml new file mode 100644 index 0000000..1e27ee1 --- /dev/null +++ b/trials/2026-08-08-1734.yaml @@ -0,0 +1,149 @@ +scenario: ground/cb-play-session +description: recorded by cb-play (CB-WP-0008 T02) +covers: [] +provisional: false +provisional_owner: '' +provisional_raised: '' +ruled: '' +ruled_by: '' +ruled_note: '' +encodes_u_item: '' +seed: 1 +setup: + players: 3 + preset: standard-3p + patch: {} +commands: +- actor: P1 + cmd: select_action + args: + action: INVESTIGATE + problem: 2 +- actor: P2 + cmd: select_action + args: + action: SOLVE + problem: 1 +- actor: P3 + cmd: select_action + args: + action: SOLVE + problem: 1 +- actor: SYSTEM + cmd: reveal + args: {} +- actor: SYSTEM + cmd: resolve + args: {} +- actor: SYSTEM + cmd: end_round + args: {} +- actor: P1 + cmd: select_action + args: + action: INVESTIGATE + problem: 3 +- actor: P2 + cmd: select_action + args: + action: INVESTIGATE + problem: 3 +- actor: P3 + cmd: select_action + args: + action: INVESTIGATE + problem: 3 +- actor: SYSTEM + cmd: reveal + args: {} +- actor: SYSTEM + cmd: resolve + args: {} +- actor: SYSTEM + cmd: end_round + args: {} +- actor: P1 + cmd: select_action + args: + action: SOLVE + problem: 2 +- actor: P2 + cmd: select_action + args: + action: INVESTIGATE + problem: 4 +- actor: P3 + cmd: select_action + args: + action: SOLVE + problem: 2 +- actor: SYSTEM + cmd: reveal + args: {} +- actor: SYSTEM + cmd: resolve + args: {} +- actor: SYSTEM + cmd: end_round + args: {} +- actor: P1 + cmd: select_action + args: + action: SOLVE + problem: 3 +- actor: P2 + cmd: select_action + args: + action: SOLVE + problem: 3 +- actor: P3 + cmd: select_action + args: + action: SOLVE + problem: 4 +- actor: SYSTEM + cmd: reveal + args: {} +- actor: SYSTEM + cmd: resolve + args: {} +- actor: SYSTEM + cmd: end_round + args: {} +- actor: P1 + cmd: select_action + args: + action: SUPPORT + target: P2 +- actor: P2 + cmd: select_action + args: + action: SUPPORT + target: P1 +- actor: P3 + cmd: select_action + args: + action: SUPPORT + target: P1 +- actor: SYSTEM + cmd: reveal + args: {} +- actor: P1 + cmd: respond_to_support + args: + response: accept_bond +- actor: P2 + cmd: respond_to_support + args: + response: accept_bond +- actor: SYSTEM + cmd: resolve + args: {} +- actor: SYSTEM + cmd: end_round + args: {} +expect: + events: [] + state: {} + rejects: [] + state_hash: c852f3b15ee8a8e68f0cecfa3c4a7dd7f1b3413a1b90df496e9418d121e6d9a4 diff --git a/workplans/CB-WP-0044-the-page-says-which-rules-it-plays.md b/workplans/CB-WP-0044-the-page-says-which-rules-it-plays.md new file mode 100644 index 0000000..976b445 --- /dev/null +++ b/workplans/CB-WP-0044-the-page-says-which-rules-it-plays.md @@ -0,0 +1,75 @@ +--- +id: CB-WP-0044 +kind: product +title: "The page says which rules it plays" +status: done +--- + +# Purpose + +``` +structural tier M (adds a field to the projection, a canonical + interface, and a driver knob) +declared tier M +``` + +## The report + +> *"I did a session and noted no changes."* + +**Correct, and the fault was ours twice over.** + +`make ground` passes no `--variant`, so the session was **baseline** — and +CB-WP-0043 deliberately leaves the baseline layout untouched, because a +variant that redraws the baseline invalidates every prior look at it. + +**But the deeper defect is that nothing said so.** The page named the +round, the step, the Lead, the scoring mode and the viewer — **and never +which rules it was playing.** `GroundView` did not even carry the variant. +There was no way, from the screen, to tell baseline from H1 from H2. + +> **A session that cannot say which rules it is playing cannot report a +> rules change.** The player did the right thing and the instrument had +> nothing to tell them. + +## Task: say it, and make it reachable + +```task +id: CB-WP-0044-T01 +status: done +priority: high +``` + +**Controls:** +- **the page names the variant**, beside the scoring mode where a player + already looks for what game this is; +- **the inspector names it too** — a replay that cannot say which rules + produced it is the same defect in the other tool; +- **`make ground` can select it**, or the capability exists and nobody + can reach it; +- **verified end to end against a served page**, not by reading the code. + +**Done 2026-08-08.** + +`variant` on `GroundView`, `rules ` in the header, `rules ` in the +inspector, and `make ground VARIANT=h2`. + +**Both coverage probes caught the new field independently** — the render +crate's and `cb-play`'s — which is the second time in two passes that the +probes have turned an addition into a legibility requirement rather than +letting it be silent state. + +**Verified by fetching the served page**: `make ground VARIANT=h2` prints +`rules: h2`, and the page carries `rules h2-scoped-problem-stress` plus +the scope labels. The baseline page says `rules ground-darvo-r0` and keeps +its row, which is the behaviour CB-WP-0043 intended and could not +previously be told apart from a bug. + +## What this does not fix + +- **Nothing on the page explains what a scope does.** It says *whose* a + Problem is; it does not say that an unclaimed personal card ticks only + its owner at Round End. H2's `Rules_Text.csv` is vendored and unread. +- **The variant is not in the trial log's header**, so a note written + during an H2 session does not record which rules it was about. That is + the same class of defect as this one, one artifact along.