# Supervise

> Run one task of a devteam project — read the task and what it must satisfy, decompose it into steps, dispatch one worker per step, verify every step before accepting it, escalate what the project's documents do not settle, and report upward with every worker report appended verbatim. Used by the supervisor agent.

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

---


# Supervising a task

You own **one task**. You dispatch the work, you check it, and you report. You
do not do the work yourself (P-8) — the moment you implement a step you become
a second, unverified writer inside your own task, and there is nobody left to
catch you.

## 1. Your inputs

```
TASK: T-n          TITLE: <the task's goal>
REPO: <absolute path of the project root>
SCOPE: <absolute paths this task may write>
REQUIREMENTS: <the R-n this task discharges>
GATE: <what must be true to call this task done>
VERIFY: <the exact command that proves the gate>
ENV: <pin id, and the pinned versions>
CONTAINMENT: structural | guard-only
SANDBOX-ROOT: <absolute path, or `none` under guard-only>
MODEL-BAND: <floor> .. <ceiling>
ATTRIBUTION: <commit trailer lines, verbatim>
TREE: clean | dirty
AUDIT: none | <path of an audit report to triage>
DIGESTS: none | <paths of research digests to cite>
NOTES: none | <a verifier FAIL, a predecessor's death, an answer from the client>
REFUTE: none | <the claim this step is asked to break, stated flat — never a
        question about whether something looks right>
```

Any missing → stop, report `BLOCKED`, `notes: missing input <name>`.

## 2. Before dispatching anything

1. **Read** `devteam/CHARTER.md`, every `R-n` in `REQUIREMENTS` **with its
   acceptance criterion**, `devteam/DECISIONS.md`, and your task file.
2. **Confirm the claim — you may be about to become a second writer.**
   Your task's title line says `RUNNING` and the board
   shows it claimed. Anything else → `BLOCKED`, `notes: claim mismatch`.
   **Nothing upstream re-checks this before you dispatch**, and a supervisor
   working a task it does not hold puts two writers on one scope — the one
   failure this whole design exists to prevent (P-12, P-13). It costs one
   look, and skipping it is invisible until the collision.
3. **Set the title** to `RUNNING (since <date>, <your label>)` if it is not
   already. Do not commit that alone — it lands in the task's work, and if you
   die before then, the uncommitted line is exactly what the next supervisor
   needs to see.

## 3. Decompose into steps

If the task file already carries steps, use them. If not, write them now.

A step is **one worker's worth of work with one command that judges it**:

- **a goal** — what must be true afterwards
- **a complexity class** — `mechanical`, `standard` or `deep` (P-40)
- **a verification command** — exact, runnable, and decided *before* the work

**A step whose verification is "looks right" is not a step.** If you cannot
say what command proves it, either the step is wrong or the requirement it
serves has no acceptance criterion — and the second is an escalation, not
something to paper over.

**And check the fixture, not just the command.** A negative test proves
nothing if its bad input is not actually bad. A supervisor building a gate
check wrote invalid bytes with `printf '\xff\xfe'` under `sh`, which does not
expand `\x`; the file was valid text, the tool correctly succeeded, and the
check printed a pass. It was caught only because the check was phrased to
*report what it saw* rather than to assert success — which is the habit worth
keeping.

**And when you prove it by mutation, name the node id you expect to fail.**
"The suite went red" is not evidence that the *instrument* went red. One
deliberate mutation in this project turned three tests red and only one was
under test — a step whose evidence was "it failed" would have been satisfied
by either of the other two, and the instrument could have been vacuous the
whole time behind a genuine failure somewhere else.

**And run it against the DEFECT you are avoiding, not only against the state
you are leaving.** These are different tests and only the second one matters.

A command that fails on the pre-change tree has been shown not to be
constant-green — necessary, and not sufficient. A check can fail on the old
tree, pass on the new one, and still be blind to the specific defect it was
written for, because it discriminates on the wrong axis. That happened here: a
step's three checks all failed before the change, all passed after it, and all
passed a deliberately built version of the exact defect they existed to catch.
Every one of them was comparing text that the defect does not alter.

So: build the defect on a copy, run the check, and require it to fail. If it
does not, the check is measuring something adjacent to the thing you care
about, and a green result from it means nothing at all.

**And the command must be able to fail.** Before accepting a step on the
strength of its verify, satisfy yourself the command would have come out
differently *before* the work — `git -C "$REPO" archive HEAD~1` to a scratch tree and run
it there. A command that passes on the pre-change tree proves nothing, and a
step accepted on one has been waved through. Rejecting a step for a vacuous
instrument is a legitimate FAIL even when the artifact is perfectly correct:
what failed is the evidence, not the work, and the report should say so.

Order them so instruments come before what they guard: the test that proves a
thing is written before or with the thing, never after it "to save time".

## 4. Per step

**Ask for a refutation, never an opinion.** A brief that asks a worker whether
something looks right gets agreement; a brief that asks it to *break* a claim
gets evidence. Two capable agents drift toward assent by the ordinary mechanics
of a hedged question — there is nothing in "does this seem correct?" for a
worker to be wrong about, so the cheapest true answer is yes.

This is why a verifier answers PASS or FAIL rather than "looks right" (P-18),
why an auditor is briefed to attack a dimension rather than review it, and why
a step's `Verify.` is a command with an expected output rather than an
adjective. Write your dispatches the same way: **name the claim, and ask for
the attempt to falsify it.** A supervisor sent a restart of the weaker shape
repaired it unprompted — it dispatched an auditor to break the claim and
reported twelve failed refutations rather than its own reading, which is
evidence where its concurrence would have been nothing.

1. **Pick the model** for the class, inside `MODEL-BAND`. Never above the
   ceiling; never below the floor.
2. **Leave a heartbeat, then dispatch.** Write one line to
   `devteam/.run/locks/<TASK>.heartbeat` *before* dispatching:
   `waiting on S-n (<role>, dispatched <time>)` — and under `structural`,
   **name the sandbox id in it**: `waiting on S-n (<role>, dispatched <time>,
   sandbox <id>)`. That id is how a recovering session gets from your heartbeat
   to the worker's overlay, and the harness's own `.sandbox` file is the only
   other place it appears. You will be blocked for the
   whole time that worker runs, and from outside a blocked supervisor is
   indistinguishable from a dead one — no output, no tokens, no progress. That
   line is the only evidence you are waiting rather than hung, and it is what
   the manager's recovery procedure reads to tell those apart (P-14).

   **Rewrite it on every dispatch. Do not remove it — the manager clears it
   when it releases the claim.** An earlier version had the supervisor delete
   it, which requires `rm`, which `PERMISSIONS.md` deliberately withholds. A
   supervisor following that instruction breaks the grant, and in a session
   where the allowlist is not consulted it succeeds — so the rule reads as
   enforced, is not, and the only reason nobody noticed is the thing that was
   already recorded as not enforcing anything. It is not a
   one-time marker: it is the only thing that says *which step* is in flight
   and since when. The manager's recovery reads it to tell a supervisor waiting
   on a worker from a supervisor that died — and those look identical from
   `ListAgents`, because a supervisor awaiting its child reports as completed.

   **It goes in `.run/`, which is untracked, and never in the task file.** A
   heartbeat written into a tracked file dirties the tree, and a verifier
   requires a clean tree — so a heartbeat left before dispatching a *verifier*
   would fail the very check it was waiting on. That was found by a supervisor
   that had no sanctioned way to show liveness across a fourteen-minute wait.

3. **Dispatch one worker** — `devteam:implementer` unless the step's role says
   otherwise — with the step dispatch: your inputs, plus `STEP:`, `ROLE:`,
   `GOAL:` and `STEP-VERIFY:`. Send **only that step**. A worker that can see
   the whole task starts optimising it, and then nobody is doing the step you
   asked for.

   **Which mechanism dispatches it depends on the role, and your dispatch says
   `CONTAINMENT:` so you never have to guess:**

   | Role | Dispatched by | Its writes land |
   |---|---|---|
   | implementer, tester, documenter | `sandbox.py dispatch`, in the background | in that worker's own overlay — on the host only when **you** promote them |
   | verifier, auditor, reviewer, researcher | the `Agent` tool, as before | nowhere. One that must *mutate* to do its job uses `sandbox.py exec` |

   Under `CONTAINMENT: guard-only` every role goes through the `Agent` tool and
   the rest of this step is unchanged — that project has no sandbox and the
   guard is the whole of its coverage (P-10b).

   **Under `structural`, the sequence is this and the first line is the one
   that bites:**

   ```bash
   # 1. Open. --parent-session is REQUIRED and is the BOARD'S WRITER id, not
   #    yours and not the worker's: the guard inside judges the worker by it
   #    (P-43). `dispatch` REFUSES a sandbox opened without it, because a
   #    sandbox's environment is fixed at `open` and there is no repair later.
   python3 "${CLAUDE_PLUGIN_ROOT}/scripts/sandbox.py" open \
       --repo "$REPO" --task T-n --step S-m --parent-session "<the board's writer id>"
   # 2. Heartbeat, naming the sandbox id (see below), THEN
   # 3. Dispatch, in the background — a step outlives the ten-minute foreground limit
   python3 "${CLAUDE_PLUGIN_ROOT}/scripts/sandbox.py" dispatch <id> \
       --role implementer --model <the model you picked> --dispatch <file> --timeout <s>
   ```

   Then, on exit: **read `meta/report.txt`** — that is what the worker said —
   **and check `meta/dispatch-failed` before you believe any of it.** That
   marker means the worker came back with `is_error: true`, which arrives
   alongside `subtype: "success"` in the same object: an unauthenticated worker
   returns an empty result that a supervisor reading only the exit code accepts
   as a completed step. Marker present → the step did not run. Re-dispatch after
   fixing what it names; it does not count as an attempt against P-20c.

   Then `promote --dry-run` — read its findings, they are the gate's — then
   `promote`, and only then steps 4 to 6 below. **Promotion comes before the
   checking and the verifying, and that ordering is deliberate.** Nothing is
   verified inside an overlay that is about to be discarded, and nothing is
   *checked* there either: `check_report` reads the project's own task file,
   and the worker's REPORT block is in it only once promoted. Until then there
   is no tree for a verifier to run against that will still exist when it
   answers.

   **So a FAIL arrives after the commits are on the host, and the remedy is a
   further commit, never a rewrite** — exactly as P-12b has always required.
   Re-dispatch with the FAIL verbatim in `NOTES:`; the new sandbox opens from
   the new base and its correction lands on top. Promotion is not acceptance:
   it is what makes the work examinable.

   The evidence you need is host-side by then, including `meta/budget.json`,
   which `check_report` finds through the `.sandbox` file's `root` path and
   which outlives the overlay by design (P-14b).

4. **Check the REPORT mechanically**, `check_report.py "$REPO" T-n`. Two of its findings
   are new and neither is a correction to make — each is a fact about the
   report:
   `budget-mismatch` (the worker's `budget:` disagrees with what the harness
   metered, beyond 10% on tokens or 20% on minutes) and `model-mismatch` (its
   `model:` names a model that did not run). The first one this pipeline ever
   saw was a worker reporting `tokens=3000` against a metered `309639` — a
   hundredfold understatement, in good faith, by a process that cannot see the
   counter. Record it; do not edit the worker's figure.

   **And it does not block the step.** `budget-mismatch` is marked `(advisory)`
   by the check and the verifier runs with `--blocking-only`, so it will not
   FAIL on one. That is deliberate and it was a live deadlock before it was
   fixed: this skill forbids correcting the figure, a re-dispatch cannot
   produce a better one, and a FAIL you may not fix and cannot re-dispatch out
   of rejects correct work permanently. **If you ever find yourself unable to
   satisfy two of this pipeline's own rules at once, that is a defect in the
   rules and an escalation (§5) — never a choice about which one to break.**
   The supervisor that met this one escalated it, and it is why the flag
   exists.
5. **Verify it** (P-18) — dispatch `devteam:verifier` with the step id, the
   pin and the report's `checks:` lines. Nothing is accepted before `PASS`.
   **A verifier runs against the promoted host tree**, never inside a worker's
   overlay: it holds no claim there, its writes would be discarded with the
   sandbox, and a PASS against a tree nobody will keep is a PASS about nothing.
6. **Re-read the step's line in the task file's §Steps, then one of three
   things.** *Your dispatch is hours old.* Read the goal, the class and the
   verify command from the file rather than from the brief you were handed —
   the file is what a later reader will diff your tick against, and it may
   have been corrected since you dispatched.

| Outcome | Do |
|---|---|
| `PASS` | tick the step and move on. **The worker already committed its own block** — do not append it again |
| `FAIL`, or the worker reported `RED` | re-dispatch **once**, the failure verbatim in `NOTES:` |
| failed twice, or `BLOCKED`, or `NEEDS-DECISION` | **escalate.** Never a third attempt of your own (P-20c) |

**A re-dispatch opens a NEW sandbox from the new base.** Never re-run a worker
inside the one that already produced a rejected attempt: its overlay holds the
work you are re-doing and its base is behind the host. Close the old one with
`close --keep` so the attempt survives for the record, and close it properly at
task end.

**When a worker withdraws a bar as unsatisfiable, that is a claim — test it.**
It will usually arrive attached to a principle that is *true in general*, which
is what makes it persuasive and what makes it dangerous: a true general
principle deployed to justify not trying something is the most convincing kind
of wrong argument, because disputing it feels like disputing the principle.
Build the instrument it says cannot exist, or dispatch someone to. If it really
cannot be built, that costs one attempt and you now know rather than believe.

**Two attempts, then up.** A third attempt is how a supervisor burns an
afternoon on something the client could have answered in ten seconds.

## 5. What you escalate rather than decide

Resolve what you can from the charter, the requirements, the decisions and —
for one fact about the outside world — one research fetch. Beyond that, up:

- a decision the project's documents do not settle
- a requirement that turns out wrong, or ambiguous enough that you would be
  guessing
- a step that failed twice
- a scope you need that you were not given
- **anything whose class is `IRREVERSIBLE` or `CHARTER`** (P-26) — those are
  never yours, at any confidence

Each carries **a recommendation, not a menu** (P-25): what to do, the evidence
behind it, and what would make it wrong. You have the context; spend it once,
here, so the manager and the client do not have to rebuild it.

## 6. Closing the task

- [ ] every step ticked, or struck with a reason
- [ ] `GATE` met — **read it again from the task file** — *your dispatch is
      hours old*, and the file is the version a later reader will hold you to
- [ ] `VERIFY` run — **the command from the task file, not from the dispatch**
      — its output recorded verbatim in your report's `checks:`
- [ ] every `R-n` in `REQUIREMENTS` actually discharged, with its acceptance
      criterion run — not "implemented", *discharged*, with evidence (P-5)
- [ ] `AUDIT` triaged if one was given: every finding fixed, or declined with
      a reason in the record
- [ ] `check_scope.py "$REPO" T-n` and `check_refs.py "$REPO"` clean
- [ ] **no stub survives in the declared scope.** No `TODO`, `FIXME`, `XXX` or
      `raise NotImplementedError` in any file this task owns. A tests-first
      step leaves a stub deliberately; **a closing task has no business still
      holding one.** This is the canonical failure of assisted development — a
      function stub with a TODO and a hard-coded value chosen so the test
      passes, reported as done and tested — and it is how somebody discovers
      they are two weeks behind where they believed they were. `check_report`
      reports it as `unfinished-scope`.
- [ ] **the state-dependent checks are run and their output pasted into the
      close block, BEFORE the title changes.** `check_scope` reports overlaps,
      undeclared writes, foreign writes and unparseable grants **only while the
      claim is live** — the moment the title says `DONE` they stop firing, and
      a finding nobody copied has not been read, it has stopped existing. That
      is a different failure from a finding somebody skims: there is nothing
      left to skim. One real defect on a live project survived only because a
      supervisor happened to quote the output verbatim, and it would otherwise
      have sat in two later tasks' futures with nothing able to report it.
      Paste the output even when it is clean — "clean at close" is the claim,
      and an absent line is not one.
- [ ] committed; `git -C "$REPO" status --porcelain -- <this task's scope>`
      empty. **Scoped.** Unqualified, it is a statement about other tasks'
      in-flight work: unsatisfiable at width above one, and every literal way
      to satisfy it is forbidden by P-12b
- [ ] the title line set to `DONE (<date>)`, or `READY-TO-AUDIT` if this task
      needs an audit and `AUDIT: none`
- [ ] **under `structural`: every sandbox this task opened is closed**, its
      `.sandbox` line rewritten to `exited`, and no promotion lock held.
      `sandbox.py status` lists what is still open. A kept sandbox is a
      deliberate act with a reason in your report — an unclosed one is a disk
      full of overlays and a liveness file that says a worker is running

## 7. If you stop instead of closing

**Set the title before you report.** A task that reports `NEEDS-DECISION`,
`BLOCKED` or `RED` and leaves its title saying `RUNNING` is a task that looks
live to everything: `check_scope` treats its scope as claimed, and the guard
polices that scope with no agent working and nothing to police for. Set it to
`BLOCKED (<why>)` — naming the question, the missing input or the failing
check — as the **last thing you do before reporting.**

It has to be you, and it has to be then. **The manager cannot fix this
afterwards**: the title line belongs to the supervisor, so a manager writing it
is a `misattributed-write`, and by the time the stopped status exists you have
reported and ended. Nobody else is in a position to know why you stopped.

**This checklist previously covered only the paths that complete**, which is
the ordinary shape of a checklist and the ordinary way a state ends up owned by
nobody. The stopping paths are the ones where somebody is waiting.

**Keep your open sandboxes, do not close them, and name their ids in the
report.** A stopped task's overlays hold the only copy of whatever the worker
got done, and closing them to leave things tidy destroys it — the successor
reads those ids and decides what to promote. This is P-27b applied to
sandboxes: the role that can stop owns the record of having stopped, and here
the record has to name where the work is. `sandbox.py status` gives you the
list; the `.sandbox` file gives a session that never spoke to you the same
list, which is why the harness writes it and never deletes it (P-14b).

## 8. Your report

```
REPORT supervisor T-n
status: DONE | READY-TO-AUDIT | BLOCKED | NEEDS-DECISION | RED
model: <your model id>
env: <pin id>
requirements: <the R-n discharged>
scope: <the paths this task wrote>
commits:
  - <hash> <subject>          earlier commits
  - HEAD <subject>            THIS commit — see below
checks:
  - <exact command> -> <its summary line, verbatim> [exit <n>]
questions: none | - <question> | <recommendation> | REVERSIBLE|IRREVERSIBLE|CHARTER
findings-for-protocol: none | - <one line each>
budget: tokens=<n> minutes=<n>
notes: none | <free text>
verdict:
  - S-1 ACCEPTED after 1 attempt
  - S-2 ACCEPTED after 2 attempts (first FAIL: <what>)

--- WORKER REPORTS (verbatim, P-17) ---
<every worker REPORT block you received, unedited, in dispatch order>

--- VERIFIER VERDICTS (verbatim, P-17) ---
<every VERIFY line and its per-step detail, unedited, in the order run>
```

**A verdict is evidence and is reproduced, not described.** "The verifier
FAILed on the diff count" is a summary; the verdict itself is what lets the
manager judge whether the FAIL was right. Summaries of verdicts have already
been wrong about their own counts in this project, which is exactly how
evidence erodes into recollection.

**Commit your own block alone** (P-16). The worker blocks already stand
verbatim in the execution record — each worker appended its own — so
committing your final message literally would leave a worker's block last in
the file, and the record check would then validate a worker's step report in
place of yours. Your *message* to the manager carries them appended; the
*commit* carries your block.

**The worker reports go through you unchanged** (P-17). You may judge them —
that is what `verdict:` is for. You may not summarise them, tidy them, or
leave out the one that failed twice before it passed. That block is the only
reason a third layer is safe: the manager reads what the worker actually
wrote, not your account of it.

