|
| 1 | +# ECS decision traceability |
| 2 | + |
| 3 | +Status: Current implementation audit |
| 4 | +Verified: 2026-08-16 against PR 14246 |
| 5 | + |
| 6 | +This audit maps the implementation on `feature/ecs-migration` to the principles in |
| 7 | +[ADR 0003](../../adr/0003-crdt-based-layout-system.md) and |
| 8 | +[ADR 0008](../../adr/0008-entity-component-system.md). The ADRs remain the |
| 9 | +decision records; this audit neither replaces nor amends them. |
| 10 | + |
| 11 | +Status meanings: |
| 12 | + |
| 13 | +- `Implemented`: the observed implementation satisfies the principle for |
| 14 | + its stated scope. |
| 15 | +- `Partial`: an authoritative path exists, but legacy or uncovered concerns |
| 16 | + remain. |
| 17 | +- `Remaining`: the decision is not materially implemented. |
| 18 | +- `Superseded`: a documented amendment replaced an ADR detail. |
| 19 | + |
| 20 | +For ownership by state concern, see the |
| 21 | +[ECS State Authority Audit](ecs-state-authority-audit.md). Target descriptions |
| 22 | +remain in [ECS Target Architecture](../ecs-target-architecture.md), and |
| 23 | +sequencing is recorded in [ECS Migration Plan](ecs-migration-plan.md). |
| 24 | + |
| 25 | +## Traceability matrix |
| 26 | + |
| 27 | +| Principle | Status | Implementation | Verification evidence | Concrete remaining work | |
| 28 | +| --------------------------------------------------------------- | --------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | |
| 29 | +| Dedicated stores rather than a single World | **Implemented; original World superseded** | `useNodeDataStore`, `useWidgetValueStore`, `useLinkStore`, `useRerouteStore`, `layoutStore`, `useDomWidgetStore`, `useNodeOutputStore`, `useSubgraphNavigationStore`, and `usePreviewExposureStore` | Store tests cover registration, identity collisions, graph isolation, queries, and cleanup; ADR 0008's 2026-06-19 amendment explicitly replaces `world/*` | Continue moving the concerns still owned by LiteGraph classes; do not recreate a universal registry | |
| 30 | +| Plain-data components | **Partial** | `NodeState`, `LinkTopology`, `RerouteChain`, widget state, layout records, and `BadgeData` are data records; stores and systems own their behavior | `nodeDataStore`, `linkStore`, and `rerouteStore` register records and return reactive proxies; `computeBadges` accepts and returns plain data | Extract slot data and remaining link visual/runtime state; `NodeInputSlot`, `NodeOutputSlot`, `LLink`, and widgets still contain behavior | |
| 31 | +| Behavior in systems | **Partial** | `badgeSystem.computeBadges` is pure; `useLayoutMutations`, `graphLayoutAttachment`, `slotLinks`, and store actions isolate some behavior | `badgeSystem.test.ts`, layout operation tests, link/reroute store tests, and slot-link tests exercise behavior without a renderer | Move serialization, execution, connectivity orchestration, and render orchestration out of `LGraphNode`, `LGraph`, and `LGraphCanvas`; the ADR 0008 named systems are not generally present | |
| 32 | +| Command-driven mutation | **Partial** | `LayoutOperation`, `layoutStore.applyOperation` / `applyOperations`, `useLayoutMutations`, and geometry attachment functions route layout writes through explicit operations | `layoutStore.test.ts` and `layoutMutations.test.ts` verify operation handling and batches; all Yjs layout mutations occur in store transactions | Define serializable command boundaries for node data, links, reroutes, widgets, slots, and graph lifecycle; their current store/class mutators are imperative and are not replayable commands | |
| 33 | +| Graph and workflow scope | **Implemented for migrated stores** | `GraphScope`, `RootGraphId`, `OwningGraphId`, `graphScopeOf`; root buckets plus owner indexes in node/link/reroute stores; scoped layout keys; graph-prefixed `WidgetId` | Store tests cover root isolation, owner-local queries, duplicate IDs, and subgraph cases; browser coverage includes subgraph serialization and link identity collisions | Normalize older stores whose scope/key conventions differ; keep mutable state instance-scoped if linked subgraph definitions become shared | |
| 34 | +| Entity lifecycle follows graph lifecycle | **Implemented for migrated concerns** | `LGraph.add` / `remove` register and unregister node, topology, reroute, and geometry state; `clearOwner`, `clearGraph`, `attach*Layout`, `detach*Layout`, and `detachGraphLayouts` perform teardown | Identity-checked deletion tests prevent one instance vacating another's key; graph clear and replacement tests cover teardown and transfer | Remove lifecycle ownership from `LGraph` only when a replacement coordinator exists; audit transient DOM widgets and compatibility registries for the same owner-scoped teardown guarantees | |
| 35 | +| God-object reduction | **Partial** | Node shell, geometry, topology, reroute chains, widget values/order, and badge derivation have moved behind stores or systems | `NodeState` proxy drilling removed renderer mirrors; slot arrays are reactive by construction; topology reads use `slotLinks` | `LGraphNode`, `LGraph`, and `LGraphCanvas` still coordinate slots, widgets, mutation, serialization, execution, drawing, and input; extract only behind real consumers and parity tests | |
| 36 | +| Extension behavior and serialization preserved during migration | **Partial** | Legacy class accessors adopt store proxies; `input.link` and `output.links` remain deprecated derived reads; class mutation APIs remain compatibility entry points; existing workflow format remains in use | LiteGraph serialization/configuration, extension, widget, clipboard, replacement, and browser tests exercise old surfaces; deprecation tests cover slot mirrors | Publish and complete migrations for direct slot writes and node property enumeration; preserve callbacks and old workflow loading while removing mirrors; no proof covers the entire custom-node ecosystem | |
| 37 | +| CRDT-backed centralized layout | **Implemented for persistent entity geometry; partial overall** | Yjs owns node, group, and reroute geometry in `LayoutStoreImpl`; scoped keys, observers, geometry views, and `LayoutOperation` provide renderer-independent updates | `layoutStore.test.ts`, geometry-view tests, layout mutation tests, and Vue-node layout browser tests cover reads, writes, synchronization, and subgraphs | Link paths, slot bounds, and other hit-test geometry remain transient plain maps; integrate collaboration through the separate multiplayer contract rather than adding unused layout-store transport; undo/redo remains snapshot-based | |
| 38 | + |
| 39 | +## Observed boundaries |
| 40 | + |
| 41 | +- "Single source of truth" is per concern and workflow instance. It does not |
| 42 | + mean one global store. |
| 43 | +- The proxy-returning registration pattern avoids a second copy for node shell, |
| 44 | + link topology, reroute chain, and widget state. A class accessor over the |
| 45 | + registered proxy is a compatibility view, not another authority. |
| 46 | +- Layout command coverage must not be generalized to all ECS mutation. The |
| 47 | + other stores expose direct actions, and graph operations still coordinate |
| 48 | + imperative class callbacks. |
| 49 | +- Within this repository, Yjs supplies mergeable layout state and |
| 50 | + notifications, not a retained application operation log or network |
| 51 | + transport. ADR 0003's amendment records removal of those unused local seams. |
| 52 | +- [`@comfyorg/comfy-multi-player`](https://github.com/Comfy-Org/comfy-multi-player) |
| 53 | + separately implements a Yjs workflow document, stamped operation applier, |
| 54 | + and canonical workflow projection for a server-host/browser-follower model. |
| 55 | + Its contract leaves node positions, camera state, and other |
| 56 | + layout concerns in the frontend layout document. This frontend branch does |
| 57 | + not yet depend on or integrate that package, and its server document host is |
| 58 | + still described as unmerged. |
| 59 | +- Badges have no authoritative store. `badgeSystem` derives |
| 60 | + transient `BadgeData` from authoritative settings, definitions, topology, |
| 61 | + pricing, widget, and graph state. |
| 62 | +- The migration preserves extension-facing object surfaces, but compatibility |
| 63 | + has costs: enumerable node shell fields changed to accessors, direct slot |
| 64 | + mirror writes are ignored, and callback preservation remains a release |
| 65 | + constraint. |
| 66 | + |
| 67 | +## Reference records |
| 68 | + |
| 69 | +- [ADR 0003: Centralized Layout Management with CRDT](../../adr/0003-crdt-based-layout-system.md) |
| 70 | +- [ADR 0008: Entity Component System](../../adr/0008-entity-component-system.md) |
| 71 | +- [Node Data Store](../node-data-store.md) |
| 72 | +- [Link Topology Store](../link-topology-store.md) |
| 73 | +- [Reroute Chain Store](../reroute-chain-store.md) |
| 74 | +- [Node Badge Store design history](../node-badge-store.md) |
| 75 | +- [Output Slot Connectivity](../output-slot-connectivity.md) |
| 76 | +- [`@comfyorg/comfy-multi-player`](https://github.com/Comfy-Org/comfy-multi-player) |
0 commit comments