Skip to content

T-V8K4-task-ensure-ready-fuzzy-locates-cited-paths

Status: closed/superseded · Impact: medium · Complexity: small

Auto-generated from a /sdlc:task-work post-mortem. Review and promote to open/ready before picking up.

/sdlc:task-ensure-ready validates referenced file paths only when they appear in the ## Files to touch section. Paths cited elsewhere in the body (Goal / Today / Acceptance criteria) slip through even when the basename matches an existing script but the parent dir is wrong — e.g. plugin/validators/lint_skill_prose.py vs the real plugin/scripts/lint_skill_prose.py. The drift surfaces only at relevance-check time during /sdlc:task-work, well after the readiness gate has stamped readiness_verified_at:. Catching it at ensure-ready time keeps stale paths out of open/ready tasks. Cited by the post-mortem of T-TJB3-orchestrate-enforces-one-line-verdict.

plugin/skills/task-ensure-ready/SKILL.md Step 3 (“Evaluate the contract”) extracts paths via a body-wide regex but only verifies existence for paths listed under ## Files to touch. The implementation-ready.md contract’s “File-path disqualifiers” entry is similarly scoped to that section. A path like plugin/validators/lint_skill_prose.py in ## Acceptance criteria (when the real script lives at plugin/scripts/lint_skill_prose.py) never trips the disqualifier — the basename exists, but at a different parent.

Quote from the originating post-mortem: “The task body cited plugin/validators/lint_skill_prose.py but the script actually lives at plugin/scripts/lint_skill_prose.py. The relevance check caught it, but the task spec slipped through /sdlc:task-ensure-ready because path-resolution against a tight glob only checks paths under ‘Files to touch’.”

Extend the readiness check to also fuzzy-locate every plugin/... (or other project-root-rooted) path mentioned anywhere in the body. When a cited path doesn’t exist but a file with the same basename exists elsewhere, flag it as a definition_gap with a suggested correction. Existing path-exists checks under ## Files to touch remain authoritative for new-file declarations.

  1. Audit plugin/skills/task-ensure-ready/SKILL.md Step 3 and plugin/entities/task/implementation-ready.md for the current path-check scope; identify the regex used and where the check gate is applied.
  2. Add a “cited-path drift” sub-check that runs the same path regex over the WHOLE body (excluding fenced code blocks), and for each non-existent path searches for files matching the basename anywhere under the project root.
  3. On a basename match with parent-dir drift, record a definition_gap that names both the cited path and the most-likely real path so the operator can fix the body in one edit.
  4. Add a new run_evals.py case covering the drift scenario.
LocationKindChange
plugin/skills/task-ensure-ready/SKILL.mdmodifyExtend Step 3’s path-resolution sub-check to scan the whole body (excluding fenced code blocks) for project-rooted paths and fuzzy-locate basenames when the cited path doesn’t exist.
plugin/entities/task/implementation-ready.mdmodifyDocument the new “cited-path drift” disqualifier alongside the existing file-path disqualifier; tighten the contract so basename-elsewhere mismatches are surfaced at ensure-ready time.
plugin/skills/task-ensure-ready/tests/run_evals.pymodifyAdd fixture cases for both AC-1 (basename exists at different parent) and AC-2 (basename absent entirely).
  • AC-1: A task whose body cites plugin/validators/lint_skill_prose.py (a basename that exists, but at a different parent) fails ensure-ready with a definition_gap that names the cited path and the actual location.
  • AC-2: A task whose body cites a non-existent path with no matching basename anywhere in the repo fails ensure-ready with a definition_gap naming the missing path.
  • AC-3: plugin/skills/task-ensure-ready/tests/run_evals.py covers both cases and passes.
  • Fuzzy-matching arbitrary code symbols (the original disqualifier for symbol drift remains as-is — that’s a command grep check, not a fuzzy locator).
  • Auto-correcting the cited path in the task body (only flagging).
  • none

Spawned by /sdlc:task-work post-mortem of T-TJB3-orchestrate-enforces-one-line-verdict on 2026-05-21.

Review feedback (from PR #87, closed for refactor)

Section titled “Review feedback (from PR #87, closed for refactor)”

PR #87 implemented this task end-to-end (added plugin/skills/task-ensure-ready/scan_cited_paths.py, extended Step 3 of the skill, widened the file-path disqualifier in implementation-ready.md, and added seven new eval cases — 23/23 passing). The PR is being closed without merge because broader refactoring is planned in this area; re-pick this task post-refactor.

Reviewer (sksizer) feedback during the PR:

  • The only review comments were on the spawned sibling task docs/planning/tasks/2026-05-21-run-quality-checks-continue-on-fail.md (added by this PR as a post-mortem follow-up), not on the scan_cited_paths.py implementation itself. Specifically: should run_quality_checks.py --continue-on-fail emit a structured data payload of all errors (not just --line output)? — answered yes, the sibling task spec was updated in commit 0472966 to add AC-4 covering a --json mode that emits a structured array (verb name, exit code, status, captured output) so consumers (e.g. /sdlc:task-work Step 7) can diff pre-existing vs branch-introduced failures programmatically.
  • No reviewer feedback was filed against the cited-path-scanner design, the eval coverage, the scope of body-wide scanning, or the fenced-code / inline-code / optional-section exemption inheritance from scan_placeholders.py. On re-pickup, treat the PR #87 implementation as a working reference but expect the surrounding refactor to change the integration surface (Step 3 hook point, the shell-out vs in-process boundary, and the disqualifier vocabulary).

← Back to Tasks