# 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`, recommended `op`, `op_type`
  (`deterministic` | `generative`), the op characterization booleans
  `is_destructive` and `is_reversible`, a **derived** `safety_tier`
  (`auto` | `confirm`), an optional `exact_edit` (present iff `op_type` is
  `deterministic`), and a per-entry `token_estimate`.
- Fix the **category taxonomy** as a closed enum: stale =
  `contradicted` | `orphaned` | `superseded` | `provisional` |
  `completed-in-place` | `duplicated`; bloat = `distill` | `split` | `freeze`.
- Make **`op_type` a property of the chosen `op`** (not a free field, not a
  subtype lookup): `op_type` must be consistent with `op`, with `exact_edit`
  present iff `op_type` is `deterministic`, validated deterministically.
- Make **`safety_tier` derived deterministically** per invariant #7: the model
  proposes `op`, `op_type`, `is_destructive`, and `is_reversible`; a script
  function `safety_tier(op_type, is_destructive, is_reversible)` computes the
  tier (generative ⟹ confirm; destructive or irreversible ⟹ confirm; only
  deterministic + reversible + objective ⟹ auto). The model cannot emit `auto`
  for a generative or destructive op.
- Scope the **`token_estimate`** to match the PRD build order: in v1 only
  `raw_tokens` (deterministic local-tokenizer count, no API call) is required;
  `injection_frequency` and `weighted_tokens` are 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.kind`** closed enum: one `kind` per deterministic op
  family the PRD names (`delete-range`, `move-to-archive`, `insert-frontmatter`
  for freeze-stamp, `replace-text` for known-target link fix, `dedupe` for
  exact-dup removal), each with its required sub-fields and inherent
  `(is_destructive, is_reversible)` characterization that feeds the `safety_tier`
  derivation.
- Declare the schema a **frozen contract** enforced by `invariants.md` (which now
  exists and carries the schema-freeze and `safety_tier` derivation invariants):
  changing any field, enum value, or semantic requires updating `invariants.md`
  with 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 the `check` change 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-schema` capability.
- Affected code: none yet. This is the contract every later component (scanner,
  `check` skill, `clean` skill / 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 two `examples/golden/`
  schema fixtures used to verify the schema shape.
- Human-readable report ownership: this change specifies only the **machine**
  report. The human-readable `.md` report SHAPE is a sibling user-facing contract
  owned by the upcoming `check` change. It is load-bearing for the confirm-tier
  escalation UX (it is what the user reads when approving `confirm` ops), 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 `check`
  change (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 `check` skill.
