# M2 Mesh Resource Finalizer ## Metadata | Field | Value | |---|---| | Status | Implemented extraction | | Target/work package | M03 / `M03-RND-M2-MESH-RESOURCE-FINALIZER-001` | | Owners | Static M2 terminal Resource I/O, Mesh preparation and cache outcome | | Last verified | Worktree `work/sindo-main-codex/m03-m2-mesh-resource-finalizer`, 2026-07-18 | | Profiles/capabilities | Existing cached/static MultiMesh M2 path | ## Purpose Drain static M2 ResourceLoader work and publish a prepared Mesh or missing-model outcome without keeping terminal I/O and refresh logic in `StreamingWorldLoader`. The same preparation method serves threaded and synchronous Mesh consumers. ## Non-goals - Select cache candidates or admit threaded ResourceLoader requests. - Own scheduler permits, prototype Nodes, MultiMeshes or SceneTree roots. - Change first-Mesh traversal, refresh version, rebuild rules or raw parser. - Merge static and animated terminal services through callbacks/frameworks. - Change cache formats, profiles or visible output. ## Context and boundaries ```mermaid flowchart LR Observer[M2StaticBuildResourceObserver] --> Pipeline[M2MeshLoadPipelineState] Loader[StreamingWorldLoader] --> Finalizer[M2MeshResourceFinalizer] Pipeline --> Finalizer ResourceLoader --> Finalizer Finalizer --> Extractor[M2MeshResourceExtractor] Finalizer --> Runtime[M2RuntimeMeshFinalizer] Finalizer --> Raw[M2RawModelRepository] Finalizer --> MeshCache[M2MeshResourceCacheState] Finalizer --> Prototype[M2PrototypeCacheState] ``` ## Public API | Symbol | Kind | Purpose | Failure behavior | |---|---|---|---| | `poll_terminal_requests(pipeline, prototype_cache)` | I/O command | Move LOADED/FAILED records into completion FIFO | Invalid composition returns zero | | `finalize_next_resource(pipeline, mesh_cache, prototype_cache, extracted_dir)` | I/O command | Pop one record and publish Mesh/missing outcome | Empty/invalid composition returns false | | `prepare_mesh_for_runtime(path, mesh, extracted_dir)` | I/O preparation | Preserve current Mesh or load raw data and refresh stale Mesh | Null returns null | | `load_threaded_get_status(path)` | I/O adapter | Production status query with injectable test seam | Returns ResourceLoader status | | `load_threaded_get(path)` | I/O adapter | Production terminal Resource retrieval with injectable test seam | May return null | ## Inputs and outputs | Direction | Data | Producer | Consumer | Ownership/lifetime | |---|---|---|---|---| | Input | Pending/finalize records | Mesh pipeline | Finalizer | Pipeline-owned copied Dictionaries | | Input | Terminal Resource | ResourceLoader | Mesh extractor | Borrowed one operation | | Input | Extracted/cached Mesh | Mesh extractor/loader consumer | Runtime preparation | Borrowed Resource reference | | Input | Raw M2 Dictionary | Raw repository | Runtime finalizer | Call-local value | | Output | Prepared Mesh | Runtime finalizer | Mesh cache/loader consumer | Resource reference | | Output | Missing-model outcome | Finalizer | Prototype cache | Copied path; loader session | | Output | Processed-record flag | Finalizer | Loader permit loop/tests | Boolean value | ## Data flow ```mermaid flowchart TD Poll[Poll pending records in insertion order] --> Path{Resource path empty?} Path -->|yes| Discard[Discard and mark missing] Path -->|no| Status{LOADED or FAILED?} Status -->|no| Pending[Keep pending] Status -->|yes| Complete[Append completion FIFO] Complete --> Permit[Loader consumes M2_MESH_FINALIZE permit] Permit --> Pop[Pop oldest terminal record] Pop --> Cached{Empty path or Mesh cached?} Cached -->|yes| Skip[Finish one permit operation] Cached -->|no| Loaded{Status LOADED?} Loaded -->|no| Missing[Mark model missing] Loaded -->|yes| Get[Get terminal Resource] Get --> Extract[Extract first Mesh] Extract --> Found{Mesh found?} Found -->|no| Missing Found -->|yes| Current{Refresh version current?} Current -->|yes| Store[Store exact Mesh] Current -->|no| Raw[Read raw M2 data] Raw --> Refresh[Finalize/rebuild/fallback Mesh] Refresh --> Store ``` ## Lifecycle/state ```mermaid stateDiagram-v2 [*] --> Polling Polling --> Pending: nonterminal status Polling --> TerminalQueued: LOADED or FAILED Polling --> Missing: empty Resource path TerminalQueued --> Skipped: empty/cached record TerminalQueued --> Missing: failed load or no Mesh TerminalQueued --> Extracted: Mesh found Extracted --> Current: refresh version current Extracted --> Refreshing: stale Mesh Refreshing --> Prepared: rebuild or fallback Current --> Cached Prepared --> Cached Pending --> [*] Skipped --> [*] Missing --> [*] Cached --> [*] ``` ## Main sequence ```mermaid sequenceDiagram participant L as StreamingWorldLoader participant F as M2MeshResourceFinalizer participant P as M2MeshLoadPipelineState participant R as ResourceLoader participant E as M2MeshResourceExtractor participant N as M2RuntimeMeshFinalizer participant C as M2MeshResourceCacheState L->>F: poll_terminal_requests(P, prototype cache) F->>R: load_threaded_get_status(path) F->>P: complete terminal request L->>L: consume M2_MESH_FINALIZE permit L->>F: finalize_next_resource(...) F->>P: pop oldest record F->>R: load_threaded_get(path) F->>E: extract_first_mesh(Resource) F->>N: requires_raw_data_for_refresh(Mesh) opt stale Mesh F->>F: read raw M2 data F->>N: finalize_mesh(...) end F->>C: store prepared Mesh ``` ## Dependency diagram ```mermaid flowchart TB Finalizer[M2MeshResourceFinalizer] --> ResourceLoader Finalizer --> Pipeline[M2MeshLoadPipelineState] Finalizer --> Extractor[M2MeshResourceExtractor] Finalizer --> Runtime[M2RuntimeMeshFinalizer] Finalizer --> Raw[M2RawModelRepository] Finalizer --> MeshCache[M2MeshResourceCacheState] Finalizer --> Prototype[M2PrototypeCacheState] Loader[StreamingWorldLoader] --> Finalizer Loader --> Scheduler[RenderBudgetScheduler] Finalizer -. no dependency .-> Scheduler Finalizer -. no dependency .-> MultiMesh Finalizer -. no dependency .-> SceneTree ``` ## Ownership, threading and resources - All operations run synchronously on the renderer main thread. - Pipeline owns pending/completion records; one permit pops one terminal record. - Extractor owns temporary PackedScene instance cleanup and returns a Mesh reference. - Runtime finalizer owns stale/current/rebuild/fallback rules; raw repository owns only call-local native I/O. - Mesh cache retains prepared Mesh references until final shutdown; prototype cache retains missing-model paths. - Service retains dependency references but no pending record, Resource, Mesh or raw Dictionary between calls. Loader retains permits and materialization. ## Errors, cancellation and recovery | Failure/state | Behavior | Recovery | |---|---|---| | Missing composition dependency | Return zero/false; preparation keeps Mesh where possible | Correct composition | | Empty Resource path | Discard request and mark missing | Repair cache and restart session | | Nonterminal status | Keep pending | Poll next tick | | FAILED status | Pop and mark missing | Repair cache and restart session | | Existing cached Mesh | Pop and skip terminal Resource get | None | | Null/unsupported/no-Mesh Resource | Mark missing | Repair imported cache | | Raw read/rebuild unavailable | Runtime finalizer marks/reuses original Mesh | Existing fallback | | Tile cancellation | Shared cache work continues | Loader queue remains authoritative | | Shutdown | Loader drains ResourceLoader before pipeline/cache clear | New loader starts empty | ## Configuration and capabilities The service consumes the existing extracted directory. The scheduler retains `m2_mesh_finalize_ops_per_tick`; material refresh version remains `2`. ## Persistence, cache and migration No cache path, schema or version changes are introduced. Existing `.tscn/.glb` Resources and in-memory refresh metadata remain compatible; no rebake is required. ## Diagnostics and observability The service adds no log. Existing pending-plus-finalize metrics and refresh metadata remain unchanged. Normalized relative path remains the correlation key. ## Verification - Dedicated verifier covers status insertion order, empty-path discard, FIFO, failed/cached/null outcomes, terminal get, exact Mesh identity, stale-only raw read, exact finalizer arguments, cache adoption, source ownership and timing. - Pipeline/cache/extractor/runtime-finalizer/raw-repository/prototype/shutdown, facade, internal-access and baseline regressions protect adjacent behavior. - Fidelity evidence is exact lifecycle/I/O extraction only; no private asset, original-client visual, leak-pressure or p95/p99 claim is made. ## Extension points Further extraction can move static prototype/material-source construction without changing this terminal Resource contract. Animated finalization remains separate because its candidate-before-material ordering and Node ownership differ. ## Capability status | Capability | Status | Evidence | Gap/next step | |---|---|---|---| | Static terminal polling/load | Implemented extraction | Status/FIFO/load/source verifier | Asset-backed traversal pending | | Mesh extraction/preparation/cache outcome | Implemented extraction | Identity/raw/finalizer/store verifier | Private leak/p95/p99 pending | | Static MultiMesh materialization | Separate implemented service | Materializer verifier | GPU/asset-backed evidence pending | ## Known gaps and risks - Terminal Resource get, extraction and stale rebuild remain synchronous main-thread work. - Prepared Mesh cache remains unbounded until final shutdown. - Private asset traversal, descriptor pressure, leak and p95/p99 evidence is absent. ## Source map | Path | Responsibility | |---|---| | `src/render/m2/m2_mesh_resource_finalizer.gd` | Poll/load/extract/prepare/cache/missing service | | `src/render/m2/m2_mesh_load_pipeline_state.gd` | Pending and completion FIFO ownership | | `src/render/m2/m2_mesh_resource_extractor.gd` | First-Mesh and temporary-instance ownership | | `src/render/m2/m2_runtime_mesh_finalizer.gd` | Refresh/rebuild/fallback rules | | `src/render/m2/m2_raw_model_repository.gd` | Optional native raw M2 boundary | | `src/render/m2/m2_mesh_resource_cache_state.gd` | Prepared Mesh ownership | | `src/render/m2/m2_prototype_cache_state.gd` | Missing-model outcome ownership | | `src/scenes/streaming/streaming_world_loader.gd` | Permit loop and materialization composition | | `src/tools/verify_m2_mesh_resource_finalizer.gd` | Polling/preparation/boundary/timing regression | ## Related decisions and references - [`m2-mesh-load-pipeline-state.md`](m2-mesh-load-pipeline-state.md) - [`m2-mesh-resource-cache-state.md`](m2-mesh-resource-cache-state.md) - [`m2-mesh-resource-extractor.md`](m2-mesh-resource-extractor.md) - [`m2-runtime-mesh-finalizer.md`](m2-runtime-mesh-finalizer.md) - [`m2-raw-model-repository.md`](m2-raw-model-repository.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)