anything that points to a non canonical pack is hack territory, fix asap and update the triage to deny such requests
Rgthree comfy
Configure and author rgthree-comfy nodes — Fast Groups Bypasser/Muter (group toggles), Power Lora Loader, Context/Context Big, Seed, Any Switch.
How to install
- Setup differs for this server — follow the Installation part of the README below.
- Claude Code:
claude mcp add <name> -- <command>. - Claude Desktop / Cursor: add it under
mcpServersin the MCP config file.
npx degit artokun/comfyui-mcp/plugin/skills/rgthree#main ~/.claude/skills/rgthreeFor one project only, change the path to .claude/skills/rgthree. This skill also uses fast_groups_muter.ts, fast_groups_service.ts — copying SKILL.md alone won't be enough. See the folder on GitHub.
This one runs on your machine and can reach your files. Read the README below before you connect it.
Not working?
- Check which app you pasted it into — the steps above name the right one.
- Some skills need the paid tier of Claude or ChatGPT.
Paste into Claude, ChatGPT or Cursor.
Show the full text222 lines
rgthree-comfy
rgthree-comfy is one of the most widely installed packs, so its nodes turn up in a
large share of community workflows. Three of its properties make it a recurring
agent-failure mode — all three fail quietly enough to look like success.
The three things that catch agents out
1. Some rgthree nodes are FRONTEND-ONLY. They are registered by the pack's JS
(registerCustomNodes()), have no Python class, and are therefore absent from
/object_info by design. Checking /object_info and concluding "this node doesn't
exist" is wrong. /object_info lists 24 rgthree backend types; the toggles are not
among them.
2. They are configured through PROPERTIES, not widgets. matchTitle,
toggleRestriction and sort live in node.properties (right-click → Properties),
not in widgets. Use panel_set_property. panel_set_widget does not silently
half-work — it refuses, with has no widget "matchTitle" (available: …) listing
the widgets that do exist. That refusal is the fastest confirmation you are on the
properties path; read it rather than retrying the write.
3. Fast Groups nodes take NO wiring and enumerate GROUPS by title. Leave the
OPT_CONNECTION output unconnected. The node renders one toggle per matching group,
so the groups must exist and be named before the node is useful.
Which rgthree nodes panel_add_node will actually add
The panel authorizes every add against fresh /object_info and fails closed on a
type it cannot find. Genuinely frontend-only types are exempt only via an explicit
allowlist (FRONTEND_ONLY_NODE_TYPES), so the exemption covers seven rgthree
types and no others:
Frontend-only, panel_add_node WORKS |
Frontend-only, panel_add_node REFUSES |
|---|---|
Fast Groups Bypasser (rgthree) |
Bookmark (rgthree) |
Fast Groups Muter (rgthree) |
Mute / Bypass Relay (rgthree) |
Fast Bypasser (rgthree) |
Mute / Bypass Repeater (rgthree) |
Fast Muter (rgthree) |
Fast Actions Button (rgthree) |
Node Collector (rgthree) |
Random Unmuter (rgthree) |
Label (rgthree) |
|
Reroute (rgthree) |
A refusal in the right-hand column is the guard working as designed, not a broken pack and not something to work around — the node has no backend def and is not on the allowlist. Say so and pick a different approach (the Bypasser/Muter cover almost every real toggle need). Everything with a Python class — Power Lora Loader, Context*, Seed, Any Switch, Power Prompt, Image Comparer — is a normal backend node and adds normally.
Fast Groups Bypasser / Muter
Fast Groups Bypasser (rgthree) sets the nodes of a group to bypass (mode 4 —
the node is skipped and its input passes through). Fast Groups Muter (rgthree) sets
them to mute (mode 2 — the node does not execute and everything downstream
dies). Prefer the Bypasser for toggling an optional stage inside a chain; reach
for the Muter only when you genuinely want to stop a branch.
All of the following are node properties — set them with panel_set_property:
| Property | Values | Default | Notes |
|---|---|---|---|
matchTitle |
regex, case-insensitive | "" |
Set this. Empty means every group in the workflow becomes a toggle. It is a real regex matched unanchored against the group title, so anchor it (^STAGE) or it matches mid-title. |
matchColors |
comma-separated colors | "" |
Alternative filter; pairs with a color convention. |
toggleRestriction |
default / max one / always one |
default |
Both non-default values enforce mutual exclusion (they are matched on the substring " one"). Do NOT set either if the user may ever want all stages on in one queue. |
sort |
position / alphanumeric / custom alphabet |
position |
The default means moving a group on the canvas silently reorders the toggles. alphanumeric is stable — prefer it. |
customSortAlphabet |
string | "" |
Only read when sort is custom alphabet. |
showNav |
bool | true |
Per-row jump-to-group arrow. |
showAllGraphs |
bool | true |
Include groups that live inside subgraphs. |
matchTitle does not rebuild the toggle list on the first write
panel_set_property stores matchTitle (and matchColors / sort / …) and
the reply from/to is truthful. Fast Groups nodes do not implement
onPropertyChanged. The toggle list is rebuilt by rgthree's
refreshWidgets() on a service tick (~8 ms after add, then every ~500 ms),
and leftover-row removal increments the index while splicing — a 22-group
list can stall at 13 with non-matching Enable … rows still present. A
never-drawn node can also come back as widgets:{} — that means the list
has not been built yet, not that there are no matching groups.
panel_query_graph also keys widgets by name, and every toggle is named
RGTHREE_TOGGLE_AND_NAV, so a built list collapses to one key.
Do this:
- Set
matchTitleimmediately afterpanel_add_node(before the first unfiltered refresh paints every group). - Re-read with
panel_query_graph {ids:[<id>], fields:'detail'}. - If
widgetsis empty or the canvas still showsEnablerows that do not match the regex, setmatchTitleagain. Do not delete and re-add the node — that is slower and still needs a second set.
Recipe — make pipeline stages toggleable
panel_create_groupper stage, with a prefixed title (STAGE 1 — …) so one anchored regex selects exactly the intended set.Verify group membership before you trust it. Group membership is purely geometric: LiteGraph counts a node as a member when its centre falls inside the box, and the auto-fit box around your
node_idswill happily swallow unrelated neighbours. When the live members differ from what you asked for, the result carriesextra_node_ids,missing_node_idsand awarningalongsiderequested_node_ids— read them. (They appear only when you passednode_idsand something differs, so their absence is a real all-clear.)A stray node here is not cosmetic: toggling one stage will disable part of another. To fix it, move the nodes apart (
panel_edit_node, orpanel_auto_layout) so the regions are contiguous, or set an explicitboundswithpanel_edit_group— then re-check.panel_move_groupdoes not help: by default it drags the contained nodes along with the box, so the same nodes stay inside it.panel_add_node(class_type="Fast Groups Bypasser (rgthree)"). Leave its output unwired. Add nodes one at a time, not as a parallel batch.panel_set_property→matchTitle=^STAGE, andsort=alphanumeric. Set them immediately after the add, then re-read the node. Ifwidgetsis empty or leftoverEnablerows remain, setmatchTitleagain — do not delete and re-add.Toggle, then verify with
panel_graph_outline— it tags nodes[bypass]/[mute].
Power Lora Loader (rgthree)
A backend node (present in /object_info) that stacks N LoRAs in one node. Each row
is a widget named lora_1, lora_2, … whose value is a composite object
{on: bool, lora: "subdir\\name.safetensors", strength: float, strengthTwo: float|null}
(strengthTwo is the separate CLIP strength, null in the simple view). Rows are
identified by the presence of a lora key, and the node's control widgets are
appended after them, so do not index positionally — address the row by name.
Rows CAN be created programmatically. A freshly added Power Lora Loader has
no lora_N widgets at all — the on-canvas "➕ Add Lora" button opens a chooser on a
mouse event that no panel tool can press, but panel_set_widget does not need it:
writing lora_1 (then lora_2, …) with a JSON object STRING creates the row and
the reply carries created_widget: "lora_1". Create rows in order, one call each:
panel_set_widget(node_id=<id>, widget="lora_1",
value='{"on":true,"lora":"subdir/turbo.safetensors","strength":1,"strengthTwo":null}')
# A Windows subdir separator is a JSON escape — write it DOUBLED in the string:
# "lora":"Anima\\Tools\\turbo.safetensors"
Re-read with panel_query_graph {ids:[<id>], fields:'detail'} to confirm the row
landed. If you need a stack from scratch, create lora_1, then lora_2, and so on;
do not assume a skipped number is the next row.
On an existing row, write ONE field with dotted sub-field addressing — it merges onto the current object and preserves every other field:
panel_set_widget(node_id=<id>, widget="lora_1.strength", value=0.8)
panel_set_widget(node_id=<id>, widget="lora_2.on", value=false)
panel_set_widget(node_id=<id>, widget="lora_1.lora", value="style/foo.safetensors")
Writing a bare scalar to lora_1 itself is the trap: it would set one field and
null the rest, so it is refused. To change several fields at once, pass a JSON
object STRING (the value argument accepts only string/number/boolean, so a literal
object fails tool validation before any write) — it is parsed and merged:
panel_set_widget(node_id=<id>, widget="lora_1", value='{"on":false,"strength":0.6}')
Fields are schema-checked: on non-nullable boolean, strength non-nullable number,
lora nullable string, strengthTwo nullable number. An unknown field name (a typo like
lora_1.strenght) is refused, not silently created, and nested paths are unsupported.
Clearing a nullable field takes the JSON-string form, not a dotted write. The panel
accepts null for lora / strengthTwo, but value is typed string | number | boolean, so a bare value=null is rejected by tool-arg validation before any write
happens — the same schema limit as the whole-row case above. Clear it through the string:
panel_set_widget(node_id=<id>, widget="lora_1", value='{"lora":null}')
Turning a LoRA off (lora_N.on = false) is usually safer than clearing it anyway.
Other commonly-seen rgthree nodes
- Context / Context Big / Context Switch / Context Merge — bundle
MODEL/CLIP/VAE/conditioning into one
RGTHREE_CONTEXTwire. These are NOT virtual wiring. Unlike Get/Set buses they are real executable backend nodes, sopanel_strip_workflowandpanel_flatten_workflowdeliberately keep them — they run. Do not expect either tool to dissolve a Context chain. There is no hidden edge to resolve: every link is a real link, traceable withpanel_query_graph. What a Context hides is which field a downstream node pulls out of the bundle, so read the chain node by node. (panel_slice_workflowstill carves one pipeline out of a toggled monolith, andpanel_strip_workflowstill resolves any genuine Get/Set buses and Reroutes around it.) - Seed (rgthree) — it deletes the built-in
control_after_generatewidget on creation, so do not try to write it; the widget is not there. Control is by SPECIAL SEED VALUES written to theseedwidget instead:-1randomize,-2increment,-3decrement. Any concrete seed is returned unchanged —42stays42every run — so to pin a run, write the number; to re-randomize, write-1. The frontend resolves a special value into a real seed before queueing and shows the result in a read-onlylast_seedwidget, so aseedre-read after a run may not be the special value the user set (a fixed seed, however, is stable). - Any Switch (rgthree) — the first non-null input wins; a common A/B toggle paired with bypassed branches. An empty Context counts as null, so an unfilled Context branch is skipped rather than selected.
Gotchas
- A bypassed node is skipped and passes its input through; a muted node kills everything downstream. Choosing the Muter where the Bypasser was meant breaks the chain rather than shortening it.
- Always
panel_graph_outlinebefore a run — a stale toggle is a top cause of a wrong render, and the outline marks[bypass]/[mute]explicitly. - rgthree's
Bookmarknodes respond to keypresses and are inert to agents.
Sources
- Official: https://github.com/rgthree/rgthree-comfy
- Empirical: frontend-only allowlist and properties-not-widgets notes verified against the installed pack and the panel guard.
#1808matchTitle rebuild: Fast Groups have noonPropertyChanged;refreshWidgets()leftover removal isremoveWidget(index++)infast_groups_muter.ts; first unfiltered tick is scheduled fromaddFastGroupNodeinfast_groups_service.ts.
| 1 | |
| 2 | name rgthree |
| 3 | description Configure and author rgthree-comfy nodes — Fast Groups Bypasser/Muter (group toggles), Power Lora Loader, Context/Context Big, Seed, Any Switch. Use when a workflow contains rgthree nodes, when asked to add stage/section toggles or an A/B switch, when stacking LoRAs, or when an rgthree node needs configuring. Covers the frontend-only nodes that are absent from /object_info and the properties-not-widgets configuration model. |
| 4 | |
| 5 | |
| 6 | # rgthree-comfy |
| 7 | |
| 8 | `rgthree-comfy` is one of the most widely installed packs, so its nodes turn up in a |
| 9 | large share of community workflows. Three of its properties make it a recurring |
| 10 | agent-failure mode — all three fail *quietly enough* to look like success. |
| 11 | |
| 12 | ## The three things that catch agents out |
| 13 | |
| 14 | **1. Some rgthree nodes are FRONTEND-ONLY.** They are registered by the pack's JS |
| 15 | (`registerCustomNodes()`), have no Python class, and are therefore **absent from |
| 16 | `/object_info` by design**. Checking `/object_info` and concluding "this node doesn't |
| 17 | exist" is wrong. `/object_info` lists 24 rgthree *backend* types; the toggles are not |
| 18 | among them. |
| 19 | |
| 20 | **2. They are configured through PROPERTIES, not widgets.** `matchTitle`, |
| 21 | `toggleRestriction` and `sort` live in `node.properties` (right-click → Properties), |
| 22 | not in `widgets`. Use **`panel_set_property`**. `panel_set_widget` does not silently |
| 23 | half-work — it **refuses**, with `has no widget "matchTitle" (available: …)` listing |
| 24 | the widgets that do exist. That refusal is the fastest confirmation you are on the |
| 25 | properties path; read it rather than retrying the write. |
| 26 | |
| 27 | **3. Fast Groups nodes take NO wiring and enumerate GROUPS by title.** Leave the |
| 28 | `OPT_CONNECTION` output unconnected. The node renders one toggle per matching group, |
| 29 | so **the groups must exist and be named before the node is useful**. |
| 30 | |
| 31 | ## Which rgthree nodes `panel_add_node` will actually add |
| 32 | |
| 33 | The panel authorizes every add against fresh `/object_info` and **fails closed** on a |
| 34 | type it cannot find. Genuinely frontend-only types are exempt only via an explicit |
| 35 | allowlist (`FRONTEND_ONLY_NODE_TYPES`), so the exemption covers **seven** rgthree |
| 36 | types and no others: |
| 37 | |
| 38 | | Frontend-only, `panel_add_node` WORKS | Frontend-only, `panel_add_node` REFUSES | |
| 39 | |---|---| |
| 40 | | `Fast Groups Bypasser (rgthree)` | `Bookmark (rgthree)` | |
| 41 | | `Fast Groups Muter (rgthree)` | `Mute / Bypass Relay (rgthree)` | |
| 42 | | `Fast Bypasser (rgthree)` | `Mute / Bypass Repeater (rgthree)` | |
| 43 | | `Fast Muter (rgthree)` | `Fast Actions Button (rgthree)` | |
| 44 | | `Node Collector (rgthree)` | `Random Unmuter (rgthree)` | |
| 45 | | `Label (rgthree)` | | |
| 46 | | `Reroute (rgthree)` | | |
| 47 | |
| 48 | A refusal in the right-hand column is the guard working as designed, **not** a broken |
| 49 | pack and not something to work around — the node has no backend def and is not on the |
| 50 | allowlist. Say so and pick a different approach (the Bypasser/Muter cover almost every |
| 51 | real toggle need). Everything with a Python class — Power Lora Loader, Context*, Seed, |
| 52 | Any Switch, Power Prompt, Image Comparer — is a normal backend node and adds normally. |
| 53 | |
| 54 | ## Fast Groups Bypasser / Muter |
| 55 | |
| 56 | `Fast Groups Bypasser (rgthree)` sets the nodes of a group to **bypass** (mode `4` — |
| 57 | the node is skipped and its input passes through). `Fast Groups Muter (rgthree)` sets |
| 58 | them to **mute** (mode `2` — the node does not execute and everything downstream |
| 59 | dies). **Prefer the Bypasser** for toggling an optional stage inside a chain; reach |
| 60 | for the Muter only when you genuinely want to stop a branch. |
| 61 | |
| 62 | All of the following are node properties — set them with `panel_set_property`: |
| 63 | |
| 64 | | Property | Values | Default | Notes | |
| 65 | |---|---|---|---| |
| 66 | | `matchTitle` | regex, case-insensitive | `""` | **Set this.** Empty means every group in the workflow becomes a toggle. It is a real regex matched *unanchored* against the group title, so anchor it (`^STAGE`) or it matches mid-title. | |
| 67 | | `matchColors` | comma-separated colors | `""` | Alternative filter; pairs with a color convention. | |
| 68 | | `toggleRestriction` | `default` / `max one` / `always one` | `default` | Both non-default values enforce mutual exclusion (they are matched on the substring `" one"`). Do NOT set either if the user may ever want all stages on in one queue. | |
| 69 | | `sort` | `position` / `alphanumeric` / `custom alphabet` | `position` | The default means **moving a group on the canvas silently reorders the toggles**. `alphanumeric` is stable — prefer it. | |
| 70 | | `customSortAlphabet` | string | `""` | Only read when `sort` is `custom alphabet`. | |
| 71 | | `showNav` | bool | `true` | Per-row jump-to-group arrow. | |
| 72 | | `showAllGraphs` | bool | `true` | Include groups that live inside subgraphs. | |
| 73 | |
| 74 | ### matchTitle does not rebuild the toggle list on the first write |
| 75 | |
| 76 | `panel_set_property` stores `matchTitle` (and `matchColors` / `sort` / …) and |
| 77 | the reply `from`/`to` is truthful. Fast Groups nodes **do not implement |
| 78 | `onPropertyChanged`**. The toggle list is rebuilt by rgthree's |
| 79 | `refreshWidgets()` on a service tick (~8 ms after add, then every ~500 ms), |
| 80 | and leftover-row removal increments the index while splicing — a 22-group |
| 81 | list can stall at 13 with non-matching `Enable …` rows still present. A |
| 82 | never-drawn node can also come back as `widgets:{}` — that means the list |
| 83 | has **not been built yet**, not that there are no matching groups. |
| 84 | `panel_query_graph` also keys widgets by name, and every toggle is named |
| 85 | `RGTHREE_TOGGLE_AND_NAV`, so a built list collapses to one key. |
| 86 | |
| 87 | **Do this:** |
| 88 | |
| 89 | Set `matchTitle` **immediately** after `panel_add_node` (before the first |
| 90 | unfiltered refresh paints every group). |
| 91 | Re-read with `panel_query_graph {ids:[<id>], fields:'detail'}`. |
| 92 | If `widgets` is empty **or** the canvas still shows `Enable` rows that do |
| 93 | not match the regex, **set `matchTitle` again**. Do **not** delete and |
| 94 | re-add the node — that is slower and still needs a second set. |
| 95 | |
| 96 | ### Recipe — make pipeline stages toggleable |
| 97 | |
| 98 | `panel_create_group` per stage, with a **prefixed title** (`STAGE 1 — …`) so one |
| 99 | anchored regex selects exactly the intended set. |
| 100 | |
| 101 | **Verify group membership before you trust it.** Group membership is purely |
| 102 | **geometric**: LiteGraph counts a node as a member when its *centre* falls inside |
| 103 | the box, and the auto-fit box around your `node_ids` will happily swallow unrelated |
| 104 | neighbours. When the live members differ from what you asked for, the result |
| 105 | carries `extra_node_ids`, `missing_node_ids` and a `warning` alongside |
| 106 | `requested_node_ids` — **read them**. (They appear only when you passed `node_ids` |
| 107 | *and* something differs, so their absence is a real all-clear.) |
| 108 | |
| 109 | A stray node here is not cosmetic: toggling one stage will disable part of another. |
| 110 | To fix it, **move the nodes apart** (`panel_edit_node`, or `panel_auto_layout`) so |
| 111 | the regions are contiguous, or set an explicit `bounds` with `panel_edit_group` — |
| 112 | then re-check. `panel_move_group` does **not** help: by default it drags the |
| 113 | contained nodes along with the box, so the same nodes stay inside it. |
| 114 | |
| 115 | `panel_add_node(class_type="Fast Groups Bypasser (rgthree)")`. Leave its output |
| 116 | unwired. Add nodes one at a time, not as a parallel batch. |
| 117 | |
| 118 | `panel_set_property` → `matchTitle` = `^STAGE`, and `sort` = `alphanumeric`. |
| 119 | Set them immediately after the add, then re-read the node. If `widgets` is |
| 120 | empty or leftover `Enable` rows remain, set `matchTitle` again — do not |
| 121 | delete and re-add. |
| 122 | |
| 123 | Toggle, then verify with `panel_graph_outline` — it tags nodes `[bypass]` / `[mute]`. |
| 124 | |
| 125 | ## Power Lora Loader (rgthree) |
| 126 | |
| 127 | A **backend** node (present in `/object_info`) that stacks N LoRAs in one node. Each row |
| 128 | is a widget named **`lora_1`, `lora_2`, …** whose value is a composite object |
| 129 | `{on: bool, lora: "subdir\\name.safetensors", strength: float, strengthTwo: float|null}` |
| 130 | (`strengthTwo` is the separate CLIP strength, `null` in the simple view). Rows are |
| 131 | identified by the **presence of a `lora` key**, and the node's control widgets are |
| 132 | appended *after* them, so do not index positionally — **address the row by name**. |
| 133 | |
| 134 | **Rows CAN be created programmatically.** A freshly added Power Lora Loader has |
| 135 | **no `lora_N` widgets at all** — the on-canvas "➕ Add Lora" button opens a chooser on a |
| 136 | mouse event that no panel tool can press, but `panel_set_widget` does not need it: |
| 137 | writing `lora_1` (then `lora_2`, …) with a **JSON object STRING** creates the row and |
| 138 | the reply carries `created_widget: "lora_1"`. Create rows **in order**, one call each: |
| 139 | |
| 140 | |
| 141 | panel_set_widget(node_id=<id>, widget="lora_1", |
| 142 | value='{"on":true,"lora":"subdir/turbo.safetensors","strength":1,"strengthTwo":null}') |
| 143 | |
| 144 | # A Windows subdir separator is a JSON escape — write it DOUBLED in the string: |
| 145 | # "lora":"Anima\\Tools\\turbo.safetensors" |
| 146 | |
| 147 | |
| 148 | Re-read with `panel_query_graph {ids:[<id>], fields:'detail'}` to confirm the row |
| 149 | landed. If you need a stack from scratch, create `lora_1`, then `lora_2`, and so on; |
| 150 | do not assume a skipped number is the next row. |
| 151 | |
| 152 | On an existing row, write ONE field with **dotted sub-field addressing** — it merges |
| 153 | onto the current object and preserves every other field: |
| 154 | |
| 155 | |
| 156 | panel_set_widget(node_id=<id>, widget="lora_1.strength", value=0.8) |
| 157 | panel_set_widget(node_id=<id>, widget="lora_2.on", value=false) |
| 158 | panel_set_widget(node_id=<id>, widget="lora_1.lora", value="style/foo.safetensors") |
| 159 | |
| 160 | |
| 161 | Writing a **bare scalar to `lora_1` itself** is the trap: it would set one field and |
| 162 | null the rest, so it is refused. To change several fields at once, pass a **JSON |
| 163 | object STRING** (the `value` argument accepts only string/number/boolean, so a literal |
| 164 | object fails tool validation before any write) — it is parsed and merged: |
| 165 | |
| 166 | |
| 167 | panel_set_widget(node_id=<id>, widget="lora_1", value='{"on":false,"strength":0.6}') |
| 168 | |
| 169 | |
| 170 | Fields are schema-checked: `on` non-nullable boolean, `strength` non-nullable number, |
| 171 | `lora` nullable string, `strengthTwo` nullable number. An unknown field name (a typo like |
| 172 | `lora_1.strenght`) is **refused**, not silently created, and nested paths are unsupported. |
| 173 | |
| 174 | **Clearing a nullable field takes the JSON-string form, not a dotted write.** The panel |
| 175 | accepts `null` for `lora` / `strengthTwo`, but `value` is typed `string | number | |
| 176 | boolean`, so a bare `value=null` is rejected by tool-arg validation before any write |
| 177 | happens — the same schema limit as the whole-row case above. Clear it through the string: |
| 178 | |
| 179 | |
| 180 | panel_set_widget(node_id=<id>, widget="lora_1", value='{"lora":null}') |
| 181 | |
| 182 | |
| 183 | Turning a LoRA **off** (`lora_N.on = false`) is usually safer than clearing it anyway. |
| 184 | |
| 185 | ## Other commonly-seen rgthree nodes |
| 186 | |
| 187 | **Context / Context Big / Context Switch / Context Merge** — bundle |
| 188 | MODEL/CLIP/VAE/conditioning into one `RGTHREE_CONTEXT` wire. **These are NOT virtual |
| 189 | wiring.** Unlike Get/Set buses they are real executable backend nodes, so |
| 190 | `panel_strip_workflow` and `panel_flatten_workflow` deliberately **keep** them — they |
| 191 | run. Do not expect either tool to dissolve a Context chain. There is no hidden edge to |
| 192 | resolve: every link is a real link, traceable with `panel_query_graph`. What a Context |
| 193 | hides is *which field* a downstream node pulls out of the bundle, so read the chain |
| 194 | node by node. (`panel_slice_workflow` still carves one pipeline out of a toggled |
| 195 | monolith, and `panel_strip_workflow` still resolves any genuine Get/Set buses and |
| 196 | Reroutes around it.) |
| 197 | **Seed (rgthree)** — it **deletes the built-in `control_after_generate` widget** on |
| 198 | creation, so do not try to write it; the widget is not there. Control is by SPECIAL |
| 199 | SEED VALUES written to the `seed` widget instead: **`-1` randomize, `-2` increment, |
| 200 | `-3` decrement**. Any concrete seed is returned **unchanged** — `42` stays `42` every |
| 201 | run — so to pin a run, write the number; to re-randomize, write `-1`. The frontend |
| 202 | resolves a special value into a real seed *before* queueing and shows the result in a |
| 203 | read-only `last_seed` widget, so a `seed` re-read after a run may not be the special |
| 204 | value the user set (a fixed seed, however, is stable). |
| 205 | **Any Switch (rgthree)** — the first non-null input wins; a common A/B toggle paired |
| 206 | with bypassed branches. An **empty Context counts as null**, so an unfilled Context |
| 207 | branch is skipped rather than selected. |
| 208 | |
| 209 | ## Gotchas |
| 210 | |
| 211 | A **bypassed** node is skipped and passes its input through; a **muted** node kills |
| 212 | everything downstream. Choosing the Muter where the Bypasser was meant breaks the |
| 213 | chain rather than shortening it. |
| 214 | Always `panel_graph_outline` before a run — a stale toggle is a top cause of a wrong |
| 215 | render, and the outline marks `[bypass]` / `[mute]` explicitly. |
| 216 | rgthree's `Bookmark` nodes respond to keypresses and are inert to agents. |
| 217 | |
| 218 | ## Sources |
| 219 | |
| 220 | **Official:** https://github.com/rgthree/rgthree-comfy |
| 221 | **Empirical:** frontend-only allowlist and properties-not-widgets notes verified against the installed pack and the panel guard. `#1808` matchTitle rebuild: Fast Groups have no `onPropertyChanged`; `refreshWidgets()` leftover removal is `removeWidget(index++)` in `fast_groups_muter.ts`; first unfiltered tick is scheduled from `addFastGroupNode` in `fast_groups_service.ts`. |
| 222 |
Discussion
From GitHub
6 comments on 2 threadsClaimed 2026-09-03T05:48:00Z — dispatched to a fix agent. Root cause confirmed against the **canonical** ComfyUI-Manager `extension-node-map.json` (5,614 packs / 40,656 exactly-owned class names), no reporter box needed. The resolver in `src/services/workflow-deps.ts` trusts a Manager `nodename_pattern` as if it were ownership. Measured on the real catalogue: | pattern | claimed by | class names it steals from OTHER packs | |---|---|---| | `Hunyuan` | `exedesign/Hunyuan…` | **182** | | `PulidFlux` | `PaoloC68/…` | 13 | | `Inspire$` | `ComfyUI Connection Helper` | **101** | | `Inspire$` | `Insp… read the rest
**Status: fix complete, merge HELD on review capacity — not merged.** Two PRs exist for this issue (two agents collided): **#2777** (mine, gate-reviewed) and **#2775** (an independent fix by a sibling agent). Neither is merged. The codex review gate exhausted its account quota on round 6 (`exit 2 — INDETERMINATE`). An indeterminate gate is not a pass, so I am not merging on my own testing. **Root cause**, measured against the canonical ComfyUI-Manager catalogue (5,614 packs / 40,656 exactly-owned class names) rather than inferred — a `nodename_pattern` was being read as an ownership record. It… read the rest
Root cause confirmed on disk, from the catalogue everyone has rather than the reporter's box. `DemonGatanjieu/Anomalous_Model_Browser` — the repository this issue says was named as the owner of `Power Lora Loader (rgthree)` and the other three — publishes **`nodename_pattern: ".*"`**. In this machine's live `extension-node-map.json` (4,884 packs, 36,174 exactly-owned class names, 39 patterns) that single pattern matches **all 36,174** known class names, and the pack exactly owns **zero** of them. So any class the catalogue does not name exactly was attributable to that repo, and `install_deps`… read the rest
Claimed by Codex for the next P2 drain swarm. I will trace Manager v4 apply_manifest enqueue response/queue-start semantics and existing-node satisfaction, inspect current claims/worktrees before coding, and post the validation/merge outcome here. Other agents should skip this issue while claimed.
Still claimed by Codex; the release checkpoint is complete pending publication verification, then I will re-engage the existing PR/worktree to rebase onto current main and drive the exact-head review/merge gate. Other agents should skip this issue while claimed.