comic-cross-layer-gate

SkillDocs & knowledge

The 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.

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_fingerprint in every decision node; if round N's fused per-dim vector equals round N−1's after the artifact changed, the gate HALTS and flags judge_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 (the intent gate can never emit keep; the asset gate can emit locked, the intent gate cannot). The legal node status tokens 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: xhigh with NO model pin — it follows the local codex config (currently gpt-5.6-sol) — for every gate's ambiguity / correctness / logic pass; Gemini auto-gemini-3 wherever 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 + xhigh as the single compat default in run_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.py exposes only --review-effort; there is no --effort flag.)
  • 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 the nulls) — 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/locked if the deterministic floor failed); Codex has SOFT VETO over everything else (a Codex revise overrules a threshold approve). Structural facts (§⓪) also hard-veto advance.
  • CAPSMAX_ASSET_REGEN = 4 then escalate the asset gate to the outline gate (abandon_shot); re-gate (re-vote) caps fold into the calling step's attempt budget. The 准 ×3 convention (asset gate, owned by comic-asset-review-loop): a locked verdict 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 == 0 in BOTH non-author families {openai, google} on the SAME comic_sha, then the certificate is MINTED by scripts/run_p0_proof.py — a HARD HALT until the digest-bound decision: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 skip failure_mode compilation. Malformed adjudicator JSON → codex-reply retry ×2, then fall back to threshold-only.
  • OUTPUT — a decision node in wiki/nodes/, the decides edge, a review-tracing entry per collected reviewer + the adjudicator, and (on a FAIL verdict only) a failure_mode node. Final stdout line is EXACTLY VERDICT=<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 with reviews edges → 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, or rationale (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-only abandon_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.py is planned, not shipped. The only executables this skill owns/shells today are scripts/run_p0_proof.py (the p0 certificate minter) and the deterministic --gate compile scripts. 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 == advance AND Codex returns a FAIL verdict → Codex's FAIL wins (Codex soft-vetoes advance).
  • threshold_verdict == advance AND 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) iff completeness ≥ 4 AND safety_flag_coverage ≥ 4.
  • Advisory: clarity, scope_feasibility.
  • EXTRA veto: if the intent_spec.payload.confidence < 0.6, OR any unresolved high-impact uncertainty remains, downgrade approve → revise even when both floor dims pass (low-confidence / unresolved intent must not lock silently). This is the EXACT predicate comic-intent-parser must quote — no 0.5/0.6 drift 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-parser step ⑥ — 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_ids lists) 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) iff coverage ≥ 4 AND safety_ip ≥ 4.
    • Advisory: asset_promptability, audio_plan.
  • 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 ≥ 4 and scene_lock_feasibility ≥ 4 are scored (they are meaningless before real locked refs exist). The hard locked-asset barrier lives at the storyboard FINAL asset-resolution validation + the blueprint gate, before blueprint authoring — not at the draft outline.

--gate asset → verdicts {approve, regenerate, locked, abandon_shot}

  • LOCK (LOCKED) iff identity_lock_satisfied ≥ 4 AND ref_quality ≥ 4 AND bg_isolation ≥ 4 AND safety_ip ≥ 4and the 准 ×3 rule 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_ref exists on disk AND its sha256 matches the node AND the data_url is 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_referenceable is unscorable, left null, and the fuser SKIPs it (the verdict rides on the other three dims; only an UNDECLARED ref — no whitelist entry, no complete asset_request — vetoes). A provisional approve does NOT lock the storyboard node — no ⑥ FLIP; it stays under_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), and approve flips the storyboard to locked on 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 is locked. (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 is null/SKIPped and the declared-check applies instead.)
  • global_policies_validglobal_policies fields 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 the TOTALS line 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-panel motifs field agrees with its table row.
  • ADVANCE (APPROVE) iff ALL FOUR ≥ 4 — at the PROVISIONAL stage, all scorable dims (panel_assets_referenceable is 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, forces revise regardless 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 compiled comic.json page 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) iff refs_present ≥ 4 AND spatial_correctness ≥ 4 AND blueprint_renders ≥ 4 (the SVG rasterizes to a non-empty PNG — a RAW pre-check, not a vote).
  • text_preservation required 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 (no claim_delta value in the exact_parse column 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 tagged env prop 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 every text_mode:"baked" figure-panel carries ascii condition.expected_literals, and prints each concrete bake prompt (no placeholders). --panels is required by run_comic.py (argparse required=True), so run this once per page in pages[] with that page's panel ids — omitting --panels exits non-zero (a false blocker).
  • python3 cli/validate_wiki.py <dir> — node/edge/payload/privacy/node_id conformance against node_schema.json. There is no reconcile_pages.py (it never existed) — these on-disk scripts are the entire deterministic core. PASS (approve) iff EVERY per-page run_comic.py AND validate_wiki.py exit 0. Record all exit codes + any stderr in the decision audit. The §⑥ FLIP target is the schema-valid decision:compile_<slug> wiki node this gate writes (status: final) — NOT comic.json, which is a file, not a wiki node (it has no legal node_id prefix, carries no wiki_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