comic-cross-layer-gate
SkillDocs & knowledgeThe ONE parameterized score-fuser for EVERY comic-author authoring gate — `--gate intent|outline|asset|storyboard|blueprint|continuity|p0_proof|compile`. A single fuser (not a per-layer split) prevents drift. It NEVER re-runs a reviewer; it collects the reviewer score-nodes already on the wiki (via `reviews` edges), fuses them deterministically (min-fuse per dim, max for inverted dims, SKIP missing dims — never substitute 0), then a Codex xhigh adjudicator (NO model pin — follows the local codex config) that sees ONLY structured inputs (scores + tags + raw artifact PATHS + verbatim source context + verbatim rubric — NEVER reviewer prose) makes an asymmetric call (threshold HARD-vetoes "advance"; Codex SOFT-vetoes everything else). The `--gate p0_proof` mode is the zero-credit pre-production proof: a text-only cross-model adversarial review of the pipeline's CODE + IR-CONTRACT + ENGINE state-machine that MUST clear all blockers in BOTH non-author families and then MINT the digest-bound decision:p0_proof certificate via scripts/run_p0_proof.py BEFORE a single metered image-generation credit is spent. Use when a sibling step (intent-parser, outline-creator, asset-review-loop, storyboard-creator, blueprint-author, continuity-audit, json-compiler) defers its acquittal to "the gate", or the user says "过 gate", "cross-layer gate", "审这一层", "p0 proof", "证明流水线再花钱".
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the comic-cross-layer-gate skill
What this skill tells your AI
The instructions your AI receives, as published by wanshuiyin/aris-movie-director in skills/comic-cross-layer-gate/SKILL.md and read by ahel’s review.
The acquittal organ of the comic-author suite. Every authoring step
(intent → style → outline → asset → storyboard → blueprint → continuity → the compiled comic.json) is a
generator; none of them acquits itself. They each emit their node(s), fan out independent reviewers, and
then defer to this one skill to fuse the scores into a verdict, mint the audit trail, and flip the target's
status. It is the image-comic port of aris_movie's 6-gate adversarial decision skill — but folded into one
parameterized fuser (Codex's single-fuser design, against the per-layer split that drifts: six near-copies
diverge, one fuser stays honest). The downstream per-panel panel_gate / page assembly_gate are NOT this
skill — those live in packages/core/spiral_engine.js and run at bake
time; this skill is the authoring-side, pre-bake gate that decides whether a spec may advance.
Cardinal lesson, landed as a guard not prose: identical scores across rounds = the judge is broken — audit the rubric, do not regenerate the artifact (memory:
feedback_gate_identical_scores_judge_broken). Concretely: this gate carries a_score_fingerprintin everydecisionnode; if round N's fused per-dim vector equals round N−1's after the artifact changed, the gate HALTS and flagsjudge_suspect— the rubric (this skill), not the spec, is the suspect. A gate that emits the same verdict regardless of the work is worse than no gate.
upstream step emits node(s) + fans out independent reviewers (writes review:* score-nodes + `reviews` edges)
│
comic-cross-layer-gate <target_node_id> --gate <kind>
▼
⓪ PRE-CHECK structural facts the GATE computes (asset-resolve / policy / count-band / continuity) — RAW, not opinion
▼
① COLLECT reviewer score-nodes via `reviews` edges — NEVER re-run a reviewer; hard-fail if none
▼
② THRESHOLD per-dim min-fuse (max for inverted dims); SKIP missing dims (NEVER 0-substitute); per-gate floor → threshold_verdict
▼
③ ADJUDICATE Codex xhigh (no model pin — local codex config) — sees ONLY {scores + failure_mode tags + threshold_block + raw PATHS + ≤200w verbatim source + verbatim rubric}
▼ (NEVER reviewer prose / notes / overall — that is the contamination vector)
④ ASYMMETRIC threshold HARD-VETO over "advance"; Codex SOFT-VETO over everything else
▼
⑤ WRITE decision node (full audit) + (on FAIL only) a positive-invariant failure_mode the NEXT step preloads as a banlist
▼
⑥ FLIP target status → locked (advance) · under_review (needs-work) · rejected (terminal) ; stdout last line: VERDICT=<v> GATE=<kind> TARGET=<id>
The --gate p0_proof branch is a different shape (a text-only adversarial review of the pipeline machinery,
not a score-fuse over a spec) — it is documented in its own section below. It is the single most important
contract this skill owns: it runs AFTER comic-json-compiler and
BEFORE any metered image bake (the agent mcp__codex__codex sidecar), costs zero generation credits,
and must clear all blockers in BOTH non-author families and then MINT the digest-bound decision:p0_proof_*
certificate via scripts/run_p0_proof.py — or the spiral is forbidden to spend a
credit.
Constants
- GATE KINDS =
intent | outline | asset | storyboard | blueprint | continuity | p0_proof | compile. The legal verdict set is per-gate (below) and enforced — a verdict outside a gate's set is a hard error (theintentgate can never emitkeep; theassetgate can emitlocked, theintentgate cannot). The legal nodestatustokens a FLIP may write are ONLY{draft, pending, under_review, locked, rejected, superseded, active, complete, final}(schema enum) — a verdict (revise/regenerate/fallback) is never a status. - REVIEWERS (collected, never re-run here): the Codex CLI at
model_reasoning_effort: xhighwith NO model pin — it follows the local codex config (currentlygpt-5.6-sol) — for every gate's ambiguity / correctness / logic pass; Geminiauto-gemini-3wherever a second family or a visual read is needed (image inputs, UX/design). Never downgrade the effort tier (reviewer-routing). (The one place a model IS pinned is the metered BAKE, not this skill:gpt-5.5+xhighas the single compat default inrun_comic.get_bake_plan()— config-driven override plumbing is planned, not yet implemented.) - ADJUDICATOR = the Codex CLI at
xhigh(same no-model-pin rule — local codex config), fed ONLY structured inputs (§③). Its effort is always xhigh — effort widens fan-out, it never weakens the judge. (run_comic.pyexposes only--review-effort; there is no--effortflag.) - FUSE RULE = min per dimension (most-pessimistic), EXCEPT inverted dims (
artifact_severity,*_severity, anything where higher = worse) use max; SKIP a dim no reviewer scored (filter thenulls) — NEVER substitute 0 (the v1.0 bug: a lite reviewer leaving a dim unscored must neither slip an advance nor force a fail). - ASYMMETRIC TRUST = the deterministic threshold has HARD VETO over "advance" (Codex cannot overrule
approve/lockedif the deterministic floor failed); Codex has SOFT VETO over everything else (a Codexreviseoverrules a thresholdapprove). Structural facts (§⓪) also hard-veto advance. - CAPS —
MAX_ASSET_REGEN = 4then escalate the asset gate to the outline gate (abandon_shot); re-gate (re-vote) caps fold into the calling step's attempt budget. The准 ×3convention (asset gate, owned bycomic-asset-review-loop): alockedverdict requires cross-model UNANIMITY in the SAME round — CC and Gemini and Codex all approve the asset that round (≥3 distinct reviewer families lock-pass together). Fewer than 3 families approving →regenerate --another-voter(re-vote to reach the third family, not re-bake); a family's hard-fail → re-bake. (NOT "three consecutive rounds" — that aris_movie video port is wrong for this repo; the owner is same-round unanimity.) - P0 GATE THRESHOLD =
blockers.length == 0in BOTH non-author families{openai, google}on the SAMEcomic_sha, then the certificate is MINTED byscripts/run_p0_proof.py— a HARD HALT until the digest-bounddecision:p0_proof_*node exists (a timed-out/missing family does NOT count toward quorum; quorum unmet = no certificate = baking stays blocked). Zero image-generation credits are spent before the mint. The review is deliberately text-only → not rate-limited → free. - CODEX UNAVAILABLE → emit the threshold-only provisional verdict with
_confidence: "low", exit code 2, and skipfailure_modecompilation. Malformed adjudicator JSON →codex-replyretry ×2, then fall back to threshold-only. - OUTPUT — a
decisionnode inwiki/nodes/, thedecidesedge, areview-tracingentry per collected reviewer + the adjudicator, and (on a FAIL verdict only) afailure_modenode. Final stdout line is EXACTLYVERDICT=<v> GATE=<kind> TARGET=<id>for the caller to parse.
Input contract — what the gate is given, what it refuses
The direct input is a target_node_id + a --gate <kind>. The gate reads from the wiki, it is not
handed prose:
- It NEVER re-runs a reviewer. The upstream step already fanned out and wrote
review:*score-nodes withreviewsedges → the target. The gate collects those nodes; if zero reviews are attached, it hard-fails (no reviews — gate is a score-fuser, not a reviewer). This is the load-bearing separation: the executor that authored the spec must not also be the one whose read of it acquits it. - The adjudicator sees scores + failure-mode tags + raw artifact PATHS + a ≤200-word VERBATIM source slice +
the VERBATIM rubric — and NOTHING else. It never sees a reviewer's prose,
notes,evidence,overall_assessment, orrationale(reviewer-independence). Reviewer prose is the contamination vector; forwarding it re-introduces the correlated blind spot cross-model review exists to break. (Structural facts in §⓪ are an exception — they are RAW artifacts the gate itself computed, not reviewer opinion, so forwarding them does not violate independence.) - The upstream gate state machine is
verdict ∈ {approve, locked, revise, regenerate, fallback}(plus the asset-gate-onlyabandon_shot). Each reviewer call that feeds this gate gets file paths + an explicit=== EXTERNAL CONTEXT (advisory) ===fence around any cross-cutting context — never the author's interpretation. The fence is what keeps "here is the situation" from becoming "here is what to conclude".
The universal architecture (every --gate except p0_proof — which has its OWN write path, the deterministic minter, §p0_proof below)
Ported verbatim from the aris_movie 6-gate skill; the deterministic-JS fuse pattern is the same one the engine
already proves in packages/core/spiral_engine.js:59 (panelVerdict).
Honesty note: the six universal score-fuse gates ship NO runner today — the agent executes this SOP directly (collect → fuse → adjudicate → write → flip, by hand, per the steps below); a parameterized
run_gate.pyis planned, not shipped. The only executables this skill owns/shells today arescripts/run_p0_proof.py(the p0 certificate minter) and the deterministic--gate compilescripts. The worked-example workflows below are the pattern to copy.
⓪ Pre-check — the structural facts the gate computes
Before touching reviewers, compute the raw artifacts (filesystem facts, not opinions) the gate hard-vetoes
on. These differ per gate (see each rubric) but the shape is constant: resolve every referenced asset_id,
every asset is status: locked, policy fields match expected, count in band, continuity links
well-formed (no dangling / out-of-order / cycle). Any non-empty violation set → revise regardless of
reviewer scores OR Codex ("structural failures cannot be voted-around"). Record each as
_unresolved_asset_refs / _policy_violations / _count_band / _continuity_breaks in the decision audit.
① Collect — reviewer score-nodes, never re-run
Walk reviews edges into target_node_id; load each review:* node's payload.review_scores. Build
per_reviewer = {reviewer: {dim: score, ...}, failure_mode_tags: [...]}. Hard-fail if the set is empty.
② Threshold — deterministic per-dim fuse
For each rubric dimension, fuse across reviewers with min (or max for an inverted dim), skipping
any reviewer that left it null. Apply the per-gate floor (each rubric below). Yield threshold_verdict ∈ {advance, revise} + a _cited_dimensions map of every fused value. This is mechanical and reproducible — a
fresh reviewer can re-derive it from the table alone.
③ Adjudicate — Codex, structured inputs only
Call the Codex CLI at xhigh (no model pin — local codex config) with EXACTLY: per_reviewer scores, failure_mode_tags, the threshold_block
(the fused values + the floor), the raw artifact PATHS, a ≤200-word verbatim slice of the source node
(not a summary — a literal excerpt), and the verbatim rubric for this gate. Ask for a verdict in this
gate's legal set + a one-line confidence + the single most important fix. Trace the call
(review-tracing).
④ Asymmetric cross-check
threshold_verdict == revise→ the final verdict is a FAIL verdict no matter what Codex said (threshold hard-vetoes advance).threshold_verdict == advanceAND Codex returns a FAIL verdict → Codex's FAIL wins (Codex soft-vetoes advance).threshold_verdict == advanceAND Codex advances → ADVANCE (approve/locked, per gate).- Record
_threshold_verdict,_codex_verdict,_disagreement(bool),_confidence.
⑤ Write — decision + (on FAIL only) a positive-invariant failure_mode
Write a decision node (full audit). On any FAIL verdict, compile one failure_mode node whose
repair_pattern is a POSITIVE INVARIANT ("force a status:locked ref for every must_show asset", NOT "no
draft assets") — diffusion and the next authoring step focus on what you mention, so state the desired
target, not the ban (negative patterns are only for explicit banlists). Default scope is movie-local;
engine-global needs explicit grounding (an over-broad failure_mode poisons cross-project banlists). The
next authoring step preloads this node as its banlist — the spiral's learning loop.
⑥ Flip + emit
Flip target.status (locked on advance for asset/storyboard/etc.; leave/rejected on a terminal fail).
Exception: a PROVISIONAL-stage storyboard approve never flips — the node stays under_review (see --gate storyboard). Append the decides edge. Print the parse line.
EXACT gates (dimensions · thresholds · vetoes) — ported from the aris_movie source
Every reviewer scores each dim 0–5. "ADVANCE" verdict in CAPS. Advisory dims do NOT block advance; they ride into the decision audit and the adjudicator's context.
--gate intent → verdicts {approve, revise}
- ADVANCE (
APPROVE) iffcompleteness ≥ 4ANDsafety_flag_coverage ≥ 4. - Advisory:
clarity,scope_feasibility. - EXTRA veto: if the
intent_spec.payload.confidence < 0.6, OR any unresolved high-impact uncertainty remains, downgradeapprove → reviseeven when both floor dims pass (low-confidence / unresolved intent must not lock silently). This is the EXACT predicatecomic-intent-parsermust quote — no0.5/0.6drift between the parser's stated gate and the gate that actually runs. - Note: the user-approval gate for intent is a separate HARD human gate owned by
comic-intent-parserstep ⑥ — this gate is the cross-model adjudication, not the human sign-off.
--gate outline → verdicts {approve, revise} — two checkpoints: OUTLINE_DRAFT_VALID, then OUTLINE_FINAL_LOCK
The outline acquittal is deliberately split in two. A single-stage "outline needs locked assets" contract
deadlocks a fresh project: assets are produced from the storyboard's consolidated_asset_requests, the
storyboard needs an approved outline, so the outline can never see a locked asset first. The Phase-1 DAG is:
OUTLINE_DRAFT_VALID → human outline approval → provisional storyboard (structural pass, may
reference draft assets) → consolidated_asset_requests → asset generation + review → assets LOCKED →
OUTLINE_FINAL_LOCK (cheap re-check) → storyboard FINAL asset-resolution validation → blueprints
- OUTLINE_DRAFT_VALID (this gate, pre-assets): validates NARRATIVE + CONTINUITY + safety only — it does
NOT require any referenced asset to be locked.
- Pre-check (HARD): every referenced
asset_id(scene / character / prop / must_show in the*_asset_idslists) must be DECLARED with a complete, generatable request (enough spec for the asset pipeline to produce it), else hard-fail with the missing-declaration list. Declared-but-draft is fine; undeclared or unrequestable is not. - ADVANCE (
APPROVE) iffcoverage ≥ 4ANDsafety_ip ≥ 4. - Advisory:
asset_promptability,audio_plan.
- Pre-check (HARD): every referenced
- OUTLINE_FINAL_LOCK (after assets lock): the cheap re-check that the now-locked assets still match the
approved outline — this is where
identity_lock_feasibility ≥ 4andscene_lock_feasibility ≥ 4are scored (they are meaningless before real locked refs exist). The hard locked-asset barrier lives at the storyboard FINAL asset-resolution validation + theblueprintgate, before blueprint authoring — not at the draft outline.
--gate asset → verdicts {approve, regenerate, locked, abandon_shot}
- LOCK (
LOCKED) iffidentity_lock_satisfied ≥ 4ANDref_quality ≥ 4ANDbg_isolation ≥ 4ANDsafety_ip ≥ 4— and the准 ×3rule holds (cross-model unanimity in the SAME round: CC AND Gemini AND Codex all lock-pass that round; fewer than 3 families approving →regenerate --another-voter= re-vote to reach the third family, not re-bake; a family's hard-fail → re-bake). See Constants. - Advisory:
reuse_readiness. - Cross-check (RAW):
output_refexists on disk AND itssha256matches the node AND thedata_urlis non-empty — any mismatch hard-vetoes lock. - Cap:
MAX_ASSET_REGEN = 4→ escalate to the outline gate (abandon_shot).
--gate storyboard → verdicts {approve, revise} — STRUCTURAL, CC-only (no visual reviewer; no pixels yet)
This is the comic.json structural validator (it supersedes the lone check_asset_collisions.py) — and
it is a TWO-STAGE contract: the gate runs TWICE per storyboard (the N1 DAG under --gate outline;
comic-storyboard-creator ⑨.0 quotes this same ordering):
- PROVISIONAL stage (right after authoring, pre asset-lock): structural pass only — declared-but-draft
assets are allowed;
panel_assets_referenceableis unscorable, leftnull, and the fuser SKIPs it (the verdict rides on the other three dims; only an UNDECLARED ref — no whitelist entry, no completeasset_request— vetoes). A provisionalapprovedoes NOT lock the storyboard node — no ⑥ FLIP; it staysunder_review. - FINAL stage (after the asset layer locks everything + OUTLINE_FINAL_LOCK): all four dims scorable — the
full asset-resolution predicate applies (every panel asset ref resolves AND is
locked; an un-locked ref hard-vetoes via_unresolved_asset_refs), andapproveflips the storyboard tolockedon advance.
The four structural dims are FILE-SYSTEM FACTS the gate computes, not reviewer opinion:
panel_assets_referenceable— every asset ref in each panel resolves and islocked. (Scored at the FINAL stage only — the storyboard's FINAL asset-resolution validation, the hard locked-asset barrier of the Phase-1 DAG; at the PROVISIONAL stage it isnull/SKIPped and the declared-check applies instead.)global_policies_valid—global_policiesfields match expected (e.g. text-mode rules present; mirror-lock policy present; page-order authority declared).panel_count_band_aligned— panels-per-page in band per target tier{mvp:(2,2), demo:(4,6), longform:(10,12)}(in-range = 5, off-by-one = 3, further = ≤2), AND theTOTALSline reconciles (Σ panels-per-page == panel count; NEW + reused == total).continuity_chain_well_formed— the MOTIF STATE TABLE has one row per panel; links have no dangling / out-of-order / cycle; every per-panelmotifsfield agrees with its table row.- ADVANCE (
APPROVE) iff ALL FOUR ≥ 4 — at the PROVISIONAL stage, all scorable dims (panel_assets_referenceableis SKIPped, never substituted with 0). - STRUCTURAL HARD VETO: any non-empty
_unresolved_asset_refs(FINAL stage; at the PROVISIONAL stage declared-but-unlocked refs are expected — only an UNDECLARED ref vetoes) /_policy_violations/_continuity_breaks, or an out-of-band_panel_count_band, forcesreviseregardless of reviewer scores OR Codex. (Plus the comic-specific structural vetoes the storyboard step also asks for: DDL non-monotonic; bounce-uniqueness broken; the two metric columns co-mingling; a DONE panel retro-edited; the storyboard page order disagreeing with the compiledcomic.jsonpage order — the storyboard is the authority.)
--gate blueprint (the IMAGE analog of aris_movie's frame_condition gate) → verdicts {approve, revise, fallback}
aris_movie's frame_condition gate is VIDEO-flavored (action_freeze, harmonization); the IMAGE analog
drops the motion dims and asks instead: "is this panel's condition.content_svg + identity_ref + scene
buildable?"
- ADVANCE (
APPROVE) iffrefs_present ≥ 4ANDspatial_correctness ≥ 4ANDblueprint_renders ≥ 4(the SVG rasterizes to a non-empty PNG — a RAW pre-check, not a vote). text_preservationrequired only when the panel has whitelisted baked text.safezone_quality(html panels) < 3 while the floor otherwise passes →fallback= route the panel's text to the HTML overlay (a route switch, not a regen).- Cap:
MAX_BLUEPRINT_REGEN = 3→ escalate to rewrite the panel_spec.
--gate continuity → verdicts {approve, revise}
Adjudicates the comic-continuity-audit read against the
motif_ledger. Dims (all ≥ 4 to ADVANCE):
ledger_row_complete— one MOTIF-table row per panel; no missing variable.invariants_hold— the declarative predicates verify against the table:ddl_monotonic_non_increasing,bounce_single_max(S02 = the film's ONLY MAX; no post-fall peak),metric_columns_disjoint(noclaim_deltavalue in theexact_parsecolumn or vice-versa).mirror_locks_paired— each paired constraint (REJECT ↔ ACCEPT same stamp geometry; S02-MAX ↔ S21-smallest; S16b labeled star-map ↔ S22 wordless twin from the same node JSON,禁目测) is present and consistent.design_aware— MOTIF-vs-ENV disambiguation is honored: only continuity-bearing instances are tracked; an intended absence / a taggedenvprop is not flagged as drift (absence ≠ drift).- Structural HARD VETO: any invariant violation forces
revise(invariants are machine-checkable predicates, not vibes).
--gate compile → verdicts {approve, revise} — DETERMINISTIC (no reviewer fan-out; the scripts ARE the judge)
The compiled-comic.json acquittal that comic-json-compiler defers to.
Unlike every other gate this one is purely deterministic — NO review:* nodes, NO Codex adjudication, so
§① (collect) is skipped and the "hard-fail if zero reviews" rule does NOT apply. It PASSES (approve) iff
both real scripts exit 0, else revise carrying their stderr as the blocker list:
python3 skills/comic-director/scripts/run_comic.py --project <dir> --page <P> --panels <ids> --dry-run— validates the comic.json shape, that everytext_mode:"baked"figure-panel carries asciicondition.expected_literals, and prints each concrete bake prompt (no placeholders).--panelsis required byrun_comic.py(argparserequired=True), so run this once per page inpages[]with that page's panel ids — omitting--panelsexits non-zero (a false blocker).python3 cli/validate_wiki.py <dir>— node/edge/payload/privacy/node_id conformance againstnode_schema.json. There is noreconcile_pages.py(it never existed) — these on-disk scripts are the entire deterministic core. PASS (approve) iff EVERY per-pagerun_comic.pyANDvalidate_wiki.pyexit 0. Record all exit codes + any stderr in the decision audit. The §⑥ FLIP target is the schema-validdecision:compile_<slug>wiki node this gate writes (status: final) — NOTcomic.json, which is a file, not a wiki node (it has no legal node_id prefix, carries nowiki_node_id, and can never be an edge endpoint).
Shortened here. Read the whole file on GitHub.
Signals
- GitHub stars
- 61
- Forks
- 4
- Last commit
- Sep 2026
Advanced
- Catalog kind
- skill
- Gateway key
comic-cross-layer-gate- Source
- github.com/wanshuiyin/aris-movie-director