Nodes/MiniMax H3 Novel Pipeline/Spatial Continuity
ComfyUI Node

Spatial Continuity

One JSON box that stops MiniMax H3 teleporting the furniture

By yuyuki·Created 28 days ago·Updated a day ago· 2
Spatial Continuity
    • spatial_continuity
    • anchor_summary
    ◄anchors_json{ "tablet.wall": "right wall", "main_rope.side": "right side of crevasse" }►

    This node runs no model, calls no API, and needs no GPU. It takes a small JSON dictionary of fixed spatial facts you type yourself and hands it to Generate H3 Prompts so the scene planner can't quietly move the wall.

    That sounds trivial. It's the boring half of the thing everyone actually complains about: an LLM plans your scenes, writes prompt #7, and the tablet chained to the right-hand wall in scene #3 is now floating somewhere on the left. Nothing in the pipeline remembers geometry, because every scene prompt comes out of text alone.

    Why you'd reach for it

    The famous version of this problem is character consistency - same face, same outfit, across forty generations. The spatial version is quieter and just as annoying. The crevasse you established in chapter one drifts, the rope switches sides, the room changes shape between shots, because the prompt LLM re-derives staging from whatever excerpt it's holding.

    "Spatial continuity" is the pack author's own coinage - the phrase barely exists in community discussion, where people talk about continuity between shots instead. The mechanism is the honest fix for it: you declare which relations are immutable, once, in plain English, and the model is instructed to treat them as ground truth forever after.

    How it works

    The node does three things. It parses your text as JSON, rejects anything that isn't a flat object with non-empty string keys and string values, and wraps it as {"schema_version": "minimax-spatial-continuity.v1", "anchors": {...}}. It also renders a plain-text anchor_summary, one key: value line each, so you can see what you typed without reopening the field.

    The real work happens downstream. Wire it into Generate H3 Prompts' optional spatial_continuity input and the generator runs one extra LM Studio request per scene before writing the prompt. That pass is framed as a "film spatial-continuity director" and told - per the shipped source - to treat your anchors as immutable even when currently offscreen, to carry the previous scene's final state into the current scene's initial state unless an event explicitly changes it, and to let the next five scenes constrain staging without letting their events happen early. Anything it assumes about geometry goes into an inferences list, never into the facts it read from your novel. It returns strict JSON (source_facts, inferences, initial_state, final_state, warnings) at low temperature, and each chapter folder gets a spatial_continuity.json holding your anchors plus the per-scene states - which then feed prompt generation, the repair pass and the optional camera-refinement pass.

    Inputs and outputs that matter

    • anchors_json - the only input, a multiline string, defaulting to a worked example (tablet.wall / main_rope.side). Write a flat object of stable, operator-approved relations: {"tablet.wall": "right wall", "main_rope.side": "right side of crevasse"}. The entity.attribute naming in that default is a convention rather than a requirement, but keys and values must both be non-empty strings, so {"tablet.distance": 3} fails validation.
    • spatial_continuity - the typed output you connect to Generate H3 Prompts' spatial_continuity input. Nothing else accepts this type.
    • anchor_summary - a plain string, one relation per line. Send it to a Preview Text node to sanity-check your entry; it's produced when the graph runs, not as you type.

    Keep the list short. Five to fifteen anchors that genuinely never change beats a hundred that are really per-scene staging.

    Install

    Easiest is ComfyUI Manager: search MiniMax H3 Novel, install, restart. By hand:

    cd ComfyUI/custom_nodes
    git clone https://github.com/yuyuki/minimax_h3_novel_pipeline.git
    python -m pip install -r minimax_h3_novel_pipeline/requirements.txt
    

    Use the Python that runs ComfyUI - the embedded one on a portable install. You need the whole repo (__init__.py, src/, web/), not just src/. Dependencies are light: openai>=1.0,<3, httpx>=0.27,<1, and pypdf if you feed it PDFs. Nothing GPU-shaped.

    The node is useless without the rest of the chain: LM Studio running locally with a loaded model, an API key in ComfyUI Settings → MiniMax H3 Novel → LM Studio (use lm-studio if auth is off), and an LM Studio Configuration node feeding Generate. Its model_family has to match what's actually loaded - Qwen or Mistral.

    Common issues

    "Invalid spatial anchors JSON" is nearly always a trailing comma, single quotes, or a value that isn't a string. Validate it elsewhere first.

    Don't anchor screen-relative wording. The continuity prompt explicitly warns that screen right is camera-relative - a fixed wall isn't screen-right once the camera rotates. Anchor world-side facts ("right wall", "north end of the clearing") and put the camera axis in Generate H3 Prompts' camera_direction if framing matters.

    Anchors steer an LLM, they don't solve constraints. Read the warnings and inferences in spatial_continuity.json - that's where the pass admits it guessed. The README says it plainly: check the actual generated video before treating a position as established.

    It costs one extra request per scene. On a twenty-scene chapter that's twenty serial LM Studio calls before a prompt gets written. Leave it disconnected while you iterate on planning and switch it on for the real run.

    Structured JSON is mandatory. A model that can't hold a schema fails the pass with "LM Studio returned invalid spatial continuity". Small Qwen and Mistral instruct models are the intended targets - and running the LLM locally is the point, since nothing here leaves your machine.

    CategoryMiniMax H3 Novel

    Inputs (1)

    NameTypeDefaultDescription
    anchors_jsonSTRING{ "tablet.wall": "right wall", "main_rope.side": "right side of crevasse" }—

    Outputs (2)

    NameTypeDescription
    spatial_continuityMINIMAX_SPATIAL_CONTINUITY—
    anchor_summarySTRING—