v0.7.9.2 — two things the table could hear that only one seat should
Both leaks were found while planning the common board (Gitea#20 step 1), and both are live multiplayer bugs with or without that display, so they are fixed now rather than with 0.8.0. `game.log` is one shared list and `linesSince(seat)` slices it with no per-seat filter, so every line reaches every player. It carried the SEED in the opening line of each multiplayer game — the whole future of the deal — and the NAME OF A CARD DRAWN BLIND from the face-down Home Office deck. Solitaire deliberately keeps both: a one-seat table has nobody to leak to, the seed is what a bug report quotes, and a player's own history naming their own draw is the record. A Department slot is face up and stays named. The drawer still learns their card through `justDrawn`, which already goes to that seat alone. Neither was found by a test. Every test in `redaction.test.ts` passes an empty log, so the whole of narration has sat outside the redaction net since the net was built. Both now have tests there; TODO #91 carries what is still owed and supersedes #78, which described a gap that had already been closed and never mentioned this one. `docs/rules/` had no current description of the game, and `content.ts` named `card-reference.md` as the file that carries what the cards say — a file whose own banner says not to use its numbers, describing the v0.4.5 deck where 3/4 is a Mail-Express with three coaches. Every file in that directory is a deliberate historical record, so none of them is rewritten. `as-built.md` is new and GENERATED from the same catalogues the engine instantiates from, with a test that re-runs the generator and fails when the checked-in file disagrees. A hand-written replacement would have drifted the same way, for the same reason. TODO.md: #32 closed — the playtest migration note did its job and the jump is made; the durable fact it carried is kept. #78 retired in favour of #91. The "play it at a table" section now records that 0.7.4-0.7.9 were test-run without change requests, and that more testing comes at the end of the 0.7.9 series. 897 tests pass, up from 891. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01E3Qk7uresKCHksdZajXCLg
This commit is contained in:
co-authored by
Claude Opus 5
parent
7ade60e21f
commit
819996faa2
@@ -74,8 +74,8 @@ Not items. Things that are true of every change, and that have gone wrong when s
|
||||
|
||||
## Sections
|
||||
|
||||
1. **Play it at a table** — #39 #35 #42a #40 #32
|
||||
2. **The common board, and watching play happen — Gitea#20** — #13 #15 #18 #78 #75
|
||||
1. **Play it at a table** — #39 #35 #42a #40
|
||||
2. **The common board, and watching play happen — Gitea#20** — #13 #15 #18 #91 #75
|
||||
3. **Multiplayer, sessions and operations** — #8 #7 #76 #77 #79
|
||||
4. **The screen** — #44 #81 #33 #36
|
||||
5. **Replays and saved games** — #14 #47 #48 #49 #50 #51 #52
|
||||
@@ -94,8 +94,14 @@ ruling or a lesson).
|
||||
## Play it at a table
|
||||
|
||||
The largest gap in the project, and none of it is a coding gap. Features are shipped, packed,
|
||||
running on `phoenix.local` — and no person has met them at a board. Everything else in this file
|
||||
waits behind a release; this waits behind an afternoon.
|
||||
running on `phoenix.local` — and the items below name the ones no person has met at a board.
|
||||
Everything else in this file waits behind a release; this waits behind an afternoon.
|
||||
|
||||
**Test runs WERE made across 0.7.4 through 0.7.9** (Jesse, 2026-09-07) and produced no change
|
||||
requests — the two bugs that did come out of them are Gitea#21 and #22, fixed in v0.7.9.1. So this
|
||||
section is not "nobody has touched it since 0.7.4"; it is the narrower and still-true claim that the
|
||||
specific paths below have not been exercised at a table. **More testing is planned at the end of the
|
||||
0.7.9 series, before 0.8.0 starts** — that is the moment to close these, not a separate errand.
|
||||
|
||||
- [ ] **#39** — **None of v0.7.4 has been played by a human.** The Yard Office offer, the Red Flag
|
||||
hold and its out-of-phase prompt, and the loaded-Extra make-up rules are tested end to end,
|
||||
@@ -118,11 +124,6 @@ waits behind a release; this waits behind an afternoon.
|
||||
in a release note rather than code, and worth knowing when a bug report arrives with a save that
|
||||
will not load. See **Reference · #40**.
|
||||
|
||||
- [ ] **#32** — **Tell the 0.4.9 playtesters their saves are dead, before they find out.** The same
|
||||
shape as #40 for the playtest line; the saves attached to Gitea#15 and #17 are among them.
|
||||
`PLAYTEST-0.7.4.md` at the repo root is the note drafted for this and leads with it. See
|
||||
**Reference · #32**.
|
||||
|
||||
---
|
||||
|
||||
## The common board, and watching play happen — Gitea#20
|
||||
@@ -148,8 +149,16 @@ cheaper.
|
||||
it needs the async stepped pump that Gitea#20 step 4 specifies**, which is why it lives here
|
||||
rather than under The screen. See **Reference · #18**.
|
||||
|
||||
- [ ] **#78** — The redaction test is more done than the plan suggests, but the remaining gap is real
|
||||
and is Gitea#20 step 1's starting point. See **Reference · #78**.
|
||||
- [ ] **#91** — **Narration is still outside the redaction net, and the two known leaks in it are
|
||||
fixed but the net is not.** `game.log` is one shared list that `linesSince` slices with no
|
||||
per-seat filter, so anything written into it reaches every player. The seed and the blind-draw
|
||||
card name were closed in v0.7.9.2; what has NOT been done is the systematic check the plan
|
||||
asks for — serialise the log alongside the Frame and search it for every opponent's card ids
|
||||
AND display names, objective names, `justDrawn` for the wrong seat, and private decision data,
|
||||
across a fresh game, a pending decision, the Superintendent acting, Employee Rotation, a
|
||||
reconnect and a finished game. **This is Gitea#20 step 1's starting point and its acceptance
|
||||
bar** — the plan is explicit that passing redaction tests alone is insufficient and that every
|
||||
public property needs an allow-list review. See **Reference · #91**.
|
||||
|
||||
- [ ] **#75** — Let the game join a call and talk to the table — the chat, audio and nudge half of the
|
||||
idea Gitea#20 took the visual half of. Long-term. See **Reference · #75**.
|
||||
@@ -453,14 +462,6 @@ the move and leaves the file untouched — and `WHISTLE-4086` did survive on `ph
|
||||
is "may not" rather than "will not". Worth a line wherever the build is announced, and worth
|
||||
knowing when a bug report arrives with a save that will not load.
|
||||
|
||||
#### #32 — Tell the 0.4.9 playtesters their saves are dead, before they find out.
|
||||
|
||||
**Tell the 0.4.9 playtesters their saves are dead, before they find out.** The same shape as #40
|
||||
but for the playtest line: the deck change shipped as v0.4.9h, so every save filed before it —
|
||||
including the ones attached to Gitea#15 and #17 — stops replaying at its first `card.play`. They
|
||||
fail safe and the files are kept, but nobody has been told. `PLAYTEST-0.7.4.md` (untracked, at
|
||||
the repo root) is the note drafted for this and leads with it.
|
||||
|
||||
### The common board, and watching play happen — Gitea#20
|
||||
|
||||
#### #13 — I CANNOT SEE WHAT THE OTHER PLAYERS DID — BOTS INCLUDED.
|
||||
@@ -582,22 +583,41 @@ of enforced waiting per Stage, forty-eight per Day, and a player who has seen it
|
||||
will want it off. Whatever this becomes probably needs a speed control, or to scale with whether
|
||||
anything actually happened in the phase.
|
||||
|
||||
#### #78 — The redaction test (multiplayer.md §7) is more done than the plan sugg…
|
||||
#### #91 — NARRATION IS OUTSIDE THE REDACTION NET.
|
||||
|
||||
**The redaction test (multiplayer.md §7) is more done than the plan suggests, but the
|
||||
**NARRATION IS OUTSIDE THE REDACTION NET.** `test/redaction.test.ts` serialises a seat's whole
|
||||
|
||||
exhaustive check is still missing.** `test/multiplayer.test.ts`'s "the view shows one seat at
|
||||
a time" section (added earlier) already proves `snapshot(s, ..., viewer)` gives each seat its
|
||||
own hand, board, Revenue and impediments — traced `snapshot()` itself
|
||||
(`src/sim/view.ts:1180-1219`): `hand` reads only `s.decks.hands.get(viewer)`, `deck` is a
|
||||
count, other seats' hands appear only as `.length`, and `Frame`'s type has no `seed`,
|
||||
`rngState` or card-id-dictionary field for anything to leak through by accident. What exists
|
||||
is all spot-checks, though — "this seat's Frame has the right hand length." What's still
|
||||
missing is the exhaustive one §7 actually calls for: serialize a seat's `Frame` and assert it
|
||||
contains none of another seat's actual card ids and no deck order, so a future careless edit
|
||||
is caught rather than assumed safe. Doesn't need a server — buildable now against `snapshot()`
|
||||
and the existing `game()`/`playGame` harness already in `multiplayer.test.ts`. Held for now,
|
||||
2026-08-20.
|
||||
`Frame` and asserts no other seat's card ids or deck order appear in it — and every one of those
|
||||
tests passes `[]` for the log. So the shared narration has never been checked at all, while
|
||||
`game.log` is ONE list and `linesSince(seat)` (`server/session.ts:181`) slices it with no per-seat
|
||||
filter whatsoever. Every line written there reaches every player.
|
||||
|
||||
**Two leaks found and closed in v0.7.9.2**, both discovered while planning Gitea#20 and both live in
|
||||
multiplayer with or without that display: the **seed**, announced in the opening line of every
|
||||
multiplayer game, and the **name of a card drawn blind** from the Home Office deck. The tests for
|
||||
them are in `redaction.test.ts` now, so narration is no longer entirely unchecked — but two specific
|
||||
strings are not a net.
|
||||
|
||||
**Solitaire deliberately keeps both**, and that is the rule to apply to anything found next: a
|
||||
one-seat table has nobody to leak to, the seed in the log is what a bug report quotes, and a solo
|
||||
player's own history naming their own draw is the record. The rule is "do not tell the OTHER seats",
|
||||
not "write less down".
|
||||
|
||||
**What is still owed** is the plan's own list (`docs/plans/jitsi-common-board.md`, Step 1 § Tests):
|
||||
serialise the public frame *and* the player pushes and search for every opponent hand-card id **and
|
||||
display name**, objective ids and names, `justDrawn` for the wrong player, seed values and seed
|
||||
narration, and private decision/menu data — across a newly created game, a blind draw, a pending
|
||||
decision, the Superintendent acting, Employee Rotation before and after ownership changes, a
|
||||
reconnect push, and a finished game. **And the plan's acceptance bar is not the tests**: it requires
|
||||
an allow-list review of every public property, on the grounds that passing redaction tests alone is
|
||||
insufficient. That is the right bar — the two leaks above would have passed any test nobody thought
|
||||
to write.
|
||||
|
||||
**Supersedes #78**, which said the exhaustive Frame check was "still missing… held for now,
|
||||
2026-08-20". It is not missing: `test/redaction.test.ts` exists and does exactly what #78 described
|
||||
— serialise a seat's Frame, assert no other seat's card ids and no deck order. #78 was written
|
||||
before that file and was never revisited, so it read as live work for two weeks after it was done.
|
||||
**The gap that is actually real is the log, which #78 never mentioned.**
|
||||
|
||||
#### #75 — Let the game join a call and talk to the table.
|
||||
|
||||
@@ -1729,11 +1749,43 @@ re-verified turn out to have been re-verified against a premise rather than agai
|
||||
Closed items, kept because several are the only record of a ruling or a lesson. Newest first within
|
||||
each group.
|
||||
|
||||
### Shipped through v0.7.9.1, from the queue
|
||||
### Shipped through v0.7.9.2, from the queue
|
||||
|
||||
Closed items, newest first. Kept because several of them are the only record of a ruling or a lesson;
|
||||
the numbers stay so cross-references above and below still resolve.
|
||||
|
||||
32. ~~**Tell the 0.4.9 playtesters their saves are dead, before they find out.**~~ — done
|
||||
2026-09-07. `PLAYTEST-0.7.4.md` was written for exactly this and did its job; Jesse, 2026-09-07:
|
||||
"a temporary document to help some of the playtesters out on making the big jump, but that is no
|
||||
longer needed." The jump is made, so the note is retired rather than committed. **The durable
|
||||
fact, which is why this entry stays:** a save written by v0.4.9h does not replay on 0.7.x — the
|
||||
deck changed, so it stops at its first `card.play` — and that includes the saves attached to
|
||||
Gitea#15 and #17. It fails safe, naming the move and leaving the file untouched, so a bug report
|
||||
arriving with a save that will not load is this and not a new fault. #40 is the same shape on the
|
||||
main line and is still open.
|
||||
|
||||
92. ~~**Two multiplayer information leaks in the shared narration log.**~~ — done 2026-09-07 in
|
||||
v0.7.9.2, found while planning Gitea#20 step 1. The **seed** was announced in the opening line of
|
||||
every multiplayer game and a **blind Home Office draw named the card** — and `linesSince(seat)`
|
||||
slices one shared `game.log` with no per-seat filter, so both went to every player. **Ruling:
|
||||
solitaire keeps both**, because a one-seat table has nobody to leak to, the seed is what a bug
|
||||
report quotes, and a solo player's history naming their own draw is the record. A Department
|
||||
slot is face up and stays named for the same reason. **Worth knowing:** these were not found by
|
||||
a test, they were found by reading the plan — every redaction test passes `[]` for the log, so
|
||||
the whole of narration was unchecked. #91 is what remains.
|
||||
|
||||
93. ~~**`docs/rules/` had no current description of the game, and the code pointed at a superseded
|
||||
one.**~~ — done 2026-09-07 in v0.7.9.2. `content.ts` named `card-reference.md` as "the place
|
||||
that now carries what the cards say" while that file's own banner said not to use its numbers;
|
||||
it describes the v0.4.5 deck, where 3/4 is a Mail-Express with three coaches against a `content.ts`
|
||||
whose train 3 is the Express with two freight cars. **The fix is not a rewritten table** — every
|
||||
file in `docs/rules/` is a deliberate historical record and worth more intact than patched. A new
|
||||
`as-built.md` is GENERATED from the same catalogues the engine instantiates from, by
|
||||
`scripts/build-card-reference.ts` (`npm run build:cards`), and `test/card-reference.test.ts`
|
||||
re-runs the generator and fails if the checked-in file disagrees. **Worth knowing:** a
|
||||
hand-written replacement would have drifted the same way and for the same reason — nothing fails
|
||||
when a table falls behind a constant. Generate it or check it; do not retype it.
|
||||
|
||||
89. ~~**The map drew westbound trains in the wrong half of a Mainline card.**~~ — done 2026-09-07 in
|
||||
v0.7.9.1, Gitea#22. `regionOfTransit` counts from the end a train ENTERED, which is what the
|
||||
collision rules want; the map wanted "which printed box, left to right" and used the same number,
|
||||
|
||||
Reference in New Issue
Block a user