Status: promoted/task
Reading an SDLC entity’s data is un-abstracted: each consumer resolves the path, reads the file
(working tree only), parseFrontmatter’s into an untyped Record, and indexes fields by hand. Example:
sweep.ts#statusAtOriginMain does ‘git show origin/main:’ + parseFrontmatter + fm[‘status’].
Evidence: (1) readTaskDoc (task/ops/_task_doc.ts) only readFileSync’s the WORKING TREE and returns
raw {path,text}, not a validated Task, and can’t read at a git rev; (2) 14 files call
parseFrontmatter, with at least TWO implementations (@lib/util/frontmatter and a second one inside
_task_doc.ts); (3) the Zod schema / TaskContract are wired into validation-on-WRITE (entities
validate/audit) but no READ path; (4) reading an entity at a git rev exists only ad hoc in sweep.ts
and a couple of tests. PROPOSED: a model-layer accessor readTask(id, {projectRoot, at?: rev, git?:
CommandRunner}): Task | null (generalize to readEntity over all entity types) that resolves the path
(reuse resolveTaskDocPath), reads from the working tree OR an injected git seam at ‘at’, and returns
the INFERRED TYPED object from markdown-contract’s parse(TaskContract, text) — the typed leaf the
contract already gives — not an untyped frontmatter record. Then statusAtOriginMain collapses to
readTask(taskId, {at:‘origin/main’, git: ctx.git})?.status ?? null and the ~13 other hand-rolled
sites converge on one path. Surfaced reviewing PR #905 (T-Z698 lease sweep) 2026-07-19.
← Back to Backlog