Files
open-wc/docs/modules/streaming-target-planner.md
T
sindoring 5b10288ff7 docs(M03): publish streaming planner handoff
Work-Package: M03-RND-STREAMING-PLANNER-001
Agent: sindo-main-codex
Tests: planner and repository gates pass
Fidelity: no renderer policy or visual change
2026-07-16 00:08:24 +04:00

12 KiB

Streaming Target Planner

Metadata

Field Value
Status Implemented
Target/work package M03-RND-STREAMING-PLANNER-001
Owners Renderer workstream / M03 integrator
Last verified e887c3b, 2026-07-15
Profiles/capabilities Runtime and Editor preview ADT target selection; profile values supplied by caller

Purpose

Calculate which available ADT tiles are wanted and retained for one typed focus without accessing the SceneTree, worker tasks, renderer queues, caches or GPU resources. Runtime planning preserves prewarm, hysteresis and boundary-prefetch behavior; editor planning preserves the square preview radius.

Non-goals

  • Mutate load/finalize/eviction queues.
  • Prioritize queued tile paths by world distance.
  • Calculate chunk or tile LOD levels after a tile is loaded.
  • Own the available WDT tile catalog or cache paths.
  • Create, cancel or await jobs.
  • Implement M2, WMO, liquid or terrain attachment.

Context and boundaries

flowchart LR
    Focus[GodotWorldPosition] --> Planner[StreamingTargetPlanner]
    Policy[StreamingTargetPolicy] --> Planner
    Catalog[Available tile keys from WDT/directory] --> Planner
    Planner --> Plan[StreamingTargetPlan]
    Plan --> Streamer[StreamingWorldLoader queue/state apply]
    Streamer --> Queue[Tile load queue]

Allowed dependencies:

  • typed coordinate values and CoordinateMapper;
  • immutable planner policy/result contracts;
  • read-only available-tile key membership.

Forbidden dependencies:

  • Node, SceneTree and viewport/camera discovery;
  • WorkerThreadPool, ResourceLoader and filesystem access;
  • RenderingServer, meshes, materials, nodes and RIDs;
  • gameplay, network, UI, editor UI or server adapters;
  • streamer queues, tile states and cache dictionaries.

Public API

Symbol Kind Purpose Thread/lifetime Errors
StreamingTargetPlanner.plan_runtime Pure method Builds wanted/retained sets with edge/corner prefetch Any thread if caller does not mutate catalog concurrently; call-scoped Empty catalog produces empty sets
StreamingTargetPlanner.plan_editor Pure method Builds identical editor wanted/retained square sets Same as runtime planning Negative radius clamps to zero
StreamingTargetPolicy Immutable value Captures radius margins and boundary threshold for one plan Caller-owned, shareable Values retain scene input; effective margins/threshold are clamped
visible_tile_radius Pure query Resolves chunk-radius versus tile-radius visibility Any thread/value lifetime No failure
load_tile_radius Pure query Adds non-negative prewarm margin Any thread/value lifetime No failure
retained_tile_radius Pure query Adds non-negative hysteresis margin Any thread/value lifetime No failure
StreamingTargetPlan Immutable value Holds focus tile and read-only wanted/retained key sets Caller-owned plan lifetime No failure
wanted_tile_keys Read-only query Returns immutable wanted set Plan lifetime Mutation is rejected by Godot read-only Dictionary
retained_tile_keys Read-only query Returns immutable retained set Plan lifetime Mutation is rejected by Godot read-only Dictionary

Inputs and outputs

Direction Contract/data Producer Consumer Ownership Thread/lifetime
Input GodotWorldPosition WorldRenderFacade/streamer focus adapter Planner Immutable caller value One plan
Input Available <tile_x>_<tile_y> keys StreamingWorldLoader WDT/directory catalog Planner membership checks Loader-owned, read-only during call Map session
Input StreamingTargetPolicy Streamer configuration snapshot Planner Immutable caller value One or more plans
Input Editor preview radius Editor scene configuration Planner Scalar copy One plan
Output StreamingTargetPlan.focus_tile Planner/CoordinateMapper Streamer diagnostics Immutable typed coordinate Plan lifetime
Output Wanted tile-key set Planner Streamer queue/state apply Plan-owned read-only Dictionary Plan lifetime
Output Retained tile-key set Planner Streamer hysteresis/state apply Plan-owned read-only Dictionary Plan lifetime

Side effects:

  • none;
  • no input mutation;
  • no logging, I/O, task submission, cache access, SceneTree or GPU work.

Data flow

flowchart TD
    Position[GodotWorldPosition] --> Tile[CoordinateMapper.godot_to_adt_tile]
    Position --> Local[CoordinateMapper.godot_to_adt_tile_local]
    Policy[StreamingTargetPolicy] --> Radii[load and retained radii]
    Policy --> Threshold[clamped boundary threshold]
    Tile --> Centers[base prefetch center]
    Local --> Centers
    Threshold --> Centers
    Centers --> Wanted[available keys within load radius]
    Centers --> Retained[available keys within retained radius]
    Catalog[Available tile keys] --> Wanted
    Catalog --> Retained
    Wanted --> Plan[StreamingTargetPlan]
    Retained --> Plan
    Tile --> Plan

Lifecycle/state

The planner is stateless. A call creates local center/set dictionaries, freezes the result dictionaries in StreamingTargetPlan, returns the plan and retains no reference to inputs or output. There is no retry, cancellation or shutdown state machine.

Main sequence

sequenceDiagram
    participant Stream as StreamingWorldLoader
    participant Planner as StreamingTargetPlanner
    participant Mapper as CoordinateMapper
    participant Plan as StreamingTargetPlan
    Stream->>Planner: plan_runtime(catalog, typed focus, policy)
    Planner->>Mapper: focus tile and tile-local position
    Mapper-->>Planner: typed coordinates
    Planner->>Planner: prefetch centers and available key sets
    Planner->>Plan: freeze focus/wanted/retained result
    Plan-->>Stream: immutable target plan
    Stream->>Stream: apply queues, LOD and detail state

Ownership, threading and resources

  • StreamingWorldLoader owns the available catalog and must not mutate it during a planning call.
  • StreamingTargetPolicy and typed focus remain caller-owned immutable values.
  • The planner owns temporary center/set values only until plan construction.
  • StreamingTargetPlan owns its read-only result dictionaries.
  • The planner creates no Node, Resource, RID, thread, mutex or task.
  • Current runtime calls occur on the main thread; scene-free contracts permit a future worker call only after catalog publication/ownership is explicit.

Errors, cancellation and recovery

Failure Detection Behavior Diagnostic Recovery
Empty/unavailable catalog No membership matches Valid plan with empty sets Streamer retains existing missing-data diagnostics Load a valid WDT/directory catalog and replan
Focus outside catalog/grid Typed coordinate does not match keys Valid focus tile with filtered empty/partial sets Caller diagnostic if required Supply valid focus/map or catalog
Negative prewarm/retain margin Policy effective-radius query Margin clamps to zero Contract test Correct configuration if negative value was unintended
Boundary threshold outside range Policy query Clamp to 0.0..0.49 Contract test Correct configuration or accept safe clamp
Plan no longer current New focus/config/catalog revision Caller discards ephemeral plan Streamer refresh diagnostics Replan from current inputs

Cancellation is not applicable: planning is synchronous, bounded and owns no external work. A returned stale plan is simply not retained by the planner.

Configuration and capabilities

Setting/capability Default source Profile Runtime mutable Effect
lod2_radius_chunks Streamer scene/profile Renderer Yes at composition/debug boundary Converts chunk coverage to minimum ADT radius
lod2_tile_radius Streamer scene/profile Renderer Yes Minimum visible ADT radius
warm_tile_margin Streamer scene/profile Renderer Yes Extends chunk-derived visible radius
prewarm_tile_margin Streamer scene/profile Renderer Yes Extends wanted/load radius
retain_tile_margin Streamer scene/profile Renderer Yes Extends retained hysteresis radius
boundary_prefetch_threshold Streamer scene/profile Renderer Yes Adds adjacent/corner prefetch centers near tile boundaries
Editor preview radius Editor scene Authoring preview Yes Square wanted/retained preview set

The planner does not select Blizzlike335 or Enhanced; it applies the values already selected by renderer composition.

Persistence, cache and migration

  • Planner contracts are runtime-only and are not serialized.
  • Existing tile keys and cache paths are unchanged.
  • No cache/resource/schema version bump or migration is required.

Diagnostics and observability

  • Logs remain emitted by StreamingWorldLoader after applying a plan.
  • StreamingTargetPlan exposes focus/wanted/retained data for deterministic tests.
  • Dedicated verifier reports case count, iteration count, total time and average plan time.
  • No correlation ID is required for synchronous ephemeral plans.

Verification

  • Unit/contract: src/tools/verify_streaming_target_planner.gd covers center radii, edge/corner cross product, catalog filtering, clamps, editor behavior, input/result ownership and scene-free dependencies.
  • Integration: streamer source gate confirms both runtime/editor delegation and removal of _predictive_focus_tiles from the monolith.
  • Fidelity evidence: expected sets encode the pre-extraction formulas; renderer checkpoint dry-run must retain all seven checkpoint plans.
  • Performance budget: 250 synthetic High-like corner plans average at most 4.0 ms each on the headless regression runner; measured result is recorded in test output.
  • Manual diagnostics: unchanged StreamingWorld focus/wanted/queued log.

Extension points

  • Direction/velocity/frustum priority can extend policy/input only with fixtures and a compatibility-safe default reproducing the current position-only plan.
  • Multi-focus planning may union additional typed centers without giving the planner ownership of queues or consumers.
  • Queue ordering remains a separate scheduler/application responsibility.

Capability status

Capability Status Evidence Gap/next step
Runtime wanted/retained sets Implemented Center/corner/catalog fixtures Add paired traversal performance evidence
Boundary prefetch centers Implemented Edge/corner cross-product fixture Direction/velocity prediction not implemented
Editor preview set Implemented Negative/radius-one fixtures Editor viewport integration remains existing adapter
Scene-free deterministic execution Implemented Dependency/source gate and 250-iteration run Worker execution is unnecessary today
Queue priority/LOD Not in module Preserved in streamer Separate extraction packages

Known gaps and risks

  • Tile-key sets preserve the streamer's internal string representation; a typed catalog migration is deferred until it can remove, rather than duplicate, that source of truth.
  • Planner time scales with the union of square radii/prefetch centers. The current bounded regression covers High-like corner input but not pathological custom radii.
  • Exact p95/p99 frame impact still requires renderer baseline runs with local assets.
  • Direction, velocity and camera frustum do not influence target selection yet.

Source map

Path Responsibility
src/render/streaming/streaming_target_planner.gd Pure runtime/editor set calculation and boundary centers
src/render/streaming/streaming_target_policy.gd Immutable radius/threshold snapshot and effective clamps
src/render/streaming/streaming_target_plan.gd Immutable typed focus and read-only result sets
src/scenes/streaming/streaming_world_loader.gd Planner composition and plan application to queues/state
src/tools/verify_streaming_target_planner.gd Asset-free behavior/dependency/performance regression