Agents Local Tasks
Purpose
Define how this repo uses .agents/tasks/ as a gitignored local workspace with two complementary layers:
TODO.md — a lightweight notes and small-tasks list for quick items that do not need lifecycle tracking.
- Tracked task folders — one date-prefixed, kebab-case folder per substantial task, each carrying a
README.md whose frontmatter records status, created, updated, and (once closed) a prose outcome. Each folder lives in exactly one lifecycle subfolder — 10-new/, 20-open/, or 90-closed/ — and moves between them as the task progresses.
Treat .agents/tasks/ for task tracking and .agents/playground/ for scratch artifacts as the default paired local workspaces unless the current repo explicitly documents a different convention.
When to use this skill
- Reading or updating
.agents/tasks/TODO.md.
- Creating a tracked task folder under
.agents/tasks/10-new/<YYYY-MM-DD>-<task-name>/, or moving one between 10-new/, 20-open/, and 90-closed/.
- Setting or updating a task's frontmatter
status, updated, or outcome.
- Storing temporary working files such as
pr-description.md, notes.md, validation.md, or plan.md inside a task folder.
- Reviewing whether local task files still match the active work.
Scope boundaries
This skill owns the format and conventions of .agents/tasks/: the directory model, the
lifecycle subfolders, folder naming, TODO.md syntax, and the frontmatter fields.
tool-sp-handle-agents-local-tasks — actually working the backlog: picking the next item, doing
it, moving the folder. Read this skill for the format; invoke that one to run the loop.
ref-sp-dev-repo-conventions — where .agents/tasks/ and .agents/playground/ sit in this repo's
layout.
- Issue trackers, project boards, and anything outside
.agents/tasks/ are out of scope. This is the
local, gitignored workspace only.
Core Workflow
- Check
.agents/tasks/TODO.md for quick notes and small items, and scan 10-new/, 20-open/, and 90-closed/ for tracked task folders.
- Decide whether the item is a quick note (leave it in
TODO.md) or substantial enough to become a tracked task folder.
- For substantial work, create
.agents/tasks/10-new/<YYYY-MM-DD>-<task-name>/ with a README.md whose frontmatter sets status: (new, ready, or blocked) plus created: and updated:.
- When work begins, move the folder to
20-open/ and update status to in-progress (or in-review / blocked).
- Keep the
README.md brief current — objective, status, blockers, assumptions, and next steps — as the task changes, bumping updated in the same edit.
- When the task finishes, move the folder to
90-closed/, set status to done or cancelled, and write the prose outcome.
- For complex tasks, prepare a concise closeout answer that explains what was done, what was not done, how and why important decisions were made, validation, and any remaining caveats.
- Remove or refresh stale local files once a task is done or no longer relevant.
Directory Model
| Path |
Role |
.agents/tasks/TODO.md |
Lightweight notes and small tasks that do not need lifecycle tracking. |
.agents/tasks/10-new/<date>-<task-name>/ |
Tracked task not started yet (status: new | ready | blocked). |
.agents/tasks/20-open/<date>-<task-name>/ |
Tracked task being worked (status: in-progress | in-review | blocked). |
.agents/tasks/90-closed/<date>-<task-name>/ |
Finished tracked task (status: done | cancelled). |
.agents/tasks/<lifecycle>/<date>-<task-name>/README.md |
Living brief with frontmatter, plan, and context. |
.agents/tasks/<lifecycle>/<date>-<task-name>/pr-description.md |
Temporary draft content for a PR or summary. |
.agents/tasks/<lifecycle>/<date>-<task-name>/notes.md, validation.md, plan.md |
Scratch notes, validation results, or a focused local plan. |
.agents/playground/ |
Scratch space for temporary helper scripts or generated local artifacts that should be created with edit tools instead of terminal file-writing commands. |
Naming and ordering
The lifecycle subfolders carry a fixed-width numeric prefix — 10-new/, 20-open/, 90-closed/ —
so a plain ls shows them in lifecycle order instead of alphabetical order, which would put closed
first. The gaps leave room to insert a stage without renumbering. This is the Linux .d-directory
convention; ref-sp-dev-projects-architecture records where it comes from and why fixed width
matters. Nothing parses these numbers — they exist only to make the sort match the sequence.
Task folders are named <YYYY-MM-DD>-<task-name>/, where the date is the day the task was created
and matches the date part of created in frontmatter. The prefix sorts each subfolder
chronologically, so a stale backlog item is visible at a glance in 10-new/. Match a task by topic
with a glob (10-new/*wordpress*) rather than by typing the date.
Task Lifecycle
A tracked task is a folder that lives in exactly one lifecycle subfolder at a time. As the task progresses, move the whole folder and update the status frontmatter to a value valid for the new subfolder.
| Subfolder |
Meaning |
Valid status values |
10-new/ |
Backlog — identified but not being worked yet. |
new, ready, blocked |
20-open/ |
Active — currently being worked. |
in-progress, in-review, blocked |
90-closed/ |
Finished — no further work expected. |
done, cancelled |
Core invariant — the subfolder and the status must always agree. The subfolder is the source of truth for the lifecycle stage, and a task's status must be one of the values valid for the subfolder it currently sits in. The only allowed combinations are exactly those three rows above; any other pairing is invalid and must be corrected. Concretely:
- A folder in
10-new/ may only be new, ready, or blocked — never in-progress, in-review, done, or cancelled.
- A folder in
20-open/ may only be in-progress, in-review, or blocked — never new, ready, done, or cancelled.
- A folder in
90-closed/ may only be done or cancelled — never anything else.
- Whenever you move a folder to a new subfolder, update its
status in the same step; whenever you change a task's status, confirm it is still valid for the subfolder (and move the folder if not). Never do one without the other.
Notes:
blocked is the one status valid in two subfolders — 10-new/ and 20-open/. Keep a blocked task in whichever subfolder reflects whether work has begun: 10-new/ if it never started, 20-open/ if it was in flight. A blocked task is never moved to 90-closed/; 90-closed/ is only for done or cancelled.
new means not yet triaged/refined; ready means refined and ready to pick up.
Task README frontmatter
Each tracked task's README.md starts with YAML frontmatter:
---
status: in-progress
created: 2026-07-11T21:56:06+02:00
updated: 2026-07-25T11:11:26+02:00
---
# Task Title
Objective, plan, blockers, next steps…
A task in 90-closed/ adds a prose outcome:
---
status: done
created: 2026-07-15T21:53:15+02:00
updated: 2026-07-15T22:04:32+02:00
outcome: "Both fixes landed, but the auto-merge path was never re-verified end to end because CI
was red on an unrelated error. Closed on its fixes, not on full verification."
---
The fields:
status — the lifecycle position, which must agree with the subfolder. Multi-word values are
hyphenated (in-progress, in-review) so they need no quoting and match cleanly.
created — ISO 8601 timestamp with offset, from date -Iseconds. Its date part must match the
folder-name prefix.
updated — same format, bumped whenever the README.md is edited or the folder moves.
outcome — prose, not an enum, required once a task reaches 90-closed/. One or two sentences
saying how the task actually ended, including what was not done and why.
outcome is prose because done and cancelled already carry the machine-readable part, and the
part worth reading is the qualification — "closed on its fixes, not on full verification" is the
signal an enum destroys. Keep it to a sentence or two and leave the full reasoning in the body:
frontmatter is what a grep or head across the directory surfaces, not where a long argument
belongs. YAML has no markdown rendering and is indentation-sensitive, so anything with bullets or
multiple paragraphs belongs in the body instead.
Nothing validates these files — they are gitignored and the skill validators only cover SKILL.md.
The invariants hold only because this checklist is followed. updated is the field most likely to
drift; when it looks wrong, the filesystem is the fallback ground truth, but note that a folder's
mtime tracks child add/remove rather than content edits, so compare against the files inside it.
TODO.md Syntax
TODO.md holds quick notes and small tasks only; anything substantial becomes a tracked task folder. Unfinished items in .agents/tasks/TODO.md may use any of these forms:
- todo item description
- [] todo item description
- [ ] todo item description
Completed items should use [x]:
- [x] completed todo item description
When a helper script needs to find the next open task, treat plain bullets, empty brackets, and spaced empty brackets as open items, and skip [x] or [X] items.
Task Framing
| Command or action |
What |
Why |
When |
Expected outcome |
Update .agents/tasks/TODO.md |
Refresh the quick-notes and small-tasks list. |
TODO.md should reflect the current lightweight items that do not warrant a tracked folder. |
When a quick note or small task appears, is resolved, or should be promoted into a tracked folder. |
TODO.md matches the real state of small local work. |
Create .agents/tasks/10-new/<date>-<task-name>/ |
Open a tracked task folder in the 10-new/ backlog with status, created, and updated frontmatter. |
Substantial work needs its own lifecycle-tracked workspace separate from quick notes. |
When an item is large enough to need running notes, a brief, or lifecycle tracking. |
The task has a date-prefixed folder under 10-new/ with an initial status. |
Move a task between 10-new/, 20-open/, 90-closed/ |
Relocate the whole task folder and update its status to a value valid for the new subfolder, bumping updated. |
The subfolder and status are the source of truth for where a task is in its lifecycle. |
When work starts (10-new/→20-open/) or finishes (20-open/→90-closed/), or a task is cancelled. |
The folder location and status agree and reflect reality. |
| Triage one tracked task |
Decide whether the task can be executed directly or needs clarification first, and set status (new→ready, or blocked). |
Simple tasks should not be over-processed, while broad or underdefined tasks should not be executed on guesswork. |
When picking up a task from 10-new/. |
The next step is explicit and the status reflects readiness. |
Write a task's outcome on close |
Record in prose how the task actually ended, including what was not done and why. |
The qualification around a done is the part worth reading later; the status enum cannot carry it. |
When moving a task to 90-closed/. |
A future reader can tell what really happened without opening the body. |
Add or update the task README.md |
Keep a running summary of objective, status, blockers, and next steps, with current status frontmatter. |
Multi-step work becomes hard to recover if the local context is scattered across chat only. |
When the task has enough moving parts that a single summary file will reduce drift. |
Another pass can resume the task from the local file without reconstructing context from scratch. |
Store a temporary artifact such as pr-description.md or validation.md |
Save work product that is useful during the task but does not belong in the committed repo. |
Temporary drafts and scratch outputs should stay near the task they support. |
When you need a local draft, notes, or validation log for the active task. |
The artifact is easy to find and scoped to the right task folder. |
| Prepare a complex-task closeout answer |
Summarize done, not done, how, why, validation, and residual caveats. |
Complex tasks create context and tradeoffs that should not disappear into local notes. |
When a TODO led to feature work, significant edits, cross-skill changes, or important design/quality decisions. |
The user can understand the outcome without rereading the whole transcript or local task files. |
| Prune stale local files |
Remove or update local tracking that no longer reflects real work. |
Gitignored local notes become misleading if they outlive the task or drift from the code. |
After scope changes, task completion, or abandonment. |
.agents/tasks/ stays useful instead of becoming a graveyard of stale notes. |
Decision Rules
- Treat
.agents/tasks/ as local working state, not as committed product documentation.
- Use
.agents/tasks/ and .agents/playground/ together as the default local workspace pair unless the current repo explicitly documents a different convention.
- Keep
.agents/tasks/ gitignored and promote durable guidance elsewhere instead of relying on local notes to survive cloning or review.
- Keep quick notes and small items in
TODO.md; promote work into a tracked task folder once it is substantial enough to need lifecycle tracking or a running brief.
- Place a new tracked task folder in
10-new/, move it to 20-open/ when work starts, and to 90-closed/ when it is done or cancelled; always move the whole folder, never copy it into two subfolders.
- Keep the lifecycle subfolder and the
status frontmatter consistent: 10-new/ → new/ready/blocked, 20-open/ → in-progress/in-review/blocked, 90-closed/ → done/cancelled.
- Use
blocked in 10-new/ when a not-yet-started task is blocked, and in 20-open/ when an in-flight task is blocked; do not move a task to 90-closed/ just because it is blocked.
- Bump
updated in the same edit that changes the README.md or moves the folder, exactly as status is kept in step with the subfolder.
- Write
outcome as prose when closing a task, and say plainly what was left undone rather than rounding a partial result up to done.
- If a task is simple and well-defined, execute it directly instead of forcing a planning ritual first.
- Treat mundane chores such as creating a branch, running a simple command, or applying a narrow typo fix as simple unless they reveal broader decisions or blockers.
- Treat feature development, broad refactors, multi-file skill or workflow changes, cross-repo updates, and tasks with meaningful tradeoffs as complex.
- If a task is broad, ambiguous, or underdefined, ask the missing questions first and treat that clarification as part of the task rather than guessing; keep its
status: new until it is refined to ready.
- If a task needs refinement before implementation, create the
README.md and capture the clarified goal, assumptions, and subtasks there before starting execution.
- If the work still cannot be executed cleanly after initial clarification, run an interactive breakdown with the user and record the resulting subtasks in the task
README.md.
- If a task relies on an incorrect assumption, state the problem calmly, explain the misunderstanding, and correct it with the user before proceeding.
- When a complex task is completed or blocked, the user-facing answer should state what was done, what was not done, how the work was approached, why notable decisions were made, what validation ran, and what caveats or next steps remain.
- Do not inflate simple tasks with a long closeout. A short status and validation note is enough when there were no meaningful decisions or residual risks.
- Prefer task- or PR-style, kebab-case folder names behind the date prefix, such as
.agents/tasks/10-new/2026-07-25-add-button-for-language/.
- When a temporary helper script or generated scratch file is needed, put it under
.agents/playground/ and create or edit it with the edit tools rather than shell heredocs, redirection, or inline terminal-generated files.
- Every tracked task folder should carry a
README.md with status frontmatter so its lifecycle state is explicit; quick items that stay in TODO.md do not need one.
- If a local note becomes durable repo guidance, promote it into a committed doc, skill, or code comment instead of leaving it only under
.agents/tasks/.
- Do not overwrite unrelated task folders when the active task changes; keep local notes scoped to the task they belong to.
Gotchas
.agents/tasks/ is normally gitignored, so other collaborators and future clones will not see it unless the content is promoted elsewhere.
- Local tracking can drift from the code if it is not updated after scope changes.
- A task's lifecycle subfolder and its
status frontmatter can drift apart if the folder is moved without updating status, or vice versa; keep them in sync.
- A temporary draft under
.agents/tasks/ is not a substitute for updating the actual repo source of truth when the information becomes permanent.
- Broad task text is not authorization to improvise missing requirements; refine it first when the scope is unclear.
- A broken premise in a task should be corrected, not silently worked around.
Example Next-Todo Readers
Use examples like these as temporary helpers under .agents/playground/ when manual scanning is noisy. Keep them simple and delete them when they are no longer useful.
from pathlib import Path
import re
TODO_PATH = Path(".agents/tasks/TODO.md")
DONE_LINE = re.compile(r"^-\s*\[[xX]\]\s+")
OPEN_LINE = re.compile(r"^-\s*(?:\[\s*\]\s*)?(?P<text>\S.*)$")
def find_next_todo(todo_path: Path) -> tuple[int, str] | None:
for line_number, line in enumerate(
todo_path.read_text(encoding="utf-8").splitlines(), start=1
):
if DONE_LINE.match(line):
continue
match = OPEN_LINE.match(line)
text = match.group("text").strip() if match else ""
if text:
return line_number, text
return None
def main() -> None:
todo_item = find_next_todo(TODO_PATH)
if todo_item is None:
print("No open todos found.")
return
line_number, text = todo_item
print(f"{TODO_PATH}:{line_number}: {text}")
if __name__ == "__main__":
main()
import { readFileSync } from "node:fs";
type TodoItem = {
lineNumber: number;
text: string;
};
const todoPath = ".agents/tasks/TODO.md";
const doneLine = /^-\s*\[[xX]\]\s+/;
const openLine = /^-\s*(?:\[\s*\]\s*)?(?<text>\S.*)$/;
const findNextTodo = (content: string): TodoItem | null => {
const lines = content.split(/\r?\n/);
for (const [index, line] of lines.entries()) {
if (doneLine.test(line)) {
continue;
}
const match = openLine.exec(line);
const text = match?.groups?.text?.trim();
if (text) {
return { lineNumber: index + 1, text };
}
}
return null;
};
const main = (): void => {
const todoItem = findNextTodo(readFileSync(todoPath, "utf8"));
if (!todoItem) {
console.log("No open todos found.");
return;
}
console.log(`${todoPath}:${todoItem.lineNumber}: ${todoItem.text}`);
};
main();
Validation
- Any helper or workflow that scans
.agents/tasks/TODO.md recognizes plain bullets, [], and [ ] as open items, and skips [x] or [X] items.
- Every tracked task folder under
10-new/, 20-open/, or 90-closed/ has a README.md with a status frontmatter value valid for its subfolder, plus created and updated.
- No tracked task folder is in a subfolder whose lifecycle contradicts its
status (e.g. 90-closed/ with status: in-progress, or 10-new/ with status: done).
- Every folder name is
<YYYY-MM-DD>-<task-name>, and the date matches the date part of created.
- Every task in
90-closed/ has a prose outcome that names what was not done, not only what was.
- After a major shift in scope, confirm that the active task folder's location,
status, and README.md still describe the same task you are actually performing.
- Before concluding a task, check whether any durable guidance discovered in local notes should be moved into committed repo files.
- Before concluding a complex task, confirm the user-facing answer explains done, not done, how, why, validation, and remaining caveats at the level the task deserves.
1---2name: ref-sp-agents-local-tasks3description: Reference guidance for using `.agents/tasks/` as a gitignored local workspace: a lightweight `TODO.md` notes list plus date-prefixed tracked task folders that move through the `10-new/`, `20-open/`, and `90-closed/` lifecycle subfolders, each carrying `status`, `created`, `updated`, and (once closed) a prose `outcome` in frontmatter. Use when: reading or updating `.agents/tasks/TODO.md`, creating or moving a tracked task folder between `10-new/`, `20-open/`, and `90-closed/`, setting a task's frontmatter `status` or `outcome`, naming a task folder, or checking whether local agent task notes still match the active work.4license: MIT5---67# Agents Local Tasks89## Purpose1011Define how this repo uses `.agents/tasks/` as a gitignored local workspace with two complementary layers:1213- **`TODO.md`** — a lightweight notes and small-tasks list for quick items that do not need lifecycle tracking.14- **Tracked task folders** — one date-prefixed, kebab-case folder per substantial task, each carrying a `README.md` whose frontmatter records `status`, `created`, `updated`, and (once closed) a prose `outcome`. Each folder lives in exactly one lifecycle subfolder — `10-new/`, `20-open/`, or `90-closed/` — and moves between them as the task progresses.1516Treat `.agents/tasks/` for task tracking and `.agents/playground/` for scratch artifacts as the default paired local workspaces unless the current repo explicitly documents a different convention.1718## When to use this skill1920- Reading or updating `.agents/tasks/TODO.md`.21- Creating a tracked task folder under `.agents/tasks/10-new/<YYYY-MM-DD>-<task-name>/`, or moving one between `10-new/`, `20-open/`, and `90-closed/`.22- Setting or updating a task's frontmatter `status`, `updated`, or `outcome`.23- Storing temporary working files such as `pr-description.md`, `notes.md`, `validation.md`, or `plan.md` inside a task folder.24- Reviewing whether local task files still match the active work.2526## Scope boundaries2728This skill owns the **format and conventions** of `.agents/tasks/`: the directory model, the29lifecycle subfolders, folder naming, `TODO.md` syntax, and the frontmatter fields.3031- `tool-sp-handle-agents-local-tasks` — actually working the backlog: picking the next item, doing32 it, moving the folder. Read this skill for the format; invoke that one to run the loop.33- `ref-sp-dev-repo-conventions` — where `.agents/tasks/` and `.agents/playground/` sit in this repo's34 layout.35- Issue trackers, project boards, and anything outside `.agents/tasks/` are out of scope. This is the36 local, gitignored workspace only.3738## Core Workflow39401. Check `.agents/tasks/TODO.md` for quick notes and small items, and scan `10-new/`, `20-open/`, and `90-closed/` for tracked task folders.412. Decide whether the item is a quick note (leave it in `TODO.md`) or substantial enough to become a tracked task folder.423. For substantial work, create `.agents/tasks/10-new/<YYYY-MM-DD>-<task-name>/` with a `README.md` whose frontmatter sets `status:` (`new`, `ready`, or `blocked`) plus `created:` and `updated:`.434. When work begins, move the folder to `20-open/` and update `status` to `in-progress` (or `in-review` / `blocked`).445. Keep the `README.md` brief current — objective, status, blockers, assumptions, and next steps — as the task changes, bumping `updated` in the same edit.456. When the task finishes, move the folder to `90-closed/`, set `status` to `done` or `cancelled`, and write the prose `outcome`.467. For complex tasks, prepare a concise closeout answer that explains what was done, what was not done, how and why important decisions were made, validation, and any remaining caveats.478. Remove or refresh stale local files once a task is done or no longer relevant.4849## Directory Model5051| Path | Role |52| --- | --- |53| `.agents/tasks/TODO.md` | Lightweight notes and small tasks that do not need lifecycle tracking. |54| `.agents/tasks/10-new/<date>-<task-name>/` | Tracked task not started yet (`status: new \| ready \| blocked`). |55| `.agents/tasks/20-open/<date>-<task-name>/` | Tracked task being worked (`status: in-progress \| in-review \| blocked`). |56| `.agents/tasks/90-closed/<date>-<task-name>/` | Finished tracked task (`status: done \| cancelled`). |57| `.agents/tasks/<lifecycle>/<date>-<task-name>/README.md` | Living brief with frontmatter, plan, and context. |58| `.agents/tasks/<lifecycle>/<date>-<task-name>/pr-description.md` | Temporary draft content for a PR or summary. |59| `.agents/tasks/<lifecycle>/<date>-<task-name>/notes.md`, `validation.md`, `plan.md` | Scratch notes, validation results, or a focused local plan. |60| `.agents/playground/` | Scratch space for temporary helper scripts or generated local artifacts that should be created with edit tools instead of terminal file-writing commands. |6162### Naming and ordering6364The lifecycle subfolders carry a fixed-width numeric prefix — `10-new/`, `20-open/`, `90-closed/` —65so a plain `ls` shows them in lifecycle order instead of alphabetical order, which would put `closed`66first. The gaps leave room to insert a stage without renumbering. This is the Linux `.d`-directory67convention; `ref-sp-dev-projects-architecture` records where it comes from and why fixed width68matters. Nothing parses these numbers — they exist only to make the sort match the sequence.6970Task folders are named `<YYYY-MM-DD>-<task-name>/`, where the date is the day the task was created71and matches the date part of `created` in frontmatter. The prefix sorts each subfolder72chronologically, so a stale backlog item is visible at a glance in `10-new/`. Match a task by topic73with a glob (`10-new/*wordpress*`) rather than by typing the date.7475## Task Lifecycle7677A tracked task is a folder that lives in exactly one lifecycle subfolder at a time. As the task progresses, **move the whole folder** and update the `status` frontmatter to a value valid for the new subfolder.7879| Subfolder | Meaning | Valid `status` values |80| --- | --- | --- |81| `10-new/` | Backlog — identified but not being worked yet. | `new`, `ready`, `blocked` |82| `20-open/` | Active — currently being worked. | `in-progress`, `in-review`, `blocked` |83| `90-closed/` | Finished — no further work expected. | `done`, `cancelled` |8485**Core invariant — the subfolder and the `status` must always agree.** The subfolder is the source of truth for the lifecycle stage, and a task's `status` must be one of the values valid for the subfolder it currently sits in. The only allowed combinations are exactly those three rows above; any other pairing is invalid and must be corrected. Concretely:8687- A folder in `10-new/` may only be `new`, `ready`, or `blocked` — never `in-progress`, `in-review`, `done`, or `cancelled`.88- A folder in `20-open/` may only be `in-progress`, `in-review`, or `blocked` — never `new`, `ready`, `done`, or `cancelled`.89- A folder in `90-closed/` may only be `done` or `cancelled` — never anything else.90- Whenever you move a folder to a new subfolder, update its `status` in the same step; whenever you change a task's `status`, confirm it is still valid for the subfolder (and move the folder if not). Never do one without the other.9192Notes:9394- `blocked` is the one status valid in **two** subfolders — `10-new/` and `20-open/`. Keep a blocked task in whichever subfolder reflects whether work has begun: `10-new/` if it never started, `20-open/` if it was in flight. A blocked task is never moved to `90-closed/`; `90-closed/` is only for `done` or `cancelled`.95- `new` means not yet triaged/refined; `ready` means refined and ready to pick up.9697### Task README frontmatter9899Each tracked task's `README.md` starts with YAML frontmatter:100101```markdown102---103status: in-progress104created: 2026-07-11T21:56:06+02:00105updated: 2026-07-25T11:11:26+02:00106---107108# Task Title109110Objective, plan, blockers, next steps…111```112113A task in `90-closed/` adds a prose `outcome`:114115```markdown116---117status: done118created: 2026-07-15T21:53:15+02:00119updated: 2026-07-15T22:04:32+02:00120outcome: "Both fixes landed, but the auto-merge path was never re-verified end to end because CI121 was red on an unrelated error. Closed on its fixes, not on full verification."122---123```124125The fields:126127- `status` — the lifecycle position, which must agree with the subfolder. Multi-word values are128 hyphenated (`in-progress`, `in-review`) so they need no quoting and match cleanly.129- `created` — ISO 8601 timestamp with offset, from `date -Iseconds`. Its date part must match the130 folder-name prefix.131- `updated` — same format, bumped whenever the `README.md` is edited or the folder moves.132- `outcome` — **prose, not an enum**, required once a task reaches `90-closed/`. One or two sentences133 saying how the task actually ended, including what was *not* done and why.134135`outcome` is prose because `done` and `cancelled` already carry the machine-readable part, and the136part worth reading is the qualification — "closed on its fixes, not on full verification" is the137signal an enum destroys. Keep it to a sentence or two and leave the full reasoning in the body:138frontmatter is what a `grep` or `head` across the directory surfaces, not where a long argument139belongs. YAML has no markdown rendering and is indentation-sensitive, so anything with bullets or140multiple paragraphs belongs in the body instead.141142Nothing validates these files — they are gitignored and the skill validators only cover `SKILL.md`.143The invariants hold only because this checklist is followed. `updated` is the field most likely to144drift; when it looks wrong, the filesystem is the fallback ground truth, but note that a folder's145`mtime` tracks child add/remove rather than content edits, so compare against the files inside it.146147## TODO.md Syntax148149`TODO.md` holds quick notes and small tasks only; anything substantial becomes a tracked task folder. Unfinished items in `.agents/tasks/TODO.md` may use any of these forms:150151```markdown152- todo item description153- [] todo item description154- [ ] todo item description155```156157Completed items should use `[x]`:158159```markdown160- [x] completed todo item description161```162163When a helper script needs to find the next open task, treat plain bullets, empty brackets, and spaced empty brackets as open items, and skip `[x]` or `[X]` items.164165## Task Framing166167| Command or action | What | Why | When | Expected outcome |168| --- | --- | --- | --- | --- |169| Update `.agents/tasks/TODO.md` | Refresh the quick-notes and small-tasks list. | `TODO.md` should reflect the current lightweight items that do not warrant a tracked folder. | When a quick note or small task appears, is resolved, or should be promoted into a tracked folder. | `TODO.md` matches the real state of small local work. |170| Create `.agents/tasks/10-new/<date>-<task-name>/` | Open a tracked task folder in the `10-new/` backlog with `status`, `created`, and `updated` frontmatter. | Substantial work needs its own lifecycle-tracked workspace separate from quick notes. | When an item is large enough to need running notes, a brief, or lifecycle tracking. | The task has a date-prefixed folder under `10-new/` with an initial `status`. |171| Move a task between `10-new/`, `20-open/`, `90-closed/` | Relocate the whole task folder and update its `status` to a value valid for the new subfolder, bumping `updated`. | The subfolder and `status` are the source of truth for where a task is in its lifecycle. | When work starts (`10-new/`→`20-open/`) or finishes (`20-open/`→`90-closed/`), or a task is cancelled. | The folder location and `status` agree and reflect reality. |172| Triage one tracked task | Decide whether the task can be executed directly or needs clarification first, and set `status` (`new`→`ready`, or `blocked`). | Simple tasks should not be over-processed, while broad or underdefined tasks should not be executed on guesswork. | When picking up a task from `10-new/`. | The next step is explicit and the `status` reflects readiness. |173| Write a task's `outcome` on close | Record in prose how the task actually ended, including what was not done and why. | The qualification around a `done` is the part worth reading later; the status enum cannot carry it. | When moving a task to `90-closed/`. | A future reader can tell what really happened without opening the body. |174| Add or update the task `README.md` | Keep a running summary of objective, status, blockers, and next steps, with current `status` frontmatter. | Multi-step work becomes hard to recover if the local context is scattered across chat only. | When the task has enough moving parts that a single summary file will reduce drift. | Another pass can resume the task from the local file without reconstructing context from scratch. |175| Store a temporary artifact such as `pr-description.md` or `validation.md` | Save work product that is useful during the task but does not belong in the committed repo. | Temporary drafts and scratch outputs should stay near the task they support. | When you need a local draft, notes, or validation log for the active task. | The artifact is easy to find and scoped to the right task folder. |176| Prepare a complex-task closeout answer | Summarize done, not done, how, why, validation, and residual caveats. | Complex tasks create context and tradeoffs that should not disappear into local notes. | When a TODO led to feature work, significant edits, cross-skill changes, or important design/quality decisions. | The user can understand the outcome without rereading the whole transcript or local task files. |177| Prune stale local files | Remove or update local tracking that no longer reflects real work. | Gitignored local notes become misleading if they outlive the task or drift from the code. | After scope changes, task completion, or abandonment. | `.agents/tasks/` stays useful instead of becoming a graveyard of stale notes. |178179## Decision Rules180181- Treat `.agents/tasks/` as local working state, not as committed product documentation.182- Use `.agents/tasks/` and `.agents/playground/` together as the default local workspace pair unless the current repo explicitly documents a different convention.183- Keep `.agents/tasks/` gitignored and promote durable guidance elsewhere instead of relying on local notes to survive cloning or review.184- Keep quick notes and small items in `TODO.md`; promote work into a tracked task folder once it is substantial enough to need lifecycle tracking or a running brief.185- Place a new tracked task folder in `10-new/`, move it to `20-open/` when work starts, and to `90-closed/` when it is done or cancelled; always move the whole folder, never copy it into two subfolders.186- Keep the lifecycle subfolder and the `status` frontmatter consistent: `10-new/` → `new`/`ready`/`blocked`, `20-open/` → `in-progress`/`in-review`/`blocked`, `90-closed/` → `done`/`cancelled`.187- Use `blocked` in `10-new/` when a not-yet-started task is blocked, and in `20-open/` when an in-flight task is blocked; do not move a task to `90-closed/` just because it is blocked.188- Bump `updated` in the same edit that changes the `README.md` or moves the folder, exactly as `status` is kept in step with the subfolder.189- Write `outcome` as prose when closing a task, and say plainly what was left undone rather than rounding a partial result up to `done`.190- If a task is simple and well-defined, execute it directly instead of forcing a planning ritual first.191- Treat mundane chores such as creating a branch, running a simple command, or applying a narrow typo fix as simple unless they reveal broader decisions or blockers.192- Treat feature development, broad refactors, multi-file skill or workflow changes, cross-repo updates, and tasks with meaningful tradeoffs as complex.193- If a task is broad, ambiguous, or underdefined, ask the missing questions first and treat that clarification as part of the task rather than guessing; keep its `status: new` until it is refined to `ready`.194- If a task needs refinement before implementation, create the `README.md` and capture the clarified goal, assumptions, and subtasks there before starting execution.195- If the work still cannot be executed cleanly after initial clarification, run an interactive breakdown with the user and record the resulting subtasks in the task `README.md`.196- If a task relies on an incorrect assumption, state the problem calmly, explain the misunderstanding, and correct it with the user before proceeding.197- When a complex task is completed or blocked, the user-facing answer should state what was done, what was not done, how the work was approached, why notable decisions were made, what validation ran, and what caveats or next steps remain.198- Do not inflate simple tasks with a long closeout. A short status and validation note is enough when there were no meaningful decisions or residual risks.199- Prefer task- or PR-style, kebab-case folder names behind the date prefix, such as `.agents/tasks/10-new/2026-07-25-add-button-for-language/`.200- When a temporary helper script or generated scratch file is needed, put it under `.agents/playground/` and create or edit it with the edit tools rather than shell heredocs, redirection, or inline terminal-generated files.201- Every tracked task folder should carry a `README.md` with `status` frontmatter so its lifecycle state is explicit; quick items that stay in `TODO.md` do not need one.202- If a local note becomes durable repo guidance, promote it into a committed doc, skill, or code comment instead of leaving it only under `.agents/tasks/`.203- Do not overwrite unrelated task folders when the active task changes; keep local notes scoped to the task they belong to.204205## Gotchas206207- `.agents/tasks/` is normally gitignored, so other collaborators and future clones will not see it unless the content is promoted elsewhere.208- Local tracking can drift from the code if it is not updated after scope changes.209- A task's lifecycle subfolder and its `status` frontmatter can drift apart if the folder is moved without updating `status`, or vice versa; keep them in sync.210- A temporary draft under `.agents/tasks/` is not a substitute for updating the actual repo source of truth when the information becomes permanent.211- Broad task text is not authorization to improvise missing requirements; refine it first when the scope is unclear.212- A broken premise in a task should be corrected, not silently worked around.213214## Example Next-Todo Readers215216Use examples like these as temporary helpers under `.agents/playground/` when manual scanning is noisy. Keep them simple and delete them when they are no longer useful.217218```python219from pathlib import Path220import re221222223TODO_PATH = Path(".agents/tasks/TODO.md")224DONE_LINE = re.compile(r"^-\s*\[[xX]\]\s+")225OPEN_LINE = re.compile(r"^-\s*(?:\[\s*\]\s*)?(?P<text>\S.*)$")226227228def find_next_todo(todo_path: Path) -> tuple[int, str] | None:229 for line_number, line in enumerate(230 todo_path.read_text(encoding="utf-8").splitlines(), start=1231 ):232 if DONE_LINE.match(line):233 continue234235 match = OPEN_LINE.match(line)236 text = match.group("text").strip() if match else ""237 if text:238 return line_number, text239240 return None241242243def main() -> None:244 todo_item = find_next_todo(TODO_PATH)245 if todo_item is None:246 print("No open todos found.")247 return248249 line_number, text = todo_item250 print(f"{TODO_PATH}:{line_number}: {text}")251252253if __name__ == "__main__":254 main()255```256257```typescript258import { readFileSync } from "node:fs";259260type TodoItem = {261 lineNumber: number;262 text: string;263};264265const todoPath = ".agents/tasks/TODO.md";266const doneLine = /^-\s*\[[xX]\]\s+/;267const openLine = /^-\s*(?:\[\s*\]\s*)?(?<text>\S.*)$/;268269const findNextTodo = (content: string): TodoItem | null => {270 const lines = content.split(/\r?\n/);271272 for (const [index, line] of lines.entries()) {273 if (doneLine.test(line)) {274 continue;275 }276277 const match = openLine.exec(line);278 const text = match?.groups?.text?.trim();279 if (text) {280 return { lineNumber: index + 1, text };281 }282 }283284 return null;285};286287const main = (): void => {288 const todoItem = findNextTodo(readFileSync(todoPath, "utf8"));289 if (!todoItem) {290 console.log("No open todos found.");291 return;292 }293294 console.log(`${todoPath}:${todoItem.lineNumber}: ${todoItem.text}`);295};296297main();298```299300## Validation301302- Any helper or workflow that scans `.agents/tasks/TODO.md` recognizes plain bullets, `[]`, and `[ ]` as open items, and skips `[x]` or `[X]` items.303- Every tracked task folder under `10-new/`, `20-open/`, or `90-closed/` has a `README.md` with a `status` frontmatter value valid for its subfolder, plus `created` and `updated`.304- No tracked task folder is in a subfolder whose lifecycle contradicts its `status` (e.g. `90-closed/` with `status: in-progress`, or `10-new/` with `status: done`).305- Every folder name is `<YYYY-MM-DD>-<task-name>`, and the date matches the date part of `created`.306- Every task in `90-closed/` has a prose `outcome` that names what was not done, not only what was.307- After a major shift in scope, confirm that the active task folder's location, `status`, and `README.md` still describe the same task you are actually performing.308- Before concluding a task, check whether any durable guidance discovered in local notes should be moved into committed repo files.309- Before concluding a complex task, confirm the user-facing answer explains done, not done, how, why, validation, and remaining caveats at the level the task deserves.