Files
open-wc/docs/modules/m2-static-build-resource-observer.md
T

8.5 KiB

M2 Static Build Resource Observer

Metadata

Field Value
Status Implemented extraction
Target/work package M03 / M03-RND-M2-STATIC-BUILD-RESOURCE-OBSERVER-001
Owners Static build Mesh lookup, request selection and missing transition
Last verified Worktree work/sindo-main-codex/m03-m2-static-build-resource-observer, 2026-07-18
Profiles/capabilities Existing static MultiMesh M2 build path

Purpose

Produce the static phase of M2BuildResourceSnapshot: reuse a prepared Mesh, wait for an existing request, start the first eligible cache request, or record a terminal missing model while preserving historical path and GLB rules.

Non-goals

  • Observe animated/native prototypes or finalize threaded loads.
  • Own/free Meshes, Nodes, cache entries or snapshot lifetime.
  • Materialize instances, plan batches, rotate queues or consume permits.
  • Change cache format, candidate order, profiles or visible output.

Context and boundaries

flowchart LR
    Loader[StreamingWorldLoader] --> Observer[M2StaticBuildResourceObserver]
    MeshCache[M2MeshResourceCacheState] --> Observer
    Missing[M2PrototypeCacheState] --> Observer
    Pipeline[M2MeshLoadPipelineState] --> Observer
    Observer --> Snapshot[M2BuildResourceSnapshot]
    Snapshot --> Dispatch[M2BuildDispatchPlanner]

Public API

Symbol Kind Purpose Errors
observe(snapshot, path, cache_dir, mesh_cache, prototype_cache, pipeline) Command/query Adopt cached/pending/requested/missing static result Invalid inputs return rejected
cache_resource_paths(cache_dir, path, extensions) Pure query Return unique historical nested/lowercase/basename candidates Empty values yield fewer/empty candidates
glb_animation_schema(path) Read query Read OpenWC schema marker from GLB JSON Invalid/missing GLB returns empty String
OUTCOME_* Constants Stable diagnostic transition identifiers None

Inputs and outputs

Direction Data Producer Consumer Ownership/lifetime
Input Normalized M2 path/cache directory Loader Observer Copied Strings; one observation
Input Mesh/missing/request states M2 state services Observer Borrowed services; map/session
Input/output Resource snapshot Loader Observer/dispatch/materializer Borrowed; one build operation
Output Cached Mesh or missing/pending values Observer Snapshot Exact borrowed Mesh/scalars
Output Threaded request record Observer Mesh pipeline Pipeline-owned path record
Output Outcome StringName Observer Tests/future diagnostics Immutable scalar

Data flow

flowchart TD
    Start[Observe static path] --> Cached{Mesh cached?}
    Cached -->|yes| AdoptMesh[Adopt exact Mesh; cached]
    Cached -->|no| Missing{Already missing?}
    Missing -->|yes| AdoptMissing[Adopt missing]
    Missing -->|no| Pending{Request pending?}
    Pending -->|yes| AdoptPending[Adopt unresolved; pending]
    Pending -->|no| Candidates[Generate tscn then glb candidates]
    Candidates --> Eligible{Exists and not pivot-prefix GLB?}
    Eligible -->|yes| Request[Threaded request]
    Request -->|OK or busy| Remember[Remember request; requested]
    Eligible -->|none/error| MarkMissing[Mark/adopt missing]

Lifecycle/state

stateDiagram-v2
    [*] --> Observing
    Observing --> Cached
    Observing --> Pending
    Observing --> Requested
    Observing --> Missing
    Observing --> Rejected
    Cached --> [*]
    Pending --> [*]
    Requested --> [*]
    Missing --> [*]
    Rejected --> [*]

Main sequence

sequenceDiagram
    participant L as StreamingWorldLoader
    participant O as StaticBuildResourceObserver
    participant C as Mesh/prototype cache state
    participant P as MeshLoadPipelineState
    participant R as ResourceLoader
    participant S as M2BuildResourceSnapshot
    L->>O: observe(snapshot, path, cache_dir, states)
    O->>C: cached/missing lookup
    alt cache hit or missing
        O->>S: adopt static observation
    else pending
        O->>P: has_request
        O->>S: adopt unresolved observation
    else request candidate
        O->>R: exists + load_threaded_request
        O->>P: remember_request
        O->>S: adopt unresolved observation
    end

Dependency diagram

flowchart TB
    Observer[M2StaticBuildResourceObserver] --> ResourceLoader
    Observer --> FileAccess[GLB header/JSON read]
    Observer --> MeshCache[M2MeshResourceCacheState]
    Observer --> PrototypeCache[M2PrototypeCacheState]
    Observer --> Pipeline[M2MeshLoadPipelineState]
    Observer --> Snapshot[M2BuildResourceSnapshot]
    Observer -. no dependency .-> SceneTree
    Observer -. no dependency .-> Materializers
    Observer -. no dependency .-> Scheduler

Ownership, threading and resources

  • Observer retains no request, cache, snapshot or engine reference.
  • Cache/pipeline services retain their existing state and resource ownership.
  • Snapshot borrows the exact cached Mesh; observer never frees it.
  • Resource existence/request and GLB inspection run on renderer main thread.
  • M2MeshResourceFinalizer performs terminal polling, Resource extraction, Mesh preparation and cache/missing adoption from the loader permit loop.

Errors, cancellation and recovery

State Behavior Recovery
Invalid dependency/path Return rejected; no mutation Correct composition
Existing request Return pending; no duplicate request Retry when queue rotates
Pivot-prefix GLB Skip as static candidate Continue next candidate
Request error Stop historical search and mark missing Later reset/new session
No candidate Mark/adopt terminal missing Cache content becomes available in new session
Tile cancellation Observer retains nothing Loader/queue cancellation remains authoritative

Configuration and capabilities

The observer consumes existing m2_cache_dir. It adds no profile, cache version, batch, visibility, shadow or scheduler setting.

Persistence, cache and migration

No new persistence is introduced. Existing .tscn/.glb layout, pipeline records and missing-cache lifetime are unchanged; no rebake is required.

Diagnostics and observability

Returned outcomes distinguish rejected/cached/pending/requested/missing without logging. Existing queue and hitch metrics remain unchanged.

Verification

  • Dedicated verifier covers invalid, cached identity, missing, pending, path order/deduplication, absent GLB schema, source ownership and bounded timing.
  • Snapshot/dispatch/pipeline/cache/shutdown/facade/internal-access/checkpoint regressions protect adjacent behavior.
  • No original-client visual claim is made; this is bookkeeping/I/O extraction.

Extension points

Animated/native observation may become a separate producer of the animation phase. Shared cache candidate/GLB inspection can later be reused without adding a generic resource framework.

Capability status

Capability Status Evidence Gap
Static build lookup/request production Implemented extraction Lifecycle/path/source/timing verifier Asset-backed traversal pending
Static finalize/preparation Implemented extraction Mesh resource finalizer verifier Asset-backed traversal pending
Animated observation Existing loader-owned Animation regressions Separate producer pending

Known gaps and risks

  • Successful request behavior is protected by source plus existing pipeline tests; starting an undrained asynchronous request in the unit fixture would leak.
  • GLB schema parser reads synchronously, matching the previous loader behavior.
  • Private traversal, p95/p99, leak and visual evidence remain unavailable.

Source map

Path Responsibility
src/render/m2/m2_static_build_resource_observer.gd Static cache/request/missing observation
src/render/m2/m2_build_resource_snapshot.gd Typed observation result
src/render/m2/m2_mesh_resource_finalizer.gd Terminal polling, preparation and adoption
src/scenes/streaming/streaming_world_loader.gd Composition, permits and action execution
src/tools/verify_m2_static_build_resource_observer.gd Lifecycle/path/boundary/timing regression