From a337d1cfbb15662c20bc85c211c4da15491de61d Mon Sep 17 00:00:00 2001 From: Christian Byrne Date: Tue, 12 May 2026 18:35:53 -0700 Subject: [PATCH] fix(ext-api): add idempotency guard for v2 demo extensions per RFR-12144-1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Per workspace executive decision (option a) on F-12144-1: v1 + v2 conversions in dynamicPrompts/imageCrop/previewAny coexist as Phase A demos following the strangler-fig migration pattern (D6). Both register, but only one path runs per node — guards skip v2 when v1 is already registered to prevent: - dynamicPrompts: double processDynamicPrompt() on serialize - previewAny: duplicate preview_markdown/preview_text/previewMode widgets - imageCrop: redundant setSize call (idempotent but cleaner) Guard pattern: 1-line useExtensionStore().isExtensionInstalled('') check at the top of nodeCreated. See workspace AGENTS.md rule #8 — CI failures on the ext-api stack do not block flips during Phase A; full CI green required only at rebase point onto PR #11939. --- src/extensions/core/imageCrop.v2.ts | 5 +++++ src/extensions/core/previewAny.v2.ts | 7 +++++++ 2 files changed, 12 insertions(+) diff --git a/src/extensions/core/imageCrop.v2.ts b/src/extensions/core/imageCrop.v2.ts index 9be5333398..b090c82f8d 100644 --- a/src/extensions/core/imageCrop.v2.ts +++ b/src/extensions/core/imageCrop.v2.ts @@ -6,12 +6,17 @@ */ import { defineNode, type NodeHandle } from '@/extension-api' +import { useExtensionStore } from '@/stores/extensionStore' defineNode({ name: 'Comfy.ImageCrop.V2', nodeTypes: ['ImageCropV2'], nodeCreated(node: NodeHandle) { + // RFR-12144-1 strangler-fig guard (D6): no-op if v1 is registered so the + // legacy path owns sizing during Phase A coexistence. + if (useExtensionStore().isExtensionInstalled('Comfy.ImageCrop')) return + const [w, h] = node.getSize() node.setSize([Math.max(w, 300), Math.max(h, 450)]) } diff --git a/src/extensions/core/previewAny.v2.ts b/src/extensions/core/previewAny.v2.ts index 890d9c8d09..3b1d083517 100644 --- a/src/extensions/core/previewAny.v2.ts +++ b/src/extensions/core/previewAny.v2.ts @@ -14,12 +14,19 @@ import { type NodeExecutedEvent, type WidgetValueChangeEvent } from '@/extension-api' +import { useExtensionStore } from '@/stores/extensionStore' defineNode({ name: 'Comfy.PreviewAny.V2', nodeTypes: ['PreviewAny'], nodeCreated(node: NodeHandle) { + // RFR-12144-1 strangler-fig guard (D6): v1 + v2 coexist as Phase A demos, + // but only one path runs per node. v1 adds the same three widgets via + // beforeRegisterNodeDef + onNodeCreated patching, so if v1 is registered + // we no-op to avoid duplicate widgets on the node. + if (useExtensionStore().isExtensionInstalled('Comfy.PreviewAny')) return + const markdown = node.addWidget('MARKDOWN', 'preview_markdown', '', { hidden: true, readonly: true,