# supership — Full Documentation

## Getting Started

### Overview

> Supership Pipeline and Commands

# Overview

supership is a slash-command workflow kit for [oh-my-pi (`omp`)](https://github.com/can1357/oh-my-pi). It turns a non-trivial coding task into a deterministic, resumable, multi-agent run that you can watch in a live HTML dashboard.

The main agent does not hand orchestration to a nested "manager" agent. Instead it authors and runs `eval` cells (Python on omp's `workflowz` engine, using `agent()`, `parallel()`, and `completion()`) that drive the pipeline in real code with real control flow.

## Pipeline

Every run moves through five stages.

1. **Clarify.** A genius planner builds a dependency-ordered question tree, then the main agent grills you one question at a time until you are aligned. Interactive runs only.
2. **Plan.** The planner returns a structured plan (pieces, execution shape, review lenses) rendered to a `.planning/<slug>/plan.html` dashboard.
3. **Build.** Workers implement each piece, sequentially or in parallel, escalating to the architect or a debugger when stuck.
4. **Review.** Diverse reviewers fan out per lens, a judge keeps the real findings, a verifier refutes the weak ones, fixers apply the rest, and the loop re-reviews until a clean round.
5. **Consolidate.** Final dashboard state, a `## Lessons` writeup, and a debt harvest. omp's per-repo memory carries the lessons forward.

State lives in the dashboard, not in agent memory. The embedded JSON is canonical and every write is code-driven, so the artifact cannot drift and any interrupted run is resumable.

## The command family

- `/supership <task>` runs the full interactive pipeline with a clarify interview and an approval gate.
- `/shipit <task>` runs the same pipeline autonomously, with no interview and no gate.
- `/ultraship` and `/ultrashipit` replace the single planner with two genius seats that debate the plan, and review genius-tier too.
- `/superreview` runs the review-and-fix loop standalone over your current local changes.
- `resume` re-enters any interrupted run where it left off.

See [Commands](/getting-started/commands) for the full table.

```cards
# Installation
Requirements, sharp edges, and the installer.
/getting-started/installation

# How it works
The five stages, the dashboard, and eval cells.
/pipeline/how-it-works

# Ultra mode
Two genius seats debate the plan and the review.
/ultra/overview

# Standalone review
Run the review-and-fix loop over local changes.
/guides/superreview
```

---

### Installation

> Requirements, sharp edges learned the hard way, and the installer.

# Installation

## Requirements and sharp edges

supership rides on omp's subagent and config machinery, so a few version and config details matter.

> [!WARNING]
> **omp version floors.** Use **omp >= 16.2.8**. Earlier snapcompact builds can mess up long sessions (unbounded frame payloads produce an `Anthropic Internal server error` on resume, fixed by oh-my-pi PR #3866). If you ship `modelRoles` chains as YAML lists you also need **omp >= 16.3.7** (list values crash the `pi/<role>` resolver on older builds, oh-my-pi #4492). On anything older than 16.3.7, flatten each list to one comma-separated string. The semantics are identical.

The request-count governor default is too low for this kit. omp steers a subagent to wrap up at `task.softRequestBudget` and hard-aborts it at 1.5x the budget. The default of 90 silent kills at 135 requests, which this kit's builders and debuggers routinely exceed. Raise the budget and turn the notice on.

```type-table
# task settings
softRequestBudget | number | 90 | Requests before omp steers the child to wrap up; hard-abort at 1.5x. Set to 250 (warns at 250, kills at 375).
softRequestBudgetNotice | boolean | false | Off by default, so the first signal a child gets is the kill. Turn on so children can wrap up and yield.
maxRecursionDepth | number | 2 | Subagent spawn depth cap. Set to 3 so ad-hoc escalation (a task agent spawning deep-debugger) keeps its own scouts.
```

The pipeline routes its own escalation at depth 0 and works at any cap. The bump to `maxRecursionDepth: 3` is for ad-hoc use, where a `task` agent spawns `deep-debugger`, which then needs room for its own scouts (main = 0, each `agent()` child adds 1, the eval hard cap is 3).

> [!INFO]
> **Authenticate your providers.** The shipped model roles reference Anthropic, OpenAI-Codex, Google-Antigravity, and ZAI. You must have those authenticated in omp, or edit `config/modelRoles.json` to match your own catalog (check `omp models`).

## Install

```steps
# Clone and run the installer
Clone the repo, then run `install.sh`. The default copies the commands, agents, templates, and the grill skill into place. Use `--link` to symlink instead, so this repo stays the live source of truth and edits here take effect everywhere.

# Apply the config keys
Add `--config` to also apply the config keys via `omp config set`. This writes `modelRoles`, `task.maxRecursionDepth`, `task.softRequestBudget`, and `task.softRequestBudgetNotice`. The `compaction` and `memory` keys are not auto-applied; merge them from `config/config.snippet.yml` if you want them.

# Restart omp
Restart your omp session so it picks up the new commands, agents, and config.

# Verify
Try `/supership <task>` or `/shipit <task>`.
```

Clone the repo, then run the installer from its root.

```bash
git clone https://github.com/mgpai22/supership.git && cd supership
./install.sh            # copy into ~/.omp/agent + ~/.agents/skills
./install.sh --link     # symlink (edit here, live everywhere)
./install.sh --config   # also apply modelRoles + task keys via omp config
```

The installer is idempotent and never overwrites an existing `APPEND_SYSTEM.md` that differs from the shipped one. If yours differs it tells you to merge by hand.

## Install with an agent

Paste this into your coding agent and it does the setup for you.

```text
Install the supership kit for oh-my-pi from https://github.com/mgpai22/supership.
Clone the repo, run `./install.sh --config` (this copies the commands, agents, and
grill skill into ~/.omp/agent and applies the modelRoles + task config), then tell
me to restart my omp session. Reference: https://supership.shishirpai.com
```

## Plans stay out of git by default

The first run in a repo appends `.planning/` to `.gitignore` with a "delete to commit/push plans" comment. Plan dashboards are local by default, but committing them to share a plan is a supported choice. Delete the two added lines to opt in.

> [!TIP]
> Sharing a plan across a team is intentional. If you want the dashboard committed, remove the `# supership plan dashboards` block from `.gitignore` and the JSON travels with your branch.

---

### Commands

> Every command and its one-line behavior.

# Commands

| Command | Behavior |
|---|---|
| `/supership <task>` | Interactive. Clarify interview, plan, approval gate, build, review loop, consolidate. |
| `/shipit <task>` | Autonomous. The same pipeline with no interview and no gate, run end to end. |
| `/ultraship [topo] <task>` | Interactive, dual-genius. Two genius seats (`plato` + `aristotle`) debate the plan and review genius-tier. |
| `/ultrashipit [topo] <task>` | Autonomous dual-genius. Same two-planner front end, no interview, no gate. |
| `/superreview [--base <ref>] [intent]` | Standalone genius review-and-fix loop over your current local changes. |
| `<command> resume [slug]` | Re-enter an interrupted run of that command where it left off. |

## Interactive versus auto

The difference between `/supership` and `/shipit` is exactly two things. `/supership` runs the clarify interview and pauses at an approval gate so you refine the plan before anything builds. `/shipit` skips both, treats your raw request as the spec, and runs to completion. Everything after the gate (build, review, consolidate) is identical code. The ultra pair maps the same way, `/ultraship` interactive and `/ultrashipit` autonomous.

The optional topology word (`crossreview`, `duel`, or `debate`) is the first argument to the ultra commands. If the first word is not one of those, the topology defaults to `duel` and the whole argument string is the task. See [Planning topologies](/ultra/planning-topologies).

## Resume

Every command accepts `resume`. Given a slug it uses that run; otherwise it picks the newest `.planning/` dashboard whose status is not `done` or `failed` and re-enters at the right stage based on the stored status. Resume skips pieces already built and continues the review-round count from the file, so it recovers rather than redoes. See [Resume and recovery](/guides/resume-and-recovery).

---

## The Pipeline

### How it works

> The five stages, the dashboard, MODE, and eval-cell authoring.

# How it works

A supership run is five stages driven by real code. The main agent authors `eval` cells that call the named global agents and record everything to a self-rendering dashboard.

```mermaid
flowchart TD
    C[0 Clarify<br/>interactive only] --> P[1 Plan<br/>planner to plan.html]
    P --> G{Approval gate<br/>interactive only}
    G -->|approved| E[2 Execute<br/>sequential / parallel]
    E --> R[3 Review loop<br/>reviewers to judge to verify to fix]
    R -->|clean round| K[4 Consolidate<br/>Lessons + debt]
    R -->|findings remain| E2[re-review after fixes]
    E2 --> R
```

## The five stages

1. **Clarify.** The planner in CLARIFY mode returns a dependency-ordered question tree, each question carrying a recommended answer it derived from the code. The main agent then grills you one question at a time, upstream decisions first, and produces a CLARIFIED SPEC. That spec, not the raw request, becomes the run's `TASK`. Auto runs skip this entirely.
2. **Plan.** The planner in PLAN mode returns a structured plan. The main agent writes it to the dashboard. See [Planning](/pipeline/planning).
3. **Execute.** Workers implement each piece. The wave shape (sequential, disjoint parallel, or overlapping parallel) comes from the plan. See [Execution](/pipeline/execution).
4. **Review.** The shared review loop fans reviewers out per lens, judges, verifies, and fixes until a clean round. See [Review](/pipeline/review).
5. **Consolidate.** Final state is written, lessons and debt are harvested, and per-repo memory captures the lessons. See [Consolidate](/pipeline/consolidate).

## The dashboard

Durable state lives in `.planning/<slug>/plan.html`. The `<script id="plan-data">` JSON is canonical and the visible page is a derived render. Open it in a browser and it live-refreshes every five seconds while the run is active, then stops once the status is `done` or `failed`.

Every write is code-driven from the pipeline, never trusted to agent memory, so the dashboard cannot drift from reality. The file is the source of truth. Each eval cell re-reads it, which is what makes the whole run resume-safe. The page is dark, dependency-free, `file://`-safe, and renders with `textContent` only so agent text cannot inject markup.

## MODE, interactive versus auto

`MODE` is set in the first eval cell.

- **interactive** (via `/supership`, `/ultraship`) runs the clarify interview and pauses at the approval gate. The plan's status starts as `awaiting_approval`.
- **auto** (via `/shipit`, `/ultrashipit`) skips both. Cell 1 sets the approval state to `auto` and the status to `building`, so Cell 2 runs immediately.

## Eval cells and the recursion-depth rule

The main agent authors and runs the pipeline as `eval` cells with `language: "py"`, using `agent()`, `parallel()`, and `completion()`. Orchestration is never handed to a nested orchestrator agent.

Every cell is the assignment lines plus the SHARED HELPERS block plus that cell's body. The eval kernel persists state between cells, but re-including the helpers is harmless and keeps each cell runnable cold (which is how resume works).

Recursion depth is a hard contract. The main agent is depth 0, each `agent()` child adds 1, and a spawner may call `agent()` only while its depth is below `task.maxRecursionDepth` (the eval hard cap is 3). Authoring the pipeline at depth 0 keeps consultants you spawn at depth 1, which leaves them room for their own scouts at depth 2. This is why the kit asks for `maxRecursionDepth: 3`.

---

### Planning

> Planner Modes and Plan Schema

# Planning

## Modes

The `planner` agent is a genius architect with three modes. The pipeline picks the mode by what it asks for.

- **CLARIFY.** Explore the task via cheap subagents, then return a dependency-ordered list of clarifying questions, each with a recommended answer the planner derived from the code. It answers from the code whatever the code can answer and only asks what it genuinely cannot. This produces questions, not a plan.
- **PLAN.** The default. Return a concrete execution plan matching the schema below.
- **CONSULT.** An implementer is stuck on a design question mid-build. The planner is handed the plan, the piece, what was tried, and the precise question, and it adjudicates. It clarifies intent, adjusts the piece, or descopes it, and returns actionable guidance, not a new plan.

The planner never greps or browses itself. It offloads all fact-finding to cheap subagents (`david-research` for external docs and web, `explore` for the local codebase, `librarian` for library and API source) and reasons over their summaries.

## Plan schema

PLAN mode returns an object matching `PLAN_SCHEMA`.

```type-table
# Plan
mode | "sequential" \| "parallel" | (required) | sequential = one implementer does all pieces in order; parallel = pieces run concurrently.
overlap | boolean | (required) | Parallel only. true if pieces may edit the SAME files (isolated worktrees plus serial synthesis); false if they touch disjoint files.
pieces | Piece[] | (required) | Ordered, self-contained units of work. At least one, even for sequential plans.
review_lenses | string[] | (required) | Review focuses to fan out, e.g. correctness, security, edge-cases, design.
notes | string | (required) | Sequencing constraints plus synthesis and verification guidance.
```

Each piece is a small object.

```type-table
# Piece
id | string | (required) | Stable short id, e.g. p1.
description | string | (required) | Complete standalone instruction for this piece's implementer.
agent | "task" \| "deep-debugger" \| "designer" | (required) | Which agent builds the piece.
```

## Per-piece agent

The planner tags each piece with the agent that should build it. This is the build-time routing decision, a semantic call the planner makes.

- **task** for mechanical work: backend, API, data, build config.
- **designer** when the piece's primary deliverable is user-facing UI: building frontend from scratch, modifying it, or improving it (components, styling, layout, UX flows, client-side interactivity). The planner prefers splitting a half-UI, half-backend piece into a `designer` piece plus a `task` piece when both are substantial, otherwise it tags by the dominant surface. See [Frontend and design](/guides/frontend-and-design).
- **deep-debugger** only when the piece is expected to need hard diagnosis before any implementation.

## Approval gate

Interactive runs pause here. Auto runs skip straight to execution.

The main agent opens the dashboard, presents the plan in chat (shape, pieces, lenses, notes), and iterates with you. You can give feedback (which re-runs the planner with your feedback folded in, or patches pieces directly), or you can edit the JSON in the dashboard file yourself and say "re-read" to have the run reload your edits.

Nothing builds until you approve. On approval the run records the approval state, stamps the time, sets the status to `building`, and only then starts Cell 2.

---

### Execution

> Build Waves and Escalation

# Execution

Cell 2 executes the plan. The wave shape comes from the plan's `mode` and `overlap`. Execution is resume-safe and only touches pieces whose status is not already `done`.

## Build waves

**Sequential.** When the plan is `sequential` (or only one piece is left to do), one worker builds the pieces in order on the shared working tree, no isolation.

**Disjoint parallel.** When the plan is `parallel` with `overlap=false`, the pieces touch disjoint files, so they run concurrently on the shared tree directly. There is no race because no two pieces edit the same files.

**Overlapping parallel.** When the plan is `parallel` with `overlap=true`, the pieces may edit the same files. Each builds in an isolated git worktree in patch mode (`merge=false`, `apply=false`, `handle=true`) so its edits stay in the worktree and never apply concurrently. The pipeline collects each piece's patch, then a serial **Synthesize** step applies and reconciles the patches in order, resolving conflicts, and builds or lints to confirm it compiles.

> [!NOTE]
> If isolation is unavailable (not a git repo, or omp's isolation mode is off) or an isolated build raises, that piece falls back to a sequential build on the shared tree, where the full stuck contract still applies.

Dashboard writes happen at the driver level, between and after waves, never from inside a `parallel()` thunk. Concurrent writes would race and drop sibling updates.

## Stuck contract

A builder that hits a wall does not thrash and does not spawn a debugger itself. It stops, leaves its work in place, and returns `status="stuck"` with a `kind` (`bug` or `design`), what it `tried` (including the exact error), and the precise `question` to escalate.

## Escalation

The pipeline reads the stuck signal and consults the right specialist, at depth 1 so the consultant keeps its own scouts.

- **kind = design** goes to the architect, the `planner` in CONSULT mode. On an ultra run this is re-adjudicated by the challenger (`aristotle`) instead, since the model that red-teamed the plan is best placed to reopen it.
- **kind = bug** goes to `deep-debugger` for root-cause diagnosis.

## Guided retry

After a consult, the builder is re-dispatched **once** with the guidance folded into its prompt (labeled `build:<id>:retry`). If it comes back done, the piece is done. If it is still stuck, the piece is surfaced as unresolved in the dashboard rather than looping forever.

## salvage_yield

omp hard-aborts a subagent at 1.5x `task.softRequestBudget`. That abort can land after the child finished its work but before its final yield was recorded, which would misfile a finished piece as an error.

Before writing a piece off, `run_build` calls `salvage_yield`, which reads the child's transcript, finds the final `yield` tool call, and recovers its result. If that recovered result says `status="done"`, the piece is marked done (tagged as salvaged) rather than lost. Raising `task.softRequestBudget` is what actually prevents the kill. See [Resume and recovery](/guides/resume-and-recovery).

> [!TIP]
> When a piece dies to a subscription limit rather than a budget kill, the build also flips to the other pool provider and re-dispatches the piece once there. See [Load balancing](/guides/load-balancing).

---

### Review

> The Review Loop Engine

# Review

Review is the shared `run_review_loop()` engine. The pipeline and the standalone `/superreview` command both drive this exact function, so an improvement to the review engine lands in both at once. The loop mutates the run state and the working tree, and the caller consolidates afterward.

## Lenses

The loop reviews per lens. It starts from the plan's `review_lenses` (default `correctness`, `security`, `edge-cases`, `design`), then always appends a standing **over-engineering** lens (the ponytail rubric). If frontend changed, it also appends a **design** lens. See [Frontend and design](/guides/frontend-and-design).

## Round by round

Each round runs this sequence. Everything after the reviewers is shared between the normal path and the [ultra path](/ultra/review).

1. **Reviewers fan out per lens.** Each lens gets a `deep-reviewer` running a model drawn from the `modelRoles.reviewers` diversity set (entries alternate across lenses so different lenses get different eyes). The `design` lens goes to the `designer` agent instead. `deep-reviewer` carries no native output schema, so the call-site findings schema applies cleanly, which sidesteps an intermittent schema violation with omp's bundled reviewer (oh-my-pi #3926).
2. **The judge keeps the real findings.** A `completion(model="slow")` judge rules on each finding and drops nits, dupes, and false positives, then emits a per-lens verdict (`clean` or `issues_remain`).
3. **The numeric gate.** Only actionable, high-confidence defects pass: `priority <= 1` and `confidence >= 0.6`. The count that survives this gate is recorded as `kept`.
4. **The refute-verifier gates the fixers.** The judge rules on the finding *text*, never the code, so a plausible-but-wrong finding can survive. To close that gap, each kept finding is handed to a per-finding verifier (`task` agent) that tries to *disprove* it against the actual code. A finding is dropped unless it comes back confirmed with concrete evidence (`file:line` plus why it is a real defect). The gate is **fail-open**. A verifier that errors keeps its finding, so infra noise never silently drops a real bug. The `verify_findings` knob (default on) disables it. The count that survives verification is recorded as `confirmed`.
5. **Fixers apply the confirmed findings.** Findings are grouped by file and fixed in parallel across distinct files. A fix on a frontend file routes to the `designer`; everything else goes through the task pool.
6. **Re-review.** Fixes land on the shared tree so they accumulate, and the next round re-reviews them.

## Exit conditions

Each round records `found` (raw reviewer findings), `kept` (after the numeric gate), `confirmed` (after verification), and the per-lens verdicts, all in the dashboard.

The loop exits when any of these is true.

- A round finds nothing, or a round confirms nothing (everything was refuted). Both count as clean.
- The round count hits `MAX_ROUNDS` (default 3) with findings still open.
- The remaining budget drops below the reserve floor (checked at the top of each round).

An all-refuted round counting as clean is deliberate. It means the reviewers raised only things the verifier could not stand up against the real code.

---

### Consolidate

> Final dashboard state, Lessons, ponytail-debt harvest, and per-repo memory.

# Consolidate

The last stage closes out the run. Cell 2 sets the run status to `done`, saves the dashboard (which stops its live refresh), and prints a summary: the plan shape, each piece's status, the review rounds, the unresolved list, and whether the run ended clean.

A run counts as **clean** when the last review round confirmed nothing and there are no unresolved pieces. A round whose findings were all refuted also breaks clean.

## Lessons

After Cell 2 returns, the main agent writes a `## Lessons` section for you: recurring mistakes, dead-ends, and gotchas seen across planning, building, and review.

## Debt Harvest (powered by [ponytail skill](https://github.com/DietrichGebert/ponytail))

The build prompts encourage marking deliberate shortcuts with a `// ponytail:` comment naming the ceiling and the upgrade path. Consolidation harvests them by grepping the diff and the touched files for `ponytail:` markers, then lists each one with its ceiling and upgrade path under a `## Ponytail debt` heading.

## Patching the artifact

Both writeups are patched back into the dashboard with a small eval so the artifact is complete and self-contained.

```py
S = load_state()
S["lessons"] = """..."""
S["ponytail_debt"] = ["file:line (marker text)", ...]
save_state(S)
```

The main agent then points you at `.planning/<slug>/plan.html` for the final render.

## Per-repo memory

With `memory.backend: local`, omp captures the consolidated lessons into per-repo memory, so they carry into future sessions in the same repo. The dashboard is the artifact for this run; memory is what carries the learning forward.

---

## Ultra Mode

### Overview

> The two genius seats, chain resolution, plan-time freezing, and loud-fail.

# Ultra mode

The base pipeline plans with a single genius. The ultra variants (`/ultraship`, `/ultrashipit`) run the **exact same pipeline** but replace that one planner with two genius seats that debate the plan before anything builds, then hand the agreed plan to the unchanged execute-and-consolidate machinery. Ultra reviews genius-tier too.

## The two seats

Both are model-role seats you configure in `modelRoles`.

- **`plato`** is the chief architect and final consolidator. It always owns THE plan.
- **`aristotle`** is the challenger. It red-teams and never rubber-stamps. It's better to use a different model for this.

## Why the pipeline resolves the chains itself

omp's `pi/<role>` alias resolver is hard-gated to built-in role names (verified through omp 16.3.15). A custom role like `pi/plato` passes through unresolved, and omp then *silently* spawns an undefined-model session, discarding the error.

So the pipeline does not rely on the alias. Cell 1 reads `modelRoles` from config itself, normalizes each chain to a comma-joined fallback string, and passes it via `model=`. A call-site `model=` overrides the planner agent's own frontmatter chain, so the geniuses you configured are the ones that run.

## Plan-time freezing

The two resolved chains are frozen into the run state at plan time, stored in `meta.ultra` alongside the topology. Editing `modelRoles` mid-run does not retarget an in-flight or resumed run. The review stage reads the seats from that frozen state, not live config, so a resumed run keeps its ultra identity and reviews with the same brains that planned. Plan-time identity is deliberate.

## Loud-fail

Ultra refuses to degrade to a single genius. Cell 1 asserts that both `plato` and `aristotle` are configured and non-empty. If either is unset, the run fails loud rather than quietly planning with one seat.

## Fresh-eyes consult

In an ultra run, a `design` escalation from a stuck builder is re-adjudicated by the challenger (`aristotle`), not the plan's author. The model that red-teamed the plan is best placed to reopen it. `bug` escalations still go to `deep-debugger`.

## Where to go next

- [Planning topologies](/ultra/planning-topologies) covers crossreview, duel, and debate.
- [Ultra review](/ultra/review) covers the genius review duel.

---

### Planning topologies

> Crossreview, Duel, and Debate

# Planning topologies

The ultra planner has three topologies, selected by the first word of the command arguments. The default is `duel`. If the first word is not a topology name, it is treated as part of the task.

| Topology | Genius calls | Flow | Use when |
|---|---|---|---|
| `crossreview` | 3 | plato plans, aristotle red-teams it, plato revises its own plan | cheapest sanity check on a single strong plan |
| `duel` | 5 | both plan blind in parallel, each red-teams the rival's plan, plato synthesizes | you want two genuinely independent takes reconciled |
| `debate` | 7 | duel through the critiques, then one revision round (each revises its own plan given the rival plus the critique it received), plato synthesizes | highest-stakes plans worth a full argue-and-refine |

## crossreview (3 calls)

The cheapest topology. `plato` produces a plan, `aristotle` red-teams it, and `plato` revises its own plan to address every valid critique point. One strong author, one challenge, one revision.

## duel (5 calls)

`plato` and `aristotle` plan **blind** in parallel, neither seeing the other's work. Then each red-teams the rival's plan in parallel (`plato` critiques aristotle's plan and vice versa). Finally `plato` synthesizes THE plan from both plans and both critiques. This is the default.

## debate (7 calls)

Everything duel does through the cross-critiques, then exactly one revision round. Each genius revises its **own** plan given the rival's plan and the critique it received, stealing the rival's best ideas. Then `plato` synthesizes from the two revised plans plus both critiques. The revision round is hard-capped at one; there are no convergence loops.

## Synthesis

Every topology ends with `plato` as the sole owner of the final plan. Synthesis is never a committee merge. `plato` adopts the strongest elements, discards the rest, and records in the plan `notes` exactly what it took from the aristotle plan or critique and what it rejected and why.

> [!NOTE]
> The topology controls the **planning** shape only. Ultra review is always a fixed duel regardless of the planning topology. See [Ultra review](/ultra/review).

---

### Ultra review

> The Genius Review Duel

# Ultra review

Ultra runs review genius-tier too. Each review round is a fixed duel of the same two seats read from the frozen run state.

## The duel

1. **Blind review.** `plato` and `aristotle` each review the diff blind, in parallel. This is one holistic pass covering **all** lenses at once. The lenses become a rubric rather than a per-lens genius fan-out, which would blow up cost. The persona stays `deep-reviewer` (for the clean call-site schema); only the model is the genius chain.
2. **Cross red-team.** Each seat red-teams the *rival's* findings against the actual code, adversarially, with concrete evidence.
3. **Synthesis.** `plato` synthesizes the final kept set as sole owner, plus a verdict per lens. It keeps only findings that survived the cross-red-team with evidence and drops nits, dupes, and false positives.

## Subsuming the verifier

In the normal loop, a per-finding refute-verifier gates the fixers. In an ultra round there is no separate verify pass. The cross-red-team already tried to knock each finding down, so the synthesis output *is* the confirmed set. Kept equals confirmed with no task-tier verify spawns.

The synthesis output still passes through the same numeric gate (`priority <= 1`, `confidence >= 0.6`) as the normal path.

## A fixed shape

Ultra review is always a duel, regardless of the planning topology. Crossreview and debate do not map to review. You do not "revise a review"; you re-review after fixes, which the outer round loop already does. Cost is bounded to roughly five genius calls per round, with an early exit on a clean round and a cap at `MAX_ROUNDS`.

## Shared back half

Ultra swaps only the front half of `run_review_loop`. The reviewer fan-out plus the judge are replaced by the genius duel of `ultra_review_round()`. Everything after "here are the confirmed findings" is the **identical code** the normal loop runs: the numeric gate, the fixers, the round loop, `MAX_ROUNDS`, the budget gate, clean detection, and the `found` / `kept` / `confirmed` dashboard records. Normal `/supership` runs are byte-for-byte unaffected.

> [!INFO]
> Ultra review rides the same `ULTRA` flag as ultra planning. There is no new config and no new command. You cannot get ultra review on a normally-planned run, which is an accepted non-goal. The one exception is [`/superreview`](/guides/superreview), which is always ultra.

---

## Guides

### Standalone review

> Standalone Always-ultra Review

# Standalone review

`/supership` reviews as the last stage of a full plan-build-review run. `/superreview` peels that review stage off into a standalone command you point at any local changes: a diff you wrote by hand, or the output of a previous supership run you want a second, harder pass on.

It runs the **exact same engine**, the shared `run_review_loop()`, seeded with a review-only state and no plan or build. There is no clarify and no approval gate.

```
/superreview [--base <ref>] [--slug <slug>] [free-text intent...]
```

## Always ultra

`/superreview` is always the `plato` and `aristotle` genius duel. There is no normal-tier or lite mode; that is `/supership`'s inline review. The seats are resolved live from config at review start (there is no plan to freeze them) and frozen into this run's state, and the run loud-fails if either seat is unset. It reuses the `plato` and `aristotle` keys, so there is no new config.

## Diff-target detection

The command decides what to review before authoring the cell, in this order.

1. It must be a git repo, or there is nothing to review.
2. If `--base <ref>` was given, review the range since that ref.
3. Otherwise, if the working tree is dirty (any uncommitted or untracked files), review the working tree. This is the "I just made changes" or "I just ran supership" case.
4. Otherwise (clean tree), review the current branch against its merge-base with the default branch. The default branch is the basename of `origin/HEAD` (falling back to `main`, then `master`, then `HEAD~1`).

Re-review always diffs the same fixed base, so fixes accumulate across rounds rather than shifting the target under you.

## Intent

The free-text argument is what the change is meant to do, plus any scope or non-goals (for example, "tightening the auth refactor; ignore vendored/"). Omit it and the reviewers infer intent from the diff plus recent commit messages. There is no plan to anchor scope, so reviewers lean toward defects in what changed.

## Dashboard and resume

`/superreview` writes a `.planning/review-<MMDD-HHMM>/plan.html` dashboard (override the slug with `--slug`), the same live UX as the pipeline: rounds, findings, and verdicts. It fixes on the shared tree (the full review, fix, and re-verify loop, not just a report). It is resumable via `/superreview resume`, which re-enters the loop against the original base, continues the round count from the file, and preserves fixes already applied.

Because it shares `run_review_loop()` with the pipeline, the frontend design lens and the `is_frontend` fix routing apply here too. See [Frontend and design](/guides/frontend-and-design).

## Local only

`/superreview` reviews the local working tree only. There is no PR or GitHub integration. For GitHub PR review, use the built-in `/code-review` or `/review`.

---

### Frontend and design

> The Designer Agent and Routing

# Frontend and design

Anything user-facing routes through the `designer` agent, omp's UI/UX specialist (model `pi/designer`), instead of the generic `task` worker. The designer is design-system-first and accessibility-aware, and it handles frontend end to end: build, review, and fix. There is no new config; this reuses the existing `modelRoles.designer` chain.

## Build

The planner tags any piece whose primary deliverable is UI as `agent="designer"` (building frontend from scratch, modifying it, or improving it). The build wave dispatches those pieces to the designer, with no pooling. Backend, API, and data pieces stay `task`. This is a semantic call the planner makes at plan time. See [Planning](/pipeline/planning).

## Review

When the change touched frontend, the review loop adds a **design lens**.

- On a normal run, the design lens is reviewed by the designer (it does not consume a reviewer-model slot, which keeps the diversity alternation stable).
- On an ultra run, the design rubric is folded into the `plato` and `aristotle` duel instead of spawning a third reviewer.

## Fix

Review fixes on a frontend file are dispatched to the designer, not the task pool, so the agent correcting UI findings has design instincts too. If the designer fix errors, it falls back to the task pool.

## is_frontend detection

Build routing is the planner's semantic call. Review and fix routing is mechanical, because after the fact the only signal available is the file path. The `is_frontend(path)` check matches a known UI extension or a UI-ish path segment.

- **Extensions:** `.tsx`, `.jsx`, `.vue`, `.svelte`, `.astro`, `.css`, `.scss`, `.sass`, `.less`, `.html`, `.htm`, `.mdx`.
- **Path segments:** `components`, `component`, `styles`, `style`, `ui`, `pages`, `views`, `layouts`.

The check is approximate and tunable. A `.ts` file full of DOM logic will not match, which is an accepted tradeoff. `/superreview` uses the same `is_frontend` signal over its diff.

> [!NOTE]
> Two detection paths, split by where they happen. Build routing is the planner's call, encoded in the piece `agent`. Review and fix routing is the mechanical `is_frontend(path)` glob. Both send frontend work to the same designer.

---

### Load balancing

> The Task Pool and Health Checks

# Load balancing

omp's `modelRoles` chains are fallback-only. The first resolvable model always wins, there is no native rotation, and a provider's in-flight cap queues work rather than spilling it to another provider. So the pipeline load-balances plain `task` spawns itself, across models and subscriptions, via `agent(model=...)`.

This covers plain `task` builders, fixers, and review verifiers. **Genius agents never pool.** The planner, deep-debugger, and the ultra seats always run their own explicit chains.

## Task pool

The pool is configured, not a cell constant. It comes from `modelRoles.taskpool`.

- Entries are single model patterns.
- Weight an entry by repeating it in the list.
- `taskpool: []` **disables** pooling, so spawns run with `model=None`.
- Omitting the key falls back to the shipped default pair.

## Round-robin

Routing is deterministic by piece order (which is what makes it resume-safe). Each spawn picks a pool entry by a stable index derived from the piece id or its position, then walks forward past any unhealthy entry.

## Health checks

Routing is subscription-aware in two layers, both reading omp's own durable usage ledger at `~/.omp/agent/agent.db` (the same data `omp usage` shows).

**Proactive.** Before each spawn, the pipeline reads the ledger (`usage_history` for the used-fraction and status per limit window, plus `auth_credential_blocks`) and walks past any pool entry whose subscription is exhausted (at or above `POOL_FULL`, default 0.95) or whose credentials are all blocked. Model-class-scoped limits are respected, so an exhausted `anthropic:7d:fable` window does not gate a sonnet spawn. The check is **fail-open**. If the ledger cannot be read, the entry counts as healthy.

**Reactive.** If a spawn dies with a usage-limit, quota, or auth-exhaustion error (omp gives up after at most three fast internal same-provider retries), the pipeline re-dispatches that piece once on the other provider and skip-lists the failed provider for 30 minutes, so subsequent pieces route away proactively. Ordinary task failures never trigger cross-provider fallback.

## Multiple accounts

Several Claude Max or Codex logins compose cleanly. omp natively hash-sticks each subagent session to one account and rotates off blocked or exhausted siblings, so intra-provider spreading is automatic. The proactive check evaluates the ledger per account and only marks a provider unhealthy when every account is drained or credential-blocked. One healthy Max account keeps the whole anthropic pool entry usable.

> [!NOTE]
> `taskpool` is a **pool** (round-robin plus health checks), which is a different thing from a fallback chain (first resolvable wins) or the `reviewers` **diversity set** (entries alternate across lenses). See [Configuration](/reference/configuration).

---

### Resume and recovery

> Resume and Budget Recovery

# Resume and recovery

Every command accepts `resume`. Because the dashboard file is the source of truth and every eval cell re-reads it, a run can pick up cold.

## Resume

Given a slug, resume uses that run. Otherwise it picks the newest `.planning/` dashboard whose status is not `done` or `failed`, then branches on the stored status.

- `awaiting_approval` re-enters the approval gate.
- `building` or `reviewing` re-runs Cell 2 as-is. It skips pieces already `done` and continues the review-round count from the file.
- `planning` or `clarifying` (rare, died mid-plan) restarts Cell 1 from the stored spec.

## Interrupted eval cells

An interrupted eval cell (a `KeyboardInterrupt`) does **not** kill the `agent()` jobs it spawned. They keep running in the background and usually finish, writing their result to the session artifacts (`<label>.md`, also retrievable with the eval `output("<job id>")` helper; check `/jobs`).

So recover, do not redo. Check the job first. If it is still running, wait or poll it. If it finished, fetch its result and continue the pipeline from that exact point. Respawning burns the money already spent and orphans a live genius job.

## Budget kills

omp caps each subagent at `task.softRequestBudget` requests. At the budget it may steer the child to wrap up (only if `task.softRequestBudgetNotice` is true), and at 1.5x it hard-aborts, sometimes in the exact instant the child is yielding `status="done"`. `run_build` salvages that case automatically via `salvage_yield`. If a piece still lands unresolved with this error:

1. The child's edits survive in the working tree. Run `git status` before assuming loss; its transcript holds its findings.
2. Re-dispatch as a **continuation** ("prior work is on disk at `<files>`; verify and finish, do not restart"), never a from-scratch redo.
3. For heavy pieces (debuggers routinely need 150-plus requests), raise `task.softRequestBudget` and enable `task.softRequestBudgetNotice` so children get the wrap-up warning instead of a silent kill.

> [!DANGER]
> **Never downgrade a genius to a generic worker.** Do not re-route planning, consult, or debug work to a generic worker as a "faster fallback." The task tool's `role=` field is a display persona, not an agent selector. A task item without an explicit `agent="planner"` runs on the generic task worker, silently swapping the genius brain for a cheap one. If the genius genuinely cannot run, stop and tell the user. Repeated interrupts are an environment problem to surface, not to code around with a weaker spawn path.

---

### ax web fetch

> The Web Fetch and Extract CLI

# ax web fetch

`ax` is the AI-era curl. It fetches a URL, discovers page structure, and extracts rows or tables in one command.

## Why the kit ships it

Agents reach for `curl` and get nothing back on an empty body. Or they dump raw HTML into context and blow the token budget. Or they hand-roll regex over markup that breaks on the next page. `ax` replaces all three. It returns structured status and body, never goes silent, and caps output at 50 rows by default so a page cannot flood the window. The kit ships a matching `ax` skill so every agent knows the discover-then-extract workflow.

## Cheatsheet

```sh
ax https://api.site.example/users                 # {status, ok, ms, headers, body}
ax https://api.site.example/x -H 'authorization: Bearer k' -X POST -d '{"a":1}'
ax https://site.example --outline                 # discover repeating structures
ax https://site.example --locate 'some text'      # find which selector holds text
ax https://site.example '.card' --count           # confirm a hypothesis
ax https://site.example '.card' --row 'title=a, href=a@href'
ax https://site.example 'table' --table --where 'Stars >= 30000'
ax https://docs.site.example/guide --md --budget 800
```

Fetch or `--outline` once, `--locate` or `--count` to confirm, then one `--row` or `--table` call. Repeat fetches of the same URL are cached for about two minutes, so probing is cheap. Every extraction prints `N rows extracted` on stderr, which is the verification.

## Install

`ax` is pinned to v0.1.5 and vendored next to the skill so the agent instructions match the binary. `install.sh` installs it automatically into `~/.local/bin` (override with `AX_INSTALL_DIR`), verifies the download against the published sha256 checksum, and skips when `ax` is already present. If you already had a different `ax` version installed, the installer keeps yours, so the skill-matches-binary guarantee only holds for the auto-installed pin. To install by hand, run `curl -fsSL https://ax.yusuke.run/install | sh`.

## When not to use it

- JS-rendered SPAs. If `ax` reports a likely SPA, the data is not in the raw HTML, so switch to the browser tool.
- Local files and non-web work. Use your normal read and search tools.

---

## Reference

### Agents

> The Agent Roster

# Agents

The kit ships a roster of global agents. The pipeline spawns them by name via `agent(...)`. Each agent's model comes from its own frontmatter chain, except where the pipeline overrides it with a call-site `model=` (the reviewers and the ultra seats).

| Agent | Model | Purpose |
|---|---|---|
| `planner` | genius chain | Architect. Three modes: CLARIFY (question tree), PLAN (structured plan), CONSULT (adjudicate a stuck builder's design question). Investigates only via cheap subagents; never implements. |
| `task` | `pi/task` (the task pool) | Mechanical worker. Does the actual implementation, offloads research to scouts, and returns a `stuck` signal instead of thrashing. |
| `deep-debugger` | genius chain | Root-cause diagnostician. Read-only; returns the cause plus the exact fix and how to verify. Does not implement. |
| `deep-reviewer` | genius tier, varied per call | Clean reviewer with no native output schema, so call-site schemas apply cleanly. The pipeline overrides its model per lens (reviewers diversity set) and per ultra seat. |
| `designer` | `pi/designer` | UI/UX specialist. Builds, modifies, and improves frontend pieces, reviews the `design` lens, and fixes frontend findings. Design-system-first and accessibility-aware. |
| `david-research` | `pi/smol` | Cheap external research scout (web, docs, repos, APIs). Keeps internet context out of the parent. |
| `review-orchestrator` | genius chain | Legacy manual review-loop orchestrator. Superseded by the in-pipeline `run_review_loop()`; kept for standalone, non-eval use. |

The exact model strings live in the `modelRoles` config and in each agent's frontmatter chain, and both are tunable. See [Configuration](/reference/configuration).

## Bundled omp scouts

The planner and the genius agents also spawn omp's own bundled scouts, which are not part of this kit: `explore` (read-only local codebase scout) and `librarian` (library and API source). Both run on the cheap `smol` role. These keep fact-finding off the expensive genius reasoning.

> [!NOTE]
> Agent selection is an invariant, not a preference. Plan and consult go to `planner`, hard diagnosis to `deep-debugger`, review to `deep-reviewer`, always via an explicit `agent=`. A `role=` string alone never substitutes for `agent=`. See [Resume and recovery](/guides/resume-and-recovery) for why this matters.

---

### Configuration

> modelRoles and Settings

# Configuration

supership relies on a set of `modelRoles` plus a few `task`, `compaction`, and `memory` keys. Apply them with `./install.sh --config`, or merge `config/config.snippet.yml` by hand.

## modelRoles

```type-table
# modelRoles
default | chain | (main agent) | Fallback chain for the main agent.
smol | chain | (scouts) | Cheap scouts: david-research, explore, librarian.
slow | chain | (reviewer tier) | The reviewer tier and the review judge.
plan | chain | (genius) | The genius chain for planner and deep-debugger.
task | chain | (workers) | Fallback chain for the mechanical task worker.
advisor | chain | | Advisor genius chain.
designer | chain | (pi/designer) | The designer agent's chain for frontend build, review, and fix.
plato | chain | (loud-fail if unset) | Ultra seat: chief architect and final consolidator.
aristotle | chain | (loud-fail if unset) | Ultra seat: challenger.
taskpool | pool | default pair | Load-balancing pool for task builders, fixers, and verifiers.
reviewers | diversity set | default pair | Reviewer models that alternate across the review lenses.
```

## task, compaction, memory

```type-table
# task / compaction / memory
task.maxRecursionDepth | number | 2 | Set to 3. Depth cap for subagent spawns; 3 keeps ad-hoc escalation's scouts alive.
task.softRequestBudget | number | 90 | Set to 250. Requests before wrap-up; hard-abort at 1.5x.
task.softRequestBudgetNotice | boolean | false | Set to true, so children get a wrap-up warning instead of a silent kill.
compaction.strategy | string | | Use snapcompact (needs omp >= 16.2.8); older builds should use shake.
memory.backend | string | | local captures consolidated Lessons into per-repo memory.
```

The installer's `--config` applies `modelRoles`, `task.maxRecursionDepth`, `task.softRequestBudget`, and `task.softRequestBudgetNotice`. The `compaction` and `memory` keys are not auto-applied; merge them from the snippet if you want them.

## Chain versus pool versus diversity set

These three read differently.

- **A role is a fallback chain.** Entries are tried in order and the first resolvable model wins. There is no rotation. `default`, `smol`, `slow`, `plan`, `task`, `advisor`, `designer`, `plato`, and `aristotle` are all chains.
- **`taskpool` is a pool.** The pipeline round-robins and health-checks each entry per provider to load-balance across subscriptions. Entries are single model patterns; weight one by repeating it; `[]` disables pooling; omitting the key uses the default. See [Load balancing](/guides/load-balancing).
- **`reviewers` is a diversity set.** Entries alternate across the review lenses (model index `i % len`) so different lenses get different eyes. An entry may itself be a comma-joined chain, but the list as a whole is not a fallback chain.

> [!WARNING]
> Chains ship as YAML lists and require omp >= 16.3.7. On older builds, flatten each list to one comma-separated string. The semantics are identical. See [Installation](/getting-started/installation).

---

### Architecture

> Eval Cells and State Model

# Architecture

## Eval cells

The main agent authors and runs the pipeline as `eval` cells (`language: "py"`) on omp's `workflowz` engine. Three primitives drive everything:

- `agent(prompt, agent=..., model=..., schema=..., label=...)` spawns a named subagent and returns its structured result.
- `parallel([...])` runs a list of thunks concurrently and returns their results in order.
- `completion(prompt, model=..., schema=...)` runs a single model completion (used for the review judge).

Control flow is ordinary Python. The main agent authors this at depth 0 rather than delegating to a nested orchestrator.

## SHARED HELPERS

Every cell is the assignment lines plus the SHARED HELPERS block plus that cell's body. The helpers block holds:

- **State I/O.** `save_state(S)` renders the dashboard from canonical JSON, `load_state()` parses it back, `plog(S, phase, msg)` appends a progress-log entry and saves, and `ensure_gitignore()` keeps `.planning/` out of git by default.
- **`read_model_roles()`.** Reads `modelRoles` from omp config inside a cell body. Fail-open. Any error returns `{}` so callers fall back to their own defaults.
- **Schemas.** `PLAN_SCHEMA`, `FINDINGS_SCHEMA`, `JUDGE_SCHEMA`, `BUILD_SCHEMA`, `VERIFY_SCHEMA`, and `UREVIEW_SCHEMA` (the ultra synthesis output, which reuses the findings and judge sub-schemas verbatim so the two review paths stay interchangeable).
- **`is_frontend(path)`.** The mechanical frontend glob used for review and fix routing. See [Frontend and design](/guides/frontend-and-design).
- **`review_diff_hint(base)`.** What reviewers are told to inspect (the working tree by default, a committed range when a base is given).
- **`run_review_loop(...)`.** The whole review engine (see below).

The load-balancing pool helpers (`pool_healthy`, `pool_model`, `pool_alt`) live in Cell 2's POOL block, not in the shared helpers. `run_review_loop` reaches for them lazily from the calling cell's globals at call time, which is why `/superreview` pastes both the helpers and the POOL block.

## Shared review engine

`run_review_loop()` is the single review-fix-reverify loop, factored out so `/supership` Cell 2 and the standalone `/superreview` drive the **identical** code. Fix it once, and both improve. Ultra versus normal is chosen inside the loop by whether `S["meta"]["ultra"]` is set; the two paths differ only in the front half and share the entire back half. See [Review](/pipeline/review) and [Ultra review](/ultra/review).

## State model

The canonical state `S` is a single JSON object embedded in the dashboard.

```type-table
# S
meta | object | | task, slug, mode, created, updated, status, plus ultra (topology + seats) and base when present.
spec | string | | The CLARIFIED SPEC (or the raw task in auto mode). This is the run's TASK.
plan | object | | The plan (mode, overlap, pieces, review_lenses, notes), with per-piece status and summary.
approval | object | | state (pending / approved / auto), at, notes.
progress_log | array | | Timestamped phase and message entries.
review_rounds | array | | Per round: found, kept, confirmed, verdicts.
findings | array | | Confirmed findings across rounds.
unresolved | array | | Pieces surfaced as unresolved, each with a reason.
lessons | string | | The consolidated Lessons writeup.
ponytail_debt | array | | Harvested // ponytail: markers with ceiling and upgrade path.
```

Every write is code-driven from the pipeline, so the artifact cannot drift from reality, and each cell re-reads the file so the run is resume-safe.

## Recursion depth

The main agent is depth 0, each `agent()` child adds 1, and a spawner may call `agent()` only while its depth is below `task.maxRecursionDepth` (the eval hard cap is 3). Authoring at depth 0 keeps consultants at depth 1 with room for their own scouts at depth 2. The full escalation chain (`task` to `deep-debugger` to its scouts) needs `maxRecursionDepth >= 3`; the default of 2 blocks the innermost spawn.

---

## Changelog

### Changelog

> Merged Changes

# Changelog

Every merged pull request, newest first. Regenerated from GitHub on each deploy, so it always reflects what shipped.

- [#4](https://github.com/mgpai22/supership/pull/4) docs: petit documentation site, Cloudflare deploy, and per-PR changelog (2026-07-10)
- [#3](https://github.com/mgpai22/supership/pull/3) Route frontend work through the designer agent (2026-07-10)
- [#2](https://github.com/mgpai22/supership/pull/2) /superreview: standalone genius review and fix over local changes (2026-07-10)
- [#1](https://github.com/mgpai22/supership/pull/1) Ultra review: genius-tier adversarial review on ultra runs (2026-07-10)

---
