Markdown Do All Tasks
Use the markdown-tasks skill for script path rules and task semantics. Use this workflow only when live edits are permitted; leave plan mode before starting the loop.
Keep the Leader Focused
The leader coordinates the loop and does not implement tasks. It may only:
- Extract work with
task_get.py. - Survey blocked work with
task_unblock.py --dry-run. - Record a failed attempt with
task_mark.py --marker='!' --reason='<what failed>'. - Spawn and wait for one fresh subagent at a time.
- Inspect Git status and commit boundaries.
- Run the test gate against
HEAD. - Archive the task list with
task_archive.py.
The leader must not read .llm/todo.md directly, read task-referenced source files, or edit implementation files. Each worker discovers and reads its own implementation context.
Report Blocked Work Before the Loop
Blocked [!] tasks left by an earlier run are invisible to task_get.py, so open the run by surveying them:
python <plugin-root>/scripts/task_unblock.py .llm --dry-run
The dry run rewrites nothing. It reports the blocked count per file, so .llm/todo.md shows the blocked tasks this run will skip and the archives show blocked work still waiting for recovery.
Report those counts to the user before spawning the first worker, not after the loop finishes, where they scroll away under the run's output. Blocked tasks in .llm/todo.md are skipped rather than retried, so state the count and continue. Recovering them is the user's decision, not something the loop makes on its own; point them at the markdown-unblock-tasks skill and move on.
Process One Task per Worker
Extract the first incomplete task:
python <plugin-root>/scripts/task_get.py .llm/todo.md
If no task is returned, proceed to archiving. Otherwise:
- Report the task being started.
- Record the current
HEADcommit. - Spawn one fresh subagent for only the extracted task. Give it the task block and direct it to follow
markdown-do-one-task; do not combine tasks or add unrelated work. - Require the worker to implement only that task, run the finish workflow, leave exactly one new task commit, and mark the task complete with
task_mark.pyonly after validation succeeds. - Wait for the worker before starting another task. Never run workers concurrently because they share the first incomplete task and Git worktree.
Handle the Worker Result
After the worker returns:
Require a clean worktree. Stop and report if the worker left staged or unstaged changes.
On success, verify that
HEADadvanced by exactly one commit and thattask_get.pyno longer returns the completed task.On failure, verify that
HEADdid not advance, then mark the first incomplete task blocked so the loop can continue:python <plugin-root>/scripts/task_mark.py .llm/todo.md --marker='!' --reason='<what failed>'--reasonis required here and is recorded in the task body, so it is the only record of the failure that survives this session. Quote the concrete failure the worker reported — the failing command, the assertion, the missing dependency — not a restatement of the task. The script rejects a blocked mark with no reason.If the worker made commits before failing or the task state is ambiguous, stop instead of marking or stacking more work.
Blocked [!] tasks are skipped by task_get.py, so each failed task is attempted once and cannot create an infinite loop.
Gate the Next Task on HEAD
Before extracting another task, run the repository's precommit test against the committed HEAD:
git test run HEAD --retest --verbose --verbose
Also check git test results HEAD when available. Continue only when the command succeeds and the recorded result is good. Stop if the result is bad or unknown; never stack another task on an unverified commit.
Repeat extraction, delegation, result handling, and the HEAD gate until no incomplete tasks remain.
Archive the Finished List
When task_get.py returns no result, every task is completed [x] or blocked [!]. Archive the list:
python <plugin-root>/scripts/task_archive.py .llm/todo.md
Archiving carries blocked [!] tasks forward into a fresh .llm/todo.md instead of filing them away, and reports how many it carried. Report the archive path and that carried-forward count alongside the blocked tasks seen during this run. Do not archive early when user-supplied stopping instructions leave incomplete [ ] tasks.