cc-os/plugins/os-doc-hygiene/openspec/changes/lifecycle-aware-doc-hygiene/specs/doc-check/spec.md

4.6 KiB

Spec: doc-check (delta)

MODIFIED Requirements

Requirement: Check Skill Orchestrates Scan, Classification, and Report Writing

The check skill SHALL orchestrate the check pipeline: load the lifecycle rulebook (global plus any project override), run the deterministic scanner (consuming the rulebook so directory-rule matches prune the walk and lifecycle signals are attached per the lifecycle-rulebook spec), dispatch a Sonnet subagent for judgment-only classification of the signal-bearing candidates, run the deterministic finalize pass (which also computes promotion_candidates from conventions.json), validate, write the report pair, and stamp last_check. The skill SHALL run all non-judgment steps as deterministic scripts with no model (invariant #6). Zero-signal shortlisted files SHALL be treated as presumptively cleared: they SHALL remain in the shortlist, produce no entries, and SHALL NOT be read by the model. A --scope argument SHALL narrow the scanner; a --category argument SHALL filter which entries are produced after classification; both SHALL be recorded in the human-report header.

Scenario: Skill runs the full pipeline

  • WHEN the check skill runs
  • THEN it loads the rulebook, scans (deterministic, rulebook-aware), classifies signal-bearing candidates (Sonnet), finalizes (deterministic, including promotion candidates), validates (deterministic), writes the report pair (deterministic), and stamps last_check (deterministic)

Scenario: Zero-signal files are not read by the model

  • WHEN a shortlisted file carries no scanner signals
  • THEN it remains in the shortlist, produces no entry, and is not read by the classification model

Scenario: Scope and category are recorded and applied

  • WHEN the user passes --scope docs/**/*.md and --category bloat
  • THEN the scanner is narrowed by the scope, only bloat entries are produced after classification, and both the scope and the category are recorded in the human-report header

Scenario: Rulebook load failure is a hard failure, not a silent skip

  • WHEN the rulebook loader hard-fails (unparseable JSON or unknown schema_version in either rulebook file)
  • THEN the check skill stops and reports the rulebook error before running the scanner, rather than proceeding with lifecycle signals silently disabled

ADDED Requirements

Requirement: Scanner Consumes the Rulebook for Pruning and Lifecycle Signals

The deterministic scanner SHALL consult the loaded rulebook during its walk. A directory-rule match (including IGNORE-surface entries) SHALL prune the walk beneath that directory per the lifecycle-rulebook spec. A file-rule match SHALL attach a lifecycle signal to that file's shortlist entry. These lifecycle signals SHALL flow into the classification subagent as a new signal class alongside the pre-existing stale/bloat signals, and MAY drive op/op_type selection toward delete or extract-then-delete per the lifecycle-deletion spec.

Scenario: A directory-rule prune is reflected in the scan artifact

  • WHEN the scanner encounters a directory matching a directory rule
  • THEN the scan artifact reflects the prune (no files beneath it are in files_scanned), and, for non-IGNORE directory rules, exactly one aggregate shortlist entry appears for that directory

Scenario: A file-rule lifecycle signal reaches the classifier

  • WHEN a file matches a file-rule with lifetime: delete-once-served
  • THEN the classification subagent receives the lifecycle signal (rule reference, lifetime, served_when/served_when_path) as part of that file's signals, verbatim, per the existing "signals are passed through verbatim" contract

Requirement: Report Gains a Promotion-Candidates Section

The machine and human reports produced by :check SHALL include a promotion_candidates section (top-level, sibling to entries), populated deterministically by the finalize pass from conventions.json for every classifier-judged lifecycle entry with an applicable, not-yet-adopted convention. This section SHALL be present (possibly empty) on every run, including runs with no lifecycle entries.

Scenario: A run with an applicable convention names it in both reports

  • WHEN a classifier-judged entry has an applicable, unadopted convention
  • THEN both the machine report's promotion_candidates array and the human report show the candidate with its one-line pitch

Scenario: A run with no applicable conventions still has the section, empty

  • WHEN no classifier-judged entry has an applicable unadopted convention
  • THEN promotion_candidates is present as an empty array/section rather than omitted