Version gallery

  1. v000

    Seed

    2026-07-14
    Requested by

    — (seed)

    Why they wanted it

    A control condition. A complete, correct, unremarkable chess game against which every subsequent version can be measured.

    What changed

    Everything; 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 broke

    Nothing. There was nothing before it.

    Play v000RulesNo references.
  2. v001

    Hierarchical Piece Sizing

    2026-07-14
    Requested by

    Merrin Voss (persona:merrin)

    Why they wanted it

    Merrin 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 changed

    Per-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 broke

    Nothing 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.

  3. v002

    Capitalized Checkmate Verdict

    2026-07-15
    Requested by

    Dr. Ellen Tarr (persona:ellen)

    Why they wanted it

    Dr. 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 changed

    In 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 broke

    Nothing. 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.

  4. v003

    En Passant Repetition Parity

    2026-07-16
    Requested by

    Dr. Ellen Tarr (persona:ellen)

    Why they wanted it

    Dr. 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 changed

    In 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 broke

    Nothing 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.

  5. v004

    Pre-emptive Move Execution

    2026-07-17
    Requested by

    Nick Land (persona:nick-land)

    Why they wanted it

    Nick 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 changed

    New 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 broke

    Undo 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.

  6. v005

    Editable Move List

    2026-07-17
    Requested by

    Sable Quist (persona:sable)

    Why they wanted it

    Sable 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 changed

    Each 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 broke

    Check, 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.

  7. v006

    Stalemate Verdict Wording

    2026-07-18
    Requested by

    Dr. Ellen Tarr (persona:ellen)

    Why they wanted it

    Ellen 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 changed

    public/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 broke

    Nothing. 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.

  8. v007

    Hexagonal Board Geometry

    2026-07-19
    Requested by

    Merrin Voss (persona:merrin)

    Why they wanted it

    Merrin 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 changed

    Adds 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 broke

    Replaces 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.

  9. v008

    Forced Move Execution After Edit

    2026-07-21
    Requested by

    Dr. Ellen Tarr (persona:ellen)

    Why they wanted it

    Ellen 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 changed

    public/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 broke

    No 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.

  10. v009

    Draw Verdict Wording

    2026-07-21
    Requested by

    Dr. Ellen Tarr (persona:ellen)

    Why they wanted it

    Ellen 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 changed

    public/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 broke

    Nothing. 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.

  11. v010

    Decaying Auto-Move Delay

    2026-07-21
    Requested by

    Nick Land (persona:nick-land)

    Why they wanted it

    Nick 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 changed

    public/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 broke

    v004 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.

  12. v011

    Piece Type Drift on Arrival

    2026-07-22
    Requested by

    Sable Quist (persona:sable)

    Why they wanted it

    Sable 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 changed

    A 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 broke

    No 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.