diff --git a/STATE OF WORLD.md b/STATE OF WORLD.md
new file mode 100644
index 0000000..3dd0cdb
--- /dev/null
+++ b/STATE OF WORLD.md
@@ -0,0 +1,39 @@
+# STATE OF WORLD
+
+## Baseline Snapshot
+- Date/time: 2026-03-02T20:19:29.5824836-06:00
+- Branch: `feat/xbox-controller-support`
+- Attempt: Fork `kalepail/kalien` into `tacticalnoot/kalien` and implement upstreamable Xbox controller support PR.
+
+## Git Remotes
+- `origin`: `https://github.com/tacticalnoot/kalien.git`
+- `upstream`: `https://github.com/kalepail/kalien.git`
+
+## Tool Versions
+- `bun`: `1.3.9`
+- `node`: `v22.21.1`
+- `cargo`: `cargo 1.91.1 (ea2d97820 2025-10-10)`
+- `gh auth`: logged in as `tacticalnoot` with active account
+
+## Baseline Audit Results
+- `bun install`: pass
+- Baseline `bun run check`: fail (pre-existing gate)
+ - `worker-configuration.d.ts` out of date (`wrangler types --check` fails)
+
+## Final Snapshot
+- Date/time: 2026-03-02T20:50:34.0314779-06:00
+- Branch: `feat/xbox-controller-support`
+- Controller support implementation complete in `src/game` input path.
+- Deterministic tape/replay contract unchanged.
+- Deferred pass complete: replay-mode controller shortcuts + optional controller rumble + expanded controller HUD hints.
+
+## Validation Runbook (Final)
+- `bun test tests/src/gamepad-input.test.ts`: pass (8 tests)
+- `bun run lint`: pass
+- `bun run typecheck`: fail at pre-existing `typegen:check` gate when `worker-configuration.d.ts` is not regenerated
+- `bun run check`: not fully passable in this environment without unrelated repo churn:
+ - If `worker-configuration.d.ts` is regenerated, typecheck/lint pass, then `format:check` reports existing formatting drift across ~120 files in `src/` and `worker/`.
+
+## Caveats
+- Manual browser/controller smoke test was not run in this shell session (no attached Xbox controller hardware/browser interaction in terminal workflow).
+- Full root `bun run check` remains blocked by pre-existing repository state unrelated to controller logic.
diff --git a/docs/CONTROLLER-SUPPORT-PLAN.md b/docs/CONTROLLER-SUPPORT-PLAN.md
new file mode 100644
index 0000000..0e57fff
--- /dev/null
+++ b/docs/CONTROLLER-SUPPORT-PLAN.md
@@ -0,0 +1,47 @@
+# Controller Support Plan
+
+Date: 2026-03-02
+Branch: `feat/xbox-controller-support`
+
+## Current Input Architecture
+- Keyboard events are handled by `InputController` in `src/game/input.ts`.
+- Held state (`down`) and edge state (`pressed`) are tracked per key code.
+- `LiveInputSource` in `src/game/input-source.ts` turns keyboard (or autopilot) into per-frame booleans: `left`, `right`, `thrust`, `fire`.
+- `AsteroidsGame` reads one frame input in `updateSimulation()`, records it to tape, and updates simulation.
+- Menu/pause/restart/replay controls are edge-triggered in `AsteroidsGame.handleGlobalInput()` via `consumePress(...)`.
+- Frame loop is `requestAnimationFrame -> updateFrame()`, which is suitable for per-frame gamepad polling.
+
+## Files To Touch
+- `src/game/input.ts`
+- `src/game/input-source.ts`
+- `src/game/AsteroidsGame.ts`
+- New small adapter: `src/game/gamepad.ts`
+- Focused tests under `src/game/*.test.ts`
+- Canonical docs under `docs/games/asteroids/`
+
+## Determinism Risks
+- Risk: introducing a parallel simulation path for controller input.
+ - Mitigation: controller state is normalized into existing action booleans only.
+- Risk: edge-triggered menu actions repeatedly firing while a button is held.
+ - Mitigation: track controller pressed-vs-held edges and consume once per frame.
+- Risk: stick drift causing unintended turn input.
+ - Mitigation: deadzone threshold (~0.25).
+- Risk: replay mode drift.
+ - Mitigation: tape/replay input source remains unchanged; only live input path is extended.
+
+## Implementation Plan
+1. Add controller action/edge state support to `InputController` with keyboard behavior unchanged.
+2. Add gamepad polling adapter using `navigator.getGamepads()` and Xbox-style mapping.
+3. Poll controller once per frame in `AsteroidsGame.updateFrame()`.
+4. Route gameplay booleans through unified action state (`keyboard OR controller`) in `LiveInputSource`.
+5. Route one-shot global actions through keyboard-or-controller consume methods.
+6. Add targeted tests for mapping/deadzone/edge behavior.
+7. Update docs and state notes.
+
+## Acceptance Tests
+- Left stick and D-pad map to left/right with deadzone respected.
+- A/RT maps to fire; thrust mapping is consistent and documented.
+- Start/Menu maps to start/resume/pause behavior.
+- Back/View maps to return-to-menu behavior.
+- Keyboard controls continue to behave exactly as before.
+- Per-frame deterministic booleans remain the only simulation input path.
diff --git a/docs/CONTROLLER-SUPPORT-ROLLUP.md b/docs/CONTROLLER-SUPPORT-ROLLUP.md
new file mode 100644
index 0000000..356f221
--- /dev/null
+++ b/docs/CONTROLLER-SUPPORT-ROLLUP.md
@@ -0,0 +1,58 @@
+# Controller Support Rollup
+
+Date: 2026-03-02
+Branch: `feat/xbox-controller-support`
+
+## Summary
+Added Xbox-style gamepad support to live Asteroids play by polling the browser Gamepad API each frame and normalizing state into the existing deterministic action model (`left`, `right`, `thrust`, `fire`).
+This pass also adds replay-mode controller shortcuts and optional controller rumble feedback.
+
+Keyboard controls remain unchanged and continue to work in parallel (`keyboard OR controller`).
+
+## Files Touched
+- `src/game/input.ts`
+- `src/game/input-source.ts`
+- `src/game/AsteroidsGame.ts`
+- `src/game/gamepad.ts` (new)
+- `tests/src/gamepad-input.test.ts` (new)
+- `docs/games/asteroids/README.md`
+- `docs/games/asteroids/01-GAME-SPEC.md`
+- `docs/games/asteroids/15-DOCS-PARITY-CHECKLIST.md`
+- `docs/CONTROLLER-SUPPORT-PLAN.md`
+
+## Controller Mapping
+- Left stick X < `-0.25` or d-pad left -> `left`
+- Left stick X > `0.25` or d-pad right -> `right`
+- `LT` or `LB` -> `thrust`
+- `A` or `RT` -> `fire`
+- `Start/Menu` -> start game / pause / resume (mode-dependent global action)
+- `Back/View` -> return to menu
+- Replay controls: `X=1x`, `Y=2x`, `B=4x`, `A/Start=pause`
+
+## Gamepad API Constraints
+- Uses polling (`navigator.getGamepads()`) once per animation frame.
+- Uses edge detection for one-shot controller actions (`start`, `menu`) to avoid repeated triggers while held.
+- Replay/tape format is unchanged. Controller input is only a live-input source mapped to existing booleans.
+- Optional gamepad rumble uses browser Gamepad vibration APIs when available; unsupported implementations are ignored safely.
+
+## Test Evidence
+- `bun test tests/src/gamepad-input.test.ts`
+ - 8 passing tests:
+ - deadzone behavior
+ - left/right mapping (stick + d-pad)
+ - fire/thrust/start/menu mapping
+ - replay shortcut button mapping
+ - keyboard press semantics unchanged
+ - keyboard+controller held-state merge
+ - gamepad press edge semantics
+ - replay shortcut edge semantics
+- `bun run typecheck` fails at pre-existing `typegen:check` (`worker-configuration.d.ts` out of date)
+ - with regenerated worker types, app/node/worker/script typechecks pass
+- `bun run lint` passed
+- `bun run format:check` currently fails repository-wide due pre-existing formatting drift across many files unrelated to this change.
+
+## Manual Smoke Test
+Not executed in this shell session (no browser/controller hardware attached).
+
+## Follow-up Ideas (Deferred)
+- In-game rebinding UI for controller mappings.
diff --git a/docs/games/asteroids/01-GAME-SPEC.md b/docs/games/asteroids/01-GAME-SPEC.md
index c2fbf2f..45d4ff7 100644
--- a/docs/games/asteroids/01-GAME-SPEC.md
+++ b/docs/games/asteroids/01-GAME-SPEC.md
@@ -9,6 +9,15 @@ Game state transitions must be deterministic given:
## Input Model
- 4 action bits per frame: `left`, `right`, `thrust`, `fire`.
- High nibble reserved and must be zero.
+- Live controls (keyboard/gamepad) must normalize into these same 4 bits before simulation.
+- Xbox-style controller mapping for live play:
+ - left stick X or d-pad left/right -> `left` / `right`
+ - `LT` or `LB` -> `thrust`
+ - `A` or `RT` -> `fire`
+ - `Start` -> menu start/resume/pause action (UI/global only, not tape bit)
+ - `Back/View` -> return-to-menu action (UI/global only, not tape bit)
+ - replay-only shortcuts: `X=1x`, `Y=2x`, `B=4x`, `A/Start=pause`
+- Optional controller haptics may be emitted in interactive mode; they are cosmetic and not part of deterministic replay state.
## Core Mechanics
### Ship
diff --git a/docs/games/asteroids/15-DOCS-PARITY-CHECKLIST.md b/docs/games/asteroids/15-DOCS-PARITY-CHECKLIST.md
index b54417d..7b266eb 100644
--- a/docs/games/asteroids/15-DOCS-PARITY-CHECKLIST.md
+++ b/docs/games/asteroids/15-DOCS-PARITY-CHECKLIST.md
@@ -1,6 +1,6 @@
# Asteroids Docs Parity Checklist (AST4)
-Date: 2026-02-28
+Date: 2026-03-02
## Purpose
Code-backed checklist confirming that Asteroids docs match the current TS/Rust/Worker/Contract implementation.
@@ -14,6 +14,9 @@ This is a point-in-time snapshot. Keep canonical docs updated directly; refresh
- `kalien-verifier/asteroids-core/src/constants.rs`
- Gameplay rules/math:
- `src/game/AsteroidsGame.ts`
+ - `src/game/input.ts`
+ - `src/game/input-source.ts`
+ - `src/game/gamepad.ts`
- `src/game/constants.ts`
- `kalien-verifier/asteroids-core/src/sim/mod.rs`
- `kalien-verifier/asteroids-core/src/sim/game.rs`
@@ -57,12 +60,23 @@ This is a point-in-time snapshot. Keep canonical docs updated directly; refresh
- Prover `proof_mode` is forced from `RISC0_DEV_MODE` (not request-driven).
- Score contract call is `submit_score(seal, journal_raw)`.
+7. Live input normalization
+- Live gameplay input still enters simulation only as `left/right/thrust/fire` booleans.
+- Keyboard and gamepad input are merged before simulation, and tape encoding semantics are unchanged.
+- Controller-only global actions (`Start`, `Back/View`) affect menu/pause flow only and are not serialized into tape bits.
+- Replay shortcut buttons (`X/Y/B/A/Start`) map to replay controls only and do not alter tape semantics.
+
+8. Controller haptics (cosmetic)
+- Browser gamepad rumble calls are optional runtime effects in interactive mode only.
+- Haptic effects are outside simulation state and do not influence deterministic replay, tape bytes, verifier behavior, or score outcomes.
+
## Docs Updated In This Pass
- `docs/games/asteroids/README.md`
- `docs/games/asteroids/01-GAME-SPEC.md`
- `docs/games/asteroids/02-VERIFICATION-SPEC.md`
- `docs/games/asteroids/04-INTEGER-MATH-SPEC.md`
- `docs/games/asteroids/06-IMPLEMENTATION-STATUS.md`
+- `docs/games/asteroids/15-DOCS-PARITY-CHECKLIST.md`
- `docs/archive/games/asteroids/13-ORIGINAL-RULESET-VARIANCE-AUDIT.md`
- `docs/archive/games/asteroids/14-VARIANCE-RESOLUTION-PLAN.md`
diff --git a/docs/games/asteroids/16-GAME-CONTENT-INVENTORY.md b/docs/games/asteroids/16-GAME-CONTENT-INVENTORY.md
new file mode 100644
index 0000000..e9da662
--- /dev/null
+++ b/docs/games/asteroids/16-GAME-CONTENT-INVENTORY.md
@@ -0,0 +1,138 @@
+# 16 - Game Content Inventory (AST4)
+
+## Current Build Snapshot
+- Generated from current code/docs baseline on 2026-03-02.
+- Ruleset: `AST4` (`rules_tag=4`).
+- Core deterministic input contract remains `left/right/thrust/fire` only.
+- Status: `Implemented`
+- Evidence:
+ - `src/game/tape.ts:15` (four-bit nibble mapping)
+ - `src/game/constants.ts:68` (`RULES_TAG = 4`)
+ - `docs/games/asteroids/01-GAME-SPEC.md:7`
+
+## Core Player Verbs
+| ID | Verb | Status | Evidence |
+|---|---|---|---|
+| `action_left` | Turn Left | Implemented | `src/game/tape.ts:19`, `src/game/AsteroidsGame.ts:970` |
+| `action_right` | Turn Right | Implemented | `src/game/tape.ts:20`, `src/game/AsteroidsGame.ts:971` |
+| `action_thrust` | Thrust | Implemented | `src/game/tape.ts:21`, `src/game/AsteroidsGame.ts:972` |
+| `action_fire` | Fire | Implemented | `src/game/tape.ts:22`, `src/game/AsteroidsGame.ts:1002` |
+| `action_keyboard_controls` | Keyboard Controls | Implemented | `src/game/input.ts:1`, `docs/games/asteroids/README.md:38` |
+| `action_xbox_controller` | Xbox Controller Mapping | Implemented | `src/game/gamepad.ts:3`, `src/game/input.ts:132`, `docs/games/asteroids/README.md:39` |
+
+## Game Modes
+| ID | Mode | Status | Evidence |
+|---|---|---|---|
+| `mode_menu` | Menu Mode | Implemented | `src/game/types.ts:9`, `src/game/AsteroidsGame.ts:303` |
+| `mode_playing` | Playing Mode | Implemented | `src/game/types.ts:9`, `src/game/AsteroidsGame.ts:489` |
+| `mode_paused` | Paused Mode | Implemented | `src/game/types.ts:9`, `src/game/AsteroidsGame.ts:515` |
+| `mode_game_over` | Game Over Mode | Implemented | `src/game/types.ts:9`, `src/game/AsteroidsGame.ts:700` |
+| `mode_replay` | Replay Mode | Implemented | `src/game/types.ts:9`, `src/game/AsteroidsGame.ts:1673` |
+
+## Entities
+| ID | Entity | Status | Notes |
+|---|---|---|---|
+| `entity_ship` | Player Ship | Implemented | Respawn + invulnerability timers |
+| `entity_asteroid_sizes` | Asteroid Size Chain | Implemented | Large -> Medium -> Small |
+| `weapon_ship_bullets` | Ship Bullets | Implemented | Cap + cooldown + lifetime |
+| `weapon_saucer_bullets` | Saucer Bullets | Implemented | Cap + lifetime |
+
+Evidence:
+- `src/game/types.ts:11`
+- `src/game/AsteroidsGame.ts:876`
+- `src/game/AsteroidsGame.ts:1254`
+- `src/game/constants.ts:24`
+
+## Enemies
+| ID | Enemy Group | Status | Evidence |
+|---|---|---|---|
+| `entity_asteroid_sizes` | Asteroids (large/medium/small) | Implemented | `src/game/types.ts:11`, `src/game/AsteroidsGame.ts:1479` |
+| `enemy_saucers` | Saucers (large/small) | Implemented | `src/game/types.ts:51`, `src/game/AsteroidsGame.ts:1217` |
+
+## Weapons / Attacks
+| ID | Weapon | Status | Evidence |
+|---|---|---|---|
+| `weapon_ship_bullets` | Ship Bullets | Implemented | `src/game/AsteroidsGame.ts:1003`, `src/game/constants.ts:18` |
+| `weapon_saucer_bullets` | Saucer Bullets | Implemented | `src/game/AsteroidsGame.ts:1255`, `src/game/constants.ts:21` |
+
+## Scoring Rules
+- Status: `Implemented`
+- Asteroid score bands: `20 / 50 / 100`
+- Saucer score bands: `200 / 990`
+- Extra life step: `10,000`
+- Evidence:
+ - `src/game/constants.ts:37`
+ - `src/game/constants.ts:41`
+ - `src/game/constants.ts:9`
+ - `src/game/AsteroidsGame.ts:1523`
+
+## Progression / Waves / Pressure
+- Status: `Implemented`
+- `progress_wave_system`: wave spawns scale up to 16 large asteroids.
+- `progress_anti_lurk`: `timeSinceLastKill` pressure kicks in after `360` frames.
+- Saucer concurrency by wave tier: `1`, then `2`, then `3`.
+- Evidence:
+ - `src/game/AsteroidsGame.ts:94` (`waveLargeAsteroidCount`)
+ - `src/game/AsteroidsGame.ts:102` (`maxSaucersForWave`)
+ - `src/game/AsteroidsGame.ts:1133` (`saucerLurkPressurePct`)
+ - `src/game/constants.ts:61`
+
+## Session End Conditions
+- Status: `Implemented`
+- `session_hard_cap`: game-over if frame count exceeds `MAX_GAME_FRAMES`.
+- Life exhaustion (`lives <= 0`) also causes game-over.
+- Evidence:
+ - `src/game/AsteroidsGame.ts:699`
+ - `src/game/AsteroidsGame.ts:1510`
+ - `src/game/constants.ts:65`
+
+## Determinism-Critical Rules
+- Status: `Implemented`
+- `deterministic_tape_recording`: AST4 tape format, nibble-packed body, CRC32.
+- `system_score_claim_flow`: proof/claim path bound by `(seed_id, claimant)` and `submit_score`.
+- `action_*` and progression rules feed deterministic per-frame simulation.
+- Evidence:
+ - `src/game/tape.ts:1`
+ - `worker/api/routes-proofs.ts:301`
+ - `kalien-contract/contracts/asteroids_score/src/lib.rs:125`
+ - `docs/games/asteroids/15-DOCS-PARITY-CHECKLIST.md:33`
+
+## Non-Consensus Presentation Layer
+- `cosmetic_gamepad_rumble`: Implemented
+- Scope: browser rumble only; no replay/proof/score effect.
+- Evidence:
+ - `src/game/gamepad.ts:78`
+ - `src/game/AsteroidsGame.ts:1118`
+ - `docs/games/asteroids/15-DOCS-PARITY-CHECKLIST.md:69`
+
+## Explicit Omissions / Not Present
+| ID | Feature | Status | Evidence |
+|---|---|---|---|
+| `omission_hyperspace` | Hyperspace | Absent | `docs/games/asteroids/01-GAME-SPEC.md:74` |
+| `omission_bosses` | Bosses | Absent | no gameplay symbols in `src/game` audit |
+| `omission_powerups` | Powerups and Pickups | Absent | no gameplay symbols in `src/game` audit |
+| `omission_shields` | Shield mechanics | Absent | no shield action/state; only spawn invulnerability timer |
+
+## Known Ambiguities
+| ID | Topic | Status | Follow-up |
+|---|---|---|---|
+| `unknown_hidden_menus` | Hidden menus | Unknown | Keep scanning non-gameplay UI routes for hidden dev toggles |
+| `unknown_secret_lore` | Secret lore/easter eggs | Unknown | If added, register in manifest + manual as non-consensus flavor |
+
+## Evidence Index
+- `src/game/tape.ts`
+- `src/game/constants.ts`
+- `src/game/input.ts`
+- `src/game/gamepad.ts`
+- `src/game/input-source.ts`
+- `src/game/AsteroidsGame.ts`
+- `src/game/types.ts`
+- `worker/api/routes-proofs.ts`
+- `worker/queue/consumer.ts`
+- `kalien-contract/contracts/asteroids_score/src/lib.rs`
+- `docs/games/asteroids/01-GAME-SPEC.md`
+- `docs/games/asteroids/15-DOCS-PARITY-CHECKLIST.md`
+- `docs/archive/games/asteroids/13-ORIGINAL-RULESET-VARIANCE-AUDIT.md`
+
+## Inventory IDs (Machine Cross-Check)
+`mode_menu`, `mode_playing`, `mode_paused`, `mode_game_over`, `mode_replay`, `action_left`, `action_right`, `action_thrust`, `action_fire`, `action_keyboard_controls`, `action_xbox_controller`, `entity_ship`, `entity_asteroid_sizes`, `enemy_saucers`, `weapon_ship_bullets`, `weapon_saucer_bullets`, `progress_wave_system`, `progress_anti_lurk`, `progress_extra_lives`, `session_hard_cap`, `system_replay_load_download`, `system_autopilot`, `system_leaderboard_hooks`, `system_score_claim_flow`, `cosmetic_gamepad_rumble`, `omission_hyperspace`, `omission_bosses`, `omission_powerups`, `omission_shields`, `unknown_hidden_menus`, `unknown_secret_lore`, `planned_classic_hyperspace_profile`
diff --git a/docs/games/asteroids/17-GAME-MANUAL.md b/docs/games/asteroids/17-GAME-MANUAL.md
new file mode 100644
index 0000000..134372d
--- /dev/null
+++ b/docs/games/asteroids/17-GAME-MANUAL.md
@@ -0,0 +1,137 @@
+# 17 - Game Manual (AST4)
+
+## Cover Page
+- Title: `KALIEN`
+- Subtitle: `A Deterministic Asteroids Field Manual`
+- Layout note: high-contrast retro header, center ship silhouette, wave/score strip footer.
+
+## Welcome to Kalien
+Welcome, pilot. This build is a deterministic Asteroids run machine: your run is played, recorded, and provable.
+
+## Story / Premise
+Kalien is a score-integrity arcade stack. You fly a ship through asteroid waves, record frame inputs as a compact tape, and route verified scores to Stellar settlement.
+
+## Controls
+### Keyboard Controls
+- `ArrowLeft`: Turn Left
+- `ArrowRight`: Turn Right
+- `ArrowUp`: Thrust
+- `Space`: Fire
+- `Enter`: start/resume
+- `P`: pause toggle
+- `R`: restart
+- `L`: load replay tape
+- `D`: download replay tape (game-over)
+
+### Xbox Controller Mapping
+- Left stick X or d-pad: Turn Left / Turn Right
+- `LT` or `LB`: Thrust
+- `A` or `RT`: Fire
+- `Start`: menu start and pause/resume
+- `Back/View`: return to menu
+- Replay shortcuts: `X=1x`, `Y=2x`, `B=4x`, `A/Start=pause`
+
+## Objective
+Survive and score by destroying asteroids and saucers while keeping your run deterministic and claimable.
+
+## Core Gameplay Loop
+1. Enter Playing Mode from Menu Mode.
+2. Clear wave hazards using Player Ship movement and Ship Bullets.
+3. Advance Wave Progression and manage Anti-Lurk Pressure.
+4. End in Game Over Mode (lives exhausted or Hard Run Cap reached).
+5. Use Replay Mode or Replay Load and Download workflows.
+
+## Enemies and Hazards
+### Asteroid Size Chain
+- Large asteroids split into medium.
+- Medium asteroids split into small.
+- Small asteroids are terminal.
+
+### Saucer Variants
+- Large saucers are lower precision.
+- Small saucers tighten aim under pressure and score higher.
+- Saucer Bullets add crossfire pressure.
+
+## Survival Guide
+- Keep velocity disciplined: over-thrusting under pressure leads to wrap collisions.
+- Use Turn Left and Turn Right continuously; avoid static firing lanes.
+- Break lurking behavior early; anti-lurk ramps saucer pressure.
+
+## Scoring and Extra Lives
+- Asteroids: `20 / 50 / 100`
+- Saucers: `200 / 990`
+- Extra Lives every `10,000` points
+
+## Waves and Difficulty Curve
+- Wave count ramps large asteroid count to a cap.
+- Saucer spawn and fire cadence scale with wave and pressure.
+- Hard Run Cap enforces bounded run length (`36,000` frames).
+
+## Replay / Tape / Proof / Fairness
+- Each frame stores four deterministic actions.
+- Tape is AST4 nibble-packed with checksum.
+- Proof jobs bind `seed_id` and claimant.
+- Score Claim Flow settles verified runs on-chain.
+
+## How Stellar Integration Fits In
+- Worker accepts proof jobs and validates tape format/rules.
+- Contract `submit_score` enforces claimant-seed best-score policy.
+- Leaderboard Hooks surface succeeded claimed runs.
+
+## Modes / Menus / Replays
+- Menu Mode: start/load entrypoint.
+- Playing Mode: live simulation.
+- Paused Mode: session interrupt.
+- Replay Mode: visual playback controls.
+- Game Over Mode: terminal state and tape download point.
+
+## Glossary
+- `AST4`: current deterministic rules tag.
+- `Tape`: serialized run input stream with footer score/checksum.
+- `seed_id`: epoch-bound seed window id for settlement.
+- `claimant`: Stellar account/contract receiving score outcome.
+
+## What This Build Does Not Include
+- Hyperspace
+- Bosses
+- Powerups and Pickups
+- Shield mechanics
+
+## Strategy Tips
+- Prioritize lane control over frantic spinning.
+- Farm safely: keep saucer pressure manageable before greed plays.
+- Use replay speed controls to study positioning mistakes.
+
+## Appendix: Deterministic Rules at a Glance
+- Input contract: `left/right/thrust/fire` only.
+- Fixed timestep: `60 Hz`.
+- Run cap: `MAX_GAME_FRAMES = 36,000`.
+- Rules tag: `4 (AST4)`.
+
+## Implementation Index
+The following player-visible implemented systems are present in this build:
+- Menu Mode
+- Playing Mode
+- Paused Mode
+- Game Over Mode
+- Replay Mode
+- Turn Left
+- Turn Right
+- Thrust
+- Fire
+- Keyboard Controls
+- Xbox Controller Mapping
+- Player Ship
+- Asteroid Size Chain
+- Saucer Variants
+- Ship Bullets
+- Saucer Bullets
+- Wave Progression
+- Anti-Lurk Pressure
+- Extra Lives
+- Hard Run Cap
+- Replay Load and Download
+- Autopilot
+- Leaderboard Hooks
+- Score Claim Flow
+- Gamepad Rumble
diff --git a/docs/games/asteroids/18-GAME-CONTENT-MANIFEST.json b/docs/games/asteroids/18-GAME-CONTENT-MANIFEST.json
new file mode 100644
index 0000000..25a35aa
--- /dev/null
+++ b/docs/games/asteroids/18-GAME-CONTENT-MANIFEST.json
@@ -0,0 +1,853 @@
+{
+ "generated_at": "2026-03-03T03:34:23.278Z",
+ "repo_commit": "47bd408",
+ "rules_tag": 4,
+ "game_identity": {
+ "name": "Kalien",
+ "genre": "Deterministic Asteroids",
+ "core_claim": "Seeded frame-input tapes are replayed for proof and settled as claimant-bound scores on Stellar."
+ },
+ "modes": [
+ {
+ "id": "mode_menu",
+ "name": "Menu Mode",
+ "category": "I. UI / Modes / Replay",
+ "status": "Implemented",
+ "player_visible": true,
+ "determinism_critical": false,
+ "current_behavior_summary": "Main menu state for start/load flow and seed waiting.",
+ "balancing_notes": "UI-only state.",
+ "progression_role": "Run/replay entry point.",
+ "related_constants": [],
+ "related_tests": [],
+ "evidence_refs": [
+ "src/game/types.ts:9 (mode enum includes menu)"
+ ],
+ "change_risk": "Medium",
+ "future_design_constraints": "Keep start transitions deterministic once gameplay begins."
+ },
+ {
+ "id": "mode_playing",
+ "name": "Playing Mode",
+ "category": "I. UI / Modes / Replay",
+ "status": "Implemented",
+ "player_visible": true,
+ "determinism_critical": true,
+ "current_behavior_summary": "Active simulation and recording mode.",
+ "balancing_notes": "Main gameplay tuning state.",
+ "progression_role": "Primary run mode.",
+ "related_constants": [
+ "FIXED_TIMESTEP",
+ "MAX_GAME_FRAMES"
+ ],
+ "related_tests": [],
+ "evidence_refs": [
+ "src/game/types.ts:9 (mode enum includes playing)",
+ "src/game/AsteroidsGame.ts:294 (runtime transitions)"
+ ],
+ "change_risk": "High",
+ "future_design_constraints": "Preserve frame-step order and tape recording."
+ },
+ {
+ "id": "mode_paused",
+ "name": "Paused Mode",
+ "category": "I. UI / Modes / Replay",
+ "status": "Implemented",
+ "player_visible": true,
+ "determinism_critical": false,
+ "current_behavior_summary": "Pause state for runtime and visibility changes.",
+ "balancing_notes": "No tape semantic impact.",
+ "progression_role": "Session control.",
+ "related_constants": [],
+ "related_tests": [],
+ "evidence_refs": [
+ "src/game/AsteroidsGame.ts:293 (paused branch handling)"
+ ],
+ "change_risk": "Low",
+ "future_design_constraints": "Keep edge-triggered pause behavior."
+ },
+ {
+ "id": "mode_game_over",
+ "name": "Game Over Mode",
+ "category": "I. UI / Modes / Replay",
+ "status": "Implemented",
+ "player_visible": true,
+ "determinism_critical": true,
+ "current_behavior_summary": "Terminal state after life exhaustion or run cap.",
+ "balancing_notes": "Defines final score boundary.",
+ "progression_role": "Run termination.",
+ "related_constants": [
+ "MAX_GAME_FRAMES",
+ "STARTING_LIVES"
+ ],
+ "related_tests": [],
+ "evidence_refs": [
+ "src/game/AsteroidsGame.ts:458 (terminal transition)"
+ ],
+ "change_risk": "High",
+ "future_design_constraints": "Keep terminal conditions aligned with replay/proof flow."
+ },
+ {
+ "id": "mode_replay",
+ "name": "Replay Mode",
+ "category": "I. UI / Modes / Replay",
+ "status": "Implemented",
+ "player_visible": true,
+ "determinism_critical": true,
+ "current_behavior_summary": "Visual replay from tape bytes with speed/pause controls.",
+ "balancing_notes": "Replay controls are non-scoring.",
+ "progression_role": "Post-run inspection mode.",
+ "related_constants": [
+ "RULES_TAG"
+ ],
+ "related_tests": [],
+ "evidence_refs": [
+ "src/game/AsteroidsGame.ts:1673 (loadReplay sets replay mode)"
+ ],
+ "change_risk": "High",
+ "future_design_constraints": "Keep replay visual-only for claim path."
+ }
+ ],
+ "player_actions": [
+ {
+ "id": "action_left",
+ "name": "Turn Left",
+ "category": "A. Core Mechanics",
+ "status": "Implemented",
+ "player_visible": true,
+ "determinism_critical": true,
+ "current_behavior_summary": "Left input bit rotates ship left.",
+ "balancing_notes": "Core handling control.",
+ "progression_role": "Primary movement verb.",
+ "related_constants": [
+ "SHIP_TURN_SPEED_BAM"
+ ],
+ "related_tests": [
+ "tests/src/gamepad-input.test.ts"
+ ],
+ "evidence_refs": [
+ "src/game/tape.ts:19 (tape bit mapping)",
+ "src/game/AsteroidsGame.ts:968 (simulation read)"
+ ],
+ "change_risk": "High",
+ "future_design_constraints": "Must stay encoded in the four-bit input model."
+ },
+ {
+ "id": "action_right",
+ "name": "Turn Right",
+ "category": "A. Core Mechanics",
+ "status": "Implemented",
+ "player_visible": true,
+ "determinism_critical": true,
+ "current_behavior_summary": "Right input bit rotates ship right.",
+ "balancing_notes": "Core handling control.",
+ "progression_role": "Primary movement verb.",
+ "related_constants": [
+ "SHIP_TURN_SPEED_BAM"
+ ],
+ "related_tests": [
+ "tests/src/gamepad-input.test.ts"
+ ],
+ "evidence_refs": [
+ "src/game/tape.ts:20 (tape bit mapping)",
+ "src/game/AsteroidsGame.ts:969 (simulation read)"
+ ],
+ "change_risk": "High",
+ "future_design_constraints": "Must stay encoded in the four-bit input model."
+ },
+ {
+ "id": "action_thrust",
+ "name": "Thrust",
+ "category": "A. Core Mechanics",
+ "status": "Implemented",
+ "player_visible": true,
+ "determinism_critical": true,
+ "current_behavior_summary": "Thrust input bit accelerates ship velocity.",
+ "balancing_notes": "Bounded by drag and max speed.",
+ "progression_role": "Primary movement verb.",
+ "related_constants": [
+ "SHIP_THRUST_Q8_8",
+ "SHIP_MAX_SPEED_Q8_8"
+ ],
+ "related_tests": [
+ "tests/src/gamepad-input.test.ts"
+ ],
+ "evidence_refs": [
+ "src/game/tape.ts:21 (tape bit mapping)",
+ "src/game/AsteroidsGame.ts:970 (simulation read)"
+ ],
+ "change_risk": "High",
+ "future_design_constraints": "Must stay encoded in the four-bit input model."
+ },
+ {
+ "id": "action_fire",
+ "name": "Fire",
+ "category": "A. Core Mechanics",
+ "status": "Implemented",
+ "player_visible": true,
+ "determinism_critical": true,
+ "current_behavior_summary": "Fire input bit edge-triggers shot creation with cooldown/cap checks.",
+ "balancing_notes": "Fire latch + cooldown curb autofire.",
+ "progression_role": "Primary offensive verb.",
+ "related_constants": [
+ "SHIP_BULLET_LIMIT",
+ "SHIP_BULLET_COOLDOWN_FRAMES"
+ ],
+ "related_tests": [
+ "tests/src/gamepad-input.test.ts"
+ ],
+ "evidence_refs": [
+ "src/game/tape.ts:22 (tape bit mapping)",
+ "src/game/AsteroidsGame.ts:278 (fire edge logic)"
+ ],
+ "change_risk": "High",
+ "future_design_constraints": "Preserve latch and cooldown semantics."
+ },
+ {
+ "id": "action_keyboard_controls",
+ "name": "Keyboard Controls",
+ "category": "A. Core Mechanics",
+ "status": "Implemented",
+ "player_visible": true,
+ "determinism_critical": true,
+ "current_behavior_summary": "ArrowLeft/ArrowRight/ArrowUp/Space map to core gameplay actions.",
+ "balancing_notes": "Reference control path.",
+ "progression_role": "Default live input path.",
+ "related_constants": [],
+ "related_tests": [
+ "tests/src/gamepad-input.test.ts"
+ ],
+ "evidence_refs": [
+ "src/game/input.ts:2 (keyboard mapping list)"
+ ],
+ "change_risk": "Medium",
+ "future_design_constraints": "Keep key mapping in sync with docs and UI."
+ },
+ {
+ "id": "action_xbox_controller",
+ "name": "Xbox Controller Mapping",
+ "category": "A. Core Mechanics",
+ "status": "Implemented",
+ "player_visible": true,
+ "determinism_critical": true,
+ "current_behavior_summary": "Gamepad polling maps stick/dpad/buttons into existing action booleans.",
+ "balancing_notes": "0.25 deadzone avoids twitch turns.",
+ "progression_role": "Alternative live input device.",
+ "related_constants": [],
+ "related_tests": [
+ "tests/src/gamepad-input.test.ts"
+ ],
+ "evidence_refs": [
+ "src/game/gamepad.ts:3 (deadzone)",
+ "src/game/input.ts:132 (merged state)",
+ "docs/games/asteroids/README.md:44 (canonical docs)"
+ ],
+ "change_risk": "Medium",
+ "future_design_constraints": "Controller-only global actions must not alter tape bits."
+ }
+ ],
+ "entities": [
+ {
+ "id": "entity_ship",
+ "name": "Player Ship",
+ "category": "B. Entities",
+ "status": "Implemented",
+ "player_visible": true,
+ "determinism_critical": true,
+ "current_behavior_summary": "Single controllable ship with deterministic respawn + invulnerability timers.",
+ "balancing_notes": "Lives and respawn safety shape survival.",
+ "progression_role": "Player avatar.",
+ "related_constants": [
+ "SHIP_RESPAWN_FRAMES",
+ "SHIP_SPAWN_INVULNERABLE_FRAMES",
+ "STARTING_LIVES"
+ ],
+ "related_tests": [],
+ "evidence_refs": [
+ "src/game/types.ts:33 (ship type)",
+ "src/game/AsteroidsGame.ts:744 (ship creation)"
+ ],
+ "change_risk": "High",
+ "future_design_constraints": "Preserve deterministic spawn logic."
+ },
+ {
+ "id": "entity_asteroid_sizes",
+ "name": "Asteroid Size Chain",
+ "category": "B. Entities",
+ "status": "Implemented",
+ "player_visible": true,
+ "determinism_critical": true,
+ "current_behavior_summary": "Asteroids split large -> medium -> small and then are removed.",
+ "balancing_notes": "Split density drives pressure.",
+ "progression_role": "Wave core hazard ladder.",
+ "related_constants": [
+ "SCORE_LARGE_ASTEROID",
+ "SCORE_MEDIUM_ASTEROID",
+ "SCORE_SMALL_ASTEROID"
+ ],
+ "related_tests": [],
+ "evidence_refs": [
+ "src/game/types.ts:11 (size enum)",
+ "src/game/AsteroidsGame.ts:1481 (split chain)"
+ ],
+ "change_risk": "High",
+ "future_design_constraints": "Keep split ordering and cap checks deterministic."
+ },
+ {
+ "id": "weapon_ship_bullets",
+ "name": "Ship Bullets",
+ "category": "D. Weapons / Attacks",
+ "status": "Implemented",
+ "player_visible": true,
+ "determinism_critical": true,
+ "current_behavior_summary": "Player bullets are cap-limited and lifetime-limited.",
+ "balancing_notes": "Cap and cooldown prevent sustained spam.",
+ "progression_role": "Primary kill/scoring tool.",
+ "related_constants": [
+ "SHIP_BULLET_LIMIT",
+ "SHIP_BULLET_LIFETIME_FRAMES",
+ "SHIP_BULLET_COOLDOWN_FRAMES"
+ ],
+ "related_tests": [],
+ "evidence_refs": [
+ "src/game/AsteroidsGame.ts:28 (ship bullet cap)",
+ "src/game/AsteroidsGame.ts:1080 (ship bullet life)"
+ ],
+ "change_risk": "High",
+ "future_design_constraints": "Do not bypass cap/cooldown/latch checks."
+ },
+ {
+ "id": "weapon_saucer_bullets",
+ "name": "Saucer Bullets",
+ "category": "D. Weapons / Attacks",
+ "status": "Implemented",
+ "player_visible": true,
+ "determinism_critical": true,
+ "current_behavior_summary": "Saucer bullets are cap-limited and lifetime-limited.",
+ "balancing_notes": "Crossfire ceiling prevents runaway density.",
+ "progression_role": "Enemy offensive channel.",
+ "related_constants": [
+ "SAUCER_BULLET_LIMIT",
+ "SAUCER_BULLET_LIFETIME_FRAMES"
+ ],
+ "related_tests": [],
+ "evidence_refs": [
+ "src/game/AsteroidsGame.ts:12 (saucer bullet cap)",
+ "src/game/AsteroidsGame.ts:1290 (saucer bullet life)"
+ ],
+ "change_risk": "High",
+ "future_design_constraints": "Keep cap and cooldown deterministic."
+ }
+ ],
+ "enemies": [
+ {
+ "id": "entity_asteroid_sizes",
+ "name": "Asteroid Size Chain",
+ "category": "B. Entities",
+ "status": "Implemented",
+ "player_visible": true,
+ "determinism_critical": true,
+ "current_behavior_summary": "Asteroids split large -> medium -> small and then are removed.",
+ "balancing_notes": "Split density drives pressure.",
+ "progression_role": "Wave core hazard ladder.",
+ "related_constants": [
+ "SCORE_LARGE_ASTEROID",
+ "SCORE_MEDIUM_ASTEROID",
+ "SCORE_SMALL_ASTEROID"
+ ],
+ "related_tests": [],
+ "evidence_refs": [
+ "src/game/types.ts:11 (size enum)",
+ "src/game/AsteroidsGame.ts:1481 (split chain)"
+ ],
+ "change_risk": "High",
+ "future_design_constraints": "Keep split ordering and cap checks deterministic."
+ },
+ {
+ "id": "enemy_saucers",
+ "name": "Saucer Variants",
+ "category": "C. Enemies",
+ "status": "Implemented",
+ "player_visible": true,
+ "determinism_critical": true,
+ "current_behavior_summary": "Large and small saucers spawn with pressure-scaled cadence and aim.",
+ "balancing_notes": "Small saucers are high-risk/high-reward.",
+ "progression_role": "Secondary enemy pressure channel.",
+ "related_constants": [
+ "SCORE_LARGE_SAUCER",
+ "SCORE_SMALL_SAUCER",
+ "SAUCER_BULLET_LIMIT"
+ ],
+ "related_tests": [],
+ "evidence_refs": [
+ "src/game/AsteroidsGame.ts:101 (wave concurrency)",
+ "src/game/AsteroidsGame.ts:1155 (small saucer aim)"
+ ],
+ "change_risk": "High",
+ "future_design_constraints": "Keep pressure function deterministic and mirrored in verifier core."
+ }
+ ],
+ "weapons": [
+ {
+ "id": "weapon_ship_bullets",
+ "name": "Ship Bullets",
+ "category": "D. Weapons / Attacks",
+ "status": "Implemented",
+ "player_visible": true,
+ "determinism_critical": true,
+ "current_behavior_summary": "Player bullets are cap-limited and lifetime-limited.",
+ "balancing_notes": "Cap and cooldown prevent sustained spam.",
+ "progression_role": "Primary kill/scoring tool.",
+ "related_constants": [
+ "SHIP_BULLET_LIMIT",
+ "SHIP_BULLET_LIFETIME_FRAMES",
+ "SHIP_BULLET_COOLDOWN_FRAMES"
+ ],
+ "related_tests": [],
+ "evidence_refs": [
+ "src/game/AsteroidsGame.ts:28 (ship bullet cap)",
+ "src/game/AsteroidsGame.ts:1080 (ship bullet life)"
+ ],
+ "change_risk": "High",
+ "future_design_constraints": "Do not bypass cap/cooldown/latch checks."
+ },
+ {
+ "id": "weapon_saucer_bullets",
+ "name": "Saucer Bullets",
+ "category": "D. Weapons / Attacks",
+ "status": "Implemented",
+ "player_visible": true,
+ "determinism_critical": true,
+ "current_behavior_summary": "Saucer bullets are cap-limited and lifetime-limited.",
+ "balancing_notes": "Crossfire ceiling prevents runaway density.",
+ "progression_role": "Enemy offensive channel.",
+ "related_constants": [
+ "SAUCER_BULLET_LIMIT",
+ "SAUCER_BULLET_LIFETIME_FRAMES"
+ ],
+ "related_tests": [],
+ "evidence_refs": [
+ "src/game/AsteroidsGame.ts:12 (saucer bullet cap)",
+ "src/game/AsteroidsGame.ts:1290 (saucer bullet life)"
+ ],
+ "change_risk": "High",
+ "future_design_constraints": "Keep cap and cooldown deterministic."
+ }
+ ],
+ "progression": {
+ "summary": "Wave-driven asteroid pacing with pressure-scaled saucer threat.",
+ "wave_model": "Waves increment and large asteroid count ramps 4,6,8,10 then +1 to cap 16.",
+ "anti_lurk": "After 360 frames without asteroid kills, anti-lurk pressure accelerates saucer behavior.",
+ "saucer_pressure": "Wave+lurk pressure compresses saucer cooldown windows and small-saucer aim error.",
+ "evidence_refs": [
+ "src/game/AsteroidsGame.ts:94",
+ "src/game/AsteroidsGame.ts:234"
+ ]
+ },
+ "scoring": {
+ "summary": "Scoring comes from asteroid/saucer destruction and grants extra lives every 10,000 points.",
+ "score_bands": {
+ "asteroid_large": 20,
+ "asteroid_medium": 50,
+ "asteroid_small": 100,
+ "saucer_large": 200,
+ "saucer_small": 990
+ },
+ "extra_life_step": 10000,
+ "evidence_refs": [
+ "src/game/constants.ts:37",
+ "src/game/AsteroidsGame.ts:204"
+ ]
+ },
+ "session_constraints": {
+ "max_game_frames": 36000,
+ "fixed_timestep_hz": 60,
+ "requires_seed_and_seed_id_for_claim": true,
+ "deterministic_constants": {
+ "RULES_TAG": 4,
+ "MAX_GAME_FRAMES": 36000,
+ "STARTING_LIVES": 3,
+ "EXTRA_LIFE_SCORE_STEP": 10000,
+ "SHIP_BULLET_LIMIT": 4,
+ "SAUCER_BULLET_LIMIT": 2,
+ "SHIP_RESPAWN_FRAMES": 75,
+ "SHIP_SPAWN_INVULNERABLE_FRAMES": 120,
+ "LURK_TIME_THRESHOLD_FRAMES": 360,
+ "LURK_SAUCER_SPAWN_FAST_FRAMES": 180
+ },
+ "evidence_refs": [
+ "src/game/constants.ts:65",
+ "worker/api/routes-proofs.ts:309",
+ "kalien-contract/contracts/asteroids_score/src/lib.rs:125"
+ ]
+ },
+ "determinism_critical": [
+ {
+ "id": "action_left",
+ "name": "Turn Left",
+ "category": "A. Core Mechanics",
+ "status": "Implemented",
+ "player_visible": true,
+ "determinism_critical": true,
+ "current_behavior_summary": "Left input bit rotates ship left.",
+ "balancing_notes": "Core handling control.",
+ "progression_role": "Primary movement verb.",
+ "related_constants": [
+ "SHIP_TURN_SPEED_BAM"
+ ],
+ "related_tests": [
+ "tests/src/gamepad-input.test.ts"
+ ],
+ "evidence_refs": [
+ "src/game/tape.ts:19 (tape bit mapping)",
+ "src/game/AsteroidsGame.ts:968 (simulation read)"
+ ],
+ "change_risk": "High",
+ "future_design_constraints": "Must stay encoded in the four-bit input model."
+ },
+ {
+ "id": "action_right",
+ "name": "Turn Right",
+ "category": "A. Core Mechanics",
+ "status": "Implemented",
+ "player_visible": true,
+ "determinism_critical": true,
+ "current_behavior_summary": "Right input bit rotates ship right.",
+ "balancing_notes": "Core handling control.",
+ "progression_role": "Primary movement verb.",
+ "related_constants": [
+ "SHIP_TURN_SPEED_BAM"
+ ],
+ "related_tests": [
+ "tests/src/gamepad-input.test.ts"
+ ],
+ "evidence_refs": [
+ "src/game/tape.ts:20 (tape bit mapping)",
+ "src/game/AsteroidsGame.ts:969 (simulation read)"
+ ],
+ "change_risk": "High",
+ "future_design_constraints": "Must stay encoded in the four-bit input model."
+ },
+ {
+ "id": "action_thrust",
+ "name": "Thrust",
+ "category": "A. Core Mechanics",
+ "status": "Implemented",
+ "player_visible": true,
+ "determinism_critical": true,
+ "current_behavior_summary": "Thrust input bit accelerates ship velocity.",
+ "balancing_notes": "Bounded by drag and max speed.",
+ "progression_role": "Primary movement verb.",
+ "related_constants": [
+ "SHIP_THRUST_Q8_8",
+ "SHIP_MAX_SPEED_Q8_8"
+ ],
+ "related_tests": [
+ "tests/src/gamepad-input.test.ts"
+ ],
+ "evidence_refs": [
+ "src/game/tape.ts:21 (tape bit mapping)",
+ "src/game/AsteroidsGame.ts:970 (simulation read)"
+ ],
+ "change_risk": "High",
+ "future_design_constraints": "Must stay encoded in the four-bit input model."
+ },
+ {
+ "id": "action_fire",
+ "name": "Fire",
+ "category": "A. Core Mechanics",
+ "status": "Implemented",
+ "player_visible": true,
+ "determinism_critical": true,
+ "current_behavior_summary": "Fire input bit edge-triggers shot creation with cooldown/cap checks.",
+ "balancing_notes": "Fire latch + cooldown curb autofire.",
+ "progression_role": "Primary offensive verb.",
+ "related_constants": [
+ "SHIP_BULLET_LIMIT",
+ "SHIP_BULLET_COOLDOWN_FRAMES"
+ ],
+ "related_tests": [
+ "tests/src/gamepad-input.test.ts"
+ ],
+ "evidence_refs": [
+ "src/game/tape.ts:22 (tape bit mapping)",
+ "src/game/AsteroidsGame.ts:278 (fire edge logic)"
+ ],
+ "change_risk": "High",
+ "future_design_constraints": "Preserve latch and cooldown semantics."
+ },
+ {
+ "id": "progress_wave_system",
+ "name": "Wave Progression",
+ "category": "F. Progression / Pressure / Pacing",
+ "status": "Implemented",
+ "player_visible": true,
+ "determinism_critical": true,
+ "current_behavior_summary": "Wave count increments and large asteroid count ramps to cap 16.",
+ "balancing_notes": "Primary difficulty curve.",
+ "progression_role": "Pacing backbone.",
+ "related_constants": [
+ "ASTEROID_CAP"
+ ],
+ "related_tests": [],
+ "evidence_refs": [
+ "src/game/AsteroidsGame.ts:94 (wave function)"
+ ],
+ "change_risk": "High",
+ "future_design_constraints": "Maintain deterministic wave spawn curve."
+ },
+ {
+ "id": "progress_anti_lurk",
+ "name": "Anti-Lurk Pressure",
+ "category": "F. Progression / Pressure / Pacing",
+ "status": "Implemented",
+ "player_visible": true,
+ "determinism_critical": true,
+ "current_behavior_summary": "timeSinceLastKill raises saucer pressure after 360 frames.",
+ "balancing_notes": "Punishes passive play.",
+ "progression_role": "Secondary pacing accelerator.",
+ "related_constants": [
+ "LURK_TIME_THRESHOLD_FRAMES",
+ "LURK_SAUCER_SPAWN_FAST_FRAMES"
+ ],
+ "related_tests": [],
+ "evidence_refs": [
+ "src/game/AsteroidsGame.ts:234 (anti-lurk timer)"
+ ],
+ "change_risk": "High",
+ "future_design_constraints": "Keep thresholds deterministic."
+ },
+ {
+ "id": "progress_extra_lives",
+ "name": "Extra Lives",
+ "category": "E. Scoring / Rewards",
+ "status": "Implemented",
+ "player_visible": true,
+ "determinism_critical": true,
+ "current_behavior_summary": "Starting lives are 3; each 10,000 points grants one extra life.",
+ "balancing_notes": "Survival reward loop.",
+ "progression_role": "Run extension reward.",
+ "related_constants": [
+ "STARTING_LIVES",
+ "EXTRA_LIFE_SCORE_STEP"
+ ],
+ "related_tests": [],
+ "evidence_refs": [
+ "src/game/constants.ts:8 (start lives)",
+ "src/game/AsteroidsGame.ts:204 (extra life threshold)"
+ ],
+ "change_risk": "High",
+ "future_design_constraints": "Keep threshold logic deterministic."
+ },
+ {
+ "id": "session_hard_cap",
+ "name": "Hard Run Cap",
+ "category": "G. Session Conditions",
+ "status": "Implemented",
+ "player_visible": true,
+ "determinism_critical": true,
+ "current_behavior_summary": "Run ends at MAX_GAME_FRAMES (36,000 frames, ~10 minutes at 60 FPS).",
+ "balancing_notes": "Controls proving cost/time ceiling.",
+ "progression_role": "Hard session boundary.",
+ "related_constants": [
+ "MAX_GAME_FRAMES"
+ ],
+ "related_tests": [],
+ "evidence_refs": [
+ "src/game/constants.ts:65 (cap constant)",
+ "src/game/AsteroidsGame.ts:699 (cap enforcement)"
+ ],
+ "change_risk": "High",
+ "future_design_constraints": "Changing cap requires changelog + docs + cost review."
+ },
+ {
+ "id": "system_score_claim_flow",
+ "name": "Score Claim Flow",
+ "category": "H. Determinism / Verification",
+ "status": "Implemented",
+ "player_visible": true,
+ "determinism_critical": true,
+ "current_behavior_summary": "Proof jobs require seed_id+claimant and relay submit_score(seal,journal_raw).",
+ "balancing_notes": "Only improved claimant/seed scores mint rewards.",
+ "progression_role": "On-chain settlement.",
+ "related_constants": [
+ "RULES_DIGEST"
+ ],
+ "related_tests": [
+ "tests/worker/queue-consumer.test.ts"
+ ],
+ "evidence_refs": [
+ "worker/api/routes-proofs.ts:309 (proof query requirement)",
+ "kalien-contract/contracts/asteroids_score/src/lib.rs:125 (contract submit)"
+ ],
+ "change_risk": "Critical",
+ "future_design_constraints": "No bypass of claimant/seed and journal digest checks."
+ }
+ ],
+ "non_consensus_cosmetics": [
+ {
+ "id": "cosmetic_gamepad_rumble",
+ "name": "Gamepad Rumble",
+ "category": "J. Presentation / Cosmetic",
+ "status": "Implemented",
+ "player_visible": true,
+ "determinism_critical": false,
+ "current_behavior_summary": "Optional Gamepad API rumble effects on fire/ship-loss/extra-life.",
+ "balancing_notes": "No gameplay-state effect.",
+ "progression_role": "Feedback-only presentation.",
+ "related_constants": [],
+ "related_tests": [],
+ "evidence_refs": [
+ "src/game/gamepad.ts:80",
+ "src/game/AsteroidsGame.ts:1087"
+ ],
+ "change_risk": "Low",
+ "future_design_constraints": "Keep non-consensus."
+ }
+ ],
+ "explicit_omissions": [
+ {
+ "id": "omission_hyperspace",
+ "name": "Hyperspace",
+ "category": "L. Archived / Planned / Removed",
+ "status": "Absent",
+ "player_visible": true,
+ "determinism_critical": false,
+ "current_behavior_summary": "Hyperspace is explicitly omitted in AST4.",
+ "balancing_notes": "Keeps control and proof surface small.",
+ "progression_role": "Explicit omission.",
+ "related_constants": [],
+ "related_tests": [],
+ "evidence_refs": [
+ "docs/games/asteroids/01-GAME-SPEC.md:75 (explicit omission)",
+ "docs/archive/games/asteroids/13-ORIGINAL-RULESET-VARIANCE-AUDIT.md:27 (archive note)"
+ ],
+ "change_risk": "High",
+ "future_design_constraints": "Would require deterministic rules and docs updates if added."
+ },
+ {
+ "id": "omission_bosses",
+ "name": "Bosses",
+ "category": "L. Archived / Planned / Removed",
+ "status": "Absent",
+ "player_visible": true,
+ "determinism_critical": false,
+ "current_behavior_summary": "No boss system exists in current AST4 gameplay.",
+ "balancing_notes": "Current pacing uses waves+saucers, not boss gates.",
+ "progression_role": "Explicit omission.",
+ "related_constants": [],
+ "related_tests": [],
+ "evidence_refs": [],
+ "change_risk": "Medium",
+ "future_design_constraints": "Adding bosses requires full inventory/docs/test pass."
+ },
+ {
+ "id": "omission_powerups",
+ "name": "Powerups and Pickups",
+ "category": "L. Archived / Planned / Removed",
+ "status": "Absent",
+ "player_visible": true,
+ "determinism_critical": false,
+ "current_behavior_summary": "No powerup or pickup entities are implemented.",
+ "balancing_notes": "Current score model is destruction-only.",
+ "progression_role": "Explicit omission.",
+ "related_constants": [],
+ "related_tests": [],
+ "evidence_refs": [],
+ "change_risk": "Medium",
+ "future_design_constraints": "If added, define deterministic spawn/pickup rules first."
+ },
+ {
+ "id": "omission_shields",
+ "name": "Shield Mechanics",
+ "category": "L. Archived / Planned / Removed",
+ "status": "Absent",
+ "player_visible": true,
+ "determinism_critical": false,
+ "current_behavior_summary": "No shield resource/action; only fixed spawn invulnerability timer exists.",
+ "balancing_notes": "Avoid conflating invulnerability timer with shield feature.",
+ "progression_role": "Explicit omission.",
+ "related_constants": [
+ "SHIP_SPAWN_INVULNERABLE_FRAMES"
+ ],
+ "related_tests": [],
+ "evidence_refs": [],
+ "change_risk": "Medium",
+ "future_design_constraints": "Document separately if shield systems are introduced."
+ }
+ ],
+ "unknowns": [
+ {
+ "id": "unknown_hidden_menus",
+ "name": "Hidden Menus",
+ "category": "M. Unknown / Needs Verification",
+ "status": "Unknown",
+ "player_visible": true,
+ "determinism_critical": false,
+ "current_behavior_summary": "No hidden menu flow is evident in audited gameplay paths.",
+ "balancing_notes": "N/A.",
+ "progression_role": "N/A.",
+ "related_constants": [],
+ "related_tests": [],
+ "evidence_refs": [],
+ "change_risk": "Low",
+ "future_design_constraints": "If hidden flows are added, classify and document them."
+ },
+ {
+ "id": "unknown_secret_lore",
+ "name": "Secret Lore or Easter Eggs",
+ "category": "M. Unknown / Needs Verification",
+ "status": "Unknown",
+ "player_visible": true,
+ "determinism_critical": false,
+ "current_behavior_summary": "No dedicated lore registry is visible in core gameplay files.",
+ "balancing_notes": "N/A.",
+ "progression_role": "N/A.",
+ "related_constants": [],
+ "related_tests": [],
+ "evidence_refs": [],
+ "change_risk": "Low",
+ "future_design_constraints": "Keep lore optional and non-consensus."
+ }
+ ],
+ "archived_or_planned": [
+ {
+ "id": "planned_classic_hyperspace_profile",
+ "name": "Classic Profile with Hyperspace",
+ "category": "L. Archived / Planned / Removed",
+ "status": "Planned",
+ "player_visible": true,
+ "determinism_critical": true,
+ "current_behavior_summary": "Archived variance notes suggest a classic profile including hyperspace.",
+ "balancing_notes": "Would widen rules and proof surface significantly.",
+ "progression_role": "Deferred design branch.",
+ "related_constants": [],
+ "related_tests": [],
+ "evidence_refs": [
+ "docs/archive/games/asteroids/13-ORIGINAL-RULESET-VARIANCE-AUDIT.md:100 (archived recommendation)"
+ ],
+ "change_risk": "High",
+ "future_design_constraints": "Remain planned-only until code exists."
+ }
+ ],
+ "evidence": [
+ {
+ "id": "ev_4bit_input",
+ "file": "src/game/tape.ts",
+ "line": 19,
+ "note": "Four-bit action contract"
+ },
+ {
+ "id": "ev_run_cap",
+ "file": "src/game/constants.ts",
+ "line": 65,
+ "note": "10-minute cap"
+ },
+ {
+ "id": "ev_claim_path",
+ "file": "kalien-contract/contracts/asteroids_score/src/lib.rs",
+ "line": 125,
+ "note": "On-chain claim entrypoint"
+ }
+ ]
+}
diff --git a/docs/games/asteroids/19-FUTURE-DESIGN-GUARDRAILS.md b/docs/games/asteroids/19-FUTURE-DESIGN-GUARDRAILS.md
new file mode 100644
index 0000000..880b0bd
--- /dev/null
+++ b/docs/games/asteroids/19-FUTURE-DESIGN-GUARDRAILS.md
@@ -0,0 +1,97 @@
+# 19 - Future Design Guardrails
+
+## How to Inspect Before Changing Design
+1. Read canonical docs first: `01-GAME-SPEC.md`, `15-DOCS-PARITY-CHECKLIST.md`, `16-GAME-CONTENT-INVENTORY.md`.
+2. Audit implementation files: `AsteroidsGame.ts`, `constants.ts`, `input.ts`, `tape.ts`.
+3. Run `bun run game:inventory -- --strict` before edits.
+4. Confirm changed mechanics in tests and evidence references.
+
+## How to Avoid Inventing Nonexistent Systems
+- Treat `Absent` and `Unknown` as first-class truths.
+- Do not assume bosses/powerups/hyperspace exist because they are common in arcade derivatives.
+- If code evidence is missing, mark `Unknown` or `Absent`; do not upgrade status.
+
+## How to Preserve Linear Progression Clarity
+- Keep wave progression legible: wave count, asteroid count, saucer pressure, anti-lurk.
+- Avoid adding overlapping progression systems without explicit player-facing signaling.
+- Preserve clean score-to-survival loop (`destroy -> score -> extra life`).
+
+## Gameplay Ethics
+- Fairness: no hidden deterministic penalties.
+- Readability: telegraph threats and preserve control responsiveness.
+- Avoid cheap difficulty spikes: tune pressure curves with evidence.
+- Preserve proofability: all consensus-relevant mechanics must remain replay-deterministic.
+
+## When a Feature Must Update Docs
+Update canonical docs when any gameplay-visible mechanic changes:
+- controls
+- entities/enemies/weapons
+- scoring or progression
+- session start/end behavior
+- replay semantics
+
+## When a Feature Must Update Manifest
+Always update `18-GAME-CONTENT-MANIFEST.json` when adding/removing/retuning:
+- player actions
+- entities
+- enemies
+- deterministic constants
+- omissions/unknowns statuses
+
+## When a Feature Must Update Tests
+Add/update tests when changes affect:
+- deterministic simulation
+- input mapping or edge semantics
+- tape format/rules tag/checksum behavior
+- score/claim settlement assumptions
+
+## Determinism Danger Zones
+- Input encoding (`left/right/thrust/fire` bits).
+- Tape format version/rules tag/checksum.
+- Update order in simulation loop.
+- Seed/seed_id/claimant binding in proof + settlement.
+- Constants mirrored between TS and Rust core.
+
+## No Feature Without Inventory Rule
+No gameplay feature may be added, removed, or retuned without:
+1. Updating manifest (`18-...json`)
+2. Updating inventory (`16-...md`)
+3. Updating manual (`17-...md`) when player-visible
+4. Updating tests when deterministic or balance-relevant
+5. Adding changelog entry (`20-...md`)
+
+## Pre-Add Checklists
+### New Enemy
+- deterministic spawn/AI rules defined
+- score value and progression role documented
+- cap/collision/update-order implications tested
+
+### New Weapon
+- input mapping and fire cadence deterministic
+- cap/cooldown/lifetime constants specified
+- replay/tape semantics unchanged or explicitly versioned
+
+### New Scoring Rule
+- scoring event triggers uniquely defined
+- extra-life interaction reviewed
+- claim/leaderboard implications documented
+
+### New Powerup
+- deterministic spawn/pickup/expiry model required
+- explicit non-presence state removed from omissions list
+- anti-lurk and pacing interactions tested
+
+### New Boss
+- deterministic phase transitions required
+- wave/pacing integration documented
+- risk of proof-cost growth assessed
+
+### New Lore Layer
+- mark as non-consensus cosmetic by default
+- keep out of deterministic simulation path
+- add evidence refs in inventory/manual
+
+### New UI Mode
+- classify mode in manifest and manual
+- define transitions and input edges
+- verify no hidden side effects on replay/recording
diff --git a/docs/games/asteroids/20-GAME-CONTENT-CHANGELOG.md b/docs/games/asteroids/20-GAME-CONTENT-CHANGELOG.md
new file mode 100644
index 0000000..453f623
--- /dev/null
+++ b/docs/games/asteroids/20-GAME-CONTENT-CHANGELOG.md
@@ -0,0 +1,28 @@
+# 20 - Game Content Changelog
+
+Append-only record for gameplay content additions/removals/renames.
+
+## 2026-03-02
+- Commit: `pending`
+- Change type: `docs+inventory-bootstrap`
+- Affected systems: inventory, manual, manifest, guardrails, refresh script
+- Docs updated?: `yes` (`16`, `17`, `19`, `20`)
+- Tests updated?: `no` (no gameplay runtime logic changed in this pass)
+- Determinism impact?: `none`
+- Balance impact?: `none`
+- Player-facing manual impact?: `yes` (new manual produced)
+- Notes:
+ - Established explicit implemented/absent/unknown feature taxonomy.
+ - Added strict drift checks for manifest and documentation coverage.
+
+## Entry Template
+- Date: `YYYY-MM-DD`
+- Commit: `