# Task Pipeline

> Use when work changes the repository — feature, fix, refactor, migration, integration, rewrite, adoption or hardening; фича, фикс, рефактор, миграция, интеграция, доработать, починить, внедрить, перевести — or when the output is a finding that lands in it: audit/аудит, bug hunt/проверь ошибки, production check/проверь прод, PR review/ревью PR — or on 'run this through the pipeline' / 'прогони по конвейеру', 'full cycle, the full cycle' / 'полный цикл', /task-pipeline. Runs a substantial task through an intake grill, docs study, brainstorm, spec, plan, build, tests, deploy, post-deploy, docs/wiki sync and acceptance with explicit gates. 'checkup' / 'чекап' reports unconfirmed releases; 'setup' audits existing docs. Not for: answering a question, explaining code, a typo or a one-line edit, a mechanical rename, reconnaissance that lands nothing — say 'no pipeline' / 'без пайплайна' to opt out.

- Skill: `ssheleg/task-pipeline` (Agent Skill, multi-file: 75 files)
- Install (CLI): `npx skillmds@latest add ssheleg/task-pipeline`
- Raw SKILL.md: https://api.skillmd.com/api/skills/ssheleg/task-pipeline/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: DevOps & Infra
- License: MIT
- Author: ssheleg (https://skillmd.com/u/ssheleg)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/ssheleg/task-pipeline

---


# task-pipeline

Self-contained orchestrator. Runs a task through **gated stages**, each carrying its
own built-in doctrine — no companion plugin required. Keeps the main thread
disciplined: no stage advances until its gate passes; the whole run uses one model,
confirmed before it starts.

**Grill first, then run autonomously.** Stage 0 is **mandatory**, but it is a
GAP CHECK before it is an interview: the brief is built from the request, the
files and the harvest first, and a question is asked only for a **material
unknown** the sources cannot answer. A complete brief yields ZERO intake
questions; what the request or the project already decided is recorded, never
re-negotiated. The interview, where gaps remain, is one-question-at-a-time and
sweeps stages 1→10 for anything that would stop the run later — then locks the
answers into a brief. Autonomy is bought there or not at all; every MATERIAL
question skipped at stage 0 comes back as an interruption at stage 6.

**Config contract: [`pipeline.schema.json`](pipeline.schema.json).** A pipeline is
a machine-readable config — an ordered list of stages, each with `skills[]` (the
skills/agents that run it) and a `gate {type, check}`. The schema is the universal
contract; it imposes **no** specific stages, skills, or gate assignments.
[`pipeline.example.json`](pipeline.example.json) is a **copy-and-rewrite example**
that encodes this plugin's own default flow (stage 0 intake + the 1→10 stages
tabled below) and an optional, toggleable `release` block.

**Two layers, and only one is replaceable.** The **KERNEL** is what every
pipeline must carry no matter how few stages it has — for every unit of work:
its **scope** (what it may change), its **evidence** (a claim carries its
receipt), its **deps** (what it reads and what must precede it), and a
**resume** point (it survives context loss). The kernel is invariant. The
**PROFILE** is the STAGE LIST — how many stages, their names, their skills,
their gates — and a project **replaces the profile wholesale** (any number of
stages, its own skills/agents, its own gate types; see *Bring your own
skills*). **The stage numbers belong to the SELECTED profile, never to the
kernel:** a minimal three-stage profile has no "stage 7", and a rule keyed on a
global stage number is a rule about the default profile, not about every
pipeline. What a custom profile may drop is stages; what it may not drop is a
kernel field. Each gate has a **type**: `auto` (the
orchestrator verifies the `check` itself, pass/fail), `judgment` (no complete
deterministic check exists — a named judge rules, and the ruling is recorded as
judgement, never as a measurement; `references/gates.md` → *The judgment gate*)
or `manual` (wait for an explicit operator go); which stages are manual is the
operator's call. In the
example's `skills[]`, `task-pipeline:<name>` denotes this skill's own built-in
doctrine (`references/<name>.md`) and `host:<name>` denotes the host project's own
command for that job (`references/conventions.md`); everything else is a real skill
the environment resolves.

## Prerequisites — none required

**Every stage's doctrine ships inside this skill.** There is no required companion
plugin, nothing to resolve at preflight and no version skew with someone else's
repo. Stages 1 and 6–9 additionally run the *host's own* commands and optional
tools, and **no stage blocks on an install** — stage 1 falls back to web search, the
wiki and the code graph are recommendations. The **one** exception is deliberate and
named: on a user-facing task the stage-3 UX track requires super-ux, and the spec
gate stops until it is installed.

Which reference owns which stage — all forty-odd of them, by stage number:
[`references/doctrine-map.md`](./references/doctrine-map.md).

**Optional bridge.** An equivalent skill set the operator already runs can be mapped
onto stages 2/4/5/6 in `pipeline.json` → `skills[]`. That is a **substitution, never a
requirement**. And the precedence is explicit, because two layers could seem to
disagree: on a CUSTOM profile the **kernel wins** — scope, evidence, deps and
resume are owed by every unit of work — while `references/stages.md` is the
**default profile's** normative gate set, governing the stages that profile
actually selects, not imposing its stage numbers on a profile that dropped
them. The built-in doctrine is normative for the default profile; the kernel is
normative for all. Nothing detects, recommends or waits for an external
provider.

**super-ux — the preferred provider for ANY user-facing task.** The moment a task
implies an interface (web / mobile / CLI / TUI), the WHY→UI→scenario chain runs
through `/ux` and its linter, which belongs in the host's CI so UX drift cannot
merge. **But the stage-3 gate checks the ARTIFACT, not the package**: valid
scenarios covering the change — produced by super-ux, by an alternative provider
honouring the same contract, or written inline against
`references/companion-skills.md`'s fallback — pass the gate. What stops the gate
is the ABSENCE of any scenario artifact: then create one (super-ux is the
preferred way, the inline fallback is the floor), and a missing tool is reported
as the NAMED check that was not done, never as a failed task.

**The grill is built in and mandatory** (`references/grill.md`). No "clear enough task"
exemption and no stage 1 without a committed, operator-confirmed brief. It produces the
**REQ spine** — the request as an addressable list, each row naming how it is verified —
which stages 3–5 trace to, stage 4 set-compares against, and **stage 10 accounts for
every one of**, turning the pipeline from a funnel into a circle.

**Harvest before you ask** (`references/knowledge-sources.md`). Stage 0 opens by
pulling what the project already knows about *this* task, writes the source ledger
into the brief, and then interviews **against** it — so the operator outranks any
document, **but only out loud**, and an override is a recorded decision rather than
an undetected divergence. That ledger is also stage 9's work list. Which sources,
and the two ways the retro is read — standing instructions in full because they
bind this run, the log queried because nothing caps it — are in
`references/knowledge-sources.md` and `references/retrospective.md`.

**Three artifacts close a run, not two — and they are a convergence, not a sequence.**
Stage 9 syncs the docs, the wiki **and the code graph**; none consumes another, and the
**graph↔docs divergence check is the gate over their convergence** — the only thing
comparing two of the three against each other, so it is not optional where a graph
exists. A stale graph is a false premise **carrying the authority of a machine**
(`references/knowledge-graph.md`, `references/audit.md`).

**Documentation is a deliverable, and it has a gate** (`references/documentation.md`).
Stage 0 answers the four questions that make docs a *system* into `docs/DOCMAP.md`;
from then the **Doc Loop** fires whenever anything is settled, at **any** stage rather
than only at stage 9, the stage-9 sweep walks the **propagation matrix** — the harvest
ledger names what you *read*, the matrix names what you *owe* — and *"docs in sync"*
becomes a command with an exit code.

**The run teaches the next run, and the list stays short**
(`references/retrospective.md`). Every gate is good at *this* run and blind across
runs, so one class of failure can be caught, fixed and forgotten five times with
nothing noticing it is the same one. Stage 10's last act, **in this order and the
order is load-bearing**: stamp the run, then prune, then write the entry — a
retirement trigger counts firings across the last five stamps, so a prune placed
ahead of the stamp reads a counter its own stage has not written yet. The cap, the
triggers and what an entry must carry are in `references/retrospective.md`; why
the order cannot be swapped is `references/learned.md` rule 21.

Stage 0 reads those standing instructions in full, which is why the prune is a gate
criterion: a rule nobody reads to the end is worse than no rule, because everyone
believes it is covered.

Three things the grill does beyond clarifying the request, each in full in
[`references/grill.md`](references/grill.md):
- **Domain awareness** — it reads the project's `CONTEXT.md` / `docs/adr/` and holds the operator to them, writing resolved terms back as they land.
- **The autonomy sweep** — it pre-resolves what would otherwise stop stages 1→10 mid-flight. Autonomy is bought here or not at all; an unasked question is a scheduled interruption.
- **The design destination** with Figma on — *which* file, in which team, decided at stage 0. Left to drawing time it is answered by whoever holds the brush, and the answer is usually *create a new file*.

## How to run

1. Restate the task in one line. Create a **TaskList: one task per stage, starting
   with stage 0** (survives context loss; lets you resume). Then run the
   **companion preflight** (`references/companion-skills.md`): the stage doctrine
   is built in, so this only checks the *optional* companions (super-ux for UI
   tasks, context7, wiki-update, graphify) and emits ONE block covering them
   **and the model decision** (`references/model-tiering.md`): recommend
   the most capable model available (advice), let the operator confirm or
   override (the choice — inherited verbatim by plan, stages and subagents), record
   it. Ask once, here. **The same block carries the run mode**
   (`references/continuity.md`): read `pipeline.json` → `run.loop`; where it is
   recorded, arm it **at the point `run.loop.arm` names** — here at preflight, or
   at stage 2's close for `after-decomposition`, once the queue exists — and when
   it arms, print the job id and the cancel command; the config is
   the authorization, so re-asking rebuilds the habit it exists to retire. Where
   it is **absent, the mode is off**; recommend it in one line and move on.
   Silence arms nothing, and the mode never collapses a `manual` gate.
2. **Run stage 0 — always, no exceptions.** It opens with the **knowledge harvest**
   (`references/knowledge-sources.md`): query the project's own sources — repo docs,
   ADRs, `docs/ux/`, past briefs, the wiki if installed, any doc repo the project
   names — for this task's terms, and write the **source ledger** into the brief
   before question one. Then grill until shared
   understanding is reached, **each answer checked against the harvest**, the
   autonomy sweep is covered, **the REQ table is
   written (one row per independently verifiable deliverable, each naming its
   check)** and the brief is locked
   (`references/stages.md` → 0). Do not touch stage 1 before the brief is
   committed and confirmed. **Entered from super-ux?**
   (a validated `docs/ux/` chain and/or a `docs/ux/plans/…` fix plan already
   exists — super-ux's `/ux` hands off here) → don't re-grill or rebuild the UX
   chain: just check it's OK (`/ux-lint` green), confirm scope in one line, and
   skip ahead to the first stage with real work (see `references/stages.md` → 0).
3. Walk stages 1→10 on the model confirmed at preflight. **Don't re-ask about the
   model at every boundary** — only when the operator recorded a per-stage override
   map and the next stage's entry differs (`references/model-tiering.md`).
   **The SELECTED profile is compiled once, at preflight, and only ITS declared
   stages and gates run** (FIX-TP-03.02): the numbers "1→10" name the DEFAULT
   profile, and a custom profile with three stages runs three — no hidden stage
   0, 7 or 10 is injected because the default profile has one. What a custom
   profile does NOT escape is the KERNEL (03.01): scope, evidence, deps and
   resume are owed by every stage of every profile, so dropping stages never
   drops the evidence gate. And an unknown MANDATORY capability blocks the
   compile — a profile whose `must_understand` names a capability this runtime
   does not have is refused, never run with the capability silently absent.
   **Is the brief a platform rather than a change?** Then stage 2 also cuts it into
   modules (`references/decomposition.md`) and stages 3→10 run **per module** in
   build order, one brick at a time — stages 0–2 run once, and the module map's
   status column is the resume point (`references/stages.md` → *The program loop*).
4. Do **not** advance until the stage **gate** passes (`references/stages.md`).
   Honor the gate **type**: for `auto`, verify the gate's `check` yourself and
   stop/return on fail; for `judgment`, record the named judge's ruling as
   judgement, never as a measurement; for `manual`, present the result and
   **wait for the operator's explicit "continue"/go** — neither of the other
   two ever substitutes for a required manual approval.
5. **The cross-cutting rules fire at any stage**, not only here — the Doc Loop, the
   loop guard, the audit's exit, the frozen REQ list, the carry-over ledger, and
   what counts as evidence, and **every gate prints `holds: N`** — what this run left
   running, across all eight classes, enumerated by class and never by a single
   tool — and stage 10 does not close while this run's residue is live and
   unaccounted (`references/residue.md`). The rest are in
   [`references/gates.md`](references/gates.md) → *Cross-cutting, at every stage*.

## Stages (detail in `references/stages.md`)

All stages run on the **one model confirmed at preflight** (default: the most
capable available — see `references/model-tiering.md`).

| # | Stage | Gate | Type |
|---|---|---|---|
| 0 | Intake grill — **mandatory** | source ledger written with its `Contradictions:` line; `docs/DOCMAP.md` answered and intent reconciled against as-built; the retro read in full; autonomy sweep covered; brief locked and confirmed | manual |
| 1 | Docs study | contracts grounded on fetched docs | auto |
| 2 | Brainstorm + decompose | design approved; UI verdict recorded; every REQ answered; **the queue is an artifact** — a work graph validates and its coverage names no unserved REQ; platform: module map approved | manual |
| 3 | Spec | committed + reviewed; UI: chain validated, linter green, scenarios and `SCR-` traced; COPY and VISUAL are a parallel layer after UX, and where both ran their convergence check is recorded | manual |
| 4 | Plan | parallel-ready, DoD per task; **every edge names what it carries** — the fake-edge test run and its `Edges:` count computed | auto |
| 5 | Dev | tasks DONE, TDD green per task, branch integrated per the brief; a fanned-out group gets **one convergence check over all its diffs together** before the first worktree lands | auto |
| 6 | Tests | full suite green, new and changed code covered, every new check probed both ways and asserted on its exit code; **a web surface is checked in a browser, not in the diff** — where a browser channel is connected; absent, the weaker claim is recorded | auto |
| 7 | Lint + deploy | lint clean and suite green before deploy; deploy needs a go, or the brief's specific standing authorization | manual |
| 8 | Post-deploy | clean boot or an honest degradation report; **a deployed web target is opened, not curled** — a `200` proves the server answered and nothing else; where no browser channel is connected, the weaker claim is recorded | auto |
| 9 | Docs + wiki | every stale row of the stage-0 source ledger updated; the propagation matrix walked for every change type this run produced; the documentation gate green with its ratchets printed; docs, wiki and the code graph synced and checked against each other | auto |
| 10 | **Acceptance** | the ladder walk ran and its absences became REQ rows; every REQ accounted for with evidence from a check seen failing once; no unresolved ledger row; **every repository clean, pushed and pointed at**; the hand-back written and the environment given back; the retrospective written **last**, and in order | manual |

**Every gate above is the short form**, and the long form is the point of
[`references/stages.md`](references/stages.md) — one section per stage. What the
ladder walk is, which eight environment classes stage 10 enumerates, what makes an
edge fake, why a `200` is not a working page: all there, none here.

**Several repositories?** A submodule is finished when its parent says so — a clone
can still get the commit before it while neither repository looks wrong alone. The
commands that prove it are in
[`references/acceptance.md`](references/acceptance.md) → *A project of several
repositories*.

## Model — ask once, at preflight

Recommend **the most capable reasoning model available** — a tier resolved at
runtime, **never a hardcoded id**; stage configs use `default` / `inherit`. The
block to emit is `references/model-tiering.md` → *Mechanic*, and it is a
reminder: no such tier means say which one is in use and continue. Record the
answer in the brief, don't re-ask per stage; stage-5 subagents are pinned to it
automatically.

## Degradation

- **No python3** → the work-graph verbs and the seeded gate scripts cannot run: the queue degrades to a prose plan, the gates to checklists — said out loud, never silently.
- **No git** → no worktree isolation and no commit-addressed evidence: the run records the weaker claim instead of pretending to the stronger one.
- **No browser channel** → a web surface is verified by reading the diff, and the close-out records that as the weaker claim it is.

## Bring your own skills

The stages above are the **example** flow. A host project owns its pipeline: copy
`pipeline.example.json` → `pipeline.json`, define its **own** stages (any count),
point each `skills[]` at what its environment resolves, set each `gate.type`
(`auto`/`judgment`/`manual`) to fit its process, and toggle its own `release`
block. The
framework ships no fixed stage count and no opinion on which gates are manual —
`pipeline.schema.json` is the only contract.

## References

Most references are routed from the **Built-in doctrine** table above, keyed by
the stage that sends you there. The rest are routed by prose: `stages.md` (named
at every stage of *How to run*), `learned.md` (cited where a rule binds) and
`probing.md` (from `gates.md`, whose checks it proves). The config contracts sit
beside this file: `pipeline.schema.json` and `pipeline.example.json`. The
family's task/context contract sits there too: `execution-packet.schema.json`
with `execution-packet.example.json` — an immutable, content-addressed packet
per dispatchable unit of work, validated dependency-free by
`scripts/packet.py` before anything acts on it (an unknown mandatory version,
a ref without its digest, or an unbound decision is rejected at the door) —
and its answer half, `execution-result.schema.json` with
`execution-result.example.json`: an AttemptGrant that a boolean can never
substitute for, and a ResultEnvelope whose stale candidate (older revision, or
a superseded fence) re-plans instead of landing as current
(`scripts/packet.py validate-result`). The compiler's first stage maps an
audit report onto parent tasks (`scripts/context_packets.py compile|verify`):
ids derived from finding ids — never positional, so a shuffled report compiles
byte-identically — evidence/limits/priority in their own fields separate from
status, and any row it cannot map blocks the whole compile rather than being
dropped silently.

