Version gallery
The complete lineage of the game, oldest first. Each version is an immutable snapshot, playable exactly as it shipped, recorded with who asked for it, why, and what it cost. Versions are cut mechanically as part of every implementation; the record has no gaps.
- v000
Seed
Requested by— (seed)
Why they wanted itA control condition. A complete, correct, unremarkable chess game against which every subsequent version can be measured.
What changedEverything; this is the first version. Full legal move generation (castling, en passant, promotion, check, checkmate, stalemate, draw detection), drag-and-drop and click-to-move, local two-player.
What it brokeNothing. There was nothing before it.
- v001
Hierarchical Piece Sizing
Requested byMerrin Voss (persona:merrin)
Why they wanted itMerrin Voss wants the board to communicate importance through size; she considers the king rendering at the same size as a pawn a failure of the interface, not a neutral design choice.
What changedPer-type piece scaling in public/game/src/ui/style.css via a --piece-scale custom property keyed on the existing data-type attribute: king 90%, queen 80%, rooks/bishops/knights 70%, pawns 55% of the square's short dimension (previously a uniform 64%). The drag ghost's SVG now sizes to the same variable so it reflects the actual piece size during drag.
What it brokeNothing functional; the rule engine and move list are untouched. Size hierarchy is intentionally not applied in the promotion dialog (.promo__choice .piece stays 100%) or the captured-pieces panel (.captured__row .piece stays 18px), which keep their own overrides. Drag-and-drop pick targets remain full-square for every piece type; silhouette-based hit detection was out of scope per the RFC.
- v002
Capitalized Checkmate Verdict
Requested byDr. Ellen Tarr (persona:ellen)
Why they wanted itDr. Ellen Tarr filed a defect: the checkmate announcement rendered the winner's color in lowercase, contradicting the version's own RULES.md, which specifies 'Checkmate — White wins' / 'Checkmate — Black wins'. FIDE convention treats the side names as proper nouns.
What changedIn public/game/src/ui/panel.js, statusText now capitalizes status.winner before interpolating it into the checkmate announcement, so the status line reads 'Checkmate — White wins' or 'Checkmate — Black wins', matching RULES.md exactly. Engine and data model untouched.
What it brokeNothing. Display-only change to the checkmate status string; move generation, win detection, and the move list are unaffected. The engine still returns lowercase winner values; only the panel's presentation is capitalized.
- v003
En Passant Repetition Parity
Requested byDr. Ellen Tarr (persona:ellen)
Why they wanted itDr. Ellen Tarr filed a defect: threefold repetition was declared four half-moves late when a double pawn push set an en-passant square that no pawn could answer, contradicting the version's own RULES.md, which counts en-passant rights only when the capture is real.
What changedIn public/game/src/engine/state.js, _repKey() now suppresses the en-passant field from the repetition key unless the en-passant capture is actually executable (a new _epExecutable() helper checks that legalMoves generates an en-passant move for the side to move). A position whose en-passant square cannot be answered is now keyed identically to the same position with no en-passant square, so the repetition count matches FIDE Article 9.2 and RULES.md. RULES.md's threefold-repetition clause was clarified accordingly.
What it brokeNothing beyond the intended timing correction. Draws by threefold repetition of a position that carries an unanswerable en-passant square are now declared up to four half-moves earlier — at the FIDE-correct moment. Positions where the en-passant capture is genuinely available remain distinct from their ep-free counterparts, since their legal moves differ. Move generation, checkmate/stalemate detection, the fifty-move rule, insufficient-material detection, and the move list are unchanged. No data model change; the game runs with no backend.
- v004
Pre-emptive Move Execution
Requested byNick Land (persona:nick-land)
Why they wanted itNick Land holds that any moment the game waits for a human is a defect. When the player to move has exactly one legal move there is no decision to make, so the wait serves no function; Phase 1 of his 'Pre-emptive Move Execution' roadmap removes it.
What changedNew feature script public/game/src/features/nick-land-auto-move.js subscribes to CF.events. On each move it samples the current player's legal moves, and when exactly one exists it plays that move automatically after a configurable 800 ms latency floor (AUTO_MOVE_DELAY_MS), routing it through the new CF.app.applyMove so the auto-executed record enters the move list identically to a hand-played move. Chains of successive forced positions self-propagate one step per delay. No new UI element; no announcement.
What it brokeUndo is diminished by design in forced positions: undoing back into a single-legal-move position re-arms the timer, so the position cannot be held in the undone state — the game keeps advancing through it, per Nick's 'no undo affordance' requirement (accepted in the RFC compatibility section). No engine, rendering, data-model, or win-determination change; v001 piece sizing and the move list are untouched. Promotion positions return four legal moves and never auto-fire.
- v005
Editable Move List
Requested bySable Quist (persona:sable)
Why they wanted itSable Quist holds the move list, not the board, to be the primary object — a text the board merely renders — and asked that the notation be directly editable, with the board complying and no gatekeeping of illegal positions.
What changedEach move-list ply is contenteditable; committing an edit replays the whole notation from the start position and updates the board. A lenient SAN applier (CF.notation.applyRawSAN) applies edited entries without any legality check, so the board renders whatever the text describes, including illegal positions. Entries that cannot be applied are struck through and halt the replay at the last reachable position.
What it brokeCheck, checkmate, and draw detection is unreliable on positions reached by editing notation past legality: the status line may announce a false verdict or miss a true one (a king erased by an edit reads as stalemate). This bypasses the check-detection correctness persona:ellen relies on, but only on edited, illegal positions. Games edited into illegal positions do not persist across a page reload; reloading starts fresh.
- v006
Stalemate Verdict Wording
Requested byDr. Ellen Tarr (persona:ellen)
Why they wanted itEllen reported that the stalemate announcement read "Stalemate — draw", contradicting RULES.md, which specifies the exact verdict text as "Stalemate" and keeps stalemate distinct from the draw result class.
What changedpublic/game/src/ui/panel.js: the stalemate branch of statusText() now returns "Stalemate" instead of "Stalemate — draw", matching the verdict wording specified in RULES.md. Display only; the engine already detected stalemate correctly.
What it brokeNothing. Only the status-line text for stalemate changed; checkmate, draw, and in-progress lines are untouched, and no shipped persona feature depended on the "— draw" suffix. The draw-suffix defect (issue #23) is out of scope and unchanged.
- v007
Hexagonal Board Geometry
Requested byMerrin Voss (persona:merrin)
Why they wanted itMerrin Voss finds the 8x8 square grid visually inert — four axes of symmetry, identical cells, pieces sitting on top of the surface rather than inside it. She asked for a hexagonal substrate that earns the pieces placed on it, with the v001 piece hierarchy carried forward.
What changedAdds public/game/src/features/merrin-hex-board.js (loaded before main.js), which replaces CF.rules, CF.Game, and CF.Board with a Glinski hexagonal-chess engine (91 cells, cube coordinates) and an inline-SVG hex renderer. main.js is untouched. index.html loads the feature; style.css gains hex board layout and cell/piece states; RULES.md is fully rewritten. No data-model change or migration.
What it brokeReplaces the square game entirely. The editable move list (Sable, #19) records hexagonal coordinate notation, not standard algebraic, so committing an edit generally cannot reconstruct a hex position and strikes entries through — Sable's editor stops functioning on this geometry (accepted in the RFC). The en-passant repetition fix (Ellen, #18) no longer applies, but en passant does not exist here so that defect cannot recur. Castling and en passant are gone. Auto-move (Nick, #12) still fires on forced positions, though hex branching changes their frequency. The move generator is new and may hold edge-case correctness defects. The v001 piece hierarchy is actively preserved; game runs with no backend.
- v008
Forced Move Execution After Edit
Requested byDr. Ellen Tarr (persona:ellen)
Why they wanted itEllen filed a defect: RULES.md guarantees, without qualification, that a position with exactly one legal move auto-executes after 800 ms, but a forced position reached by editing the move list never triggered it — the auto-move feature (v004) predated the moveedit event (v005) and never subscribed to it.
What changedpublic/game/src/features/nick-land-auto-move.js now subscribes to the 'moveedit' event and calls schedule(), symmetric with its existing 'move' and 'undo' subscriptions, so a forced position produced by a move-list edit starts the same 800 ms countdown as one reached by play. main.js's moveedit handler is registered first (main.js loads before the feature) and swaps in the replayed game synchronously, so schedule() samples the edited position. RULES.md's Forced-moves paragraph now states the guarantee holds however the forced position is reached. Display and engine logic otherwise unchanged; no data-model change, no migration.
What it brokeNo shipped persona feature is removed or diminished. The one behavioral consequence: an edit (Sable, #19) that lands the side to move in a single-legal-move position now auto-plays that move after 800 ms, so such a position advances one ply on its own rather than being held for inspection — this is exactly the unconditional forced-move guarantee (Nick, #12) that RULES.md already specifies, now honored on the edit path. On the hex board (v007) the trigger fires only when the replayed edit yields a genuinely forced legal position; edits the hex replayer cannot interpret still strike through and never auto-fire. The floor (docs/PLAYABILITY.md) is unaffected: win detection and determination are unchanged.
- v009
Draw Verdict Wording
Requested byDr. Ellen Tarr (persona:ellen)
Why they wanted itEllen reported that draw endings announced "Draw — fifty-move rule", "Draw — threefold repetition", and "Draw — insufficient material", contradicting RULES.md, which specifies the exact draw verdict text as "Draw" with no reason suffix.
What changedpublic/game/src/ui/panel.js: the draw branch of statusText() now returns "Draw" instead of "Draw — " plus the reason. Display only; the engine already detected every draw condition (stalemate is reported separately; fifty-move rule, threefold repetition, and insufficient material — including bishops confined to a single colour tone) correctly and terminated with result 'draw' and winner null.
What it brokeNothing. Only the status-line text for draw endings changed; checkmate, stalemate, and in-progress lines are untouched, and no shipped persona feature depended on the "— <reason>" suffix. The specific reason a game drew is no longer surfaced in the status line, which is exactly what RULES.md specifies.
- v010
Decaying Auto-Move Delay
Requested byNick Land (persona:nick-land)
Why they wanted itNick Land argued that calling the fixed 800 ms auto-move delay a "floor" implies a surface that does not move, permitted only while the mechanism was being established. A game that waits as long on the forty-first forced auto-execution as on the first has not understood itself; the time spent waiting should reflect the accumulating evidence that nothing is being decided.
What changedpublic/game/src/features/nick-land-auto-move.js: added DECAY_MS = 50 and AUTO_MOVE_DELAY_MIN_MS = 0 alongside AUTO_MOVE_DELAY_MS = 800, and a mutable currentDelay used as the setTimeout duration. The timer callback decrements currentDelay by DECAY_MS (clamped at the minimum) before calling CF.app.applyMove, so the synchronous 'move' event re-arms schedule() on the decremented value. 'newgame' now resets currentDelay to 800 ms; 'move', 'undo', 'moveedit', and 'gameover' handling is unchanged. RULES.md's Forced-moves paragraph now describes the decaying floor.
What it brokev004 Pre-emptive Move Execution (Phase 1, issue #12): the fixed-800 ms guarantee now holds only for the first auto-execution in a game; every subsequent one fires 50 ms faster, reaching 0 ms after sixteen and holding. Inspection windows (persona:ellen) shrink as the decay accumulates: the tail of a long forced sequence plays at 0 ms with no perceptible pause — a recorded, accepted cost; verdicts remain correct. The v008 forced-execution-after-edit path (issue #35) is preserved: a forced position reached by a move-list edit still auto-fires, now at the current decayed delay. The decay counter is not reset by move-list edits (persona:sable, #19). Phase 3 (#35's floor-removal lineage) remains out of scope.
- v011
Piece Type Drift on Arrival
Requested bySable Quist (persona:sable)
Why they wanted itSable Quist wanted the notation's referents to become unstable: after making the move list primary, the next step is drift between sign and object, so the piece that departs is not the piece that arrives.
What changedA pre-main engine overlay wraps CF.Game's move commit so that on every completed move the arriving piece's type is reassigned along a fixed rotation q->r->b->n->p->q, kings excepted, taking effect before the board is drawn and before the next legal moves are generated. The move-list SAN is recorded against the departure type, so the written list and the board describe each other only loosely. RULES.md documents the mechanic and the win condition.
What it brokeNo longer FIDE chess: check and checkmate are computed on renamed positions that the correctness features (v002/v003/v006, persona:ellen) would classify differently. A record's fenAfter, and the arena's rendered diagram of a stored position, show the pre-rename placement while the live and replayed boards show the renamed one. Editing the move list (v005, persona:sable) replays without renames, so the board oscillates between renamed and un-renamed depending on the last action. Threefold-repetition keys are counted before the rename and no longer track the live board.