Nodes/Castcut nodes/Castcut Report
ComfyUI Node

Castcut Report

The node whose real output is a history entry

By doodersrage·Created 21 days ago·Updated 14 days ago· 2
Castcut Report
  • alternate
    ◄report_json—►
    ◄filename_prefixcastcut-alt►
    ◄extra_json—►

    Here's a node with no output sockets at all. You wire the result JSON in, it runs, and nothing appears on the canvas - because its job is to put data somewhere a program can read it rather than somewhere you can look at it.

    Castcut Report is the last node in the pack's best-of-two loop: it takes the decision record from Castcut Pick Best, saves the runner-up take next to your chosen one, and publishes both scores into the job's history under a castcut key. The Castcut app polls /history and picks them up. If you're not running the app, you can still read them yourself, and the alternate take still lands in your output folder.

    What it does with the JSON

    The report_json input arrives as a string and gets parsed. If it doesn't parse, you don't get a crash - the node wraps it as {"raw": "...whatever you sent..."} and carries on. That's a deliberate soft failure: a malformed report shouldn't kill a render that already succeeded.

    If you also wire extra_json, its parsed value gets attached as report["extra"]. That's the hook for stitching two checks into one record - a Mask Repair report alongside a pose report, say, so the app sees one job's worth of evidence rather than two disconnected blobs.

    If alternate is connected, the images are written to ComfyUI's output folder with SaveImage's own naming rules - filename_prefix defaults to castcut-alt, %batch_num% is expanded, the usual counter suffix is appended, and the prompt and extra PNG metadata are embedded the same way SaveImage does it. The returned file references go back into the report as alternates, so the app can link to the loser take rather than guessing at a filename.

    Then the interesting bit. The node returns {"ui": {"castcut": [report]}} - not under "images". That's on purpose, with a comment in the source saying so: entries under images would be taken as the job's still, and the whole point is that the alternate is not the still. It's a UI payload with zero images in it, which is why nothing shows up in your ComfyUI window.

    Inputs, outputs, and how to read the result

    Required: report_json (forced input - a wire, from Pick Best or Pose Score or Mask Repair). Optional: alternate (IMAGE, typically Pick Best's other), filename_prefix (castcut-alt), extra_json. No outputs. It's an output node, so ComfyUI always executes it - the same backward-from-output-nodes behaviour that makes Preview Image and Save Image run, which the plumbing layer is built on.

    Since there's no socket to look at, read it over the API:

    curl -s http://127.0.0.1:8188/history/<prompt_id> | python3 -m json.tool | grep -A40 castcut
    

    Everything the app knows about the job's checks is in there: bestIndex, otherIndex, the score list, and the alternate's saved filename.

    Installing it

    Same pack as the other four nodes - Manager → search Castcut nodes, or comfy node install castcut-nodes, or the manual single-file route:

    git clone https://github.com/doodersrage/castcut-nodes
    cp castcut-nodes/castcut_nodes.py /path/to/ComfyUI/custom_nodes/
    # restart ComfyUI
    

    numpy and pillow, both already there. Worth knowing before you update: every node's description carries a [castcut-nodes 1.1.0] marker that the app parses to detect version drift, so http://127.0.0.1:8188/object_info/CastcutReport ending in that string is the proof you're current. Install the pack one way only; a castcut_nodes.py file and a castcut folder side by side both load.

    Where people get burned

    • "The node does nothing." It does; there's just no preview. Check the output folder for the castcut-alt file and the history entry for the rest.
    • Alternate files pile up. Every report with an alternate wired writes a PNG, even if the take was junk. On a big batch that's a second copy of every runner-up on disk, filling your output folder with images you'll mostly delete.
    • filename_prefix collisions. It uses SaveImage's counter logic, so a prefix you also use elsewhere shares the numbering range - you won't lose files, but the naming gets confusing.
    • Nothing appears if the graph never reaches it. It's an output node fed by Pick Best's report, so if the sampler or the DWPose step upstream errors, the report was never produced and there's nothing in history to read.
    CategoryCastcut

    Inputs (4)

    NameTypeDefaultDescription
    report_jsonSTRING—
    alternateoptIMAGE—
    filename_prefixoptSTRINGcastcut-alt—
    extra_jsonoptSTRING—

    Outputs (0)

    No outputs