# Macrostep 09 — Delayed-time backend ## Objective Implement the distance-dependent delayed-time experiment as a deterministic, configurable 2-D backend with explicit history indexing, CPU oracle, accelerated GPU path, history diagnostics, and decoupled simulation/window resolution. ## Dependencies Macrosteps 00–06 complete; follow the roadmap order after Macrostep 08. ## Phase 9.1 — Explicit history model ### Substep 9.1.1 — Storage and indexing Represent history as `depth × height × width` with default depth 16 and a circular `head` denoting the next layer to overwrite. Define helpers: ```text latest = wrap(head-1, depth) sample(distance) = wrap(latest-floor(distance+0.5), depth) ``` Tests, UI, and shader must use the same integer helpers. Spatial x/y addressing is periodic. Window resize never changes simulation resolution by default. ### Substep 9.1.2 — Causal policy Use one policy only: delay zero reads `latest`, and increasing rounded distance walks backward from it. Smooth dynamics also use `latest` as their base. The historical next-overwrite-head anomaly is discarded and is not configurable. Use explicit integer layer selection; do not blur time through normalized 3-D texture interpolation. ## Phase 9.2 — Delayed neighborhood oracle ### Substep 9.2.1 — Stencil Implement: ```text ri = ra/3 inner width = outer width = 1 search radius = ceil(ra+0.5) ``` For each spatial offset, precompute: - `(dx,dy)`; - Euclidean distance; - integer delay layer offset; - disk and ring weights. Normalize by numerically summing this exact discrete stencil, not analytic area. ### Substep 9.2.2 — CPU evaluation For each output point, wrap x/y, choose the causal history layer, accumulate `M/N`, evaluate the shared rule, then: ```text discrete: next = clamp(S) smooth: next = clamp(history[latest] + 0.1*(2S-1)) ``` Commit next into `history[head]`, then advance `head`. Separate `preview()` from `commit()` so pause semantics are explicit. ### Substep 9.2.3 — Pause and reset Pause freezes output and head. Reset initializes every layer; recompute-without-commit and stale/undefined storage are not supported. ## Phase 9.3 — Initialization and interaction Provide deterministic modes: - all layers zero; - one seeded frame replicated to all layers; - independently seeded layers; - populate one layer as an explicit analysis operation; - source-inspired seeded boxes applied through a documented all-layer policy; - import a restart state under an explicit layer-fill policy; - import/export an exact checkpoint containing all history layers, `head`, generation, run descriptor, and RNG state. The seeded box initializer uses width/height in `10..19` and one documented boundary policy, then initializes all layers explicitly. Keep reset and later overlay actions distinct; do not retain gradual history filling. ## Phase 9.4 — GPU history representation ### Substep 9.4.1 — Choose after capability spike Preferred portable path is a tiled 2-D history atlas (default `4×4`) plus separate output/current targets. A texture array is an optional optimized path behind the same tested index abstraction. Atlas requirements: - integer tile/texel fetch; - no interpolation bleed; - dimensions preflighted against maximum texture size; - clear ownership of padding; - distinct read and write targets. ### Substep 9.4.2 — Rule pass and commit Run the direct stencil pass using precomputed offsets/weights/delays (uniform buffer, lookup texture, or generated shader according to measured limits). Copy/blit output into the `head` tile only after all reads complete, then rotate the logical head. Never sample the atlas tile while writing it. ### Substep 9.4.3 — CPU/GPU parity Read back `M`, `N`, output, and selected history tiles for small tests. Initial one-step max-error target: `≤1e-3`. ## Phase 9.5 — Workbench integration Add: - current committed state and computed preview; - history timeline with selectable layer, age, and physical tile; - radial delay map showing which distance uses which age; - `M/N/S/increment` inspection; - head/latest indicators; - history initialization controls; - direct/smooth mode selector; - DT preset browser and model-resolution controls independent of window size. Parameter edits state whether they preserve or reinitialize history. Rule-only edits may preserve state but must produce a reproducible run descriptor; radius or depth changes are cold rebuilds. ## Phase 9.6 — Verification ### History tests 1. Fill each layer with its index and verify every radial delay. 2. Test boundaries around `distance=n±0.5`. 3. Test head wrap `15→0`. 4. Verify smooth base is `head-1`. 5. Place one layer impulse and observe only the expected radial shell. 6. Verify x/y wrapping at all edges/corners. 7. Verify pause leaves head/state unchanged. 8. Verify every reset initializes all layers. 9. Verify atlas and CPU layouts select identical values. ### Performance target At 512² and `ra≈12`, target p95 GPU step below 33 ms on the designated machine after offset/weight/delay precomputation. Keep CPU for correctness and reduced-resolution fallback. High-resolution cost limits must be visible before allocation. ## Deliverables - CPU delayed-history oracle and GPU backend. - One explicit causal indexing policy. - Newly authored deterministic DT presets with stable names and identities. - History/radial-delay workbench views, restart-state export, and exact continuation checkpoints. ## Exit gate - All layer, radial shell, wrap, pause, and reset tests pass. - CPU/GPU one-step tolerance passes. - Window resize does not reset history. - No atlas bleed, uninitialized layer, or read/write alias exists. - Every DT preset uses the causal latest-relative delay policy and is reproducible.