This is the north star for AI coding agents working on Taskplane.
Taskplane is an experimental but production-minded pi package for:
- single-task autonomous execution (
/task) - dependency-aware parallel orchestration (
/orch*) - file-backed state, resumability, and observability
When in doubt, optimize for: determinism, recoverability, and clear operator visibility.
README.md(user-facing behavior)docs/README.md(full docs map)docs/explanation/architecture.md
extensions/taskplane/extension.ts(command surface)extensions/taskplane/discovery.ts(task discovery + deps)extensions/taskplane/waves.ts(DAG/waves/assignment)extensions/taskplane/execution.ts(lane execution)extensions/taskplane/merge.ts(merge flow)extensions/taskplane/persistence.ts+resume.ts(resume/state)extensions/taskplane/types.ts(defaults + contracts)docs/reference/commands.mddocs/reference/configuration/task-orchestrator.yaml.md
- CLI:
bin/taskplane.mjs - Dashboard:
dashboard/server.cjs,dashboard/public/* - Templates:
templates/** - Packaging:
package.json,docs/maintainers/package-layout.md
extensions/tests/*docs/maintainers/testing.md
-
File-backed execution memory is fundamental
STATUS.mdis persistent task memory..DONEis authoritative completion marker.
-
Orchestrator state must be resumable
- Persisted state in
.pi/batch-state.jsonis part of runtime contract. - Resume/abort flows depend on consistent state semantics.
- Persisted state in
-
Task execution and orchestration are separate concerns
/orch*behavior coordinates discovery/waves/lanes/worktrees/merge.
-
Templates are public scaffolding, not project-specific policy
- Keep template examples generic and safe for open-source distribution.
-
Published package boundaries matter
- Only files in
package.json#filesship. - Changes to package layout or manifest impact install/runtime behavior.
- Only files in
-
Configuration lives in
taskplane-config.json, not YAML- The canonical project config file is
.pi/taskplane-config.json(JSON, camelCase keys). - Legacy
.pi/task-runner.yamland.pi/task-orchestrator.yamlfiles may still exist but are fallback only — the JSON config takes precedence when present. - When reading or modifying configuration, always check for
taskplane-config.jsonfirst. - When documenting config changes, reference the JSON format and keys (e.g.,
taskRunner.reviewer.thinking, notreviewer:\n thinking:). - User preferences live in
~/.pi/agent/taskplane/preferences.jsonand override project config. - See
extensions/taskplane/config-loader.tsandextensions/taskplane/config-schema.tsfor the loading chain and defaults.
- The canonical project config file is
-
Read before editing
- Inspect relevant code paths + reference docs before making changes.
-
Keep behavior and docs aligned
- If command/config/format behavior changes, update docs in the same change.
-
Add or update tests for behavior changes
- Especially for discovery, waves, persistence/resume, and command parsing.
-
Run validations locally (minimum)
cd extensions && node --experimental-strip-types --experimental-test-module-mocks --no-warnings --import ./tests/loader.mjs --test tests/*.test.ts- If CLI changed:
node bin/taskplane.mjs helpandnode bin/taskplane.mjs doctor
-
Preserve compatibility intentionally
- If changing external contracts (commands, config keys, state schema), do it explicitly and document it.
-
Keep commits scoped and reviewable
- Separate docs, templates, and runtime logic where possible.
-
Prefer small, deterministic changes
- Avoid broad refactors unless required by the task.
- Never
git reset --hardwhen you have uncommitted or staged changes. Usegit stashfirst, or commit to a branch. Hard reset silently destroys work that must then be re-applied from scratch. - Never hardcode machine/user-specific paths or private environment assumptions.
- Never leak internal/planning artifacts into public docs/templates.
- Never make template content project- or language-specific.
- Never silently change command names/flags or config schema fields.
- Never break persistence/resume semantics without schema + docs + tests updates.
- Never bypass
.DONE/STATUS.mdconventions in task execution flow. - Never introduce unnecessary build/runtime complexity for dashboard or extensions.
- Never publish/release as part of routine code edits unless explicitly requested.
- Update implementation
- Update
docs/reference/commands.md - Update README command tables if needed
- Add/adjust tests
- Update defaults/types/loaders in code
- Update templates in
templates/config/ - Update config reference docs
- Add/adjust tests for parsing/defaulting
- Update parser logic carefully
- Keep backward compatibility where possible
- Update
docs/reference/task-format.mdanddocs/reference/status-format.md - Add fixtures/tests for edge cases
- Update
types.tsschema/constants as needed - Update
persistence.ts+resume.tstogether - Add regression tests for recovery paths
- Update explanation/how-to docs
- Validate with
taskplane init --dry-run(or real init in scratch repo) - Ensure generated files are generic and coherent
mainis protected and should remain releasable.- Default to short-lived topic branches from latest
main:feat/<topic>fix/<topic>docs/<topic>chore/<topic>refactor/<topic>test/<topic>
- Keep one logical change per PR.
- Sync and branch:
git switch maingit pull --ff-onlygit switch -c <type/topic>
- Implement changes + run relevant validation.
- Commit with conventional format:
type(scope): short description
- Push and open PR:
git push -u origin <branch>gh pr create --fill
- Ensure required checks pass (
ci) and conversations are resolved. - Merge and delete branch:
gh pr merge --merge --delete-branch
- Sync local after merge:
git switch main && git pull --ff-only
- Do not bypass branch protection or push directly to
mainunless explicitly instructed by the user for an urgent exception. - If merge is blocked unexpectedly, inspect:
gh pr view <n> --json mergeStateStatus,statusCheckRollupgh pr checks <n>gh api repos/HenryLach/taskplane/branches/main/protection
- GitHub release and npm publish are related but distinct:
npm publishships installable package bits.- GitHub release publishes human-facing release metadata for a tag.
- Keep them aligned: one version → one tag → one npm publish → one GitHub release.
- Ensure
mainis clean and synced; tests/smokes pass. - Update
CHANGELOG.md(MANDATORY — do NOT skip).- Add a section for the new version with date.
- List all user-facing changes since the last changelog entry.
- Group by: Breaking, New, Fixed, Docs, Internal.
- Read
git logsince the last release tag to find all changes. - This is the permanent record of what shipped. GitHub release notes are derived from this, not the other way around.
- Validate package contents:
npm pack --dry-run
- Bump version and create tag:
npm version patch(orminor/major)
- Publish package:
npm publish(ornpm publish --tag beta)
- Push commit + tags:
git push && git push --tags
- Create GitHub release for the same version tag.
- Release notes should match or summarize
CHANGELOG.md.
- Release notes should match or summarize
- Verify:
npm view taskplane versiongh release view v<version>
Pre-release checklist (verify before step 3):
-
CHANGELOG.mdupdated with all changes since last release -
Tests pass:
cd extensions && node --experimental-strip-types --experimental-test-module-mocks --no-warnings --import ./tests/loader.mjs --test tests/*.test.ts -
CLI smoke:
node bin/taskplane.mjs helpandnode bin/taskplane.mjs doctor -
No uncommitted changes on the release branch
-
Never perform publish/release actions unless the user explicitly asks.
When operating as the supervisor (during /orch execution), these tools are available:
| Tool | Usage | Description |
|---|---|---|
orch_start(target) |
target="all", area name, directory, or PROMPT.md path(s) |
Start a batch. Multiple PROMPT.md paths can be space-separated. |
orch_status() |
No params | Check batch phase, wave progress, task counts |
orch_pause() |
No params | Pause after current tasks finish |
orch_resume(force?) |
force=true for stopped/failed state |
Resume a paused batch |
orch_abort(hard?) |
hard=true for immediate kill |
Abort the running batch |
orch_retry_task(taskId) |
Task ID (e.g., "TP-003") |
Reset a failed task for re-execution |
orch_skip_task(taskId) |
Task ID | Skip a task and unblock dependents |
orch_force_merge(waveIndex?, skipFailed?) |
0-based wave index | Force merge a wave with mixed results |
orch_integrate(mode?, force?, branch?) |
mode="fast-forward"|"merge"|"pr" |
Integrate completed batch into working branch |
send_agent_message(to, content, type?) |
Agent session name | Steer a running agent |
read_agent_replies(from?) |
Agent ID or omit for all | Read replies/escalations (non-consuming) |
broadcast_message(content, type?) |
Content string | Send to all agents (all-or-none rate limit) |
read_agent_status(lane?) |
Lane number or omit for all | Read STATUS.md + telemetry for a lane |
list_active_agents() |
No params | Show all running agent sessions |
trigger_wrap_up(lane) |
Lane number | Signal a worker to finish and exit |
read_lane_logs(lane) |
Lane number | Read stderr/crash logs for a lane |
-
Run extensions locally:
pi -e extensions/task-orchestrator.ts
-
Run tests:
cd extensions && node --experimental-strip-types --experimental-test-module-mocks --no-warnings --import ./tests/loader.mjs --test tests/*.test.ts
Note: Historical task artifacts/spec snapshots may still mention Vitest commands. Those references are archival only — the active test runner is Node's native
node:test.
Prefer the option that best preserves:
- correctness (tests/contracts)
- recoverability (state + resume)
- operator clarity (status, logs, dashboard)
- minimal surprise (stable commands/config/docs)
If code and docs disagree, treat code as current behavior and update docs accordingly.
/orch*in this document is shorthand for the orchestrator command family (/orch,/orch-plan,/orch-status,/orch-pause,/orch-resume,/orch-abort,/orch-deps,/orch-sessions).- It is not a literal command to run.