Skip to content

Release 1.4.0

Latest

Choose a tag to compare

@vancura vancura released this 23 Jul 10:40
1.4.0
98166b0

You change a line, hit save, and the game keeps running – ticks, camera, palette still where you left them. That is what 1.4.0 is about: true engine hot reload, fast enough that you forget the page used to blink, with a blit386/vite plugin, in-place asset hot-replace, and a loading-progress API for the screens you still have to wait for. CI, agent tooling, and docs catch up around the edges.

Hot Reload

Edit, save, keep playing – that is the whole trick.

  • Engine-side hot-swap runtime (src/hot/): registerHotReload, optional IBTDemo.onHotReload(context), and a three-tier swap – method-only prototype rebind when only method bodies change, full re-init when init() or the constructor changes, full page reload when hardware settings change. Ticks, camera, palette, and palette effects persist across method and re-init swaps. A second bootstrap() under a registered hot context routes to a swap instead of starting a second GameLoop; without one, it logs and returns false. (#374)
  • blit386/vite dev-server plugin (import { blit386 } from 'blit386/vite'): injects the hot-reload registration snippet into entry modules that call bootstrap( and import from 'blit386', watches configured asset directories (default public/), and broadcasts blit386:asset-changed HMR events (full reload for unrecognized extensions). Ships as a second build entry (dist/vite.js / .cjs / .d.ts) with no runtime dependency on vite itself. (#375)
  • In-place asset hot-replace for images, audio, and .btfont files: AssetLoader.evict, SpriteSheet / AudioClip / BitmapFont hot-replace (dev registries gated on an active hot context), and music restart via MusicPlayer when the current track's buffer is replaced. A broken asset event cannot crash the game loop. (#376)
  • Tier 3 under ?backend=software no longer forces a full reload on every edit – the hardware-settings diff now reapplies the URL backend override on the candidate before comparing. Plain .js / .mjs entries are syntax-checked with acorn before snippet injection so Vite's error overlay surfaces parse failures that previously only failed on the client. (#378)

Asset System

Loading screens finally get a real signal to poll.

  • BT.loadingAssetsCount returns the combined in-flight image + audio load count (AssetLoader.loadingCount + AudioClip.loadingCount). SpriteSheet.status ('loading' | 'ready' | 'failed') and coarse SpriteSheet.progress (0 or 1.0) expose per-sheet hot-reload replacement state for loading UI. (#388)

API Changes

Deprecation tags grow version stamps; dead internal aliases leave.

  • Every remaining date-only @deprecated JSDoc tag in src/ is upgraded to Deprecated since <version> (2026-05-31)., and dead internal-only compatibility aliases (PaletteView, RenderPaletteUsage, AssetLimits, OverlayToggleIcon) with no public callers are removed. docs/reference-deprecations.md now lists a removal target of 2.0.0 per alias group. (#406)

Input

Touch scrolling follows the same opt-in as pointer wheel capture.

  • canvas.style.touch-action is no longer hardcoded to none on attach. It tracks HardwareSettings.isCapturingPointerScroll (and the overlay palette band's forced capture): none while capturing, pan-y otherwise, updated live so touch tap-hold-scroll past the canvas works when scroll capture is left at its default false. (#387)

Security

The expired esbuild exception goes away for real.

  • pnpm.overrides.esbuild bumps to ^0.28.1, the GHSA-gv7w-rqvm-qjhr audit ignore is removed, and the Active exceptions row is cleared. esbuild is added as a direct devDependency so Vite 8's optional minify peer is present; fast-uri is pinned to clear the restored audit gate. (#390)

Developer Experience

Remote sessions and agent tooling stop needing a scavenger hunt.

  • Fresh remote/web sessions auto-bootstrap via scripts/session-start-bootstrap.sh (Claude Code SessionStart, Cursor sessionStart, optional .devcontainer postCreateCommand): Corepack enable when needed, then pnpm install --frozen-lockfile, skipped when the lockfile checksum stamp still matches. (#383)
  • Missing .claude/rules mirrors for Cursor-only rule files restore Claude/Cursor parity ahead of the drift checker. (#379)
  • agents:check verifies .cursor/rules.claude/rules parity, .agents/skills/* symlink integrity, and the AGENTS.mdCLAUDE.md pointer; wired into preflight and the CI quality job. (#381)
  • .github/copilot-instructions.md points Copilot agents at AGENTS.md / CLAUDE.md and the hard rules (no emoji, integer coordinates, BT namespace, American English, Conventional Commits + DCO). (#385)
  • .cursor/commands/ are generated from .claude/skills/*/SKILL.md via scripts/sync-cursor-commands.mjs, with sync:cursor-commands:check and test:cursor-commands in preflight and CI. (#386)
  • agents:check also covers Copilot instructions presence and Zed settings JSON consistency; the annotated src/ architecture tree moves into a mirrored rule pair and CLAUDE.md shrinks further. (#410)
  • Agent rules, skills, and command mirrors cleaned up after the architecture extraction – stale cross-refs and duplicated guidance trimmed. (#413)

CI and Tooling

Gates tighten, Renovate wakes up, and duplicate work gets cut.

  • Markdown link checks run with concurrency 8; quality and bundle-size checks move into ci.yml (including Knip and a 70 KB gzipped ESM limit), dropping the duplicate jobs from pr-checks.yml. (#380)
  • checkFile settles exactly once when both error and close fire, and each markdown-link-check child gets a timeout so a hung process cannot stall docs:links forever. (#382)
  • docs:links enumerates files with git ls-files "*.md" "*.mdx" so checks honor .gitignore and skip symlink duplicates under .agents/skills/*. (#391)
  • preflight gains test:api-history and test:security-preflight; CI quality runs api:since:check / api:history:check (with fetch-tags: true), and PR-scoped workflow concurrency cancels duplicate runs. (#394)
  • Dormant renovate.json repaired: real package matchers, 7-day minimumReleaseAge aligned with .npmrc, and Dependabot (security-only) vs Renovate (versions + Actions digests) documented. (#395)
  • Renovate commits get :gitSignOff and lowercase commitMessageAction: "update" so they pass DCO and commitlint; workflow node / pnpm pins are excluded from Actions digest updates. (#401)
  • GitHub Actions digests and the workflow Node version bump (22.18.022.23.1) via Renovate. (#402)
  • Dead root configs removed (.npmignore, .markdownlint.json); inert options trimmed in Vite, Biome, Prettier, and knip configs. (#405)
  • Guided GitHub issue forms (bug / feature / docs), issue chooser with contact links, and a PR template that surfaces DCO, Conventional Commits, preflight, and visual-test checklist. (#407)
  • Biome / ESLint / Prettier patch bumps (@biomejs/biome 2.5.4, ESLint 10.7.0, Prettier 3.9.5). (#404)
  • pnpm run lint uses --max-warnings 0; Biome noExplicitAny, noNonNullAssertion, and noParameterAssign promote from warn to error so full-repo lint matches pre-commit. (#408)
  • CodeRabbit reviews gated on the cr label only, and path filters / path instructions expanded for generated mirrors and house TypeScript / docs rules. (#411) (#412)
  • Post-1.3.1 API-history bookkeeping: UNRELEASED_VERSION advanced and docs/_api-history.json regenerated for the next cycle. (#373)
  • Release tracking advanced toward 1.4.0 in the API-history generator metadata. (#389)

Tests

Post-process effects finally carry their own coverage floor.

  • Unit coverage for FullscreenPixelEffect / FullscreenEffect, PixelGlitch / PixelMosaic, post-process tier dispatch, and software-renderer BT.effectAdd rejection; 80% per-directory threshold for src/render/effects/**. (#392)

Documentation

Hot reload gets a guide; the rest of the docs catch up.

  • New docs/guide-hot-reload.md: swap tiers, onHotReload / HotReloadContext, the blit386:hot-reload DOM event, the asset hot-replace matrix, full-reload triggers, and the blit386/vite plugin – published via the sitemap. (#377)
  • CLAUDE.md trimmed from a session-loading monolith into short summaries with pointers; rule files become the canonical detail; AGENTS.md grows into a real standalone quick start. (#384)
  • Changelog gains the missing 1.4.0 editorial entry for the asset loading-progress API (BT.loadingAssetsCount, loader counters, SpriteSheet.status / progress). (#393)
  • Stale agent line citations removed, SECURITY.md points at GitHub private vulnerability reporting only, and CONTRIBUTING.md gets a Getting Started path. (#409)
  • Docs index, hot-reload cross-links, loading-progress guidance, and related API/guide pages refreshed after the 1.4.0 surface settled. (#414)

Full Changelog: 1.3.1...1.4.0