Deterministic goals across harnesses
zdev goal renders an area continuation condition in native_goal, alongside
current task context. The CLI constructs the condition deterministically from
the area tag and explicit run options. Task selection, completion, and changing
task details leave the condition unchanged.
Use the condition unchanged when creating a native goal. Keep selected task IDs, snapshots, worker settings, and progress in the conversation. The area records supply the current objective and boundaries; each worker reads its task record. The run ends at queue exhaustion, area closure, or a reported confirmed blocker or required user decision. Ending the run preserves unfinished tasks and does not close the area.
Command
Section titled “Command”zdev goal <area>zdev goal <area> --format jsonzdev goal <area> --focus "payment retries" --parallel --format json<area> is required. Unlike zdev next, this command does not infer a default
area and does not require a clean branch or a task-work branch. It reads and
validates records but never changes files, Git state, or a harness session.
--focus retains the user’s selection guidance without selecting a task in
this read-only command. --parallel renders four independent task slots with
serial integration and per-task verification and commits. Worktrees are the
default; explicit workspace and worker choices remain in effect. Ordinary
invocation renders sequential continuation. These options describe a run;
they create neither workers nor workspaces and do not authorize execution.
Exact inputs
Section titled “Exact inputs”The projection reads only current .zdev records:
area.toml:tag,title,objective, andlifecycle.- Every task header in the area:
id,key,status,slice, andblocked_by, plus complexity, AFK suitability, priority, the task title and theOutcome, optionalContext, optionalBoundaries,Done when, andValidationsections. - If the selected task names a slice, that slice’s
key,title,Objective, andBoundaries.
The area branch, parent, and base_commit fields describe workspace
topology rather than intent and are excluded. Free-form area-brief sections are
also excluded: the area metadata objective is the structured source for this
projection. The full area brief remains mandatory reading before
implementation. Task result text and done-task details are not
goal inputs.
The command uses the existing record parsers and validators. It must not accept malformed input merely to produce a partial goal.
Lifecycle, queue, and ordering
Section titled “Lifecycle, queue, and ordering”The top-level lifecycle is the durable area value, open or closed. The
derived queue is one of:
ready: at least one open task has no unfinished blocker.taskis the first such task.empty: the area has no tasks.taskisnull.exhausted: tasks exist and all are done.taskisnull.
A closed area reports queue: empty or queue: exhausted, according to its
records, and never selects a task.
Task selection uses AFK suitability, priority, then numeric ID, with the full
ID as the tie-breaker.
Each blocked_by array retains its authored order. The associated slice is
read by key. No filesystem enumeration order, clock, current branch, harness,
model, or Git status enters the output.
A validated acyclic graph with an open task always has at least one ready task:
the open subgraph has a task whose dependencies are already done. Missing
blockers, cycles, and malformed graphs fail existing validation before this
queue is projected. There is no successful blocked goal queue.
The counts are always present and ordered total, open, ready, blocked,
done. They describe all tasks, not just the selected task.
Omission rules
Section titled “Omission rules”taskis always present and isnullunlesslifecycleisopenandqueueisready.native_goalis present only forready.sliceis omitted from the task when the task has no slice.contextand taskboundariesare omitted when their Markdown sections are absent. A present validated section is emitted even if another section has the same text.- Slice files that are not attached to the selected task are omitted. A slice
is context, not executable work; an area containing slices but no tasks is
still
empty. - Human output follows the same omissions: it does not print empty headings,
null, or placeholder slice text.
Markdown section values are trimmed exactly as the existing task and slice parsers trim them. Bullet and checklist markers are preserved. This avoids a second interpretation of proof conditions.
Stable output
Section titled “Stable output”For the same validated records and zdev version, both formats must be byte-for-byte stable and end with one newline. JSON key order follows the examples below; pretty printing uses two-space indentation.
Assume checkout contains three tasks. checkout-001 is done,
checkout-002 is ready and belongs to the payments slice, and
checkout-003 is blocked by checkout-002.
Human form
Section titled “Human form”Area: checkout — Checkout reliabilityLifecycle: openQueue: readyObjective:Make checkout failures safe and understandable.Counts: 3 total; 2 open; 1 ready; 1 blocked; 1 done
Task: checkout-002 — Reject duplicate payment submissionComplexity: standardTask source: .zdev/checkout/tasks/002-reject-duplicate-payment.mdOutcome:A repeated submission returns the original payment result without charging again.
Context:The provider can retry after losing our first response.
Slice: payments — Payment submissionSlice source: .zdev/checkout/slices/payments.mdSlice objective:Make payment submission safe to retry.Slice boundaries:- Do not change provider selection.
Boundaries:- Keep the public response schema unchanged.
Done when:- [ ] Duplicate provider calls are prevented.- [ ] The original result is returned.
Validation:- Run the focused payment integration test.
Native goal:Continue zdev area checkout. Read .zdev/checkout/area.toml and .zdev/checkout/brief.md for the current objective and boundaries. Run the installed one-task implementation contract, independently verifying and committing each task before selecting again. Use worktrees by default and retain the run's workspace and worker choices. Let fresh work-context select the next task. Refresh repository state after each commit. Continue while the area is open, work is ready and safe, and the work remains authorized. Ordinary dispatch stops before hypotheses. Finish when fresh context is closed or the queue is empty or exhausted, or after reporting a confirmed blocker or required user decision with its reason and preserved state. Settle owned workers before finishing; preserve unfinished work and area lifecycle.The native condition uses a fixed template in src/goal.rs. It contains no
task or slice details. Paths are repository-relative and use / separators.
JSON form
Section titled “JSON form”{ "schema_version": 1, "area": { "tag": "checkout", "title": "Checkout reliability", "objective": "Make checkout failures safe and understandable.", "path": ".zdev/checkout" }, "lifecycle": "open", "queue": "ready", "counts": { "total": 3, "open": 2, "ready": 1, "blocked": 1, "done": 1 }, "task": { "id": "checkout-002", "key": "reject-duplicate-payment", "title": "Reject duplicate payment submission", "complexity": "standard", "path": ".zdev/checkout/tasks/002-reject-duplicate-payment.md", "outcome": "A repeated submission returns the original payment result without charging again.", "context": "The provider can retry after losing our first response.", "boundaries": "- Keep the public response schema unchanged.", "done_when": "- [ ] Duplicate provider calls are prevented.\n- [ ] The original result is returned.", "validation": "- Run the focused payment integration test.", "blocked_by": [], "slice": { "key": "payments", "title": "Payment submission", "path": ".zdev/checkout/slices/payments.md", "objective": "Make payment submission safe to retry.", "boundaries": "- Do not change provider selection." } }, "native_goal": "Continue zdev area checkout. Read .zdev/checkout/area.toml and .zdev/checkout/brief.md for the current objective and boundaries. Run the installed one-task implementation contract, independently verifying and committing each task before selecting again. Use worktrees by default and retain the run's workspace and worker choices. Let fresh work-context select the next task. Refresh repository state after each commit. Continue while the area is open, work is ready and safe, and the work remains authorized. Ordinary dispatch stops before hypotheses. Finish when fresh context is closed or the queue is empty or exhausted, or after reporting a confirmed blocker or required user decision with its reason and preserved state. Settle owned workers before finishing; preserve unfinished work and area lifecycle."}No executable work
Section titled “No executable work”These are successful observations with exit code 0, not errors:
open/emptymeans that no tasks are recorded and the objective remains open.open/exhaustedmeans that tasks exist and all are done, but the area has not been explicitly closed.closedis an explicit lifecycle decision, not a synonym for queue exhaustion.
The following fixtures define their complete byte-level output, including the area header, objective, counts, blank lines, key order, and final newline.
Empty human form
Section titled “Empty human form”Area: general — General improvementsLifecycle: openQueue: emptyObjective:Capture small approved improvements without inventing a product roadmap.Counts: 0 total; 0 open; 0 ready; 0 blocked; 0 done
The open area has no tasks. Create and approve a task, or close the area.Empty JSON form
Section titled “Empty JSON form”{ "schema_version": 1, "area": { "tag": "general", "title": "General improvements", "objective": "Capture small approved improvements without inventing a product roadmap.", "path": ".zdev/general" }, "lifecycle": "open", "queue": "empty", "counts": { "total": 0, "open": 0, "ready": 0, "blocked": 0, "done": 0 }, "task": null}Exhausted human form
Section titled “Exhausted human form”Area: release-notes — Release notesLifecycle: openQueue: exhaustedObjective:Keep shipped behavior documented for users.Counts: 2 total; 0 open; 0 ready; 0 blocked; 2 done
The open area's task queue is exhausted. Add approved work, reopen a task, or close the area.Exhausted JSON form
Section titled “Exhausted JSON form”{ "schema_version": 1, "area": { "tag": "release-notes", "title": "Release notes", "objective": "Keep shipped behavior documented for users.", "path": ".zdev/release-notes" }, "lifecycle": "open", "queue": "exhausted", "counts": { "total": 2, "open": 0, "ready": 0, "blocked": 0, "done": 2 }, "task": null}Closed human form
Section titled “Closed human form”Area: release-notes — Release notesLifecycle: closedQueue: exhaustedObjective:Keep shipped behavior documented for users.Counts: 2 total; 0 open; 0 ready; 0 blocked; 2 done
The area is closed. Reopen it before adding or selecting work.Closed JSON form
Section titled “Closed JSON form”{ "schema_version": 1, "area": { "tag": "release-notes", "title": "Release notes", "objective": "Keep shipped behavior documented for users.", "path": ".zdev/release-notes" }, "lifecycle": "closed", "queue": "exhausted", "counts": { "total": 2, "open": 0, "ready": 0, "blocked": 0, "done": 2 }, "task": null}No native condition is generated for no-work states. An adapter must report the lifecycle and queue and stop rather than inventing work from an area objective or an unattached slice.
Failure behavior
Section titled “Failure behavior”Missing repositories or areas, unreadable files, invalid schemas, malformed
Markdown sections, invalid dependencies, and missing referenced slices are
command errors. Text mode writes the normal error: ... form to standard error.
JSON mode uses zdev’s existing error envelope with schema_version, command,
ok: false, and error. Both return nonzero and write no successful payload.
In particular, a missing blocker or dependency cycle fails the existing graph validator. If open tasks somehow remain with no ready task after validation, that is a malformed internal projection and also fails; it is not rendered as a fourth state.
Failure is non-mutating. zdev goal does not acquire a write lock, repair an
index, create a task, update status, touch Git, or call a harness. An adapter
must parse a successful complete JSON document before sending any prompt or
native-goal command. On command or parse failure it leaves the current session
goal unchanged and reports the error.
Harness capabilities (2026-08-20)
Section titled “Harness capabilities (2026-08-20)”| Harness | Observed capability | zdev integration point |
|---|---|---|
| Codex | Codex has a session goal command. /goal <objective> sets a goal, /goal shows it, and edit, pause, resume, and clear manage it. The objective is limited to 4,000 characters. The feature can be disabled, so it is not universally available. Codex also loads reusable SKILL.md workflows. Codex developer commands, goal use case, and skill documentation (accessed 2026-08-20). |
The installed continuation skills use model-callable get_goal and create_goal; they do not try to enter interactive composer commands. Ordinary task work uses the complete validated work-context. |
| Claude Code | /goal keeps a session running until a model judges a completion condition satisfied. One goal can be active; setting another replaces it. An active goal is restored on session resume, and conditions are limited to 4,000 characters. The evaluator reads the transcript but does not run tools. Plugin skills are namespaced, invocable workflows. Claude Code goal documentation and skill documentation (accessed 2026-08-20). |
/zdev:zdev-loop and /zdev:zdev-goal run the same standalone area workflow; /zdev:zdev-implement remains one task. Zdev’s workflows do not inspect or apply Claude Code’s separate /goal command. |
| OpenCode | The documented extension is a custom command whose Markdown body becomes a prompt. Command templates accept arguments, shell output, and file references. The official command guide documents built-ins such as /init, /undo, and /share, but no native session-goal lifecycle. OpenCode separately persists and resumes sessions. OpenCode commands and OpenCode CLI sessions (accessed 2026-08-20). |
The packaged /zdev-implement <area> command, or the zdev skill directly, runs zdev work-context <area> --format json. It cross-validates the nested goal and status projections with HEAD and exact Git evidence, then supplies the complete context to ordinary task work. No goal emulation or extra state is needed. |
| Pi | Pi prompt templates are Markdown expanded into ordinary prompts and invoked as /name; project templates live under .pi/prompts/. Skills are loaded on demand and can be invoked as /skill:<name>. Sessions are persisted as JSONL and can be resumed, but the documented built-in and extension surfaces do not define a native goal lifecycle. Pi prompt templates, Pi skills, and Pi sessions (accessed 2026-08-20). |
The packaged /zdev-implement <area> prompt or zdev skill runs zdev work-context <area> --format json. It cross-validates the nested goal and status projections with HEAD and exact Git evidence, then uses the complete context for ordinary task work. |
| Oh My Pi | Oh My Pi has a persistent goal runtime. Its create operation refuses to overwrite an unfinished session goal; the runtime supports pause, resume, drop, completion, accounting, and autonomous continuation. Interactive /goal set <objective> creates a goal, while /goal show, pause, resume, and drop manage it. Oh My Pi goal runtime, interactive goal command, and goal continuation prompt (accessed 2026-08-20). |
The installed continuation prompts use the model-facing goal tool with get, create, and same-goal resume; they never invoke the interactive composer. Ordinary task work uses the complete validated work-context. |
The table describes the documented features at the research date. Plugins may provide additional capabilities. Skills, commands, and prompt templates are enough for the zdev behavior, so zdev does not need to emulate a native goal.