## Summary
Stop running the full Vitest suite twice in unit CI. The critical
coverage gate is now a glob-keyed `coverage.thresholds` entry enforced
during the single `pnpm test:coverage` run, instead of a second
`COVERAGE_CRITICAL=true vitest run --coverage` pass.
## Changes
- **What**: All critical directories form one brace-expanded glob key in
`coverage.thresholds`; Vitest aggregates the matching files into a
single bucket and checks the existing thresholds (69/60/67/70) against
it during the normal coverage run. Untested files matching
`coverage.include` are counted at 0%, preserving the previous gate's
semantics.
- **What**: Narrows the litegraph coverage exclusion from a blanket
`src/lib/litegraph/**` to the non-critical subfolders, so the critical
litegraph folders (`node`, `subgraph`, `utils`) are present in the
coverage report the thresholds read.
- **What**: Removes the `test:coverage:critical` script, the
`COVERAGE_CRITICAL` env branch in `vite.config.mts`, and the separate CI
gate step.
## Notes
- The normal coverage report now includes the critical litegraph
folders, so the Codecov `unit` flag and the coverage Slack baseline will
show a one-time shift.
- Filtered local runs (`pnpm test:coverage <file>`) fail the gate since
most critical files are uncovered; a full `pnpm test:coverage`
reproduces CI exactly.
Validation:
- `pnpm typecheck`, `pnpm exec eslint vite.config.mts`, `pnpm
format:check`, `pnpm knip` (pre-push)
- Smoke: `pnpm vitest run --coverage src/utils/colorUtil.test.ts` —
tests pass, then the gate fails all four metrics against the critical
bucket and exits 1, confirming enforcement happens inside the single run
- Full-suite gate numbers should be confirmed in CI
## Summary
Add a `COVERAGE_CRITICAL` unit-coverage gate over folder-based critical
runtime areas and wire it into the unit CI job. First PR of a stacked
series that ratchets the gate upward as tests land.
## Changes
- **What**: `vite.config.mts` gains `CRITICAL_COVERAGE_INCLUDE` folder
globs for core runtime areas: `src/base`, `src/composables`, `src/core`,
`src/schemas`, `src/scripts`, `src/services`, `src/stores`, `src/utils`,
selected `src/platform` logic slices, selected
`src/lib/litegraph/src/{node,subgraph,utils}` primitives, and selected
`src/workbench` manager logic; `package.json` gains
`test:coverage:critical` (`COVERAGE_CRITICAL=true vitest run
--coverage`); `ci-tests-unit.yaml` runs the gate. The thresholds are
env-gated, so the normal `test:coverage` run is unaffected.
- **Breaking**: none.
## Review Focus
Establishes the measurement substrate, no tests added yet. Thresholds
are locked to the current baseline over the folder-based critical scope
so CI is green:
| metric | baseline | threshold |
|---|---|---|
| statements | 69.53% (24287/34930) | 69 |
| branches | 60.7% (11497/18940) | 60 |
| functions | 67.34% (4980/7395) | 67 |
| lines | 70.83% (22619/31930) | 70 |
The scope is intentionally not whole `src/platform`, `src/lib`, or
`src/workbench`: UI-heavy and specialized lanes like platform
components, telemetry/surveys, litegraph
canvas/widgets/infrastructure/types, and manager components/types stay
outside this gate for now.
Subsequent stacked PRs add tests and bump these thresholds; a later
refactor series ratchets branches to 90.
Created by Codex
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> **Low Risk**
> Changes are limited to test/coverage configuration and CI; no
application runtime behavior is modified.
>
> **Overview**
> Introduces a **critical-path unit coverage gate** that only runs when
`COVERAGE_CRITICAL=true`, leaving the existing `pnpm test:coverage`
behavior unchanged.
>
> **Vitest** (`vite.config.mts`): when the flag is set, coverage is
limited to folder globs for core runtime areas (base, composables, core,
services, stores, utils, selected platform/workspace/auth slices,
litegraph node/subgraph/utils, workbench manager logic, etc.) and
**Vitest thresholds** are enforced (statements 69%, branches 60%,
functions 67%, lines 70%). In that mode, litegraph is no longer
blanket-excluded from coverage the way the full `src` run still excludes
`src/lib/litegraph/**`.
>
> **Tooling & CI**: adds `test:coverage:critical` in `package.json` and
a new unit CI step after Codecov upload that runs the gate so
regressions in those areas fail the job.
>
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
25e73f3844. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
---------
Co-authored-by: huang47 <157390+huang47@users.noreply.github.com>
## Summary
Allows engineers to run their localhost frontend while choosing which
backend to point. This PR adds staging and prod as targets.
## Changes
- **What**: New NPM scripts: `dev:cloud:test`, `dev:cloud:staging`, and
`dev:cloud:prod`. `dev:cloud` points at `dev:cloud:test`
- **Breaking**: None
## Why
Currently, the testcloud environment is broken (backend config issue)
and doesn't allow going through the subscription registration process.
This also allows testing frontend code against backend changes being
staged for release, as well as against actual backend production code.
## Summary
Adds `@comfyorg/comfyui-desktop-bridge-types` as a workspace package in
the frontend monorepo and changes the frontend app dependency to
`workspace:*`.
Adds a dedicated `Publish Desktop Bridge Types` workflow for publishing
`packages/comfyui-desktop-bridge-types` by its own package version,
without coupling it to the generated `@comfyorg/comfyui-frontend-types`
release. The generated frontend types package still emits a concrete
`@comfyorg/comfyui-desktop-bridge-types@0.1.2` dependency instead of
leaking workspace/catalog protocol references.
The Desktop2 missing-model path uses `window.__comfyDesktop2.isRemote()`
when available, but falls back to the legacy
`window.__comfyDesktop2Remote` marker so frontend rollout stays
compatible with older Desktop builds.
Paired Desktop PR: https://github.com/Comfy-Org/Comfy-Desktop/pull/1112
## Summary
Update the default workflow to use a more modern model than SD1.5. This
new workflow uses Z-Image Turbo and is the same workflow as the one in
the README for consistency.
## Changes
- **What**: `src/scripts/defaultGraph.ts`
## Screenshots (if applicable)
<img width="1920" height="1152"
alt="{2DD28B9F-A9E7-4DD7-8F07-AF7241F5702E}"
src="https://github.com/user-attachments/assets/6e6ee298-a786-4a8c-adf3-6452df08a995"
/>
---------
Co-authored-by: Connor Byrne <c.byrne@comfy.org>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
## Summary
Centralize pnpm-run Node options so Node 25 does not shadow happy-dom
storage and build scripts keep the existing heap limit.
## Changes
- **What**: Adds workspace-level `nodeOptions` that preserve
caller-provided `NODE_OPTIONS`, disable Node's native Web Storage, and
set `--max-old-space-size=8192`.
- **What**: Removes duplicate script-local heap `NODE_OPTIONS` from
build scripts now covered by pnpm.
- **Dependencies**: None.
## Review Focus
Check whether applying these Node options to all pnpm-run Node
subprocesses is acceptable versus keeping flags script-local.
## Screenshots (if applicable)
Not applicable.
## Summary
Bump required Node.js to `>=25` and pnpm to `>=11.3`.
## Changes
- **What**: Updated `engines.node` to `>=25`, `engines.pnpm` to
`>=11.3`, and `packageManager` to `pnpm@11.3.0` in `package.json`.
Bumped `.nvmrc` from `24` to `25`.
- **Breaking**: Contributors and CI must now use Node 25+ and pnpm
11.3+.
## Review Focus
CI workflows resolve Node from `.nvmrc`, so they pick up the bump
automatically. Confirm no downstream tooling pins an older Node/pnpm.
---------
Co-authored-by: Amp <amp@ampcode.com>
## Summary
- Spark 2.x requires SparkRenderer in scene tree; add it in SceneManager
and protect it in clearModel so model reloads don't dispose the splat
renderer.
- three 0.184 OrbitControls listens on ownerDocument; drop redundant
pointermove/up .stop in Load3D containers so the document listener can
receive events.
- Narrow Texture.image type for 0.184 strict typing.
## Summary
Migrate pnpm configuration to the v11 layout and clean up stale v10-era
references.
## Changes
- **What**: Moves pnpm settings into `pnpm-workspace.yaml`, converts
build dependency policy to `allowBuilds`, removes stale workspace
`packageManager` pins, and updates global install commands in CI.
- **Dependencies**: No new dependencies.
## Review Focus
- Confirm pnpm v11 workspace settings match the former `.npmrc`
behavior.
- Confirm CI global install syntax is compatible with pnpm v11.
## Test Plan
- `pnpm install --frozen-lockfile`
- `pnpm exec oxfmt --check pnpm-workspace.yaml
packages/shared-frontend-utils/package.json
packages/registry-types/package.json packages/ingest-types/package.json
packages/design-system/package.json
.github/workflows/weekly-docs-check.yaml
.github/workflows/pr-claude-review.yaml`
- commit hook: `pnpm typecheck`
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-12195-build-migrate-pnpm-config-to-v11-35e6d73d36508116a821dbc71db94cd1)
by [Unito](https://www.unito.io)
---------
Co-authored-by: Amp <amp@ampcode.com>
*PR Created by the Glary-Bot Agent*
---
## Summary
Adds a comfy.org page that lists every custom-node pack supported on
Comfy Cloud, with per-pack detail subpages. Data is fetched at build
time from `cloud.comfy.org/api/object_info` (gated by
`WEBSITE_CLOUD_API_KEY`), sanitized of user content, joined with public
registry metadata from `api.comfy.org/nodes`, and falls back to a
committed snapshot — mirroring the existing Ashby careers integration
pattern.
- Index: `/cloud/supported-nodes` (en) and
`/zh-CN/cloud/supported-nodes` (zh-CN)
- Detail: `/cloud/supported-nodes/[pack]` and
`/zh-CN/cloud/supported-nodes/[pack]`, generated via `getStaticPaths()`
from the same fetcher as the index so the two routes can never diverge.
## What's new
**Shared package (extracted)**
- `@comfyorg/object-info-parser` — Zod schemas (`zComfyNodeDef`,
`validateComfyNodeDef`), node-source classifier (`getNodeSource`,
`isCustomNode`, `CORE_NODE_MODULES`), and helpers (`groupNodesByPack`,
`sanitizeUserContent`). `src/schemas/nodeDefSchema.ts` and
`src/types/nodeSource.ts` become 1-line re-export shims; existing
imports keep compiling.
**Build-time pipeline**
- `apps/website/src/utils/cloudNodes.ts` — Ashby-style fetcher:
retry/backoff `[1s, 2s, 4s]`, 10 s timeout via AbortController, Zod
envelope + per-node validation, snapshot fallback, memoized via
module-level `inflight` promise.
- `apps/website/src/utils/cloudNodes.registry.ts` — Public registry
enrichment (no auth, batches of 50, single retry, soft-fail).
- `apps/website/src/utils/cloudNodes.ci.ts` — GitHub Actions annotations
+ step summary mirroring the Ashby reporter.
- `apps/website/src/utils/cloudNodes.build.ts` — Single
`loadPacksForBuild()` consumed by both index and detail pages so they
share one source of truth.
- `apps/website/scripts/refresh-cloud-nodes-snapshot.ts` — atomic-rename
refresh CLI that walks pack/node string fields with a user-content
extension regex *before* renaming the snapshot into place.
- Mandatory user-content sanitization strips uploaded filenames from
combo lists (`LoadImage`, `LoadImageMask`, `LoadImageOutput`,
`LoadVideo`, `LoadAudio` zeroed; any combo value matching
`/\.(png|jpe?g|webp|gif|mp4|mov|webm|wav|mp3|flac|ogg|safetensors|ckpt|pt)$/i`
filtered).
**Page + components**
- `apps/website/src/pages/cloud/supported-nodes.astro` (en) + zh-CN
twin.
- `apps/website/src/pages/cloud/supported-nodes/[pack].astro` detail
(en) + zh-CN twin, async `getStaticPaths` driven by
`loadPacksForBuild()`.
-
`apps/website/src/components/cloud-nodes/{HeroSection,PackGridSection,PackCard,PackBanner,NodeList,PackDetail}.vue`
— Vue 3.5 destructured props, `cn()` from `@comfyorg/tailwind-utils`,
design-system tokens only, no PrimeVue.
- Pack card name links to its detail page; banner uses the shared
`fallback-gradient-avatar.svg` asset (copied into
`apps/website/public/assets/images/`) when `banner_url` and `icon` are
missing.
- 25 new `cloudNodes.*` i18n keys in `en` + `zh-CN`.
**Tests**
- 33 unit tests in `@comfyorg/object-info-parser` (schemas, classifier,
sanitizer, grouping).
- 19 new website unit tests covering fetcher (10), CI reporter (6),
registry enrichment (3) — Ashby patterns mirrored.
- E2E: index smoke + search + banner + detail click-through + direct
visit + zh-CN parity.
## Required maintainer follow-up
GitHub Apps cannot push `.github/workflows/*` changes (push was rejected
with `refusing to allow a GitHub App to create or update workflow …
without workflows permission`), so the workflow edits prepared in this
branch were reverted in commit `9be2abce8`. The intended diffs are
documented as copy-paste-ready snippets in `apps/website/README.md`
under the new "Cloud nodes integration → CI wiring" section.
A maintainer must:
1. Provision `WEBSITE_CLOUD_API_KEY` in the repo secrets and the Vercel
project env.
2. Apply the `ci-website-build.yaml` and
`ci-vercel-website-preview.yaml` diffs documented in the README directly
to `main` (or as a follow-up commit on this branch with a maintainer
account).
The committed snapshot lets builds succeed without the secret while the
maintainer step is pending — pages render from
`apps/website/src/data/cloud-nodes.snapshot.json`.
## Self-review (Oracle)
Two warnings caught and fixed in commits `deba5ab02` and `99dfc3381`:
- Index/detail pages now share a single source of truth
(`loadPacksForBuild`), so a fresh fetch can't expose packs whose detail
routes weren't generated.
- Refresh script validates parsed snapshot fields *before* the atomic
rename, instead of regex-scanning the serialized JSON after the file is
already in place.
## Quality gates (local)
```
pnpm --filter @comfyorg/object-info-parser test → 33 passed
pnpm --filter @comfyorg/website test:unit → 42 passed
pnpm --filter @comfyorg/website typecheck → 0 errors
pnpm --filter @comfyorg/website build → 47 pages built (incl. 6 cloud-nodes routes)
pnpm lint → 0 errors (1 pre-existing warning in unrelated test file)
pnpm knip → 0 errors (1 pre-existing tag hint in unrelated file)
```
E2E (`pnpm --filter @comfyorg/website test:e2e`) is intended to be run
by the Vercel/CI pipelines.
## Manual verification
Built `dist/`, served locally on port 4321, drove with Playwright:
- `/cloud/supported-nodes` renders both pack cards, search input, sort
dropdown
- `/cloud/supported-nodes/comfyui-impact-pack` renders the metadata grid
(publisher, downloads, stars, version, license, last updated) and 3
categorized node sections with 5 nodes total
- `/zh-CN/cloud/supported-nodes` localizes hero (`Comfy Cloud 上的自定义节点`),
label (`云端节点目录`), search placeholder (`搜索节点包或节点名称`), sort
- `/zh-CN/cloud/supported-nodes/comfyui-controlnet-aux` localizes every
metadata label (`查看仓库`, `发布者`, `下载量`, `GitHub 星标`, `最新版本`, `许可证`,
`最后更新`) and renders dates with `Intl.DateTimeFormat('zh-CN')`
(`2026年4月27日`)
- Search input narrows pack count from 2 to 1 when typing `impact`
(verified via DOM count)
Banners render the shared `fallback-gradient-avatar.svg` when the
snapshot's image URL doesn't resolve — expected in the local sandbox.
## Preview URL (after CI completes)
`https://comfy-website-preview-pr-{N}.vercel.app/cloud/supported-nodes`
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-11903-feat-cloud-nodes-catalog-at-cloud-supported-nodes-3566d73d36508194afdec5f389897585)
by [Unito](https://www.unito.io)
---------
Co-authored-by: Glary-Bot <glary-bot@users.noreply.github.com>
Co-authored-by: GitHub Action <action@github.com>