Pass 3
Some checks failed
CI / React UI Build (push) Successful in 11s
CI / Native Windows Build And Tests (push) Successful in 2m48s
CI / Windows Release Package (push) Has been cancelled

This commit is contained in:
Aiden
2026-05-11 02:06:17 +10:00
parent b2369c418b
commit 5cbdbd6813
22 changed files with 2069 additions and 1504 deletions

View File

@@ -42,11 +42,11 @@ That order mirrors the intended dependency story:
## Subsystem Notes
- [RuntimeStore.md](/c:/Users/Aiden/Documents/GitHub/video-shader-toys/docs/subsystems/RuntimeStore.md)
Durable runtime config, persisted layer state, presets, and package metadata ownership.
Durable runtime-state facade over layer-stack, config, package-catalog, presentation, and persistence boundaries.
- [RuntimeCoordinator.md](/c:/Users/Aiden/Documents/GitHub/video-shader-toys/docs/subsystems/RuntimeCoordinator.md)
Mutation validation, state classification, reset/reload policy, and publication/persistence requests.
- [RuntimeSnapshotProvider.md](/c:/Users/Aiden/Documents/GitHub/video-shader-toys/docs/subsystems/RuntimeSnapshotProvider.md)
Render-facing snapshot build, publication, and versioning boundaries.
Render-facing snapshot publication boundary backed by explicit render snapshot building/versioning.
- [ControlServices.md](/c:/Users/Aiden/Documents/GitHub/video-shader-toys/docs/subsystems/ControlServices.md)
OSC, HTTP/WebSocket, and file-watch ingress plus normalization and service-local buffering.
- [RenderEngine.md](/c:/Users/Aiden/Documents/GitHub/video-shader-toys/docs/subsystems/RenderEngine.md)

View File

@@ -12,7 +12,7 @@ It exists to solve three current problems:
- render state is still built directly out of `RuntimeHost` under a shared mutex
- render reads and refreshes partially mutable cached layer state in more than one place
- state publication, state versioning, and dynamic frame-field refresh are not yet explicit subsystems
- state publication, state versioning, and dynamic frame-field refresh need explicit ownership
Today the closest current behavior lives in:
@@ -29,13 +29,17 @@ Today the closest current behavior lives in:
`RuntimeSnapshotProvider` is responsible for:
- building render-facing snapshots from durable store state plus whatever committed-live state view the Phase 3 split ultimately exposes
- publishing stable, versioned snapshots that can be consumed without large shared mutable locks
- giving `RenderEngine` a cheap read path for the latest committed snapshot
- making snapshot invalidation and publication rules explicit
`RenderSnapshotBuilder` is responsible for:
- building render-facing snapshots from durable store state plus whatever committed-live state view the Phase 3 split ultimately exposes
- separating structural snapshot changes from dynamic frame fields
- translating runtime layer state into render-ready layer descriptors
- attaching immutable or near-immutable shader/package-derived data needed by render
- giving `RenderEngine` a cheap read path for the latest committed snapshot
- making snapshot invalidation and publication rules explicit
- maintaining render snapshot version counters and frame advancement
It is not responsible for:
@@ -75,7 +79,7 @@ The shape of render-facing layer state should remain consistent across phases ev
## Snapshot Inputs
`RuntimeSnapshotProvider` should build from a read-oriented runtime view, not from direct mutation calls.
`RenderSnapshotBuilder` should build from a read-oriented runtime view, not from direct mutation calls. `RuntimeSnapshotProvider` should consume the builder's output and own publication/cache behavior.
That view will likely include:
@@ -87,7 +91,8 @@ That view will likely include:
The important Phase 1 rule is not "the provider always reads one specific object." It is:
- the provider consumes read-oriented committed runtime state
- the builder consumes read-oriented committed runtime state
- the provider consumes builder-published render snapshot data
- the provider does not own mutation policy
- render consumes the provider's published output instead of reaching back into whichever runtime object currently stores the truth
@@ -292,11 +297,11 @@ Notes:
### `RuntimeStore`
`RuntimeSnapshotProvider` depends on store-owned durable data and package metadata through a read-oriented interface or view.
`RenderSnapshotBuilder` depends on store-owned durable data and package metadata through a read-oriented interface or view. `RuntimeSnapshotProvider` depends on the builder rather than reaching into store internals directly.
If committed live state remains physically co-located with the store during early migration, the provider may read it through the same view. If committed live state moves behind a coordinator-owned live-session model later, the provider should consume that through a similarly read-oriented view.
If committed live state remains physically co-located with the store during early migration, the builder may read it through the same view. If committed live state moves behind a coordinator-owned live-session model later, the builder should consume that through a similarly read-oriented view.
It should not mutate the store directly.
Neither the builder nor provider should mutate the store directly.
### `RuntimeCoordinator`
@@ -337,7 +342,7 @@ This is especially important while migrating away from the current lock/fallback
The current code suggests the following migration map.
### Move into `RuntimeSnapshotProvider`
### Move into `RenderSnapshotBuilder`
From `RuntimeHost`:
@@ -346,6 +351,12 @@ From `RuntimeHost`:
- explicit version composition for render-visible state
- dynamic frame-context construction currently done in `RefreshDynamicRenderStateFields(...)`
### Move into `RuntimeSnapshotProvider`
- published snapshot cache ownership
- version matching for already-published snapshots
- render-facing compatibility API while render callers migrate
### Stop exposing directly from the host/store boundary
Current methods that should become compatibility shims and later disappear:
@@ -357,9 +368,9 @@ Current methods that should become compatibility shims and later disappear:
### Render-side compatibility during migration
The current `OpenGLComposite` cache path:
The previous `OpenGLComposite` cache path:
- reads versions from `RuntimeHost`
- reads versions from `RuntimeHost`/store-owned counters
- conditionally calls `TryRefreshCachedLayerStates(...)`
- conditionally rebuilds full layer state
- then reapplies render-local OSC overlay state
@@ -367,8 +378,8 @@ The current `OpenGLComposite` cache path:
During migration, that should become:
1. get latest published snapshot from provider
2. compare snapshot versions against render-local cache
3. rebuild only if needed
2. compare snapshot versions produced by `RenderSnapshotBuilder`
3. rebuild through `RenderSnapshotBuilder` only if needed
4. apply render-local overlay state
5. attach frame context

View File

@@ -276,7 +276,7 @@ Per the Phase 1 subsystem design, `RuntimeStore` should sit low in the dependenc
Allowed inbound dependencies:
- `RuntimeCoordinator -> RuntimeStore`
- `RuntimeSnapshotProvider -> RuntimeStore`
- `RenderSnapshotBuilder -> RuntimeStore`
- temporary migration shims from `ControlServices` only where explicitly tolerated
Allowed outbound dependencies:
@@ -359,16 +359,33 @@ Those belong under other target subsystems.
`RuntimeStore` does not need to be one monolithic class forever. A practical internal shape would be:
- `RuntimeConfigStore`
- runtime host config load/save and resolved paths
- `PersistentLayerStore`
- runtime host config load and resolved paths
The current codebase has begun this split: `RuntimeConfigStore` owns config parsing, path resolution, configured ports/formats, runtime roots, and shader compiler paths, while `RuntimeStore` keeps compatibility delegates for existing callers.
- `LayerStackStore`
- durable layer stack and parameter values
- `StackPresetStore`
- preset enumeration/load/save
- `ShaderPackageCatalogStore`
- layer CRUD/reorder and shader selection
- stack preset value serialization/load
- `RuntimeStatePresenter` / `RuntimeStateJson`
- runtime-state JSON assembly
- layer-stack presentation serialization
- `RenderSnapshotBuilder`
- render-state assembly and parameter refresh
- dynamic frame-field refresh and render snapshot version counters
- `ShaderPackageCatalog`
- durable manifest/package metadata
- shader package scanning, status/order/lookup, and asset/source change comparison
- `PersistenceWriter` helper
- synchronous at first, async/debounced later
The current codebase has begun the layer split: `LayerStackStore` owns durable layer state, layer CRUD/reorder, parameter persistence, and stack preset value serialization/load. `RuntimeStore` still owns locking, file IO, and compatibility delegates for existing callers.
The current codebase has begun the render snapshot split: `RenderSnapshotBuilder` owns render-state assembly, cached parameter refresh, dynamic frame-field refresh, and render snapshot versions. `RuntimeSnapshotProvider` depends on this builder rather than on `RuntimeStore` friendship.
The current codebase has also begun the presentation split: `RuntimeStatePresenter` owns top-level runtime-state JSON assembly, while `RuntimeStateJson` owns the layer-stack and parameter presentation shape used by runtime state clients.
The current codebase has also begun the package split: `ShaderPackageCatalog` owns package scanning and registry comparison, while `RuntimeStore` uses it to keep layer state valid and to build compatibility read models.
These can still be presented through one subsystem façade during migration.
## Persistence Model