Use ArchDev Tasks as the shared plan and work record. You drive drafting,
browser handoff, feedback collection, revisions, and save verification; the
human reviews the plan in the web UI. This works from any coding harness and
does not require Factory, a daemon, a resident agent, or archdev setup.
Epic and project membership
Before creating Tasks, search archdev projects list --query "<epic>" for an
active project with the epic's exact name and the appropriate scope. Reuse it;
if none fits, create it with archdev projects create "<epic>" --description "<scope>". Resolve duplicate names by scope. Set both --epic and --project
on task create/update. For graph import and review, set top-level epic and
project_id on every node. Preserve the project ID across name changes.
Without an epic, select the project by product area or initiative. Older tasks
and artifacts may omit these optional fields; new agent-authored work should
include both. Project membership does not change task visibility.
1. Connect this machine
Resolve the absolute directory containing this loaded SKILL.md, independently
of the current repository. Its bootstrap installs ArchDev when missing and
updates a CLI older than 0.47.0 or lacking review commands. Get approval
before installing or upgrading software. The scripts never install or
refresh hooks or change configuration scope. For initial ArchDev setup,
follow the agent installation guide and
wait for explicit placement and reporting consent. Capture bootstrap stdout,
which is the executable's absolute path; diagnostics go to stderr.
Bash/Zsh:
archdev="$(bash /absolute/path/to/tasks/scripts/bootstrap.sh)"
Fish:
set archdev (bash /absolute/path/to/tasks/scripts/bootstrap.sh)
Windows PowerShell:
$archdev = & powershell -NoProfile -File 'C:\absolute\path\to\tasks\scripts\bootstrap.ps1'
Commands below use "$archdev"; PowerShell uses & $archdev with the same
arguments. If bootstrap fails, report its error and point to the
official installer.
- Run
"$archdev" auth status. If signed out, run"$archdev" auth login, let the human finish browser sign-in, then check status again. - Read
"$archdev" tasks guideand"$archdev" tasks graph schemafor the installed CLI's contract. Read the schema's full output — do not truncate it (for example by piping throughhead) — it is the authority when it and this skill disagree. Prefer--jsonfor output you need to parse. - Choose the destination from the user's request and existing context.
Review defaults to the signed-in user's personal Tasks. For team work,
supply a known
--team <id>; use--repository <owner/repo>when applicable. If the team is ambiguous, ask which team before saving. Never guess an ID. - When resuming work, inspect the existing Tasks and local plan/receipt before
creating another plan.
tasks list --team <id>andtasks show <task-id>expose existing work; consult their help for other scopes.
2. Turn the source into a draft DAG
A DAG is a task graph with prerequisite edges and no cycles. Draft locally
first; opening review does not create Tasks. Do not pre-create every node with
tasks create, or import it separately, before sending the same graph through
review: approval owns saving this plan.
- From conversation: extract the requested outcome, agreed decisions, constraints, exclusions, and unresolved choices. Inspect relevant code when needed to make the tasks actionable. Do not invent requirements.
- From a harness plan: read the actual plan artifact or harness-provided plan state. Translate its steps into graph nodes while preserving intent, acceptance criteria, references, and dependencies. A harness checklist is input, not a second task authority after saving. Use stable source IDs as node keys where possible; do not invent harness/session metadata.
- Name tasks by observable outcome. Give each a concrete objective, acceptance criteria, and verification. For implementation work, name the planned end-to-end test file/scenario and the boundary and observable outcome it proves; identify any missing prerequisites honestly.
- Add
depends_ononly where a task needs another task's result. Explain each edge withdependency_reasons. Leave independent tasks parallel. Every dependency must reference a node key in this graph; no self-edges or cycles. - Keep unresolved design choices in
major_decisionsfor the human to review. Do not silently choose on their behalf when the choice changes scope.
Write a UTF-8 JSON file at a stable path, such as plans/task-review.json.
Use the graph schema's action: "preview" format. Required node fields are
key, title, objective, acceptance, verification, implementation,
and risk.
implementation: the abstract plan of attack, written without inspecting the whole codebase — numbered procedure steps, a high-level API sketch, a CLI verb/flags/outputs, or the algorithm. Use###or lower headings only; the Task keeps exactly one## Implementation plansection. Workers may later expand this same section.risk:{grade: "low"|"medium"|"high", notes?}. Grade from system sensitivity, blast radius if the change is wrong, and how invasive the add is — easy additive work on a well-tested edge is low, a rewrite of auth, payments, or data-integrity is high. State the reason for the grade innotes(markdown, or a string array rendered as bullets).
The review command also accepts optional major_decisions (not part of
tasks graph schema).
{
"action": "preview",
"epic": "Users can export their filtered results",
"nodes": [
{
"key": "export-api",
"title": "Export respects the user's filters",
"objective": "Add the export endpoint using the existing filtered query.",
"acceptance": ["Export includes exactly the authorized filtered results."],
"verification": ["Planned tests/export-api.e2e.test.ts: filtered export crosses HTTP and database boundaries and asserts returned rows."],
"implementation": [
"### Endpoint",
"1. Add `GET /api/export` reusing the existing filtered-query builder.",
"2. Stream rows to CSV instead of loading the full result set.",
"3. Enforce the same authorization the results page already applies."
],
"risk": {
"grade": "low",
"notes": "Reuses an existing, tested query path; blast radius is one new read-only endpoint."
},
"scope": ["Export API"],
"exclusions": ["Scheduled exports"]
},
{
"key": "export-ui",
"title": "Users can download filtered results",
"objective": "Connect the results page's download action to the export endpoint.",
"acceptance": ["The downloaded file matches the active filters."],
"verification": ["Planned tests/export-ui.e2e.test.ts: download filtered results through the browser and inspect file contents."],
"implementation": "### Download action\n1. Wire the existing download button to `GET /api/export` with current filters as query params.\n2. Show a loading state until the file starts downloading.\n3. Surface a toast on a non-2xx response.",
"risk": {
"grade": "low",
"notes": ["Additive UI change on an existing button.", "No data model or auth changes."]
},
"depends_on": ["export-api"],
"dependency_reasons": {"export-api": "The download action needs the export endpoint."}
}
],
"major_decisions": [
{
"id": "export-format",
"name": "Choose the export format",
"description": "Which format should the first version support?",
"options": ["CSV", "JSON"]
}
]
}
Replace illustrative paths with this project's real planned proof. Optional
node fields also include context, scope, exclusions, deliverables,
depends_on, dependency_reasons, priority (0–4), and kind
("human" or "post_deploy", which exempts the node from the
pre-merge-unsatisfiable plan lint).
Keep context concise and omit secrets and customer data. The CLI validates the
preview and computes its hash; do not manufacture plan_hash.
3. Check each task in isolation before review
The drafter has the whole conversation, so its tasks read as complete to it even when they lean on context a worker will never see. Before opening review, test each node with a reader that has only that node. Run exactly one round.
-
For every node, start a fresh subagent with no conversation history. Use a smaller, cheaper model than the one drafting the plan: the check needs careful reading, not deep reasoning. The harness knows its own model lineup, so pick its cheaper tier yourself rather than naming a fixed model. For example, Claude Code's Agent tool takes
model: "haiku"or"sonnet"; other harnesses expose a mini or flash tier, or a per-agent model setting. If the harness cannot choose a subagent model, use its default. Prefer a read-only agent type or tool set (for example, Claude Code'sExplore). Run the checks in parallel, batching if the harness limits concurrency. If the harness has no subagent facility, say so and skip this step; do not self-review in the main context as a substitute. -
Give each subagent only that node's JSON object, copied verbatim from the draft, and the prompt below. Do not pass the plan file path, the epic, other nodes, the conversation, or your own summary.
Read-only review. Do not implement anything, edit files, or run commands. You may read the repository to confirm that referenced paths and symbols exist and that referenced commands are defined (package scripts, Makefile, CLI help). Judge whether you could implement the task below if it were all you received: you will not see the conversation that produced it or any other task. Treat depends_on keys as work that will already be done, and nothing more. Return only JSON, with no prose or code fence: {"ready": true|false, "gaps": [{"kind": "field" | "prerequisite", "field": "<node field this gap is about, or null>", "blocking": true|false, "question": "<what you would have to ask>", "why": "<what you would otherwise have to guess, or what you checked>"}]} kind "prerequisite" means the task needs work that neither it nor its depends_on provides. blocking is true when you could not start implementing without an answer; false when you could start but would have to guess partway through. Report a gap when you would have to guess: which files or components to change, the expected behavior or interface, an acceptance criterion you could not verify, a planned test that does not name its file, boundary, or assertion, a referenced path or symbol that does not exist, what a dependency provides, or a scope boundary. Also report an empty or missing `implementation` plan, or a `risk` grade with no stated reason. Do not report style preferences or propose redesigns. An empty gaps list is a valid answer. Task: <node JSON>If a reply is not valid JSON, use a JSON block inside it when present; otherwise list that node as unchecked in the summary. Do not guess its gaps.
-
Triage every returned gap in the main context, which has the full history:
- Answerable from the conversation or code: add the answer to the node
(
objective,context,acceptance,verification,scope,exclusions,deliverables,implementation, orrisk). Write it so a reader without your history could act on it; name real paths and symbols. - A choice only the human can make: add or extend a
major_decisionsentry. Do not pick an answer to close the gap. - Not a real gap (already stated, or out of scope): leave the node as is and note why in the triage summary.
Subagent questions are prompts for missing context, not requirements. Do not add scope, acceptance criteria, or decisions the source did not support. A confirmed
prerequisitegap becomes a new node or adepends_onedge with its reason. - Answerable from the conversation or code: add the answer to the node
(
-
Do not re-run the check on revised nodes or on nodes added during triage. Give the human a short summary in the progress update before review: per task, gaps found, how each was resolved, any moved to
major_decisions, and any node left unchecked.
4. Open the review and keep it running
"$archdev" tasks review start --file plans/task-review.json --no-open
Add the chosen --team and --repository flags to that command when needed.
Run it in the harness's persistent process/PTY facility: it stays running and
streams JSONL. Do not wrap it in a short timeout, wait for it to exit before
opening the page, or kill it when the command tool yields.
- Read the
event: "ready"record. Retain itsurl,sessionFile,stateFile,revision, andplanHashalong with the process handle. - Open that exact URL once in the human's main browser profile using the
available browser/open tool. The page updates in place on revisions.
If browser control is unavailable, hand the URL to the human. Without
--no-open, the CLI attempts to open the default browser itself. - Tell the human where to review and that Approve & save writes Tasks to the selected destination in a progress update, then enter the feedback loop in the same turn. Opening the page and leaving its server running do not monitor feedback; do not end the turn with an invitation to review.
The URL and session handle contain a local bearer capability. Do not commit or publish them, dump the handle contents, or put them in shared logs. The browser must run on a machine that can reach this CLI's loopback server; a remote sandbox's localhost is not the human's localhost. If that boundary prevents review, arrange execution on the human's machine instead of claiming the page is reachable or exposing the server publicly.
5. Listen, revise, and verify saving
Start the feedback cursor at 0 for this session.
"$archdev" tasks review feedback <sessionFile> --after <cursor>
"$archdev" tasks review status <sessionFile>
"$archdev" tasks review update <sessionFile> --file plans/task-review.json --revision <currentRevision>
Keep the turn active and drive this loop until the current revision is saved and verified, the user explicitly pauses/cancels, or a concrete blocker needs their input. Answer status questions in progress updates and continue polling; an incidental interruption does not complete the review. After a blocker is resolved or an interrupted turn resumes, read feedback from the retained cursor and status before continuing; do not wait for the user to announce new feedback.
- Read feedback and status. Feedback returns
{events, cursor}without consuming events. Process new events, then retain the returned cursor. The start process also streams events; avoid processing the same sequence twice. Poll with a modest wait (for example 5–10 seconds), staying responsive to user messages; empty feedback is not approval or a reason to stop. - Match feedback to its
revisionandplanHash. Read plan-wide, task-specific, and decision-specific notes. Map task IDs through the current status request to the stable node keys. Old-revision notes are historical context, not instructions to apply automatically to a new plan. - For requested changes, edit the same JSON file. Preserve keys for unchanged
work; add keys for new work, remove obsolete nodes, and repair dependency
edges. Resolve reviewed decisions in the plan and remove resolved entries
from
major_decisions. Explain briefly what changed and why. - Publish with the current revision from status. On a revision conflict, re-read status and feedback and reconcile; do not blindly retry with an incremented number. Retain the returned revision/hash. Continue on the existing browser page rather than starting another review session.
- For approval, wait for status
savedfor the current revision/hash and inspect itssavedreceipt.savingis still in progress.save_failedmay mean some Tasks were already written. For a transient failure, report the error, address it, and use the browser's save retry. If the error says a Task changed outside this review, inspect that Task, reconcile the draft, publish a new revision, and obtain fresh human approval; retrying the old revision cannot resolve that conflict. Keep the same receipt and session; do not recreate the plan to retry. Never submit approval through a private HTTP endpoint or click Approve & save on the human's behalf. - Verify returned task IDs with
tasks show <task-id>and check prerequisite edges withtasks deps list <task-id>(follow pagination when present). Report the saved outcome and task IDs. If the user requests another revision, continue with the same plan and receipt.
The durable stateFile maps node keys to task IDs. Later approved revisions
update those IDs; removing a previously saved node closes its Task and retains
history. Preserve the receipt even after review ends. Restarting with the same
absolute plan path reuses the default receipt; if moving the plan, pass the
original --state-file <path>. A restarted server has a new session handle and
URL, so open its new ready URL and reset the feedback cursor. Do not delete a
receipt or change its destination to bypass an error.
When finished or cancelled, run "$archdev" tasks review stop <sessionFile>.
This stops the local server and removes its private session handle; it does
not delete saved Tasks. If explicitly pausing for later, retain the draft and
receipt and explain how to restart. Do not report a paused review as saved.
6. Work from the saved Tasks when asked
Approval of a plan saves Tasks; it does not itself request implementation.
When implementation is authorized, use the installed tasks guide lifecycle:
- Read
tasks ready --explain --team <id>(or the intended user scope). - Claim with
tasks claim <task-id> --session-name "<short name>"before working. Retain the returnedlease_idandsession_id; readiness alone is not ownership. - Record progress with
tasks comment. Use both--lease-idand--session-idon fenced updates, close, and release. Close only after verification; re-read ready Tasks when a prerequisite finishes.
Presence commands require CLI 0.46.3 or newer.
When beginning an accessible team-owned task, set current attention with
"$archdev" presence update --task <task-id>. Check presence --help lists
update and clear first; if unavailable after the normal CLI upgrade,
report the limitation and continue the task lifecycle. Personal tasks remain
private: do not publish their IDs or change their ownership for presence.
When attention shifts to its PR or job, use
"$archdev" presence update --pr 'owner/repo#123' --job <job-id> with only the
references currently relevant. Each update replaces all previous references;
include --task <task-id> again only while it still describes your attention.
On finishing or handing off, use "$archdev" presence clear to remain idle.
This neither closes the task nor releases its lease. Run these commands in
the existing harness session; never substitute the task lease's session_id
for CLAUDE_CODE_SESSION_ID or CODEX_THREAD_ID. The CLI owns authentication,
expiry, and concurrency; do not build snapshots or emit room presence posts.
If an update is rejected, earlier attention remains: clear it if it no longer
applies, and report any failure. --json is supported; superseded means a
newer observation won and should not be overwritten by retrying older work.
Keep shared progress on these saved Tasks rather than creating duplicate
harness tasks. Use tasks deps add <blocked-task> --blocked-by <prerequisite>
for explicit changes to existing dependencies, and consult command help for
other lifecycle operations.
7. Audit and unblock paused or failed work
Run this only when the user asks for an audit of paused, failed, or stalled Tasks. Do not start one on your own because you noticed paused work; mention it and let the user decide. The goal is unblocking the graph safely, not rubber-stamping status changes, and every change below still follows the user's direction on decisions and scope.
-
Inventory. Page through work needing attention:
"$archdev" tasks list --status paused --limit 100 --after-cursor <cursor>Repeat for
failed,open,in_review(100 is the max page size). Group results byepic.tasks list --epic "<epic>"filters to one epic;tasks list --status doneshows what already shipped there. -
Find why before changing anything. The pause reason is rarely in the description. Read, in order: the Task's activity feed (status changes, lease claims/releases, who and when), then comments, then description progress notes. If the installed CLI lacks
tasks comments/tasks activity, get the same data fromGET /api/v1/tasks/{id}/commentsandGET /api/v1/tasks/{id}/activity(cursor-paginated) via the ArchDev web app atarchdev.ai/tasks/<id>— never by reading credential files to call the API directly. Prefer the CLI, then the web UI, then a human. A pause with no comment usually means a Factory overseer paused it viafactory_tasks; ask the overseer or its human rather than guessing. -
Check for a live Factory before touching status.
tasks update --status openchanges only the native status — it does not clear a Factory's local state, and the overseer re-pauses the Task within minutes. Look for recent lease claims byfactory:worker-Nin the activity feed. If a Factory owns the work: fix the spec or dependencies, then ask the overseer (or its human) toresumethroughfactory_tasks. Do not fight an active overseer with native status flips. -
Classify each paused/failed Task, then act:
- Spec underspecified or self-contradictory (acceptance vs. deliverables disagree, objective vs. plan drifted, a recorded decision contradicted by later plan steps) → rewrite the description, record the decision with date and decider, comment what changed and why.
- Needs a human decision → ask; record the decision in the description once made. Don't decide scope silently. Check for prior direction first — a decision made without knowing an earlier direction was reverted just repeats the mistake.
- Blocked on another Task →
tasks deps add <task> --blocked-by <prereq>instead of leaving it hand-parked with no edge. - Factory/tooling bug surfaced by a worker → file it as its own Task and add the dependency edge back to the blocked work.
- Acceptance a worker can't meet before merge (production
observation, human visual review, numeric approvals, real
credentials) → split off a separate Task tagged
human(addneeds-accessif applicable), blocked-by the implementation Task. The implementation Task closes on local proof only. - Needs access/credentials → leave paused, tag
needs-access, comment the exact human action required. - Duplicate or superseded → cancel with a comment pointing at the replacement Task.
- A "done" prerequisite never actually shipped (no commit/PR/ result on the default branch) → reopen it; dependents re-block automatically. Verify against git on the default branch, not the Task's status field.
- Churn (hundreds of versions, the same failure repeating,
"workspace preparation failed" on retry) → stop retrying. Reset the
spec, or ask for
restart_clean. Destructive cleanup of retained work needs human authorization first.
-
Batch per epic.
tasks reviewonly safely edits an existing graph when you hold that plan's receipt/state file — a Factory-created plan keeps its receipt locally, so a newtasks reviewon it creates duplicates instead of updating it. Otherwise batch manually: write each task's new description to a file and runtasks updateper task, keeping the same task IDs. -
Mechanics gotchas:
--tagreplaces the full tag set — re-pass existing tags (includingarchdev-plan,plan:<id>,plan-key:<key>) whenever adding one.- Build multi-flag commands as an argument array; zsh does not word-split a flags string.
- Pass long descriptions from a file (
--description "$(cat file.md)") to avoid shell-quoting bugs. - Create new human-only Tasks paused and tagged
humanso Factory workers don't claim them.
-
Comment every status change with why and what it unblocks. A status change with no comment is as opaque to the next person as the pause it resolved.
During staggered releases, check tasks create --help for --project
before authoring tasks with this guidance. If unavailable, upgrade the CLI;
do not silently omit membership. Keep project names at most 80 characters
until the deployed project schema and all participating CLI readers support
200. Do not truncate an epic to create a misleading match; defer creating
that project until those deployments are ready.