Work
One loop for task-sized and ad-hoc work. Fast over ceremonial: small mistakes caught by tests beat a process that runs 10x longer. The folder a task file sits in IS its status; the file is spec, never a phase tracker. View the board with ./workflow/status.
Contract: if
workflow/AGENTS.mdis missing, stop and explain that this repo is not initialized for the workflow plugin. Suggest explicit/workflow:framework-init(use $framework-initin Codex); never invoke it automatically. Otherwise read the contract in full. Validation commands, verify mapping, doc routing, and local notes all come from there.Select one of:
- By arg (
/work 051): the task fileworkflow/*/<id>-*.md, in whatever folder it sits. - No arg: first resume a task already in
workflow/in-progress/(an interrupted prior loop — continue it, keep its uncommitted move); if none, take the top Ready task (lowestpriority:inworkflow/ready/, ties by lowest id —./workflow/statusshows the queue). Onlyready/or an in-progress resume is eligible; draft or blocked routes through/workflow:groomfirst. Don't re-prioritize while selecting. - Ad-hoc (a direct ask with no task file): do the plan → implement → validate → verify steps, then commit with an ordinary message. Skip everything task-specific — no folder move, no
task NNN:prefix, no dependency/acceptance/done:bookkeeping (steps 5, 7, 11, 12).
- By arg (
Read and map the implementation surface: read the task file, then the doc leaf(s) the contract routes for every expected path — in full, before code. Do bounded code search and read only enough of the primary production owners to validate the groomed ownership surfaces, likely tests and docs, and load-bearing contracts before implementation. Don't read
done/unless the task links a specific historical constraint.Plan in chat: expected ownership surfaces and exclusions, files to touch, approach, test targets — a few lines, not a document. Proceed immediately when the path is clear; pause only on genuinely multiple valid outcomes, conflict with stable docs, unexpected failures without a safe evidence-backed repair, destructive steps, or material scope expansion.
Dependency gate: if the task file has a
depends: NNN[, NNN]line, each listed task must already be inworkflow/done/(ls workflow/done/<NNN>-*.md). Any dependency not indone/→ stop before touching code: report which dependency is unmet and where it currently sits (./workflow/status). Don't reorder to it or implement it inline. Ad-hoc asks have nodepends:to check.Align scope before Start: compare the surface found while planning against the task's groomed ownership surfaces and exclusions. Breadth is fine — many files inside one logical/feature boundary is still one loop; no file count triggers a split. Stop only when the work crosses into a separate independently deliverable outcome, or you hit an unknown load-bearing contract or an unresolved product decision. Then leave the task unchanged in
ready/and return a needs re-groom report: the discovered ownership map, the groomed assumption that failed, why it can't finish in one loop, candidate independent slices, and their dependency order.Start:
git mv workflow/ready/<id>-<slug>.md workflow/in-progress/(skip if resuming a task already inin-progress/). Move before the first file edit: the folder IS the status, so anything implemented while the file still sits inready/is invisible on the board and orphaned if the session dies. Do not commit this move — it rides in the completion commit. An interrupted session leaves it visible as a dirty tree, which is intended.Implement in small commits, each message prefixed
task NNN:. Only the requested change; simple readable code over new abstractions. TDD where it fits (pure logic; bug fix = failing test first; painful test setup is design feedback). Sync the routed doc leaves as part of the change when behavior or invariants changed — shipped behavior must not live only in the task file (pure refactors need no spec diff). Log a decision via/workflow:decisiononly if a future agent might plausibly flip the choice. Keep surprises/follow-ups brief in the task file's Notes — never a chronological log. If implementation reveals a step-6 scope-divergence condition, stop and return the needs re-groom report; don't silently narrow the task or absorb the extra outcome.Validate per the contract, on the complete change: targeted checks per meaningful chunk while implementing, then the full gate once before the completion commit. Never gate a commit on a piped test run — run each check as its own step, chain the commit on its exit status. Investigate unexpected failures. Fix and continue when the root cause and intended behavior are independently proven and the repair is local, reversible, in scope, and keeps validation meaningful; stale assertions, locators, snapshots, and deterministic fixtures qualify. Rerun the affected check and note the incidental repair. Stop when the cause is uncertain, multiple outcomes are valid, the repair changes a stable contract or materially expands scope, or passing requires skipping, weakening, or bypassing a check. Don't guess around flaky tests or missing dependencies.
Verify: run the contract's verify-mapping skills for the touched paths. If a required check can't run, say so and don't mark the task done.
Acceptance gate: check each acceptance criterion adversarially, in fresh context, against the final tree.
- Claude: spawn
workflow:acceptance-verifier:acceptance-verifierwith the repo path, task id, the task file path (its## Acceptance criteria), and the diff scope (commits prefixedtask NNN:plus the working tree). - Codex: spawn the registered
acceptance-verifieragent the same way (spawn_agent,fork_turns: none, same inputs) so the check runs in genuine fresh context — not the biased implementing context. Only if agent-spawning is unavailable, fall back to an explicit inline pass: re-read each criterion and try to falsify it against the diff, evidence per verdict.
It returns per-criterion verdicts.
not ready→ fix the named gaps and re-run; onlyreadyproceeds. Any code or doc edit made to clear a gap re-runs steps 9–11 on the new state. Don't override anot readyby argument alone. If a flagged gap is not a code defect but an accepted environment constraint, a user-authorized substitution (a check can't run here, a tool was swapped on the user's instruction), or a deliberate scope narrowing from the spec, don't self-clear it — surface the finding to the user and get an explicit call before committing. Skip the gate for ad-hoc asks with no written criteria.- Claude: spawn
Finish — one atomic completion commit, message starting
task NNN: <title>, only after the gate returnedready.git mvthe file toworkflow/done/, add adone: YYYY-MM-DDline under the title, and drop the now-mootpriority:line (this also commits the in-progress move from step 7). The tree is already validated — the commit adds only bookkeeping plus the already-staged work. No git tags, no phase artifacts — git history records how the implementation evolved. Report: outcome, behavior, files changed, checks run, remaining limitations. Call out anything the spec named that you did not deliver, with the reason, in the report itself — not buried only in the task file's Notes.
Tool discipline: read files with Read, search with Grep/Glob. A shell read (cat, sed -n, head) dumps the body into the transcript raw, doesn't deduplicate against a copy already in context, and is re-read on every remaining turn of the session; Bash is for state changes and process control (git, ./workflow/status, the contract's checks). Route long command output to a scratchpad file and Grep that instead of piping it into the transcript.
Delegation: subagents for bounded find/summarize, bulk mechanical edits, and batch test generation (use repo agents the contract names, e.g. a test-writer). Every dispatch carries the contract's project one-liner + the doc leaf paths + one bounded question. Decisions stay inline. Match the model to the dispatch rather than inheriting the session's: haiku for bounded find/summarize, sonnet for mechanical edits and test generation. A dispatch that needs a design call isn't bounded — keep it inline instead of paying for a large model in a subagent.
Codex: invoke as use $work. The acceptance gate spawns the acceptance-verifier agent (step 11); run the bounded find/summarize/test delegations inline.