Comic outline creator
Skill wanshuiyin/ARIS-Movie-Director/skills/comic-outline-creator
Agentic, long-horizon visual generation: a fuzzy story → a cross-model-audited image-based movie. Brings ARIS's research-wiki + multi-agent debate to multimodal generation (intelligence lives in the agent; the diffusion model just renders). Image-based today, video next.
npx -y skills add wanshuiyin/ARIS-Movie-Director --skill comic-outline-creatorAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
What its author says it does
Copied from the file, not written here
Phase-1 Layer-2 of a comic — turn a LOCKED skeleton (intent_spec + the pre-locked beat/shot list) into an approved outline_spec: a 6-column beat table that binds every ARIS capability to a STORY COST, plus the continuity-motif contract the storyboard layer will be held to. NOT free creation — editorial adaptation of a pre-locked skeleton via 3 parallel lenses → cross-model (Codex) synthesis → a density/restructure pass → a USER-approval HARD GATE. Cross-model synthesis is part of authoring here, not post-review. Author the comic.json downstream with comic-storyboard-creator + comic-blueprint-author; this skill only produces the outline + motif contract.
SKILL.md
37.7 KB, as published. Nobody here has run it
comic-outline-creator — the Outline + Motif Contract (Phase 1, Layer 2)
The middle-left of Figure 1: take a locked intent_spec (+ the pre-locked beat/shot skeleton it
carries — OR, for an idea-first comic with NO pre-locked skeleton, the 3 lenses first synthesize a beat
skeleton from the intent's logline / subjects / constraints / format, then adapt it the same way; the
synthesized skeleton is recorded so the deltas-vs-skeleton discipline still applies) and produce a single
approved outline_spec — the 6-column beat table that drives the
storyboard, and the continuity-motif arcs that become the storyboard's checkable contract. This is the
comic twin of aris_movie's movie-outline-creator (a Layer-2 authoring-time plan gate before any
pixels), specialized for our image-comic route: the deliverable is a plan, never a frame.
Two things are simultaneously true, and the whole skill is built around them: (a) the outline is NOT a free brainstorm — it is an editorial adaptation of a pre-locked skeleton (N beats / M shots, beat boundaries fixed), so every candidate must self-report its deltas vs the skeleton; (b) an unbounded "ARIS capability showcase" silently rots into a product manual unless every capability is bound to a concrete story cost and skill-name tags are banned from the 画面. The 3-lens → Codex-synthesis → density-pass → user-approval loop turns (a) into a faithful, debated outline and the 侧栏讲解铁律 + the gate catch (b) every round.
intent_spec (logline + tagline + dual-identity + LOCKED skeleton)
│
▼ ① FAN-OUT: 3 parallel named lenses over the SAME skeleton (faithful ∥ comicnative ∥ clarity)
│ each ends with a self-authored "through-line + deltas vs the skeleton" section
▼
② SYNTHESIZE — Codex (different model family) reconciles the 3 → OUTLINE v2
▼
③ DENSITY/DESIGN pass — Codex MAY restructure panel count (e.g. centerpiece 4→5 pages, +mid-act page)
│ AUTHORS the 侧栏讲解铁律 (anti "product manual" guard)
▼
④ Emit the 6-column BEAT TABLE + the centerpiece sub-plan + the 5 motif arcs (exact per-shot values)
▼
⑤ READINESS gate (PRE-user, cross-model, blind to orchestrator prose) — scores ONLY the author-controllable
│ dims; EXCLUDES user_decision_record + the unresolved-questions veto (those are not yet satisfiable).
│ Two-step (never cold): write review:* nodes + `reviews` edges → THEN comic-cross-layer-gate <id> --gate outline
▼ readiness:advance
⑥ USER APPROVAL = HARD GATE — present; record ✅ APPROVED + fill 已定决策 + EMPTY 待确认 block
│ THEN the FINAL gate (now user_decision_record==5 IS satisfiable) → write outline_spec node (locked)
│ revise ─▶ ② (bounded: MAX_OUTLINE_REVISIONS=3 → auto-abandon → failure_mode node)
▼ approve + signed
outline_spec (locked) → SOURCE OF TRUTH for the storyboard layer
│
▼ (much later, orchestrator-owned) OUTLINE_FINAL_LOCK — after the asset layer locks, a cheap
re-check that the locked assets still match this approved outline (N1 two-stage; §EXACT gate)
Constants
- LENS_COUNT = 3, mandatory (
faithful,comicnative,clarity) — Tier-1 Workflow fan-out (fan-out-pattern). Fewer than 3 lenses is a hard veto. - SYNTHESIZER =
mcp__codex__codex,model_reasoning_effort: xhigh— a different model family from the Claude lens authors. Codex both reconciles the 3 candidates AND runs the density/restructure pass; the outline layer is itself a cross-model artifact (executor ≠ reviewer,reviewer-independence). - GATE REVIEWERS =
mcp__codex__codex(NO model pin — follows the local codex config, currentlygpt-5.6-sol— atxhigh) ‖ Gemini (auto-gemini-3, readability dims) — each sees ONLYoutline_spec.json+intent_spec.json(the skeleton) + the lens files, never Claude's prose. They do not acquit; they each persist areview:<slug>node (payload{target_node_id, reviewer, gate_kind: "outline", review_scores:{...}}) with areviewsedgereview:<slug> → <outline_id>, and the SOLE acquittal organcomic-cross-layer-gate--gate outlinethen fuses those score-nodes (D4: never invoke the gate cold — write the reviews FIRST, then call the gate). - THE GATE IS RUN TWICE BY THIS SKILL (the user-approval deadlock fix): a READINESS pass BEFORE user
approval (scores only the author-controllable dims; the gate's own
user_decision_record == 5floor and the unresolved-questions veto are not yet satisfiable, so the readiness reviewers explicitly omit them), then the FINAL pass AFTER the user signs + the待确认block is emptied (nowuser_decision_record == 5IS satisfiable). See §EXACT gate. A THIRD, later touch — OUTLINE_FINAL_LOCK — is owned by the orchestrator, not this skill: after the asset layer locks (provisional storyboard → asset gen/review), a cheap re-check that the locked assets still match the approved outline (§EXACT gate → the N1 two-stage contract). - MAX_OUTLINE_REVISIONS = 3, then auto-abandon → write a
failure_modenode so a re-run must diverge. Its payload is exactly whatvalidate_wiki.pyPAYLOAD_REQUIRED demands forfailure_mode:{"layer": "outline", "affected_shot_ids": [<the abandoned skeleton shots, e.g. all S01..SMM>], "active": true}(node_idfail:<slug>, node_typefailure_mode, statusactive). There is NOencoding_stylefield in the schema — carry the "a re-run must diverge" positive-invariant intitleor a non-required note, never a fabricated required-looking key; the node must passcli/validate_wiki.py. - MAX_DRAFT_ATTEMPTS = 3 — schema-repair loop for the
outline_specnode; on each fail,codex-replyquoting the validator errors verbatim. Never silently coerce a value to pass schema (change the narrative + document it, or surface to the user). - TARGET_PAGE_CEILING (soft cap, exceed ⇒ Codex must justify in
rationale.beat_count_justification, not a hard stop):mvp=2,demo=6,longform=12beats per tier (ported fromMAX_BEATS_PER_TIER). - MIN_CAST_PER_BEAT = every beat names ≥1 world/scene + the cast in it (text-panel beats: a
text-panel scene + its world). Ported from aris_movie's
MIN_ASSETS_PER_BEAT=2; a structural check JSON-Schema can't express. - NODE =
outline_spec(this skill readsintent_spec, writes oneoutline_spec). See §Node. - APPROVAL IS NON-AUTOMATABLE — the loop can DRIVE to a clean gate, but only the user ACQUITS the
outline (
acceptance-gate). Nothing proceeds to the storyboard layer until the user signs off, recorded inline.
Input contract — what this skill reads, what it must not invent
The contract boundary is the intent_spec node (§Node) — produced upstream by
comic-intent-parser, carrying: the logline (a single sentence whose climax may be an editorial
inversion — e.g. "the climax is NOT winning — it's that ARIS didn't let itself off the hook"); the
tagline; the dual_identity constraint ("an emotional story of honest research + an ARIS capability
showcase") the whole debate optimizes against; and the source_skeleton — the pre-locked beat list
(B01…BNN), shot list (S01…SMM), and beat boundaries. The skeleton is LOCKED; this skill ADAPTS it,
never re-derives it.
This skill is plan + verify: it never bakes a pixel (image gen is comic-director / Phase 2-3) and
never invents a beat boundary or a shot. Adding a page (a density-pass split) is allowed and must be
accounted for in the deltas; moving a beat boundary or dropping a shot is a delta that must be justified +
surfaced to the user. If intent.status != locked → REFUSE (the upstream hand-off token is locked =
approved + frozen; an under_review/draft intent is not ready — re-run comic-intent-parser to its user
gate). If the skeleton is missing → REFUSE and ESCALATE (do not fabricate one).
Procedure (an agent can execute this step by step)
0. Load + refuse-guard
Snapshot the intent_spec node. Pull cumulative wiki context: prior LOCKED assets (for reuse-over-invention),
and failure_mode nodes with layer="outline" (rejected/superseded outlines — a re-run must diverge from
them). Refuse if intent.status != locked (the upstream author-node hand-off token is locked, not active).
Checkpoint an OUTLINE_STATE.json (resumable —
resumable-runs).
1. FAN-OUT — write 3 parallel candidate LENSES over the SAME locked skeleton
This is Tier-1 Workflow fan-out (fan-out-pattern): three
independent passes, each a named lens over the identical skeleton, NOT three free drafts. Write each to its
own file (story/outline_candidate_{faithful,comicnative,clarity}.md). The three lenses are fixed:
faithful— one-to-one fidelity: M shots → M panels, no cut / merge / add, beat boundariesB01…BNNpreserved exactly. The conservative anchor (palette grammar + stamp mirrors live here).comicnative— comic-as-a-medium: collapse runtime / motion shots into static-friendly pages (in our runS07-S09 → one 2×2 page;22 shots → 12 panels); choose afull-bleed / 2-up / 2×2page-rhythm for scroll-reading.clarity— legibility for a non-ML reader: foreground the through-line so the headline number-arc (in our run+6.2 → +1.4) is readable via one concrete physical prop (theTok|yobroken-JSON evidence) + one wordless emotional gauge (executor bounce height).
Each candidate MUST end with a self-authored section: ## through-line + deltas vs the skeleton stating
exactly what it merged / added / kept and why (e.g. "merged S07-S09 → one 2×2 page (motion is
redundant in a static page); kept all 13 beats; moved Tok|yo's first plant earlier to B06-S09 as a
re-pointable物证"). A candidate with no deltas section is a hard veto — delta-accounting is the
discipline that proves it is an adaptation, not a guess.
2. SYNTHESIZE — Codex reconciles the 3 → OUTLINE v2
Call the SYNTHESIZER (different model family). Feed it the three lens files + the intent_spec +
schemas/node_schema.json's outline_spec shape, inside a demarcated === EXTERNAL CONTEXT (advisory) ===
fence; Claude's prose lives ONLY in that fence (reviewer-independence).
The synthesis takes the best of each lens — in our run: faithful's two-world WARM/DARK palette grammar
- the REJECT↔ACCEPT mirror,
comicnative's page-rhythm,clarity's motif arcs + countdown spine. Emit{outline, rationale}.
3. DENSITY / DESIGN pass — Codex MAY restructure panel count
Codex then does a density / design pass that may materially change panel count where the read demands it
(in our run: the centerpiece B08 went 4 panels → 5 single-read pages by adding an "audit entry" panel,
with the 2×2 kept only as recap/hero/GitHub-screenshot; and a new mid-act page B09.5 "research
star-map / wiki" was added after the audit, before the paper — flagged as "the most powerful position";
panel count moved 22 → ~24). This pass also AUTHORS the 侧栏讲解铁律 (step 6). Adding pages is fine;
account for every one in the deltas.
4. Emit the 6-column BEAT TABLE
Emit the canonical table — fixed columns, in this order:
| Beat (zh/en) | Panels | 布局/layout | 世界/world | 内容 + 台词 gist | ARIS 特性(绑剧情)|
- Beat — bilingual id + name (
**B01 卧室·倒计时**). - Panels — the shot ids it OWNS (
S01·S07,S08,S09大·S12-15 + 新增 S12a). - 布局/layout token ∈ {
full-bleed,split,2-up,1-panel,竖排3,5单张页(默认)/2×2 recap}. - 世界/world token ∈ {
暖/WARM,暗/DARK,seam,暗·星空/starfield} — human beats warm, ARIS beats dark-cyber, explicit seam panels at hand-off / payoff. (The warm/cold split is by-design — the downstream gate must never flag it as drift.) - 内容 + 台词 gist — panel action + baked-dialogue gist + a one-line side-narration (旁白).
- ARIS 特性(绑剧情) — the bound capability, phrased as a STORY COST, never a feature name
(✅
experiment-bridge(证据是暂定的)·honest re-run(自纠 overclaim)·auto-review-loop(对抗审); ❌experiment-audit,novelty-checkas bare tags). A bare feature name here is a hard veto.
5. Centerpiece sub-plan (the densest beat)
For the centerpiece beat, emit a sub-table | 页/page | 画面/image | 侧栏(先讲发生了什么,再点能力)| with the
verbatim 70/30 composition rule:
每页:技术主画面 70% + 角色情绪 30%(右下角蓝 exec bounce 当体温计)+ 侧栏讲解。
Each row's 侧栏 puts the event-sentence first, then · *trait: <skill>* second (so the side-narration
reads as story, then footnotes the capability).
6. Embed VERBATIM the 侧栏讲解铁律 (the anti "product-manual" guard)
This block is load-bearing — copy it verbatim into the outline (it is what stops a capability showcase from rotting into a product manual):
🎙️ 侧栏讲解铁律(防止"能力展示"变产品手册 —— codex)
- 每条能力必须绑一个剧情代价:不写"ARIS has experiment-audit",写"executor 的庆祝被审计打断,所以 ARIS 没撒谎"。
- 侧栏第一句永远讲发生了什么;第二句才点能力名。
- 每个能力都改变角色状态(bounce 高低 / 咖啡冷掉 / 红队介入 / claim 被降级)。
- 画面里不堆 skill 名标签;skill 名只作侧栏小字或 hover/click metadata。
7. Lock the continuity-motif arcs AT OUTLINE TIME (exact per-shot values)
The outline doubles as the continuity contract — the storyboard's motif-state table and the panel/assembly gates will be checked against these arcs, so they must carry exact per-shot values now. Lock the 5 arcs (our run's values, as the worked pattern):
- mug heat:
STEAMING(S01) → fading(S03) → COLD(S20)— B01/B12 bookend. - executor bounce (wordless emotion thermometer):
MAX(S02) → HIGH(S09) → DROP(S11) → ZERO/SILENT(S12–S15, arc low point) → tempered-return(S16) → smallest-warm(S21). (Storyboard will add the uniqueness invariant "S02 是全片唯一 MAX"; no post-fall peak.) - Tok|yo broken-JSON evidence:
born/first-plant(B06-S09) → smoking-gun(B08) → clean footnote(S17) → faint constellation star(S22). - DDL countdown spine:
24:00:00 → ~19:00 → 00:42— strictly monotonically non-increasing across the whole film (storyboard enforces; never rewinds). - REJECT(S11) ↔ ACCEPT(S16): deliberate mirror stamps so the centerpiece audit reads as the hinge between them.
8. Write the 6-column table + sub-plan + 铁律 + motif arcs to story/OUTLINE_DRAFT.md
Add a top-of-file Logline + Tagline + 双重身份 block (mirroring the intent), an empty ## ✅ 已定决策 block,
and an ## ⚠️ 待你确认 block listing every open design question (e.g. centerpiece 5-page split OK? new
mid-act wiki page OK? 侧栏铁律 OK?).
9. READINESS gate — PRE-user, cross-model, blind (NOT the final gate)
This is the author-controllable gate, run before the user has decided anything. By construction the
artifact from step 8 has an empty 已定决策 + a non-empty ⚠️ 待确认 block and no user sign-off —
so the FINAL gate's user_decision_record == 5 floor and its "open questions unresolved but advancing" veto
are not yet satisfiable. Applying the full conjunctive APPROVE rule here would deadlock a fresh agent
(stall, or fabricate a user approval). So the readiness pass scores only the dims the author controls and
explicitly EXCLUDES user_decision_record + the unresolved-questions veto (see §EXACT gate → READINESS).
Run it as a two-step gate invocation (D4 — never call the gate cold):
- Fan out the GATE REVIEWERS (Codex at
xhigh, no model pin ‖ Geminiauto-gemini-3) on the files only (outline_spec.json+intent_spec.json+ the lens files, inside the advisory fence — no orchestrator prose). Persist EACH as areviewnode:node_id review:<slug>(e.g.review:outline_codex_r1), node_typereview, payload required{target_node_id: <outline_id>, reviewer: "codex"|"gemini", gate_kind: "outline", review_scores:{skeleton_fidelity:…, delta_accounting:…, coverage:…, page_rhythm_readability:…, story_cost_binding:…, motif_contract_completeness:…, safety_ip:…}}— and write areviewsedge{src: review:<slug>, dst: <outline_id>, type: "reviews"}(the gate walksreviewsedges in;reviewed_byis the wrong direction and the fuser won't find it). - THEN invoke
comic-cross-layer-gate <outline_id> --gate outlineto fuse the score-nodes + adjudicate. (This is the OUTLINE_DRAFT_VALID stage: on a fresh outlineidentity_lock_feasibility/scene_lock_feasibilityare unscorable — no assets exist — so the reviewers leave themnulland the gate SKIPs them, never 0-substitutes; the effective draft floor iscoverage ≥ 4 AND safety_ip ≥ 4. The readiness reviewers likewise leaveuser_decision_recordunscored. What IS checked here: every referencedasset_idis DECLARED with a complete, generatable request —lockedis NOT required until OUTLINE_FINAL_LOCK, after the asset layer.) On a FAIL verdict, fold the blockers and loop back to step 2 (bounded byMAX_OUTLINE_REVISIONS); on a clean readiness verdict, proceed to step 10.
Then schema-validate the (still-under_review) outline_spec node payload (cli/validate_wiki.py mirrors
node_schema.json); on a schema error, run the MAX_DRAFT_ATTEMPTS repair loop with codex-reply quoting the
errors verbatim. Also run the 2 structural checks JSON-Schema can't express: (i) coverage — every
intent.dual_identity "must-land" item and every skeleton beat maps to ≥1 table row; (ii) MIN_CAST_PER_BEAT
— every beat names ≥1 world + its cast. Do not flip to locked yet — that needs the user sign-off (step 10).
10. USER APPROVAL = HARD GATE → FINAL gate → then lock
Present the readiness-clean outline to the user. Nothing proceeds until they sign off. On approval:
- record inline
✅ APPROVED by user <date>(with their words, e.g.("都可以")), - fill the
## ✅ 已定决策(用户 <date>)block — every resolved open question becomes a recorded decision node (our run:B06-S09 → big panel;Tok|yo pre-plant → very small, narration does NOT spell it out;B13 constellation → pure glowing star-points, NO labels), - empty the
## ⚠️ 待你确认block (every open question is now in已定决策).
Now — and only now — run the FINAL gate (D4 two-step again): re-fan the GATE REVIEWERS on the
now-complete artifact, persist fresh review:<slug> nodes (this round CAN score user_decision_record,
since the sign-off + 已定决策 block + emptied 待确认 block exist) with reviews edges, then call
comic-cross-layer-gate <outline_id> --gate outline. The FINAL gate applies the full conjunctive APPROVE rule
(§EXACT gate → FINAL) including user_decision_record == 5, now satisfiable. On the gate's approve:
- the gate itself mints the
decisionnode (node_id decision:outline_<slug>, payload required{target_node_id: <outline_id>, verdict: "approve", gate_kind: "outline"}) + thedecidesedge and flips theoutline_specnodestatus: locked— that FLIP is the gate's job, not this skill's. (Never writestatus: lockedby hand without the gate'sapproveverdict node and the inline user sign-off.) - declare the file "SOURCE OF TRUTH for the storyboard layer."
Then hand off to comic-storyboard-creator for its PROVISIONAL structural pass (it inherits the locked beats
- the motif arcs as its continuity ledger). Asset generation/review, OUTLINE_FINAL_LOCK, and the storyboard's
FINAL asset-resolution validation follow —
comic-authorsteps 4–6b.
EXACT gate — this skill's PRE-gate rubric, fused by comic-cross-layer-gate --gate outline
Authority note (D3) — the N1 TWO-STAGE contract: the canonical APPROVE predicate + the status FLIP for the
outline gate are owned by comic-cross-layer-gate --gate outline,
and under the N1 DAG that gate runs in two stages:
- OUTLINE_DRAFT_VALID (this skill's readiness + final passes) — validates narrative + continuity +
safety only. It does NOT require any referenced asset to be
locked(on a fresh project assets don't exist yet); it requires every referencedasset_idto be DECLARED with a complete, generatable request. Because no locked assets exist, the gate-floor dimsidentity_lock_feasibility/scene_lock_feasibilityare unscorable at draft time: the reviewers leave themnull, the fuser SKIPs them (never 0-substitutes), and the effective draft floor reduces tocoverage ≥ 4 AND safety_ip ≥ 4— this is the explicit resolution of the dim-vocabulary gap (the reviewers here never score those two dims; nobody does until assets exist). - OUTLINE_FINAL_LOCK (orchestrator-owned —
comic-authorstep 6a, AFTER the asset layer locks) — a cheap re-check that the now-locked assets still match the approved outline;identity_lock_feasibility/scene_lock_feasibilityARE scored here, against real locked assets. The hard locked-asset barrier itself stays downstream, before blueprint authoring (comic-author steps 6b–7). This replaces the deadlocked single-stage contract (an outline gate demanding locked assets that depend on a storyboard that depends on a locked outline). The dims + verdict rules below are THIS skill's pre-gate routing (step 9 step-1 fan-out): the rubric the GATE REVIEWERS score into theirreview:<slug>nodes, and the local stop-rule this skill uses to loop/abandon before deferring to the fuser. They are not a competing gate — the cross-layer-gate fuses these score-nodes and makes the final call.
Each GATE REVIEWER scores these dims 0–5 seeing ONLY outline_spec.json + intent_spec.json (the
skeleton) + the lens files — no orchestrator prose:
skeleton_fidelity— beats / shots / beat boundaries from the locked skeleton are preserved or every change is an accounted delta (no silent re-derivation).delta_accounting— every candidate has adeltas vs the skeletonsection; the synthesized outline's added/merged pages are all listed and justified.coverage— everyintent.dual_identitymust-land item + every skeleton beat maps to ≥1 table row with the right cast inmust_show(the comic analog of aris_movie'scoveragedim).page_rhythm_readability— layout tokens give a real scroll-read rhythm; the centerpiece is single-read paced; non-ML reader can follow the headline arc (readability — Gemini co-scores).story_cost_binding— everyARIS 特性cell is phrased as a story cost that changes a character state, never a bare feature name.motif_contract_completeness— all motif arcs are locked with exact per-shot values (not "a recurring mug"); REJECT↔ACCEPT mirror + monotonic DDL declared.safety_ip— no celebrity likeness / copyrighted character / trademarked logo / off-policy content; anti-IPmust_avoidcarried into the style bible (HIGHER = better).user_decision_record— the✅ APPROVEDstamp +已定决策block (resolved questions as decision nodes) + an EMPTY⚠️ 待确认block are all present and consistent. Scored in the FINAL round ONLY — at step 9 it is not yet satisfiable, so the READINESS reviewers leave itnull(the fuser SKIPs anulldim, it does not 0-substitute).
READINESS verdict rule (step 9 — PRE-user; EXCLUDES the user dim + the unresolved-questions veto)
The author-controllable stop-rule the readiness fan-out routes on (this is what makes step 9 actually passable before the user has decided anything):
skeleton_fidelity >= 4 AND delta_accounting >= 4 AND coverage >= 4
AND story_cost_binding >= 4 AND motif_contract_completeness >= 4 AND safety_ip >= 4
user_decision_record is NOT evaluated here, and the "open questions unresolved but advancing" veto does
NOT apply at readiness (the ⚠️ 待确认 block is expected to be non-empty pre-user). Readiness-clean ⇒
present to the user (step 10).
FINAL verdict rule (step 10 — POST-user; the full conjunctive rule, now satisfiable)
skeleton_fidelity >= 4 AND delta_accounting >= 4 AND coverage >= 4
AND story_cost_binding >= 4 AND motif_contract_completeness >= 4
AND safety_ip >= 4 AND user_decision_record == 5
revise ⇐ any blocking dim < 4 but recoverable (loop to step 2, bounded by MAX_OUTLINE_REVISIONS=3).
abandon ⇐ safety_ip < 3 OR three consecutive revise rounds with the same root cause →
auto-abandon → write a failure_mode node whose payload is exactly the validator-required shape {"layer": "outline", "affected_shot_ids": [<abandoned skeleton shots>], "active": true} (node_id fail:<slug>, status
active; no encoding_style key — that is not a schema field).
Hard veto (any one → not APPROVE, regardless of scores):
- fewer than 3 lenses;
- any candidate with no
deltas vs the skeletonsection; - any
ARIS 特性cell written as a product-manual feature name instead of a character cost; - a skill-name in a 画面 main label (skill names allowed ONLY in side-narration small-text / hover metadata);
- open questions unresolved but advancing (FINAL round only — the
⚠️ 待确认block must be emptied into已定决策before the user can lock; this veto is intentionally OFF at readiness, see above); - motif arcs not locked at outline time (no exact per-shot values).
The loop can DRIVE to a clean gate, but the gate cannot ACQUIT — only the user can (
acceptance-gate). A clean cross-model readiness gate is necessary, the signed user approval is sufficient; both are required, and the FINAL gate is what mints theapprovedecision + flipsoutline_spectolocked.
Node — reads intent_spec, writes outline_spec
Per ../../schemas/node_schema.json (schema_version node/comic/3.0).
Reads intent_spec (node_id intent:<slug>) — payload required (verbatim from validate_wiki.py
PAYLOAD_REQUIRED): raw_input_refs, user_goal, audience, format, constraints, subjects, source_skeleton, dual_identity, uncertainties, confidence. Refuse unless its status == locked (the author-node hand-off
token is locked = approved + frozen, NOT active; comic-intent-parser's user gate is what flips it).
Writes one outline_spec (node_id outline:<slug> — matches the schema node_id pattern). Payload
required fields — every one of these (verbatim from validate_wiki.py PAYLOAD_REQUIRED for outline_spec)
must be present: source_intent_id, title, logline, tagline, design_constraint, target_page_count, narrative_beats, beat_table, motif_arcs, character_asset_ids, scene_asset_ids, prop_asset_ids, global_style_bible, budget:
source_intent_id— theintent:<slug>it adapts. Also write the provenance edge{src: outline:<slug>, dst: intent:<slug>, type: "derived_from"}(the author-layer "this node was authored/derived from that node" verb —derived_fromis invalidate_wiki.pyEDGE_TYPES;generated_fromis NOT and would FAIL the validator). The edge record itself must passcli/validate_wiki.py(both endpoints resolve to real node_ids; the type is in EDGE_TYPES).title,logline,tagline,design_constraint— carried from intent (the dual-identity constraint).target_page_count— withinTARGET_PAGE_CEILINGfor the tier, or justified inrationale.narrative_beats— the beat list with each beat'smust_show(cast/world per beat — enforcesMIN_CAST_PER_BEAT).beat_table— the 6-column table (the canonical render-source for the storyboard).motif_arcs— the 5 arcs with exact per-shot values (the continuity contract).character_asset_ids,scene_asset_ids,prop_asset_ids— flat lists of asset node_ids: prior LOCKED assets when one matches (reuse over invention), else newly DECLARED ids whose complete, generatable request the storyboard layer will consolidate (lockedis NOT required at the draft gate — the N1 two-stage contract; OUTLINE_FINAL_LOCK re-checks once they lock). Emit no new asset node here — that is the asset layer's job, wherereuse_oflives. (There is noreuse_offield onoutline_spec— the asset references are these three flat id-lists; don't carry the movie source'sasset_plan[].reuse_ofhere.)global_style_bible— pointer to the lockedART_BIBLE.md/style_anchornodes (incl. the warm/dark two-world palette + the anti-IPmust_avoid).budget— page/asset budget for the downstream layers.
Status lifecycle: draft → under_review → locked — locked flipped by the FINAL comic-cross-layer-gate --gate outline approve (after the inline user sign-off), or rejected / superseded. (active is a RUNTIME
status, never this author node's hand-off token.)
Fail-closed: never write status: locked without the gate's decision node verdict="approve" and the
inline user sign-off; never silently coerce a value to pass schema.
Two engine contracts the outline must SET UP (fail-closed, downstream)
The outline does not author blueprints, but it must make them authorable — so the centerpiece sub-plan
and any figure-bearing beat are spec'd so the downstream layers can satisfy these without re-litigating. (The
runtime field names below are the comic.json panel fields the engine reads — condition.content_svg /
condition.expected_literals — the only artifact that uses the condition. prefix; do not conflate with the
wiki nodes the downstream layers write, where the field is blueprint.payload.content_svg (top-level) and
panel_spec.payload.content_blueprint — there is no content_svg on a panel_spec.)
- Every panel will need a
condition.content_svg(a deterministic blueprint — figure or layout; the engine rejectscondition.content_svg: null, never write it null). So every figure-bearing beat in the table must name what the blueprint depicts (the curve, the gauge, the broken-JSON chip), not just "a screen" — the storyboard / blueprint authors instantiate the SVG, but the outline owes them a concrete subject. - A
text_mode:"baked"figure-panel will needcondition.expected_literals(exact numbers/keys, ascii-tokenizable, verbatim) — or the bake is refused. So every beat whose number is the point (+6.2,+1.4,0.60→0.71,REJECT,T-00:42) must surface that exact literal in the table's gist as the to-be-gated token; a beat with no audited number → its panel becomestext_mode: "html"downstream. The motif arcs (DDL, exact_parse, claim_delta) are precisely the literal source the gate will token-diff later.
Worked example
A converged, user-approved outline ships in
examples/comic_m3_audit/story/ — the ARIS-Movie comic "我把那 24
小时交出去了 / I Handed Over Those 24 Hours". The exact files to copy the shape from:
- The 3 lenses —
outline_candidate_faithful.md(22 shots → 22 panels, beat boundaries preserved, ends with "Through-line + deltas: one-to-one fidelity, …"),outline_candidate_comicnative.md(S07-S09 → one 2×2 page P06; 22 → 12 panels; full-bleed / 2-up / 2×2 rhythm), andoutline_candidate_clarity.md(Tok|yo prop + bounce gauge carry the +6.2→+1.4 story for a non-ML reader). Copy the pattern: three named lenses over the same skeleton, each closing with an explicitdeltas vs the skeletonsection. - The approved outline —
OUTLINE_DRAFT.md. Copy its exact shape:- header provenance line: "OUTLINE v2 — 3-lens debate → codex synthesis → codex design pass (B08 density + wiki) → user decisions. … ✅ APPROVED by user 2026-06-10 ('都可以') … Now the SOURCE OF TRUTH for the storyboard layer." — the whole lifecycle is recorded in one line;
- the
## ✅ 已定决策(用户 2026-06-10)block (3 resolved open questions as decision nodes: S09 big / Tok|yo tiny, narration doesn't spell it out / B13 unlabeled glowing star-points); - the verbatim
## 🎙️ 侧栏讲解铁律block; - the 13-row 6-column beat table (every
ARIS 特性cell is a story cost, e.g.experiment-bridge(证据是暂定的)); - the B08 5-page sub-plan with the 70/30 rule + event-first / trait-second 侧栏;
- the
## vs v1 的增量deltas (22 → ~24panels, +S12a +S16b) and the## ⚠️ 待你确认block.
Copy its shape; swap in your own logline / skeleton / cast.
Hard do / don't (earned lessons)
- DO treat the skeleton as locked and make every candidate self-report its
deltas vs the skeleton— adapt, never re-derive; a candidate with no deltas section is a veto. - DO write 3 lenses (faithful ∥ comicnative ∥ clarity) and let Codex (a different model family) synthesize + run the density pass — the outline layer is a cross-model artifact, not a solo draft.
- DO bind every capability to a story cost and embed the 侧栏讲解铁律 verbatim — this is the guard that stops a capability showcase from rotting into a product manual.
- DO lock the motif arcs with exact per-shot values at outline time — the outline is the storyboard's continuity contract; vague motifs make the downstream gate uncheckable.
- DON'T put a skill name in a 画面 main label — skill names live ONLY in side-narration small-text / hover metadata.
- DON'T advance to the storyboard with open questions unresolved — empty the
⚠️ 待确认block into已定决策first; resolved questions are recorded decision nodes. - DON'T batch ahead, and never draft (or proceed) without explicit user story approval — the user
is the only acquitter; record
✅ APPROVED <date>inline before locking. (Memory: never draft outline/storyboard without explicit user story approval; confirm intent → outline → storyboard layer by layer.) - DON'T bake or invent — this skill produces a plan; pixels are
comic-director's job, and a missing beat/shot is an ESCALATE, not a fabrication. - DON'T silently coerce a value to pass schema or to pass the gate — change the narrative + document it, or surface to the user.
Protocols (governance contracts this skill honors)
reviewer-independence— the Codex synthesizer + the gate reviewer get the lens files +intent_spec+ schema inside an=== EXTERNAL CONTEXT (advisory) ===fence, never the author's interpretation; the Claude lens authors ≠ the Codex synthesizer/judge.acceptance-gate— the loop can DRIVE to a clean cross-model gate but cannot ACQUIT; USER approval is the hard gate for the outline (never proceed without it), recorded inline as✅ APPROVED <date>+ the已定决策decision block.fan-out-pattern— the 3 lenses are Tier-1 Workflow fan-out (faithful ∥ comicnative ∥ clarity), all reconciled at the single Codex synthesis seat;<3lenses is a veto.reviewer-routing— Codex atxhigh(synthesizer + gate; NO model pin — it follows the local codex config, currentlygpt-5.6-sol); Geminiauto-gemini-3(optional readability co-reviewer); never downgrade the effort tier.review-tracing— every gate round's reviewer verdict + the user decision are logged asreview/decisionnodes so each verdict is auditable.output-versioning·resumable-runs— version the outline (_v{N}+supersedes);OUTLINE_STATE.jsonmakes the loop resumable.