# Prism

> Dispatch multiple independent agents to answer the SAME complete question from different analytical lenses, then synthesize. Reach for this by default, without waiting to be asked, when redundant cross-model judgment could change the decision: ambiguous architecture/design tradeoffs, high-stakes or hard-to-reverse changes, competing root-cause hypotheses, or failure-mode-sensitive reviews — and whenever you would otherwise spawn 2+ independent reviewers for one question. Skip for trivial lookups, deterministic transforms, routine small edits, mechanical syncs, and single-correct-answer tasks. With no leading number, autonomously decide N and gpt-pro from the question every time (N=1 is the bottom-rung anchor, never a lazy default); with explicit numbers `prism N M` (e.g. `prism 2 1` = 2 of each model + 1 gpt-pro lens; M is a count, not a flag), honor them verbatim and skip auto-sizing. There is no reasoning-effort knob. Scale above the anchor only when decision risk justifies the 7N-agent cost.

- Skill: `chrisliu298/prism` (Agent Skill, multi-file: 18 files)
- Install (CLI): `npx skillmds@latest add chrisliu298/prism`
- Raw SKILL.md: https://api.skillmd.com/api/skills/chrisliu298/prism/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: AI & ML
- Author: chrisliu298 (https://skillmd.com/u/chrisliu298)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/chrisliu298/prism

---


# Prism

**Claude-only.** If `ANTHROPIC_BASE_URL` contains `deepseek`, `xiaomimimo`, `z.ai`, or `kimi.com`, this skill is unavailable — stop and tell the user: "prism is Claude-only; a non-Claude session cannot orchestrate other models." Prism dispatches parallax via [[relay]], which itself refuses from non-Claude sessions.

Prism sends the **same complete question** to multiple independent agents. Each agent answers the **entire question end-to-end**. The only thing that changes between agents is the **lens**: what they prioritize and what tradeoffs they weigh more heavily.

## Operator quick reference

A skim card + execution TOC for the orchestrating Claude — every line points to its authoritative section below; nothing here overrides them.

- **Invoke:** `prism [N|Nns] [M] <question>`. A leading number, the terse `Nns` no-subagents token, or a natural-language tier modifier ⇒ honor it verbatim; **no** number ⇒ auto-size (anchor `N=1`). See *Invocation*.
- **The 7 standard tiers:** Claude subagent · GPT · Grok Build · GLM · Kimi · DeepSeek · MiMo. gpt-pro is a *separate opt-in* tier (`M`, default 0). See *Counting Contract*.
- **Counts:** dispatched = `7N+M`; perspectives = dispatched + self. The full 7-tier fan at `N` is the **floor** — drop or skew a tier *only* on explicit user instruction.
- **No-subagents (external-only):** user says "no subagents" or the terse `Nns` (e.g. `prism 1ns 1`) → drop only the Claude tier, keep the 6 parallax (+ gpt-pro); dispatched `6N+M`, self the lone Claude perspective. Recognized + floor-checked via `PL scaffold --no-subagents` → `Prism-Mode: partial` + `Variant: no-subagents` (not a bare partial). User-only. See *Counting Contract* → No-subagents shape.
- **Effort:** never authored — GPT `xhigh` (deliberately not `max` or `ultra` — `ultra` is a multi-agent topology, not a leaf depth tier, and `max`'s single-leaf depth isn't validated to beat `xhigh` on a redundant fan), Grok Build `high`, derived from the registry; the rest have no knob.
- **Run** (see *Execution Spine*): write packet `/tmp/prism-<id>.md` → `scaffold` (prints the `Prism-Mode: full` roster contract to stdout, for reference) → **Write** the dispatch directly with your lenses (never `scaffold > file` then edit) → `prepare --dispatch …` (default fail-closed floor check on the contract) → launch **all at once** (1 backgrounded `parallax` + one Agent call per subagent — **zero in a no-subagents run** — + `M` gpt-pro) → **wait for every notification** → `results` / `digest` → synthesize verdict-first. A reduced roster needs an explicit `Prism-Mode: partial` + `Partial-User-Quote:` waiver.
- **Hard gates:** no synthesis until *every* agent returns; dispatched agents are read-only (no cross-model recursion or side effects; own same-model subagents OK); **never** revert the working tree. See *Guards*.
- **Local files:** attach repo files with `Include:` dispatch lines (repeatable; `/abs`, `@base-relative`, or single-level glob; `Include-Base:`/`Include-From:`/`Include-Tree:` too). `prepare` resolves them via `filectx` → generates the packet's `### Reference Materials` (relay/subagent tiers **read** the paths) **and** the gpt-pro **inline** list — one source, secret-scanned, fail-closed. `scaffold` pre-prints the commented slot. Mutually exclusive with hand-written `Reference:` / `### Reference Materials`. See *Shared Context*.
- **Script:** `~/.claude/skills/prism/scripts/prism-launch` (always the absolute path).

## Core Principle

**Prism is redundancy, not division of labor.** Every agent gets the full question, full scope, and full deliverable. The lens changes **emphasis**, not **coverage**. If agents own different files, sections, or outputs, that is division of labor, not Prism.

Convergence across diverse lenses is high-confidence signal; divergence surfaces tradeoffs that need explicit resolution.

## Counting Contract (authoritative — every count in this skill derives from here; never restate bare numbers elsewhere)

Prism has exactly **seven standard tiers**, each dispatched at count `N`: **Claude subagent · GPT · Grok Build · GLM · Kimi · DeepSeek · MiMo** (= 1 Claude subagent via the Agent tool + 6 parallax tiers via relay). gpt-pro is a separate opt-in tier (`M`), never one of the 7.

- **`N`** — the per-tier count of the **7 standard tiers**. In the symmetric shape every standard tier gets `N`.
- **`M`** — the **gpt-pro** count: a **separate opt-in tier, independent of `N`, default `0`**. GPT-Pro is **never one of the 7** and never consumes a standard-tier slot.
- **Self** (the orchestrator / Integrator) — a **perspective, never a dispatched agent**: adds `0` to dispatched, `+1` to perspectives.

| Quantity | Formula |
|---|---|
| **Dispatched agents** (symmetric) | **`7N + M`** |
| **Dispatched agents** (after explicit exclusions / per-tier overrides) | `Σ(resolved counts over the 7 standard tiers) + M` |
| **Perspectives** (the synthesis `n/total`, incl. self) | **dispatched `+ 1`** |

At `N=1, M=0`: `7×1 + 0 = 7` dispatched, `7 + self = 8` perspectives. **"8" denotes only this** — never reuse a bare agent count without showing its `7N+M` derivation. (`prism-launch`'s manifest reports `counts.dispatched_total` as the standard-tier subtotal — parallax + subagents, which `= 7N` on a full symmetric run but is the actual record count on a partial — never including gpt-pro (tracked separately in `counts."gpt-pro"`); see README for the grep caveat.)

**No-subagents shape (the recognized external-only run):** the user may drop **only the Claude subagent tier** and keep the full parallax fan (+ optional gpt-pro) — "no subagents" / "no Claude subagents". This is the asymmetric `Σ` row with the subagent tier at 0: **dispatched = `6N + M`, perspectives = `6N + M + 1`** (self is the lone Claude perspective). `N` is **not** redefined — it is still the per-standard-tier count; one tier is just pinned to 0. It is a *recognized, floor-checked* reduced shape — `prepare` asserts all 6 parallax tiers at `N` + zero subagents — declared as `Prism-Mode: partial` + `Variant: no-subagents` (the one partial shape that keeps `Prism-N`/`Prism-M`), not a new top-level mode and not a bare partial. Distinct from `N=0` (which drops parallax **too** → gpt-pro-only); `N=0` with "no subagents" is just the gpt-pro-only shape. See Invocation → Natural-language modifications and *Execution Spine* → Roster contract.

**Dispatch invariant (HARD RULE — mechanically enforced by `prepare`):** every tier whose resolved count is `> 0` MUST be dispatched at exactly that count — no silent drops, substitutions, or merges. The **full 7-tier fan at `N` is the floor**: the orchestrator **never self-initiates a partial or asymmetric group**. A tier drops to `0` or takes a non-`N` count **only** when the user explicitly says so (an exclusion or per-tier count — see Invocation → Natural-language modifications); autonomous sizing picks `N` but always across **all 7**. `N=0` (drop all seven standard tiers, gpt-pro-only) is itself a user-stated config and is legal only with `M ≥ 1`. On the `--dispatch` path `prepare` enforces this fail-closed via the `Prism-Mode` contract (see *Execution Spine* → Roster contract). A run that drops a family for cost, latency, or a flaky/overloaded peer (e.g. GLM 529s) is the exact defect this blocks — unavailability is a *post-dispatch* `result.json` `status: error` (retry with `parallax --only <peer>`), never a reason to omit the record.

**The floor is a dispatch-time contract — it is NEVER satisfied by post-hoc salvage of an unverified artifact.** A lens that dies *after* dispatch is a **result to report honestly**, not a hole to paper over: resubmit it, or take an explicitly user-authorized partial. Mind the asymmetry the `--only` out hides: a parallax peer has a cheap in-place retry (`parallax --only <peer>`), **gpt-pro has none** — its only recovery is a fresh, quota-costing run with a new run-id, so a dead gpt-pro lens is a **user decision, not a self-service retry**. An orchestrator holding a dead gpt-pro lens therefore has no legal move that preserves the floor by itself — that is expected. Reaching into the run dir to make the count come out right is the defect this rule names (see *Handling failures* → Provenance failure).

`N=1, M=0` is the bottom-rung anchor (not a fire-without-thinking default): all seven standard tiers once, gpt-pro absent, self added only as a perspective. A bare invocation always routes through **Choosing N and gpt-pro** and never emits this by shortcut.

## Invocation

Two layers: a dead-simple positional form for the symmetric common case, and natural language for any deviation.

**Positional — `prism [N|Nns] [M] <question>`:**
- `N` — how many of **each** of the seven models. Integer `≥ 0`, default `1`. `N ≥ 1` dispatches `N` of every standard tier. **`N = 0` excludes all seven standard tiers at once** (the terse "gpt-pro-only") and is legal **only when `M ≥ 1`**; `prism 0` / `prism 0 0` is rejected (zero dispatched agents is not a Prism run). To drop *some* tiers, use a natural-language exclusion instead. `N` is the symmetric **floor** applied to all 7 tiers — deviating requires an explicit user modification.
- **`Nns` — the terse no-subagents form.** A first token of `<int>ns` (e.g. `1ns`, `2ns`) means **N=`<int>` in no-subagents mode**: drop only the Claude subagent tier, keep the 6 parallax tiers at `N` (+ gpt-pro at `M`). It is the exact equivalent of `prism <int> [M] no subagents <question>` and resolves to the same `Prism-Mode: partial` + `Variant: no-subagents` shape (emit it with `PL scaffold --no-subagents --n <int> --m <M>`). `ns` attaches only to the **first** token; `M` stays a bare integer (`prism 1ns 1 <q>` → N=1, no-subagents, M=1 → 6 + 1 + self = `/8`). `0ns` is just the gpt-pro-only shape (N=0 already drops parallax too) — legal only with `M ≥ 1`. **User-only**, like every tier exclusion.
- `M` — how many **gpt-pro** lenses to add. Integer `≥ 0`, default `0`; **independent of `N`** (never dispatched unless given). Naming it is the cost consent — it burns real Pro quota and runs 5–20 min/lens (see GPT-Pro tier).

**There is no reasoning-effort token.** Effort is fixed per tier — GPT `xhigh`, Grok Build `high`; the rest have no knob. You never choose effort.

The parser consumes **up to two leading whitespace-delimited integers**, left-to-right: first is `N` (or the `Nns` no-subagents form), second is `M`. The first token that is **not** a bare integer (or `<int>ns`) begins the question; everything from there is verbatim question text.
- **Escape:** if the question's own first word is a bare integer **or matches `<int>ns`** (e.g. a nanoseconds question — `1ns latency budget?`), put `--` first — everything after `--` is question text (`prism -- 3 reasons to refactor?`, `prism -- 1ns latency budget?`). `--` is not a config token; it leaves zero config tokens, so the invocation routes to the autonomous decision, not a pinned baseline.

Examples (a leading number skips auto-sizing; **no** number → autonomous decision):
- `prism Why does X?` — no number → autonomously decide `N` and `M`.
- `prism 2 Why does X?` — explicit: 2 of each, no gpt-pro → 14 dispatched + self = 15 perspectives.
- `prism 2 3 Why does X?` — explicit: 2 of each **plus** 3 gpt-pro lenses → 14 + 3 + self = 18.
- `prism 0 4 Which approach?` — `N=0` drops all seven standard tiers; 4 gpt-pro lenses → 0 + 4 + self = 5 (gpt-pro-only). `prism 0` alone is rejected.
- `prism 1ns 1 Why does X?` — no-subagents: drop the Claude tier, 6 parallax ×1 + 1 gpt-pro → 6×1+1 = 7 dispatched + self = `/8`. Same as `prism 1 1 no subagents Why does X?`.
- `prism 2ns Which design?` — no-subagents, N=2, M=0 → 12 parallax + self = `/13`.
- `prism -- 2 reasons to refactor?` — the `--` makes the leading `2` question text; `N`/`M` decided autonomously.

`M`'s accepted natural-language synonyms in the leading config zone are `<M> gpt-pro` and `plus <M> gpt-pro lenses`.

**Natural-language modifications.** The positional form always dispatches all seven models symmetrically; to deviate, state it in words **in a leading config clause before the question** (config is parsed only up to where the question begins — a modifier buried *after* the question starts is question text, not config). Treat a phrase as a modification only when it pairs a **tier name with a config action** (a count, or an exclusion word like no/skip/without); a bare tier name inside the question — e.g. *"why is there no DeepSeek fallback?"* — is **not** a modification, so do not strip or reinterpret it. Resolve modifications into an explicit per-tier count before launch. Supported:
- **Exclude a model** — "no DeepSeek", "skip GLM", "without mimo" → that tier's count = `0` (warn the user that dropping a whole lineage reduces cross-model diversity).
- **No subagents (external-only)** — "no subagents", "no Claude subagents", "without subagents", or the terse positional **`Nns`** (`prism 1ns 1 …`) → the **Claude subagent tier** alone drops to `0`; all 6 parallax tiers stay at `N` (+ gpt-pro at `M`). Resolve it to the recognized shape `Prism-Mode: partial` + `Variant: no-subagents` + `Prism-N`/`Prism-M` + `Partial-User-Quote` (**not** a bare partial — the Variant keeps the floor check). Emit it with `PL scaffold --no-subagents [--n N] [--m M] [--preset T]`. **User-only, never auto-selected.** Self becomes the lone Claude perspective; note that in synthesis (Step 4 → No-subagent run).
- **Per-model count** — "2 GPT, 1 of the rest", "3 Claude subagents" → the named tier overrides `N`; unnamed tiers keep `N`.
- **Combinations** — "2 of each but no GLM".
- **Asymmetric example**: "2 of each, but no Grok Build, and 3 DeepSeek" → Claude 2, GPT 2, **Grok Build 0**, GLM 2, Kimi 2, DeepSeek 3, MiMo 2 → Σ = 13 dispatched, 14 perspectives.

`N` (and the optional `M`) set the symmetric baseline; named modifications override specific tiers on top of it (an explicit exclusion overrides the "all seven always included" default; on conflicting clauses the more specific or later one wins). You — the orchestrator — own resolving the shorthand and NL into the dispatch records **and into the `Prism-Mode` contract** (`full` + `Prism-N` for the symmetric default; `partial` + `Partial-User-Quote` only when the user explicitly asked for a reduced set; see *Execution Spine* → Roster contract). The `relay`-unavailable exception (substitute a same-model subagent carrying that tier's lens and warn) keeps the tier present, not dropped.

### Config-presence gate (the routing decision)

Before anything else, the parser's result routes the invocation down exactly one of two paths — keyed on **what the parser resolved**, never on a re-reading of the raw string:

- **Any config token present** — a leading integer (`N`, or `N M`), the terse `Nns` no-subagents token, *or* a leading natural-language modification (a tier name paired with a count or exclusion) → **honor it verbatim and skip auto-sizing.** `M` defaults to `0` and all seven tiers are included unless a modification says otherwise — a *stated default*, not an autonomous decision. Do not consult the decision table; do not "improve" the user's `N` or `M`. `prism 2 <q>` is `N=2`/`M=0`, full stop. (One validity check, not an "improvement": `N=0` is honored only with `M ≥ 1`; `prism 0` / `prism 0 0` is rejected.)
- **Zero config tokens** (the question begins immediately; `--` also lands here) → **autonomously decide** `N` and `M` per **Choosing N and gpt-pro**. Run that decision every time; the absence of a number is never permission to fire the baseline without reasoning.

A bare tier name *inside the question* ("why is there no DeepSeek fallback?") is **not** a config token — it does not flip the gate to the explicit path.

### Choosing N and gpt-pro (decide autonomously — don't ask)

**This section runs only when the Config-presence gate routed you here — i.e. no leading number.** On a bare question, pick `N` and `M` yourself — do not ask. Use the smallest run whose extra perspectives could change the action, confidence, or rollback plan. **Default down:** each `+1` to `N` adds a full seven-model slate and slower synthesis; never raise `N` just to "be thorough." **Two independent cost axes:** `N` scales with task *difficulty* and costs **real money** (per-token API); `M` scales with *research/reasoning need* and costs **rate limit, not money** (see gpt-pro below). **Start at the bottom rung and justify each step up:** land on the *lowest* row whose situation actually matches; if you cannot name the specific extra perspective an added agent would contribute, you are at the anchor.

| Situation | N |
|---|---|
| **Easy–medium** (anchor — start here) — a Prism-worthy decision one good pass could settle | 1 |
| **Hard** — several viable options or stakeholder tradeoffs where breadth matters more than depth | 2 |
| **Extremely challenging, or a critical / big decision** — exceptional blast radius, or still underdetermined after framing | 3 |
| Beyond N=3 | only on explicit user request or documented exceptional complexity — note the larger run shape in the launch status line, not as a gate |

**gpt-pro (default M=0 — usually skip):** gpt-pro is the opt-in premium tier on **two co-equal axes — Deep Reasoning and Research-Grounded Judgment** (top-tier reasoning, plus the only tier that browses by default in a front-loaded run). It runs 5–20 min/lens, so the seven-model lineup is the default. Add **one** lens (`M=1`) when the task genuinely needs online research, deep reasoning, or the most effort/intelligence in the run; give it the posture matching that need (see GPT-Pro tier). Use **`M≥2`** (pair a Deep-Reasoning with a Research-Grounded lens) only when the task needs deep *and* wide online research with a correctness/quality guarantee. Because `M` costs **rate limit, not money** — many gpt-pro lenses fired at once force a recovery wait — keep `M` as low as the task allows and never bump the concurrency cap. You fire it yourself and just launch — do **not** pause for a confirmation or abort gate.

Note the resolved shape and its source as a one-line status line as you launch — **always show the `7N+M` arithmetic, never a bare headcount**: `<auto-sized|explicit> · N=<n>, M=<m> · dispatched 7×<n>+<m>=<D> · +self=<D+1> perspectives` (for an asymmetric run, replace `7×<n>+<m>` with the resolved per-tier sum and name the non-`N` tiers). A wrong count is then self-evidently wrong (`7×2+0=14`, never a bare `8`). Not a confirmation gate; never pause for the user to approve or redirect.

## Agents and lanes

| Tier | Tool | Role |
|------|------|------|
| Self | (none) | Your own analysis while agents run |
| Subagents | **Agent** | Same-model agents (Claude), one Agent call each |
| Parallax (×6) | **Bash** (`relay call --to <peer>`) | Cross-model agents via relay: GPT · Grok Build · GLM · Kimi · DeepSeek · MiMo |
| GPT-Pro (opt-in) | **Bash** (`gpt-pro < prompt.md`) | Additive ChatGPT Pro Extended lenses via [[gpt-pro-relay]]; composed by `prepare`, fired orchestrator-direct; **not** a relay peer / not in the parallax fan; slow + quota-burning; off by default |

### Parallax (cross-model agents)

Parallax is dispatched via `relay` to **different models**. Invoke `relay` directly — not via a subagent that calls relay. The value of each tier is **model-lineage diversity**:

| Peer | Lineage | Effort | Note |
|---|---|---|---|
| `gpt` | OpenAI | `xhigh` | agentic code-review strength |
| `grok-build` | xAI | `high` | independent of Anthropic/OpenAI |
| `glm` | Zhipu/z.ai | none (pinned max) | independent lineage |
| `kimi` | Moonshot | none (K2.7 Coding is thinking-only, no graded effort) | independent lineage |
| `deepseek` | DeepSeek (open-weight) | none (max/DeepThink) | independent lineage |
| `mimo` | Xiaomi (open-weight) | none | independent lineage |

(Full per-model version/endpoint/plan detail lives in README; it is reference, not runbook.)

**Tier strength and lens fit (heuristic for lens assignment, not a routing rule):** reasoning-capability tiering (operator-assessed; revisit as versions change) — **gpt-pro (when opted in) ≳ Claude ≈ GPT > {GLM, Kimi, Grok Build} > {DeepSeek, MiMo}**. This informs lens *placement*, not inclusion — **never drop GLM, Kimi, DeepSeek, or MiMo to "upgrade" a run**; lineage diversity is non-substitutable:
- **Subtle hard-reasoning lenses on risk-bearing questions** (Adversarial / Falsification / Disconfirming where finding the non-obvious attack is the deliverable): prefer Claude subagent or GPT (`xhigh`). If a parallax tier must take it, prefer a middle-tier peer (GLM, Kimi, or Grok Build) over the bottom tier (DeepSeek/MiMo).
- **Lenses where the value is a different prior** (Outsider, First-Principles, Reframe, Breadth-Weighted, Lateral-Generative, Stakeholder): give these to the independent lineages (GLM, Kimi, DeepSeek, MiMo) — their lineage is the asset; raw reasoning depth is not the bottleneck.

In synthesis every tier's dissent keeps full cross-model weight (discount weak reasoning, never the model label).

**Same shared prompt.** Don't tailor the prompt body per peer — Prism sends the **same shared prompt** to every model (the launcher templates handle the only per-peer difference: GPT `<goal>` vs CO-STAR XML). Optimize shared-prompt quality (an outcome-first packet + sharp, distinct lens descriptions), not per-model fit.

**Web access is not a dispatch concern — don't verify it.** Every peer can reach the web (native WebSearch + WebFetch, with verified Jina fallbacks for the two native gaps — MiMo WebSearch, GLM WebFetch; see [[relay]]). By default Prism front-loads stable evidence in the packet (Reference Materials) so agents reason over it rather than re-searching; the shared `## Grounding external facts` block (injected for every agent) directs each to verify any external / time-sensitive fact against a live source instead of answering from memory. When the *whole task* is live research, each agent researches independently (see *Shared Context* → Independent research). Either way, do **not** spend a dispatch-time step checking web support.

**Relay call syntax** — `prism-launch parallax` emits these for you (deriving each peer's fixed `--effort` from the registry); this is also the manual-fallback form:

```bash
relay call --to <peer> --name prism-<slug> [--effort <effort>] <<'BODY'
<prompt content here>
BODY
```

Only GPT (`--effort xhigh`) and Grok Build (`--effort high`) carry `--effort`; the rest omit it. For all other relay rules (`--name` required, non-empty heredoc, no model flags, concurrency) follow the [[relay]] skill.

**Inspecting results:** Read only the `.res.md` response file — never the `.log` sidecar (token-heavy stderr; the Bash output already surfaces failure diagnostics).

If `relay` is unavailable, replace all Parallax tiers with same-model subagents and warn the user. Each substitute carries the lens that tier was already assigned — do not re-decide by task category. **Exception — a no-subagents run (HARD RULE):** this fallback is **forbidden** when the user excluded subagents (the substitutes would reintroduce the very Agent calls they banned). Instead: if `M ≥ 1`, degrade to gpt-pro-only (the `N=0` shape) **only with the user's explicit OK**; if `M = 0`, **refuse** (offer: retry relay, or re-run allowing subagents). Both lanes down ⇒ refuse — self alone is not a Prism run.

**Constraint leakage risk (CRITICAL):** Relay peers may recurse unless the anti-recursion rule is explicit, early, and repeated. You MUST:
1. Put the anti-recursion warning at the top of every launcher prompt, before the file-read instruction.
2. Preserve the Constraints section verbatim in the shared context file — do not summarize or abbreviate.
3. Ensure the prohibition appears in both each launcher (short form) and the shared file (full form).
4. Tell each peer to ignore loaded skill descriptions for the dispatching/side-effecting skills (prism, relay, gpt-pro-relay, deep-research) — read-only analysis skills stay available.

Without these redundant prohibitions, the peer treats the task as a fresh request and recurses. (`prepare` checks only that each rendered launcher's first line starts with `CRITICAL:` — the content above is guaranteed by the committed templates for the script path, and is yours to emit for any hand-built launcher.)

### Subagents

Same-model agents dispatched via the Agent tool. Each gets a distinct lens. **Prism subagents may spawn their own same-model subagents at their discretion** (they're told they are spawned Prism agents; any child stays terminal — read-only, no further spawning, no cross-model dispatch, no response-file write) — but their prompts forbid starting a nested Prism run, invoking any cross-model dispatch skill (prism, relay, gpt-pro-relay, deep-research) or calling another model, and side effects, while permitting read-only analysis skills (see Constraints in the Shared Packet Template). Launch all agents concurrently before starting self-review.

### GPT-Pro tier (opt-in)

Dispatched only when the user gave `M > 0`; default count `0`. gpt-pro is **orchestrator-direct**: `prism-launch` composes each launcher for you, but **you fire the `gpt-pro` calls yourself** (one backgrounded Bash call per lens, concurrent with the parallax fan and Agent calls). It is **not** a relay peer and **not** in the `parallax` fan — never add it to `relay/peers.json` or the parallax batch (a 5–20 min lens would block the fast relay results). Each gpt-pro lens is its **own** completion notification (included in `prepare`'s printed count); collect with `prism-launch results`/`digest`. **Never raise `GPT_PRO_MAX_PARALLEL` from prism** (account anti-abuse risk).

**Gate — if `M > 0`, read `references/gpt-pro.md` before authoring the `Type: gpt-pro` dispatch records or launching.** It owns the record/posture format + canonical example, the launch command (timeout/PATH fallback), notification accounting, and collect/recovery. `prepare` validates gpt-pro records fail-closed (posture enum, key names, declared references, 5 MB caps), so a skipped read surfaces as a `prepare` bounce, not a silent defect.

## Shared Context

Build one shared evidence packet (Full Question + Context; `prepare` injects the canonical Constraints, How-to-answer, and Grounding blocks) before composing prompts. Prefer compact digests over full file dumps. Write it to a temporary file once; every agent receives a short launcher referencing this file plus its unique lens. If the packet cannot be duplicated cleanly across all agents, the task is too large for Prism.

**Neutral framing (author the packet objectively):** The packet is shared, redundant input, so any slant in it primes *every* agent the same way and manufactures false consensus — the exact failure Prism exists to avoid. Frame the Full Question, sub-questions, and lens notes to prime **no verdict**: describe *what to weigh*, never *what to conclude*. Keep your own tentative answer, ranked hypothesis, or expected outcome **out** of the packet — that belongs in your private pre-position (Step 2: Self-review), weighed *against* the fan, not broadcast to it as a shared prior. No leading language or thumb-on-the-scale emphasis; a lens note tilts *attention*, not the answer. If the user's own question arrives slanted, preserve it **verbatim** (don't sanitize or reframe it — see the template's *unchanged* Full Question) but don't amplify the slant in the Context you add, and flag it in your Step 2 pre-position so synthesis can watch for a fan that merely echoed the framing.

**Reference materials (REQUIRED):** Before building the packet, identify all reference materials relevant to the question — CLAUDE.md files, READMEs, configs, docs, skill definitions, style guides, or any file an agent would need. Agents cannot discover references on their own; if a file is not listed, the agent will not consult it.

- **Preferred — `Include:` in the dispatch.** Add `Include: <spec>` lines to the dispatch file (`/abs`, `@base-relative`, or single-level glob; plus `Include-Base:`, `Include-From: <list-file>`, `Include-Tree: <dir>`). At `prepare` time `filectx` resolves them once — generating the packet's `### Reference Materials` for the path-reading tiers **and** the gpt-pro inline list — validated, deduped, and **secret-scanned, fail-closed** (a **best-effort** deny-list of common secret files/token formats — `.env`, keys, `AKIA…`/`sk-…`/`ghp_…` etc. — refused; it is not exhaustive, so still review what you attach; override one path by excerpting it or `FILECTX_SECRETS=warn`). `scaffold` pre-prints the commented `Include:` slot, so you see the affordance every time. **`Include:` is the single source — it cannot coexist with hand-written `Reference:` keys or a `### Reference Materials` block in the packet.**
- **Manual fallback.** You may still hand-author a `### Reference Materials` list of **absolute paths** in the packet's Context (and/or `Reference:` keys for the gpt-pro-only inline list). Use this for a bespoke split or when `filectx` is unavailable; otherwise prefer `Include:`.

**Independent research for live-research tasks:** When the task requires *online* research — current facts, fresh docs, version-specific behavior, anything not settled in the repo or packet — do **not** have the orchestrator research it once and front-load the findings (a single front-loaded evidence set collapses cross-lens/cross-model diversity into a shared-evidence monoculture). Instead, state in the packet the **exact** live question(s) to answer plus any **common evidence floor** (a few authoritative sources every agent must consult and may *extend*, never replace), and direct **each agent to research the live question independently, to sufficiency rather than exhaustion, and cite + list the sources it used.** This stays redundancy, not division of labor — every agent still answers the *whole* question; only evidence-gathering is parallelized. The common floor keeps divergence comparable, and the listed sources let synthesis distinguish an information asymmetry from a genuine reasoning split (Step 4 / Step 5). Still front-load **stable** context (repo files, CLAUDE.md, configs, the question) via Reference Materials — the carve-out is for *live* evidence only and is never an excuse to skip the packet. If a research-tilted lens lands on a tier that can't reach a needed source, route that lens to a full-web tier or front-load that one source **for all agents** (labeled as provided, so the packet stays identical) — never front-load it for the gapped tier alone.

### Shared Packet Template

Write this to `/tmp/prism-<unique-id>.md` with the Write tool (one call, before any dispatch; use a unique id to avoid collisions between concurrent runs). **Write only Full Question + Context** — attach files via `Include:` in the **dispatch** (`prepare` generates the `### Reference Materials` section from them; hand-author that block here only as a manual fallback, and never alongside `Include:`). `prepare` injects `## Constraints`, `## How to answer`, and `## Grounding external facts` when absent, so you never hand-copy them.

```
## Full Question

{User's COMPLETE question/task, unchanged. Identical across all agents.}

## Context

{Shared evidence packet. Identical across all agents. Nest ALL domain content here as `###` subsections — background, constraints, sub-questions, lens notes. `## Full Question` and `## Context` are the only top-level `##` sections you author.}

<!-- Reference Materials: attach files via `Include:` lines in the DISPATCH (see Shared Context →
     Reference materials). `prepare` generates the packet's `### Reference Materials` from them,
     secret-scanned. ONLY hand-author a `### Reference Materials` block here as a manual fallback
     when NOT using Include — having both makes `prepare` abort (fail-closed, by design). -->

### Live research (omit unless the task needs live online facts)

{Name the EXACT question(s) each agent must research independently, plus any common-floor sources. Do NOT front-load findings. See the Independent research rule.}
```

`prepare` appends the canonical blocks (`templates/shared-{constraints,how-to-answer,grounding}.md`) only when absent — idempotent, so re-runs never double them. **It keys on the exact reserved heading, so a prefix-collision heading that is not the exact `##` (`## Constraints on the program`, `## How to answer the question`, …) fails closed naming the offender — keep domain content under `## Context` as `###` subsections.** To override one deliberately, author that exact `##` heading yourself (Constraints then still **fails closed** without the anti-recursion sentinel). The packet is **frozen** after `prepare` runs; agents read it live.

Launcher prompts are committed templates in `templates/` with `{{PLACEHOLDER}}` slots filled by `prism-launch` (one relay template per prompting style, selected by `relay/peers.json`'s `template` field; anti-recursion is the first line of every template). Don't hand-regenerate them. (Adding a peer/template is a `peers.json` + `lens-catalog.json` change — see README.)

## Execution Spine

The authoritative run path. `PL` = `~/.claude/skills/prism/scripts/prism-launch` — **always the absolute path**, never the bare name (the bare command is on PATH only when the shell inherited `.zshenv`; a sandboxed/non-zsh shell will not have it, and a bare-name miss must NOT trigger the manual fallback). Every subcommand needs `jq` in PATH. `prism-launch` cannot dispatch Claude subagents (only Claude can invoke the Agent tool, never `claude -p`) — you issue those Agent calls yourself.

**1. Resolve the invocation shape** (per *Invocation* + the Config-presence gate) and emit the `7N+M` status line.

**2. Write the shared packet** `/tmp/prism-<id>.md` — just `## Full Question` + `## Context` (attach files via `Include:` in the dispatch, not a hand-written block). Add a `### Live research` block only if the answer depends on live online facts (don't front-load findings). `prepare` injects Constraints / How-to-answer / Grounding.

**3. Write the dispatch file** `/tmp/prism-<id>.dispatch` **with the Write tool** (one record per agent — never a shell heredoc, and **never `scaffold > file` then edit it**). Run `PL scaffold --n <N>` first to **print** the `Prism-Mode` contract + all records in canonical order to stdout — use that output as a **copy-from template**, then author the whole dispatch in **one Write call**, replacing the `FILL` lens names + descriptions. (Authoring a brand-new file with Write needs no prior Read; *redirecting* scaffold into the dispatch and then editing it forces a wasted Read, because the harness does not track shell-created files. The line format below exists precisely so the Write tool can author it with no escaping.) At `N ≥ 2`, give each copy a **distinct** lens name — e.g. `Adversarial-A`/`-B` — `prepare` rejects duplicates. `--preset review|design|diagnosis|compare|research|decision|writing` pre-fills seven lenses (N=1), often leaving **zero** FILLs to replace. **Fastest path when a preset fits:** `PL scaffold --preset <type> --packet /tmp/prism-<id>.md --out /tmp/prism-<id>.dispatch` writes a complete, prepare-ready dispatch **directly to the file** (no Write/Edit step at all) — `--out` requires `--preset` + `--packet` so it can only ever emit a zero-FILL file (a FILL skeleton written to a file would just re-create the Read trap). **For gpt-pro:** add `--m <M>` (to any scaffold form) to emit `M` ready `Type: gpt-pro` records with canonical postures — no hand-writing the gpt-pro format; `--n 0 --m <M>` scaffolds a gpt-pro-only run (`Prism-N: 0`, legal only with `M ≥ 1`). **For a no-subagents (external-only) run** (user asked to drop the Claude subagent tier): `PL scaffold --no-subagents [--n N] [--m M] [--preset T]` emits the recognized `Prism-Mode: partial` + `Variant: no-subagents` shape (6 parallax at `N`, zero subagents) — add `--partial-user-quote "<user's words>"` with `--out`. The format is plain `Key: value` lines in blank-line-separated records — no braces/commas/quoting/escaping.

`scaffold --n <N>` prints this exact canonical contract + all seven records to stdout — copy from there. **The full annotated example + exhaustive key grammar (record types, required keys, the `Effort:`-rejected and injection-token rules) live in `references/dispatch-shapes.md`; read it when hand-authoring beyond what `scaffold` prints** (custom lenses, `N>1`, exclusions, no-subagents, gpt-pro-only, or after a `prepare` bounce).

**Roster contract** (top-level lines — `scaffold` emits them, so full is the path of least resistance):

```text
Prism-Mode: full
# Prism-N: every standard tier + subagents must be present at N (the floor check).
Prism-N: 1
# Prism-M: gpt-pro count.
Prism-M: 0
```

`prepare` then runs a **default, fail-closed** floor check: if any standard tier is missing or off-count it aborts naming the tier, before any launcher or manifest is written.

**Authorizing a reduced roster (the one authoritative how-to).** A partial roster is allowed **only when the user explicitly asked for it** (an exclusion or subset in their own words — never your inference, and never "cost / it's slow / it's flaky / these are enough"). Declare it as a high-friction, audited waiver — the double-confirm:

```text
Prism-Mode: partial
Partial-User-Quote: "<paste the user's exact words, verbatim, in double quotes>"
```

Rules: `partial` **omits** `Prism-N`/`Prism-M` (the shape is asymmetric — the records *are* the shape). The quote is stored **verbatim** — paste the user's actual words, do not paraphrase (an unverifiable paraphrase defeats the audit; `prepare` records it but cannot prove it). `prepare` records the quote + dropped tiers in the manifest `.shape` and prints a loud `⚠ PARTIAL` warning; **cite that quote in your synthesis** so a fabricated authorization is visible to the user. A `partial` with no (or whitespace-only) quote, or any `--dispatch` with **no** `Prism-Mode` line, is rejected — the enforcement cannot be dodged by omission.

**No-subagents run — the one recognized, floor-checked reduced shape.** When the user asks to drop *only* the Claude subagent tier (keeping the parallax fan), don't hand-author a bare partial — let `scaffold --no-subagents` emit it, or write the `Variant` form yourself:

```text
Prism-Mode: partial
Variant: no-subagents
Prism-N: 1
Prism-M: 0
Partial-User-Quote: "no subagents"
```

This is the **only** partial shape that keeps `Prism-N`/`Prism-M`: the Variant makes `prepare` floor-check the kept tiers (all 6 parallax at `N`, **zero** subagents, gpt-pro at `M`) — so an external-only run gets the same completeness guarantee a `full` run does, without a new top-level mode. Because it is a principled, diversity-preserving shape (not a suspicious drop), `prepare` prints a **calm informational line, not `⚠ PARTIAL`** — but it still records + expects the quote (it is a user-authorized tier exclusion; cite it in synthesis). `Variant:` is rejected on `Prism-Mode: full`, and only `no-subagents` is defined. **Fastest path:** `PL scaffold --no-subagents --preset <type> --packet … --out … --partial-user-quote "<user's words>"` writes a zero-FILL, prepare-ready external-only dispatch (the heaviest preset lens shifts onto GPT `xhigh`, so adversarial coverage survives the dropped subagent slot).

**4. Prepare** (foreground): `PL prepare --dispatch /tmp/prism-<id>.dispatch`. It compiles the dispatch into a normalized config (kept for audit), validates, renders all launchers, prints each subagent launcher's contents inline + the parallax command + the expected notification count, and writes `<id>-manifest.json`. If it exits non-zero, fix the packet/dispatch and re-run — nothing has been dispatched. (Note: `prepare` injects the canonical blocks into the packet *before* it validates the dispatch, so a failed

…(truncated)
