Skip to content

Release v0.17.0

Choose a tag to compare

@github-actions github-actions released this 07 Jun 09:23
· 13 commits to main since this release

v0.17.0

Highlights

  • xs store: 0.12 -> 0.13.2. A breaking change, but only to the store's internal bookkeeping. The topics your own handlers append to and read are unaffected.

    • xs now keeps its lifecycle records under a reserved xs. prefix, named consistently across actors, services, and actions as xs.<kind>.<name>.<event>. Previously each kind used its own ad-hoc topic names in the same namespace as your data.
    • An old store still opens. To bring its --services automation back up, rewrite those lifecycle topics to the new names with the new binary (.export -> rewrite -> .import); see examples/2048/migrate-topics.nu.
    • Registration topics renamed: *.register -> xs.actor.*.create, *.spawn -> xs.service.*.create, *.define -> xs.action.*.create, *.nu -> xs.module.*.
    • Exit reasons are now distinct topics (fin.ok / fin.error / fin.term) rather than a field on the frame.
    • New handler builtins: .import (restore frames) and .cas-post (write a CAS blob).
  • --services for http-nu eval. Eval mode can now start the same background services serve mode runs, so scripts can exercise actors, services, and actions without a live server.

  • Nushell engine: 0.112.1 -> 0.113.1. Handlers gain peek (sample a stream without a collect) and the idx family (in-memory file index with fuzzy lookup and content search). Minimum Rust is now 1.93.1; CI's setup-nu tracks the bundled engine.

  • Datastar SDK: 1.0.1 -> 1.0.2. The bundle http-nu serves under --datastar advances to /datastar@1.0.2.js (sourcemap comment stripped). Upstream changes:

    • datastar-patch-elements events accept a viewTransitionSelector data line naming the element to use for the view transition (defaults to document);
    • in-flight requests are cancelled by matching method + URL, regardless of which element initiated them;
    • checkboxes and radios bound with data-bind now sync on the input event for more immediate updates;
    • faster single-target element patches;
    • fixes for data-bind with a modifier on an array-valued checkbox signal, and for retrying on 5xx responses.
  • Accurate startup_ms. The startup timer now starts before handler eval, so the banner and started log event report the real cold start. build.rs also reruns on Cargo.lock changes to keep NU_VERSION / XS_VERSION in sync.

  • 2048 example, substantially rebuilt. nu2048 is now a full event-sourced, multiplayer app and a worked example of the http-nu + xs primitives. Game state is a chain of game.snapshot.<id> frames in the store, each pointing at its predecessor, so a move appends a snapshot and undo walks back up the chain. Three xs actors write and derive from that stream:

    • the snapshot actor is the single writer of the chain: per move it reads the head, computes the next state, and appends the new snapshot;
    • the leaderboard actor watches every snapshot and maintains a derived leaderboard.top view, resuming from a stored cursor rather than replaying all history;
    • the presence actor folds ephemeral per-tab pings into a _presence.summary frame, pruning stale tabs on each xs.pulse.
    • SSE handlers follow these frames with .last --follow / .cat --follow and patch the browser over Datastar, with cookie sessions, a <game-board> web component, and a /design playground.

Raw commits

  • fix: start the startup timer before handler eval so startup_ms reflects real cold start (2026-06-06)
  • build: rerun build.rs on Cargo.lock change so NU_VERSION/XS_VERSION track dep bumps (2026-06-06)
  • docs: add how-to for refreshing the embedded datastar SDK (2026-06-06)
  • deps: update datastar to v1.0.2, strip embedded sourcemap comment (2026-06-06)
  • refactor: register store builtins via cross-stream's add_{core,read,write}_commands (2026-06-06)
  • build: bump cross-stream to 0.13.2; strip-store imports via .import in one eval (2026-06-06)
  • feat(2048): undo tally left of score (score stays put); undo evicts a game from the leaderboard (2026-06-05)
  • feat(2048): live undo tally next to score on /play and /watch (2026-06-05)
  • feat(2048): leaderboard ranks clean runs only (undo-assisted scores excluded) (2026-06-05)
  • feat(2048): track undos count in snapshot meta; leaderboard reads it O(1) (2026-06-05)
  • perf(2048): list-games/list-players/top-players use indexed -T "prefix.*" not full .cat scans (2026-06-05)
  • perf(2048): /sse-wc reads head via --last 1 instead of replaying the chain (2026-06-05)
  • fix(2048): emit trailing newline from strip-store.nu (2026-06-04)
  • refactor(2048): xs 0.13 lifecycle topics, actor-owned snapshot rebuild (2026-06-04)
  • build: upgrade to cross-stream 0.13.0 and nushell 0.113.1 (2026-06-04)
  • fix(2048): widen /design via body max-width after column moved to body (2026-06-03)
  • fix(2048): drop preview frame on the design markdown story (2026-06-03)
  • fix(2048): render design markdown preview in so it matches /notes (2026-06-03)
  • feat(2048): add 'why is this so addictive' notes page (2026-06-03)
  • refactor(2048): render notes in semantic , drop .prose wrapper (2026-06-03)
  • docs(adr): remove 0006 (moved to xs/docs/adr/0005-lifecycle-topics.md) (2026-05-30)
  • docs(adr): reword 'load-bearing' to 'depend on' (2026-05-30)
  • docs(adr): rename parse.error to invalid, strip em-dashes, reframe trade-off as property (2026-05-30)
  • docs(adr): plainer wording, drop 'collapses' (2026-05-30)
  • docs(adr): enumerate deficiencies, add lifecycle invariants (2026-05-30)
  • docs(adr): xs.. namespacing, one-shot migration (2026-05-30)
  • docs(adr): xs lifecycle topics + compaction algorithm (2026-05-30)
  • examples/2048: add migrate-topics.nu for old->new topic shape (2026-05-28)
  • examples/2048: prefix-shape game topics; reroute no-op ack via ephemeral snapshot (2026-05-28)
  • examples/2048: add /sse-wc integration test (2026-05-28)
  • examples/2048: add snapshot-actor integration test (2026-05-28)
  • feat: add --services flag to eval subcommand (2026-05-28)
  • examples/2048: plain-language test-sse.nu names, fix leaderboard resume comment (2026-05-28)
  • examples/2048: fix leaderboard-actor crash on empty .last, guard the idiom (2026-05-27)
  • examples/2048: snapshot-actor resumes from cursor so reloads don't drop moves (2026-05-27)
  • examples/2048: dim the board while a move's response is pending (2026-05-27)
  • docs: note to keep setup-nu in sync with the bundled nu version (2026-05-26)
  • ci: run nu tests on 0.112.1 to match the bundled engine (2026-05-26)
  • examples/2048: enlarge splash PLAY NOW button and callout text (2026-05-25)
  • examples/2048: use Cirulli-continued palette in the board WC (2026-05-25)
  • examples/2048: tile-palette gallery in /design, drop colors experiment (2026-05-25)
  • examples/2048: thumb-ergonomic D-pad controls, mobile-friendly chrome (2026-05-24)
  • examples/2048: snapshot-actor clears spawned/merged on undo (no re-animation) (2026-05-20)
  • examples/2048: strip decorative parens around single-line let values (2026-05-20)
  • examples/2048: drop dead try around .last; use get?.field? | default for chained access (2026-05-20)
  • examples/2048: /sse/games --from instead of --new (race-free cursor) (2026-05-20)
  • examples/2048: /sse/games uses .cat --follow --new instead of .cat | last head probe (2026-05-20)
  • examples/2048: layout owns $presence seed; drop redundant per-route declarations (2026-05-20)
  • examples/2048: hoist /watch signals to so site-header data-text can read $presence (2026-05-20)
  • examples/2048: leaderboard-actor resumes from last_processed_id cursor (2026-05-20)
  • examples/2048: cap actor register topics with --ttl last:1 (2026-05-20)
  • examples/2048: presence-stream filters xs.threshold before .meta access (2026-05-20)
  • examples/2048: fix let board_stream = .cat --follow hang in 3 SSE handlers + test-sse.nu regression guard (2026-05-20)
  • examples/2048: site-wide presence (X here chip + per-game count, /presence/ping) (2026-05-20)
  • examples/2048: fold playedMs into board signal, owns overlay (2026-05-20)
  • examples/2048: leaderboard link in header; #1 podium row, #2-5 two-up (2026-05-20)
  • examples/2048: /leaderboard page reads leaderboard.top, dimmed-card per row (2026-05-20)
  • examples/2048: leaderboard-actor maintains leaderboard.top (last:5) (2026-05-20)
  • examples/2048: reserve over-slot so 'you win' stays in place (2026-05-19)
  • examples/2048: per-tab splash topic, no more shared bus.splash.seek (2026-05-19)
  • examples/2048: WC drives the splash slider (2026-05-19)
  • examples/2048: dual-badge endgame + /design/badges tab (2026-05-19)
  • examples/2048: restore Cirulli past-the-end signal for 4096+ tiles (2026-05-19)
  • examples/2048: refresh stale design.css comment header (2026-05-19)
  • examples/2048: drop dead vt-tuner CSS, refresh stale comments in serve.nu + sse.nu (2026-05-19)
  • examples/2048: annotate /design/board playground states with spawned/merged/ghosts (2026-05-19)
  • examples/2048: drives animations from snapshot annotations, no prevState (2026-05-19)
  • examples/2048: dim variant on for thumbnails; resync DOM to prevState on apply (2026-05-19)
  • examples/2048: badge moves into shadow DOM; drop old VT pipeline (2026-05-19)
  • examples/2048: /play renders WC; delete states-to-html, render-game, fx-tuner (2026-05-19)
  • examples/2048: splash board renders via WC (2026-05-19)
  • examples/2048: client-driven heartbeat, drop server pulses, indicator everywhere (2026-05-19)
  • examples/2048: /watch renders WC via /sse-wc signals (2026-05-18)
  • examples/2048: WC + /design/board-wc playground (2026-05-18)
  • examples/2048: random splash start pos; slider scrub seeks audio; CSS view-transition opt-in (2026-05-18)
  • examples/2048: fix RTT probe wiring -- subtree observer + data-on-signal-patch (2026-05-18)
  • examples/2048: route move-ack via $lastReqId signal instead of data-rev DOM observer (2026-05-18)
  • examples/2048: kbd-btn --style passthrough; nudge splash CTA margin-top (2026-05-18)
  • examples/2048: stop callout list-item from stretching its anchor (2026-05-18)
  • examples/2048: consolidate normalize block at top; drop redundant inherits (2026-05-18)
  • examples/2048: fade pending edge-line in and out (2026-05-18)
  • examples/2048: strip drag/swipe/reconnect glow; keep only pending edge-line (2026-05-18)
  • examples/2048: splash hero as title + .lede/.preview flex columns (2026-05-18)
  • examples/2048: flat grid splash hero; cross-column row anchors (2026-05-18)
  • examples/2048: render splash audio toggle as anchor (webkit VT button-opacity bug) (2026-05-18)
  • examples/2048: fix trailing spaces in splash credit paragraphs (2026-05-18)
  • examples/2048: collapse static routes; restructure splash hero column (2026-05-18)
  • examples/2048: splash CTA reads Play [n]ow (2026-05-18)
  • examples/2048: unify buttons under kbd-btn; primary variant for CTA (2026-05-18)
  • examples/2048: splash cadence driven by client, server purely reactive (2026-05-18)
  • examples/2048: gate header status indicator on layout --sse flag (2026-05-18)
  • examples/2048: wire splash slider seek via Datastar pos signal (2026-05-18)
  • examples/2048: slider auto-advances; relative @font-face url; nav hrefs via body data-attrs (2026-05-18)
  • examples/2048: self-host Source Sans 3 + Source Code Pro (2026-05-18)
  • fix: point check.sh at examples/2048/test/test.nu (2026-05-18)
  • examples/2048: keep splash interactive during VT replay; audio toggle (2026-05-18)
  • examples/2048: card takes resolved --href (drop --href-prefix conflation) (2026-05-18)
  • examples/2048: stamp moves with session; actor gates; /watch viewer (2026-05-18)
  • examples/2048: backstory leads with Threes!; add Best of 2048; splash callout reframed (2026-05-18)
  • examples/2048: session-cookie auth, /by/, /play owner-or-404 (2026-05-18)
  • examples/2048: splash replays oleksii_lisovyi's run via SSE; seek scaffold (2026-05-17)
  • examples/2048: scroll by default; tuner escapes help; prose + asset fixes (2026-05-17)
  • examples/2048: unify anchor styling; notes share layout; prose typography (2026-05-17)
  • examples/2048: notes/split-md handles parsed-md + heading-first files; fleshed content (2026-05-17)
  • examples/2048: chrome polish across splash, /play, layout (2026-05-17)
  • examples/2048: leaderboard uses topic indexes; gates on snapshot recency before drilling in (2026-05-17)
  • examples/2048: rewrite leaderboard as single .cat pass with group-by (2026-05-17)
  • examples/2048: split splash from library -- / is marketing landing with PLAY NOW orange CTA, /my/games is the cookie-scoped card grid; site-header gets my-games/notes nav + player-id chip; play breadcrumb starts with home/[esc] · my games · game-id (2026-05-17)
  • examples/2048: add leaderboard query to README CLI section (2026-05-17)
  • examples/2048: document store-supervisor model and snapshot meta in README (2026-05-17)
  • examples/2048: tighten CLAUDE.md hammer-test section (2026-05-17)
  • examples/2048: /design uses the breadcrumb component for the header; scrollbar-gutter on scrollable panes so width stays stable across pages; CLAUDE.md hammer-test guidance (2026-05-17)
  • examples/2048: /design right pane scrolls independently (body locked to viewport, nav + preview both overflow-y: auto) (2026-05-17)
  • examples/2048: flex 2:1 play layout (board column flex:2, help flex:1), drop arbitrary max-widths -- container decides; stacks below 700px viewport (2026-05-17)
  • examples/2048: tighten styles -- merge .game-card fragments, fold shared overlay properties to parent, drop body.play prefix from /play-only classes (2026-05-17)
  • examples/2048: move _baseline.mjs to throwaway/ (2026-05-17)
  • examples/2048: lean on cascade -- type-scale vars, element-rule for mono (header/nav/code/kbd/samp/output), drop redundant leaf font-family declarations, drop dead .play-header block (2026-05-17)
  • examples/2048: empty-store / redirects to /new -- if/else expression (return inside route closure swallowed the metadata); regression test in test.mjs (2026-05-17)
  • Update README.md (2026-05-17)
  • examples/2048: breadcrumb focus = last anchor in path (cyan); hover orange wins by source order, no per-class specificity tangle (2026-05-17)
  • examples/2048: kbd-btn always renders as (data-href for nav); links hover to same orange accent as button hover (2026-05-17)
  • examples/2048: kbd-btn hover state works for both (move keys) and (nav shortcuts) forms; consistent orange highlight (2026-05-17)
  • examples/2048: breadcrumb server-side component; [esc] pairs with past games link, [n] pairs with new game; past games is a self-link on / (2026-05-17)
  • examples/2048: shared breadcrumb header on / and /play; kbd-btn server-side component for [esc] / [n] / help-panel keys; game-id is a breadcrumb path link in --brand cyan; n key navigates to /new (2026-05-17)
  • examples: drop 2048-animation (subsumed by 2048) (2026-05-17)
  • examples/2048: move tile-palette swatch explorer into experiments/colors/ (2026-05-17)
  • examples/2048: tighten README, drop '.bus demo' framing; nu2048 title and og metadata (2026-05-17)
  • examples/2048: splash card overlays paint above .is-max (z-index + board stacking context); client ticker keeps 'last played' label live without server round trips (2026-05-17)
  • examples/2048: guard states-to-html against null-state records (fresh game / pre-snapshot race); unit test 0a reproduces (2026-05-17)
  • examples/2048: right-align score with the board's right edge (2026-05-17)
  • examples/2048: help panel -- arrows are clickable buttons too, labels move to the left of the action buttons (2026-05-17)
  • examples/2048: help panel polish -- micro space inside brackets [ h ], fx button bracketless (not a keypress), tighter right padding (2026-05-17)
  • examples/2048: help panel sized to its content (align-self:start + align-content:start), no longer stretches to board height (2026-05-17)
  • examples/2048: help panel kbd buttons in bracketed [u]ndo style; drop floating fx tab, tuner now expands from help panel via [fx] button; board left-aligned with breadcrumb (2026-05-17)
  • examples/2048: /play layout -- breadcrumb + score/undo above board, side help panel (aligned with board top), fx toggle to bottom-right (2026-05-17)
  • examples/2048: shared 900px page chrome on both routes; only the play board column caps at 600px (2026-05-17)
  • examples/2048: /play single-column with max-width 600 so the board doesn't dominate; splash keeps 900 for 3-up grid (2026-05-17)
  • examples/2048: dim mask uses body blue so boards recede into the page instead of standing out as voids (2026-05-17)
  • examples/2048: dim the whole board (frame + cells + tiles) via mask overlay, max tile lifted above with z-index (2026-05-17)
  • examples/2048: dark pill backdrop on splash 'in play' label so it reads cleanly over any tile (2026-05-17)
  • examples/2048: splash polish -- nu2048 links home, '+new game' top-right, boards muted to 0.2, larger last-active, fun rotated won/over badge, drop score chip (2026-05-17)
  • examples/2048: drop --use-view-transition on splash games-list patch; the cross-fade was flashing all cards un-dimmed and re-running animations on unchanged boards (2026-05-17)
  • examples/2048: max tile is its own indicator -- mute all board tiles except the highest, drop the redundant max-tile chip (2026-05-17)
  • examples/2048: tighter card overlays -- 'in play' for live games, paired score+max chips in tile palette, no muting of the chips (2026-05-17)
  • examples/2048: use built-in .id unpack instead of shelling out to xs scru128 (2026-05-17)
  • examples/2048: splash card redesign -- nu2048 title, 3-up grid, on-board metadata overlays (created/played/score/max+status), muted boards with hover-bright (2026-05-17)
  • examples/2048: monospace headings, no divider lines, generous spacing (matches http-nu/www patterns); revert tiles to Cirulli (2026-05-17)
  • examples/2048: align chrome with http-nu/www design language (Source Sans 3, inherit-color links, cream emphasis, transparent overlays) (2026-05-17)
  • examples/2048: http-nu/www blue palette; restore 'served by http-nu' text; hide empty rtt on splash (2026-05-17)
  • examples/2048: site header into layout.html; larger title, top-anchored pages (2026-05-17)
  • examples/2048: shared site header (title + status + credit); tuner collapsed by default (2026-05-17)
  • examples/2048: fx tuner reads defaults from CSS; bump dial values (2026-05-17)
  • examples/2048: soft-fade pending indicator with asymmetric reveal delay (2026-05-17)
  • examples/2048: fx tuner -> six knobs for the VT-only pipeline, extracted to vt-tuner.html template (2026-05-17)
  • examples/2048: move layout.html into tfe/templates/ (2026-05-17)
  • examples/2048: edge glow as pending-request indicator (no flash) (2026-05-17)
  • examples/2048: VT-only animation pipeline (slide -> merge pop -> spawn) (2026-05-17)
  • examples/2048: shared layout.html minijinja template for / and /play (2026-05-17)
  • examples/2048: move package.json into test/; drop NODE_PATH hack (2026-05-17)
  • examples/2048: split into tfe/ submodules (game/render/sse/store) (2026-05-17)
  • examples/2048: tests into test/; og.png into static/; show game id in play header (2026-05-17)
  • examples/2048: add research notes; gitignore throwaway/ scratch dir (2026-05-17)
  • examples/2048: /games shares /play chrome; document scrolls when cards overflow (2026-05-17)
  • examples/2048: comments pass -- contracts not fix-narratives; drop dead #replay rule + stale --decay-duration mention (2026-05-16)
  • examples/2048: 600px-max play column, header/footer hug the board; fluid board via grid 1fr + container queries; apply tuned defaults (2026-05-16)
  • examples/2048: echo state for every move frame so no-op moves resolve client RTT; unit test guards the regression (2026-05-16)
  • examples/2048: merge ghosts (slide-fade consumed tile into merge cell); ghost-duration dial; magnitude in tile widths; copy/reset; attack/decay labels (2026-05-16)
  • examples/2048: drop settings/mode-toggle plumbing; expose y2 + ant-duration dials; rename overshoot->slide; body slides under fx tab (2026-05-16)
  • examples: stellar ascent and phase transitions palettes (2026-05-16)
  • examples: spectral cascade palette (photon-energy octaves) (2026-05-16)
  • examples: in-hue fg picker gated by WCAG contrast (2026-05-16)
  • examples: tile-palette color-theory swatches (2026-05-16)
  • examples/2048: floating fx tuner panel for vt + anticipation dials, with latency k scaling (2026-05-16)
  • examples/2048: compile board to a minijinja template (~40x faster render) (2026-05-16)
  • examples/2048: view-transition on /games preview boards, scope tile names by game id (2026-05-16)
  • examples/2048: /sse/games keeps in-memory game data, upserts on each frame, morphs .games-list (2026-05-16)
  • examples/2048: new games appear on /games via SSE prepend when player.X.games frame arrives (2026-05-16)
  • examples/2048: /games SSE skips historical replay; restore play animations; computed-style regression checks (2026-05-16)
  • examples/2048: live SSE updates on /games; shared site footer; pulse-keepalive helper (2026-05-16)
  • examples/2048: plain layouts on /play and /games, drop tracker chrome (2026-05-16)
  • examples/2048: .board as self-contained component, used on /play and in /games thumbnails (2026-05-16)
  • fix: delegate [data-intent] button clicks so undo in top bar works (2026-05-16)
  • examples/2048: top bar with [esc]/[u]ndo/gear chrome buttons; score top-right as tracker digits (2026-05-16)
  • examples/2048: simpler play layout; top bar + bottom bar full-width, board centered with padding (2026-05-16)
  • examples/2048: tracker aesthetic on play view (status bars, slate panels, monospace); Esc returns to splash (2026-05-16)
  • examples/2048: splash is past-games list; URL-routed /play/:game_id; /new mints + 302 (2026-05-16)
  • examples/2048: SSE echoes empty-intent pings for RTT (2026-05-16)
  • examples/2048: stateless actor with prev chain; SSE is a pure snapshot reader; req_id propagated through snapshots (2026-05-16)
  • examples/2048: snapshots ttl:forever; POST /move redirects on stale cookie (2026-05-16)
  • examples/2048: move snapshot writing to an xs actor; split mod.nu into game.nu (pure) + mod.nu (store helpers) (2026-05-16)
  • examples/2048: drop slam (legacy slam-X intents are noop echos on replay) (2026-05-16)
  • examples/2048: reset carries req_id so RTT probe resolves on game-switch (2026-05-16)
  • examples/2048: add resume-game; /games and /sse use it; backfill snapshots on the slow path (2026-05-16)
  • examples/2048: relocate browser test from tests-browser/, add check.sh, rewrite bench without store dep (2026-05-16)
  • examples/2048: snapshot game state per change, resume SSE from snapshot (2026-05-16)
  • examples/2048: empty-intent RTT pings are ephemeral (2026-05-15)
  • examples/2048: extract game logic to mod.nu, optimize replay, narrow SSE source (2026-05-15)
  • examples/2048: slam replay no longer paces; slam body uses generate with early stop (2026-05-14)
  • examples/2048: reqId on every move; client RTT matches on data-rev (2026-05-14)
  • examples/2048: status reads 'replayed in Xms · rtt Yms'; hide both when down (2026-05-14)
  • examples/2048: hide #replay while disconnected (2026-05-14)
  • examples/2048: clear replayMs indicator on disconnect (2026-05-14)
  • examples/2048: emit replayMs at threshold; reset+reprobe RTT on reconnect (2026-05-14)
  • examples/2048: keyboard anticipation winds back opposite the press (2026-05-14)
  • examples/2048: grayscale the board on disconnect instead of fading it out (2026-05-14)
  • examples/2048: slam pacing 250ms -> 200ms (2026-05-14)
  • examples/2048: liveness signal via xs --pulse 450 + staleness timer (2026-05-14)
  • examples/2048: add /games -- read-only past games list (2026-05-14)
  • examples/2048: smooth reset via games-index frame on existing SSE; filter-for-player stage (2026-05-14)
  • examples/2048: split games into per-game topics with a player index (2026-05-14)
  • fix: handle empty topic in 2048 (seed orphaned cookies, guard threshold gate) (2026-05-14)
  • fix: roll() handles hashes starting with 0b/0x/0o (2026-05-14)
  • examples/2048: player cookie, deterministic rolls from (game_id, state, dir) (2026-05-14)
  • examples/2048: nu unit tests for game logic + stack-based impulses-to-states (2026-05-13)
  • fix: slam dir slice off-by-one (5 chars, not 6) (2026-05-13)
  • examples/2048: add undo (stack pop), rename shift -> slam, split rendering stage (2026-05-13)
  • examples/2048: tighter SSE reconnect (100ms flat, unlimited retries) (2026-05-13)
  • examples/2048: defer impulse to release, blast at 250ms pacing (2026-05-13)
  • examples/2048: hold-for-shift 500ms (2026-05-13)
  • examples/2048: shift no-op echoes state, relight edge on shift fire (2026-05-13)
  • examples/2048: settle-then-charge swipe, live RTT indicator, 175ms shift pacing (2026-05-13)
  • examples/2048: defer charge-up until impulse confirmed, no-op state echo (2026-05-13)
  • examples/2048: lit edge until SSE, RTT-tuned decay, touch dot (2026-05-13)
  • examples/2048: shift+letter cascades (lowercase fallback for uppercased keys) (2026-05-13)
  • examples/2048: swipe-and-hold for shift mode, skip flash on no-op moves (2026-05-13)
  • examples/2048: edge flash via fresh DOM element per patch, no JS bridge (2026-05-13)
  • examples/2048: refactor SSE into pipeline boxes, pulse edge glow on each patch direction (2026-05-13)
  • examples/2048: tiles flip with the board on view switch (suppress per-tile transition names while flipping) (2026-05-13)
  • examples/2048: pop tiles before/after flip, match settings height, cache-bust static assets (2026-05-13)
  • examples/2048: switch board layout from absolute positioning to CSS grid (2026-05-13)
  • examples/2048: continuous card-flip on view switch, ephemeral view events via xs ttl (2026-05-13)
  • examples/2048: settings view morphed from #game, mode lives in the event log (2026-05-13)
  • examples/2048: anticipation animation on keypress, matching swipe feel (2026-05-13)
  • examples/2048: event-source the game state over xs (2026-05-13)
  • examples/2048: SSE connection indicator via datastar data-indicator + fade-out on disconnect (2026-05-12)
  • examples/2048: edge glow on lean, holds through commit, fades on patch arrival (2026-05-12)
  • examples/2048: anticipation polish - axis lock, RTT-tuned decay, spring overshoot (2026-05-12)
  • examples/2048: lean only the value tiles, not the background grid (2026-05-12)
  • examples/2048: anticipate swipe by leaning the tiles inside the board (2026-05-12)
  • examples/2048: rebuild minimal version with swipe, mobile, static assets (2026-05-12)
  • examples/stor: make stor create idempotent so watch reloads don't error (2026-05-12)
  • chore: gitignore .claude/ (2026-05-11)
  • examples/2048: ghost tiles on merge, trailing-edge spawn bias (2026-05-11)
  • feat: 2048 win banner when any tile reaches 2048 (2026-05-07)
  • feat: 2048 polish - resume, latency, lead-in, sliders, layout (2026-05-07)
  • perf: drain-then-flush brotli stream for one sync-point per burst (2026-05-07)