Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
# Local ComfyUI checkout used by maintenance scripts (e.g. API node model scanner).
# Scripts append /comfy_api_nodes automatically — point this at the ComfyUI repo root.
# Local ComfyUI checkout used by maintenance scripts (e.g. API node model scanner,
# static node-compat scan). For live local checks, start ComfyUI and run
# npm run validate:comfyui-nodes (uses http://127.0.0.1:8188/object_info).
COMFYUI_REPO_PATH=/path/to/ComfyUI

# Optional override for live local /object_info checks:
# COMFYUI_OBJECT_INFO_URL=http://127.0.0.1:8188/object_info

# =============================================================================
# MCP AI enhancement (Step 2: enhance_models_registry.py, enhance_descriptions.py)
# =============================================================================
Expand Down
30 changes: 30 additions & 0 deletions .github/workflows/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,33 @@ Validates template JSON structure, thumbnails, and checks for third-party nodes.
### 4. Publish (`publish.yml`)

Publishes approved templates to the registry.

### 5. ComfyUI Node Compatibility Report (`report-comfyui-node-compat.yml`)

Informational check — **never blocks PR merges**. Compares changed `templates/*.json` against ComfyUI `master` via static source scan (no torch, no running server).

**What it checks (static mode):**
- Deprecated nodes (display name contains `DEPRECATED`)

**When it runs:**
- On pull requests that change files under `templates/` only
- Manual dispatch

**How it works:**
1. Sparse-checkout template JSON + compat scripts only
2. Shallow-clone `Comfy-Org/ComfyUI` and run `scripts/comfyui_node_compat/check.py --static-scan --clone-comfyui`
3. Post or update a single PR comment with the Markdown report
4. Upload `compat_report.md` / `.json` as a workflow artifact

**Local testing (full coverage — needs running ComfyUI):**
```bash
npm run validate:comfyui-nodes
# Reports: comfyui-node-compat.latest.log, comfyui-node-compat.log (gitignored)
```

**Local testing (CI-style static scan):**
```bash
python3 scripts/comfyui_node_compat/check.py --static-scan --clone-comfyui --no-fail
```
Comment on lines +75 to +84

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Surround fenced code blocks with blank lines (MD031).

markdownlint flags the fences at Lines 76 and 82 — a blank line above each keeps the renderer (and the linter) from fencing with you.

📝 Add blank lines around fences
 **Local testing (full coverage — needs running ComfyUI):**
+
 ```bash
 npm run validate:comfyui-nodes
 # Reports: comfyui-node-compat.latest.log, comfyui-node-compat.log (gitignored)

Local testing (CI-style static scan):
+

python3 scripts/comfyui_node_compat/check.py --static-scan --clone-comfyui --no-fail
</details>

<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

```suggestion
**Local testing (full coverage — needs running ComfyUI):**

🧰 Tools
🪛 markdownlint-cli2 (0.22.1)

[warning] 76-76: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 82-82: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/README.md around lines 75 - 84, The markdown in this
README section violates MD031 because the fenced code blocks are not separated
by blank lines. Update the surrounding content near the local testing examples
so each fence in the README has an empty line before and after it, keeping the
text and the two code blocks clearly separated.

Source: Linters/SAST tools


See [`scripts/README.md`](../scripts/README.md#comfyui-node-compatibility-check) for issue types, log tiers, and flags.
145 changes: 145 additions & 0 deletions .github/workflows/report-comfyui-node-compat.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
name: ComfyUI Node Compatibility Report

# Informational report only — never blocks PR merges.
# Statically scans ComfyUI master source + templates/*.json (no torch, no running server).

on:
pull_request:
types: [opened, synchronize]
paths:
- 'templates/**'
workflow_dispatch:
Comment on lines +6 to +11

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

Add a concurrency group to cancel superseded runs.

Rapid synchronize pushes can launch overlapping runs that race on the same PR comment (duplicate posts, stale content). A per-PR concurrency group keeps things orderly — first come, last served.

🔒 Suggested concurrency block
 on:
   pull_request:
     types: [opened, synchronize]
     paths:
       - 'templates/**'
   workflow_dispatch:
+
+concurrency:
+  group: comfyui-node-compat-${{ github.event.pull_request.number || github.ref }}
+  cancel-in-progress: true
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
on:
pull_request:
types: [opened, synchronize]
paths:
- 'templates/**'
workflow_dispatch:
on:
pull_request:
types: [opened, synchronize]
paths:
- 'templates/**'
workflow_dispatch:
concurrency:
group: comfyui-node-compat-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
🧰 Tools
🪛 zizmor (1.26.1)

[warning] 6-11: insufficient job-level concurrency limits (concurrency-limits): workflow is missing concurrency setting

(concurrency-limits)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/report-comfyui-node-compat.yml around lines 6 - 11, The
workflow trigger currently allows overlapping runs on the same pull request,
which can cause duplicate or stale comment updates. Add a per-PR concurrency
configuration to the report-comfyui-node-compat workflow so only the latest run
for a given PR stays active and earlier ones are canceled. Use the workflow’s
existing pull_request context with a stable group key and enable
cancel-in-progress to keep runs orderly.

Source: Linters/SAST tools


permissions:
contents: read
pull-requests: write
Comment on lines +6 to +15

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major

🧩 Analysis chain

🌐 Web query:

Does GitHub downgrade GITHUB_TOKEN to read-only for pull_request workflows triggered from forks even when pull-requests write permission is set?

💡 Result:

Yes, GitHub intentionally downgrades the GITHUB_TOKEN to read-only for workflows triggered by pull request events from forked repositories [1][2][3]. Even if you explicitly define write permissions in your workflow configuration (using the permissions key) or set repository-level default permissions to read/write, GitHub enforces this read-only restriction for security reasons to prevent malicious code in a fork from potentially compromising the base repository [1][3][4][5]. There is a specific repository-level setting called "Send write tokens to workflows from pull requests" that, when enabled, allows pull requests from forks to receive a GITHUB_TOKEN with write permissions [6][7]. However, this is disabled by default for security and must be explicitly enabled by a repository administrator [6][7]. For workflows that require write access (e.g., to post comments on a PR), a common architectural pattern is to use a two-stage workflow [4]: 1. A first, untrusted workflow (triggered by pull_request) runs on the fork's code with read-only permissions and saves necessary information as workflow artifacts [4]. 2. A second, trusted workflow (triggered by workflow_run) runs on the base repository's context, has access to write permissions, and consumes the artifacts produced by the first workflow to perform the desired actions (like posting a comment) [4]. Alternatively, the pull_request_target event can be used to run workflows in the context of the base repository, which does not receive this automatic read-only downgrade, but this approach carries significant security risks if not handled carefully, as it executes code from the pull request using the base repository's permissions [3][8][5].

Citations:


Fork PRs can't post comments with a pull_request trigger—don't let the token go rogue!

For pull requests originating from forks, GitHub strictly downgrades the GITHUB_TOKEN to read-only, even if you explicitly grant pull-requests: write in your workflow. The repository's guardian goblins enforce this to prevent malicious code from slipping through the cracks. Attempting to comment will cause your job to stumble and turn red for external contributors.

Since this repo welcomes fork contributions, you should verify the intended behavior. The usual safe spell is a workflow_run-based commenter pattern to avoid token traps and keep the deed done without the dread.

🧰 Tools
🪛 zizmor (1.26.1)

[error] 15-15: overly broad permissions (excessive-permissions): pull-requests: write is overly broad at the workflow level

(excessive-permissions)


[warning] 15-15: permissions without explanatory comments (undocumented-permissions): needs an explanatory comment

(undocumented-permissions)


[warning] 6-11: insufficient job-level concurrency limits (concurrency-limits): workflow is missing concurrency setting

(concurrency-limits)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/report-comfyui-node-compat.yml around lines 6 - 15, Forked
pull requests cannot safely use a write-enabled GITHUB_TOKEN with the current
pull_request-based commenter workflow, so update the comment-posting flow in the
report-comfyui-node-compat workflow to avoid token downgrade failures. Refactor
the workflow trigger/setup to use a safer pattern for external contributions,
such as a workflow_run-driven comment step, and ensure the job that posts
comments no longer relies on pull_request permissions that will be read-only for
fork PRs.


env:
COMFYUI_GITHUB_REPO: Comfy-Org/ComfyUI
COMFYUI_REF: master

jobs:
report:
runs-on: ubuntu-latest
steps:
- name: Checkout workflow templates (JSON only)
uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha || github.sha }}
sparse-checkout: |
templates/*.json
scripts/comfyui_node_compat/
scripts/lib/paths.py
scripts/lib/locale_index_files.py
sparse-checkout-cone-mode: false

- name: Set up Python
uses: actions/setup-python@v5
Comment on lines +25 to +37

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🔵 Trivial | 💤 Low value

Optional hardening per static analysis (zizmor).

A few low-risk posture nits worth a once-over: set persist-credentials: false on the checkout (credentials aren't needed downstream), and consider scoping pull-requests: write to the report job rather than the whole workflow. Pinning actions to commit SHAs is also flagged — confirm whether this repo's other workflows follow that blanket policy before churning here.

🛡️ persist-credentials
       - name: Checkout workflow templates (JSON only)
         uses: actions/checkout@v4
         with:
           ref: ${{ github.event.pull_request.head.sha || github.sha }}
+          persist-credentials: false
           sparse-checkout: |
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- name: Checkout workflow templates (JSON only)
uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha || github.sha }}
sparse-checkout: |
templates/*.json
scripts/comfyui_node_compat/
scripts/lib/paths.py
scripts/lib/locale_index_files.py
sparse-checkout-cone-mode: false
- name: Set up Python
uses: actions/setup-python@v5
- name: Checkout workflow templates (JSON only)
uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha || github.sha }}
persist-credentials: false
sparse-checkout: |
templates/*.json
scripts/comfyui_node_compat/
scripts/lib/paths.py
scripts/lib/locale_index_files.py
sparse-checkout-cone-mode: false
- name: Set up Python
uses: actions/setup-python@v5
🧰 Tools
🪛 zizmor (1.26.1)

[warning] 25-34: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false

(artipacked)


[error] 26-26: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)

(unpinned-uses)


[error] 37-37: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)

(unpinned-uses)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/report-comfyui-node-compat.yml around lines 25 - 37, The
workflow checkout in the report job should be hardened by disabling persisted
GitHub credentials and, if possible, limiting the pull-requests permission to
only the report job instead of the entire workflow. Update the actions/checkout
step in the workflow’s checkout setup to set persist-credentials to false, and
adjust the workflow-level permissions so the job that posts the report owns
pull-requests: write. Also verify whether the repo policy requires pinning
actions in this workflow before making any broader changes.

Source: Linters/SAST tools

with:
python-version: '3.11'

- name: Run static ComfyUI node compatibility check
id: compat_check
continue-on-error: true
run: |
python3 scripts/comfyui_node_compat/check.py \
--static-scan \
--clone-comfyui \
--templates-dir templates \
--markdown-output compat_report.md \
--json-output compat_report.json \
--no-log-file \
--no-fail | tee compat_check.log

- name: Write workflow failure report
if: steps.compat_check.outcome != 'success'
run: |
cat > compat_report.md <<EOF
## ComfyUI Node Compatibility Report

**Status: check could not complete** — no template compatibility results were produced.

_Informational only — this check does not block merging._

### Setup failure
- Static compatibility script exited with an error (see workflow logs).
- Expected mode: \`--static-scan --clone-comfyui\` against \`${COMFYUI_GITHUB_REPO}\` (\`${COMFYUI_REF}\`).

### Next steps
- Open the workflow run logs for details.
- Re-run locally after starting ComfyUI: \`npm run validate:comfyui-nodes\`
- Or run CI-style static scan locally:
\`python3 scripts/comfyui_node_compat/check.py --static-scan --clone-comfyui\`
EOF

- name: Comment compatibility report on PR
if: always() && github.event_name == 'pull_request'
uses: actions/github-script@v7
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const fs = require('fs');

const readFile = (path) => {
try {
return fs.readFileSync(path, 'utf8');
} catch {
return '';
}
};

let report = readFile('compat_report.md').trim();
if (!report) {
report = [
'## ComfyUI Node Compatibility Report',
'',
'**Status: no report generated.**',
'',
'_Informational only — this check does not block merging._',
'',
readFile('compat_check.log').trim() || 'See workflow logs for details.',
].join('\n');
}

const marker = '<!-- comfyui-node-compat-report -->';
const maxLength = 60000;
if (report.length > maxLength) {
report = report.slice(0, maxLength) + '\n\n...(Report truncated due to length. Download the workflow artifact for the full report.)';
}

const body = `${marker}\n${report}\n\n---\n*This comment is automatically updated by the ComfyUI Node Compatibility Report workflow.*`;

const { data: comments } = await github.rest.issues.listComments({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
});

const existing = comments.find((comment) => comment.body.includes(marker));
Comment on lines +112 to +118

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Paginate listComments or the single-comment update will multiply on busy PRs.

listComments defaults to 30 results per page, so on a PR with many comments the existing <!-- comfyui-node-compat-report --> marker may sit on a later page and never be found — meaning a fresh comment is created on every run. To keep it a solo act rather than a chorus, paginate.

♻️ Use the paginator
-            const { data: comments } = await github.rest.issues.listComments({
-              owner: context.repo.owner,
-              repo: context.repo.repo,
-              issue_number: context.issue.number,
-            });
+            const comments = await github.paginate(github.rest.issues.listComments, {
+              owner: context.repo.owner,
+              repo: context.repo.repo,
+              issue_number: context.issue.number,
+              per_page: 100,
+            });
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const { data: comments } = await github.rest.issues.listComments({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
});
const existing = comments.find((comment) => comment.body.includes(marker));
const comments = await github.paginate(github.rest.issues.listComments, {
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
per_page: 100,
});
const existing = comments.find((comment) => comment.body.includes(marker));
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/report-comfyui-node-compat.yml around lines 112 - 118, The
comment lookup in the GitHub Action only checks the first page of results, so
`existing` can miss the `<!-- comfyui-node-compat-report -->` marker on busy PRs
and create duplicates. Update the `listComments` call to use pagination (for
example via `github.paginate` or repeated page fetching) before running the
`comments.find(...)` check. Keep the existing marker-based match logic in the
workflow step so the update path still finds the prior report comment.

if (existing) {
await github.rest.issues.updateComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: existing.id,
body,
});
} else {
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body,
});
}

- name: Upload compatibility report artifact
if: always()
uses: actions/upload-artifact@v4
with:
name: comfyui-node-compat-report
path: |
compat_report.md
compat_report.json
compat_check.log
if-no-files-found: ignore
retention-days: 14
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,10 @@ LINK_CHECKER_REPORT.md
asset_validation_report.md
model_analysis_report.md

# ComfyUI node compatibility check logs (npm run validate:comfyui-nodes)
comfyui-node-compat.log
comfyui-node-compat.latest.log

# Python cache
*.pyc
*.pyo
Expand Down
3 changes: 3 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,10 @@
- `npm run mcp:models` — AI model profiles in `models_registry.json`
- `npm run validate:templates` — Validate template JSON files
- `npm run validate:manifests` — Validate package manifests
- `npm run validate:comfyui-nodes` — Compare templates to ComfyUI node baseline (local: live `/object_info`)
- `python scripts/sync/sync_bundles.py` — Same as `npm run sync:bundles`
- `python scripts/validate/validate_templates.py` — Same as `npm run validate:templates`
- `python scripts/comfyui_node_compat/check.py --static-scan --clone-comfyui --no-fail` — CI-style static compat scan

**MCP index pipeline:** see skill `.claude/skills/managing-mcp-index/SKILL.md` and `scripts/mcp/docs/MCP_AI_ENHANCEMENT.md`. Do not confuse with hub i18n (`i18n`) or site AI (`site/scripts/generate-ai.ts`).

Expand All @@ -33,6 +35,7 @@ Root `scripts/` is organized by role:
| `scripts/sync/` | Sync / generate data | `sync_data.py`, `sync_bundles.py` |
| `scripts/mcp/` | MCP index pipeline | `sync_index.py`, `enhance_descriptions.py` |
| `scripts/validate/` | Validation & analysis (CI) | `validate_templates.py`, `check_links.py`, `analyze_models.py` |
| `scripts/comfyui_node_compat/` | ComfyUI node baseline vs templates | `check.py` |
| `scripts/blueprints/` | Blueprint-specific import | `import_blueprints.py` |
| `scripts/ci/` | Release pipeline only | `ci_version_manager.py`, `check_pypi_quota.py` |
| `scripts/data/` | Static config JSON | `i18n.json`, `whitelist.json`, `mcp/models_registry.json`, `mcp/template_cache.json` |
Expand Down
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ PR opened/updated
| Add a workflow template | Edit `templates/`, `bundles.json`, then `python scripts/sync/sync_bundles.py` |
| Add a subgraph blueprint | Edit `blueprints/`, `blueprints_bundles.json`, then `python scripts/sync/sync_blueprints.py` |
| Import external blueprints | Copy JSONs to `blueprints/`, then `python scripts/blueprints/import_blueprints.py` |
| Check node compatibility | `npm run validate:comfyui-nodes` (local ComfyUI) or see [`scripts/README.md`](scripts/README.md#comfyui-node-compatibility-check) |

---

Expand Down Expand Up @@ -580,9 +581,13 @@ CI automatically validates:
| Bundle consistency | ✅ | ✅ |
| Manifest sync | ✅ | ✅ |
| Thumbnails | ✅ | ❌ (optional) |
| ComfyUI node compatibility | ✅ (informational PR comment) | ❌ |

Run locally before committing:
```bash
python scripts/sync/sync_bundles.py # Templates
python scripts/sync/sync_blueprints.py # Blueprints
npm run validate:comfyui-nodes # Optional: node baseline vs templates (needs running ComfyUI)
```
Comment on lines 586 to 591

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Add a blank line before the fenced block (MD031).

markdownlint flags the fence at Line 587 — let it breathe with a blank line above.

📝 Blank line before fence
 Run locally before committing:
+
 ```bash
 python scripts/sync/sync_bundles.py      # Templates
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
Run locally before committing:
```bash
python scripts/sync/sync_bundles.py # Templates
python scripts/sync/sync_blueprints.py # Blueprints
npm run validate:comfyui-nodes # Optional: node baseline vs templates (needs running ComfyUI)
```
Run locally before committing:
🧰 Tools
🪛 markdownlint-cli2 (0.22.1)

[warning] 587-587: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@README.md` around lines 586 - 591, The Markdown section in README.md needs a
blank line before the fenced code block to satisfy MD031. Update the “Run
locally before committing:” section so the fence in the README sits after an
empty line, keeping the existing commands and surrounding prose intact.

Source: Linters/SAST tools


See [`scripts/README.md`](scripts/README.md#comfyui-node-compatibility-check) for local vs static scan modes and log output.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"mcp:models": "python scripts/mcp/enhance_models_registry.py",
"validate:templates": "python scripts/validate/validate_templates.py",
"validate:manifests": "python scripts/validate/validate_manifests.py",
"validate:comfyui-nodes": "python3 scripts/comfyui_node_compat/check.py",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Interpreter inconsistency: python3 here vs python in sibling scripts.

Lines 17-18 invoke python, while this new entry uses python3. On hosts where only one of the two is on PATH, this split could trip a runner up. Pick one binary to keep the scripts in sync and skip the surprise.

♻️ Optional alignment
-    "validate:comfyui-nodes": "python3 scripts/comfyui_node_compat/check.py",
+    "validate:comfyui-nodes": "python scripts/comfyui_node_compat/check.py",
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"validate:comfyui-nodes": "python3 scripts/comfyui_node_compat/check.py",
"validate:comfyui-nodes": "python scripts/comfyui_node_compat/check.py",
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@package.json` at line 19, The new package script uses a different Python
interpreter than the sibling validation scripts, so align
`validate:comfyui-nodes` with the existing `python`-based entries in
package.json. Update the script in the package.json scripts section to use the
same binary as the other validation commands so all checks invoke a consistent
interpreter.

"build:all": "NX_ADD_PLUGINS=false NX_DAEMON=false npx nx run-many --target build --skip-nx-cache",
"site:install": "cd site && pnpm install",
"site:dev": "cd site && pnpm run dev",
Expand Down
95 changes: 94 additions & 1 deletion scripts/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ Python maintenance scripts for ComfyUI workflow templates (packages, CI, i18n).
| Sync blueprints | `python scripts/sync/sync_blueprints.py` |
| Validate templates | `python scripts/validate/validate_templates.py` |
| Validate manifests | `python scripts/validate/validate_manifests.py` |
| ComfyUI node compatibility | `npm run validate:comfyui-nodes` |
| Maintainer smoke check | `./scripts/maintenance/check_templates.sh` |

## Directory layout
Expand All @@ -20,6 +21,7 @@ Python maintenance scripts for ComfyUI workflow templates (packages, CI, i18n).
| [`sync/`](sync/) | Data synchronization and generation |
| [`mcp/`](mcp/) | MCP index pipeline (`index.mcp.json`) |
| [`validate/`](validate/) | Validation and analysis (most run in CI) |
| [`comfyui_node_compat/`](comfyui_node_compat/) | ComfyUI node baseline vs template workflows (informational) |
| [`blueprints/`](blueprints/) | Subgraph blueprint import |
| [`ci/`](ci/) | Release pipeline helpers (version, PyPI quota) |
| [`maintenance/`](maintenance/) | Local-only tools (archive, one-off fixes) |
Expand Down Expand Up @@ -51,6 +53,7 @@ Also runs workflow I/O extraction via `generate_workflow_io.py` before locale sy
| `validate-blueprints.yml` | `validate/validate_blueprints.py`, `blueprints/import_blueprints.py`, `sync/sync_blueprints.py` |
| `link-checker.yml` | `validate/check_links.py`, `data/whitelist.json` |
| `model-analysis.yml` | `validate/analyze_models.py`, `data/whitelist.json` |
| `report-comfyui-node-compat.yml` | `comfyui_node_compat/check.py` (static scan; PR comment only) |
| `check_input_assets.yml`, `generate-upload-json.yml` | `validate/check_input_assets.py` |
| `sync-custom-nodes.yml` | `sync/sync_custom_nodes.py` |
| `version-check.yml`, `publish.yml` | `ci/ci_version_manager.py`, `sync/sync_bundles.py`, `ci/*` |
Expand Down Expand Up @@ -84,4 +87,94 @@ npm run mcp:models # AI model registry
- **`data/mcp/template_cache.json`** — Per-template AI copy, versioned by workflow JSON hash.
- **`data/krea_registry_aliases.json`**, **`data/krea_*_models.json`** — Temporary Krea snapshots for one-off registry seeding (delete when seeding is complete).

Generated output goes to `scripts/.output/` (gitignored) or repo root (`model_analysis_report.md`, `asset_validation_report.md`).
Generated output goes to `scripts/.output/` (gitignored) or repo root (`model_analysis_report.md`, `asset_validation_report.md`, `comfyui-node-compat.log`, `comfyui-node-compat.latest.log`).

## ComfyUI node compatibility check

Compares `templates/*.json` workflows against a ComfyUI node baseline. **Informational only** — does not block PR merges. On PRs that change `templates/`, [`report-comfyui-node-compat.yml`](../.github/workflows/report-comfyui-node-compat.yml) posts/updates a comment with findings.

### Local (recommended for full coverage)

Requires a running ComfyUI instance. Reads live `/object_info` (full combo lists, API nodes, inputs):

```bash
npm run validate:comfyui-nodes
# same as:
python3 scripts/comfyui_node_compat/check.py
```

If ComfyUI is not reachable, the script exits with a hint to start the server or use `--static-scan`.

Reports are written to repo root (gitignored):

- `comfyui-node-compat.latest.log` — latest run (overwrite)
- `comfyui-node-compat.log` — append-only history

### CI / static scan (no server, no torch)

Clones `Comfy-Org/ComfyUI` and AST-scans Python sources. Faster and dependency-free, but only reports **deprecated nodes** (skips missing-node / combo noise from incomplete static parsing):

```bash
python3 scripts/comfyui_node_compat/check.py --static-scan --clone-comfyui --no-fail
```

Use an existing checkout instead of cloning:

```bash
export COMFYUI_REPO_PATH=/path/to/ComfyUI
python3 scripts/comfyui_node_compat/check.py --static-scan --no-fail
```

### What it detects

| Issue kind | Severity | Local | Static |
|------------|----------|-------|--------|
| `invalid_api_model` | error | ✅ | — |
| `widget_slot_mismatch` | error | ✅ (API nodes) | — |
| `invalid_widget_value` | error | ✅ (API nodes) | — |
| `missing_node` | error | ✅ | — |
| `invalid_combo_value` | error | ✅ | — |
| `missing_input` | error | ✅ | — |
| `deprecated_node` | warning | ✅ | ✅ |

Runtime checks map save-format `widgets_values[]` to field names via `/object_info` `input_order` (skipping linked sockets and non-widget types like IMAGE/AUDIO, while preserving linked rows that are still widget-backed). Filesystem-backed dropdowns such as model, upload, and 3D asset pickers are treated as local-install dependent. This catches API workflows whose widget slots drifted after a node schema change (e.g. a new `resolution` field inserted mid-list) without turning every local missing model into a template error.

Log and PR reports group findings by priority:

1. **Critical** — workflow will likely fail or run with wrong inputs (`invalid_api_model`, `widget_slot_mismatch`)
2. **Errors** — removed nodes, invalid inputs, stale combo values
3. **Warnings** — deprecated nodes and other review items

### Useful flags

| Flag | Purpose |
|------|---------|
| `--static-scan` | Source scan without running ComfyUI |
| `--clone-comfyui` | Shallow-clone ComfyUI master for static scan |
| `--comfyui-dir PATH` | ComfyUI checkout for static scan |
| `--object-info-url URL` | Override live endpoint (default `http://127.0.0.1:8188/object_info`) |
| `--object-info-json PATH` | Debug with a saved `/object_info` JSON |
| `--strict-unknown` | Warn on unknown non-core custom nodes |
| `--no-log-file` | Skip writing log files (CI default) |
| `--no-fail` | Exit 0 even when errors are found |
| `--markdown-output PATH` | Write Markdown report (PR comments) |
| `--json-output PATH` | Write machine-readable JSON report |

### Environment variables

- `COMFYUI_REPO_PATH` — local ComfyUI checkout for `--static-scan`
- `COMFYUI_OBJECT_INFO_URL` — override live `/object_info` URL

See [`.env.example`](../.env.example).

### Layout

| File | Role |
|------|------|
| `comfyui_node_compat/check.py` | CLI entry point |
| `comfyui_node_compat/models.py` | Issue types, priority tiers |
| `comfyui_node_compat/registry.py` | Parse live `/object_info` |
| `comfyui_node_compat/static_registry.py` | AST scan of ComfyUI `.py` sources |
| `comfyui_node_compat/workflow.py` | Scan template JSON + subgraphs |
| `comfyui_node_compat/report.py` | Log/Markdown formatting |
| `comfyui_node_compat/clone.py` | Clone/resolve ComfyUI checkout |
1 change: 1 addition & 0 deletions scripts/comfyui_node_compat/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"""ComfyUI workflow template node compatibility checks."""
Loading
Loading