mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-07-14 19:27:09 +00:00
8f6d4e09275136e023408fe03497fa097fd39b03
7 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
be38f14619 |
docs: retarget ECS architecture docs to dedicated stores over a single World (#13039)
## Summary Realign the ECS architecture docs and ADR 0008 with the shipped direction (PR #12617): entity data lives in dedicated Pinia stores keyed by string IDs, rather than one unified \"World\" registry addressed by branded entity IDs. ## Changes - **What**: Docs-only. Retarget the `docs/architecture/` set + ADR 0008 + agent guidance from the single-World/branded-`*EntityId` model to the dedicated-store model that PR #12617 actually shipped (`widgetValueStore` keyed by `WidgetId`, `layoutStore`, `nodeOutputStore`, `domWidgetStore`, `subgraphNavigationStore`, `previewExposureStore`). - `AGENTS.md` + `.agents/checks/adr-compliance.md`: point entity-data guidance at dedicated stores; fix the inverted `world.getComponent` compliance check (it flagged correct store-based code). - `ADR 0008`: dated amendment note (stays Proposed); rewrite the World section → dedicated stores, Branded ID design (`WidgetId` composite string), migration strategy, render-loop, consequences, notes. - `proto-ecs-stores.md`: flip the \"Unified World / branded IDs\" framing from gap-to-close → target; replace the deleted `PromotedWidgetViewManager` with the `input.widgetId` store-backed model; fix key formats and store count. - `ecs-target-architecture.md` / `ecs-lifecycle-scenarios.md` / `ecs-migration-plan.md`: reframe all `world.*` APIs and `*EntityId` brands to per-store APIs + string keys; mark already-shipped migration phases done. - `subgraph-boundaries-and-promotion.md` / `entity-interactions.md` / `entity-problems.md`: scope-tagged store entries; swap removed `PromotionStore` for `previewExposureStore`. - `appendix-critical-analysis.md`: post-pivot status banner + resolution notes on the critiques the pivot vindicated; still-open gaps (extension callbacks, atomicity, Y.js↔ECS) left live. - `appendix-ecs-pattern-survey.md`: supersede banner; keep the external library survey (§1). - Delete obsolete `ecs-world-command-api.md` (its command-pattern argument folded into ADR 0008). - **Breaking**: None (documentation only). ## Review Focus - ADR 0008 stays **Proposed** with an amendment note rather than a new superseding ADR — confirm that's the preferred mechanism vs. a fresh ADR. - Numeric per-kind brands (`NodeEntityId`, `LinkEntityId`, …) are retained in ADR 0008 but explicitly marked aspirational/unshipped; only `WidgetId` (composite string) reflects shipped code. - `appendix-ecs-pattern-survey.md` §2–§4 are kept under a supersede banner as historical record (they describe the deleted `src/world/` substrate) rather than rewritten — confirm that's preferred over deletion. - Net −384 lines; no code or test changes. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
162908a421 |
docs: ECS pattern survey appendix + PromotionStore cleanup (#12580)
## Summary Add the ECS pattern survey appendix to ADR 0008's companion-documents table, and drop stale `PromotionStore` references across architecture docs to reflect the ADR 0009 removal. ## Changes - **What**: - New `docs/architecture/appendix-ecs-pattern-survey.md` — surveys bitECS, miniplex, koota, ECSY, Bevy, and Thyseus: patterns adopted, departed from, and when to revisit. - ADR 0008 companion table gains a row pointing at the new appendix. - `docs/adr/0009-…/before-after-flows.md`, `docs/architecture/ecs-target-architecture.md`, `docs/architecture/entity-problems.md` — drop references to `PromotionStore` / `usePromotionStore` (the legacy three-layer mechanism is gone; promoted value widgets are now linked `SubgraphInput`s). - `docs/architecture/subgraph-boundaries-and-promotion.md` — reframes its "current mechanism" section as historical context with an explicit "removed by ADR 0009" callout. - **Breaking**: None — docs-only. ## Review Focus Wording in the historical-context callout on `subgraph-boundaries-and-promotion.md`. Everything else is a small cleanup or a new standalone document. --------- Co-authored-by: Amp <amp@ampcode.com> Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> Co-authored-by: GitHub Action <action@github.com> |
||
|
|
0157b47024 |
feat(subgraph): Subgraph Link Only Promotion (ADR 0009) + migration/store hygiene (#12197)
## Summary Introduces **Subgraph Link Only Promotion** (ADR 0009) — a new model for surfacing inner subgraph widgets on the parent SubgraphNode by *promoting through links* rather than by duplicating widget state on the host. Ships with the hygiene/refactor pass on the migration, store, and event layers that the new model depends on. ## What changes ### Subgraph Link Only Promotion (ADR 0009) Promoted widgets are defined by the link from a SubgraphNode input to the interior node, not by a duplicated widget instance on the host. Consequences: - A SubgraphNode renders inner widgets purely as a **projection** of the interior widgets and links — no host-side state to drift. - **Per-host independence**: multiple instances of the same SubgraphNode render and edit their own values without cross-talk. - **Reversible promote/demote**: structural link operation, so demote preserves host slots and external connections (#12278). ### Supporting refactors - **Migration** — Planner/classifier/repair/quarantine helpers collapsed into a single `proxyWidgetMigration` entry point with black-box round-trip coverage. Honors the source-node-id disambiguator on `proxyWidgets`, so deduplicated names (e.g. `text`, `text_1`) resolve to the right interior widget. - **Widget identity** — `appMode` unified on `WidgetEntityId`; promoted widget state is keyed by entityId across the store, DOM, and migration paths. - **SubgraphNode** — 3-key promoted-view cache replaced with a single version counter + explicit `invalidatePromotedViews()` at mutation sites; `id === -1` sentinel removed. - **Events** — `LGraph.trigger()` now dispatches node trigger payloads through `this.events`, replacing a leaky `onTrigger` monkey-patch. `SubgraphEditor` reactivity is driven from subgraph events instead of imperative refresh. - **Stores** — `appModeStore` migration helpers collapsed into `upgradeAndValidateInput`; `nodeOutputStore.*ByExecutionId` derived from the locator index; `previewExposureStore` cleanup and cycle-detection double-warn fix. - **Misc** — `Outcome` types consolidated; mutable accumulators replaced with `flatMap`; new ESLint rule forbids litegraph imports under `src/world/`. ### Tests - Browser tests for promoted widgets retagged `@vue-nodes` and rewritten to assert against the rendered Vue node DOM (via `getNodeLocator` / `getByRole('textbox')` / `enterSubgraph`) instead of `page.evaluate` graph introspection. - Per-host widget independence asserted via DOM. - Migration coverage moved to black-box round-trip tests. - Added coverage for duplicate-named promoted widget identity (ADR 0009) and the per-parent demote branch in `WidgetActions`. ## Review focus - ADR 0009 conformance of the link-only promotion model. - Disambiguator resolution path in `proxyWidgetMigration`. - Single-version-counter promoted-view cache and its `invalidatePromotedViews()` call sites. - `LGraph.trigger()` event dispatch and the `AppModeWidgetList.vue` migration off `onTrigger` (FE-667 tracks the remaining `useGraphNodeManager` conversion). ## Breaking changes None for users. Internal subgraph promotion APIs changed — see ADR 0009. ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-12197-feat-subgraph-link-only-widget-promotion-migration-store-hygiene-35e6d73d365081fd882cf3a69bc09956) by [Unito](https://www.unito.io) --------- Co-authored-by: Amp <amp@ampcode.com> Co-authored-by: GitHub Action <action@github.com> Co-authored-by: github-actions <github-actions@github.com> Co-authored-by: Glary-Bot <glary-bot@users.noreply.github.com> Co-authored-by: AustinMroz <austin@comfy.org> |
||
|
|
1f4a4af079 |
docs: add subgraph promoted widgets ADR (#11997)
## Summary Adds an ADR documenting the canonical subgraph promoted-widget model and legacy proxy-widget ratchet. ## Changes - **What**: Defines linked `SubgraphInput` promoted widgets, host-owned sparse value overlays, proxy-widget repair/quarantine behavior, primitive-node repair, and separate display-only preview exposures. - **Breaking**: None; documentation only. - **Dependencies**: None. ## Review Focus - Whether the ADR cleanly separates value-owning promoted widgets from display-only preview exposures. - Whether the legacy ratchet, quarantine, primitive repair, and UI identity decisions are clear enough for implementation review. ## Screenshots (if applicable) N/A @Coderabbitai why would a docs update need an end-to-end test? ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-11997-docs-add-subgraph-promoted-widgets-ADR-3576d73d36508133bf1ee8d49282cac1) by [Unito](https://www.unito.io) --------- Co-authored-by: GitHub Action <action@github.com> |
||
|
|
a1e6fb36d2 |
refactor: harden ChangeTracker lifecycle with self-defending API (#10816)
## Summary Harden the `ChangeTracker` lifecycle to eliminate the class of bugs where an inactive workflow's tracker silently captures the wrong graph state. Renames `checkState()` to `captureCanvasState()` with a self-defending assertion, introduces `deactivate()` and `prepareForSave()` lifecycle methods, and closes a latent undo-history corruption bug discovered during code review. ## Background ComfyUI supports multiple workflows open as tabs, but only one canvas (`app.rootGraph`) exists at a time. When the user switches tabs, the old workflow's graph is unloaded and the new one is loaded into this shared canvas. The old `checkState()` method serialized `app.rootGraph` into `activeState` to track changes for undo/redo. It had no awareness of *which* workflow it belonged to -- if called on an inactive tab's tracker, it would capture the active tab's graph data and silently overwrite the inactive workflow's state. This caused permanent data loss (fixed in PR #10745 with caller-side `isActive` guards). The caller-side guards were fragile: every new call site had to remember to add the guard, and forgetting would reintroduce the same silent data corruption. Additionally, `beforeLoadNewGraph` only called `store()` (viewport/outputs) without `checkState()`, meaning canvas state could be stale if a tab switch happened without a preceding mouseup event. ### Before (fragile) ``` saveWorkflow(workflow): if (isActive(workflow)) <-- caller must remember this guard workflow.changeTracker.checkState() <-- name implies "read", actually writes ... beforeLoadNewGraph(): activeWorkflow.changeTracker.store() <-- only saves viewport, NOT graph state ``` ### After (self-defending) ``` saveWorkflow(workflow): workflow.changeTracker.prepareForSave() <-- handles active/inactive internally ... beforeLoadNewGraph(): activeWorkflow.changeTracker.deactivate() <-- captures graph + viewport together ``` ## Changes - Rename `checkState` to `captureCanvasState` with active-tracker assertion - Add `deactivate()` and `prepareForSave()` lifecycle methods - Fix undo-history corruption: `captureCanvasState()` guarded by `_restoringState` - Fix viewport regression during undo: `deactivate()` skips `captureCanvasState()` during undo/redo but always calls `store()` to preserve viewport (regression from PR #10247) - Log inactive tracker warnings unconditionally at warn level (not DEV-only) - Deprecated `checkState()` wrapper for extension compatibility - Rename `checkState` to `captureCanvasState` in `useWidgetSelectActions` composable - Add `appModeStore.ts` to manual call sites documentation - Add `checkState()` deprecation note to architecture docs - Add 16 unit tests covering all guard conditions, lifecycle methods, and undo behavior - Add E2E test: "Undo preserves viewport offset" ## New ChangeTracker Public API | Method | Caller | Purpose | |--------|--------|---------| | `captureCanvasState()` | Event handlers, UI interactions | Snapshots canvas into activeState, pushes undo. Asserts active tracker. | | `deactivate()` | `beforeLoadNewGraph` only | `captureCanvasState()` (skipped during undo/redo) + `store()`. Freezes state for tab switch. | | `prepareForSave()` | Save paths only | Active: `captureCanvasState()`. Inactive: no-op. | | `checkState()` | **Deprecated** -- extensions only | Wrapper that delegates to `captureCanvasState()` with deprecation warning. | | `store()` | Internal to `deactivate()` | Saves viewport, outputs, subgraph navigation. | | `restore()` | `afterLoadNewGraph` | Restores viewport, outputs, subgraph navigation. | | `reset()` | `afterLoadNewGraph`, save | Resets initial state (marks as "clean"). | ## Test plan - [x] Unit tests: 16 tests covering all guard conditions, state capture, undo queue behavior - [x] E2E test: "Undo preserves viewport offset" verifies no viewport drift on undo - [x] E2E test: "Prevents captureCanvasState from corrupting workflow state during tab switch" - [x] Existing E2E: "Closing an inactive tab with save preserves its own content" - [ ] Manual: rapidly switch tabs during undo/redo, verify no viewport drift - [ ] Manual: verify extensions calling `checkState()` see deprecation warning in console |
||
|
|
3e197b5c57 |
docs: ADR 0008 — Entity Component System (#10420)
## Summary
Architecture documentation proposing an Entity Component System for the
litegraph layer.
```mermaid
graph LR
subgraph Today["Today: Spaghetti"]
God["🍝 God Objects"]
Circ["🔄 Circular Deps"]
Mut["💥 Render Mutations"]
end
subgraph Tomorrow["Tomorrow: ECS"]
ID["🏷️ Branded IDs"]
Comp["📦 Components"]
Sys["⚙️ Systems"]
World["🌍 World"]
end
God -->|"decompose"| Comp
Circ -->|"flatten"| ID
Mut -->|"separate"| Sys
Comp --> World
ID --> World
Sys -->|"query"| World
```
## Changes
- **What**: ADR 0008 + 4 architecture docs (no code changes)
- `docs/adr/0008-entity-component-system.md` — entity taxonomy, branded
IDs, component decomposition, migration strategy
- `docs/architecture/entity-interactions.md` — as-is Mermaid diagrams of
all entity relationships
- `docs/architecture/entity-problems.md` — structural problems with
file:line evidence
- `docs/architecture/ecs-target-architecture.md` — target architecture
diagrams
- `docs/architecture/proto-ecs-stores.md` — analysis of existing Pinia
stores as proto-ECS patterns
## Review Focus
- Does the entity taxonomy (Node, Link, Subgraph, Widget, Slot, Reroute,
Group) cover all cases?
- Are the component decompositions reasonable starting points?
- Is the migration strategy (bridge layer, incremental extraction)
feasible?
- Are there entity interactions or problems we missed?
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-10420-docs-ADR-0008-Entity-Component-System-32d6d73d365081feb048d16a5231d350)
by [Unito](https://www.unito.io)
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: GitHub Action <action@github.com>
Co-authored-by: Amp <amp@ampcode.com>
Co-authored-by: Christian Byrne <cbyrne@comfy.org>
|
||
|
|
7e137d880b |
docs: add change tracker architecture documentation (#9767)
Documents the ChangeTracker undo/redo system: how checkState() works, all automatic triggers, when manual calls are needed, transaction guards, and key invariants. Companion to #9623 which fixed missing checkState() calls in Vue widgets. ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-9767-docs-add-change-tracker-architecture-documentation-3216d73d365081268c27c54e0d5824e6) by [Unito](https://www.unito.io) --------- Co-authored-by: GitHub Action <action@github.com> |