Skip to content

Task-list Field Discipline

RETIRED (S491): Archived as low-read/stale. Ledger field discipline is now enforced mechanically by scripts/ledger-cli.ts soft-warn budgets (lib/validation/ledger-budgets.ts) and operationalised in the canonical repo update-ledgers skill. Retained for historical context (§-numbered sections still cited by older material).

Status: Authoritative. Authored: kh-prod-readiness-S267 (ID-34). Scope: The workflow ledgers — docs/reference/task-list.json, product-backlog.json, and the SERVER-managed initiatives.json (writes via ServerIntent through the task-view patch-server, DR-073/074) — with task-list.json as the primary surface. product-roadmap.json no longer exists (repurposed server-side into initiatives.json, ID-148.8; see §0 below).

Purpose: Define how to write each human-writable ledger field — what shape of content belongs where, and which limits are machine-checked. This complements taskmaster-schema-reference.md (which defines what the fields are) and the enforced constraints in lib/validation/task-list-schema.ts.

This doc is the canonical reference cited by workflow-orchestration, write-product-spec, write-tech-spec, and planning-and-task-breakdown, and the discipline the ID-35 ledger CLI surfaces warnings against at write time.


0. Which ledger: Task List vs Backlog vs Roadmap (item classification)

Section titled “0. Which ledger: Task List vs Backlog vs Roadmap (item classification)”

§1 below governs where prose goes. This section governs which ledger an item belongs in — a distinct axis, and a recurring source of mis-filing (S300: concrete defects discovered during active work were filed to the backlog when they were already committed work).

The test is commitment, not size:

  • Task List (task-list.json) — committed work: anything we have decided will be done. This includes defects/regressions discovered during active work, scoped fixes on a committed path (e.g. the critical path), and planned features. A discovered defect goes straight to the Task List — a new Task (ID-N), or a Subtask (ID-N.M) if it is in-scope of an open Task. It is not parked in the backlog first.
  • Backlog (product-backlog.json) — uncommitted candidates: ideas, nice-to-haves, and improvements that still need a product / prioritisation decision before they would be worked. The backlog is the “should we?” queue; the Task List is the “we will” queue. An item leaves the backlog only when that decision is made (promote → Task).
  • Roadmap (product-roadmap.json) — RETIRED (ID-148.8/DR-073/074): the file no longer exists. Strategic/cross-cutting groupings now live in the SERVER-managed initiatives.json (initiatives → sub-initiatives → projects; only projects carry linked_tasks/linked_backlog, DR-074) — writes route via ServerIntent through the task-view patch-server, not this doc’s ledger-CLI write discipline. There is currently no designed procedure for classifying a NEW strategic finding onto that ledger (flagged for the owner, ID-148.11) — treat “strategic themes” as unclassifiable pending that design, not as a live third option alongside Task List / Backlog.

One-line test: Have we committed to doing this? Yes → Task List (new Task or Subtask). Not yet — it needs a decision to be worked at all → Backlog.

This refines triage-finding Branch C: “tactical → backlog” applies only to uncommitted candidates. A committed tactical defect (e.g. a bug blocking the critical path) routes to a new Task, not the backlog. (The existing top-of-tree rule already bars backlogging CI-red regressions; this generalises it: committed work is Task-List work.)


1. The one rule: canonical reference vs traceability

Section titled “1. The one rule: canonical reference vs traceability”

Every piece of text an author wants to record passes one test — the “would-it-survive-the-task” test:

Content that remains true and useful after the Task closes — design rationale, architecture decisions, the “why” behind an approach, API contracts, schema definitions, REJECTED-alternatives analysis — is canonical reference. It belongs in docs/specs/<feature>/{PRODUCT,TECH}.md, docs/research/, or docs/reference/. The task-list field carries a cross_doc_links pointer to it, not a copy.

Content specific to executing or tracking this Task — what to build next, which files a Subtask owns, the one-line acceptance the Checker gates against, the session-by-session record of what happened — is traceability. It belongs in the task-list, in the field whose shape matches (§2).

Documentation is the canonical reference; the task-list shows implementation/test steps + traceability context only.


FieldShapeBudget (advisory)Load-bearing forLimit class
Task.titleShort noun phrase~30–60 charsHuman scan + cross-ref labeldoc-only
Task.descriptionOne paragraph: compact what + why. No design rationale, no migration narrative, no REJECTED-alternatives prose — those go to docs/specs/… + a cross_doc_links pointer. Updated only on scope amendment.≤ 1500 charsCross-doc cross-reference targetsoft-warn
Task.status_noteShort rationale for the current status (blocked: waiting on X; S267: prioritised for …). Acute carryover only; bump on status flip.≤ 300 charsStatus-line contextsoft-warn
Task.priority_noteOne-line rationale for the MoSCoW/Ranked priority.~≤ 300 charsPriority justificationdoc-only
Subtask.titleShort noun phrase~40–80 charsDispatch labeldoc-only
Subtask.descriptionOne sentence summarising the Subtask. Not a copy of details.≤ 250 charsSubtask scan labelsoft-warn
Subtask.detailsMulti-line markdown: the dispatch-brief slice and the append-only <info added on …> journal (commits, test counts, OQ ratifications, Checker verdicts, Curator decisions). THE canonical home for session-by-session narrative.no limitPer-Subtask traceability + journalnone
Subtask.testStrategyOne-line acceptance criterion the Checker verifies against. Not a multi-criterion test plan.≤ 300 chars, single assertionChecker contractsoft-warn
BacklogItem.titleShort noun-phrase heading (the backlog item’s H1-equivalent). Same prose class as Subtask.title. Optional; added by ID-35 ({35.14}) and backfilled across the live backlog ({35.23}).≤ 80 charsBacklog scan label + mirror headingsoft-warn
cross_doc_links[]{path (repo-relative), anchor, raw} per DocLinkSchema. The pointer to canonical reference.Doc-graph traversalZod-enforced (shape)
Task.session_refs[] / commit_refs[]Bare session ids / short commit SHAs.Provenancedoc-only
document_purpose (root)One-paragraph purpose of the ledger.Doc headerdoc-only

When in doubt about which field carries narrative content, the answer is the Subtask details journal block. Its length is intentionally uncapped — capping the journal would defeat its purpose.


  • soft-warn — surfaced by parseTaskListWithWarnings() (lib/validation/task-list-schema.ts) as a non-fatal TaskListWarning, alongside the existing 25-Subtask-ceiling warning. TaskListSchema.parse() is not affected — over-budget records still parse. The ID-35 ledger CLI prints these warnings to stderr on every mutating command, so drift surfaces to the operator at write time without hard-failing.

    Updated (ID-35 v2 — {35.17}): the soft-warn budget is now ALSO a hard-reject at write time. Before any byte is written, the changed record’s budgeted field is checked against lib/validation/ledger-budgets.ts and an over-budget write is refused (budget-exceeded, exit 1, nothing written) unless --force is passed — which downgrades it back to the soft warning and writes anyway. So a soft-warn field is warn-on-parse but reject-on-write: the schema still parses the live (over-budget) ledger, but a new over-budget record will not be AUTHORED without the explicit escape hatch. Separately, every write is also gated by the record-set-preservation check ({35.16}): a write that would silently drop or duplicate a record is rejected (record-set-violation, exit 1, nothing written).

    Updated (ID-90.22 — enforcement point moved server-side): the enforcement point for both gates (and serialisation + mirror regen) is now the task-view patch-server substrate, not the CLI. As of ID-90.22 the ledger CLI (scripts/ledger-cli.ts) is server-unconditional: it is the operator surface (argv, envelopes, exit codes — all unchanged, invariant 8) and routes every mutation to the substrate, which is where the budget gate, the record-set gate, atomic serialisation and .md mirror regen actually fire (invariant 57 — enforcement point = substrate/server; façade = operator surface). The thresholds, the --force escape hatch and the reject behaviour described above are identical — only WHERE the check runs moved. The previous scoped-vs-whole-file write-path distinction is now a no-op: the substrate emits the same minimal-diff bytes regardless.

  • doc-only — a human convention enforced by Planner/Checker review and the skill bodies. Not mechanically detectable.

  • Zod-enforced (shape) — the field’s structure (not its length) is rejected at parse time by the schema.

There are no hard length caps (z.string().max(N)) on any text field — a hard cap would reject the live (over-budget) ledger and diverge the vendored lib/validation/task-list-schema.ts from task-view’s source schema (watched by task-view-vendor-drift.yml). The soft-warning pattern mirrors the established 25-Subtask soft ceiling.


Bad — rationale inlined into description (drift):

ID-28 description (9590 chars) carries the full Cocoindex flow-scaffolding design narrative + Cloud Run sidecar dependency analysis. ID-29 description (8203 chars) carries the Option A/B/C migration trade-off analysis. This rationale survives the Task and belongs in docs/specs/cocoindex-*/ — the description should be a one-paragraph what+why with a cross_doc_links pointer to the spec.

Bad — session narrative in status_note:

A status_note accumulating “S264 did X, S265 hit Y, re-ran Z” is using a status field as a journal. The current-status assertion stays in status_note (≤300); the session-by-session record moves to the relevant Subtask details <info added on …> block.

Good — pointer, not copy:

ID-35 description references docs/research/id-35-crossover-audit.md and the spec chain rather than inlining the patch-primitive audit. The heavy material lives in docs/; the description summarises and points.

Good — one-line testStrategy:

"RESEARCH.md ≥ 600 lines covering primitive inventory + reuse audit + ≥5 OQs" — a single assertion the Checker gates against, not a paragraph of sub-criteria.


The discipline is forward-looking; existing over-budget records are tightened by the ID-34 {34.8} retroactive sweep (lowest-priority, parent-sequenced because 4 cmux terminals share task-list.json). The sweep is relocate-not-delete: rationale moves to a docs/ artefact with a cross_doc_links pointer back; narrative moves into the appropriate Subtask details journal. No fact is lost. Policy: docs/specs/id-34-task-list-discipline/PRODUCT.md §4.


  • taskmaster-schema-reference.md — empirical field shapes (the what).
  • lib/validation/task-list-schema.ts — enforced constraints + parseTaskListWithWarnings.
  • .claude/skills/workflow-orchestration/SKILL.md §Ledger field-discipline — the Orchestrator-facing summary table.
  • docs/specs/id-34-task-list-discipline/ — the ID-34 spec chain (RESEARCH/PRODUCT/TECH/PLAN).