Generate the manifest/PWA + native-wrapper icons that were referenced but
missing (icon-192/512 were 404). A reproducible pure-Node generator
(tools/gen-icons.mjs, npm run gen:icons) draws a clock ring with amber
hands + a green target dot in the app palette — no image deps, hand-rolled
PNG encoder with analytic anti-aliasing.
- public/icons/icon-192, -512, -180 (apple-touch); linked in index.html.
- resources/icon.png (1024) + splash.png (2732) for @capacitor/assets.
- tests/tools/icons.test.js ties every manifest icon to a real PNG of the
declared size. 213 tests pass; icons now serve 200.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Wrap the PWA in a thin native iOS shell (Capacitor 8):
- capacitor.config.json (webDir dist, appId uk.timevans.thedirector,
iOS safe-area contentInset + theme background).
- @capacitor/{core,cli,ios} as devDependencies (web app keeps zero
runtime deps); ios:add / ios:sync / ios:open / ios npm scripts.
- main.js skips service-worker registration under Capacitor
(window.Capacitor.isNativePlatform) — assets are already local.
- iOS <meta> hints in index.html; .gitignore for native build output.
- docs/native-ipad-wrapper.md: full Xcode + CocoaPods build guide,
incl. the keep-awake plugin note for the wake toggle in WKWebView.
The iOS project generation/build (npx cap add ios → Xcode) needs a Mac
with full Xcode + CocoaPods, which this env lacks; it is documented for
the user to run. tests/tools/capacitor-config.test.js guards the config.
211 tests pass; build clean.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add a deterministic authoring tool that turns a structured scenario
markdown file into a validated scenario-data module:
- tools/scenario-md.js: pure parseScenarioMarkdown + emitScenarioModule
(frontmatter → meta; ## Timeline/## Clues/## Cast lists → the arrays;
auto-slugged ids; validated via validateScenario before emit).
- tools/md-to-scenario.mjs: CLI (npm run gen:scenario), file or stdout.
- tools/example-scenario.md: documented format example.
Parses a defined format, not freeform con prose. tools/ is dev-only and
never bundled. tests/tools/scenario-md.test.js round-trips + validates.
187 tests pass; build clean.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add the last two design-§5 tray tools:
- <parking-lot>: one-tap capture of a thread to return to, stamped with
the session time, persisted per-scenario (parkingLot store key), 📝 chip.
- src/core/wake-lock.js: injectable Screen Wake Lock controller (keeps the
tablet awake, re-acquires on foreground, graceful no-op where the API is
absent). Toggled by a 💡 rail chip that lights when active.
Tests: parking-lot.test.js, wake-lock.test.js, gm-shell-parking.test.js,
gm-shell-wake.test.js. 179 tests pass; build clean.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add <break-timer> tray: pick a duration, Start break pauses the session
clock (reusing clock.pause/resume), End break resumes it — so meal/comfort
break time is excluded from elapsed and drift stays honest. The shell owns
pause/resume + persistence (break store key); the rail shows a on-break
badge and gains a coffee chip. fmtCountdown (M:SS) added to format.js.
tests/components/break-timer.test.js + gm-shell-break.test.js (incl. the
30-play/20-break/10-play drift-honesty case) + fmtCountdown. 159 tests pass.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add brp-d100 rule-pack (Basic Roleplaying roll-under): fumble on 100,
critical <= skill/20, special <= skill/5, success <= skill — bands
transcribed from the Continuum Day One console's verdict() logic.
Register it and switch day-one meta.system from coc-d100 to brp-d100.
tests/dice/brp-d100.test.js covers the ladder, low-skill rounding, and
the fumble-only-on-100 edge. 147 tests pass.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add <cast-tray>: renders scenario.cast (name + one-line note) with each
NPC secret behind a tap-to-reveal so spoilers stay off-screen at the
table. Wired into the shell as the 'cast' tool with a 👥 rail chip;
reveal state is ephemeral component state. Now the 57 ported NPCs are
visible in a running session.
tests/components/cast-tray.test.js + gm-shell-cast.test.js. 141 tests pass.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Populate cast[] (kind:'npc') for every Continuum scenario, transcribed
from the gm-utility NPC sources — normalising the two schemas (console
{id,name,ess,sec} and module {name,tag,secret}) into
{ id, name, kind, note, secret? }. 57 NPCs total. Pregens/PCs excluded
(separate character-sheet system).
No cast UI consumer yet — the design reserves scenario.cast for a future
cast dashboard, so this is a data-model port guarded by
tests/scenarios/cast.test.js (shape + unique ids). 131 tests pass.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Populate clues[] for every Continuum scenario (afterimage, day-one,
vain-crown, silvery-moon, chopper, princes-bride), transcribed faithfully
from the gm-utility console sources (CLUES arrays, gbclue GM-brief spines,
and the princes-bride module). The Slice 4 clue safety-net now works
against real content — essential-gap banner, act labels, and fallbacks.
day-one and princes-bride carry the source's own essential/optional split;
the four GM-brief spines mark each tracked clue essential (single curated
list, no optional tier in-source).
tests/scenarios/clues.test.js guards shape, unique ids, and solvability.
129 tests pass; build clean.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Rewrite continuum-2026.js from the authoritative con-desk.html SLOTS
array: six real slots with days/times/systems/players and startsAt set,
so the hub's live-now/up-next follows the real convention clock.
Add five scenario modules (day-one, vain-crown, silvery-moon, chopper,
princes-bride) transcribed from the existing gm-utility console
timelines, and register them so every slot is tappable. Day One (BRP)
borrows the coc-d100 pack; the others map to their own systems.
Corrections found while porting: the slate is six slots (Slot 5 Silvery
Moon was missing) and s6 is 'Get to the Chopper — Another Fine Mess'.
tests/con/continuum-2026.test.js guards slot resolvability, valid dice
packs, and schedule status. 125 tests pass; build clean.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add the convention hub landing screen: a pure schedule engine
(analyzeSchedule) classifies each slot as live/next/done/upcoming from an
injected now; <con-hub> renders the slate + summary and emits open-scenario;
a scenario registry resolves a slot's scenarioId to its module; gm-shell
routes hub<->session (hiding/restoring the Rail) with a home rail chip.
Ships continuum-2026.js with the real slate (only AFTERIMAGE ported;
others scenarioId:null, start-times TBC) and a fully-timed example-con.js
template/fixture. 122 tests pass; build clean.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
8 TDD tasks: noir genre pack + registry, pure NPC generator, <npc-tray>,
art search, art manifest, <prop-viewer>, <art-tray>, and shell/rail wiring
(open-tool for npc/art, keep-npc persistence, show-prop fullscreen).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
12 TDD tasks proving the vertical slice end-to-end on the AFTERIMAGE pilot:
scaffold, store, clock, timeline/drift, dice core, Year-Zero rule-pack,
scenario validator+data, formatting, <director-rail>, <dice-tray>, <gm-shell>,
and the offline PWA (manifest + service worker).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Offline-first PWA (Web Components) with an always-on Director Rail (pacing
co-pilot), one animated dice engine + system rule-packs, offline NPC/art
generators, and a per-scenario data model as source of truth. Sliced roadmap;
Slice 1 = shell + rail + data model + Year-Zero dice, proven on AFTERIMAGE.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>