> For the complete documentation index, see [llms.txt](https://ai-os-and-trend-finder.gitbook.io/ai-os-and-trend-finder-docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://ai-os-and-trend-finder.gitbook.io/ai-os-and-trend-finder-docs/.spec_system/archive/phases/phase_39/prd_phase_39.md).

# PRD Phase 39: AI Rogue Level Authoring Infrastructure

**Status**: Complete **Sessions**: 8 (initial estimate) **Estimated Duration**: 8-12 days

**Progress**: 8/8 sessions (100%)

***

## Overview

Phase 39 turns AI Rogue level expansion from a cross-cutting set of depth branches into a typed, registry-backed authoring workflow. The phase starts by locking current shipped behavior, then introduces a level registry, routes depth resolvers through that registry, adds content and save-schema validation gates, proves the workflow with a reused-media fourth floor, and hardens the enemy, asset, audio, boss, finale, documentation, and validation paths needed for future content additions.

The phase preserves browser-local AI Rogue state, the static public-demo boundary, no remote game-content loading, deterministic simulation behavior, asset-size policy, route-lazy PixiJS ownership, and existing save privacy rules.

This phase consolidated the former ongoing-project planning note checked on 2026-06-30 and turned the broader level-expansion architecture work into an implementation sequence based on the current runtime under `src/extensions/ai-rogue/`. The resulting current workflow is captured in the [New Level Authoring Guide](https://github.com/moshehbenavraham/ai-os/blob/main/.spec_system/docs/extensions/ai-rogue/new-level-authoring-guide.md).

***

## Authoring Goal

Move level creation from a cross-cutting runtime edit into a typed content authoring workflow.

| Level Type                 | Expected Author Work After This Phase                                                                                                      |
| -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
| Existing-media level       | Add one level spec, choose existing theme, enemies, rewards, and audio, then add focused generation tests.                                 |
| Real content level         | Add one level spec plus new catalog entries for any new theme, enemy, boss, audio, or asset frames; validation reports missing references. |
| Experimental endless floor | Opt into an explicit looping policy outside the authored main run. No silent clamp or rotation in the main run.                            |

The practical success metric is that a fourth floor using existing content should not require edits to simulation internals, renderer internals, audio switches, or save schemas beyond deliberate new IDs.

The refactor must be behavior-preserving first. The current three shipped floors should remain byte-identical for stable seeds while the registry is introduced, existing depth resolvers are wrapped, and validation gates are added. New content starts only after that foundation is proven.

***

## Current Friction To Remove

Adding a level today means editing depth policy spread across independent resolvers. These source locations were checked on 2026-06-30.

| Resolver                                          | Current Location                                                | Current Behavior                                                                                                        |
| ------------------------------------------------- | --------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- |
| `AI_ROGUE_MAX_DEPTH`                              | `runtime/run-factory.ts:38`                                     | Standalone `const = 3`; not derived from authored content.                                                              |
| `themeForDepth()` / `sectorThemeForDepth()`       | `runtime/themes.ts:123`, `runtime/themes.ts:128`                | Clamps out-of-range depths to the last theme in `AI_ROGUE_THEME_ORDER`.                                                 |
| `floorObjectiveForDepth()` / `floorArcForDepth()` | `runtime/floor-arc.ts:52`, `runtime/floor-arc.ts:95`            | Clamps later depths to the last of three authored arcs.                                                                 |
| `prefabForDepth()`                                | `runtime/prefabs.ts:68`                                         | No prefab at depth 1, then rotates the prefab catalog.                                                                  |
| `protocolForDepth()`                              | `runtime/protocols.ts:97`                                       | Rotates the protocol catalog from depth 1. This is separate from floor-arc guaranteed protocols.                        |
| `terminalForDepth()`                              | `runtime/terminals.ts:106`                                      | No terminal at depth 1, then rotates the terminal catalog.                                                              |
| `findExitGuardSpawn()`                            | `runtime/world-placement.ts:23`                                 | Branches by depth: depth 1 uses `errant-process`, depth 2 uses `cache-wraith`, depth 3 and later use `kernel-sentinel`. |
| `createAiRogueWorld()` assembly                   | `runtime/world-generator.ts:91`, `:163`, `:289`, `:324`, `:340` | Re-derives theme, guard, protocol, prefab, and terminal decisions from raw `depth`.                                     |
| `musicTrackForDepth()`                            | `runtime/audio.ts:1040`                                         | Sends depth 3 and later to `sector_3`.                                                                                  |

Two related couplings make new entities expensive:

* Enemy audio is a switch, not data. `audioFamilyForEnemyKind()` in `runtime/audio.ts:878` enumerates enemy kinds; a new enemy requires another audio branch instead of a template field.
* Boss behavior means `kernel-sentinel` literally. The kind appears in `runtime/boss-presentation.ts`, `runtime/render-model.ts:490`, `runtime/renderer-audio-adapter.ts:202`, `runtime/effects.ts`, and `runtime/combat.ts`. A second boss would need renderer, audio, combat, and presentation branches unless the boss contract becomes data-driven.

ID coverage is also split across runtime catalogs and save schemas:

* Protocol IDs are named in runtime protocol code and duplicated in `save-schema.ts:74`.
* Terminal IDs are named in terminal code and duplicated inline at `save-schema.ts:141`.
* Enemy kinds are named in `runtime/entities.ts` and `runtime/types-entities.ts` and duplicated in `save-schema.ts:391`.
* Theme IDs are named in `runtime/themes.ts` and duplicated inline at `save-schema.ts:411`.

The existing code is deterministic and typed. The problem is not correctness; the problem is that content intent is distributed across too many depth lookups, rotations, clamps, and duplicated ID lists.

***

## Design Principle

Keep AI Rogue repo-local and typed. Do not introduce remote content loading, runtime mods, dynamic plugins, or unreviewed JSON packs.

The infrastructure should make level content explicit in source, then derive runtime routing from that content. A new level should fail fast in tests when it references an unknown enemy, frame, audio file, terminal, protocol, objective, theme, prefab, boss, or save-persisted ID.

The first pass should be minimal: create a level registry and validation layer that references existing catalogs. Split themes, enemies, bosses, terminals, or protocols into new content modules only when that catalog is being expanded or when the split reduces real churn.

***

## Target Architecture

Create `src/extensions/ai-rogue/runtime/content/` as the source of authored level order and per-floor routing.

Proposed layout:

```
runtime/content/
  index.ts        -- registry exports and levelSpecForDepth()
  levels.ts       -- ordered AI_ROGUE_LEVEL_SPECS
  validate.ts     -- pure validation for registry and catalog references
  types.ts        -- AiRogueLevelSpec and related content contracts
```

Initial `AiRogueLevelSpec` should capture only the fields already needed to reproduce the current run:

```ts
export interface AiRogueLevelSpec {
  id: string;
  depth: number; // 1-based and contiguous.
  label: string;
  lesson: string;
  themeId: AiRogueSectorThemeId;
  generation: {
    roomModifier: AiRogueRoomModifier;
    hazardDelta?: number;
    shardDelta?: number;
    healthDelta?: number;
    enemyCountDelta?: number;
  };
  enemyTable: readonly AiRogueEnemyKind[];
  exitGuardKind: AiRogueEnemyKind;
  placements: {
    /** Baseline placed protocol from current world generation. */
    protocol?: AiRogueProtocolId;
    prefab?: AiRoguePrefabId;
    terminal?: AiRogueTerminalId;
  };
  guarantees: {
    enemies?: readonly AiRogueEnemyKind[];
    pickup?: AiRoguePickupKind;
    /** Separate from the baseline placed protocol; mirrors current floor arcs. */
    protocol?: AiRogueProtocolId;
    objective?: {
      kind: Exclude<AiRogueFloorObjective["kind"], "none">;
      label: string;
      target: number;
    };
  };
  musicTrack: AiRogueMusicId;
  ambience: AiRogueThemeAmbienceId;
  isFinale?: boolean;
}
```

Compatibility requirements:

* `AI_ROGUE_LEVEL_SPECS` contains exactly the current three playable depths at first.
* The initial specs reproduce the current values from `AI_ROGUE_THEME_ORDER`, `AI_ROGUE_FLOOR_ARCS`, `findExitGuardSpawn()`, `musicTrackForDepth()`, `prefabForDepth()`, `terminalForDepth()`, and current world protocol placement.
* `AI_ROGUE_MAX_DEPTH` derives from `AI_ROGUE_LEVEL_SPECS.length`.
* Existing exports such as `themeForDepth()`, `floorArcForDepth()`, `floorObjectiveForDepth()`, `protocolForDepth()`, `terminalForDepth()`, `prefabForDepth()`, and `musicTrackForDepth()` stay available during migration, but delegate to `levelSpecForDepth()` where their semantics are authored level identity.
* The main authored run rejects out-of-range depths. A future endless mode can use a separate explicit `levelSpecForEndlessDepth()` policy.

Protocol handling needs care: today there is a rotating baseline protocol from `world-generator.ts` and a floor-arc guaranteed protocol. The spec should model both separately, and any existing callers of `protocolForDepth()` must be audited before removing or changing rotation semantics.

***

## Implementation Roadmap

The roadmap below maps the former phase labels from the planning note onto the eight Phase 39 session stubs.

### Phase 0 / Session 01: Lock The Current Baseline

Before moving routing code, add tests that describe the current shipped run.

Deliverables:

* Add a small content-baseline test suite that records the current three playable depths: theme, floor arc label, exit guard kind, baseline protocol, guaranteed protocol, terminal, prefab, music, ambience, and objective.
* Add golden determinism coverage for a fixed seed at each current depth. The generated world and first-turn state should stay byte-identical while the registry and wrappers are introduced.
* Add world-generation parity checks proving stable seeds keep the same public world shape before and after compatibility wrappers move.
* Add a boss-presentation baseline test proving Kernel Sentinel frame selection, reveal, hit, telegraph, attack, shutdown, scale, and audio metadata stay unchanged.
* Keep these tests focused on behavior and safe labels, not raw generated private data.

Exit criteria:

* The baseline suite can catch accidental changes while registry wrappers are introduced.
* Existing behavior tests are not edited to make the refactor pass.
* No new level content is added in this phase.

### Phase 1 / Session 01: Add A Content Registry Skeleton

Create `src/extensions/ai-rogue/runtime/content/` without changing shipped behavior or routing callers.

Deliverables:

* Add `types.ts`, `levels.ts`, `validate.ts`, and `index.ts`.
* Author three `AiRogueLevelSpec` rows that reproduce today's shipped floors.
* Add `levelSpecForDepth(depth)` and an explicit out-of-range policy for the authored main run.
* Add `validateAiRogueContentRegistry()` with the initial structural checks: unique IDs, contiguous 1-based depths, non-empty enemy tables, valid local references, no finale before the last authored level, and safe text for labels and lessons.
* Add a focused registry test proving the three current specs pass validation.

Exit criteria:

* The new code is dead-but-tested: no runtime caller changes yet.
* `bun run typecheck` passes.
* A new `content/__tests__/levels.test.ts` or equivalent registry test is green.

### Phase 2 / Session 02: Route Depth Resolvers And Generation Through Level Specs

Move depth policy out of scattered modules while preserving public signatures and current outputs for depths 1-3.

Deliverables:

* Re-export `AI_ROGUE_MAX_DEPTH` from its existing location if needed, but derive the value from `AI_ROGUE_LEVEL_SPECS.length`.
* Rewrite compatibility exports as thin wrappers over `levelSpecForDepth()` where appropriate: `themeForDepth()`, `floorArcForDepth()`, `floorObjectiveForDepth()`, `prefabForDepth()`, `terminalForDepth()`, `musicTrackForDepth()`, and the guard kind inside `findExitGuardSpawn()`.
* Extend `AiRogueWorldGenerationOptions` to accept `levelSpec` or resolve one from `depth`.
* Replace `roomModifierForDepth(depth)` with `levelSpec.generation.roomModifier`.
* Use `levelSpec.themeId`, `levelSpec.enemyTable`, and `levelSpec.exitGuardKind` during generation.
* Move baseline protocol, terminal, and prefab decisions to `levelSpec.placements`.
* Keep floor-arc guarantees separate as `levelSpec.guarantees`, including the current guaranteed pickup, introduced enemies, guaranteed protocol, and optional objective.
* Rename or wrap `applyFloorArc()` as `applyLevelGuarantees()` while keeping the old export as a migration shim.
* Add deterministic tests proving each level's exit is reachable, the guard is adjacent to the exit, prefabs never disconnect the map, and terminal or vault placement never blocks the route.

Exit criteria:

* `createAiRogueWorld({ depth })` reads one level spec for authored content decisions.
* The generator no longer contains level-specific depth branches except for fallback validation or legacy test support.
* Existing depth 1-3 tests pass without expected-output edits.
* Golden determinism tests remain byte-identical for the current three floors.

Suggested focused gate:

```bash
bun run typecheck
bunx vitest run src/extensions/ai-rogue/runtime/__tests__/world.test.ts \
  src/extensions/ai-rogue/runtime/__tests__/simulation.test.ts \
  src/extensions/ai-rogue/runtime/__tests__/floor-arc.test.ts \
  src/extensions/ai-rogue/runtime/__tests__/themes.test.ts \
  src/extensions/ai-rogue/runtime/__tests__/prefabs.test.ts \
  src/extensions/ai-rogue/runtime/__tests__/protocols.test.ts \
  src/extensions/ai-rogue/runtime/__tests__/terminals.test.ts \
  src/extensions/ai-rogue/runtime/__tests__/audio.test.ts
```

### Phase 3 / Session 03: Add ID Parity And Content Validation Gates

Make catalog/save-schema drift impossible to ship before adding content.

Deliverables:

* Extend `validateAiRogueContentRegistry()` to verify every level reference points at a known runtime catalog entry: theme, enemy, protocol, prefab, terminal, objective, music, ambience, pickup, and boss/finale ownership where applicable.
* Add save-schema parity tests for runtime IDs that can be persisted: `AiRogueEnemyKind`, `AiRogueSectorThemeId`, `AiRogueProtocolId`, and `AiRogueTerminalId`.
* Account for current save-schema shape accurately: protocol and enemy have named local schemas, while terminal and theme are inline enums today.
* Keep old IDs loadable as hidden compatibility entries if content is retired.
* Keep reusable catalogs separate from level assembly. Catalogs define reusable things; `content/levels.ts` decides when a floor uses them.
* Remove rotating depth helpers from authoring paths. They can remain as compatibility wrappers during migration, but tests should prefer level-spec lookups.

Exit criteria:

* Deliberately referencing a non-existent enemy, theme, terminal, protocol, prefab, music, or ambience fails a registry test with a clear message.
* Deliberately adding a persisted runtime ID without save-schema coverage fails a parity test.
* A content author can inspect one level spec to understand a floor's identity, generation profile, encounter guarantees, rewards, audio, and finale status.

### Phase 4 / Session 04: Add The First Registry-Authored Fourth Floor

Prove the workflow with a level that reuses existing media. This should happen before new enemies, new bosses, or new music so the team can judge whether the infrastructure actually made level authoring cheaper.

Recommended scope:

* Append one `AiRogueLevelSpec` to `content/levels.ts`.
* Use an existing shipped theme such as `firewall` or `model-vault`, and document the reuse rationale so it reads as intentional rather than an accidental repeat.
* Reuse existing enemies, prefabs, terminals, protocols, music, ambience, and frames.
* Add a distinct label, lesson, enemy table, guard, prefab, terminal/protocol choice, objective, reward profile, and generation profile.
* Add deterministic generation and simulation tests for depth 4: reachable exit, no spawn overlap, guard placement, objective lock/unlock if used, and save round-trip coverage.
* Keep new monsters, new bosses, and new music out of this phase.

Exit criteria:

* The playable max depth increases from three to four by adding a level spec.
* No renderer, audio switch, simulation branch, route import, or save-schema edit is needed unless a newly persisted ID is introduced.
* A depth-4 run round-trips through `save-schema.ts` without a schema version bump when it only reuses existing persisted IDs.

### Phase 5 / Session 05: Derive Asset And Audio Requirements

Reduce manual frame and audio bookkeeping by validating declared content.

Deliverables:

* Add `audioFamily: AiRogueEnemyAudioFamily` to enemy specs so audio routing does not switch on every enemy ID.
* Reduce `audioFamilyForEnemyKind()` to an enemy-spec lookup with a generic fallback for non-enemy or unknown metadata.
* Add enemy frame-set metadata for every enemy: `idle`, `alternateIdle`, `attack`, `hit`, and `defeated` where available.
* Add boss frame-set metadata for Kernel Sentinel: `idle`, `charge`, `telegraph`, `attack`, `shielded`, `hit`, and `shutdown`.
* Add a content asset validation test that derives required gameplay frames from themes, enemies, bosses, protocols, objectives, statuses, pickups, and level specs.
* Add a content audio validation test that verifies every declared SFX, music, and ambience ID maps to an imported `.ogg` URL and provenance record.
* Keep `REQUIRED_GAMEPLAY_FRAME_NAMES` and `SFX_FILE_BASENAMES` until the derived checks are trusted; then shrink manual lists to shared static frames only.

Exit criteria:

* Adding an enemy or level fails tests with a clear missing-frame or missing-audio message instead of surfacing later in the renderer.
* A new standard enemy needs a template row, frames, save parity if persisted, and tests; it does not need a new `audio.ts` switch branch.

Open implementation choice:

* `audioFamily` can land before `frameSet` if the team wants a smaller first enemy-spec migration. Frame projection touches rendering and can be split into its own follow-up if needed.

### Phase 6 / Session 06: Generalize Boss And Finale Contracts

Kernel Sentinel should become the first boss spec, not the only boss branch.

Deliverables:

* Introduce `AiRogueBossSpec` with kind ID, frame set, sprite scale, audio family, reveal behavior, telegraph behavior, shutdown behavior, and finale ownership.
* Add `isBossEnemyKind()` or `bossSpecForEnemyKind()` and replace `isKernelSentinelEntity()` / `selectKernelSentinelFrame()` internals with boss-spec-based helpers while preserving Kernel Sentinel behavior.
* Replace hard-coded Kernel Sentinel checks in render model, effects, renderer-audio adapter, combat audio metadata, and presentation tests with boss-spec helpers.
* Split final-defense display rules from raw `depth >= 3`; use `levelSpec.isFinale` or a finale presentation spec.
* Only add a second boss or miniboss after the generalized path passes the existing Kernel Sentinel tests unchanged.

Exit criteria:

* Kernel Sentinel still behaves the same.
* `boss-presentation.test.ts`, `render-model.test.ts`, `renderer-audio-adapter.test.ts`, `audio.test.ts`, and `combat.test.ts` remain green for Kernel Sentinel.
* Adding a second boss or miniboss requires a boss spec, enemy template, frames, audio mapping, and tests, not renderer-specific branches.

### Phase 7 / Session 07: Add Real Content On Top Of The New Workflow

After a fourth reused-media floor proves the architecture, add one content type at a time.

Recommended order:

1. Add one standard enemy using existing behavior IDs and an existing audio family.
2. Add one enemy frame set and derive its asset validation from the enemy spec.
3. Introduce that enemy through one level spec and one floor guarantee.
4. Add a new terminal, objective, protocol, or status only after the enemy path is stable.
5. Add a miniboss only after the boss-spec migration is complete.
6. Add new music or ambience after the level's encounter pacing is stable.

Exit criteria:

* Content additions are catalog work plus focused simulation, save, render, asset, and audio tests.
* New levels no longer require broad runtime archaeology.

***

## Save And Migration Rules

Keep saves ID-based and schema-validated.

* Persist level IDs, depth, runtime state, entity IDs, and small state only. Do not persist whole level specs.
* Add IDs to Zod enums deliberately when new saved IDs exist.
* Add parity tests proving every saved runtime ID has save-schema coverage.
* Keep old IDs loadable as hidden compatibility entries if content is retired.
* Bump `AI_ROGUE_SAVE_SCHEMA_VERSION` only when older records need a real migration, not for every new level spec.
* Maintain the current private-looking text rejection rules for labels, warnings, provenance, route-visible copy, tests, and docs.

***

## Authoring Checklists

For an existing-media level:

1. Add one `AiRogueLevelSpec` to `content/levels.ts`.
2. Pick an existing theme and ambience.
3. Pick an existing music track.
4. Define enemy table, exit guard, baseline protocol, guaranteed protocol, terminal, prefab, objective, and reward profile.
5. Add a depth generation test for reachable exit, no spawn overlap, guard placement, prefab route safety, terminal/vault route safety, and objective lock/unlock when relevant.
6. Run content validation and focused world/simulation tests.

For a real content level:

1. Do everything for an existing-media level.
2. Add any new theme, enemy, boss, objective, terminal, protocol, status, asset, and audio specs.
3. Add save-schema parity for any persisted new ID.
4. Add atlas/audio/provenance validation.
5. Add browser proof if visual presentation, controls, audio unlock, or route-visible UI changes.

No authoring path should require hunting through eight depth resolvers and hoping rotation math lands on the intended content.

***

## Validation Gates

Every session touching this phase should use the relevant subset of these commands and document exact blockers when a gate cannot run.

Every phase:

```bash
bun run typecheck
bunx vitest run src/extensions/ai-rogue/runtime/__tests__/assets.test.ts
bunx vitest run src/extensions/ai-rogue/runtime/__tests__/world.test.ts \
  src/extensions/ai-rogue/runtime/__tests__/simulation.test.ts
bash scripts/check-asset-sizes.sh
```

Registry and resolver phases:

```bash
bunx vitest run src/extensions/ai-rogue/runtime/__tests__/floor-arc.test.ts \
  src/extensions/ai-rogue/runtime/__tests__/themes.test.ts \
  src/extensions/ai-rogue/runtime/__tests__/prefabs.test.ts \
  src/extensions/ai-rogue/runtime/__tests__/protocols.test.ts \
  src/extensions/ai-rogue/runtime/__tests__/terminals.test.ts \
  src/extensions/ai-rogue/runtime/__tests__/audio.test.ts
```

Save, boss, render, or route-visible phases:

```bash
bunx vitest run src/extensions/ai-rogue/__tests__/save-schema.test.ts
bunx vitest run src/extensions/ai-rogue/runtime/__tests__/boss-presentation.test.ts \
  src/extensions/ai-rogue/runtime/__tests__/render-model.test.ts \
  src/extensions/ai-rogue/runtime/__tests__/renderer-audio-adapter.test.ts \
  src/extensions/ai-rogue/runtime/__tests__/combat.test.ts
```

Run the relevant Playwright AI Rogue desktop/mobile checks whenever a change touches runtime rendering, controls, audio unlock behavior, or route-visible UI. Run `bun run build` and `bun run budget:check` on milestones that touch route code or import shape, because AI Rogue relies on lazy loading to keep PixiJS out of shared chunks.

***

## Open Decisions

1. Out-of-range depth policy. Recommendation: throw or return a typed invalid result for the authored main run; add endless looping behind an explicit separate helper only when endless mode is real.
2. Content module split. Recommendation: start minimal with `levels.ts`, `types.ts`, and `validate.ts` referencing existing catalogs; split a catalog only when it is being expanded.
3. Enemy frame migration size. Recommendation: land `audioFamily` first if needed, then add `frameSet` once renderer projection has focused tests.
4. Fourth-floor media reuse. Recommendation: intentionally reuse an existing theme and audio in Phase 4 to prove the infrastructure before expanding the asset surface.

***

## Non-Goals

* No remote content loading.
* No dynamic plugins or user-authored mod system.
* No collector, hosted write, analytics, or telemetry dependency.
* No raw prompts, transcripts, local file paths, logs, command bodies, credentials, or private telemetry in content, saves, tests, docs, or provenance.
* No broad inventory rewrite.
* No worker simulation migration unless profiling shows real main-thread pressure.
* No Tiled or map-editor dependency.
* No new boss before Kernel Sentinel is represented by a reusable boss spec.

***

## Immediate Execution Order

Start with Session 01, which combines the former baseline-lock and registry skeleton steps:

1. Add behavior-preserving baseline tests and golden determinism snapshots for depths 1-3.
2. Add `runtime/content/levels.ts` with the current three playable levels.
3. Add registry validation and a focused registry test.
4. Do not route callers or add level 4 until the current run is described by the registry and baseline tests are in place.

Then Session 02 can make max depth and compatibility lookups derive from level specs with a clear safety net.

***

## Progress Tracker

| Session | Name                                    | Status   | Est. Tasks | Validated  |
| ------- | --------------------------------------- | -------- | ---------- | ---------- |
| 01      | Baseline And Registry Skeleton          | Complete | 16         | 2026-06-30 |
| 02      | Depth Resolver Migration                | Complete | 20         | 2026-06-30 |
| 03      | Registry Validation And Save Parity     | Complete | 16         | 2026-06-30 |
| 04      | Existing-Media Floor Four               | Complete | 16         | 2026-06-30 |
| 05      | Enemy Metadata And Derived Asset Checks | Complete | 18         | 2026-06-30 |
| 06      | Boss And Finale Contracts               | Complete | 20         | 2026-06-30 |
| 07      | Real Content Expansion Path             | Complete | 18         | 2026-07-01 |
| 08      | Validation And Documentation Hardening  | Complete | 20         | 2026-07-01 |

***

## Completed Sessions

* 2026-06-30: Session 01 - Baseline And Registry Skeleton completed. Added behavior-preserving depth 1-3 baseline and golden determinism coverage, created the dead-but-tested AI Rogue content registry skeleton, and validated all session gates.
* 2026-06-30: Session 02 - Depth Resolver Migration completed. Routed max depth, helper projections, world generation, run creation, descent, and level guarantees through authored level specs while preserving shipped depth 1-3 behavior and adding route-safety coverage.
* 2026-06-30: Session 03 - Registry Validation And Save Parity completed. Added registry validation for malformed level references, parser-owned persisted ID arrays, save-schema parity coverage, and import-boundary checks while preserving browser-local schema version 1.
* 2026-06-30: Session 04 - Existing-Media Floor Four completed. Added an authored depth-4 firewall floor using only existing media and catalog IDs, moved finale ownership to the new max depth, and validated registry, generation, run-loop, objective-lock, golden determinism, and save-schema behavior.
* 2026-06-30: Session 05 - Enemy Metadata And Derived Asset Checks completed. Added source-owned enemy audio/frame metadata, routed enemy audio family lookup through template metadata, derived gameplay frame validation from content contracts, and proved audio URL/provenance coverage with focused and full validation gates.
* 2026-07-01: Session 06 - Boss And Finale Contracts completed. Added a reusable boss/finale contract for Kernel Sentinel, routed boss presentation, render, effects, audio, combat, and content validation through metadata-backed helpers, and proved finale display ownership through authored level metadata.
* 2026-07-01: Session 07 - Real Content Expansion Path completed. Activated `insight-beetle` through the authored depth-4 `firewall-gauntlet` guarantee, proved spawn, frame, audio, combat, render, asset, and save behavior with focused tests, and kept save schema version 1 unchanged.
* 2026-07-01: Session 08 - Validation And Documentation Hardening completed. Closed Phase 39 with full validation evidence, shipped-state documentation updates, release metadata, privacy and non-goal scans, browser proof, and save schema version 1 unchanged.

***

## Upcoming Sessions

* None. Phase 39 is complete and ready for the phase-transition workflow.

***

## Objectives

1. Add behavior-preserving baseline and golden determinism coverage for the current three-floor AI Rogue run.
2. Add a typed `runtime/content/` level registry that owns authored floor order, routing, guarantees, audio, and finale metadata.
3. Route existing depth resolvers and world generation through level specs while preserving shipped depth 1-3 behavior.
4. Add registry and save-schema parity checks so malformed level specs or missing persisted IDs fail fast.
5. Prove the authoring workflow with a reused-media fourth floor before adding new enemies, bosses, or audio.
6. Move enemy audio/frame requirements and boss/finale behavior into reusable metadata contracts.
7. Validate the real-content expansion path with focused simulation, save, render, asset, audio, browser, and documentation evidence.

***

## Prerequisites

* Phase 38 completed.
* AI Rogue is production-enabled by default and keeps local-only game state.
* This Phase 39 PRD and its session stubs are the canonical source for level authoring infrastructure scope.

***

## Planning Assumptions And Resolutions

### Working Assumptions

* Phase 39 should be created from the user-supplied ongoing-project plan even though `.spec_system/PRD/PRD.md` and `.spec_system/state.json` previously ended at completed Phase 38. The requested `phasebuild` command named a current plan file with a full session split, so it is safe to reconcile the master PRD and state by adding Phase 39.
* The phase includes two content-oriented proof steps because the source plan includes them: a reused-media fourth floor and a later real-content expansion path. The infrastructure remains the primary objective, and new assets or persisted IDs stay controlled by validation and save-schema gates.
* The authored main run should reject out-of-range depths. Endless or looped behavior belongs behind a separate explicit helper only when that mode is implemented.
* Existing reusable catalogs should remain in place at first. Split themes, enemies, bosses, terminals, protocols, or other catalogs only when a session expands that catalog or the split reduces real churn.

### Conflict Resolutions

* Master PRD and state showed no upcoming phase, while the user supplied an actionable phase plan and invoked `phasebuild`. The chosen interpretation is to create Phase 39 from that plan and update both PRD and state, because the requested plan is repo-local, current, and aligned with AI Rogue active concerns around compatibility exports, route-lazy ownership, schema-backed state, and no remote content loading.

***

## Technical Considerations

### Architecture

Phase 39 must keep AI Rogue content repo-local and typed. The level registry should be pure runtime data, not a renderer or PixiJS import surface. Existing exports remain available as compatibility wrappers while callers migrate to level-spec lookups. Saves remain ID-based and schema-validated; whole level specs must not be persisted.

### Technologies

* TypeScript
* Zod
* Vitest
* Playwright
* PixiJS v8 route-lazy runtime
* Browser localStorage and IndexedDB
* Bun scripts and validation commands

### Risks

* Refactor changes shipped depth 1-3 behavior: mitigate with baseline and golden determinism tests before routing changes.
* `protocolForDepth()` has non-authoring callers: audit call sites before changing rotation semantics.
* Registry imports pull PixiJS into shared chunks: keep content pure runtime data and run build/budget checks when route imports change.
* Save-schema drift breaks hydration: add parity tests before adding new persisted IDs.
* Boss generalization regresses Kernel Sentinel visuals or audio: require the existing boss, render, audio, and combat tests to pass before adding another boss.

Consolidated mitigation table:

| Risk                                                            | Mitigation                                                                                                                                                        |
| --------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Refactor silently changes a shipped floor.                      | Add golden determinism snapshots before touching resolvers; do not edit existing expected outputs in Sessions 01-03 unless the change is deliberately documented. |
| `protocolForDepth()` has callers beyond floor identity.         | Audit call sites before folding rotation into specs; keep a rotating helper if non-authoring callers still depend on it.                                          |
| Out-of-range policy breaks fixtures that over-run depth.        | Make the policy explicit and tested; grep fixtures and tests for `maxDepth` and `depth:` before changing clamps.                                                  |
| Save drift between catalog and enum.                            | Add parity tests before adding content, not after.                                                                                                                |
| Boss generalization regresses Kernel Sentinel visuals or audio. | Require existing Kernel Sentinel boss, render, audio, and combat tests to pass unchanged before adding another boss.                                              |
| Registry import shape pulls renderer/PixiJS into shared chunks. | Keep content registry pure runtime data and run build/budget checks when route imports change.                                                                    |

### Relevant Considerations

* \[P35] **AI Rogue compatibility exports remain**: Preserve migration exports until direct consumers migrate and boundary tests stay green.
* \[P30/P32/P34-P35] **Route-lazy runtime ownership scales**: Keep Pixi behind the Play route/local facade and preserve narrow runtime barrels.
* \[P30/P32/P34-P35] **Schema-backed browser-local state works**: Keep Zod defaults, migrations, non-throwing hydration, and write-boundary guards.
* \[P30/P34-P38] **Visibility gates catch real issues**: Pair focused tests, browser proof, build/budget, privacy scans, provenance, and human-readable evidence before widening visibility.
* \[P30/P32/P34-P38] **Do not widen AI Rogue capabilities without review**: Remote loading, collectors, workers, hosted writes, expanded content, and rejected-art reuse need fresh review.

***

## Success Criteria

Phase complete when:

* [ ] All 8 sessions completed
* [ ] Current three-floor behavior remains covered by baseline and golden determinism tests
* [ ] Level specs drive authored floor routing and max depth
* [ ] Registry validation and save-schema parity gates catch malformed content
* [ ] A reused-media fourth floor proves the authoring workflow
* [ ] Enemy metadata, asset/audio validation, and boss/finale contracts support future content without renderer/audio archaeology
* [ ] Documentation and validation evidence match shipped behavior

***

## Dependencies

### Depends On

* Phase 38: Claude OS v2.8.1 Semantic Port
* AI Rogue Phase 30, 34, 35, 36, and 37 shipped runtime, audit, audio, and visual foundations

### Enables

* Future AI Rogue content phases with cheaper level, enemy, boss, terminal, protocol, music, ambience, and objective authoring


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://ai-os-and-trend-finder.gitbook.io/ai-os-and-trend-finder-docs/.spec_system/archive/phases/phase_39/prd_phase_39.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
