Shift work: plan
shiftwork_planComputes which checkpoint units can run now and in what dependency-ordered waves, returning the ready batch, widest wave width, and path-conflict holds without modifying the plan.
Instructions
Shift-work plan: which units of a checkpoint may run NOW, and in what waves — the batches its depends_on graph permits, computed read-only from the file. Call it before dispatching a wave: ready (the first batch) is what shiftwork_clock_in will brief, and width is how many agents the widest wave needs. A ready member beyond the cursor is clockable only once clock-in has briefed it; without that brief, clock-out refuses it. Use shiftwork_status instead when you only want progress counts, and work_plan when the graph is yours to hand over as nodes rather than a checkpoint on disk — this tool reads the checkpoint's own plan.units. Units already done or dropped count as satisfied and are left out of every batch; todo, in_progress and blocked stay in. Order inside a batch is plan.units order, because the checkpoint schema has no priority field. It never moves plan.cursor — the cursor is echoed unchanged so the pointer and the batch view can be read side by side — and never writes anything. Refusals are structured, never exceptions: work_plan's sentences for a duplicate id, an unknown dependency or a cycle, and shiftwork_status's for a checkpoint it cannot read; a plan whose units are all terminal answers an empty ready, which is an answer, not a refusal. depends_on says nothing about two units writing the same file; a unit's optional touches (repo-relative paths it will WRITE) does: no batch holds two units sharing a path, a unit held out of one is reported in held: [{id, batch, by, path}] (absent when no unit declares touches), and a bad path is refused with work_plan's sentence. A unit whose reviews names a unit that is undeclared, not in its depends_on, or in its own role is refused: unit <id> reviews <r> .... With job.budget declared it adds budget (spent, remaining, per_unit, affordable).
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| checkpoint | Yes | Path to the shift-work checkpoint JSON file (by convention .shiftwork/checkpoint.json in the repo the job works on), absolute or relative to the server's working directory. The same file shiftwork_plan, shiftwork_clock_in and shiftwork_clock_out take; it must validate against assets/schemas/shiftwork-checkpoint.json. |
Output Schema
| Name | Required | Description | Default |
|---|---|---|---|
| held | No | Present only when a unit declares `touches`: one {id, batch, by, path} per unit held out of batch `batch` because `by`, admitted there, already writes `path`. | |
| ready | No | batches[0] — the units clock_in may brief now; [] when every unit is done or dropped. | |
| width | No | The largest batch length: the widest fan-out. | |
| budget | No | Present only when job.budget is declared: the limit, what the log records as spent, units in flight (each reserving one unit and one per-unit estimate), what remains, the per-unit token estimate (the job's lower-median line, 60000 before any) and how many more units fit. | |
| cursor | No | plan.cursor, echoed unchanged. | |
| reason | No | With result `error`: one sentence saying why the call was refused. | |
| result | Yes | `plan` on success; `error` with `reason` when the checkpoint cannot be read or its graph cannot batch. | |
| winner | No | With ranking: the first candidate's id, null when none is validated. | |
| batches | No | Unit ids by wave: batch k holds every non-terminal unit whose dependencies all sit in batches below k. | |
| ranking | No | Present only for job.kind experimentation (#265): validated candidates as {id, score, sha}, score in experiment.direction then id; score is the reported string. A candidate is validated when a done unit that reviews it reported a validated-sha equal to the commit it submitted. | |
| sequence | No | The batches flattened in order. |