Commit Graph
3 Commits
Author SHA1 Message Date
Jesse.MarkowitzandClaude Opus 5 dc31555625 v0.8.0.16 — the guide a tester can reach, and a flag that named the card instead of the gate
v0.8.0.15 wrote a Quickstart for a tester who has never played and then left it
in docs/, where a tester does not look — reachable only by somebody who already
has the repository. Nobody handed the box had it. build-web.ts now copies it to
dist/quickstart.md and the splash page offers it under the three doors, as a
line rather than a fourth door: reading the guide is not a way to play, and
giving it equal weight in that grid would say it is.

COPIED, NEVER RE-WRITTEN. The Markdown document stays the one copy. A
hand-written HTML twin drifts from it on the first edit, which is the failure
#15a was raised about and precisely what the v0.8.0.15 pass spent itself
undoing. It is served as PLAIN TEXT, which is honest rather than good — tables
render as pipes and the links do not click. Rendering it into a styled page
wants a small Markdown converter and is filed as TODO #109; build-web.ts's
comment names that number rather than gesturing at "the next step", so the file
and the worklist cannot drift the way the references just did.

Two things had to be true and tsc checks neither, so both are tests. The href on
the splash page and the filename the build writes are two strings with nothing
connecting them: rename the document and the build quietly publishes nothing
while the page keeps offering a link that 404s. And a .md file must not arrive
as a download — the server's MIME fallback is application/octet-stream, which a
browser saves instead of displaying, so the link would have handed a tester a
file to save rather than a page to read. '.md' is in http.ts's table now, and
the test reads that table out of the source rather than asserting on a copy of
it, which would pass while the real one was wrong.

VERIFIED AGAINST A RUNNING SERVER, not only compiled: 200,
text/plain; charset=utf-8, the guide's own first lines, and the splash link
resolving.

THE sortsCars COMMENT. Asked after v0.8.0.15 whether everything now agreed, and
the audit turned up one place that did not — the field's own doc comment named
the card's printed text as though it were the flag's meaning. Nothing reads it
to permit a sort; its two readers, resolveExtraStart in apply.ts and the
enumeration in legal.ts, both ask whether this is the one Mainline card with a
Yard Limit and therefore the one an Extra may be made up and started on. Comment
only, and worth the bump because of where it is: it is what a developer reads
before using the flag, and it is the likeliest source of the sentence v0.8.0.15
had to correct off the board. The name is kept for its link to the card face and
the comment now says outright that the name is not the meaning.

The five references and docs/design.md read v0.8.0.16. They describe this build
because the audit re-checked them against it, not because the number was swept
forward — a stamp bumped without a reading is worth less than none.

1001 fast tests and 35 sim tests pass.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MUizFYCMHRWhbWwXhp7WPR
2026-09-21 01:28:51 -04:00
Jesse.MarkowitzandClaude Opus 5 f308a2d94d v0.8.0.15 — the reference documents, and a card that advertised what it cannot do
The four hand-written references brought up to the game as it actually runs,
ahead of the next testing round, plus a Quickstart to hand a tester who has never
played. They had not been touched since v0.6.2 — a month and two minor versions —
and each now says at the top which build it describes.

ONE LIVE BUG CAME OUT OF THE PASS. mainlineDescription told players "Cars may be
sorted into any new order here" on the Interchange. It is the printed capability
and has never been implemented: nothing reads sortsCars to permit a sort, and its
one live use is marking the card an Extra may be made up on, because it is the
Mainline card with a yard. That sentence is not only documentation — view.ts
renders it as a Mainline card's `what`, so it is what a player reads on the
board, and the generated reference printed a "Sorts cars: yes" column beside it.
A card advertising a button that does not exist sends a player hunting for it and
then concluding the game is broken.

What the documents had wrong, all of it verified against the code rather than
read for tone: the victory model in the Rules book (firstToTarget /
highestAfterDays and the target-bearing length presets stopped existing in
2026-08 — it is a free days count and a combined floor of 3 x players x days);
"there is no lobby, no server, no multiplayer"; crossing time in mph rather than
regions; Extras launched automatically eastbound; the Uncontrolled Siding listed
as a passing card; industry track length taken from the box count; and a
"Sister Trains" optional rule that never existed. The Home deck's counts table
came out under TODO #15a — Jesse's own ruling that counts move with balance —
and it had been wrong for a month, which is the argument made twice.

The Home and Mainline deck references are restructured to explain how a deck is
USED and to defer every per-card table to rules/as-built.md. Duplicating it by
hand is precisely the drift #15a was raised about: as-built needed no correction
beyond the Interchange, because build:cards regenerates it and a test fails when
the checked-in file disagrees. Everything hand-maintained around it had drifted;
it had not.

docs/design.md, the index everything starts from, said v0.4.3, "what is not: the
server", and 493 tests. It now also lists the player-facing references, which it
never has, so the Quickstart is findable at all.

999 fast tests and 35 sim tests pass.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DmdqqCNoiqE7GBo6wthBnR
2026-09-20 12:13:18 -04:00
Jesse 9f3b92d08e v0.4.7 — the switching game: track order, the cut on your own card, and four rules
Eight play reports and one design that had been written up and not built. The
through-line is switching: what a card can hold, which end of a train a cut comes
off, which way a train meets cars standing on the line, and what the board and the
log say about all of it.

TRACK ORDER FOR STANDING CARS, AND THE CUT ON YOUR OWN CARD

Two reports turned out to be one root cause. `TrackCard.standing` claimed "in track
order (§A.3)" and had no defined orientation at all, while `CrewTray.consist` does
(nose first, relative to facing) — so every transfer between them was a conversion
nothing performed. §A.3 says what it should be: cars occupy the track "in the same
order they originally held, left-to-right". Left-to-right is west-to-east, and that
is now the defined orientation of `standing` and of an industry track through
`carsOn`. It is the board's orientation, not the train's, so it does not change when
a different train touches the card.

  - Setting out is batch-invariant. Four cars at once, four singles and two pairs
    parked three different orders, one of them physically impossible. Successive
    cuts off the same end stack up towards the engine, so the insertion point is the
    train's own place in the row.
  - Approaching a cut from either end now mirrors. `couples` is built nearest-first
    along the direction of travel and reverses onto the nose, so the farthest car met
    ends up nose-most — which is what makes a run-around worth its Move.
  - A train no longer drives through its own cut. The walk began at the neighbour of
    the start square and never read the start card, so a crew could set cars out and
    pull straight away from them. Coupling is mandatory (§A.4) and your own square is
    no exception; the cut counts against the four-car limit. Setting out off the end
    you are not leaving by still works.

`CrewTray.standingWest` records where a train stands among the cars on its card — a
train may set out off both ends on one square, so which side a cut is on is not
recoverable from the array alone.

On the board, the cut is drawn split at the train — west cars left, east cars right,
engine in the gap — and each car's tooltip says whether it stands ahead of or behind
the engine. The history says which end a cut came off, and a move's button separates
"takes your own boxcar back off this card" from cars found standing on the line.

Decided: taking your own cut back on the square you are standing on is UNDOING the
drop. It is exempt from trains 3/4's per-location freight budget, X13's "drop but not
pick up" and X22's "empties only", and it refunds the budget the drop spent.
Otherwise a legal-looking drop becomes silently one-way.

Measured, 200 paired seeds, developer bot: -0.55 revenue (t = -3.63), freight revenue
1.11 -> 0.56. That cost is the bot's, not the rule's — its trains run engine-first,
so at a stub industry it sets a car out between itself and the only way out, and the
correct play is §A.5's facing-point move, which is the cross-turn planning TODO.md
already records as out of reach of any bot. Filtering self-recoupling moves out of its
options took recoupling from 625 of 1,029 set-outs to 101 of 677, and all 101 that
remain are that case. Read the number as a bot measurement, not a balance one.

THE SUPERINTENDENT'S RULING NAMES THE TRAINS IT IS ABOUT

Reported: the Superintendent could not tell which train he was clearing. The heading
asks the question now — "may Train 6 follow Train 4 onto the same Mainline card?" —
and the trains moved to the FRONT of each button, because the button splits its label
at the first em-dash and showed only the head.

AN INDUSTRY TRACK HOLDS FOUR CARS, LIKE EVERY OTHER CARD

Reported at undo 188: "we wanted to drop two cars, but were only allowed to drop one."
An industry track was built as long as its box count, so a one-box industry had room
for one car. Box count is how much WORK an industry can hold, not how much RAIL it
has. Ordinary track was the other exception, unbounded; both are gone and every card
holds four.

THE FREIGHT AGENT MAY STAGE A LOAD BEFORE THE CAR IS THERE

§6.3 asks nothing of the industry track — the empty car belongs to §9.3's Load the
car, which is the Laborer's action. The gate now lives only there, so cargo can wait
on the dock while the car to ship it in is still being switched in. Nothing can jam:
a load in a green box is waiting, not stuck.

THE TRUCK DOCK UNLOADS, AND BRINGS NOBODY

+1 inbound, no Laborer. It printed +1 outbound and +1 Laborer, which made it a
longer-host-list copy of Forklifts. Beside Packing Sheds it now does nothing at all,
and the hand tooltip says so before it is played.

Also in this release, from the days before: Mainline card tooltips computed from the
crossing rule; an Extra starts from the Division Point its number sends it to; a
modifier's suppressed grant comes back when a Whistle Post is upgraded; the Oil
Refinery and the Grocer's Warehouse ship as well as receive, per the card reference;
and the dormant defences name the attack they answer. `.claude/` is now gitignored —
it holds Claude Code's worktrees, i.e. a second checkout of this repository.

570 tests, typecheck clean. The three published replays were re-recorded twice —
legality changed, so bot play changed. Full detail in CHANGELOG.md.
2026-08-19 12:12:30 -04:00