Skip to content

T-DYZJ-planning-exemption-splits-open-from-closed

Status: planning/proposed · Impact: medium · Complexity: small

AUTO-DEFINED: this spec was best-effort machine-authored by /sdlc:task-auto-define on 2026-07-20 because the task is autonomy: autonomous/pr. Review the Goal, Approach, Today, Files-to-touch, and Acceptance-criteria carefully before trusting it.

Path-reference sweeps that repoint citations after a move exempt docs/planning/ wholesale, treating every planning entity as a frozen historical record. That reasoning holds for closed entities and fails for open ones: an open backlog item citing a pre-move path is naming a forward-looking work target, not recording history, so exempting it strands whoever picks it up at a dead path. Split the exemption by entity status so closed records stay frozen while open work items get swept.

Reported from T-C9RD-consolidate-augmented-into-solutions in https://github.com/sksizer/dev:

Reference sweeps that repoint paths after a move exempt docs/planning/ wholesale, on the reasoning that planning entities are historical records whose citations should stay frozen. That is right for closed entities and wrong for open ones. During T-C9RD, B-6V5U and B-UEE4 — both status: open/active backlog items citing pre-move paths as forward-looking WORK TARGETS — were exempted and will now send whoever picks them up at dead paths. Split the exemption by entity status: closed/* entities stay frozen as historical record; open/active entities are in scope for the sweep (or at minimum are reported as stale-citation warnings). Touchpoints: the paths claim resolver at apps/sdlc/lib/model/entities/task/claims/ and the reference-sweep guidance in apps/sdlc/conventions/.

LocationRole today
apps/sdlc/conventions/Home of the canonical shared conventions each SKILL.md references instead of inlining. There is no reference-sweep doc here, so the post-move sweep rule — including the docs/planning/ exemption — exists only as ad-hoc prose re-invented in each task’s ACs.
docs/planning/tasks/T-C9RD-consolidate-augmented-into-solutions.mdAC-7 carries the exemption in its wholesale form (“historical planning records exempt”), which is what stranded the two open backlog items.
apps/sdlc/lib/model/entities/task/claims/paths.tsFlags a back-ticked, path-shaped citation whose path no longer exists but whose basename uniquely matches one file elsewhere. Runs per-task inside the readiness gate only; its detection core is module-private and it ignores the entity’s status.
apps/sdlc/lib/model/corpus/loader.ts#loadCorpusWalks docs/planning/ into a basename → {type, status} index — the existing seam that already knows every planning entity’s status.
apps/sdlc/lib/model/read.ts#scanEntitiesBulk frontmatter scan across the planning dirs; the read layer any corpus-wide walk must go through.
apps/sdlc/lib/model/ops/index.tsExplicit barrel for the generic cross-entity ops (audit, validate, migrate, check-identifiers, get-schema). model/ops/ is not a discovery-walk root, so an op registers by being re-exported here.
apps/sdlc/skills/task-work/SKILL.mdStep 1’s relevance check verifies paths cited by the task being picked up. Nothing covers the reciprocal direction — repointing citations held by other entities after this task moves a file.
apps/sdlc/lib/model/entities/task/implementation-ready.mdRequires a delete row to enumerate every referencing file as its own modify row, but says nothing about how docs/planning/ participates in that enumeration.

Codify the sweep rule once, split by entity status, and make the split checkable instead of prose-only:

  • closed/* planning entities are frozen historical records — out of scope for a post-move citation sweep.
  • Every other planning entity is a live work item whose citations name forward-looking targets, so it is in scope and its stale citations are reported.

The reporting half rides on the detection core already written for the paths claim resolver, lifted to a corpus-wide, advisory op.

  1. Write the convention. Add apps/sdlc/conventions/reference-sweep.md as the single home for post-move sweep guidance: what a sweep covers (doc citations, hooks, CI/lefthook gates, eval harnesses, non-.md string fields), and the status split above stated as the rule, with the T-C9RD/B-6V5U/B-UEE4 incident as its one-paragraph rationale.
  2. Expose the detection core. In apps/sdlc/lib/model/entities/task/claims/paths.ts, export collectCitations, indexBasenames, and stripLocationSuffix. The resolver’s own resolve() and its findings are unchanged; only the module’s export surface widens so a second caller can reuse the walk.
  3. Add the corpus op. Add apps/sdlc/lib/model/ops/stale-citations.ts, a defineOp({ noun: "entities", verb: "stale-citations" }) descriptor modelled on the sibling check-identifiers.ts. It resolves the planning root from ctx.projectRoot (overridable via an optional planningRoot input), enumerates entities through scanEntities, drops any whose status starts with closed/, and runs the Step-2 helpers over each survivor’s body. Output: { findings: [{ file, path, line, relocated }] } where relocated is the unique same-basename match or null. Severity is advisory — the op always exits 0 and reports; it never blocks.
  4. Register it. Re-export the descriptor from apps/sdlc/lib/model/ops/index.ts alongside the other generic ops.
  5. Test the split. Add apps/sdlc/lib/model/ops/tests/stale-citations.test.ts with a fixture planning dir holding two entities that carry the identical stale citation — one closed/done, one open/active — and assert only the open/active one appears in findings.
  6. Point the two consumers at the convention. Add a one-line pointer in apps/sdlc/skills/task-work/SKILL.md’s Notes and in the delete-row paragraph of apps/sdlc/lib/model/entities/task/implementation-ready.md. One-line references only — no duplicated prose, per the progressive-disclosure rule in apps/sdlc/skills/CLAUDE.md.
LocationKindChange
apps/sdlc/conventions/reference-sweep.mdnewCanonical post-move sweep guidance carrying the closed/*-frozen / non-closed-in-scope split.
apps/sdlc/lib/model/entities/task/claims/paths.tsmodifyExport collectCitations, indexBasenames, stripLocationSuffix; resolver behaviour untouched.
apps/sdlc/lib/model/ops/stale-citations.tsnewentities stale-citations op — status-filtered corpus walk reporting stale citations held by non-closed entities.
apps/sdlc/lib/model/ops/index.tsmodifyRe-export the new op descriptor so importing the barrel registers it.
apps/sdlc/lib/model/ops/tests/stale-citations.test.tsnewFixture test pinning the status split (closed skipped, open reported).
apps/sdlc/skills/task-work/SKILL.mdmodifyOne-line Notes pointer to the convention doc.
apps/sdlc/lib/model/entities/task/implementation-ready.mdmodifyOne-line pointer from the delete-row enumeration paragraph to the convention doc.
  • AC-1: apps/sdlc/conventions/reference-sweep.md exists and states the split in both directions — a closed/* planning entity is exempt from a post-move citation sweep, a non-closed one is in scope.
  • AC-2: apps/sdlc/cli/sdlc entities stale-citations --output json exits 0 and emits a findings array whose entries each carry file, path, line, and relocated.
  • AC-3: the op drops any entity whose status starts with closed/ — pinned by the fixture in apps/sdlc/lib/model/ops/tests/stale-citations.test.ts, where two entities carry the identical stale citation and only the open/active one is reported.
  • AC-4: apps/sdlc/lib/model/ops/index.ts re-exports the new descriptor, and apps/sdlc/cli/sdlc entities stale-citations --help prints the op’s summary.
  • AC-5: apps/sdlc/skills/task-work/SKILL.md and apps/sdlc/lib/model/entities/task/implementation-ready.md each carry a one-line pointer to apps/sdlc/conventions/reference-sweep.md, with the sweep prose itself living only in that doc.
  • AC-6: the paths resolver’s behaviour is unchanged — bun test apps/sdlc/lib/model/entities/task/claims/tests/ passes with no edits to its existing expectations.
  • Repointing the concrete citations in docs/planning/backlog/B-6V5U-retire-augmented-logging-and-augmented-utils-for-native.md and docs/planning/backlog/B-UEE4-adopt-sksizer-panes-determined-ui-across-migrated-vue-apps.md. T-C9RD-consolidate-augmented-into-solutions is still in-progress and the cited paths still exist, so there is nothing stale to repoint yet.
  • Promoting the op to a blocking gate (lefthook / CI). It is advisory in this task; a gate is a separate decision once the finding volume is known.
  • Auto-rewriting stale citations. The op reports; repointing stays an implementer action.
  • Splitting on any frontmatter field other than status (e.g. staleness by last_reviewed).
  • none

Spawned by /sdlc:spawn-task-pr on 2026-07-20 UTC from T-C9RD-consolidate-augmented-into-solutions in https://github.com/sksizer/dev.


← Back to Tasks