Sandpies Claude Opus 5 commited on
Commit
ff9b717
·
1 Parent(s): 65ffad2

1.0.0: the writer on the node, and the docs to match

Browse files

Version 1.0.0. The README front door never mentioned WRITE at all -- the
headline feature of this release was reachable only by finding it on the node
-- so it now has its own section, and the "what v1.0 changed" table a row.

Docs:
- Four screenshots from a real 3-hop render: the editor panels, the WRITE bar,
the MEDIA strip and a contact sheet. All LFS, all referenced through
media.githubusercontent.com as .gitattributes requires.
- New "Voice, music and trims" section. The audio in/out windows were
documented only in a tooltip, and the reason they matter -- H3 encodes the
whole voice file with no cap and attends over it every step of every hop --
was nowhere a reader would find it.
- The starter workflow's notes gained the sub-hop sound rule and its symptom
row, and its writer note now leads with the built-in panel rather than the
copy-paste flow. Its context guidance said 16384 and ~4,700 tokens; the
system prompt measures ~6,000 and wants 32768.
- The old contact-sheet.png is superseded and unreferenced; dropped.

Tooltips: two named a render id (chain_00038) that means nothing outside this
repo, and the ref_plan tooltip said "today's positional behaviour", which reads
as pending work rather than a description. The engineering comments keep their
render ids -- those are provenance and never reach a user.

All 9 checks pass.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014VB4Dw6F79643vySkf19KV

README.md CHANGED
@@ -62,7 +62,25 @@ of a second, separate generation. The pack exists so that you cannot tell which.
62
  > which flags every `subprocess` call in a custom node regardless of how it is
63
  > invoked. Section 23 of the devlog.
64
 
65
- **Writing for it:** [PROMPTING.md](PROMPTING.md) is the authoring guide — the rules that come from what this model actually does, not from taste. [prompt_pack/](prompt_pack/) has a copy-paste prompt that gets a language model to write plans for you.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
66
 
67
  Each hop is native **MiniMax H3 Reference-to-Video**. Hops after the first are guided by the **previous hop's sampler AV latent** via `ComfyUI-H3-Motion-Context` when that pack is installed (22 picture frames + 24-frame end-aligned audio). Stock `MiniMaxH3AddGuide` is the fallback when Motion-Context is missing or the previous hop was a pixel cache hit. Voice stays as a reference every hop. Identity stills ride hop 1; later hops use the pin for wardrobe and room unless a ref lists those hops in `shots`. A 5 s hop drops the airlock on a continuous join — validate seams at 8 s or 15 s.
68
 
@@ -78,6 +96,7 @@ The prompt is no longer a wall of `---`-delimited text, and the MODEL wire is no
78
  | **`directives`** | `join` / `camera` / `framing` / `pace` / `tail` per shot, compiled to vetted prose. Improving a phrase improves every plan you have ever written. |
79
  | **`ref_plan`** | Stable `@tags` for reference stills, grouped into subjects, each naming a picture file. Removing one can no longer silently renumber `<Picture N>`. |
80
  | **`cache_hops`** | Lossless per-hop cache. Re-roll one shot, resume after a crash, and hold roughly one hop in RAM instead of the whole clip. Edit hop 5 of 8 and only 5-8 re-render. [How to use it](PROMPTING.md#re-rolling-one-hop). |
 
81
  | **the editor** | Cards on the node, not JSON in a textarea. Hover any directive to read the exact sentence it puts in the prompt, or hit **Templates** for a ready-made pattern. |
82
 
83
  Simple mode keeps the old one-prompt workflow; the speed stack (LoRAs, AdaLN fix, low-VRAM, SLA) stays as four ordinary nodes on the MODEL wire, where you can see it.
@@ -185,6 +204,10 @@ None of it is required by the node itself. Missing a pack, its nodes load as red
185
  5. Optional: a `voice_file`, a `start_image_file`, a look `reference_video_file` — all picked in the **MEDIA** strip, all files under `input/h3_refs`
186
  6. Queue, and wire the **`info`** output to a Preview Text node — it prints the fully assembled prompt for every hop
187
 
 
 
 
 
188
  Keep later-hop beats on **what happens next**. Do not re-describe the face; the photos, the register and the pin already carry it.
189
 
190
  Two modes:
@@ -311,6 +334,34 @@ model is told action is still underway at the final frame and will invent
311
  something to satisfy it -- on a last shot that means a stray gesture or a stray
312
  line of dialogue in the closing second.
313
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
314
  ## Reference register
315
 
316
  ```json
@@ -381,7 +432,7 @@ hop's first and last **delivered** frame side by side, its beat, its directives,
381
  and what actually happened to it — seed, steps, whether it came from cache, what
382
  the tone correction did. Wire it to a Save Image.
383
 
384
- ![Contact sheet](https://media.githubusercontent.com/media/dntpi/ComfyUI-Hand-Tie-Clips/main/docs/img/contact-sheet.png)
385
 
386
  On a chain of any length this is the fastest way to find the hop that broke. The
387
  one hard cut in the 114-second reference chain sat in a plan that passed every
@@ -501,6 +552,25 @@ The DiT pin is the previous hop’s **sampler latent** through Motion-Context wh
501
 
502
  Three shots at 10 s with a 0.9 s overlap is about 28 s of master after the overlap is dropped.
503
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
504
  ## Limits
505
 
506
  - **A workflow saved before 2026-08-28 loses its reference pictures.** The old `ref_image_N` sockets carried tensors, so there is no filename to recover. The rail names each affected ref and asks you to pick its picture; nothing else about the plan is lost.
 
62
  > which flags every `subprocess` call in a custom node regardless of how it is
63
  > invoked. Section 23 of the devlog.
64
 
65
+ > **1.0.0 — 2026-09-02.** First full release. The headline is **WRITE**: a plan
66
+ > writer on the node itself, pointed at any OpenAI-compatible server, that fills
67
+ > the script and the reference rows together and sends your reference pictures
68
+ > with the request. Around it, the parts that make a written plan survive
69
+ > contact with the model — the schema the server is handed now *requires* both
70
+ > documents, so a reply carrying only half of one stopped being a silent
71
+ > failure; the reference rail owns each picture's pixel budget, which a plan
72
+ > used to reset to full and quietly triple the load against a fixed canvas; and
73
+ > the writer is told the hop length, so beats are sized to the clip instead of
74
+ > to a guess. Three plan lints were measured against real renders and found to
75
+ > be warning about correct work — a restated framing read as a cut, a
76
+ > single-room chain read as an abandoned location — and were narrowed. Rule 3
77
+ > of the prompt pack grew the case that cost the most renders: a hop that
78
+ > speaks *later* has opening seconds with a picture and no sound assigned, and
79
+ > the model fills them with dialogue nobody wrote. Ending the previous hop
80
+ > quiet buys a quiet pin, not a quiet opening. Sections 31 and 32 of the devlog
81
+ > have the measurements.
82
+
83
+ **Writing for it:** [PROMPTING.md](PROMPTING.md) is the authoring guide — the rules that come from what this model actually does, not from taste. The node's **WRITE** bar hands the whole job to a local model: describe the scene in a sentence and it fills the script and the reference rows for you. [prompt_pack/](prompt_pack/) is the same writer as a copy-paste prompt, for when you would rather work in a chat window.
84
 
85
  Each hop is native **MiniMax H3 Reference-to-Video**. Hops after the first are guided by the **previous hop's sampler AV latent** via `ComfyUI-H3-Motion-Context` when that pack is installed (22 picture frames + 24-frame end-aligned audio). Stock `MiniMaxH3AddGuide` is the fallback when Motion-Context is missing or the previous hop was a pixel cache hit. Voice stays as a reference every hop. Identity stills ride hop 1; later hops use the pin for wardrobe and room unless a ref lists those hops in `shots`. A 5 s hop drops the airlock on a continuous join — validate seams at 8 s or 15 s.
86
 
 
96
  | **`directives`** | `join` / `camera` / `framing` / `pace` / `tail` per shot, compiled to vetted prose. Improving a phrase improves every plan you have ever written. |
97
  | **`ref_plan`** | Stable `@tags` for reference stills, grouped into subjects, each naming a picture file. Removing one can no longer silently renumber `<Picture N>`. |
98
  | **`cache_hops`** | Lossless per-hop cache. Re-roll one shot, resume after a crash, and hold roughly one hop in RAM instead of the whole clip. Edit hop 5 of 8 and only 5-8 re-render. [How to use it](PROMPTING.md#re-rolling-one-hop). |
99
+ | **`WRITE`** | A plan writer on the node. Point it at any OpenAI-compatible server — LM Studio, llama-server — describe the scene in plain language, and it fills the script and the reference rows, reading the pictures you have already dropped in. Server settings stay on your machine, never in the workflow. |
100
  | **the editor** | Cards on the node, not JSON in a textarea. Hover any directive to read the exact sentence it puts in the prompt, or hit **Templates** for a ready-made pattern. |
101
 
102
  Simple mode keeps the old one-prompt workflow; the speed stack (LoRAs, AdaLN fix, low-VRAM, SLA) stays as four ordinary nodes on the MODEL wire, where you can see it.
 
204
  5. Optional: a `voice_file`, a `start_image_file`, a look `reference_video_file` — all picked in the **MEDIA** strip, all files under `input/h3_refs`
205
  6. Queue, and wire the **`info`** output to a Preview Text node — it prints the fully assembled prompt for every hop
206
 
207
+ ![The REFERENCES rail, the MEDIA strip and the SCRIPT cards](https://media.githubusercontent.com/media/dntpi/ComfyUI-Hand-Tie-Clips/main/docs/img/editor-panels.png)
208
+
209
+ *The three panels that make up the editor. Each reference row carries its picture, the subject it belongs to, how much of it to keep, its pixel budget and a plain-language description; the chips under it are the hops it rides. Below, one card per hop with its own directives.*
210
+
211
  Keep later-hop beats on **what happens next**. Do not re-describe the face; the photos, the register and the pin already carry it.
212
 
213
  Two modes:
 
334
  something to satisfy it -- on a last shot that means a stray gesture or a stray
335
  line of dialogue in the closing second.
336
 
337
+ ## Let a model write the plan
338
+
339
+ Open **WRITE** on the node, point it at any OpenAI-compatible server, say what
340
+ you want in one sentence, and press **Write plan**. It fills the SCRIPT cards
341
+ and the REFERENCES rows together — and the pictures already on those rows go
342
+ with the request, so the model describes what it is actually looking at rather
343
+ than guessing from a filename.
344
+
345
+ ![The WRITE bar](https://media.githubusercontent.com/media/dntpi/ComfyUI-Hand-Tie-Clips/main/docs/img/write-panel.png)
346
+
347
+ - **Context 32768.** The system prompt alone is ~6,000 tokens, the reply another
348
+ 1,000–2,000, and every reference picture costs ~260 on top.
349
+ - **Reasoning off.** Thinking tokens come out of the same budget; a reply that
350
+ stops before the JSON closes is the tell.
351
+ - **Temperature 0.3.** Higher and the JSON grows trailing commas and smart quotes.
352
+
353
+ Server settings are saved on this machine only — they are not part of the
354
+ workflow, so a shared `.json` never points at your server.
355
+
356
+ **Treat what comes back as a strong draft, not a finished plan.** It gets the
357
+ structure right — hop count, join types, which reference rides which hop, a
358
+ sound bed on every quiet hop — and that is the part that is tedious by hand.
359
+ Two things are worth reading every time: each reference's `desc`, which can be
360
+ confidently wrong about its own photograph, and the spoken words in every beat.
361
+ The node lints both and prints what it finds before you render.
362
+
363
+ `prompt_pack/` is the same writer as a copy-paste prompt for a chat window.
364
+
365
  ## Reference register
366
 
367
  ```json
 
432
  and what actually happened to it — seed, steps, whether it came from cache, what
433
  the tone correction did. Wire it to a Save Image.
434
 
435
+ ![Contact sheet](https://media.githubusercontent.com/media/dntpi/ComfyUI-Hand-Tie-Clips/main/docs/img/contact-sheet-vlog.png)
436
 
437
  On a chain of any length this is the fastest way to find the hop that broke. The
438
  one hard cut in the 114-second reference chain sat in a plan that passed every
 
552
 
553
  Three shots at 10 s with a 0.9 s overlap is about 28 s of master after the overlap is dropped.
554
 
555
+ ## Voice, music and trims
556
+
557
+ The **MEDIA** strip takes a first frame, a look reference clip, a voice
558
+ reference and a music bed — all files under `input/h3_refs`, all picked in the
559
+ panel, none of them a `Load Image` node you have to wire.
560
+
561
+ ![The MEDIA strip, with a voice reference and a soundtrack loaded](https://media.githubusercontent.com/media/dntpi/ComfyUI-Hand-Tie-Clips/main/docs/img/media-panel.png)
562
+
563
+ Each audio slot has a scrubber with an in/out window, and it is worth using.
564
+ H3 encodes the **whole** voice file into the conditioning with no cap, and every
565
+ latent frame of it is attended over on every step of every hop — so a
566
+ three-minute take is a large invisible tax on a clip that only needed four
567
+ seconds. The soundtrack window is cut from the track first, then `music_fit`
568
+ loops or trims that to the chain, which is what stops a mastered track always
569
+ starting the chain on its intro.
570
+
571
+ An end of `0` always means *to the end of the file*, so a longer replacement
572
+ file still plays out rather than being silently cropped to the old one.
573
+
574
  ## Limits
575
 
576
  - **A workflow saved before 2026-08-28 loses its reference pictures.** The old `ref_image_N` sockets carried tensors, so there is no filename to recover. The rail names each affected ref and asks you to pick its picture; nothing else about the plan is lost.
docs/img/{contact-sheet.png → contact-sheet-vlog.png} RENAMED
File without changes
docs/img/editor-panels.png ADDED

Git LFS Details

  • SHA256: 20a4213e209af2f08805ebdb21acbf851014ff14cd84e77494c54bdbdb19053d
  • Pointer size: 131 Bytes
  • Size of remote file: 113 kB
docs/img/media-panel.png ADDED

Git LFS Details

  • SHA256: 61e38cf33445d51865f0ebc63a40e1330f1fad53509dd34ca4652b0281d025aa
  • Pointer size: 130 Bytes
  • Size of remote file: 62.5 kB
docs/img/write-panel.png ADDED

Git LFS Details

  • SHA256: ffb9d80d67266cd4f465f37a29d630775ef470391b87508fc2224e3bd34e8330
  • Pointer size: 130 Bytes
  • Size of remote file: 21.4 kB
h3_ref_chain.py CHANGED
@@ -1133,7 +1133,7 @@ class HandTieClips:
1133
  "<Picture N> per hop, so removing or scheduling off a ref "
1134
  "never renumbers the others. Refs sharing a 'subject' are "
1135
  "the same person; different numbers stay different people. "
1136
- "Blank = today's positional behaviour."
1137
  ),
1138
  }),
1139
  "cache_hops": (["off", "on"], {
@@ -1178,7 +1178,7 @@ class HandTieClips:
1178
  "total sigma FALLS across a chain whose picture is "
1179
  "baking, so it corrects the wrong way. Saved as `on` "
1180
  "before 0.5. "
1181
- "off reproduces chain_00038 exactly. The log prints "
1182
  "`pin drift` every hop either way, so you can read the "
1183
  "ratchet without changing anything."
1184
  ),
@@ -1190,8 +1190,8 @@ class HandTieClips:
1190
  "conditions the next hop -- the other half of the texture "
1191
  "ratchet fix. Small values only: measured gains fall off "
1192
  "and reverse above 0.10, which is why the range stops "
1193
- "there. 0.0 reproduces chain_00038 exactly; 0.05 is the "
1194
- "documented starting point."
1195
  ),
1196
  }),
1197
  "tone_compensate": (_tone.MODES, {
 
1133
  "<Picture N> per hop, so removing or scheduling off a ref "
1134
  "never renumbers the others. Refs sharing a 'subject' are "
1135
  "the same person; different numbers stay different people. "
1136
+ "Blank = positional behaviour: refs are read in slot order."
1137
  ),
1138
  }),
1139
  "cache_hops": (["off", "on"], {
 
1178
  "total sigma FALLS across a chain whose picture is "
1179
  "baking, so it corrects the wrong way. Saved as `on` "
1180
  "before 0.5. "
1181
+ "off leaves every pin untouched. The log prints "
1182
  "`pin drift` every hop either way, so you can read the "
1183
  "ratchet without changing anything."
1184
  ),
 
1190
  "conditions the next hop -- the other half of the texture "
1191
  "ratchet fix. Small values only: measured gains fall off "
1192
  "and reverse above 0.10, which is why the range stops "
1193
+ "there. 0.0 leaves the pin untouched; 0.05 is the "
1194
+ "suggested starting point."
1195
  ),
1196
  }),
1197
  "tone_compensate": (_tone.MODES, {
pyproject.toml CHANGED
@@ -1,6 +1,6 @@
1
  [project]
2
  name = "comfyui-hand-tie-clips"
3
- version = "0.4.5"
4
  description = "Native MiniMax H3 Ref2VA chain: persistent references, previous-segment clip+audio pin, one queue."
5
  readme = "README.md"
6
  # SPDX string, not `{ file = "LICENSE" }`. The registry does not resolve the file
 
1
  [project]
2
  name = "comfyui-hand-tie-clips"
3
+ version = "1.0.0"
4
  description = "Native MiniMax H3 Ref2VA chain: persistent references, previous-segment clip+audio pin, one queue."
5
  readme = "README.md"
6
  # SPDX string, not `{ file = "LICENSE" }`. The registry does not resolve the file
workflows/HandTieClips_Starter.json CHANGED
@@ -1259,7 +1259,7 @@
1259
  "htc_card": "rules"
1260
  },
1261
  "widgets_values": [
1262
- "## The rules that decide whether it works\n\nNot style preferences. This is how this model fails.\n\n### 1. The prompt is additive\n\nSampling runs at **cfg 1.0 with no negative branch**. Every concept you name is\nadded, and nothing can be removed by mentioning it -- `no cut` puts the word\n*cut* in front of the encoder. **Never write a negation.**\n\n### 2. Never name the thing you want to end\n\n\"The cook stops talking\" keeps her talking. Write the state you want as **a pose\nplus a sound**:\n\n> leans back against the counter with her lips closed, and lets her eyes move\n> slowly across the room. The kitchen is quiet apart from the low hum of the\n> refrigerator.\n\nAudio is always generated. Silence written as an absence comes back as speech,\nso **silence has to be written as a sound** -- room tone, a fridge, a single\nclick. Keep it narrowband: \"faint street noise\" renders as a five-second hiss.\n\n**The ban is on the idea, not on a word list.** *Fades, passes, wanes, subsides,\ndies down, eases off* all name an ending as surely as *stops* does, and all of\nthem add the thing they describe. Ask of each sentence: is this happening, or\nhas it finished happening?\n\n### 3. A state change belongs at the END of the previous shot\n\nEvery hop opens holding the frames it was handed, and the audio pin carries the\nprevious hop's tail across the join. Nothing you write in shot 3 can make shot 3\nstart quiet. **Arrive there before the previous shot ends.**\n\n### 4. A hop that ends on dialogue keeps talking\n\nSpeech at the end of hop N opens hop N+1 and propagates down the whole chain.\nLand each line **mid-hop** and leave a non-verbal action running into the seam --\nslicing, walking, a hand on a doorframe. Give every hop with no dialogue a sound\nbed of its own.\n\n### 5. A walk between two rooms is `match_cut`\n\n`join: continuous` across a real location change makes the model morph one room\ninto the other mid-movement.\n\n### 6. Set `tail` on your last shot\n\nLeft at `ongoing`, the model is told action is still underway at the final frame\nand will invent something to satisfy it. Use `settle` or `hold`."
1263
  ],
1264
  "color": "#432",
1265
  "bgcolor": "#653"
@@ -1337,7 +1337,7 @@
1337
  "htc_card": "trouble"
1338
  },
1339
  "widgets_values": [
1340
- "## When it goes wrong\n\n| symptom | cause | fix |\n|---|---|---|\n| The clip cuts to the reference photo in its last seconds | The beat finished before the frames did | Set `tail`, give the beat enough to do |\n| A stray gesture or line in the closing second | `tail: ongoing` on the final shot | `settle` or `hold` |\n| She keeps talking after you asked for quiet | You named the ending | Pose plus a sound |\n| Dialogue continues into hops that have none written | The hop before ended on speech | Land the line early; non-verbal action into the seam; a sound bed on every quiet hop |\n| A character walks between two rooms and one morphs into the other | `continuous` across a location change | `match_cut` |\n| Silence renders as speech | Silence written as an absence | Name room tone, a fridge, a distant car |\n| Ambience is a five-second hiss | Broadband wording | Narrowband, or one discrete event |\n| Two characters' faces merge | Both declared as the same `subject` | One subject number per person |\n| The face becomes a different person partway through | A hop scheduled with no face plate. `locked` holds a face that is still right; only a plate rebuilds one that is gone, and the drift never self-corrects | Put the face ref on **every** hop |\n| A stylised plan renders photoreal | The node's hop-1 establishing line asserts live action | Name the medium in shot 1's first sentence, or clear the `establish` widget |\n| The film gets darker every hop | Each hop dims across its own frames and hands the darker tail on. Seam correction cannot see it | `tone_compensate=anchor`. `tone_anchor=0.35` removed ~60% of measured drift; 0.6 removes ~78% and costs ~0.5/255 more seam step. Also restate the light as a positive property in every beat |\n| A location introduced mid-plan drifts | It has no place plate of its own | Plate it, on the hop it arrives and every hop after |\n| A prop or garment changes colour or material | Named with no adjective, so each hop's encode is free to invent one | Repeat the adjective in every beat, and state it as a property in `context` |\n| A hard cut ~1.5 s into a hop, mid-scene | The previous hop over-delivered, so this beat instructs what its own live frame already did | One movement per hop; write the next beat so it is true from either ending |\n| A continuous join reads as a cut | Framing change with `camera: hold` | Earn it on the move, or `framing: keep` |\n| The run stops, naming a reference | That row's picture is not in `h3_refs` | Drop the file on the row, or clear its picture to run without it |\n| A reference has no effect on some hop | Its `shots` list leaves that hop out | List every hop the picture should ride |\n| A deliberately dark scene keeps being brightened | `anchor` cannot tell intent from drift | `\"tone\": \"rebase\"` on that scene's first shot |\n| You cannot tell which hop broke | 114 s is a lot to scrub | `contact_sheet=on` -- one row per hop, first and last frame |\n| A pasted plan is rejected as invalid JSON | Escaped double quotes mangled in transit | Single quotes around dialogue |\n\nEvery error message names the shot or the reference it came from. Nothing\nguesses."
1341
  ],
1342
  "color": "#432",
1343
  "bgcolor": "#653"
@@ -1389,7 +1389,7 @@
1389
  "htc_card": "author"
1390
  },
1391
  "widgets_values": [
1392
- "## Let a model write your plan\n\n`prompt_pack/` in the pack folder turns any chat model into a plan writer. In\nLM Studio, or anything with a system-prompt box:\n\n1. Load a model with **context 16384 or more**. The prompt is ~4,700 tokens and\n the reply another 1,000-2,000; a small window truncates the rules and you get\n invented directive names.\n2. Paste **`prompt_pack/SYSTEM_PROMPT.md`** into the **System Prompt** box.\n Nothing else goes in that box.\n3. **Temperature 0.3-0.5.** Higher and the JSON grows trailing commas and smart\n quotes.\n4. Describe the scene, and say how many hops and what pictures you have:\n\n > Six hops. A cook in a kitchen; she says one line, walks out into a hallway,\n > waits by a window, then comes back. I have a face photo, a photo of her\n > apron, and a photo of the kitchen.\n\n5. Each panel section has its own **JSON** disclosure at the bottom. The first\n ```json``` block goes in the one under **SCRIPT** (`shot_plan`), the second\n in the one under **REFERENCES** (`ref_plan`). Bad JSON keeps the last good\n version on screen and says so, rather than discarding your paste.\n6. **If the node rejects it, paste the error straight back into the chat.** One\n round trip usually fixes it.\n\nWant it to match a shape? Paste `prompt_pack/EXAMPLE_6_HOP.md` first.\n\nSmall models (7B-8B) hold the JSON schema but drift on the prose rules -- they\nwrite negations. Skim the beats before queueing.\n\n## Fixing one hop without re-rendering the rest\n\nSet **`cache_hops` to `on` before your first run.** It is off by default, and a\nhop that was never cached cannot be reused. Nothing to install.\n\nThe cache key **chains**, so editing shot 5 of 8 re-renders 5 to 8 and reuses 1\nto 4 off disk. Hop 6 was rendered *from* hop 5, so it has to. **Edit the\nearliest hop you dislike and work forward** -- that way each hop is paid for\nonce.\n\nAnything chain-wide re-renders everything: resolution, aspect, overlap, sampler,\nscheduler, either shift, `ref_image_size`, `pin_to_qwen`, the LoRA stack, or\n**any reference picture** (keyed on pixels, so a re-crop counts even under the\nsame filename). That is the usual reason the cache looks broken.\n\nLoved a hop? Put `\"locked\": true` and a stable `\"id\"` on that shot and it keeps\nthat exact take even when its inputs move. Unrelated to `subjects.N.locked`,\nwhich is identity text.\n\nFull detail in `PROMPTING.md`, under *Re-rolling one hop*."
1393
  ],
1394
  "color": "#432",
1395
  "bgcolor": "#653"
 
1259
  "htc_card": "rules"
1260
  },
1261
  "widgets_values": [
1262
+ "## The rules that decide whether it works\n\nNot style preferences. This is how this model fails.\n\n### 1. The prompt is additive\n\nSampling runs at **cfg 1.0 with no negative branch**. Every concept you name is\nadded, and nothing can be removed by mentioning it -- `no cut` puts the word\n*cut* in front of the encoder. **Never write a negation.**\n\n### 2. Never name the thing you want to end\n\n\"The cook stops talking\" keeps her talking. Write the state you want as **a pose\nplus a sound**:\n\n> leans back against the counter with her lips closed, and lets her eyes move\n> slowly across the room. The kitchen is quiet apart from the low hum of the\n> refrigerator.\n\nAudio is always generated. Silence written as an absence comes back as speech,\nso **silence has to be written as a sound** -- room tone, a fridge, a single\nclick. Keep it narrowband: \"faint street noise\" renders as a five-second hiss.\n\n**The ban is on the idea, not on a word list.** *Fades, passes, wanes, subsides,\ndies down, eases off* all name an ending as surely as *stops* does, and all of\nthem add the thing they describe. Ask of each sentence: is this happening, or\nhas it finished happening?\n\n### 3. A state change belongs at the END of the previous shot\n\nEvery hop opens holding the frames it was handed, and the audio pin carries the\nprevious hop's tail across the join. Nothing you write in shot 3 can make shot 3\nstart quiet. **Arrive there before the previous shot ends.**\n\n### 4. A hop that ends on dialogue keeps talking\n\nSpeech at the end of hop N opens hop N+1 and propagates down the whole chain.\nLand each line **mid-hop** and leave a non-verbal action running into the seam --\nslicing, walking, a hand on a doorframe. Give every hop with no dialogue a sound\nbed of its own.\n\n**A hop's own opening needs one too.** If anything happens before the first\nspoken line -- walking in, sitting down, turning to camera -- name the sound\nthose seconds carry. Frames with a picture and no audio assigned come back as\ndialogue nobody wrote, and ending the *previous* hop quiet does not cover it:\nthat buys you a quiet pin, not a quiet opening.\n\n### 5. A walk between two rooms is `match_cut`\n\n`join: continuous` across a real location change makes the model morph one room\ninto the other mid-movement.\n\n### 6. Set `tail` on your last shot\n\nLeft at `ongoing`, the model is told action is still underway at the final frame\nand will invent something to satisfy it. Use `settle` or `hold`."
1263
  ],
1264
  "color": "#432",
1265
  "bgcolor": "#653"
 
1337
  "htc_card": "trouble"
1338
  },
1339
  "widgets_values": [
1340
+ "## When it goes wrong\n\n| symptom | cause | fix |\n|---|---|---|\n| The clip cuts to the reference photo in its last seconds | The beat finished before the frames did | Set `tail`, give the beat enough to do |\n| A stray gesture or line in the closing second | `tail: ongoing` on the final shot | `settle` or `hold` |\n| She keeps talking after you asked for quiet | You named the ending | Pose plus a sound |\n| Dialogue continues into hops that have none written | The hop before ended on speech | Land the line early; non-verbal action into the seam; a sound bed on every quiet hop |\n| A character walks between two rooms and one morphs into the other | `continuous` across a location change | `match_cut` |\n| A burst of invented dialogue over a hop's opening action | The beat speaks later, so the opening seconds have a picture and no sound assigned | Name what those seconds sound like -- footsteps, room tone -- before the line |\n| Silence renders as speech | Silence written as an absence | Name room tone, a fridge, a distant car |\n| Ambience is a five-second hiss | Broadband wording | Narrowband, or one discrete event |\n| Two characters' faces merge | Both declared as the same `subject` | One subject number per person |\n| The face becomes a different person partway through | A hop scheduled with no face plate. `locked` holds a face that is still right; only a plate rebuilds one that is gone, and the drift never self-corrects | Put the face ref on **every** hop |\n| A stylised plan renders photoreal | The node's hop-1 establishing line asserts live action | Name the medium in shot 1's first sentence, or clear the `establish` widget |\n| The film gets darker every hop | Each hop dims across its own frames and hands the darker tail on. Seam correction cannot see it | `tone_compensate=anchor`. `tone_anchor=0.35` removed ~60% of measured drift; 0.6 removes ~78% and costs ~0.5/255 more seam step. Also restate the light as a positive property in every beat |\n| A location introduced mid-plan drifts | It has no place plate of its own | Plate it, on the hop it arrives and every hop after |\n| A prop or garment changes colour or material | Named with no adjective, so each hop's encode is free to invent one | Repeat the adjective in every beat, and state it as a property in `context` |\n| A hard cut ~1.5 s into a hop, mid-scene | The previous hop over-delivered, so this beat instructs what its own live frame already did | One movement per hop; write the next beat so it is true from either ending |\n| A continuous join reads as a cut | Framing change with `camera: hold` | Earn it on the move, or `framing: keep` |\n| The run stops, naming a reference | That row's picture is not in `h3_refs` | Drop the file on the row, or clear its picture to run without it |\n| A reference has no effect on some hop | Its `shots` list leaves that hop out | List every hop the picture should ride |\n| A deliberately dark scene keeps being brightened | `anchor` cannot tell intent from drift | `\"tone\": \"rebase\"` on that scene's first shot |\n| You cannot tell which hop broke | 114 s is a lot to scrub | `contact_sheet=on` -- one row per hop, first and last frame |\n| A pasted plan is rejected as invalid JSON | Escaped double quotes mangled in transit | Single quotes around dialogue |\n\nEvery error message names the shot or the reference it came from. Nothing\nguesses."
1341
  ],
1342
  "color": "#432",
1343
  "bgcolor": "#653"
 
1389
  "htc_card": "author"
1390
  },
1391
  "widgets_values": [
1392
+ "## Let a model write your plan\n\n### From the node\n\nOpen **WRITE**. Point it at any OpenAI-compatible server -- LM Studio,\nllama-server, anything serving `/v1/chat/completions` -- pick a loaded model,\nsay what you want in plain language, and press **Write plan**. It fills SCRIPT\nand REFERENCES for you, and the pictures already on your REFERENCES rows go\nwith the request, so the model describes what it is actually looking at.\n\n- **Context 32768.** The system prompt alone is ~6,000 tokens, the reply another\n 1,000-2,000, and every reference picture costs ~260 on top.\n- **Reasoning off.** Thinking tokens come out of the same budget; a reply that\n stops before the JSON closes is the tell.\n- **Temperature 0.3.** Higher and the JSON grows trailing commas and smart quotes.\n\nServer settings are saved on this machine only, never in the workflow, so a\nshared `.json` never points at your server.\n\n**Treat the result as a strong draft, not a finished plan.** Two things are\nworth reading every time: each reference's `desc`, which can be confidently\nwrong about its own photograph, and the spoken words in every beat.\n\n### By hand, in a chat window\n\n`prompt_pack/` turns any chat model into the same writer:\n\n1. Load a model with **context 32768**, for the reasons above.\n2. Paste **`prompt_pack/SYSTEM_PROMPT.md`** into the **System Prompt** box.\n Nothing else goes in that box.\n3. **Temperature 0.3-0.5.**\n4. Describe the scene, and say how many hops and what pictures you have:\n\n > Six hops. A cook in a kitchen; she says one line, walks out into a hallway,\n > waits by a window, then comes back. I have a face photo, a photo of her\n > apron, and a photo of the kitchen.\n\n5. Each panel section has its own **JSON** disclosure at the bottom. The first\n ```json``` block goes in the one under **SCRIPT** (`shot_plan`), the second\n in the one under **REFERENCES** (`ref_plan`). Bad JSON keeps the last good\n version on screen and says so, rather than discarding your paste.\n6. **If the node rejects it, paste the error straight back into the chat.** One\n round trip usually fixes it.\n\nWant it to match a shape? Paste `prompt_pack/EXAMPLE_6_HOP.md` first.\n\nSmall models (7B-8B) hold the JSON schema but drift on the prose rules -- they\nwrite negations. Skim the beats before queueing.\n\n## Fixing one hop without re-rendering the rest\n\nSet **`cache_hops` to `on` before your first run.** It is off by default, and a\nhop that was never cached cannot be reused. Nothing to install.\n\nThe cache key **chains**, so editing shot 5 of 8 re-renders 5 to 8 and reuses 1\nto 4 off disk. Hop 6 was rendered *from* hop 5, so it has to. **Edit the\nearliest hop you dislike and work forward** -- that way each hop is paid for\nonce.\n\nAnything chain-wide re-renders everything: resolution, aspect, overlap, sampler,\nscheduler, either shift, `ref_image_size`, `pin_to_qwen`, the LoRA stack, or\n**any reference picture** (keyed on pixels, so a re-crop counts even under the\nsame filename). That is the usual reason the cache looks broken.\n\nLoved a hop? Put `\"locked\": true` and a stable `\"id\"` on that shot and it keeps\nthat exact take even when its inputs move. Unrelated to `subjects.N.locked`,\nwhich is identity text.\n\nFull detail in `PROMPTING.md`, under *Re-rolling one hop*."
1393
  ],
1394
  "color": "#432",
1395
  "bgcolor": "#653"