Jobs & hand-offs
You spawned it, you own it — the follow-up contract, and the only signals that finish a job.
Hand-off protocol — you spawned it, you own it
Handing a task to a pane is not done when the spawn returns; it is done when you have read the result, verified it, and reported back to whoever gave you the task. The loop:
- Spawn with a
prompt(either a prompt or an explicitspawneropens the contract), and identify yourself: passspawner(your pane id — every agent pane has it in$MANDECK_PANE; the CLI and MCP server send it automatically). Estimate how long the work should take and passcheck_afterminutes (default 10). - While it runs, poll
GET /v1/events?since=<seq>or checkmandeck waiting— a pane that bells needs an answer, not patience. - When it stops (or your
check_afterpasses), read itsscreen/messages, verify the work actually happened — a confident final message is not evidence — then report the outcome.
The deck enforces this. A spawn that carried a prompt and goes unchecked gets
collected: the deck types a [mandeck follow-up] reminder into the spawner's
own terminal, emits a needs-review event, and if still ignored (or the
spawner is gone) rings the human's attention bell on the pane. Reading the
pane's screen or transcript settles the contract.
needs-review is not job done. Follow-up settle means someone looked (or
the deck collected). The tasked work may still be in flight, sitting at a
prompt, or waiting on a human. Job state is the other signal — see below.
Job lifecycle — when is the work done?
Pane liveness is the wrong question. live: false means the session record
ended or the process exited. A pane that answered and sits at a prompt stays
live. needs-review means the follow-up contract was collected. None of
those mean the tasked work finished.
A POST /v1/spawn creates a job (job in the spawn body) with one of:
| state | means |
|---|---|
running | tasked work is in flight (or we cannot tell yet) |
waiting-you | the pane's attention bell is up (needsYou) and the job is not terminal |
done | the tasked work finished — only via an explicit signal |
failed | the tasked work errored — only via an explicit signal |
How done / failed are decided (do not lie):
The deck does not infer completion from silence, a prompt, live: false,
unfocus, follow-up collection (needs-review), or the pane closing. The only
terminal signals are:
POST /v1/jobs/:idwith{"state":"done"}or{"state":"failed"}/opt/homebrew/bin/mandeck job done/job fail(same POST; uses$MANDECK_JOBif you omit the id)- The agent prints the exact token
[mandeck job-done]or[mandeck job-failed]alone at the start of its own line (e.g. viaecho; picked up on the next job GET). Mentioning the token mid-sentence — "I'll print [mandeck job-done] when I finish" — deliberately does NOT count, so instructions about the protocol can't finish a job by accident
A pane that is still running after it "looks finished" is honest: we do not
have the signal. job wait then times out. That is the correct answer, not a
Cloud-style completion fake.
Every API-spawned pane gets MANDECK_JOB (and MANDECK_PANE) exported. If
you are the tasked agent, finish with:
/opt/homebrew/bin/mandeck job done
# or print: [mandeck job-done]
GET /v1/jobs/:id includes report.messages / report.screen so a bot can
fetch the transcript without guessing routes. Reading the job does not settle
follow-up; job report (which hits session messages/screen) does, because
that is a real check.
Waiting and the follow-up contract. A long job wait polls only the job,
so it does not settle the spawn's follow-up contract — if the work runs past
check_after (default 10 min), the spawner still receives the
[mandeck follow-up] reminder mid-wait. Set check_after comfortably longer
than your wait timeout; the contract settles the moment you job report.
Collection sweeps on a ~30s tick, so even a tiny check_after fires within
about half a minute, not instantly.