Files
ComfyUI/docs/magic-patch.md

206 lines
9.3 KiB
Markdown

# Magic Patch CLI
Magic Patch converts a pristine or partially converted ComfyUI custom-node
pack into a new, complete V2 pack folder. It delegates implementation work to
an already-installed and authenticated Codex or Claude Code CLI, then applies
deterministic local acceptance gates. Comfy does not hold the contributor's
model credentials or pay for the conversion inference.
## Prerequisites
- Python 3.13 for the current Comfy runtime and V2 contract.
- Either Codex CLI or Claude Code, installed, authenticated, and usable from
the current shell:
- **Codex CLI:** follow OpenAI's current
[Codex CLI setup](https://learn.chatgpt.com/docs/codex/cli). On macOS or
Linux, its documented standalone install is
`curl -fsSL https://chatgpt.com/codex/install.sh | sh`. Run `codex` in a
project directory and choose **Sign in with ChatGPT** (or another offered
sign-in method) the first time it starts. OpenAI documents all supported
methods on the [Codex authentication page](https://learn.chatgpt.com/docs/auth).
- **Claude Code:** follow Anthropic's current
[Claude Code setup guide](https://code.claude.com/docs/en/getting-started).
Its recommended macOS/Linux/WSL native install is
`curl -fsSL https://claude.ai/install.sh | bash`. Run `claude` and follow
the browser login prompts. `claude --version` and `claude doctor` verify
the installation. Anthropic documents account and provider choices on the
[Claude Code authentication page](https://code.claude.com/docs/en/authentication).
- Node.js on `PATH` when converting frontend JavaScript, for an additional
syntax check.
- `git` and an authenticated `gh` CLI only when using `--create-pr`.
- A ComfyUI checkout containing `comfy_api` and `nodes.py` to prove the result
loads through the normal local V2 entrypoint. The current checkout is used
automatically; override it with `--core-root` or `COMFY_CORE_ROOT`.
- Optionally, an executable implementing the Magic Patch verifier protocol.
The Secure Nodes project can provide `comfy-secure-verify-pack`, but Magic
Patch does not import or require that project.
The command invokes only the contributor's ambient CLI login. It does not read
an API key or call a model API directly. Run `codex` or `claude` once and
finish its login before starting Magic Patch.
## Convert a pack
From this repository:
```bash
export COMFY_CORE_ROOT=/path/to/ComfyUI
/path/to/python3.13 -m tools.magic_patch \
/path/to/Original-Pack \
/path/to/Original-Pack-converted \
--agent auto
```
`auto` prefers Codex and falls back to Claude Code. Select one explicitly with
`--agent codex` or `--agent claude`; use `--model` only when a provider-specific
override is needed.
The input is never modified. The output path must not already exist. Magic
Patch creates a sibling staging directory, clones the whole original pack into
`v2/`, overlays any existing V2 draft, and permits the agent to edit only that
staged copy.
Patch identity is the pack's upstream Git commit: `x` plus the first seven
commit characters. When the input folder is the root of its Git checkout,
Magic Patch discovers it automatically. For an extracted archive or a pack
nested inside a monorepo, pass the pinned upstream commit explicitly with
`--source-sha`; use `--pack-slug` when the registry slug cannot be derived from
the input folder name.
A successful run publishes four sibling artifacts as one no-overwrite set:
```text
Original-Pack-converted/
... unchanged original files ...
v2/
... complete converted pack ...
comfy-api.pyi
comfy-api.d.ts
pyproject.toml
secure-nodes.json
V2_CONVERSION.md
Original-Pack-converted.zip
Original-Pack-converted.patches/
original-pack-x1a2b3c4.json
original-pack-x1a2b3c4.diff
Original-Pack-converted.magic-patch.json
```
The ZIP contains exactly one top-level `Original-Pack-converted/` folder with
the pristine source files at its root and the complete conversion under its
`v2/` child. It can be submitted directly as a V2 pack. ZIP member order,
timestamps, contents, and modes are deterministic. Override its destination
with `--pack-zip`, or omit it with `--no-pack-zip`.
The `.patches/` directory contains the same `.json` manifest and reviewable
`.diff` pair used by the backend deployment path. Magic Patch applies the pair
to a fresh copy of the original and requires the result to match the published
`v2/` tree byte-for-byte before it exposes any artifact. Override that directory
with `--patch-output`.
On failure, no output folder, ZIP, report, or patch directory is published.
The command prints the preserved staging path, containing agent logs and
`FAILURE.txt`, so a subsequent run can be diagnosed without losing evidence.
Use `--dry-run` to check paths, bundled contracts, the selected agent, and PR
prerequisites without invoking a model.
## Agent loop and acceptance gates
Each pass receives the complete pack plus trusted Python/frontend conversion
guidance. It returns a schema-constrained census and test record. Deterministic
findings become the repair prompt for the next pass, up to `--max-passes`.
Publishing requires all of the following:
- the original pack tree is byte-for-byte and mode-for-mode unchanged;
- pack-owned `AGENTS.md`, `CLAUDE.md`, `.agents/`, `.claude/`, and `.codex/`
content was not exposed as agent control input and is restored correctly;
- `v2/` is a complete pack with no symlinks, caches, or nested `v2/`;
- the bundled published `.pyi` and `.d.ts` contracts are unchanged;
- Python parses and has no ambient ComfyUI imports;
- declared frontend JavaScript parses when Node.js is available and contains
no known legacy host surfaces;
- `secure-nodes.json` is safe and agrees with `pyproject.toml`;
- the normal local ComfyUI V2 loader registers exactly the manifest node ids;
- the optional secure verifier passes when it is installed;
- a generated JSON/diff pair recreates the complete `v2/` tree byte-for-byte;
- the agent census has zero pending items and lists passing tests.
Source code remains untrusted data, but a coding agent necessarily reads it.
The normal local V2 load executes the converted entrypoint in a child process;
it is not an operating-system security boundary. Run deliberately hostile
repositories in a disposable machine or use the optional secure verifier.
## Optional secure-sandbox verification
Sandbox verification is `auto` by default. Magic Patch looks for
`comfy-secure-verify-pack` on `PATH`, or for the command named by
`COMFY_MAGIC_PATCH_SANDBOX_VERIFIER`. If no verifier is installed, all public
validation still runs and conversion can succeed. The public utility never
imports the secure runtime.
Use `--sandbox-verification required` when publication must have sandbox
evidence, or `--sandbox-verification off` to skip discovery. An explicit
verifier can be selected with `--sandbox-verifier /path/to/command`; its time
limit is controlled by `--sandbox-timeout`.
The public utility and optional verifier communicate through versioned JSON
request and result files. A discovered verifier that crashes, returns malformed
evidence, or reports an escape blocks publication even in `auto` mode. Passing
dynamic checks is evidence that the exercised imports and operations remained
inside the sandbox; it is not a mathematical proof that every possible code
path is incapable of escaping.
Magic Patch invokes the verifier without a shell:
```text
comfy-secure-verify-pack --request REQUEST.json --output RESULT.json
```
The request format is `comfy-magic-patch-verifier-request/1` and supplies
absolute `pack`, `source`, optional `core_root`, and `python_executable` paths.
The verifier must write `comfy-magic-patch-verifier-result/1` with a non-empty
`verifier` name, `status` equal to `passed`, `failed`, or `unavailable`, and
string arrays named `checks` and `errors`. Failed and unavailable results
require at least one error; passing results may not contain errors. In `auto`
mode, an unavailable platform backend is treated like an uninstalled verifier;
in `required` mode it blocks publication. This narrow protocol lets other
sandbox implementations integrate without coupling ComfyUI to private modules.
## Open a pull request
Add `--create-pr` to publish the validated `v2/` tree with the ambient `gh`
authentication:
```bash
/path/to/python3.13 -m tools.magic_patch \
/path/to/upstream-pack-checkout \
/path/to/upstream-pack-converted \
--agent codex \
--create-pr
```
Magic Patch discovers the GitHub repository and default branch from the source
checkout. It clones that repository into a disposable directory, checks out
the source revision when available, commits only the new or updated `v2/`
tree, pushes a generated branch, and opens a formatted PR against the original
repository. The body records the backend/frontend census, tests, validation
evidence, and conversion notes. The input checkout remains untouched.
If the authenticated user cannot push to the original repository, Magic Patch
creates or reuses their GitHub fork and opens a cross-fork PR. Direct the PR at
a different repository or a pack nested within a monorepo with:
```bash
--pr-repo owner/repository \
--pr-pack-path path/to/pack \
--pr-base main \
--pr-draft
```
`--pr-branch` and `--pr-title` override the generated branch and concise commit
title. PR publication happens only after local conversion succeeds. A GitHub
failure does not remove the converted pack or its local report.