Comic director
Phase 2/3 of a movie — bake + cross-model-verify a movie from an authored comic.json. Per frame: render the content-SVG blueprint, bake via the agent mcp__codex__codex sidecar, gate with a 3-reviewer cross-model panel (narrative [currently the codex CLI] ‖ Gemini visual ‖ Codex visual, deterministic fuse), keep/retry/assemble, write the wiki trace, project to the viewer. The movie-side twin of method-figure's render half. (Author the comic.json first with the comic-author skill.)From its SKILL.md
npx -y skills add wanshuiyin/ARIS-Movie-Director --skill comic-directorAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- runs commandsInstructs the agent to run 2 commands, including `python3 skills/comic-director/scripts/run_comic.py` and 1 more.
SKILL.md
12.0 KB, ~3.2k tokens by cl100k_base, as published. Nobody here has run it
comic-director — the Audited Spiral + Release (Phase 2/3)
The middle + right of Figure 1: take an authored comic.json (produced by the
comic-author skill, Phase 1) and turn it into baked frames + a clickable
viewer, through the audited spiral. Per frame: render a deterministic content-SVG blueprint → bake a
pixel-art frame (agent mcp__codex__codex sidecar) → a 3-reviewer cross-model panel_gate → keep / retry → page assembly →
projection. The movie twin of method-figure's render half. (Image-based today; video-based is next.)
Input contract — comic.json (authored upstream)
The contract boundary is comic.json + the assets it references (content-SVG blueprints, identity refs,
ART_BIBLE.md) — authored by comic-author. This skill is render + verify:
- It never invents a number or a cast — faithfulness is a deterministic token-diff over reviewers who never see the expected values; identity is judged against the ref the author supplied (cast-aware).
- It writes back only
image_path/active_attempt_id/wiki_node_id(+ the wiki trace) on KEEP. - The generator family (Codex image_gen) can NOT self-acquit. A KEEP needs the token-diff clean and the cross-model visual panel (Gemini + Codex) to pass. The calling agent (Claude) gives the final structural sign-off.
Full IR spec: ../../docs/comic-json.md /
../../schemas/comic.schema.json.
Run it (scripts/run_comic.py — agent-driven bake, CLI gates)
A pure-stdlib faithful port of packages/core/spiral_engine.js's movie branch. The cross-model gates
(Gemini + Codex vision) still shell the gemini / codex CLIs directly. The BAKE is performed by the
skill agent via the mcp__codex__codex MCP tool through --bake-mode=agent (the default): the core
emits a deterministic bake-request sidecar (prompt + absolute ref paths + exact out_path), the agent calls
mcp__codex__codex (sandbox: workspace-write, model: gpt-5.5, config: {model_reasoning_effort: xhigh, include_image_gen_tool: true},
cwd: <project>), and the core verifies the explicit out_path. (codex exec is RETIRED for real bakes — it
forced a hand-drawn SVG/struct+zlib fallback; --bake-mode=exec RAISES if it ever reaches a real bake. See
docs/spiral-runtime.md.)
python3 skills/comic-director/scripts/run_comic.py \
--project examples/comic_m3_audit --page P02_b08 --panels S12,S13,S14,S15 \
[--bake-lang zh] [--finalize] [--dry-run] [--skip-assembly] \
[--gemini-cmd "python3 cli/gemini_agy_shim.py"] [--gemini-family google]
--dry-runvalidates + prints each frame's concrete bake prompt (no image_gen) — run this first; it's also howcomic-authorconfirms Phase 1 is correct.--finalizerebuilds the single-file viewer (packages/viewer/build_comic.py) only if the run is shippable (nothing escalated/throttled/flagged-for-human; assembly accepted).--gemini-cmd(default: the legacygeminiCLI) — the argv prefix shelled for the google-family reviewer slot (the--model auto-gemini-3 -p <prompt>tail is appended). With the legacy CLI deprecated upstream (IneligibleTierError, 2026-07), pass--gemini-cmd "python3 cli/gemini_agy_shim.py"— the shipped shim translates the old interface to Antigravity'sagyand pins a Gemini model (Antigravity also serves Claude/GPT-OSS; the slot must stay google-family for cross-model quorum honesty).--gemini-family(defaultgoogle) — the provenance family recorded in the wiki for whatever--gemini-cmdactually routes to. It must stay non-openai(the visual quorum needs a second family); record honestly, never re-label.- Needs the
codexCLI + a google-family reviewer (legacygeminiCLI, or Antigravity via--gemini-cmd+ the shim) on PATH + headless Chrome (to rasterize the content-SVG blueprint). Reusesskills/method-figure/scripts/pickup_image.py.
It prints a JSON run-report (kept, flagged_for_human, needs_human, shippable, throttled,
escalated, assembly, attempts_per_panel). Engine semantics it ports (caps 4/panel + 6/run, the
deterministic verdict, anatomy single-vote veto, throttle → fresh-run): ../../docs/spiral-runtime.md.
Bake seam contract (agent ↔ core) — --bake-mode=agent
The bake is a synchronous sidecar handshake (contract-v2 §1–§4). The core never returns/exits early on a
bake; only the bake primitive moved off codex exec onto mcp__codex__codex:
- (A) core writes
<out>.bakereq.json={prompt_text, content_png, identity_ref, out_path, model:"gpt-5.5", config:{model_reasoning_effort:"xhigh", include_image_gen_tool:true}, sandbox:"workspace-write", cwd, created_at, min_bytes:500000, aspect, request_id:"<uuid4 hex>"}(prompt_textALREADY contains the absolute ref + out paths — the schema has no-i;configcarries bothmodel_reasoning_effort:"xhigh"ANDinclude_image_gen_tool:true— without the latter codex won't fire its native image tool;request_idis a per-bake uuid4-hex nonce the core mints — see (D)+(E)), pre-deleting any staleout_path+ status. - (B) the agent calls
mcp__codex__codexwith EXACTLY those params. - (C) codex writes a native PNG to
out_path. - (D) the agent writes
<out>.bakestatus.json={status:"ok"|"fail", failure_kind:"throttle"|"other", mcp_output:"<bounded raw codex tool output>", mcp_error, request_id:"<verbatim from bakereq>"}.mcp_outputis MANDATORY on BOTH ok and fail — the core feeds this status file topickup --transcript, and the HARD-VETO scans it forimport struct/zlib.compress/<svg>/matplotlib/… markers. Anokstatus with no raw output makes the HARD-VETO inert (a hand-drawn struct+zlib/SVG that still emits a ≥500KB sig-valid PNG would slip through) — so always embed the bounded raw tool result.request_idis EQUALLY MANDATORY on BOTH ok and fail — copy it VERBATIM from<out>.bakereq.jsoninto the bakestatus;pickup_image.py --out-existing --request-idfail-closes the bake if the statusrequest_idis missing or ≠ the bakereq nonce (a stale/foreign status at the same path can't be silently honored). - (E) the core verifies via
pickup_image.py --out-existingon the EXPLICITout_path(PNG sig + IHDR dims- size > 500000 + aspect band +
mtime >= created_at), HARD-VETOES the markers in the transcript (= the status file'smcp_output), and (via--request-id) fail-closes if the status file'srequest_idis absent or ≠ the bakereq nonce — but all ONLY after it has readstatus:"ok". Empty/timeout/any-non-ok = fail-closed (no pickup). NO fallback tocodex exec/PIL/SVG; effort is ALWAYSxhigh; sandbox ALWAYSworkspace-write.
- size > 500000 + aspect band +
Who runs --bake-mode=agent (the agent-wrapper SOP) — REQUIRED for the default mode to function
The comic-director skill agent is the bake fulfiller. Concretely:
- Launch the orchestrator in the BACKGROUND:
python3 skills/comic-director/scripts/run_comic.py --project … --page … --panels … --bake-mode agent(it blocks on each bake by polling<out>.bakestatus.json). - Loop until the orchestrator prints its final run-report JSON / exits:
- watch the project's
panels/dir for a new*.bakereq.json; - read it; call
mcp__codex__codexwith exactly its{prompt: <prompt_text>, model:"gpt-5.5", config:{include_image_gen_tool:true, model_reasoning_effort:"xhigh"}, sandbox:"workspace-write", cwd:<cwd>}(codex writes the native PNG to the sidecar'sout_path). TheconfigMUST carry bothinclude_image_gen_tool:trueANDmodel_reasoning_effort:"xhigh": withoutinclude_image_gen_toolCodex will not fire its native image tool (it falls back to descriptive text / an SVG renderer), andxhighis the required reasoning tier; - then read
request_idfrom<out>.bakereq.jsonand write<out>.bakestatus.jsoncarrying the status, a bounded rawmcp_output, AND thatrequest_idVERBATIM —mcp_outputso the core's HARD-VETO can scan it, andrequest_idbecausepickup_image.py --out-existing --request-idfail-closes the bake if the statusrequest_idis missing or mismatched (it must be written on BOTH ok and fail). Live-verified pitfall: if themcp__codex__codexreply TEXT is EMPTY (an image-only reply), serialize the RAW response object intomcp_output— never write an empty string (pickup fail-closes a blankmcp_outputon the empty-transcript guard):{"status":"ok","mcp_output":"<raw>","request_id":"<verbatim from bakereq>"}on success, or{"status":"fail","failure_kind":"throttle","mcp_output":"<raw>","request_id":"<verbatim from bakereq>"}on a 429 /MODEL_CAPACITY_EXHAUSTED/ overloaded error (otherwise{"status":"fail","failure_kind":"other","mcp_output":"<raw>","mcp_error":"<raw>","request_id":"<verbatim from bakereq>"}).
- watch the project's
- Stop when the orchestrator exits. (Without this wrapper, every bake polls to
--bake-timeoutand returnsgeneration_failedwithfailure_kind="other"— fail-closed, not a hang, and never a falsethrottle.)
--bake-mode=execis the legacy/CI non-image path and RAISES if it ever reaches a real bake — never use it to produce a panel.
Hard do / don't
- Do author
comic.jsonfirst withcomic-author; copyexamples/comic_m3_audit/comic.jsonas the shape. - Do
--dry-runfirst; confirm every baked figure-panel carries ascii-tokenizableexpected_literals(else the fail-closed gate refuses to run). - Don't run two bakes at once. The default
--bake-mode=agentwrites each native PNG to its explicit per-panelout_pathand has no/tmp/aris_imagegen.lock(that code lock is GONE in agent mode — the agent wrapper itself serializes themcp__codex__codexcalls). The real race surface: concurrent runs on the same project/page collide on the per-panel.bakereq.json/.bakestatus.jsonsidecars + the sharedout_path— so keep ONE runner per project/page. (The global generated-images dir that could cross-pollinate concurrent bakes is a hazard of the LEGACY--bake-mode=execpath ONLY, retired for real bakes.) - Don't resume after an image_gen throttle — launch a FRESH run for the remaining panels.
- Don't treat a
needs_human/flagged panel as shippable.
Protocols (governance contracts this skill honors)
reviewer-independence— reviewers get file paths only; the executor (Codex image_gen) ≠ the visual judges (Gemini + Codex vision).acceptance-gate— the loop can DRIVE but can't ACQUIT: a KEEP needs the deterministic token-diff clean and Gemini+Codex visual pass; the generator family never self-acquits; Claude gives the final structural sign-off.artifact-integrity— the model that bakes a frame does not judge its own faithfulness; numbers are verified, never originated.review-tracing— every reviewer's prompt+response is saved (trace.jsonl) so each verdict is auditable.reviewer-routing— Codexgpt-5.5xhigh; Geminiauto-gemini-3; never downgrade the reviewer tier.
What ships with it: 1 file
57.9 KB alongside SKILL.md, 1 of them executable
scripts/
- run_comic.pyruns57.9 KB