# WMO Render Resource Finalizer ## Metadata | Field | Value | |---|---| | Status | Implemented extraction | | Target/work package | M03 / `M03-RND-WMO-RENDER-RESOURCE-FINALIZER-001` | | Owners | Lightweight WMO terminal status polling, Resource validation and cache/missing publication | | Last verified | Worktree `work/sindo-main-codex/m03-wmo-render-resource-finalizer`, 2026-07-18 | | Profiles/capabilities | Profile-independent lightweight WMO render-cache finalization | ## Purpose Finalize pending lightweight WMO `.res` cache requests outside `StreamingWorldLoader`: poll terminal status, retrieve a loaded Resource, enforce exact script/current-format validation and publish either the exact Resource or the historical missing outcome. ## Non-goals - Select normalized WMO/cache paths or start threaded requests. - Finalize cached WMO PackedScenes or live WMOBuilder prototypes. - Own cache lifetime, placements, build queues, scheduler permits or Nodes. - Change `WMOStreamingResource.FORMAT_VERSION`, fallback or visible behavior. ## Context and boundaries ```mermaid flowchart LR Loader[StreamingWorldLoader] -->|compose and tick| Finalizer[WmoRenderResourceFinalizer] Cache[WmoRenderResourceCacheState] -->|pending snapshot| Finalizer Finalizer --> ResourceLoader Finalizer -->|validated Resource or missing| Cache Cache --> Build[WMO render build queue] ``` The service may depend on `ResourceLoader`, the injected expected Script and the render Resource cache-state API. File selection, FileAccess, SceneTree, WMOBuilder, placement, scheduler and application layers remain outside it. ## Public API | Symbol | Kind | Purpose | Thread/lifetime | Errors | |---|---|---|---|---| | `poll_terminal_requests(cache_state)` | Command/query | Poll all pending paths once and publish terminal outcomes | Renderer main thread; stateless between calls | Null state returns zero; non-terminal retained | | `is_current_render_resource(resource)` | Query | Enforce exact injected Script and minimum format | Renderer main thread; stateless | Null/wrong/stale false | | `load_threaded_get_status(path)` | Boundary query | Read opaque threaded status | Renderer main thread; injectable in tests | ResourceLoader semantics | | `load_threaded_get(path)` | Boundary query | Retrieve terminal Resource | Renderer main thread; injectable in tests | Null accepted as failed outcome | ## Inputs and outputs | Direction | Contract/data | Producer | Consumer | Ownership | Thread/lifetime | |---|---|---|---|---|---| | Input | Detached normalized-path to `.res` path Dictionary | Render cache state | Finalizer polling | Caller-owned copy | One poll pass | | Input | Opaque ResourceLoader status | ResourceLoader | Finalizer | Integer value | One path poll | | Input | Terminal Resource | ResourceLoader | Validator | Borrowed reference | One completion | | Input | Expected Script/minimum format | Loader composition | Validator | Borrowed/value | Finalizer lifetime | | Output | Exact validated Resource | Finalizer | Render cache state | Cache adopts strong reference | Until full clear | | Output | Missing transition | Finalizer | Render cache state | Path-only state | Until transient clear | ## Data flow ```mermaid flowchart TD Snapshot[Detached pending snapshot] --> Next[Next path in insertion order] Next --> Poll[Poll ResourceLoader status] Poll --> Terminal{Loaded or failed?} Terminal -->|no| Retain[Retain pending] Terminal -->|failed| Missing[Complete as missing] Terminal -->|loaded| Get[Get terminal Resource] Get --> Validate{Exact script and format current?} Validate -->|yes| Adopt[Complete with exact Resource] Validate -->|no| Missing Retain --> Next Adopt --> Next Missing --> Next ``` ## Lifecycle/state ```mermaid stateDiagram-v2 [*] --> Polling Polling --> Pending: non-terminal status Polling --> Missing: failed/null/wrong/stale Polling --> Cached: exact script and current format Pending --> Polling: later tick Missing --> [*] Cached --> [*] ``` The finalizer retains no per-path state. The sibling cache state owns all Pending/Cached/Missing lifetime and reset transitions. ## Main sequence ```mermaid sequenceDiagram participant Loader as StreamingWorldLoader participant Finalizer as WmoRenderResourceFinalizer participant Cache as WmoRenderResourceCacheState participant RL as ResourceLoader Loader->>Finalizer: poll_terminal_requests(Cache) Finalizer->>Cache: request_paths_snapshot() loop insertion-ordered paths Finalizer->>RL: load_threaded_get_status(cache path) alt non-terminal Finalizer->>Finalizer: retain request else failed Finalizer->>Cache: complete_request_as_missing(path) else loaded Finalizer->>RL: load_threaded_get(cache path) Finalizer->>Finalizer: exact Script and format validation Finalizer->>Cache: complete with Resource or missing end end ``` ## Dependency diagram ```mermaid flowchart TB Loader[StreamingWorldLoader] --> Finalizer[WmoRenderResourceFinalizer] Loader --> Cache[WmoRenderResourceCacheState] Finalizer --> Cache Finalizer --> ResourceLoader Finalizer --> Script[WMOStreamingResource Script contract] Finalizer -. no dependency .-> FileAccess Finalizer -. no dependency .-> WMOBuilder Finalizer -. no dependency .-> Node Finalizer -. no dependency .-> Scheduler ``` ## Ownership, threading and resources - Renderer main thread serializes polling and cache-state publication. - Finalizer owns no Resource, request, Node, RID or file lifetime. - Cache state adopts accepted exact Resource references until its full clear. - Loader owns request admission, fallback/build orchestration and shutdown order. - Detached snapshots allow terminal cache-state mutation during iteration. ## Errors, cancellation and recovery | Failure/state | Detection | Behavior | Diagnostic | Recovery | |---|---|---|---|---| | Null cache state | Guard | Return zero | Contract verifier | Correct composition | | Non-terminal request | Status | Retain pending | Pending count | Poll next tick | | Failed request | Terminal status | Complete missing | Negative cache | Transient reset/rebuilt cache | | Null/wrong-script Resource | Validation | Complete missing | Synthetic fixture | Rebuild cache and reset | | Stale format | Format below injected minimum | Complete missing | Synthetic fixture | Rebuild cache and reset | | Shutdown | Loader lifecycle | Drain then cache clear | Shutdown verifier | New loader starts absent | ## Configuration and capabilities The loader injects the exact `WMOStreamingResource` Script and its `FORMAT_VERSION`. The service introduces no setting, profile, permit or cache format. WMO cache paths and build budgets remain loader-owned. ## Persistence, cache and migration The module serializes nothing and changes no cache format. It only enforces the existing script identity and current-or-newer format rule before runtime cache adoption, so no migration or rebake is introduced. ## Diagnostics and observability - `poll_terminal_requests` returns terminal completion count for tests/future metrics. - Existing cache pending count and renderer `wmobuild` metrics are unchanged. - The service emits no logs; normalized relative path remains the correlation key. ## Verification - `verify_wmo_render_resource_finalizer.gd`: null/non-terminal, insertion order, failed/load boundary, null/wrong/stale rejection, current/newer identity, source ownership and 1,000 terminal polls under one second. - Cache-state, WMO queue/planner/registry/resolver, shutdown, facade, internal-access and baseline regressions protect adjacent behavior. - Fidelity evidence is exact orchestration extraction; no asset-backed visual or original-client parity claim is made. ## Extension points - A legal current/stale `.res` fixture can extend validation evidence unchanged. - PackedScene finalization remains separate because it instantiates a probe Node and uses WMOBuilder metadata rather than script/format Resource fields. ## Capability status | Capability | Status | Evidence | Gap/next step | |---|---|---|---| | Lightweight WMO terminal polling | Implemented extraction | Status/order/source/timing verifier | Asset-backed traversal pending | | Script/format validation | Implemented extraction | Wrong/stale/current/newer fixtures | Legal serialized fixture pending | | Resource/missing publication | Implemented extraction | Exact identity/negative-state fixtures | Asset-backed lifetime/leak run pending | | WMO materialization | Loader-owned | Existing build regressions | Further safe extraction pending | ## Known gaps and risks - ResourceLoader status/get remains synchronous main-thread boundary polling. - No proprietary WMO corpus, serialized corrupt-version fixture, leak run, traversal p95/p99 or paired original-client capture is included. ## Source map | Path | Responsibility | |---|---| | `src/render/wmo/wmo_render_resource_finalizer.gd` | Terminal polling, validation and publication | | `src/render/wmo/wmo_render_resource_cache_state.gd` | Resource/missing/request ownership and resets | | `src/scenes/streaming/streaming_world_loader.gd` | Composition, request admission, fallback and build orchestration | | `src/resources/wmo_streaming_resource.gd` | Serialized cache contract and format version | | `src/tools/verify_wmo_render_resource_finalizer.gd` | Terminal-I/O/validation/source/timing regression | ## Related decisions and references - [`wmo-render-resource-cache-state.md`](wmo-render-resource-cache-state.md) - [`wmo-render-build-queue.md`](wmo-render-build-queue.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)