4.8 KiB
4.8 KiB
Change: Add Report Schema
Why
The machine report schema is the linchpin of doc-hygiene: it is the contract
that the check skill produces and that the clean skill, sweep, and the
token estimator all consume. Per the build order, it gates everything — no
component can be built correctly until the report's shape is fixed. The PRD and
CLAUDE.md state it is "designed and frozen first."
This change specifies that schema as a frozen contract before any code exists, so that the deterministic core and the AI layers are built against a single, stable structure rather than re-deriving it. It is spec-authoring only: no scripts and no schema code are produced here.
What Changes
- Define the top-level machine report structure: schema version, scan metadata (scope, files scanned, generated-at timestamp, tool version), the candidate shortlist, and a per-file entries list.
- Define the per-file report entry fields:
path,category(with the fixed stale/bloat sub-type taxonomy),signals, recommendedop,op_type(deterministic|generative), the op characterization booleansis_destructiveandis_reversible, a derivedsafety_tier(auto|confirm), an optionalexact_edit(present iffop_typeisdeterministic), and a per-entrytoken_estimate. - Fix the category taxonomy as a closed enum: stale =
contradicted|orphaned|superseded|provisional|completed-in-place|duplicated; bloat =distill|split|freeze. - Make
op_typea property of the chosenop(not a free field, not a subtype lookup):op_typemust be consistent withop, withexact_editpresent iffop_typeisdeterministic, validated deterministically. - Make
safety_tierderived deterministically per invariant #7: the model proposesop,op_type,is_destructive, andis_reversible; a script functionsafety_tier(op_type, is_destructive, is_reversible)computes the tier (generative ⟹ confirm; destructive or irreversible ⟹ confirm; only deterministic + reversible + objective ⟹ auto). The model cannot emitautofor a generative or destructive op. - Scope the
token_estimateto match the PRD build order: in v1 onlyraw_tokens(deterministic local-tokenizer count, no API call) is required;injection_frequencyandweighted_tokensare optional/nullable v1 fields whose population (injection-frequency weighting + bottom-up rollup) is the v2 bonus. The schema shape is fixed now so the contract never changes. - Freeze the
exact_edit.kindclosed enum: onekindper deterministic op family the PRD names (delete-range,move-to-archive,insert-frontmatterfor freeze-stamp,replace-textfor known-target link fix,dedupefor exact-dup removal), each with its required sub-fields and inherent(is_destructive, is_reversible)characterization that feeds thesafety_tierderivation. - Declare the schema a frozen contract enforced by
invariants.md(which now exists and carries the schema-freeze andsafety_tierderivation invariants): changing any field, enum value, or semantic requires updatinginvariants.mdwith explicit human approval. - Provide schema-shape verification: a schema-validator script plus two
hand-authored schema fixtures under
examples/golden/(one valid machine report, one invalid) proving the validator accepts/rejects correctly. These are schema-shape fixtures, not classifier golden examples — the latter are deferred until thecheckchange exists (the classifier that would produce them does not exist yet, so hand-authoring them now risks diverging from real classifier output).
Impact
- Affected specs: creates a new
report-schemacapability. - Affected code: none yet. This is the contract every later component (scanner,
checkskill,cleanskill / patch-applier, token estimator,sweep) will consume; those are out of scope here. The only artifacts this change produces beyond the spec are the schema-validator script and the twoexamples/golden/schema fixtures used to verify the schema shape. - Human-readable report ownership: this change specifies only the machine
report. The human-readable
.mdreport SHAPE is a sibling user-facing contract owned by the upcomingcheckchange. It is load-bearing for the confirm-tier escalation UX (it is what the user reads when approvingconfirmops), so it must be treated as a contract in its own right — out of scope here, but its owner is named so it is not left ownerless. - Deferred: classifier golden examples are deferred to after the
checkchange (the classifier that produces them does not exist yet). This change ships only schema-shape fixtures, which are distinct. - Dependencies: none. This change is the first in the build order and unblocks
the deterministic core and the
checkskill.