> 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/sessions/phase34-session04-renderer-lifecycle-and-robustness/spec.md).

# Session Specification

**Session ID**: `phase34-session04-renderer-lifecycle-and-robustness` **Phase**: 34 - AI Rogue Audit Remediation **Status**: Not Started **Created**: 2026-06-26

***

## 1. Session Overview

This session hardens AI Rogue renderer resource ownership and browser fallback paths without changing gameplay rules. It closes the remaining default-enablement blocker AR-D4-001 by destroying stale transient feedback sprites during mounted runs, then reduces resize and media-query fragility that can make the Play surface unreliable on mobile, locked-down, or older browser surfaces.

It is next because Phase 34 Sessions 01 through 03 completed the prerequisite characterization, accessibility, compact-input, simulation correctness, and scenario-gate work. The analyzer reports Session 04 as the first unfinished current-phase candidate, and the phase PRD maps this session to AR-D4-001, AR-D4-003, AR-D7-001, and AR-D8-002.

The implementation should preserve explicit opt-in AI Rogue behavior, browser-local game state, route-lazy Pixi ownership, static public-demo safety, and product-facing Play route copy. It must not rewrite the renderer, add new art or audio assets, introduce remote loading, or begin the runtime API split reserved for Session 05.

***

## 2. Objectives

1. Destroy or remove inactive transient `feedback:*` Pixi sprites so long mounted runs cannot grow the feedback sprite pool without bound.
2. Coalesce resize observer and window resize work into a bounded render pass while keeping direct controller resize behavior deterministic.
3. Harden reduced-motion probing for throwing `matchMedia`, listener-only media query objects, and no-op cleanup paths.
4. Add focused fallback coverage for renderer setup failure, asset-load failure propagation, unavailable Web Audio, failed audio decode, and audio dispose.

***

## 3. Prerequisites

### Required Sessions

* [x] `phase34-session01-characterization-test-harness` - Provides feedback sprite retention characterization, route cleanup coverage, audio/storage fallback inventory, and AR-D4-001 evidence.
* [x] `phase34-session02-accessibility-and-compact-input` - Keeps the Play bridge, runtime summary, compact controls, and mobile route coverage current before renderer robustness changes.
* [x] `phase34-session03-simulation-correctness-and-scenario-gate` - Removes production combat fixture query behavior and preserves deterministic Playwright coverage through a local/test-only path.

### Required Tools Or Knowledge

* AI Rogue renderer lifecycle in `src/extensions/ai-rogue/runtime/renderer.ts`.
* Render-model transient descriptor behavior in `src/extensions/ai-rogue/runtime/render-model.ts`.
* Web Audio fallback behavior in `src/extensions/ai-rogue/runtime/audio.ts`.
* Runtime bridge error handling in `src/extensions/ai-rogue/views/runtime-canvas.tsx`.
* Vitest and Playwright coverage for AI Rogue runtime behavior.

### Environment Requirements

* Bun 1.3.14 project tooling.
* Local Playwright browser support for `tests/e2e/ai-rogue-runtime.spec.ts` when feasible.
* No remote services, hosted writes, generated private runtime data, new dependencies, or Cloudflare dashboard actions are required.

***

## 4. Scope

### In Scope (MVP)

* AI Rogue renderer destroys inactive transient feedback sprites and removes them from the mounted sprite pool.
* Persistent world, entity, tile, fog, HUD, and overlay sprites remain reusable and are hidden rather than destroyed when absent from a given render model.
* Resize observer and window resize callbacks coalesce through one pending animation frame with cancellation on controller destroy and setup failure.
* Direct `controller.resize()` remains an immediate measured resize operation for callers that explicitly request a synchronous size update.
* Reduced-motion media-query setup tolerates unavailable `window`, missing `matchMedia`, throwing `matchMedia`, modern `addEventListener`, legacy `addListener`, and objects with no listener methods.
* Runtime bridge setup-failure coverage proves a rejected renderer mount produces the existing product-facing error state without leaving a controller behind.
* Audio fallback coverage proves unavailable `AudioContext`, constructor failures, failed decode/fetch, and dispose-before-decode paths remain no-op safe.

### Out Of Scope (Deferred)

* Renderer rewrite, large file split, or render-model caching - Reason: this session only hardens lifecycle and fallback paths; hot-loop projection caching is mapped to Session 07.
* Runtime public API narrowing or selected-upgrade/loadout ownership changes - Reason: assigned to Session 05.
* Durable save schema, claim normalization, or hydration helper changes - Reason: assigned to Session 06.
* New art assets, new audio assets, visual redesign, WebGPU, workers, remote asset loading, collectors, analytics, or hosted game state - Reason: Phase 34 preserves browser-local static-demo boundaries.
* Default enablement decision - Reason: Phase 34 Session 08 owns the renewed recommendation after all gates are recorded.

***

## 5. Technical Approach

### Architecture

Keep sprite ownership inside `renderer.ts`, but split inactive sprite handling by descriptor family. Persistent descriptors should keep the current reuse path: detach or hide when inactive, then reuse on future render passes. Transient feedback descriptors should be removed from their parent layer, destroyed, and deleted from the pool as soon as they are not present in the active render model. This closes AR-D4-001 without changing combat events or render-model output.

Introduce a narrow resize scheduler around the existing measured resize/render operation. The scheduler should allow resize observer and window resize storms to collapse into one animation-frame pass, while direct controller calls can still perform a synchronous resize and emit a resize event. Destroy and setup failure paths must cancel both render and resize animation frames.

For reduced-motion, mirror the defensive media-query style already used by `src/extensions/ai-rogue/input-mode.ts`: wrap `matchMedia`, support both modern and legacy listener APIs, and make cleanup idempotent. For audio and setup fallback behavior, add focused tests around existing no-op behavior rather than adding new visible diagnostics or product controls.

### Design Patterns

* Descriptor-family lifecycle: Persistent sprites are reusable; transient feedback sprites are explicitly disposable.
* Coalesced browser events: External resize storms schedule one bounded measured render pass per animation frame.
* Defensive browser capability probing: Browser APIs are optional and may throw; fallback paths return no-op cleanup functions.
* Product-surface error state: Runtime setup failures flow through the existing Play bridge error notice instead of adding debug UI.

***

## 6. Deliverables

### Files To Create

| File                                                                                             | Purpose                                                           | Est. Lines |
| ------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------- | ---------- |
| `.spec_system/specs/phase34-session04-renderer-lifecycle-and-robustness/implementation-notes.md` | Session implementation notes, fallback matrix, and gate evidence. | \~150      |
| `src/extensions/ai-rogue/runtime/__tests__/audio.test.ts`                                        | Focused Web Audio fallback, decode failure, and dispose tests.    | \~120      |

### Files To Modify

| File                                                                   | Changes                                                                                            | Est. Lines |
| ---------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------- | ---------- |
| `src/extensions/ai-rogue/runtime/renderer.ts`                          | Destroy inactive transient feedback sprites, coalesce resize work, and harden media-query setup.   | \~160      |
| `src/extensions/ai-rogue/runtime/__tests__/renderer-lifecycle.test.ts` | Update feedback lifecycle coverage and add resize/media-query fallback tests.                      | \~170      |
| `src/extensions/ai-rogue/__tests__/runtime-canvas.test.tsx`            | Add rejected runtime mount coverage for product-facing setup failure state.                        | \~45       |
| `tests/e2e/ai-rogue-runtime.spec.ts`                                   | Preserve route remount and resize smoke coverage after resize coalescing changes.                  | \~20       |
| `docs/extensions/ai-rogue/run-loop-rebuild-notes.md`                   | Record renderer lifecycle fallback behavior if implementation changes the documented runtime path. | \~20       |

***

## 7. Success Criteria

### Functional Requirements

* [ ] Inactive `feedback:*` sprites are destroyed and deleted from the mounted sprite pool when absent from the active render model.
* [ ] Persistent inactive sprites are still hidden and reusable rather than destroyed.
* [ ] Resize observer and window resize storms produce bounded coalesced resize work instead of immediate unbounded full resize/render passes.
* [ ] Direct controller resize remains available for explicit synchronous resize callers.
* [ ] Reduced-motion setup cannot make the Play surface unavailable when `matchMedia` is missing, throws, exposes only `addListener`, or exposes no listener methods.
* [ ] Runtime setup failure uses the existing product-facing error state and leaves no mounted controller behind.
* [ ] Audio unavailable, failed decode, and dispose-before-decode paths are silent no-ops with no thrown errors.

### Testing Requirements

* [ ] Renderer lifecycle unit tests cover feedback destruction, persistent hiding, resize coalescing, and reduced-motion fallback behavior.
* [ ] Runtime canvas bridge tests cover rejected runtime mount and error-state recovery without debug copy.
* [ ] Audio unit tests cover no AudioContext, constructor failure, fetch/decode failure, and dispose-before-decode behavior.
* [ ] Focused AI Rogue unit and browser checks pass or exact blockers are recorded.

### Non-Functional Requirements

* [ ] No gameplay rule, seed determinism, save schema, persistence contract, or public-demo route behavior changes.
* [ ] No new dependencies, remote loading, hosted writes, collectors, analytics, or `/__*` public-demo bridge calls are introduced.
* [ ] Renderer cleanup remains idempotent across route unmount, failed setup, and repeated destroy calls.

### Quality Gates

* [ ] All files ASCII-encoded.
* [ ] Unix LF line endings.
* [ ] Code follows project conventions.
* [ ] Primary user-facing surfaces contain product-facing copy only.
* [ ] `bun run test -- src/extensions/ai-rogue/runtime/__tests__/renderer-lifecycle.test.ts src/extensions/ai-rogue/runtime/__tests__/audio.test.ts src/extensions/ai-rogue/__tests__/runtime-canvas.test.tsx` passes or exact blockers are recorded.
* [ ] `bun run test -- src/extensions/ai-rogue` passes or exact blockers are recorded.
* [ ] `bunx playwright test tests/e2e/ai-rogue-runtime.spec.ts` passes or exact blockers are recorded.
* [ ] `bun run typecheck`, `bun run lint`, and `bun run format:check` pass or exact blockers are recorded.

***

## 8. Implementation Notes

### Working Assumptions

* Storage fallback work in this session is verification-only unless renderer or bridge changes expose a new storage path. Evidence: the Session 04 stub says fallback tests should be added "where feasible"; current AI Rogue storage behavior is already covered in `persistence.test.ts`, `use-save-state.test.tsx`, and Session 01 validation; the planned renderer, media-query, setup, and audio changes do not touch persisted data shape.

### Key Considerations

* Keep Pixi behind the Play route and maintain explicit cleanup for every browser resource acquired during mount.
* Do not add visible debug diagnostics to the Play product surface.
* Treat setup and media-query failures as normal degraded browser capability states, not hard crashes.

### Potential Challenges

* Resize coalescing can accidentally delay explicit caller-driven resize behavior: keep `controller.resize()` synchronous and limit coalescing to observer/window callbacks.
* Destroying feedback sprites can remove sprites still present in the active descriptor set if active tracking is wrong: test active, stale transient, and persistent inactive IDs separately.
* Audio tests can be brittle when Web Audio constructors are partially mocked: keep mocks small and assert no-throw/no-leak behavior rather than browser playback details.

### Relevant Considerations

* \[P30/P32] **AI Rogue default enablement deferred**: This session closes a blocker but does not change enablement posture.
* \[P31-P33] **Pages demo stays static-only**: No local bridge, hosted write, collector, analytics, Function, or advanced Worker behavior is in scope.
* \[P30/P32] **Route-lazy runtime ownership scales**: Pixi owns mounted frames and cleanup; React owns coarse product state.
* \[P31-P33] **Route smoke is a privacy gate**: Keep route smoke and no-bridge proof available for closeout.

### Behavioral Quality Focus

Checklist active: Yes

Top behavioral risks for this session:

* Renderer resource cleanup can leak or double-destroy sprites, listeners, animation frames, audio, or Pixi app objects.
* Browser capability probes can throw or expose legacy-only listener APIs.
* Runtime setup errors can leave stale state visible or expose debug copy on the product route.

***

## 9. Testing Strategy

### Unit Tests

* Update `renderer-lifecycle.test.ts` for transient feedback destruction, persistent sprite hiding, resize coalescing, and reduced-motion media-query fallback.
* Add `audio.test.ts` for unavailable Web Audio, constructor failure, fetch/decode failure, and dispose-before-decode behavior.
* Update `runtime-canvas.test.tsx` for rejected runtime mount handling.

### Integration Tests

* Run focused AI Rogue Vitest coverage with `bun run test -- src/extensions/ai-rogue`.
* Run AI Rogue runtime browser coverage with `bunx playwright test tests/e2e/ai-rogue-runtime.spec.ts` when local browser support is available.

### Runtime Verification

* Confirm the Play route still mounts, paints, resizes, handles keyboard input, destroys the canvas on route exit, and remounts cleanly.
* Confirm product route copy remains product-facing; hidden runtime event evidence may remain test-only and `aria-hidden`.

### Edge Cases

* More inactive feedback sprite IDs than active feedback IDs.
* Persistent sprite inactive during one render and active again later.
* Multiple resize observer/window resize callbacks before the next animation frame.
* `matchMedia` missing, throwing, modern-only, legacy-only, and listener-less query objects.
* AudioContext unavailable, constructor throws, decode rejects, fetch rejects, and dispose happens before decode resolves.

***

## 10. Dependencies

### Other Sessions

* Depends on: `phase34-session01-characterization-test-harness`, `phase34-session02-accessibility-and-compact-input`, `phase34-session03-simulation-correctness-and-scenario-gate`
* Depended by: `phase34-session05-runtime-api-ownership`, `phase34-session07-render-performance-and-audio-docs`, `phase34-session08-default-enablement-evidence-closeout`

***

## Next Steps

Run the `implement` workflow step to begin implementation.


---

# 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/sessions/phase34-session04-renderer-lifecycle-and-robustness/spec.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.
