TECH — Task-list field discipline (ID-34.3)
TECH — Task-list field discipline (ID-34.3)
Section titled “TECH — Task-list field discipline (ID-34.3)”Task: ID-34. This Subtask: {34.3} TECH — doc-location decision + skill-update map + soft-warning implementation. Predecessors: RESEARCH.md, PRODUCT.md.
Maps each PRODUCT invariant to a concrete proposed change, grounded in the installed code
and skill bodies (verified at HEAD 73ffb2b4). Migration plan: zero schema migration — the
only code change is additive warning logic.
§1 Doc-location decision (resolves OQ-34-1)
Section titled “§1 Doc-location decision (resolves OQ-34-1)”Decision: new dedicated doc docs/reference/task-list-discipline.md. NOT an appended §
to taskmaster-schema-reference.md.
Rationale:
taskmaster-schema-reference.mdis a snapshot-dated empirical artefact (“Snapshot date: 2026-05-16. If the upstream Phoenix Bridges export changes shape, re-run the analysis”). It answers what the fields are. The discipline doc answers how to write them — an evolving policy with a different update cadence and a different audience (authors/Planners vs parser implementers). Co-locating couples two doc lifecycles and invites the discipline policy to inherit the schema-reference’s “re-run on upstream change” framing, which does not apply.- A dedicated doc is the natural
cross_doc_linksand skill-reference target (a single stable path), and the natural home the four skills point at (inv 9). - It registers cleanly in
docs/reference/documentation-inventory.mdas one new entry.
The discipline doc cross-links to taskmaster-schema-reference.md for the field shapes
and to lib/validation/task-list-schema.ts for the enforced constraints, so the two are
connected without being merged.
§2 Proposed changes, mapped to PRODUCT invariants
Section titled “§2 Proposed changes, mapped to PRODUCT invariants”| PRODUCT inv | Proposed change | File(s) |
|---|---|---|
| 1, 2, 3, 4, 5, 6, 7 | Author docs/reference/task-list-discipline.md publishing the §2 per-field table + the canonical-ref-vs-traceability boundary rule + ≥3 worked examples. | docs/reference/task-list-discipline.md (new) |
| 1 | Register the new doc in the documentation inventory. | docs/reference/documentation-inventory.md |
| 8, 10, 11 | Extend parseTaskListWithWarnings with a per-field budget check emitting TaskListWarning entries; no schema .max(); logic stays inside the function body. | lib/validation/task-list-schema.ts |
| 8 | Unit test: over-budget fixture warns (not throws); 25-Subtask warning still fires; field/id/measured-vs-budget surfaced. | __tests__/lib/validation/task-list-discipline-warnings.test.ts (new) |
| 9 | Amend the 3 repo-local skills to cite the discipline doc. | .claude/skills/{workflow-orchestration,write-product-spec,write-tech-spec}/SKILL.md |
| 9 | Amend planning-and-task-breakdown — see §4 (global-skill caveat / OQ-34-5). | ~/.claude/skills/planning-and-task-breakdown/SKILL.md (global — see OQ) |
| 12, 13 | Sweep policy is in PRODUCT §4; {34.4} PLAN decomposes it as the lowest-priority Subtask with the OQ-first gate. | PLAN.md + OQ-pending.md |
§3 Soft-warning implementation design (inv 8/10/11)
Section titled “§3 Soft-warning implementation design (inv 8/10/11)”Extend the existing parseTaskListWithWarnings loop. Add a small budget table and a
per-Task / per-Subtask field scan that pushes warnings alongside the existing 25-Subtask
check. No change to any *Schema definition.
// lib/validation/task-list-schema.ts — inside parseTaskListWithWarnings, after parseconst FIELD_BUDGETS = { taskDescription: 1500, taskStatusNote: 300, subtaskDescription: 250, subtaskTestStrategy: 300,} as const;
// per Task:if (task.description.length > FIELD_BUDGETS.taskDescription) { warnings.push({ taskId: task.id, message: `Task "${task.id}" description is ${task.description.length} chars ` + `(>${FIELD_BUDGETS.taskDescription}). Move design rationale to docs/ and ` + `reference it via cross_doc_links (see docs/reference/task-list-discipline.md).` });}if (task.status_note && task.status_note.length > FIELD_BUDGETS.taskStatusNote) { … }// per Subtask: description / testStrategy budgets, same shape.Why this is safe (inv 10/11):
TaskListSchema.parse()is untouched — the live over-budget ledger still parses. The warning is additive and non-fatal (matches the 25-Subtask-ceiling precedent exactly).- No
*Schemafield-shape change: the exportedSubtaskSchema/TaskSchema/TaskListSchemafield definitions are untouched, so there is no schema rejection, no enum change, and no logical divergence of the validated shape from task-view’spackages/schemas/src/task-list-schema.ts. Caveat (post-Checker correction): the new module-levelFIELD_BUDGETSconst + the extendedparseTaskListWithWarningsbody are NOT stripped by the drift workflow’snormalise()(it strips comments/imports/re-exports/ regex-consts only), so they WILL appear in the schema-step normalised diff and emit a non-blocking::warning::until task-view re-vendors KH’s schema. That is the workflow working as intended (a re-vendor reminder), acceptable per OQ-T2 — not a hard cap, not a CI failure. - The
TaskListWarninginterface already exists ({taskId, message}) — no new type. (A later enhancement could add an optionalfield/severity, but inv 8 only requires the id + field + measured-vs-budget to appear inmessage, so the minimal change keeps the interface stable and avoids touching consumers.)
ID-35 consumption (the audit §5 contract): the ID-35 CLI parses via
parseTaskListWithWarnings and prints warnings[] to stderr on every mutating command, so
discipline drift surfaces to the orchestrator-operator at write time without hard-failing.
No additional ID-35-side work — the warnings flow for free.
§4 Skill-update map (inv 9)
Section titled “§4 Skill-update map (inv 9)”| Skill | Path | Class | Insertion point | Amendment |
|---|---|---|---|---|
| workflow-orchestration | .claude/skills/workflow-orchestration/SKILL.md | repo-local ✓ | ## Ledger field-discipline (line ~270) — the table already exists | Add a lead pointer: “Canonical reference: docs/reference/task-list-discipline.md.” Align the table’s budgets with the doc (≤1500 description, ≤300 status_note, ≤250 subtask description, one-line testStrategy). |
| write-product-spec | .claude/skills/write-product-spec/SKILL.md | repo-local ✓ | ## Keep the spec current (line ~202) | Add: canonical rationale/behaviour belongs in this PRODUCT.md; the task-list description carries a compact what+why + a cross_doc_links pointer here, never a copy. Link the discipline doc. |
| write-tech-spec | .claude/skills/write-tech-spec/SKILL.md | repo-local ✓ | ## Keep the spec current (line ~158) | Same shape: REJECTED-alternatives + migration rationale live here; task-list description points, does not inline. Link the discipline doc. |
| planning-and-task-breakdown | ~/.claude/skills/planning-and-task-breakdown/SKILL.md | global ✗ | ### Step 4: Write Tasks (line ~79) + ## Task Sizing Guidelines | When emitting Subtask records: details = dispatch brief + append-only journal (uncapped); testStrategy = one-line acceptance the Checker gates against; description = one sentence. Link the discipline doc. See OQ-34-5. |
OQ-34-5 — planning-and-task-breakdown is a GLOBAL skill (uncommittable)
Section titled “OQ-34-5 — planning-and-task-breakdown is a GLOBAL skill (uncommittable)”planning-and-task-breakdown lives at ~/.claude/skills/, not in the KH repo, so an
edit to it cannot be committed to this worker branch or cherry-picked to main by the
parent. The cmux brief’s Files list assumed it was repo-local (.claude/skills/…).
Provisional default (applied): amend the three repo-local skills (committable, the
load-bearing pair being workflow-orchestration + the two write-*-spec skills) and surface
OQ-34-5 to the parent via OQ-pending.md. The global planning-and-task-breakdown edit is
deferred to the parent’s decision: either (a) vendor planning-and-task-breakdown into
.claude/skills/ (so the discipline amendment is committable + shared), or (b) the parent
applies the global-skill edit out-of-band on the host. The CLI/discipline-doc deliverables
do not depend on this skill edit, so deferral does not block ID-34 or ID-35.
Skill-edit hook policy
Section titled “Skill-edit hook policy”Per the cmux brief: ID-34 skill updates go via the update-skill skill; the
workflow-security hook may block the FIRST raw .claude/skills/ edit once — retry succeeds.
§5 Coverage matrix
Section titled “§5 Coverage matrix”| PRODUCT inv | TECH change | Verification |
|---|---|---|
| 1 | §2 discipline doc + inventory entry | file exists + inventory grep |
| 2,3,7 | doc boundary rules + examples | doc content |
| 4,5,6 | doc field designations | doc content |
| 8 | §3 warning loop + test | unit test green |
| 9 | §4 skill amendments (3 repo-local) | grep each SKILL.md |
| 10 | no .max() added | schema diff |
| 11 | warning in function body, schema shape intact | schema field-export diff + vendor-drift check |
| 12,13 | sweep policy → PLAN + OQ-first gate | PLAN.md + OQ-pending.md |
1-to-1 mapping holds. New T-OQ: OQ-34-5 (global-skill). Migration plan: zero.