Task-list Field Discipline
Task-list Field Discipline
Section titled “Task-list Field Discipline”RETIRED (S491): Archived as low-read/stale. Ledger field discipline is now enforced mechanically by
scripts/ledger-cli.tssoft-warn budgets (lib/validation/ledger-budgets.ts) and operationalised in the canonical repoupdate-ledgersskill. 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-managedinitiatives.json(initiatives → sub-initiatives → projects; only projects carrylinked_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/, ordocs/reference/. The task-list field carries across_doc_linkspointer 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.
2. Per-field discipline
Section titled “2. Per-field discipline”| Field | Shape | Budget (advisory) | Load-bearing for | Limit class |
|---|---|---|---|---|
Task.title | Short noun phrase | ~30–60 chars | Human scan + cross-ref label | doc-only |
Task.description | One 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 chars | Cross-doc cross-reference target | soft-warn |
Task.status_note | Short rationale for the current status (blocked: waiting on X; S267: prioritised for …). Acute carryover only; bump on status flip. | ≤ 300 chars | Status-line context | soft-warn |
Task.priority_note | One-line rationale for the MoSCoW/Ranked priority. | ~≤ 300 chars | Priority justification | doc-only |
Subtask.title | Short noun phrase | ~40–80 chars | Dispatch label | doc-only |
Subtask.description | One sentence summarising the Subtask. Not a copy of details. | ≤ 250 chars | Subtask scan label | soft-warn |
Subtask.details | Multi-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 limit | Per-Subtask traceability + journal | none |
Subtask.testStrategy | One-line acceptance criterion the Checker verifies against. Not a multi-criterion test plan. | ≤ 300 chars, single assertion | Checker contract | soft-warn |
BacklogItem.title | Short 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 chars | Backlog scan label + mirror heading | soft-warn |
cross_doc_links[] | {path (repo-relative), anchor, raw} per DocLinkSchema. The pointer to canonical reference. | — | Doc-graph traversal | Zod-enforced (shape) |
Task.session_refs[] / commit_refs[] | Bare session ids / short commit SHAs. | — | Provenance | doc-only |
document_purpose (root) | One-paragraph purpose of the ledger. | — | Doc header | doc-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.
3. Limit classes
Section titled “3. Limit classes”-
soft-warn — surfaced by
parseTaskListWithWarnings()(lib/validation/task-list-schema.ts) as a non-fatalTaskListWarning, 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.tsand an over-budget write is refused (budget-exceeded, exit 1, nothing written) unless--forceis 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.mdmirror regen actually fire (invariant 57 — enforcement point = substrate/server; façade = operator surface). The thresholds, the--forceescape 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.
4. Worked examples
Section titled “4. Worked examples”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-29description(8203 chars) carries the Option A/B/C migration trade-off analysis. This rationale survives the Task and belongs indocs/specs/cocoindex-*/— thedescriptionshould be a one-paragraph what+why with across_doc_linkspointer to the spec.
Bad — session narrative in status_note:
A
status_noteaccumulating “S264 did X, S265 hit Y, re-ran Z” is using a status field as a journal. The current-status assertion stays instatus_note(≤300); the session-by-session record moves to the relevant Subtaskdetails<info added on …>block.
Good — pointer, not copy:
ID-35
descriptionreferencesdocs/research/id-35-crossover-audit.mdand the spec chain rather than inlining the patch-primitive audit. The heavy material lives indocs/; thedescriptionsummarises 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.
5. Retroactive sweep
Section titled “5. Retroactive sweep”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.
6. Related
Section titled “6. Related”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).