CLI Command Contract
Taskledger uses a task-first command grammar:
taskledger [--root PATH] [--json] <area> <verb> [RESOURCE_REF] [--task TASK_REF] [options]
Global Options
--root PATHselects the workspace root.--jsonis root-level only and must appear before the command group.Command-local
--jsonoptions are not part of the public contract.
--cwd was removed in v0.7.0; use --root to select the workspace root.
Task Scoping
Task-scoped workflow commands default to the active task. Use
--task TASK_REF when explicitly targeting another task.
taskledger plan start
taskledger plan start --task task-0001
taskledger implement resume --task task-0001 --reason "Reacquire implementation lock."
taskledger implement restart --task task-0001 --summary "Fix validation findings."
taskledger implement finish --task task-0001 --summary "Implemented."
taskledger implement snapshot refresh --task task-0001 --reason "Accept current workspace as the implementation snapshot."
taskledger review record --task task-0001 --result pass --summary "No blocking issues."
taskledger validate status --task task-0001
Task-resource commands accept the task as their direct positional resource:
taskledger task show task-0001
taskledger task cancel task-0001 --reason "Duplicate"
taskledger task archive task-0001 --reason "Hide historical task"
taskledger task unarchive task-0001 --reason "Restore task"
taskledger task report task-0001
taskledger task show tl:task-0001
taskledger task show tl-task-0001
Reference parsing helpers are available:
taskledger ref show task-0001
taskledger ref parse TL-TASK-0001
Fresh-session and monitoring commands are top-level read surfaces:
taskledger usage [TASK_REF] [--task TASK_REF] [-q]
taskledger --json usage
taskledger monitor [TASK_REF] [--task TASK_REF] [--refresh-seconds 2] [--once] [--max-events 10] [--max-ready 10] [--plain] [--no-clear]
Optional positional task refs are not supported for workflow commands.
Plan guidance command
taskledger plan guidance is a read-only planning helper command that always
prints built-in plan-input guidance. When a project prompt profile is configured
it appends project-local advisory guidance:
taskledger plan guidance [--task TASK_REF] [--format markdown|json]
Rules:
defaults to the active task when
--taskis omitted;--formataccepts onlymarkdownorjson;when a planning run is active, it records a one-time guidance-view marker for that run and appends a
plan.guidance.viewedevent;root
--jsoncontinues to return the standard CLI success/error envelope;has_project_guidanceindicates whether a project prompt profile exists, not whether any guidance is available. Built-in guidance is always returned.
The command payload shape is:
kindtask_idhas_project_guidanceguidanceprofilequestion_policy
Plan revision commands
taskledger plan export renders an editable plan draft outside durable
storage, and taskledger plan amend applies structured plan-review edits:
taskledger plan export [--task TASK_REF] [--version latest|N] [--file PATH] [--overwrite] [--stdout]
taskledger plan amend [--task TASK_REF] [--drop-criterion CRITERION_ID ...] [--drop-todo TODO_ID ...] [--remove-file PATH ...] --reason "..."
taskledger plan upsert [--task TASK_REF] [--file PATH] [--auto-revise]
Plan revision preparation should happen before submitting a revision, so export or check failures do not leave an active planning run:
taskledger plan export --version latest --file ./plan.revision.md
# edit ./plan.revision.md
taskledger plan check --file ./plan.revision.md
taskledger plan upsert --auto-revise --file ./plan.revision.md
When an edited ./plan.md already exists, check and submit it directly with
plan upsert --auto-revise --file ./plan.md; do not export over it. Auto-revision
proposes a version only. Explicit user approval is still required before
implementation.
Plan proposal commands that accept --file reject file paths under
.taskledger/ because that directory is private durable ledger state.
Plan check command
taskledger plan check validates editable plan input without creating,
revising, proposing, accepting, locking, or releasing anything:
taskledger plan check [--task TASK_REF] [--file PATH] [--strict]
Rules:
--filedefaults toplan.mdwhen omitted;--strictupgrades unknown-field warnings to errors and fails on any warning;task context is optional;
task_idappears in the payload when resolvable;JSON uses the root
--jsonoption:taskledger --json plan check --file ./plan.md
Payload shape:
kind(plan_input_check)task_idpassedstrictsummary({errors, warnings})issuesparsed
Plan schema command
taskledger plan schema prints the editable plan input schema and one valid
example:
taskledger plan schema
Payload shape:
kind(plan_input_schema)schema
Plan review command
taskledger plan review is a read-only approval-facing plan renderer:
taskledger plan review [--task TASK_REF] [--version N] [--format markdown|json] [-o PATH]
Rules:
defaults to the active task when
--taskis omitted;defaults to the latest proposed plan in
plan_reviewstage when--versionis omitted;renders Markdown by default and can emit JSON-formatted content with
--format json;when
-o/--outputis provided, writes rendered content to a file path.
Taskledger stores task-local work state and opaque links. Cross-ledger semantics belong to an organizer such as ledgerdeck.
Relevant commands for external artifact references:
taskledger link add --url specs/behavior/features/checkout/payment.feature --label "behavior spec"
taskledger file link specs/behavior/features/checkout/payment.feature --kind doc --label "behavior spec"
taskledger validate check --criterion ac-0001 --status pass --evidence "pytest tests/test_checkout_payment.py::test_payment_flow"
Rules:
Links are opaque. Taskledger does not parse or interpret linked files.
Validation evidence is recorded through generic
validate check.validate command -- ...records managed validation command evidence during an active validation run.A non-zero validation command does not create a
ValidationCheck; explicitly classify and record criteria withvalidate check.A passing implementation command may be adopted explicitly as validation evidence with
validate check --from-implementation-check CHECK_IDonly when Taskledger reports an exact final/current workspace snapshot match.This is evidence reuse, not a generic command cache. Rerun validation when fresh execution or external runtime state matters.
Archive import lock policy
Archive imports support explicit lock handling:
taskledger import ./taskledger-transfer.tar.gz --replace [--lock-policy drop|quarantine|keep]
taskledger import ./taskledger-task-<project>-<ledger>-task-0040-<ts>.tar.gz [--id-policy preserve|renumber-on-conflict|fail-on-conflict]
The default is quarantine so imported source-machine runtime locks are not
restored as active lock.yaml files. keep is diagnostic-only behavior
for full-fidelity lock restoration.
Transfer archive manifest contract
Transfer archives include both machine identity and human-readable metadata:
manifest.project.name and manifest.project.slug are display metadata,
while manifest.project.uuid remains the safety identity.
{
"project": {
"uuid": "<project_uuid>",
"name": "<project_name>",
"slug": "<project_slug>",
"ledger_ref": "<ledger_ref>"
}
}
Import compatibility is backward-safe: older archives that only contain
project.uuid and project.ledger_ref remain valid. UUID comparison is
still authoritative for import safety.
taskledger import --dry-run must not mutate taskledger state for either
archive or JSON payload imports.
Export task selection
Taskledger export supports full-ledger and task-scoped archives:
taskledger export
taskledger export ./backup.tar.gz
taskledger export --task task-0040
taskledger export task-0040
taskledger export task-0040 -o ./task0040.tar.gz
Positional Resource Refs
Positional refs are reserved for the direct resource being changed or shown:
taskledger task create TITLE [options]
taskledger task record TITLE [options]
taskledger task activate TASK_REF
taskledger task follow-up PARENT_REF TITLE [options]
taskledger todo done TODO_ID --task TASK_REF --evidence "pytest -q"
taskledger question answer QUESTION_ID --task TASK_REF --text "Yes."
taskledger handoff show HANDOFF_ID --task TASK_REF
taskledger require add REQUIRED_TASK_REF --task TASK_REF
taskledger release show 0.4.1
Release commands
Release boundaries are durable project records, not task lifecycle states:
taskledger release tag 0.4.1 --at-task task-0030 --note "0.4.1 released"
taskledger release list
taskledger release show 0.4.1
release tag writes a durable release record under the current ledger’s
releases/ directory. Release boundaries must point to done tasks.
Taskledger does not provide changelog entry, changelog context, or
docs/changelog.md build commands; those belong to the separate releaseledger
tool. Load both skills when cross-ledger release notes need task context.
Legacy branch-scoped ledger commands (migration only)
In legacy projects without a canonical manifest, branch-scoped ledgers isolate
ignored local task state by the checked-in
ledger_ref stored in taskledger.toml:
taskledger ledger status
taskledger ledger list
taskledger ledger fork feature-a
taskledger ledger switch main
taskledger ledger adopt --from feature-a task-0030
taskledger ledger doctor
ledger fork creates a new local namespace under
.taskledger/ledgers/<ref>/ and updates only Taskledger-owned ledger keys in
taskledger.toml. ledger switch changes the checked-in pointer to an
existing local ledger. ledger adopt copies a task from another local ledger
into the current ledger and renumbers on collision.
Storage and sync helper commands
Taskledger also exposes local storage discovery and sync helpers:
taskledger storage where
taskledger storage move --to ../taskledger-state/project-a --mode copy|move [--adopt-existing] [--force]
taskledger sync preflight
taskledger sync status
taskledger sync commit --message "Sync project-a taskledger state"
taskledger export --output ./taskledger-transfer.tar.gz
taskledger import ./taskledger-transfer.tar.gz --dry-run
taskledger sync git status
taskledger sync git init --repo ../taskledger-state --project-path project-a
taskledger sync git commit --message "Sync project-a taskledger state"
cd "$(taskledger sync git cd)"
git pull --ff-only
git push
taskledger sync git hooks install
taskledger sync git hooks status
taskledger sync git hooks uninstall
Rules:
storage whereis read-only and reports the resolved workspace root, config path,taskledger_dir, project identity, ledger ref, Git detection, and active lock count.In legacy projects,
storage moveupdatestaskledger.tomlatomically after the target has been copied or explicitly adopted.sync preflightperforms only local checks. It must not perform network push/pull operations.sync statusandsync commitoperate only on the Git repository that contains the resolvedtaskledger_dir.exportandimportare root-level archive transfer commands;syncremains focused on storage and Git synchronization.sync gitcommands operate on a private external Git repository that stores full project taskledger state under<repo>/<project_path>.
Config commands
Project config inspection and edits are available under config:
taskledger config list
taskledger config show
taskledger config keys
taskledger config get prompt_profiles.planning.max_required_questions
taskledger config describe prompt_profiles.planning.plan_body_detail
taskledger config set prompt_profiles.planning.max_required_questions 3
taskledger config set prompt_profiles.planning.question_policy always_before_plan
Rules:
dotted keys target nested TOML tables (for example
prompt_profiles.planning.max_required_questions);config keyslists available key names and path patterns;config describeprovides key semantics, allowed values, defaults, and whether a key is explicitly set;config setaccepts TOML literals (numbers, booleans, arrays, inline tables); when TOML parsing fails, the value is treated as a plain string;invalid values are rejected using standard LaunchError JSON/human envelopes.
next-action result contract
taskledger next-action is the preferred fresh-context entrypoint for agents
and operators. It should identify the next concrete question, todo, criterion,
plan, dependency, or repair target instead of only naming a lifecycle bucket.
Human output should stay concise but actionable:
todo-work: Implementation is in progress; 1 todos remain.
Next todo: todo-0001 -- Update next-action JSON payload.
Command: taskledger todo show todo-0001
Worker step: tester
Worker context: taskledger pipeline context tester
Worker handoff: taskledger handoff create --worker tester --summary "..."
Mark todo done after evidence exists: taskledger todo done todo-0001 --evidence "..."
Progress: 0/1 todos done
JSON output preserves the existing fields:
kindtask_idstatus_stageactive_stageactionreasonblockingnext_command
and may also include:
next_itemfor the concrete targetcommandsfor ordered command hints with one primary commandprogressfor question, todo, or validation queuesworker_pipelinewhen an enabledguidedworker pipeline has a pending step; this object includesenabled,mode,next_step,context_command, andhandoff_commandtemplate_commandplusrequired_plan_fieldsandrecommended_plan_fieldswhen the next step is regenerating a plan from answered questionsguidance_commandwhen planning guidance should be reviewed before drafting or regenerating a plan
Agents should inspect next_item, prefer next_command when it is safe,
avoid inventing question answers, and never mark todos done without evidence.
When a task is in failed_validation, next-action should direct agents
back to implementation with taskledger implement restart --summary SUMMARY.
When a task persists planning, implementing, or validating as its
status but active_stage is missing, next-action must not report
The task is cancelled. For an orphaned implementation with a still-running
latest implementation run and no active lock, it should direct agents to
taskledger implement resume --task TASK_REF --reason "...".
For an implemented task whose validation is blocked by IMPLEMENTATION_SNAPSHOT_MISMATCH,
next-action must point to validate-reconcile and the audited recovery command
taskledger implement snapshot refresh --reason "...", not to implement restart unless
the task is actually in failed_validation.
For an approved task with a non-implementation run still marked running,
next-action must not direct agents to taskledger implement start.
It should report a repair-oriented action and point to taskledger doctor.
Truly cancelled tasks recover through
taskledger task uncancel --task TASK_REF --reason "..."
Compact mutation output
Mutation commands emit compact acknowledgements instead of full task or run records. This reduces LLM context consumption during implementation loops.
The following commands produce compact output:
todo add: emitstodo_addedresult with new todo, progress, and next command.todo done/todo undone: emitstodo_updateresult with todo id, status, progress, and next command. Successfultodo donerenews the active implementation lease only when the current execution proves ownership. Read-only commands and other sessions do not renew it.implement finish: emitstask_lifecycleresult with task id, run id, status, and next command.
Human mode shows a one-line summary:
added todo-0001 on task-0001 (0/3 done)
done todo-0001 on task-0001 (1/3 done)
finished implementation run-0001 task task-0001 -> implemented
JSON mode wraps the compact result in the standard success envelope with result_type.
For full task, run, or todo details after a mutation, use:
taskledger task showortaskledger statusfor task-level detail.taskledger todo show TODO_IDfor individual todo detail.taskledger next-actionfor the next concrete step.taskledger todo nextfor the next open todo.
to a durable non-active stage rather than directly re-entering an active stage.
Run and lock repair
A missing canonical task record can leave the active-task pointer and runtime lock in place. Forced deactivation clears only the dangling pointer. It does not silently remove the lock:
taskledger task deactivate --force --reason "Clear dangling active task after record loss."
taskledger repair locks
taskledger repair locks --apply --reason "Preserve and remove the orphaned runtime lock."
repair locks is dry-run by default. It reports orphan_missing_task separately from expired and dead-process locks, copies the orphan lock to the recovery audit area, removes the runtime lock, and updates derived lock indexes. Inspect the dry-run before applying.
Doctor also reports nonempty task allocation directories that lack task.md. Allocation repair is dry-run by default, and applying requires an explicit --task-id or deliberate --all scope, the reviewed plan fingerprint, and a reason. Review physical source identity separately from any display alias:
taskledger repair allocations
taskledger repair allocations --task-id task-0019
taskledger repair allocations --task-id task-0019 --apply --plan-id PLAN_ID --reason "Quarantine the reviewed physical source."
taskledger repair allocations --audit
The dry-run result includes top-level apply_safe, plan_id, and next_command,
plus incomplete_allocations entries containing physical_source, source_kind,
legacy_source_id, source_fingerprint, repair_mode, per-entry apply_safe,
collision_findings, surviving_identity, planned_quarantine, and nullable
planned_tombstone. Modes are quarantine_and_tombstone for an eligible orphan,
quarantine_shadowed_legacy_source for one stale legacy source with exactly one live
UUID owner, and blocked_identity_conflict for ambiguity. A shadowed-source repair
preserves the existing live owner and must not create a second tombstone. When any
selected entry is blocked, top-level apply_safe is false and next_command is null;
resolve the ownership ambiguity instead of applying the plan.
Prior repairs with a misattributed tombstone can be reconciled only when event and quarantine provenance support the physical source. The dry-run is also the required review step:
taskledger repair allocations --reconcile-source-id task-0019 --tombstone-id task-0037
taskledger repair allocations --reconcile-source-id task-0019 --tombstone-id task-0037 --apply --plan-id PLAN_ID --reason "Correct the tombstone to the physical source ID."
Reconciliation preserves the old tombstone and quarantine payload and records an audit event. Do not delete either by hand. Use taskledger repair allocations --audit to inspect prior repair provenance.
repair relation backfills a known relationship UUID for one UUID task bundle or requirement sidecar. It is dry-run by default; apply only the exact reviewed plan:
taskledger repair relation --task-uuid TASK_UUID --field parent_task_uuid
taskledger repair relation --task-uuid TASK_UUID --field parent_task_uuid --apply --plan-id PLAN_ID --reason "Backfill the reviewed parent UUID."
Maintenance garbage collection
taskledger maintenance gc is an explicit maintenance operation and is dry-run by default:
taskledger maintenance gc
taskledger maintenance gc --scope artifacts --task task-0042 --older-than 30d
taskledger maintenance gc --apply --scope runtime --older-than 14d --reason "Prune retained terminal snapshots."
Scopes are all, runtime, artifacts, and cache. Default retention is 14 days for terminal workspace snapshots, 30 days for unreferenced artifacts, and 7 days for quarantined cache generations. --older-than overrides the selected scopes. --task limits runtime/artifact cleanup to one canonical task ID and cannot be used with cache cleanup.
Artifact cleanup marks references from canonical task, run, todo, check, review, handoff, event, and agent-log records. Only old unreferenced artifacts owned by terminal, unlocked work are eligible. Runtime cleanup targets detailed manifests for terminal runs whose canonical summary hashes remain. Cache cleanup removes only old quarantined index generations, never the active indexes. Evidence/runtime deletion requires both --apply and --reason; every apply writes a durable report and attempts a project-level audit event. Canonical task history is never a GC target, and task completion does not run GC.
Managed command wrappers
plan command and implement command mirror the inner command exit code by
default. Both wrappers pass the argument vector after -- to the child without a
shell. They execute the child from the CLI invocation directory, or the explicit
--root directory, even when Taskledger discovers an ancestor workspace root for
ledger state, artifacts, and logs.
Managed command artifacts are bounded by the project artifact_max_bytes setting, defaulting to the 20,000,000-byte hard ceiling. Oversized persisted evidence is marked and retains both its beginning and end; only the durable artifact is truncated, not the child command’s exit code or CLI stdout/stderr contract.
validate command uses the same managed execution behavior during an active validation run, but records command evidence only. It never automatically maps a non-zero child exit to a criterion result.
Managed commands preserve the caller environment, but resolve child executable lookup
deterministically. A usable inherited VIRTUAL_ENV takes precedence. Otherwise
Taskledger checks <command-cwd>/.venv, <command-cwd>/venv, then the workspace
root’s .venv and venv, in that order. A candidate must contain pyvenv.cfg and
a platform-appropriate Python executable. For an auto-detected environment, only
the child environment is changed: its scripts directory is prepended to PATH,
VIRTUAL_ENV is set, and inherited PYTHONHOME is removed. If no candidate is
valid, the inherited environment is used unchanged. PYTHONPATH is preserved.
This does not rewrite argv, invoke a shell, change the parent environment, or
activate project environments for Taskledger’s internal subprocesses. Portable
commands such as python -m pytest, pytest, ruff, and mypy remain valid.
Captured stdout and stderr are included in the command result. Human mode emits
those streams before the recorded-command summary, while JSON mode keeps them only
inside the single JSON result envelope. The result and managed-shell log also record
the child cwd. --allow-failure changes only the wrapper exit code; the recorded
child exit code and failed check remain unchanged.
Use --allow-failure when you intentionally want to record a non-zero inner
exit code while returning wrapper exit code 0:
taskledger plan command -- pytest tests/ -q
taskledger plan command --allow-failure -- pytest tests/ -q
taskledger implement command -- ruff check --config=.ruff.toml .
taskledger implement command --allow-failure -- python -c "raise SystemExit(7)"
taskledger validate command -- pytest tests/ -q
taskledger validate command --allow-failure -- python -c "raise SystemExit(7)"
Transcript review modes
task transcript defaults to review mode, which groups wrapper +
managed-shell pairs, highlights failures and wrapper/managed mismatches, and
flags late lifecycle commands. Raw per-record audit table is available with
--raw.
taskledger task transcript --task TASK_REF
taskledger task transcript --task TASK_REF --raw
taskledger task transcript --task TASK_REF --failures
--review is the default (no flag needed). --raw shows every record
without collapsing. --failures renders only failed command rows and retry
detection. --raw, --review, and --failures are mutually exclusive.
task export writes a Markdown file with a deterministic body combining a curated
archive report, raw task-bundle record files, and optional source-file snapshots.
It is the recommended command for handing a task to an LLM/coding agent.
taskledger task export TASK_REF -o task.llm.md
taskledger task export --task TASK_REF --no-source-files -o task.records.md
taskledger --json task export TASK_REF -o task.llm.md
taskledger doctor and taskledger doctor locks report running runs without
matching active locks. Orphaned running planning runs can be finished only
through an explicit repair command with a reason:
taskledger repair run --task TASK_REF --run RUN_ID --reason "Planning was already completed."
The repair command refuses to finish non-planning runs, non-running runs, or runs that still have a matching active lock.
Post-completion follow-up deltas
taskledger task follow-up PARENT_REF TITLE is the supported path for small
post-completion changes. It requires a done parent task, creates a new draft
child task with parent_task_id and parent_relation=follow_up, and keeps
the parent task terminal.
Human monitoring UI
taskledger usage is the compact fresh-session startup command:
taskledger usage [TASK_REF] [--task TASK_REF] [-q]
taskledger --json usage
Rules:
it is read-only and must not claim handoffs, repair locks, or mutate task state;
root
--jsonreturns the standard CLI envelope withresult.kind == "usage";it summarizes actor, harness, active work, inbox items, and ready tasks;
agents should continue to use
next-action,todo next, and other JSON commands as the canonical same-session automation interface.
taskledger monitor is the dependency-free human-oriented terminal monitor:
taskledger monitor [TASK_REF] [--task TASK_REF] [--refresh-seconds 2] [--once] [--max-events 10] [--max-ready 10] [--plain] [--no-clear]
Rules:
it is read-only and never mutates
.taskledger/state;root
--jsonprints a singlemonitor_snapshotpayload and exits;non-JSON mode refreshes on a timer until interrupted;
--plaindisables styling and--no-clearappends snapshots instead of clearing the terminal;it replaces the removed server/TUI surface; agents should keep using JSON commands for automation.
Focused context and handoff options
Code review commands
review stores optional durable code-review evidence without adding a new
lifecycle stage. Review evidence may be recorded before validation or after a
task has reached done; storing the review remains append-only and does not
reopen the completed task:
taskledger review record [--task TASK_REF] --result pass|fail|blocked (--summary TEXT | --summary-file PATH) [--from-git] [--commit COMMIT] [--worker STEP_ID] [--handoff HANDOFF_ID] [--run RUN_ID]
taskledger review list [--task TASK_REF]
taskledger review show REVIEW_REF [--task TASK_REF]
JSON mode returns a stable payload with kind = "code_review_recorded" for
review record and includes review_id, task_id, result,
source, implementation_run, worker_step_id, and compact git
metadata fields when present.
When a user explicitly asks an agent for a review, the agent should persist
the final review with taskledger review record before answering. A
chat-only review is not durable task evidence. Post-completion review
records are append-only and do not reopen the task.
Focused worker contexts keep lifecycle mode separate from worker-role
--for:
taskledger context --for planner|implementer|validator|spec-reviewer|code-reviewer|reviewer|full [--scope task|todo|run] [--todo TODO_ID] [--run RUN_ID] [--format markdown|json|text] [--task TASK_REF]
taskledger handoff create --mode planning|implementation|validation|review|full [--for planner|implementer|validator|spec-reviewer|code-reviewer|reviewer|full] [--scope task|todo|run] [--todo TODO_ID] [--run RUN_ID] [--task TASK_REF]
taskledger handoff create --worker STEP_ID [--scope task|todo|run] [--todo TODO_ID] [--run RUN_ID] [--task TASK_REF]
taskledger pipeline context STEP_ID [--scope task|todo|run] [--todo TODO_ID] [--run RUN_ID] [--format markdown|json|text] [--task TASK_REF]
taskledger handoff show HANDOFF_ID --format text|markdown|json [--task TASK_REF]
Rules:
--todoimplies--scope todo.--runimplies--scope run.--scope todorequires--todo.--scope runrequires--run.--foraccepts the role names shown above;specandcodenormalize tospec-reviewerandcode-reviewer.handoff create --workerderives mode and context from the configured worker step and storesworker_step_idin the handoff record.pipeline context STEP_IDis equivalent tocontext --worker STEP_ID.spec-reviewerandcode-reviewerworker contexts require--runor explicit--scope taskwhen they are not bound to a validation/review run.handoff show --format markdownprints the stored snapshot body.
Removed Pre-Release Aliases
These aliases are intentionally not registered:
task newtask clear-activeimplement add-changevalidate add-checkfile unlinklink linklink unlink
Use task create, task deactivate, implement change,
validate check, file add, file remove, link add, and
link remove instead.
Approval escape hatches
Plan approval escape hatches require --reason to prevent silent bypass:
Approval also requires --note for user approval. Agent approval additionally
requires --allow-agent-approval --reason "...".
Todo source inference
When todo add is called without an explicit --source, the source is
inferred from the active lock:
Active lock stage |
Inferred source |
|---|---|
|
|
|
|
No active lock |
|
Plan-materialized todos always use source=plan.
Storage Compatibility
Taskledger stores canonical project configuration in schema-3 .ledger/ledger.toml
and Taskledger config in .ledger/taskledger/config.toml. Legacy
taskledger.toml and .taskledger.toml remain readable for explicit migration.
The default data mount is persistent external storage at ../ledger; indexes
is cache storage. A local .ledger/ledger.local.toml may select user-data.
Commands keep --root scoped to the source workspace, not the storage root.
Taskledger uses:
storage layout version 6 in the UUID-scoped data root’s
storage.yamlschema-2 canonical ledger state
per-record
schema_versionper-record
object_typeper-file
file_versionfor durable Markdown/YAML/JSON record files
Storage layout history is maintained by migration receipts. The current layout keeps
branch-scoped ledgers under <data-root>/ledgers/<ledger_ref>/.
Within each ledger, canonical task bundles live at
tasks/<uuidv7>/task.md. UUIDv7 is the stable storage identity and relationship
key; task-#### remains the derived user-facing alias and is never a directory
name. Layout 5 to 6 migration deterministically converts legacy numeric task
bundles before the first mutation, preserves ordinal gaps and reserved identities,
and is recoverable. Read-only commands do not migrate.
Other legacy storage-root or topology migrations remain explicit:
taskledger storage validate
taskledger migrate plan
taskledger migrate apply
After migration to layout 6, verify health with:
taskledger doctor
taskledger ledger doctor
Checkout-scoped indexes under the resolved cache mount are optional derived caches or registries. Read-only commands continue to work from canonical Markdown/YAML records and do not initialize a missing cache. Before a canonical mutation, Taskledger initializes a missing or empty cache binding and rebuilds the derived indexes. A non-empty cache without its binding marker is atomically quarantined beside the cache and rebuilt from canonical records. Conflicting or invalid markers, symlinks, and non-directory cache paths are not adopted automatically. The remaining derived caches may be plain JSON arrays with no version metadata and can be rebuilt explicitly with:
taskledger repair index
taskledger repair index uses the same recovery path and reports any quarantine
location. The indexes mount is fixed to cache storage, so
taskledger storage set indexes cache is an idempotent topology request;
non-cache indexes storage is rejected directly.
A newer storage version than the installed taskledger supports is rejected with a clear error.
Lock recovery contract
Lock diagnostics are exposed through three surfaces:
taskledger lock show --task TASKreturns adiagnosticsobject and a structured human block. Theclassificationfield names the lock state:none,expired,active_dead_local_process,active_live_local_process,active_unverifiable_remote_or_unknown_process,active_no_pid,active_current_execution,active_harness_session,active_same_actor, oractive_other_actor.active_current_executionrequires matching strong execution evidence, such as a shared harness session ID or a stable same-host owner PID; actor-name equality alone is not ownership proof.taskledger --json next-actionreturnslock_statuswhenever a lock exists, and setsaction=repair-lockwith a diagnostics blocker when the active implementation lock has a dead local holder PID.taskledger implement resume --repair-expired-lockreturns aLOCK_CONFLICTerror (exit code 4) with diagnostics when a non-expired lock belongs to another or unknown execution. If the selected run is already active andclassificationisactive_current_execution, resume succeeds as a no-op withchanged=false, preserving the existing lock and run IDs without a repair or release event. For ordinary continuation, inspectnext-actionand continue the todo loop; do not useimplement resumeor lock repair while this execution owns the lock.--repair-expired-lockis not a general stale-lock takeover flag. It only applies to locks whoseexpires_atis in the past. For non-expired active locks, follow the classification returned bylock showornext-action.
For non-expired active locks classified as active_dead_local_process, the
canonical recovery sequence is:
taskledger repair lock --task TASK --reason "Holder PID ... is no longer running."
taskledger implement resume --task TASK --reason "Reacquire implementation lock after stale holder repair."
For active_live_local_process or active_other_actor, do not repair;
use a handoff or wait for the holder to release. For
active_unverifiable_remote_or_unknown_process, do not infer staleness
from local process checks; inspect handoffs or ask the user before repairing.
Layout and migration commands
taskledger config path reports the project-located Taskledger configuration.
taskledger storage path data|runtime|logs|indexes reports named resolved mounts.
Use storage validate, storage set, and storage clear-override for schema-3
storage selection. storage set changes topology only; use the explicit
migration commands for data relocation. Legacy layout conversion remains explicit
through migrate status, migrate plan, and migrate apply.
Migration inspection and apply share these options:
--sibling-ledger-root PATH
--source-data-root PATH
--source-checkout-id ID
--project-uuid UUID
The canonical project UUID is selected when a legacy Taskledger UUID differs. The
legacy UUID is retained as source metadata. --source-data-root is the recovery
override for a specific data root. --source-checkout-id accepts an identifier,
not a filesystem path. Backups are automatic. Other ledger registrations are
preserved, sources are not retired by default, and authoritative split-brain
targets are refused without mutation. --create-sibling-store only initializes
the sibling root marker; it does not repair target metadata.