explodorama / commit
Plan: bug reports as animated replays (Q104), Explodorama's part
PLAN.md | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/PLAN.md b/PLAN.md index 17d299d..f218421 100644 --- a/PLAN.md +++ b/PLAN.md @@ -1516,3 +1516,72 @@ report, so the lab can compare the game before and after on the same seeds. with the lab's bots, so 19.1 comes first there too. - **19.4 needs 19.3's** acid puddles and (for the alternative) cracked floor. - **19.5 uses all of them** for its ramp, but could start with what exists today. + +## 20. Bug reports as animated replays (Q104; planned 2026-11-03, nothing built beyond §20.1) + +*A planning section. The server side (what receives, stores and links reports) is in +`~/code/fuzzyworld-tools/PLAN.md`, "Issues" → "Report replays". This section is Explodorama's part.* + +**Idea.** A bug report already holds the whole run (`Run record: {…}`, the seed and the actions; see +`reportBug` in `main.ts`). The game can replay a record exactly, so an issue page on code.fuzzyworld.net +could show *what the reporter saw* as a short looping animation, and (for autopilot or rules bugs) what +today's game does instead. A report then answers itself: no need to reproduce by hand. + +### 20.1 Built (2026-11-03, dev only; committed 351348d) + +- `npm run report-replay -- <mail>` reads a report's record (quoted-printable mail, a pasted text or a + bare record) into `replays/<name>.json` and prints page addresses. +- `?replay=<name>`: two players on one board, red = the recorded turns, blue = the same until the + autopilot took over and then today's autopilot (`sim/replayCompare.ts` `buildReplay`). +- `&rules=<commit>`: the whole run under an older commit's rules (red) and today's (blue) + (`sim/ruleCompare.ts` `compareRules`; the old `src/sim` is taken out of git into `rules-versions/`). +- The page takes no input and is removed from builds (`import.meta.env.DEV`). +- The Q101 report (autopilot walking into its own bomb with Bomb Pass) is the first fixture + (`test/fixtures/q101-bomb-pass.json`). + +### 20.2 What a published replay needs from the game (to do, in order) + +1. **A production replay entry** (`replay.html` beside `index.html`, its own small bundle, same-origin + script only, so the site's CSP `script-src 'self'` holds). It takes `?report=<same-origin json path>`, + plays the record in a loop, takes no input, saves nothing, records no scores. The dev page's code + (`replayTick`, the `rival` second player, labels) moves out of `main.ts` into a module both use; the + dev page stays as a thin wrapper that adds `?rules=`. +2. **Treat the record as hostile data.** It comes from a mail. Limits before anything runs: size at most + 64 KB, at most 20,000 actions, `seed` and `simVersion` integers, each action's shape checked; every + `step` call in a try/catch (a refused action stops that side, as `compareRules` already does); every + text shown through `textContent`, never as HTML. No path or name from the record is ever used. +3. **Which game plays it.** A report is only exact on the rules it was made under (`simVersion`). + Options, cheapest first: + - *Today's rules only*: right while `SIM_VERSION` is unchanged (the Q101 report replays exactly on + today's rules, because only the autopilot's decisions changed). A `simVersion` mismatch shows a + visible "the rules have changed since this report" banner (the dev page's label does this only in + the autopilot mode; make it show everywhere) and offers the next option. + - *The report's own sim*: `fw deploy` of a release also publishes just `state` + `turn` (+ what they + import, i.e. `src/sim` bundled as one ES module, a few tens of KB) as `/explodorama/sim/<simVersion>.js`. + The replay page loads the one matching the record, and today's for blue. One file per **rules + version**, not per commit: they change rarely. This replaces `rules-versions/` + `git archive` + for the published page; the dev page can keep using git for any commit. + - *Full old builds* per tag: heavier (each is the whole game with art); only if the sim-only way proves + not enough. +4. **Compact records.** Today a long run's record (66 turns ≈ 8 KB) does not fit a `mailto:` link + (`MAILTO_MAX` 1900), so the report asks the player to paste from the clipboard, and some will not. A + compact encoding (actions as short codes, deflate, base64url) might fit a typical run in the link. + Measure on real reports first (the Q101 one is 8 KB raw); keep the plain `Run record:` form readable + for anything that does not fit. +5. **Which fork to show.** The dev page's "autopilot took over" fork is one of several comparisons. + For a published page the default should be the plain recorded run (what the reporter saw) with the + last turns slowed, and the comparison (`&rules=` or autopilot) as an option, since an issue is often + about something no code change touched. + +### 20.3 Open points + +- Whether the replay page is part of the game's deploy (`/explodorama/replay.html`) or a separate small + app; fuzzyworld-tools decides how an app announces its viewer (see its PLAN.md). +- Whether the animated page may show the reporter's device string or error list (default: no; only the + record and the version/commit). +- The `sim/<simVersion>.js` files: who builds them (`fw deploy` with a per-app hook, or the CI runner on a + tag), and whether they are checked by a test that replays `test/fixtures/*.json` through each file. +- A **regression-fixtures habit**: every fixed bug whose report has a record keeps it in `test/fixtures/` + with a test that replays it (as Q101 does), so a published replay and a unit test stay one artefact. + +Related queue items: Q101 (the first report), Q102 (admin panel), Q103 (the dev page), Q104 (this).