# M2 Animation Load Pipeline State ## Metadata | Field | Value | |---|---| | Status | Implemented extraction | | Target/work package | M03 / `M03-RND-M2-ANIMATION-LOAD-PIPELINE-001` | | Owners | Animated M2 threaded request records and terminal finalize FIFO | | Last verified | Worktree `work/sindo-main-codex/m03-m2-animation-load-pipeline`, 2026-07-17 | | Profiles/capabilities | Existing optional cached-GLB animated M2 path | ## Purpose Own cross-frame bookkeeping between a successful animated M2 ResourceLoader request, terminal polling and budgeted main-thread scene finalization. This is an exact state extraction; cached animation eligibility and request admission belong to `M2CachedAnimationResourceObserver`; terminal I/O/outcomes belong to `M2AnimationResourceFinalizer`, while validation and retained Node lifetime belong to `M2AnimatedSceneFinalizer` and `M2PrototypeCacheState`. ## Non-goals - Select cache paths, interpret ResourceLoader statuses or perform I/O. - Decide animated/static fallback or own prototype Nodes. - Instantiate PackedScenes, repair materials or consume render permits. - Merge the distinct animated and static-Mesh pipelines. ## Context and boundaries ```mermaid flowchart LR Observer[M2CachedAnimationResourceObserver] --> IO[ResourceLoader request] Observer --> State[M2AnimationLoadPipelineState] Finalizer[M2AnimationResourceFinalizer] --> IO Finalizer --> State State -->|detached pending records| Finalizer Finalizer -->|opaque terminal status| State State -->|completion FIFO| Finalizer Loader[StreamingWorldLoader] --> Finalizer Loader --> Budget[M2_ANIMATION_FINALIZE permit] Loader --> Prototype[M2PrototypeCacheState] ``` Allowed dependencies are value containers, Strings and opaque integer statuses. ResourceLoader, workers, scheduler, Node/Resource/Mesh ownership and other renderer services are forbidden. ## Public API | Symbol | Kind | Purpose | Thread/lifetime | Errors | |---|---|---|---|---| | `remember_request(normalized_relative_path, resource_path)` | Command/query | Insert one pending request | Renderer main thread; until transition/clear | Empty/duplicate false | | `has_request(path)` | Query | Pending-request dedupe | Main thread | Empty/unknown false | | `request_records_snapshot()` | Query | Detached pending records in insertion order | Main thread; caller-owned | None | | `complete_request(path, terminal_status)` | Command/query | Move copied record into completion FIFO | Main thread after poll | Unknown false | | `discard_request(path)` | Command/query | Remove without finalization | Main thread | Unknown false | | `has_finalize_record()` / `pop_finalize_record()` | Query/command | Drain completion-order FIFO | Main-thread budget drain | Empty pop returns `{}` | | `total_work_count()` | Query | Pending plus finalize metric | Main thread | None | | `pending_request_count()` / `finalize_record_count()` | Query | Stage diagnostics | Main thread | None | | `clear()` | Command | Drop bookkeeping after caller I/O drain/reset | Main thread | Idempotent; no I/O drain | | `diagnostic_snapshot()` | Query | Detached paths/status records | Main thread | No Resources exposed | ## Inputs and outputs | Direction | Contract/data | Producer | Consumer | Ownership | Thread/lifetime | |---|---|---|---|---|---| | Input | Normalized M2 path and GLB Resource path | Loader request adapter | Pending map | Copied Strings | Until completion/discard/clear | | Input | Opaque terminal status | Resource finalizer | Finalize FIFO | Integer value | Until pop/clear | | Output | Detached pending records | State | Resource finalizer/shutdown adapter | Caller-owned copies | One pass | | Output | Oldest completion record | State | Resource finalizer | Transferred Dictionary | One finalize attempt | | Output | Detached diagnostics | State | Verifier/future metrics | Caller-owned copies | Snapshot lifetime | Side effects are limited to collection mutation and retaining String/integer values. ## Data flow ```mermaid flowchart TD Start[Successful threaded request] --> Remember[Remember request] Remember --> Poll[Resource finalizer polls detached snapshot] Poll --> Terminal{Loaded or failed?} Terminal -->|no| Poll Terminal -->|yes| Complete[Complete with opaque status] Complete --> FIFO[Finalize FIFO] FIFO --> Permit{Permit available?} Permit -->|no| FIFO Permit -->|yes| Pop[Pop oldest record] Pop --> Finalize[Resource finalizer loads/instantiates or marks static] ``` ## Lifecycle/state ```mermaid stateDiagram-v2 [*] --> Absent Absent --> Pending: remember Pending --> TerminalQueued: complete Pending --> Absent: discard or clear TerminalQueued --> Absent: pop or clear ``` ## Main sequence ```mermaid sequenceDiagram participant O as CachedAnimationObserver participant L as StreamingWorldLoader participant F as AnimationResourceFinalizer participant R as ResourceLoader participant S as M2AnimationLoadPipelineState participant P as M2PrototypeCacheState O->>R: load_threaded_request(GLB) O->>S: remember_request(path, GLB) loop frames L->>F: poll terminal requests F->>S: request_records_snapshot() F->>R: load_threaded_get_status(GLB) end F->>S: complete_request(path, status) L->>F: prepare after permit F->>S: pop_finalize_record() F->>R: load_threaded_get(GLB) F->>P: adopt animated prototype or mark static ``` ## Ownership, threading and resources - Main thread serializes all mutation. - State owns only request/finalize Dictionaries with copied paths and statuses. - Loader drains pending ResourceLoader paths before orderly shutdown clear. - Resource finalizer owns terminal I/O/outcomes and composes scene validation; prototype state owns accepted detached Nodes and static-only outcomes. ## Dependency diagram ```mermaid flowchart TB Observer[M2CachedAnimationResourceObserver] --> State[M2AnimationLoadPipelineState] Observer --> Resource[ResourceLoader request] Finalizer[M2AnimationResourceFinalizer] --> State[M2AnimationLoadPipelineState] Finalizer --> Resource Loader[StreamingWorldLoader] --> Finalizer Loader --> Budget[RenderBudgetScheduler] Loader --> Prototype[M2PrototypeCacheState] State -. no dependency .-> Resource State -. no dependency .-> Budget State -. no dependency .-> Prototype ``` ## Errors, cancellation and recovery | Failure | Detection | Behavior | Diagnostic | Recovery | |---|---|---|---|---| | Empty/duplicate request | State guard | Reject unchanged | Contract verifier | Correct caller or request later | | Request start/cache miss | Cached observer | No insertion; mark static | Observer contract | Cache correction/reload | | Non-terminal status | Loader | Keep pending | Existing metric | Poll next frame | | Failed terminal load | Popped status | Loader marks static | Existing behavior | Future map/session reload | | Empty defensive path | Loader poll | Discard and mark static | Source contract | Correct producer | | Shutdown | Loader drains pending paths | Clear state | Source/shutdown regressions | New loader starts empty | ## Configuration and capabilities | Setting/capability | Default | Profile | Runtime mutable | Effect | |---|---|---|---|---| | `enable_m2_animated_instances` | `true` | Existing renderer profile | Yes | Enables caller request path | | `m2_animation_finalize_ops_per_tick` | `1` | Quality/custom | Yes | Bounds caller FIFO drain | | Animated allow/deny/primitive rules | Existing values | Existing renderer profile | Yes | Observer filters before state insertion | ## Persistence, cache and migration State is not serialized. Cache formats and prototype lifetimes are unchanged; no rebake or migration is required. ## Diagnostics and observability - `total_work_count()` preserves all three historical `m2_animation` metrics. - Snapshots expose only paths and opaque statuses, never Resources or Nodes. - Normalized M2 path is the correlation key; existing loader logs are unchanged. ## Verification - `verify_m2_animation_load_pipeline_state.gd` covers validation, dedupe, insertion order, completion FIFO, opaque status, discard, detached snapshots, source boundaries and 100-by-256 timing. - Adjacent renderer, scheduler, prototype and shutdown regressions cover callers. - Fidelity evidence is exact state/lifecycle extraction; no visual 3.3.5a parity or proprietary asset-backed claim is made. - Performance budget: 25,600 request/complete/pop transitions under one second. ## Extension points ResourceLoader polling/finalization now belongs to a sibling service without changing this value-only state contract. ## Capability status | Capability | Status | Evidence | Gap/next step | |---|---|---|---| | Animated request/finalize state | Implemented extraction | Synthetic contract/source/timing verifier | Asset-backed traversal/leak/p95/p99 pending | | Cached request admission and GLB selection | Implemented in observer | Policy/GLB/source verifier | Asset-backed traversal pending | | Terminal ResourceLoader polling | Implemented finalizer extraction | Status/order/source regressions | Asset-backed traversal pending | | Animated prototype outcomes | Implemented extraction | Prototype cache verifier | Asset-backed animation fidelity pending | ## Known gaps and risks - Dictionary records preserve the existing dynamic ResourceLoader boundary. - `clear()` does not drain I/O; caller ordering remains mandatory. - No private asset traversal, leak/descriptor-pressure or paired-client run is included. ## Source map | Path | Responsibility | |---|---| | `src/render/m2/m2_animation_load_pipeline_state.gd` | Pending records, completion FIFO and metrics | | `src/render/m2/m2_animation_resource_finalizer.gd` | Terminal polling, Resource load and prototype outcome | | `src/render/m2/m2_cached_animation_resource_observer.gd` | Eligibility, GLB selection and request admission | | `src/render/m2/m2_animated_scene_finalizer.gd` | Candidate instantiation, material repair and player validation | | `src/render/m2/m2_prototype_cache_state.gd` | Animated prototype/static-only outcomes | | `src/scenes/streaming/streaming_world_loader.gd` | Permit loop, material lookup and composition | | `src/tools/verify_m2_animation_load_pipeline_state.gd` | Lifecycle/boundary/timing regression | ## Related decisions and references - [`m2-animated-scene-finalizer.md`](m2-animated-scene-finalizer.md) - [`m2-animation-resource-finalizer.md`](m2-animation-resource-finalizer.md) - [`m2-prototype-cache-state.md`](m2-prototype-cache-state.md) - [`m2-mesh-load-pipeline-state.md`](m2-mesh-load-pipeline-state.md) - [`world-renderer.md`](world-renderer.md) - [`../../RENDER.md`](../../RENDER.md) - [`../../targets/roadmap/02-rendering-and-graphics.md`](../../targets/roadmap/02-rendering-and-graphics.md)