taskflow · git:20261104.c50f5ca · 2026-11-04 · sha256 08fc3a68aa8f9afa

taskflow git:20261104.c50f5caA

Immutable. This exact content never changes and is served at /api/v1/blob/08fc3a68aa8f9afa.

---
name: taskflow
description: "Manage repository development requests through TaskFlow: features, fixes, refactors, tests, configuration/build/CI changes, and explicit $taskflow planning or research. Not for releases, which run RELEASE.md directly, and not for read-only explanation, translation, status, research, review, or diagnosis unless the user explicitly invokes $taskflow."
---

# TaskFlow

Use this skill as the single entry point for the project's task framework. It defines where task facts live and how work moves through the lifecycle. TaskFlow does not select tools: during clarification, PRD, Spec, Plan, research, and review work, first check the capabilities currently available to the Agent and use any that materially help. Review and route only incorporated task facts into the current task directory.

## Applicability gate

Apply TaskFlow automatically only when the request asks to modify a repository or deliver a development artifact, including a feature, bug fix, refactor, test, or configuration/build/CI change. Do not create or update Todo/task documents for read-only explanation, translation, status queries, research, review, or diagnosis. If such work later leads to an implementation request, begin TaskFlow with that new request. An explicit user request to use `$taskflow` opts any planning or research work into this workflow.

**A release is the exception: it does not pass through TaskFlow.** `RELEASE.md` is the procedure, and it runs from the base checkout with no TaskFlow task, no Todo item, no branch, and no PRD, Spec, or Plan. Its record is the `CHANGELOG.md` section and the GitHub Release body. An explicit `$taskflow` request, or a release that changes the plugin itself rather than shipping what is already merged, is ordinary development work and is handled as one.

Decide this applicability before Todo intake. If TaskFlow does not apply, answer or investigate directly and stop reading this workflow.

**The order is TaskFlow first, then the phase, then the capability.** When the applicability gate applies, the work enters TaskFlow before any of it is done, and every capability is selected and invoked inside a phase, not before one exists. Three failures follow from getting this backwards, and all three are ordinary rather than exotic. Research done before the record exists has no phase to belong to, so the record written afterwards cannot describe where that work came from and the reader cannot tell it happened. Work carried far enough to have findings before anyone asks whether it should be recorded is work whose registration is now a formality performed after the fact. And a capability that helps is easiest to notice while the phase is being done, so a phase entered without one tends not to acquire one.

This is an order, not a second gate: an applicability decision that is wrong is still correctable, and a task entered early is cheaper to re-scope than work whose origin cannot be reconstructed. It does not make every request a task either — the applicability gate above still decides whether a task exists at all, and a request that fails it is answered directly. Where it does apply, this is what "before" means: the Todo record exists before implementation, and the capability for a phase is chosen when that phase starts, which is what makes it recordable as that phase's rather than as an unattributed call.

TaskFlow may coordinate with host/harness hooks (Claude Code, Codex CLI, CodeBuddy, dsh, and Trae) for bounded bookkeeping and context. Host hooks are optional optimization, not a prerequisite: an environment without hooks runs the same flow. See [references/runtime.md](references/runtime.md) for what hooks may and may not do.

## Source of truth

For an active task, the task directory is:

```text
TaskFlowDocs/YYYY-MM-DD-short-slug/
```

`TaskFlowDocs/repository-docs/index.md` is the authoritative routing and check record for repository documents, repository rules, and personal rules. Maintain or read it first, route by phase, then load the listed source documents; those source documents remain authoritative for policy content. Record selected paths and incorporated conclusions in the active task Plan. If the task needs a rule that the repository does not provide, use the repository-document rules below before implementation.

`TaskFlowDocs/todo.md` is the mandatory intake record for every request that passes the applicability gate, including qualifying direct development requests, GitHub Issues, other development imports, and explicit `$taskflow` requests. Create or update its Todo item before task matching, clarification, promotion, planning, implementation, or import-specific processing. It is not a second source of task facts: after promotion, the linked `TaskFlowDocs/<task-id>/` directory is authoritative for requirements, design, plan, and verification.

Required artifacts:

- `prd.md` — goal, requirements, scope, and observable acceptance criteria.
- `plan.md` — current Task version, state, approval, steps, progress, verification, review, risks, rollback, and follow-ups.

Conditional artifacts:

- `spec.md` — required for a large task; optional for a small, self-contained task.
- `reference/` — optional research and evidence. Create `reference/index.md` only when the material is numerous enough to need navigation.
- `sessions.md` — session/resume index. Optional as a file; whether an entry must be written is a condition, stated under **Sessions and collaboration**.
- `old/vN/` — only for a superseded logical version.

Never create a second task fact source such as a root `SPEC.md`, `TaskFlowDocs/plan.md`, or an automatic review file for the same task. `TaskFlowDocs/todo.md` is the sole repository Todo inbox; it contains triage metadata only and never duplicates promoted task facts.

Task documents are read by the user and parsed by hooks, so they carry two languages at once. Write the prose, and any section heading the boundary does not name, in the user's working language; keep the lines hooks match — the section and entry headings they match by name, the `## Approval` fields, `> Task version:`, `> Status:`, `- Status:` lines, Todo field names, and `- [ ]` / `- [x]` markers — in English exactly as the hooks expect. The rule binds the document, not its drafter: a capability invoked for a phase supplies a shape to fill, and prose folded in from it is written in the user's working language like any other. `references/artifacts.md` states the boundary as an explicit name list, and says why a heading outside it is free to be translated, why a scaffold arrives in English whether `hooks/task promote` or a capability's template wrote it, and why that exemption stops at the headings. Existing documents, including everything under `TaskFlowDocs/achieved/`, are not rewritten for language.

## Triage and lifecycle

After the request passes the applicability gate, first record or update its Todo item. Then inspect the repository, `TaskFlowDocs/repository-docs/index.md`, applicable project rules, active and achieved TaskFlowDocs tasks, tests, configuration, Git state, and uncommitted changes. Separate findings into confirmed facts, user decisions, technical unknowns, and explicit exclusions.

### Todo-first intake

Every request within TaskFlow's applicability boundary enters `TaskFlowDocs/todo.md` before task selection. Record its ID, source, goal, status, next action, update date, and external identifier/link when one exists. Deduplicate imported items by source plus external identifier; preserve distinct requirements even when imported as a batch. A batch may carry common source metadata, but it is never itself a task, PRD, or requirements source.

Prefer `hooks/task intake`, `promote`, `unpromote`, `state`, `progress`, `unaided`, and `complete` for their bounded mechanical edits. Use Agent edits for semantic content and cases those commands do not cover. These commands are explicit Agent actions, not automatically bound hooks.

A task name is one path component, `YYYY-MM-DD-short-slug`, and every command that takes one validates it (`hooks/task-id`) before joining it into a path — `promote` runs `mkdir -p` on it, and `archive`/`reopen` move a directory named by it. `task unpromote <todo-id> <reason>` is `promote`'s inverse: it removes the directory and returns the entry to `inbox`. It refuses while the directory holds tracked files, or once the Plan's `## Approval` has left `requested`, or once a document has left `> Status: planning`, because from that point the directory is somebody's work rather than an empty scaffold.

Do not create, reopen, modify, or select a task before the Todo record exists. After promotion, retain lifecycle metadata, source identity, and one task link in Todo; do not duplicate task facts. Update the Todo status as the linked task moves through `inbox → clarified → promoted → in_progress → done/cancelled`.

**Report overlap before you commit to a task.** A Todo record existing is not a fact that the work is unclaimed. Once the new item is recorded and before a task is created or selected, compare it against the live Todo items and the active tasks, on two axes: item against item, and request against task. `hooks/task intake` reports word-overlap candidates on standard error; that is a hint about wording, not a finding, and it is silent whenever the two goals happen to share little vocabulary. The judgement is yours, and where a candidate is real — the same work, a scope another item already covers, or two goals that cannot both hold — say so to the user and get their choice before planning either one. Never leave two entries covering one piece of work without saying it out loud, and never merge, close, or re-scope another entry on your own. Only duplicated *requirements* are quietly folded: two items recorded in one turn that trace to the same source and the same external identifier are one item.

### Existing-task-first selection

Search active tasks before creating a task. Also compare against achieved tasks to identify a later request that belongs to an achieved deliverable. Compare the request with each task's goal, deliverable, owner, scope, acceptance criteria, open questions, and next Plan Step.

| Request relation | Required action |
| --- | --- |
| Advances an active deliverable, planned step, open question, verification, or follow-up | Maintain that task |
| Materially revises the same deliverable | Version that task and obtain re-approval |
| Belongs to an achieved task's deliverable | Retrieve that task, version it, and obtain re-approval |
| Has an independently releasable outcome **and** independent acceptance criteria | Create a related task |
| Has different owner or accountability | Create a related task |
| Mixes existing-task work with an independent deliverable | Present the split and await the user's choice before creating a second task |

A new session, new Agent, or a changed implementation detail is never by itself a new-task trigger. Before continuing an existing or retrieved task, read its current PRD, Spec when present, Plan, applicable repository documents, approval/version/status, next Step and checklist, and latest verification. Update the Plan after meaningful work, including progress, decisions, deviations, and verification; do this before starting unrelated work.

**A task's requirements are its own.** No task owns another task's documents, and this one is not an exception for a parent or a child: a child that finds its parent's approved requirement wrong reports the finding in its own `plan.md` and to the user, and does not edit the parent's `prd.md`, `spec.md`, or `plan.md`. The parent's requirements change only through its own User-change trigger, in its own working tree, by whoever owns that task — that is a separate act from the child's work, and it is not made easier by the two being in flight together.

Record the relationship and the version it rests on. `plan.md`'s `## Related Tasks` carries the direction as well as the link, and a child records there the parent Task version it planned against. When the parent moves to a new version, the child is reading a description of the system that has changed: re-record the parent version before continuing, and re-obtain approval only if the change touched the child's own approved contract. Prefer a child that depends on the parent's *outcome* over one that depends on its *internals*; the second is what forces the two to move together.

When work targets a pull request, fork, or Git remote, inspect the configured remotes, intended target repository, base branch, local branch/base relationship, and available repository-host guidance such as contribution guides, PR templates, CODEOWNERS, branch or CI rules, and host metadata. Remote names are conventions, not proof: never assume `origin` is the fork or `upstream` exists. Before creating or updating a PR, read the applicable PR template, treat unchecked fields as required unless explicitly optional, map every field to the PR title/body/checks/user decision, and record the template path, mapping, and verification in `plan.md`. A missing, ambiguous, or conflicting required item blocks PR mutation. Record URLs with credentials redacted, freshness limits of remote-tracking data, reviewed source paths, conclusions, and required pre-PR checks in the catalog or linked TaskFlow document. Do not silently add or rewrite remotes, fetch, rebase, merge, push, open a PR, claim synchronization when access fails, or copy secrets, tokens, private data, or opaque remote payloads. If target or base cannot be established from current evidence, stop and ask the user.

### Repository document environment

`TaskFlowDocs/repository-docs/index.md` is the routing/check record, not a copy of source policy. Before non-trivial work, maintain or read it first. Its deterministic SessionStart synchronizer records recognized repository-document paths with class, applicable phases, existence, and status, and one row naming the personal-rule location — marked `Exists: local`, because that file is never committed and the index is. Whether this clone has a personal rule is a per-clone fact, so the synchronizer reports it on the session route line instead of writing it into the committed index. The hook may update only this routing metadata and inject applicable paths/status; it never edits source documents, task core documents, approval, or Git/hosting state. Add an unrecognized candidate only after user confirmation.

Repository-owned documents live at their conventional repository locations, with the repository root preferred for README, contributing, code style, and roadmap documents and platform-standard directories used for PR templates, CODEOWNERS, CI, and similar files. Never copy or symbolically link them into `repository-docs/`; that directory contains `index.md` plus optional local personal rules in `personal.md`, which is never committed. Source documents are authoritative. Refresh the catalog after their addition, removal, move, or relevant change. If a changed source rule affects approved work, apply the user-change trigger before continuing.

When a non-trivial development task needs a missing repository-owned document, help the user create the smallest evidence-based document at its conventional source location. **A repository that has never carried rules is the common case, not an edge one**: the plugin ships a default `CONTRIBUTING.md` and `CODE_STYLE.md` under `hooks/templates/`, and `hooks/repo-rules show <name>` prints one without writing anything, so the user can read the actual text before deciding. `hooks/repo-rules create <name>` writes it, and refuses when the file already exists — a repository that has rules owns them, and replacing one would discard a decision somebody made. Never create either unasked: showing is not installing, and the reminder that points at these commands says so. `hooks/repo-rules check` reports places where an existing rule and this workflow would disagree — a rule requiring every change to go through a pull request, a commit prefix other than `<type>: `, a rule that commits straight to the main branch — naming the file and line each time. Those are keyword matches, so the output says *possible* conflict and never resolves one. For missing `CONTRIBUTING.md` or `CODE_STYLE.md`, derive confirmed practice from repository files, scripts, tests, CI, code patterns, history, and host guidance, ask at most three dependency-ordered questions for undecidable policy, draft the document, record evidence and intended effect in the Plan, and obtain explicit user approval before it becomes binding. Create `ROADMAP.md` only after the user confirms product direction; create README, PR templates, CODEOWNERS, CI, release, code-of-conduct, or similar documents only when the task needs them. Never create an empty template, fabricate policy, or treat a personal rule as a substitute. If legacy copies or symbolic links exist under `repository-docs/`, report them, stop using them, and index the authoritative source path; do not migrate or delete them without explicit user authorization.

Select documents by phase: code work uses code style and contributing guidance; commits/PRs use contributing, commit rules, PR templates, CODEOWNERS, and branch/CI rules; design/API/UX work uses design and architecture guidance plus relevant README behavior; release work uses release/changelog guidance; roadmap work uses roadmap and README. Record applicable documents and incorporated conclusions in the task `plan.md`. Missing document classes are informational unless the task needs them; then resolve shared governance through an approved repository-owned document and personal habits through a scoped personal rule.

Repository documents prevail over personal rules. A personal rule may add stricter or orthogonal practices, but cannot weaken, override, or conflict with any applicable repository rule or guidance. A personal rule applies only if its declared scope matches the task. On a conflict, stop and ask the user; do not silently choose one.

### User-change trigger

Treat a user message that corrects, rejects, adds to, or materially changes an approved task fact as a change event. Stop the current phase immediately. Do not update only the document named by the user or continue under stale PRD, Spec, or Plan facts.

An instruction to change something is a change event whether or not it is worded as a correction. This is the case that most often escapes: a task is `in_progress`, implementation is running, and the user reports a defect or asks for something the Plan does not contain — "fix this bug", "this is wrong", "do it this way instead". Because it arrives as new work rather than as a rejection, it is easy to absorb into whatever Step is running and keep going, and then `plan.md` no longer describes what is being built. It is a change event like any other, and the Step you were on does not resume until it is classified.

Classify the change into exactly one of two buckets before editing anything. The question is: Does it change what this task promised to deliver, or only how it is delivered? Read it against the approved goal, requirements, acceptance criteria, and Spec contracts — not against whether it feels like part of the task. When the answer is not obvious, take the work revision: it costs one change-log line, while a version change archives the current version, returns the task to `ready`, and stops implementation until the user re-approves.

| Change | Examples | Required action |
| --- | --- | --- |
| Work revision (default) | wording, an implementation approach within the approved design, formatting, a progress/checklist update, a verification result, a correction that does not alter an approved contract | Update only affected current documents and record one line in the Plan's change log. Keep the current Task version. |
| Task-version material change | a change to an approved goal, requirement, acceptance criterion, scope, architecture/interface/data contract, compatibility decision, risk decision, or standard | Archive the current Task version, update every existing core document atomically to `vN+1`, return the task to `ready`, and record a new approval before implementation resumes. |

A completed task is read-only in `TaskFlowDocs/achieved/`: if the classified request belongs to its deliverable, retrieve its complete directory to the active TaskFlowDocs root, record the Todo source and reopen reason, then version and re-approve it before changing core documents or implementation. Create a related task only when the existing-task-first boundary requires one.

### Missing repository rules and personal rules

When a task needs a rule not supplied by the repository, first determine whether the gap belongs in repository-owned governance or a personal rule. Missing shared development discipline belongs in an evidence-based repository document as described above; personal rules are only for a person's stricter or orthogonal habits. Ask no more than three dependency-ordered questions per turn, with a recommendation for each; ask only applicable categories (development process, code, commits/PR, then design by default). A repository-owned source document may be created or changed only with explicit user authorization.

After confirmation, append only the selected personal rule as its own section in `TaskFlowDocs/repository-docs/personal.md` (create that file if absent); the next sync reports it on the session route line. Each section must declare `Scope`, `Repository documents checked`, `Rules`, `Verification`, and `Exceptions / Change control`; commit-related sections also state `Commit format` and `PR checks`. Other `*.md` files beside `index.md` are not personal rules. Record any explicit waiver in the catalog and task Plan; never create an empty placeholder or fabricate repository-owned policy.

A personal rule is a local working rule, not a deliverable: it is excluded from Git, so never commit or push `personal.md`, never include it in a pull request, and never present it as team policy. That exclusion is installed rather than assumed — `hooks/install-git-hygiene` writes the rule into the clone's own `.git/info/exclude` on every session start, so it holds in any repository without that repository committing anything; a host not running the hooks needs one manual `bash hooks/install-git-hygiene`, and the rule never hides a copy that is already tracked. Removing the file from disk stops the next sync from routing it; the location stays cataloged, because the index one clone commits cannot record what another clone has on disk. Anything that must be shared, reviewed, or survive a fresh clone becomes a repository-owned document at its conventional source location under the rules above. Using a personal rule in a task does not make it commit material.

### Todo → PRD → Spec → Plan

**Isolate before the first document.** A task's artifacts are written in Phase 1, not Phase 5, so the isolation has to come first: before creating any `TaskFlowDocs/<slug>/` file or `todo.md` entry, give the task its own branch and its own working tree, and stay in it for the rest of the task.

```bash
git worktree add .worktrees/<slug> -b <type>/<slug> <base>
cd .worktrees/<slug>
```

One task, one working tree — not only when several tasks run at once. The base checkout then stays on `<base>` and clean, which is what makes the next task's branch startable at all: `git checkout` refuses to move while a shared file like `TaskFlowDocs/todo.md` carries uncommitted work from a task that belonged elsewhere. `<type>` follows the repository's branch prefixes (`CONTRIBUTING.md`); `.worktrees/` is ignored, so the worktrees themselves never appear as changes. `hooks/task promote` refuses to run outside a task working tree for this reason, and `hooks/task intake` warns when it has written `todo.md` in a shared one.

**Know which working tree you are in, and move the work rather than the rule.** Isolation is a fact about where you are standing, not a promise, and the two are easiest to confuse exactly when work has already started. The base checkout and a task working tree are different directories with different branches, and a file exists in whichever one you are in — an edit made in the base checkout is not "uncommitted work on the task branch", it is work on `<base>` that the task's branch cannot see. So establish it before the first edit rather than discovering it after: `git branch --show-current` names the branch, and `pwd` against the worktree you created names the directory.

If work has already started in the base checkout, move it before continuing:

```bash
cd <base-root>
git status --short                   # what is actually uncommitted here
git stash push -u -m "<slug>"        # -u carries new files; named so it is findable
git worktree add .worktrees/<slug> -b <type>/<slug> <base>
cd .worktrees/<slug>
git stash pop                        # the work arrives as uncommitted changes here
```

Two things that version-control the honest version of this: a dirty base checkout is not a staging area, and a move is not always a copy. Tracked files that are unmodified in the base tree are already on `<base>` — `git stash push` leaves them alone, correctly, because they will be there in the worktree too. What the stash carries is what is genuinely uncommitted, and a stash pop that conflicts is telling you the two trees had diverged, which is a fact to resolve rather than to work around. If the base checkout carries work for a *different* task, that task belongs in its own worktree, and moving it into this one is the wrong repair.

A worktree isolates the work; it does not decide where the commits land. `CONTRIBUTING.md` states that separately, and it is not one question but two independent ones — where a task's own documents go, and where the bookkeeping that belongs to no task goes. Read it there, including the checkable facts that decide it, rather than from a summary here.

Use `TaskFlowDocs/todo.md` as the single intake for every idea, request, and imported requirement, whether or not it is ready for planning. Maintain each item with an ID, status, priority, owner, source, external identifier/link when available, one-sentence goal, task link, next action, and update date. Move it through `inbox → clarified → promoted → in_progress → done/cancelled`.

For batch imports, create or update one Todo item per source requirement before triage; deduplicate only source-identical requirements, retain source identity, and never promote a whole batch as one task. Keep an item in `inbox` while its intent is unknown. Move it to `clarified` only after goal, scope, acceptance, dependencies, size, and applicable repository documents are explicit. On promotion, create `prd.md`, decide whether `spec.md` is required, create `plan.md`, and link the task path back in the Todo item. Do not duplicate requirements or design in the inbox. Enter `in_progress` only after Plan approval; mark `done` only after task acceptance and verification, or `cancelled` with a reason.

Choose the lightest path that preserves traceability:

```text
small, obvious one-file change → direct change + minimal verification
non-trivial task              → planning workflow below
```

TaskFlow is the task-lifecycle and artifact layer, not the expert-capability layer. Before substantive work in any TaskFlow phase, inspect the capabilities currently available in the host environment, including Skills, tools, MCP servers, and Agents, and freely determine whether any can materially improve the current task, artifact, or decision. TaskFlow does not require the selection or use of any particular capability, provider, chain, category, or number of capabilities. When the Agent selects one for use, invoke or load it immediately through the host's supported mechanism before following its workflow or incorporating its output; discovery, listing, or selection alone is not invocation.

If none apply, continue with the base TaskFlow flow. If an optional invocation is unavailable or fails, continue with the base flow and record the failed or unavailable attempt only when it materially affects the task; block only when the capability is required for correctness and no safe alternative exists. Review successful outputs before incorporating them; raw outputs are not authoritative. When `plan.md` exists, record only actual invocation attempts: for success, record purpose and incorporated conclusions; for a relevant failure, record the failed or unavailable outcome without claiming incorporation. Do not record discovery, selection, or an uninvoked capability as used.

A phase's artifact has an equivalent outside TaskFlow. TaskFlow names these itself, so an available capability rarely advertises "PRD"; match on the concept instead, and consider the class below before writing the artifact unaided. The class says what to look for, never what to use: availability, fit, and the decision to proceed unaided stay yours.

| Phase | Artifact | Equivalent concept class | Consider a capability for |
| --- | --- | --- | --- |
| 1. Define — PRD | `prd.md` | requirements elicitation and framing; divergent exploration | expanding a vague goal into several directions before converging on one, interviewing the user, refining a vague idea into testable requirements, writing a requirements document |
| 2. Research — Reference | `reference/` | literature and evidence review | searching external sources, assessing evidence quality, annotating findings |
| 3. Design — Spec decision | `spec.md`, or the recorded `No spec required` | architecture and design specification | methodology or architecture design, interface/contract definition |
| 4. Plan — execution contract | `plan.md` | work breakdown and task decomposition | decomposing work into verifiable steps, sequencing dependencies, estimating |
| 5. Build — implement by Plan | the change itself | incremental implementation | language and framework conventions, pattern guidance for the code being written |
| 6. Verify and review | acceptance and findings | testing strategy and code review | designing or writing tests, adversarial review, security or performance review |
| 7. Complete and archive | archived directory, promoted rules | documentation and decision records | writing durable documentation or an ADR, recording the decision trail |

A phase ran unaided when its artifact exists but nothing was invoked for its concept class; that is a legitimate outcome, and it is recorded as one — `hooks/task unaided <stage> --considered "<concept class>"` — rather than asserted in prose. `## Skills / Tools Used` in `plan.md` is required, and a phase that ran unaided says so in one `Unaided — …` line rather than staying empty. The class list names what to look for in every phase, and `[Test]` is required of every task even when the Plan writes no test Step: decide the phase, then record what was decided.

**The first body write of each stage document is gated.** A `PreToolUse` hook refuses it until a capability really was invoked for that stage, because that section is a report of what happened and no wording in the document can stand in for a call that never ran. Invoke when the document starts, not after it is written: the gate releases one stage per evidence record it consumes, oldest first, so `prd.md`, `spec.md`, and `plan.md` each spend their own record and a version needs one record per stage written. **Which record lands on which stage follows the order the documents are written, not the order the calls were made** — the gate attaches the stage, and `capability-evidence` does not know which phase is running. A call made while drafting one document can therefore be the record a later document spends, and a phase that invokes twice leaves its extra record to the next phase. Stage lines look like `- [PRD] \`some:cap\` — purpose: …; outcome: …; incorporated: …` or `- [PRD] Unaided — …; considered: <concept class>`. `task approve` requires `[PRD]`, `[Plan]` and `[Test]` always, and `[Spec]` when `spec.md` exists, and reconciles each required stage line against **this Task version's** release records: an invoke line must name a capability the version released as an invocation (any stage's, because no record carries the stage of the call), an Unaided line must carry the class recorded for that stage — that one is typed into `hooks/task unaided` and written back by the same command, so it reconciles exactly. `[Test]` is the stage whose artifact is not a document: tests span many files over several Steps, so nothing is there to gate, and `hooks/task unaided Test` instead spends a standing evidence record when one exists — which is why its kind follows the queue rather than the caller, and why the command prints what it wrote. Untagged bullets do not satisfy a stage. Fold external requirements/design/planning output by kind: requirements → `prd.md`, design → `spec.md`, breakdown → `plan.md` Steps; never a foreign root `SPEC.md` or `tasks/plan.md` as a second fact source.

For a non-trivial task:

```text
planning → ready → in_progress → checking → completed
    │                         │
    └──────── blocked ◄────────┘
```

- `planning`: requirements, evidence, design, or applicable repository documents are still being clarified.
- `ready`: PRD, required Spec, and Plan are complete and awaiting user approval.
- `in_progress`: the user approved the current Task version; implementation is allowed.
- `checking`: implementation is done and acceptance/quality verification is running.
- `blocked`: a concrete blocker is recorded with reproduction, attempts, and needed input; resume the prior phase when cleared.
- `completed`: acceptance and verification passed. Execute the archive transaction defined in **Complete and archive** below: move the entire task directory to `TaskFlowDocs/achieved/<task-id>/`, update the linked Todo item's `Task:` path to that achieved path and its status to `done`, then verify the active path is absent, the achieved path exists, and the achieved root PRD and Plan both say `completed`. If any part fails, leave the Todo item not `done`, record the blocker, and do not claim archival completion.

`ready` is not approval. Do not implement until approval is recorded in `plan.md`.

## Phase routing

### 1. Define — PRD

Create `prd.md` before implementation for a non-trivial task. It must state:

- Goal and user value;
- confirmed background facts;
- requirements;
- observable acceptance criteria;
- whether any conclusion depends on a fact from outside this repository, in `## External Facts`;
- in-scope and out-of-scope work;
- risks, deferred items, and only blocking open questions.

`## External Facts` is answered once, and `hooks/task approve` reads it: `- Depends on external facts: no` needs a `- Why not:` line, and `yes` needs at least one `- Source: <absolute http(s) URL>` with a `- What it settled:` line saying which conclusion that source changed. The question is whether a conclusion could be falsified by something outside this repository — a version, a specification, someone else's documented behaviour. Code that is only in this repository, and facts only this repository can settle, belong in `## Reference Pointers` instead. Answering `yes` is a commitment to go and look, not a note that looking might be useful: the phase table's `searching external sources` is what that answer invokes, and a `yes` with no source behind it is refused. Most tasks here are internal and answer `no`; the field exists so that answer is a decision rather than a default. **Searching is allowed.** When you think a fact might live outside the repository, go and look — a built-in search or fetch, an MCP tool, or a CLI run through `Bash` all count, and whichever you reach for is recorded for you in `taskflow/external`. Reaching for one is never a boundary crossed and never wasted work; the only thing checked is that a `yes` has a lookup behind it.

Record which repository documents were inspected and which apply. If remote PR-rule discovery was attempted, record its sources, result, and incorporated conclusions without storing sensitive payloads.

**Before this phase converges, ask where the answer comes from.** A requirement earned from memory is indistinguishable, in the document, from one earned by looking — and everything this phase is told to inspect is inside the repository, so nothing here prompts the question. Ask it once, explicitly: *which of these conclusions would a reader have to check against something outside this repository* — a version, a specification, another project's documented behaviour, a price, a limit. When the answer is none, say so in `## External Facts` and point at where the reasoning is settled inside the repository; when it is not none, go and look before writing the criterion, and the lookup is recorded for you. If looking is what the criterion needs, look: you are allowed to search, and nothing about this workflow treats a lookup as scope creep. A `yes` with no lookup behind it is refused by `task approve`, which is the whole point: the field records a decision, and the record makes the decision checkable. Do not answer `no` because the work feels internal — that is the default this question exists to displace.

Expose assumptions and turn vague requests into testable criteria using the approach that best fits the task. Do not silently decide product, compatibility, or risk questions owned by the user.

**When the goal or the approach is not yet settled, diverge before you converge.** Writing requirements is a converging act: it picks one reading of the request and turns it into criteria, which quietly discards the readings not yet on the table. So when the request leaves the target or the way to reach it undetermined, or more than one workable direction exists, this phase opens with the class above — `divergent exploration` — before `prd.md` is drafted. The condition is the state of the request, so it is answerable from what you have: a request whose goal and approach are both fixed converges directly, and one that is still an idea does not. What the class produces is candidate directions and the trade-offs between them, for the user to choose from; only the chosen ones become requirements, and the rest are recorded as out-of-scope or deferred so the discarded ground is visible rather than lost. As with every class in the table, this names what to look for and never what to use — availability, fit, and the decision to proceed unaided remain yours, and an unaided PRD is a legitimate outcome recorded as one.

### 2. Research — Reference (optional)

Use `reference/` only when external evidence, codebase investigation, experiments, or papers materially affect the decision. Preserve external originals; write conclusions, source status, and links in team-maintained notes. If `reference/index.md` exists, treat it as navigation, not a second requirements source.

Agent suggestions may mark evidence as candidate. Only the Primary Agent or user confirms `verified`, `rejected`, or `superseded` status.

### 3. Design — Spec decision

**Re-ask the external-facts question here, because this is where it can change.** Phase 1 answered it against the request; this phase answers it against the contract. Defining an interface, an error semantic, or a compatibility boundary is exactly when a "we are only changing our own code" reading stops being true — a status code another service must accept, a field a plugin manifest must declare, a version an operator must install. If Phase 1 answered `no` and this phase turns out to depend on something outside, say so rather than proceeding: the answer changes, `prd.md` changes, and any lookup made now is recorded like any other. Searching to settle it is allowed here too — defining the contract is exactly when a lookup is most likely to be needed, and reaching for one now is not a late admission that Phase 1 was wrong.

Classify the task before planning:

- Large: multiple modules/files, architecture/API/data-flow/compatibility/error-contract changes, multiple sessions, or roughly more than 30 minutes. `spec.md` is required.
- Small: one file, clear boundaries, one short session, and no cross-layer contract. `spec.md` may be omitted.

When omitted, put this exact decision in `plan.md`:

```text
No spec required — <brief reason>
```

For a large task, `spec.md` records architecture boundaries, responsibilities, data flow, interfaces/events/database contracts, invariants, compatibility, error semantics, design trade-offs, code patterns, and testing constraints. A multi-capability task may place a Capability Map in `prd.md` scope/overview or `spec.md` module boundaries; do not create multiple root-level Specs by default.

### 4. Plan — execution contract

Create or update `plan.md`. Route generic planning outputs such as `TaskFlowDocs/plan.md` into this task's `plan.md`; retain unpromoted Todo intake in `TaskFlowDocs/todo.md`. Each Step should include:

- goal;
- dependencies;
- files likely touched;
- implementation checklist;
- acceptance;
- focused verification command or manual check;
- rollback point;
- status: `pending | in_progress | done | blocked`.

The `Implementation checklist` is a checkbox list, not prose. A Step cannot be marked `done` until every required checkbox is checked and focused verification passes.

A `## Change Log` in `plan.md` records work revisions — wording or approach changes, progress, results, and other updates that do not alter an approved contract. Append one line per revision and keep the current Task version. Only a Task-version material change bumps `vN`, updates every core document atomically, and returns to approval. Do not treat a wording or approach clarification as a Task-version event.

Include checkpoints after meaningful groups of steps. Record risks, deviations, verification results, review findings, and unresolved follow-ups. `Skills / Tools Used` is required: stage-tagged invoke or Unaided lines as each document starts (see the capability section); do not leave the section blank. `task approve` rejects missing stages and unqualified stage Unaided lines.

**Before requesting approval, read `## External Facts` one last time against the Plan.** The Steps were not written yet when Phase 1 answered, and they are where a task most often discovers it needs to know something the repository does not contain — a tool's actual behaviour, a format another project defines, a limit that is not documented here. A `yes` must have its lookups already done and recorded, because `task approve` refuses one that does not; a `no` must still name where the work is settled inside the repository. If this pass changes the answer, change `prd.md` and note it in the change log rather than approving a document whose facts section no longer describes the work. And when a Step turns out to rest on something only the outside world can settle, stop and go and look: searching mid-task is allowed, and it is recorded wherever it happens.

Record approval as:

```markdown
## Approval
- Status: approved
- Approved by: <user / role>
- Approved at: YYYY-MM-DD HH:mm +08:00
- Approved version: v1
- Approved scope: PRD / Spec / Plan
```

After the user has approved, write those five fields with `task approve <task-id> [approver]` (default approver `user`). The hook only transcribes the decision you already have; it does not approve on its own. Hand-edit the block only when the hook is unavailable.

### 5. Build — implement by Plan

Before the first edit, confirm the task's working tree is still the one you are in — isolation was established in Phase 1, before the first document, and this phase only carries it forward. If it was skipped, do it now before editing, following the move procedure under **Isolate before the first document**: `git worktree add .worktrees/<slug> -b <type>/<slug> <base>`, then carry the uncommitted work across rather than re-doing it. Read the applicable repository guidance first — `CONTRIBUTING.md` names the branch prefixes and the base-branch rule; follow it when the repository states one, and otherwise branch as `<type>/<description>` off the intended base. Record the branch and worktree in `plan.md` when they are not obvious from the task directory.

Every task appends to the one `TaskFlowDocs/todo.md`, so merging parallel branches touches that file even when the branches share nothing else. TaskFlow installs a per-entry Git merge driver for it (see [runtime.md](references/runtime.md)); merge the branches locally so it runs, and expect an ordinary content conflict when a pull request is merged in a hosting web UI.

When a merge or rebase you run hits a conflict, stop and put both sides in front of the user, who decides what to keep; do not silently choose one. Record that decision in the task `plan.md` before continuing. An automatic merge needs no action. A conflict on a pull request merged in a hosting web UI is outside this rule — that path is resolved on the platform, not by the Agent.

After approval, read `prd.md`, `spec.md` if present, `reference/` if present, and `plan.md`. Implement one focused Step at a time. Keep changes within the PRD scope and current Spec contracts. Update `plan.md` after each meaningful Step and run its smallest useful check.

If an approved goal, requirement, acceptance criterion, scope, or Spec/architecture contract changes materially, stop implementation, archive the old logical version, create the next Task version, update all existing core documents atomically, and return to `ready` for approval. A change to implementation wording or approach within the approved design is a work revision: update the affected documents and add one change-log line, without a new Task version.

**An instruction that arrives mid-Step and is not the Step itself — a defect reported, a different approach demanded, "fix this first" — goes through the User-change trigger before any of it is implemented.** Report the finding and classify it while the Step is still open; do not finish the Step first and classify afterwards, because the edit is what makes the work invisible. A defect in code this task wrote is usually a work revision; a defect that shows the approved approach cannot meet the acceptance criteria is a material change, and the difference is the question the trigger asks.

The same rule applies when the applicable repository-document contract changes materially: archive the prior Task version first, update `prd.md`, `spec.md`, and `plan.md` atomically, return to `ready`, and obtain approval before implementation. Never extend a `completed` task in place.

If another tool or Skill creates files or conclusions, review and route only incorporated facts before treating them as task facts. Do not let automation skip approval, expand scope, delete history, or write secrets.

### 6. Verify and review

Enter `checking` only after implementation is complete. Verify in this order:

1. changed-file scope and Git/file archive state;
2. any conflict raised by a merge or rebase in this task: resolved as the user decided and recorded in `plan.md`;
3. every PRD acceptance criterion;
4. Spec contracts when `spec.md` exists, or the `No spec required` rationale;
5. Plan steps, deviations, rollback points, change-log entries, and follow-ups;
6. relevant evidence in `reference/`;
7. project lint, type checks, unit/integration/end-to-end tests as applicable;
8. debug code, temporary bypasses, uncovered branches, and unrelated changes.

Record each command and result in `plan.md`. Distinguish pre-existing failures, newly introduced failures, and environment failures. A test pass does not replace product acceptance.

### 7. Complete and archive

The archive transaction below is the single definition; `artifacts.md` and `versioning-and-recovery.md` reference it rather than restate it.

Run it as one command: `hooks/task complete <task-id> --user-accepted`. It checks the gates, marks the documents `completed`, and hands over to `hooks/archive`, which moves the directory and closes the Todo entry. Doing the steps by hand is what the collapse looked like — the same three gates live in `complete`, and a hand edit of two `> Status:` lines followed by `hooks/archive` used to skip all of them.

**Run it before the merge, not after.** The transaction reads the working tree and never consults the base branch, so nothing about it waits for a pull request to land. The order is: finish and verify, `hooks/task complete`, then commit the code, the documents and the archive together on the task's branch, push, and open the pull request. Archiving after the merge is the mistake to avoid, because the moved directory and the rewritten Todo entry then exist on no branch — and the only ways to land them are the two `CONTRIBUTING.md` forbids: a push to the base outside any pull request, or a second pull request carrying nothing but bookkeeping. The teardown line `complete` prints is about the **worktree**: `git worktree remove` waits for the merge, and that condition is about not deleting a directory that may still hold the only copy of something. It is not a statement about when to archive.

Before that command, confirm all acceptance criteria pass, verification is recorded, the current Task version is consistent across existing core documents, unresolved items are explicit follow-ups, and no other agent is writing core documents. What the command performs: mark the task `completed`, move the entire directory, update the linked Todo item's `Task:` path to `TaskFlowDocs/achieved/<task-id>/`, close it, then verify the active path is absent, the achieved path exists, and the achieved root PRD and Plan both say `completed`. If any part fails, record the blocker and do not claim archival completion.

**`hooks/archive` refuses an unfinished task on its own.** It requires the Plan's `## Approval` to say `approved` for its current `> Task version:` with an approver other than `pending`, no unchecked `- [ ]` item, and every Step block closed — a Step is closed when it says `- Status: done`, and nothing else counts. That last one is a whitelist, and deliberately: it used to name the three words that meant unfinished, so any word it did not know (`completed`, a misspelling, an empty value, a missing line) read as finished and archived a Plan that was not. `hooks/task progress` has only ever accepted `pending|in_progress|done|blocked`, so `done` is the one word an author can write that means closed, and the two now read the same rule from both sides. The three gates are the same ones `complete` applies, applied again where the move happens, because `archive` is also runnable by hand. All of them are checked before the directory moves, so a refusal leaves the task active, the Todo untouched, and `achieved/` without it.

**Closing the entry is part of the transaction, not a later tidying pass.** `hooks/archive` reduces the linked entry to the fields triage still needs — its heading plus `ID`, `Status`, `Goal`, `Task`, `Next action` — because a finished entry had become 78% of the file: eighty-five of them held 89 KB of the 114 KB `todo.md`. `Priority`, `Owner`, `Source`, `External`, `Added`, `Updated` and the free-form prose under any field go. A live entry keeps every field; only a closed one is reduced, and only `hooks/archive` does it, so `task next`, `task state` and `task reopen` never see a shortened entry they write to. An entry with no achieved plan.md to link — `- Task: Not promoted.`, or a `Task:` that is prose rather than a path — is left exactly as it is, because the prose has nowhere to go and cannot stay where it is: a `## Todo Record` heading at column 0 inside an entry is a new section to every hook that splits on `## `.

**The prose moves rather than disappearing.** Every non-blank line in the entry that is not a field line, plus the value on a `- Notes:` line, is appended to the achieved `plan.md` under `## Todo Record`, grouped by the field it followed, before the entry is rewritten. It is not a duplicate of the archived documents — measured over 195 sentences, 2 appear verbatim in the Plan — so it is the only copy of the analysis that produced the task, and it is carried verbatim rather than summarised. A reopened task reads its history there.

**The backfill is checked, not blind.** An entry written before the `- ID:` field existed carries its ID in the heading only, and `task get` could not reach it. `hooks/archive` adds the line when the heading starts with `TF-yyyymmdd-…` or `T-yyyymmdd-…` **and** no entry in the file already holds that ID — the old numbering ran per day-of-work and was reused, so seven of this repository's 19 heading IDs name a different entry today. A heading whose ID is taken keeps no ID line.

Treat achieved tasks as read-only in place. A later request that belongs to one must first retrieve the entire directory to the active root, record the Todo source and reopen reason, create a new Task version, and obtain approval. Stage the retrieval before reading full archives: read `old/vN/version.md` change summaries and the achieved `plan.md` first, then read a full archived document set only when the current documents or the version summary require it. Create a related task only for a new independent outcome or different owner/accountability.

After completion, promote only verified, cross-task rules into the project's shared specification/guides. Leave task-specific decisions, personal preferences, unverified ideas, and temporary workarounds in the task artifacts.

**Tear the working tree down once its work is in the base.** The task's branch has to be pushed and merged before the directory can go — `complete` runs first, so the removal is the step after the merge, not part of `complete`. The condition is two facts you can check: the branch is merged into the base branch, and the tree has nothing uncommitted (`git status --porcelain` empty). Then remove it from the base checkout:

```bash
git worktree remove <path>
git branch -d <branch>        # -d, never -D: it refuses a branch that is not merged
```

**The two commands are one step, in that order, and `-d` is the whole safety argument.** `git worktree remove` deletes the directory and never the branch — `git worktree` only owns the checkout — so stating only the removal is what let merged branches accumulate: nine on one machine by 2026-10-18, three more by 2026-11-04, and once the directory is gone nothing reported them any more. `-d` refuses an unmerged branch with `not fully merged`, so running the pair on a merged branch succeeds and on an unmerged one stops and says why; `-D` would delete exactly the branch that still holds the only copy of a commit. The order matters for the same reason: the branch is still checked out by the worktree until the first command runs, and Git refuses to delete a branch that is checked out.

Merging and archiving do not remove either for you: `.worktrees/` is ignored, so a leftover worktree costs nothing visible until the directory listing gets long. `bash hooks/repository-check .` reports two things — every worktree whose branch is already in the base with a clean tree, and every such branch with no worktree left — and both reports are informational: they do not change the check's exit code, and neither deletes anything.

Host/harness hooks may run as side effects during the flow but are bounded by [runtime.md](references/runtime.md): they never write core documents, never approve, and only update Todo triage metadata or inject derived context. Do not let a hook's presence skip the approval gate or expand scope.

Publishing, merging, deployment, or delivery processes managed by other tools are external to this framework. They may be not applicable and do not replace `completed` or `TaskFlowDocs/achieved/`.

## Sessions and collaboration

**Write the resume entry before you leave a task unfinished.** `sessions.md` is what a later session reads to pick the work up, so it is not left to a judgement about whether continuation "seems useful": if the session ends while the task is not `completed`, write the current entry's `Last completed` and `Next step` before ending it. That condition is the whole trigger, and it is checkable — the task's own phase answers it. A task that ends `completed` needs no entry; a task that ends `blocked`, `planning`, or `in_progress` does. The SessionStart hook maintains the mechanical fields of the selected task's session entry — session id, agent, availability, timestamps, directories, Task version/phase — so normally you add `Last completed`, `Next step`, and `Notes`, and you remain the only writer that closes an entry. If no hook wrote an entry — hooks are optional, and an environment without them runs the same flow — create the file from the Session outline in [artifacts.md](references/artifacts.md) and fill the entry yourself. Never treat the hook's entry as progress: `plan.md` stays authoritative for steps and verification. The file is clone-local — a session id, a working directory and `Session availability: local-only` describe the machine that wrote them — so it is never committed, and `hooks/install-git-hygiene` keeps it out of `git status` by writing a rule into the clone's own `.git/info/exclude` rather than into a tracked `.gitignore`.

Only one named owner may write `prd.md`, `spec.md`, `plan.md`, or `reference/index.md` at a time. Agents may read in parallel and produce independent research/review notes. The Primary Agent or user merges conclusions, changes Task version, records approval, and changes the phase. On handoff, the old owner updates `sessions.md` and `plan.md`; the new owner reads the current artifacts before writing. If a task has multiple agents, designate at most one `Primary` session.

## Safety and scope

- Do not delete, overwrite, commit, push, or archive user files unless the task and user authorization allow it.
- Do not put secrets, tokens, private data, or unauthorized sensitive material in any task artifact, snapshot, or patch; use redacted placeholders.
- Restore historical file versions only in a new temporary restore root; never overwrite the current task directory.
- Design documents may stay out of Git: file-mode `old/vN/` archival remains a valid recovery store. See [versioning-and-recovery.md](references/versioning-and-recovery.md).
- Host/harness hooks may update Todo triage metadata, deterministically maintain repository-document index metadata, and inject derived session-start routing/state context, but never create, rewrite, or delete core task documents or source policies, and never approve. See [runtime.md](references/runtime.md).
- Other tools are allowed to manage their own configuration and lifecycle. This skill only specifies how their task-related outputs integrate with this framework.
- A task ID is `YYYY-MM-DD-short-slug`; keep it stable after creation. Resolve same-day slug collisions with a suffix or a more specific slug. Create a new related task only at the outcome/ownership boundary defined in Existing-task-first selection.

## Supporting references

Read these only when needed:

- [artifacts.md](references/artifacts.md) for compact templates and output routing.
- [versioning-and-recovery.md](references/versioning-and-recovery.md) for Task versions, `old/`, Git/file archives, and safe restoration.
- [runtime.md](references/runtime.md) for host/harness hooks (Claude Code, Codex), single-command transitions, and `hooks/` layout.

## Verification

Before declaring a task complete, confirm:

- [ ] Required artifacts exist (`prd.md`, `plan.md`; `spec.md` when large).
- [ ] Current Task version and state are consistent.
- [ ] User approval is recorded before implementation.
- [ ] Every Step has acceptance, verification, and rollback information.
- [ ] Validation results and failure classification are in `plan.md`.
- [ ] Scope, sensitive-data, and concurrent-write checks passed.
- [ ] Completion gates passed before moving to `TaskFlowDocs/achieved/`.