From cbbb454d8f9bc9327a8da936f6d53cb2b657b41b Mon Sep 17 00:00:00 2001 From: akatz-ai Date: Fri, 13 Feb 2026 17:02:32 -0800 Subject: [PATCH 01/16] Use local-sources for comfygit-core dev override instead of pyproject injection The setup-dev-env script now uses `cg env-config local-sources add` to write comfygit-core's editable path to .local-uv-config (gitignored) instead of injecting [tool.uv.sources.comfygit-core] directly into pyproject.toml. Also cleans up old pyproject injections from previous script versions. Co-Authored-By: Claude Opus 4.6 --- scripts/setup-dev-env | 56 +++++++++++++++---------------------------- 1 file changed, 19 insertions(+), 37 deletions(-) diff --git a/scripts/setup-dev-env b/scripts/setup-dev-env index e4133a0..496b1aa 100755 --- a/scripts/setup-dev-env +++ b/scripts/setup-dev-env @@ -13,7 +13,7 @@ # # This script: # 1. Replaces registry-installed comfygit-manager with a symlink to this repo -# 2. Configures editable comfygit-core dependency in .cec/pyproject.toml +# 2. Adds comfygit-core as editable local source via .local-uv-config (not tracked in git) # 3. Marks comfygit-manager as a development node (skips version checks) set -e @@ -184,56 +184,39 @@ setup_environment() { ln -s "$MANAGER_PATH" "$manager_link" fi - # Update .cec/pyproject.toml + # Add comfygit-core as local source (writes to .local-uv-config, not tracked in git) + echo " Configuring comfygit-core local source..." + COMFYGIT_HOME="$WORKSPACE_PATH" cg -e "$env_name" env-config local-sources add comfygit-core \ + --path "$CORE_PATH" --editable 2>/dev/null \ + && echo " Core source: Configured in .local-uv-config" \ + || echo " Core source: Failed to configure (is cg installed?)" + + # Mark comfygit-manager as development node + clean up old pyproject injection if [[ ! -f "$pyproject" ]]; then - echo " Warning: .cec/pyproject.toml not found, skipping config" + echo " Warning: .cec/pyproject.toml not found, skipping dev node config" else - echo " Updating .cec/pyproject.toml..." - - # Use Python to safely update TOML python3 << PYEOF import re pyproject_path = "$pyproject" -core_path = "$CORE_PATH" -manager_path = "$MANAGER_PATH" with open(pyproject_path, "r") as f: content = f.read() modified = False -# 1. Update comfygit-core source for editable install +# Clean up old direct pyproject injection of comfygit-core source (now in .local-uv-config) if '[tool.uv.sources.comfygit-core]' in content: - if f'path = "{core_path}"' in content: - print(" Core source: Already configured") - else: - # Remove existing section and re-add - content = re.sub( - r'\[tool\.uv\.sources\.comfygit-core\][^\[]*', - '', - content, - flags=re.DOTALL - ) - modified = True -else: - modified = True - -if modified or '[tool.uv.sources.comfygit-core]' not in content: - content = content.rstrip() + f''' - -[tool.uv.sources.comfygit-core] -path = "{core_path}" -editable = true -''' - print(" Core source: Configured") + content = re.sub( + r'\n?\[tool\.uv\.sources\.comfygit-core\][^\[]*', + '', + content, + flags=re.DOTALL + ) + print(" Cleaned up old [tool.uv.sources.comfygit-core] from pyproject.toml") modified = True -# 2. Mark comfygit-manager as development node (skips version checks) -# Change source = "registry" to source = "development" for comfygit-manager if '[tool.comfygit.nodes.comfygit-manager]' in content: - # Check if already set to development - # Look for source = "development" within the comfygit-manager node section node_section_match = re.search( r'\[tool\.comfygit\.nodes\.comfygit-manager\](.*?)(?=\n\[|\Z)', content, @@ -247,13 +230,12 @@ if '[tool.comfygit.nodes.comfygit-manager]' in content: content = content.replace( 'source = "registry"', 'source = "development"', - 1 # Only replace first occurrence (in the node section) + 1 ) print(" Node source: Changed to development") modified = True else: print(" Node source: No source field found (will add)") - # Add source = "development" to the node section content = re.sub( r'(\[tool\.comfygit\.nodes\.comfygit-manager\]\n)', r'\1source = "development"\n', From 614eb3a90ede60465b57b3c9863221f5d4087410 Mon Sep 17 00:00:00 2001 From: akatz-ai Date: Sat, 14 Feb 2026 21:05:23 -0800 Subject: [PATCH 02/16] Add bead ID commit convention to CLAUDE.md and AGENTS.md Establishes convention to include bead IDs in commit messages (e.g. "Fix panel bug [cgm-abc]") for traceability between git history and issue tracking. Co-Authored-By: Claude Opus 4.6 --- AGENTS.md | 15 +++++++++++++++ CLAUDE.md | 26 ++++++++++++++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/AGENTS.md b/AGENTS.md index df7a4af..0325836 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -12,6 +12,21 @@ bd close # Complete work bd sync # Sync with git ``` +## Commit Convention — Bead References + +**When a commit implements, fixes, or closes a bead, include the bead ID(s) in the commit message.** This creates traceability between git history and issue tracking. + +Format: ` []` or ` [, ]` + +``` +Add accelerator packages panel [cgm-2v9] +Fix switch lock stale errors [cgm-abc] +``` + +- Place bead ID(s) at the end of the first line in square brackets +- Use this for commits that directly address bead work — skip for unrelated housekeeping commits +- If a commit fully resolves a bead, also close it with `bd close` + ## Landing the Plane (Session Completion) **When ending a work session**, you MUST complete ALL steps below. Work is NOT complete until `git push` succeeds. diff --git a/CLAUDE.md b/CLAUDE.md index a50ae10..d0bbd32 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -84,6 +84,32 @@ We are still pre-customer - any unnecessary fallbacks, unnecessary versioning, t Simple, elegant, maintainable code is the goal. We DONT want any legacy or backwards compatible code. +## Issue Tracking (Beads) + +Uses beads (`bd`) with prefix **`cgm-`**. Use for multi-session or dependent work; skip for simple single-session fixes. + +```bash +bd ready # Find available work +bd show cgm-xxx # View issue details +bd close cgm-xxx # Complete work +bd sync # Sync with git +``` + +### Commit Convention — Bead References + +**When a commit implements, fixes, or closes a bead, include the bead ID(s) in the commit message.** This creates traceability between git history and issue tracking. + +Format: ` []` or ` [, ]` + +``` +Add accelerator packages panel [cgm-2v9] +Fix switch lock stale errors [cgm-abc] +``` + +- Place bead ID(s) at the end of the first line in square brackets +- Use this for commits that directly address bead work — skip for unrelated housekeeping commits +- If a commit fully resolves a bead, also close it with `bd close` + ## Cross-Platform Compatibility This codebase must run on **Windows, Linux, and macOS**. All engineering choices should consider cross-platform compatibility: - Use `pathlib.Path` instead of string concatenation for file paths From 796c58ad85b5b9ece14674bd607b6785bdfd89d7 Mon Sep 17 00:00:00 2001 From: akatz-ai Date: Sat, 14 Feb 2026 23:27:25 -0800 Subject: [PATCH 03/16] Update pyproject sources and lockfile --- uv.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/uv.lock b/uv.lock index 5697620..82eaee6 100644 --- a/uv.lock +++ b/uv.lock @@ -401,7 +401,7 @@ wheels = [ [[package]] name = "comfygit-core" -version = "0.3.17" +version = "0.3.20" source = { editable = "../comfygit/packages/core" } dependencies = [ { name = "aiohttp" }, @@ -437,7 +437,7 @@ dev = [{ name = "pytest", specifier = ">=8.4.1" }] [[package]] name = "comfygit-manager" -version = "0.0.20" +version = "0.0.22" source = { virtual = "." } dependencies = [ { name = "comfygit-core" }, From 762f88327ddffad75d4895f92ee980182fc997c0 Mon Sep 17 00:00:00 2001 From: akatz-ai Date: Sat, 14 Feb 2026 23:49:35 -0800 Subject: [PATCH 04/16] Surface blocked node guidance across manager APIs and UI [cgm-225, cgm-225.1, cgm-225.2, cgm-225.3, cgm-225.4, cgm-225.5] --- .../src/components/MissingResourcesPopup.vue | 70 ++++++++ frontend/src/components/NodesSection.vue | 74 ++++++++- frontend/src/components/StatusSection.vue | 31 +++- .../src/components/WorkflowResolveModal.vue | 43 +++++ frontend/src/components/WorkflowsSection.vue | 6 + .../__tests__/useWorkflowResolution.test.ts | 59 +++++++ .../src/composables/useComfyGitService.ts | 30 +++- .../src/composables/useWorkflowResolution.ts | 5 + frontend/src/services/mockApi.ts | 8 +- frontend/src/types/comfygit.ts | 31 ++++ server/api/v2/nodes.py | 120 +++++++++++-- server/api/v2/workflows.py | 117 +++++++++++-- server/cgm_core/serializers.py | 6 + testing/helpers/mock_helpers.py | 9 + .../integration/panel/test_node_endpoints.py | 53 ++++++ .../panel/test_workflow_endpoints.py | 157 ++++++++++++++++++ testing/unit/test_serializers.py | 12 ++ 17 files changed, 799 insertions(+), 32 deletions(-) diff --git a/frontend/src/components/MissingResourcesPopup.vue b/frontend/src/components/MissingResourcesPopup.vue index c8724ee..d3f7f87 100644 --- a/frontend/src/components/MissingResourcesPopup.vue +++ b/frontend/src/components/MissingResourcesPopup.vue @@ -87,6 +87,38 @@ + +
+
+ Requires Newer ComfyUI ({{ versionGatedNodes.length }}) +
+
+
+ {{ node.node_type }} + {{ node.guidance || 'Requires a newer ComfyUI version' }} +
+
+ ...and {{ versionGatedNodes.length - 5 }} more +
+
+
+ + +
+
+ No Installable Package Version ({{ uninstallableNodes.length }}) +
+
+
+ {{ node.node_type }} + {{ node.guidance || 'No compatible package version is available for this environment' }} +
+
+ ...and {{ uninstallableNodes.length - 5 }} more +
+
+
+
@@ -199,6 +231,17 @@ interface UnresolvedNode { node_type: string } +interface VersionGatedNodeItem { + node_type: string + guidance: string | null +} + +interface UninstallableNodeItem { + node_type: string + package_id: string | null + guidance: string | null +} + const loading = ref(false) const error = ref(null) const analysis = ref(null) @@ -225,6 +268,8 @@ const { queueNodeInstall } = useComfyGitService() const hasIssues = computed(() => { return missingPackages.value.length > 0 || unresolvedNodes.value.length > 0 || + versionGatedNodes.value.length > 0 || + uninstallableNodes.value.length > 0 || missingModels.value.length > 0 }) @@ -270,6 +315,31 @@ const unresolvedNodes = computed(() => { })) }) +const versionGatedNodes = computed(() => { + if (!analysis.value?.nodes) return [] + const guidance = analysis.value.node_guidance || {} + return (analysis.value.nodes.version_gated || []).map((n: any) => { + const nodeType = n.reference?.node_type || n.node_type + return { + node_type: nodeType, + guidance: n.guidance || guidance[nodeType] || null, + } + }) +}) + +const uninstallableNodes = computed(() => { + if (!analysis.value?.nodes) return [] + const guidance = analysis.value.node_guidance || {} + return (analysis.value.nodes.uninstallable || []).map((n: any) => { + const nodeType = n.reference?.node_type || n.node_type + return { + node_type: nodeType, + package_id: n.package?.package_id || null, + guidance: n.guidance || guidance[nodeType] || null, + } + }) +}) + // Missing models with download info const missingModels = computed(() => { if (!analysis.value?.models) return [] diff --git a/frontend/src/components/NodesSection.vue b/frontend/src/components/NodesSection.vue index 42e15bc..bbbb723 100644 --- a/frontend/src/components/NodesSection.vue +++ b/frontend/src/components/NodesSection.vue @@ -37,6 +37,7 @@ {{ nodesData.installed_count }} installed + @@ -78,6 +79,46 @@ + + + + + + + + + + + @@ -242,6 +283,7 @@

Installed: Tracked nodes available in this environment
Missing: Tracked nodes that need to be installed
+ Blocked: Node types that cannot be resolved in the current environment
Untracked: Nodes on filesystem but not in manifest

@@ -315,7 +357,8 @@ const nodesData = ref({ total_count: 0, installed_count: 0, missing_count: 0, - untracked_count: 0 + untracked_count: 0, + blocked_count: 0 }) const loading = ref(false) @@ -353,7 +396,7 @@ const filteredInstalled = computed(() => // Missing: tracked but NOT on filesystem const filteredMissing = computed(() => - filteredNodes.value.filter(n => !n.installed && n.tracked) + filteredNodes.value.filter(n => !n.installed && n.tracked && !n.issue_type) ) // Untracked: on filesystem but NOT tracked @@ -361,6 +404,11 @@ const filteredUntracked = computed(() => filteredNodes.value.filter(n => n.installed && !n.tracked) ) +// Blocked: version-gated or uninstallable node types +const filteredBlocked = computed(() => + filteredNodes.value.filter(n => n.issue_type === 'version_gated' || n.issue_type === 'uninstallable') +) + // Helper functions function getSourceLabel(source: string): string { const labels: Record = { @@ -389,6 +437,26 @@ function getUsageLabel(node: NodeInfo): string { return `${node.used_in_workflows.length} workflows` } +function getBlockedSubtitle(node: NodeInfo): string { + if (node.issue_type === 'version_gated') { + return 'Requires newer ComfyUI version' + } + if (node.issue_type === 'uninstallable') { + return 'No installable package version' + } + return 'Blocked' +} + +function getBlockedGuidance(node: NodeInfo): string { + if (node.issue_type === 'version_gated') { + return 'Upgrade ComfyUI to a version that includes this builtin node.' + } + if (node.issue_type === 'uninstallable') { + return 'Select a different node package or update environment constraints.' + } + return 'Manual intervention required.' +} + function showDetails(node: NodeInfo) { selectedNode.value = node } diff --git a/frontend/src/components/StatusSection.vue b/frontend/src/components/StatusSection.vue index 932b8e1..e07a016 100644 --- a/frontend/src/components/StatusSection.vue +++ b/frontend/src/components/StatusSection.vue @@ -184,7 +184,7 @@ severity="error" icon="⚠" :title="`${allBrokenWorkflows.length} workflow${allBrokenWorkflows.length === 1 ? '' : 's'} can't run`" - description="These workflows have missing dependencies that must be resolved before they can run." + :description="brokenWorkflowDescription" :items="allBrokenWorkflows.map(w => `${w.name} — ${w.issue_summary}`)" >