Summary
spec-plan's per-task Files: block is the scope that changes-review later reviews against ("extract the list of files each task creates/modifies — the plan files"; "scope to only plan files"). But the plan template gives the author no way to state a deletion, and no rule says that every path a task's own body names — in its Objective, Key Decisions, or DoD — must also appear in Files:. Plans therefore routinely arrive with a Files: list written from what the task edits and missing what it creates, deletes, or touches in passing (a doc comment on an interface, a CLI help string, an option description, a queue/report file the task removes).
Nothing catches it at plan time: pilot spec validate checks the rendering contract, not Files: completeness, and a human reviewer skims past a missing path far more easily than a missing task. It surfaces at implementation time as a changes-review scope complaint against an implementer that did exactly what its plan said — or, worse, the out-of-list edit is scoped out of the review entirely and lands unreviewed.
Version: Pilot Shell v11.0.2, Claude Code on Linux (WSL2).
Where it lives
~/.claude/skills/spec-plan/SKILL.md, the task template (around the **Files:** label):
**Files:**
- Create: `exact/path/to/file.py`
- Modify: `exact/path/to/existing.py`
- Test: `tests/exact/path/to/test.py`
Three verbs, no Delete, and the only rule attached to the block is that it "must list reviewable implementation artifacts". The consumer side, ~/.claude/agents/changes-review.md, reads Files: as the review scope.
Reproduction
-
Run /spec on a task whose natural description mentions a file without "editing" it as the headline, e.g.:
Add a --force flag to the wipe command. Update the doc comment on IStore to say the flag bypasses the guard. Remove the now-obsolete docs/todo/wipe-guard.md.
-
Read the generated plan's task. In our runs the task body named all three files, but Files: listed only the command file and its test:
**Files:**
- Modify: `src/cli/WipeCommand.cs`
- Test: `tests/cli/WipeCommandTests.cs`
IStore.cs (doc-comment edit) and docs/todo/wipe-guard.md (deletion) are absent — the second because the template has no verb for it.
-
pilot spec validate <plan> → exit 0.
-
Implement. changes-review scopes to plan files, so the IStore.cs hunk is either flagged as out-of-scope or never reviewed, and the deletion is invisible to the review.
Across one five-task plan we counted five omissions of this shape in three tasks (a doc-comment target, a CLI-help/option-description file whose text a DoD bullet asserted on, the test class a DoD's own verify command ran, plus one create and one delete), found only by a manual sweep after approval.
Suggested fix
Two small changes to spec-plan, no CLI change:
- Add
Delete: (and optionally Rename:) to the Files: template so a removal has somewhere to go.
- Add a rule to the task-writing step: every repository path named anywhere in the task body (Objective, Key Decisions / Notes, Definition of Done — including the file a verify command runs) must appear in
Files:. Derive the list from the task body rather than from the code the author was looking at; a path that only appears as "update the doc comment on X" or "the --help text in Y" is still a modification.
Optionally, pilot spec validate could enforce (2) mechanically — it already parses the task blocks, and a backtick-quoted path in the body that is missing from Files: is a cheap, deterministic check.
Summary
spec-plan's per-taskFiles:block is the scope thatchanges-reviewlater reviews against ("extract the list of files each task creates/modifies — the plan files"; "scope to only plan files"). But the plan template gives the author no way to state a deletion, and no rule says that every path a task's own body names — in its Objective, Key Decisions, or DoD — must also appear inFiles:. Plans therefore routinely arrive with aFiles:list written from what the task edits and missing what it creates, deletes, or touches in passing (a doc comment on an interface, a CLI help string, an option description, a queue/report file the task removes).Nothing catches it at plan time:
pilot spec validatechecks the rendering contract, notFiles:completeness, and a human reviewer skims past a missing path far more easily than a missing task. It surfaces at implementation time as achanges-reviewscope complaint against an implementer that did exactly what its plan said — or, worse, the out-of-list edit is scoped out of the review entirely and lands unreviewed.Version: Pilot Shell v11.0.2, Claude Code on Linux (WSL2).
Where it lives
~/.claude/skills/spec-plan/SKILL.md, the task template (around the**Files:**label):Three verbs, no
Delete, and the only rule attached to the block is that it "must list reviewable implementation artifacts". The consumer side,~/.claude/agents/changes-review.md, readsFiles:as the review scope.Reproduction
Run
/specon a task whose natural description mentions a file without "editing" it as the headline, e.g.:Read the generated plan's task. In our runs the task body named all three files, but
Files:listed only the command file and its test:IStore.cs(doc-comment edit) anddocs/todo/wipe-guard.md(deletion) are absent — the second because the template has no verb for it.pilot spec validate <plan>→ exit 0.Implement.
changes-reviewscopes to plan files, so theIStore.cshunk is either flagged as out-of-scope or never reviewed, and the deletion is invisible to the review.Across one five-task plan we counted five omissions of this shape in three tasks (a doc-comment target, a CLI-help/option-description file whose text a DoD bullet asserted on, the test class a DoD's own verify command ran, plus one create and one delete), found only by a manual sweep after approval.
Suggested fix
Two small changes to
spec-plan, no CLI change:Delete:(and optionallyRename:) to theFiles:template so a removal has somewhere to go.Files:. Derive the list from the task body rather than from the code the author was looking at; a path that only appears as "update the doc comment on X" or "the--helptext in Y" is still a modification.Optionally,
pilot spec validatecould enforce (2) mechanically — it already parses the task blocks, and a backtick-quoted path in the body that is missing fromFiles:is a cheap, deterministic check.