cc-os/plugins/os-doc-hygiene/openspec/project.md

4.5 KiB

Project Context

Purpose

doc-hygiene is a Claude Code plugin that monitors and manages stale and bloated project documentation. It is installed globally but operates per-project. It reminds the developer (deterministically, zero AI tokens) on SessionStart when docs haven't been checked recently, then checks and cleans on demand via skills.

The plugin holds a core distinction:

  • Stale = the doc is wrong (contradicted, orphaned, superseded, provisional, completed-in-place, duplicated). Remedy: fix or remove.
  • Bloat = the doc is true but mostly irrelevant (distill, split, freeze). Remedy: change its altitude, almost never delete history.

Severity scales with injection frequency — a stale line in an auto-injected file (CLAUDE.md, memory index) misleads every session, so it is worse than the same line in a doc nobody opens.

Design Principles

  1. Deterministic-first — scan, state, patch-apply, and token-estimate are scripts (no model). AI does only classification and prose distillation.
  2. Remind, don't nag — the SessionStart hook only reminds; it never runs analysis or mutates anything. All mutation is user-invoked. Reminders snooze (at most once/day while stale).
  3. Non-intrusive — state lives in-project under a gitignored .dochygiene/; no global index. The tool never silently edits the user's repo.
  4. Git-safe cleanup — runs only on a clean/committed tree (or after an auto WIP checkpoint); each run lands as one reviewable commit.
  5. The tool must not become the bloat it polices — report rollover keeps only the latest report.

Tech Stack

  • Plugin format: Claude Code plugin (skills + commands + a SessionStart hook declared in hooks/hooks.json, emitting a systemMessage banner).
  • Language: Python, OOP — small single-responsibility classes, dependency injection, immutable transforms where possible.
  • Scripts: structured JSON output, correct exit codes, idempotent, testable in isolation with injected clock/filesystem.
  • AI layers: classification = Sonnet (hard cases → Opus); generative distillation = Sonnet (explicitly not Haiku); orchestration = Opus.

Project Conventions

Code Style

  • Small composable single-responsibility classes; dependency injection for testability; immutable transforms where practical.
  • Scripts emit structured JSON and correct exit codes; deterministic and idempotent.

Architecture Patterns

  • Deterministic / AI split: the deterministic scanner gathers objective signals and a candidate shortlist; the AI pass classifies and distills.
  • Report schema is the linchpin: the machine report (per-file category, signals, op, op-type, safety tier, optional exact-edit, token estimate) is the contract every component consumes. It is designed and frozen first.
  • Operation taxonomy: each op is tagged op-type (deterministic | generative) and safety tier (auto | confirm). auto runs without prompt; confirm (destructive/subjective/generative) escalates for approval.
  • mtime guard: never apply a cached edit to a file changed since the check.

Testing Strategy

  • Assert external behavior at the highest deterministic seam — given an input doc tree / state file / report, the script produces correct structured output and exit code. Do not assert internal class structure.
  • The AI classification layer is pinned by golden examples (examples/golden/) plus invariants.md, per the reversion-protection pattern — not by unit assertions.

Git Workflow

  • Cleanup requires a clean/committed working tree, or auto-commits a WIP checkpoint first; each cleanup run lands as a single reviewable commit.
  • confirm-tier approvals are recorded to a decisions log.
  • No pushing or outbound/network actions — cleanup is local commits only.

Important Constraints

  • The SessionStart hook spends no AI tokens, never mutates, keeps timeout low (≤5s), and always exits 0 (never blocks the session).
  • State and the single most-recent report live under gitignored .dochygiene/; the scanner always self-excludes it.
  • Frozen/ignored files (hygiene: frozen frontmatter, .dochygiene-ignore, append-only logs) are never flagged.
  • Changing any behavioral invariant requires updating invariants.md and the golden examples, with explicit human approval.

External Dependencies

  • Claude Code plugin/hook runtime (hooks/hooks.json, systemMessage banner).
  • A local tokenizer approximation for the token estimator (no API token counting at check time).