# DEAD AGAIN 1.25 — THE UNDERTAKERS

Brief: assume DEAD AGAIN ships tomorrow. Find every reason it should not. No new features may be proposed. Every finding must be classified FIX, CUT, SIMPLIFY, LEAVE ALONE, or EXTERNAL RELEASE GATE.

These are simulated specialist reviewers, not real external human testers.

## The panel

1. Release engineer — deployment, cache and versioning.
2. Save-system undertaker — persistence and migration failure.
3. Mobile-storage undertaker — iOS/browser quota pressure.
4. PWA undertaker — offline/install assumptions.
5. Input undertaker — stuck buttons, focus loss, touch priority.
6. Performance undertaker — startup payload and frame-loop risks.
7. Campaign undertaker — progression/regression.
8. Puzzle undertaker — solvability and ghost dependencies.
9. UI undertaker — clutter and accidental complexity.
10. Audio undertaker — autoplay, mute and fatigue.
11. Narrative undertaker — over-explanation and ending integrity.
12. Accessibility/legibility undertaker — colour-only state and tiny text.
13. Speedrun undertaker — determinism and race integrity.
14. Web-hosting undertaker — GitHub Pages/custom-domain failure modes.
15. Mean producer — asks whether each change is actually necessary to ship.

## Findings that survived

### FIX — Rival trajectory storage
Rival PB trajectories were stored as raw arrays inside the main localStorage save. A player accumulating long PB traces across many levels could put unnecessary pressure on browser storage, particularly on mobile. The old persistence layer also swallowed quota exceptions.

Fix in 1.25:
- Rival trajectories are compacted to six binary bytes per frame and Base64 encoded on disk.
- They are transparently expanded when loading.
- Existing uncompressed saves remain readable and migrate naturally on the next write.
- If storage is ever exhausted anyway, optional Rival replays are dropped before core campaign progress, so a large ghost library cannot block a level-completion save.
- Representative trace test: 3,359 bytes of JSON -> 1,936 Base64 characters (about 57.6% of the original JSON character footprint), with exact round-trip reconstruction.

### FIX — 404 redirect
The previous `location.replace("./")` could resolve relative to an arbitrary missing path. On the custom domain that can redirect to the wrong directory.

Fix in 1.25:
- custom-domain 404s return to `/`
- `github.io` fallback returns to `/deadagain/`

### FIX — Custom-domain deployment marker
A `CNAME` file for `deadagain.fisheggs.au` is included in the Gold Candidate so a root-replacement deployment does not accidentally omit the custom-domain marker.

### SIMPLIFY — Public package
Development reports, certification JSON, raw race-trace sources, backup files, and Robot Dave tooling are valuable project history but are not runtime assets.

Gold Candidate ships them only in the separate development archive. The public web package contains the game, runtime Robot records, PWA assets, CNAME and minimal release metadata.

### LEAVE ALONE — Movement
Real user feedback said the buttons work and movement is smooth. Robot certification is built around these constants. No evidence justifies changing acceleration, speed, jump impulse, gravity, coyote time or jump buffer.

### LEAVE ALONE — 45-level campaign geometry
The final campaign has executable certificates. No Undertaker found a new geometry reason to reopen it. Narrative polish in 1.24 changed decoration only.

### LEAVE ALONE — Story
Story Deathmatch produced a coherent implicit arc without exposition. No logs, dialogue, named scientists, lore collectibles or explanatory cutscenes should be added.

### LEAVE ALONE — Audio direction
Sparse five-zone procedural motifs plus short SFX fit the game's identity. More layers would add fatigue and blur important state sounds.

### LEAVE ALONE — Robot/Rival feature set
The systems stay because they provide replay value, but the 1.23 progressive-disclosure UI remains the correct presentation. No additional medals/dashboard UI.

## Regression

After the 1.25 persistence/hosting fixes, Robot Dave was run against every level with the current real Game engine.

- Levels 1–4, 6–10, 12, 15–44: certified in the parallel campaign pass.
- Levels 5, 11, 13, 14 and 45: separately re-run with the stronger best-certification path after the general pass hit its time budget.
- Final result: **45 / 45 executable campaign levels**.

The slower five were solver-time-budget cases, not failures; all five returned successful certificates on the follow-up run.

## Structural release checks

- JavaScript syntax: pass.
- Manifest icon references: pass.
- Index local references: pass.
- Robot race benchmark records: 45.
- Secret labels: 10.
- Rival trace compression round trip: pass.
- Service-worker cache version bumped for 1.25.
- Custom-domain CNAME present.
- No movement-physics or level-geometry changes in 1.25.

## EXTERNAL RELEASE GATE — real humans and real phones

This environment cannot honestly substitute for physical-device and blind-human testing.

Before stamping final Gold, the remaining external gate is deliberately small:

1. Play the Gold Candidate on the actual target iPhone in portrait and landscape.
2. Background/foreground Safari once and confirm input/audio/save resume sanely.
3. Install as a PWA and launch offline once.
4. Have at least a few people who have not watched development play blind.
5. Do not explain the ghost premise. Observe whether they infer it.
6. Ask after play: “What do you think happened?” and “Where did the game feel unfair rather than difficult?”

Only bugs, genuine friction, or comprehension failures found there should reopen the build.

## Undertakers' shipping verdict

**CODE / CAMPAIGN: GOLD CANDIDATE.**

The game no longer needs another design pass. It needs real-device and blind-human confirmation, then bug fixes only.
