v0.7.9.3 — the reference says what only the code knows, and saves get a rule
The generated card reference now carries the half TODO #15a said was the point of generating it: every Enhancement's `live` / `dormantSolo` / `unbuilt` status — whether its printed effect actually resolves yet — and the opponent-directed Action and Space-use cards, none of which is dealt in any deck. A transcription cannot carry either fact. Card counts are removed throughout, as ruled: they move with play balance so a document printing them is stale on the next retune. Where a count matters it is a yes/no "is this dealt at all", which is a fact about the design rather than the current tuning. #88 closes with it — it asked whether `card-reference.md`'s industry rows were stale, deliberately without rewriting them since Laborer counts are a balance decision. They are; nothing in the engine changed; that file is simply no longer where anyone looks. The balance question it guarded is #70. Save compatibility becomes a general rule in `README.md` § Design notes rather than a fact restated per version: a save is a list of moves and reopens by being re-played through the CURRENT rules, so any change that makes a once-legal move illegal stops an older one there — a deck change being the likeliest breaker. It fails safe every time. #40 generalised, #32's version-specific note dropped, #52 carries the ruling that versioned replays are a post-1.0 question. #94 opened: a Red Flag set out at an Office's Limits holds the next train from that side and is drawn nowhere. `DivisionView`'s office node has no `redFlag` field and `board-svg.ts` never mentions one, so after the single log line announcing it there is nothing on screen. Same class as Gitea#21 and #22, and already on the common board's step 1 list. No engine change. 897 tests pass, unchanged. 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
819996faa2
commit
e734481d65
@@ -77,7 +77,7 @@ Not items. Things that are true of every change, and that have gone wrong when s
|
||||
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
|
||||
4. **The screen** — #94 #44 #81 #33 #36
|
||||
5. **Replays and saved games** — #14 #47 #48 #49 #50 #51 #52
|
||||
6. **Rules** — #12 #80 #82 #83 #85
|
||||
7. **Play balance** — #61 #62 #63 #64 #67 #68 #69 #70 #71 #72 #73 #66 #65 #74
|
||||
@@ -119,10 +119,10 @@ specific paths below have not been exercised at a table. **More testing is plann
|
||||
the dealt game matches what was chosen. It took three attempts to become reachable at all —
|
||||
reachable is not the same as correct. See **Reference · #42a**.
|
||||
|
||||
- [ ] **#40** — **A save from before v0.7.4 may not replay, and nobody has been told.** It fails safe
|
||||
— the server declines the save, names the move and leaves the file untouched — so this is a line
|
||||
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**.
|
||||
- [ ] **#40** — **An older save may not replay, and players are not told so anywhere they will see
|
||||
it.** Not a v0.7.4 fact and not a bug: a save is re-played through the current rules, so any
|
||||
narrowing of what is legal can stop one. The rule is written down now (`README.md` § Design
|
||||
notes); what is still owed is a line **wherever a build is announced**. See **Reference · #40**.
|
||||
|
||||
---
|
||||
|
||||
@@ -195,6 +195,12 @@ happening, and the turn structure that is still solitaire-shaped.
|
||||
What is drawn and where, for a player at the board. The three items settled on 2026-08-30 shipped in
|
||||
v0.7.9; what is left is the history panel and the end-of-game statistics.
|
||||
|
||||
- [ ] **#94** — **A Red Flag standing at an Office's Limits is drawn nowhere.** It is set out on the
|
||||
board, it holds the next train from that side, and after the one log line announcing it there is
|
||||
nothing on screen saying it is there. Confirmed in code rather than inferred. **The same class
|
||||
as Gitea#21 and #22 — the engine is right and the screen is silent — and it is already on
|
||||
Gitea#20 step 1's list, so doing it now is 0.8.0 groundwork.** See **Reference · #94**.
|
||||
|
||||
- [ ] **#44** — How much history the panel holds should be configurable. The cap is `slice(-60)` with
|
||||
no recorded reason anywhere. **Where the setting lives is an open question and the item exists
|
||||
to ask it** — a StartOS action, per game, or per browser. The replay viewer already answers the
|
||||
@@ -455,12 +461,26 @@ below); reachable is not the same as correct. Early item for the next play sessi
|
||||
|
||||
#### #40 — A save from before v0.7.4 may not replay, and nobody has been told.
|
||||
|
||||
**A save from before v0.7.4 may not replay, and nobody has been told.** The Red Flags intent
|
||||
changed shape, a make-up that was legal may now be refused, and a Yard Office arrival asks a
|
||||
question no older history has an answer for. It fails safe — the server declines the save, names
|
||||
the move and leaves the file untouched — and `WHISTLE-4086` did survive on `phoenix.local`, so it
|
||||
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.
|
||||
**An older save may not replay, and players are not told so anywhere they will see it.** A save is
|
||||
a list of moves and reopens by being re-played through the CURRENT rules, so any change that makes a
|
||||
once-legal move illegal stops it there. **A deck change is the likeliest breaker** — a history
|
||||
naming a card the deck no longer deals has no legal answer at all — but any narrowing does it. This
|
||||
is the design working, not a fault: it fails safe every time, declining the load, naming the move
|
||||
and leaving the file untouched.
|
||||
|
||||
**So this item is no longer "saves before v0.7.4"** and should never be restated per version
|
||||
(Jesse, 2026-09-07). The specific 0.7.4 breakages — the Red Flags intent changing shape, a make-up
|
||||
that was legal being refused, a Yard Office arrival asking a question no older history answers —
|
||||
are recorded here as the ORIGIN of the rule rather than as the rule, and `WHISTLE-4086` did survive
|
||||
on `phoenix.local`, which is why it is "may not" rather than "will not".
|
||||
|
||||
**What is actually owed:** the general rule is written down in `README.md` § Design notes, and a
|
||||
line belongs wherever a build is announced. Nothing in code.
|
||||
|
||||
**Versioned, migratable replays are a post-1.0 question, deliberately deferred** (Jesse,
|
||||
2026-09-07): "once we get to a solid 1.0 release we will consider a system to version the replays so
|
||||
they are not as fragile — but not worth any effort right now." The reason it would be wasted effort
|
||||
now is that every migration would be written against rules that change again next release.
|
||||
|
||||
### The common board, and watching play happen — Gitea#20
|
||||
|
||||
@@ -782,6 +802,39 @@ and whether they took it the moment their turn arrived.
|
||||
|
||||
### The screen
|
||||
|
||||
#### #94 — A RED FLAG STANDING AT THE LIMITS IS DRAWN NOWHERE.
|
||||
|
||||
**A RED FLAG STANDING AT AN OFFICE'S LIMITS IS DRAWN NOWHERE.** Found 2026-09-07 while checking
|
||||
|
||||
which of the Gitea#20 step 1 findings were still real. It is real, and it is a play bug now rather
|
||||
than a common-board one.
|
||||
|
||||
**What the engine does**, traced rather than assumed. `maneuver.redFlags` emits `redFlagsSet`, whose
|
||||
reducer sets `node.redFlag = side` on that Office's Division node (`apply.ts:2307`). From then on
|
||||
`redFlagStop` holds the next train arriving from that side — `dest.redFlag === from` → `spendFlag`,
|
||||
which removes the flag and emits `redFlagSpent` (`advance.ts:1216, 1173`). So it is a standing token
|
||||
on the board that stops a train, exactly as a flag on the table would be.
|
||||
|
||||
**What the screen does.** `narrate` announces it once — "RED FLAGS set out on the Eastern Limits" —
|
||||
and then it is gone with the scroll. The Office node in `DivisionView` carries `kind`, `label`,
|
||||
`trains`, `capacity`, `modifiers`, `gradeUp`, `seat`, `running` and `switching`, and **no `redFlag`
|
||||
field at all**; `redFlag` appears nowhere in `board-svg.ts` and nowhere in the web layer. The map
|
||||
draws the Office, its A/D tracks and the trains standing on it, and not the flag at its Limits.
|
||||
|
||||
**So a player who set a flag out three Stages ago has nothing telling them it is still there, and an
|
||||
opponent who missed the line never knew.** Then a train stops short, and the only explanation is a
|
||||
log entry that has scrolled away. That is the shape of Gitea#21 — a correct refusal with no visible
|
||||
reason — and of Gitea#22 — a board that does not show what the rules are acting on.
|
||||
|
||||
**Why it belongs before 0.8.0 rather than in it:** the plan already lists "add the Red Flag holder to
|
||||
the public player projection — it is public game state but is currently absent from `Frame`" as part
|
||||
of step 1. The field has to exist on the projection either way, so every hour spent on it is 0.8.0
|
||||
groundwork rather than a detour. **The drawing is the open question, not the data** — a flag at the
|
||||
Limits column is the obvious rendering, and `board-svg.ts` already draws those edges (`edge()`), so
|
||||
there is somewhere to hang it.
|
||||
|
||||
**Not fixed. Sized: small on the data, a judgement call on the picture.**
|
||||
|
||||
#### #44 — The history panel's 60-line cap is hard-coded, and how much history it…
|
||||
|
||||
**The history panel's 60-line cap is hard-coded, and how much history it holds should be
|
||||
@@ -995,6 +1048,17 @@ bitten once**: both published replays were dead — one got 42 intents into 360,
|
||||
carry a ruleset stamp and the page should say "this replay was recorded under an older
|
||||
ruleset and stops at Stage N" rather than presenting a truncated game as a whole one.
|
||||
|
||||
**THE FULL FIX IS DEFERRED PAST 1.0, ON JESSE'S CALL 2026-09-07:** "once we get to a solid 1.0
|
||||
release we will consider a system to version the replays so they are not as fragile — but not worth
|
||||
any effort right now." The reason is sound and worth keeping: every migration would be written
|
||||
against rules that change again the next release, so the work would be redone rather than reused.
|
||||
|
||||
**What that ruling does NOT defer is the honesty.** A truncated replay presented as a whole game is
|
||||
a wrong answer, not a missing feature, and saying "this stops at Stage N" needs no version stamp at
|
||||
all — `fromSave` already knows how many intents it replayed of how many it was given
|
||||
(`session.ts:454` reports exactly that for multiplayer). That half is small and stands alone. The
|
||||
general rule now lives in `README.md` § Design notes; #40 is the "tell the players" half.
|
||||
|
||||
### Rules
|
||||
|
||||
#### #12 — PARTLY REPRODUCED: "when I back up to collect standing cars and, furth…
|
||||
@@ -1685,9 +1749,20 @@ counts move with play balance, so a document that prints them is stale on the ne
|
||||
same rule was applied to `content.ts`'s own comments on 2026-08-22 — see the pass recorded in
|
||||
CHANGELOG for what came out and what was kept.
|
||||
|
||||
Not started. Worth deciding first whether this is a build step writing Markdown into `docs/`,
|
||||
or a page on the site beside the replay viewer — the site can render it from the same view-model
|
||||
the game uses, which argues for the second.
|
||||
**BUILT 2026-09-07 in v0.7.9.2, completed in v0.7.9.3, as the first of the two options** — a build step writing Markdown,
|
||||
`scripts/build-card-reference.ts` → `docs/rules/as-built.md`, with `test/card-reference.test.ts`
|
||||
re-running the generator and failing when the checked-in file disagrees. All six sections are
|
||||
there, and so is the honesty column: every Enhancement carries its `live` / `dormantSolo` /
|
||||
`unbuilt` status, and the opponent-directed cards say plainly that none of them is dealt.
|
||||
**The counts are omitted as ruled** — where a count matters it is rendered as a yes/no "is this
|
||||
dealt at all", which is a fact about the design rather than about the current tuning.
|
||||
|
||||
**WHAT REMAINS, and it is the second option rather than a gap in the first:** a page on the site,
|
||||
beside the replay viewer, rendered from the same view-model the game uses. The argument for it is
|
||||
unchanged — a player cannot read a file in the repo — and it is now cheap, because the projection
|
||||
work is done and only the presentation is missing. **Do it with Gitea#20 step 3**, which builds a
|
||||
renderer for exactly this kind of read-only public page; building a second one first would be the
|
||||
waste.
|
||||
|
||||
#### #86 — Real audio, as committed assets.
|
||||
|
||||
@@ -1719,37 +1794,29 @@ placeholder, not the finished sound. Sound therefore defaults to OFF.
|
||||
- Keep the synthesised versions as the fallback for anything not sourced, so a missing file is
|
||||
a quieter game rather than a broken one.
|
||||
|
||||
#### #88 — card-reference.md's industry table may still be stale beyond Grocer's…
|
||||
#### #88 — CLOSED — card-reference.md's industry table is no longer anybody's source.
|
||||
|
||||
**`card-reference.md`'s industry table may still be stale beyond Grocer's Warehouse, the Oil
|
||||
**CLOSED 2026-09-07 in v0.7.9.3, by removing the question rather than answering it.** This asked
|
||||
|
||||
Refinery and Freight House (corrected v0.5.0) — Mine Tipple, Produce Shed and Power Plant were
|
||||
NOT re-verified.** The v0.5.0 pass corrected three rows (and the "Freight House is not a card"
|
||||
claim across `card-reference.md`, `glossary.md`, `rules-v0.2.md` and `open-questions.md`) on
|
||||
Jesse's explicit call. Checking `content.ts` while making that change turned up that
|
||||
`mineTipple` and `powerPlant` are ALSO base 1 out/in + 1 Laborer in the engine — the same
|
||||
uniform model as the three that were corrected — while `card-reference.md` still prints Mine
|
||||
Tipple 3/3/4 and Power Plant 3/3/4, and the "Throughput — why these Laborer counts" section
|
||||
right below the table is built entirely on those higher numbers. Flagged inline in
|
||||
`card-reference.md` rather than silently rewritten — this needs the same kind of decision Jesse
|
||||
made for the other three, not an assumption that the same correction applies, since raising or
|
||||
lowering Laborer counts is also a balance question, not only a docs one.
|
||||
whether `card-reference.md`'s Mine Tipple, Produce Shed and Power Plant rows were stale — it prints
|
||||
3/3/4 for two of them while `content.ts` has every industry at base 1 out / 1 in / 1 Laborer — and
|
||||
deliberately did NOT rewrite them, on the grounds that changing a Laborer count is a balance
|
||||
decision rather than a documentation one. **That reasoning still stands and nothing was changed in
|
||||
the engine.**
|
||||
|
||||
**v0.4.9e narrows it.** The Direction column for the Grocer's Warehouse and the Oil Refinery was
|
||||
the wrong half of that v0.5.0 pass and has been put back to one-way each, from gameplay testing
|
||||
and Jesse's confirmation. The *numbers* in those two rows are still the card reference's own
|
||||
(1 Laborer, 3–4 track) and still unverified against the engine, so this entry stands as written
|
||||
for all five industries — what changed is only that the two rows the v0.5.0 pass claimed to have
|
||||
re-verified turn out to have been re-verified against a premise rather than against a card.
|
||||
|
||||
---
|
||||
What changed is that `card-reference.md` is no longer where anyone looks. `docs/rules/as-built.md`
|
||||
is generated from `content.ts` and carries the industry table the game actually runs; the old file
|
||||
keeps its SUPERSEDED banner, now pointing forward, and its numbers are read as what the v0.4.5
|
||||
placeholder said. **The balance question the entry was really guarding is #70** (the rolling stock
|
||||
supply and the uniform 1/1/1 industry model, both marked provisional in `content.ts`) — that is
|
||||
where it belongs, and it is still open.
|
||||
|
||||
## Done
|
||||
|
||||
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.2, from the queue
|
||||
### Shipped through v0.7.9.3, 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.
|
||||
@@ -1757,12 +1824,11 @@ 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.
|
||||
longer needed." The jump is made, so the note is retired rather than committed. **No per-version
|
||||
save-compatibility fact is tracked from here**, on Jesse's call 2026-09-07: a save replays
|
||||
through the current rules, so an older one breaking is the design working rather than an event
|
||||
to log each time. The general rule lives in `README.md` § Design notes; #40 is the same shape and
|
||||
has been generalised to match.
|
||||
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user