From 807dcc8d9096fc527e0210fc3f0e3bb5c1ee27b5 Mon Sep 17 00:00:00 2001 From: jared Date: Wed, 15 Jul 2026 10:22:41 -0400 Subject: [PATCH] os-doc-hygiene: post-calibration follow-ups - Rules: 4 new lifecycle rules for OpenSpec trees (specs/** keep; changes/archive/*/ temporary retain 3 / 90d), root + plugins/* - Fill TBD Purpose placeholders in doc-check + doc-clean specs (the doc-check one was a check-run miss: sat under file_length thresholds) - Report header: "findings: N" + "cleared: K of M evaluated entries" (cleared no longer masquerades as files-scanned) - CLAUDE.md: vault user-guide pointer; fix stale .dochygiene/ state path to .cc-os/dochygiene/ (ADR-0027) Suite: 408 passed, 3 skipped. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01LAw7YxP71Fk6K9AHNaYPj2 --- .dochygiene-rules.json | 36 +++++++++++++++++++ plugins/os-doc-hygiene/CLAUDE.md | 6 +++- .../openspec/specs/doc-check/spec.md | 8 ++++- .../openspec/specs/doc-clean/spec.md | 9 ++++- .../os-doc-hygiene/scripts/report_builder.py | 4 +-- .../tests/test_report_builder.py | 4 +-- 6 files changed, 60 insertions(+), 7 deletions(-) diff --git a/.dochygiene-rules.json b/.dochygiene-rules.json index 36878e7..766c731 100644 --- a/.dochygiene-rules.json +++ b/.dochygiene-rules.json @@ -31,6 +31,42 @@ "source": "calibration pass #1 (lifecycle-aware-doc-hygiene)", "note": "Regenerable pytest cache. Judge noted a .gitignore entry may be preferable long-term." }, + { + "glob": "openspec/specs/**", + "lifetime": "keep", + "confirmed_by": "human", + "confirmed_on": "2026-07-15", + "source": "conversation 2026-07-15 (openspec lifecycle rules)", + "note": "Live OpenSpec capability specs — source of truth future changes diff against; never age out." + }, + { + "glob": "plugins/*/openspec/specs/**", + "lifetime": "keep", + "confirmed_by": "human", + "confirmed_on": "2026-07-15", + "source": "conversation 2026-07-15 (openspec lifecycle rules)", + "note": "Live OpenSpec capability specs — source of truth future changes diff against; never age out." + }, + { + "glob": "openspec/changes/archive/*/", + "lifetime": "temporary", + "retain_recent": 3, + "max_age_days": 90, + "confirmed_by": "human", + "confirmed_on": "2026-07-15", + "source": "conversation 2026-07-15 (openspec lifecycle rules)", + "note": "Archived change dirs are redundant once synced into specs/ and stay recoverable from git history; age out after a quarter." + }, + { + "glob": "plugins/*/openspec/changes/archive/*/", + "lifetime": "temporary", + "retain_recent": 3, + "max_age_days": 90, + "confirmed_by": "human", + "confirmed_on": "2026-07-15", + "source": "conversation 2026-07-15 (openspec lifecycle rules)", + "note": "Archived change dirs are redundant once synced into specs/ and stay recoverable from git history; age out after a quarter." + }, { "glob": "plugins/*/HANDOFF-*.md", "lifetime": "delete-once-served", diff --git a/plugins/os-doc-hygiene/CLAUDE.md b/plugins/os-doc-hygiene/CLAUDE.md index e1dde6c..392b0ab 100644 --- a/plugins/os-doc-hygiene/CLAUDE.md +++ b/plugins/os-doc-hygiene/CLAUDE.md @@ -7,6 +7,9 @@ zero-token) on `SessionStart`; checks and cleans on demand via skills. > Read `PRD.md` first — it is the source of truth for scope, decisions, and > rationale. This file is the build map. +> Vault user guide (nuance/mental-model, not a how-to): +> `~/Documents/SecondBrain/user-guide/os-doc-hygiene-user-guide.md`. + ## Lifecycle layer (2026-07-15) A rulebook layer sits on top of the scan/classify/clean core: global @@ -31,7 +34,8 @@ Severity scales with **injection frequency** — a stale line in `CLAUDE.md` (au 1. The `SessionStart` hook **only reminds** — it never runs analysis or mutates anything, and spends no AI tokens. All mutation is user-invoked. 2. Reminder **snoozes** (≤ once/day while stale) via `last_reminded`. -3. State lives **in-project** under gitignored `.dochygiene/`. No global index. +3. State lives **in-project** under gitignored `.cc-os/dochygiene/` (ADR-0027; + legacy `.dochygiene/` is fallback-read only). No global index. 4. **Report rollover**: keep only the latest report. The tool must not become the bloat it polices. 5. Cleanup is **git-safe**: clean/committed tree required (or auto WIP diff --git a/plugins/os-doc-hygiene/openspec/specs/doc-check/spec.md b/plugins/os-doc-hygiene/openspec/specs/doc-check/spec.md index d5f8af4..c8329b8 100644 --- a/plugins/os-doc-hygiene/openspec/specs/doc-check/spec.md +++ b/plugins/os-doc-hygiene/openspec/specs/doc-check/spec.md @@ -1,7 +1,13 @@ # doc-check Specification ## Purpose -TBD - created by archiving change add-check. Update Purpose after archive. + +Defines the `/os-doc-hygiene:check` command and the `check` skill it dispatches to: +the deterministic scan-classify-finalize-validate pipeline that turns a project's +docs into a schema-valid machine + human report pair, including rulebook-driven +scanning, judgment-only Sonnet classification, the model-free finalize pass that +authors safety-critical fields, and validation-gated report writes. + ## Requirements ### Requirement: `/hygiene` Command Surface diff --git a/plugins/os-doc-hygiene/openspec/specs/doc-clean/spec.md b/plugins/os-doc-hygiene/openspec/specs/doc-clean/spec.md index 764bcc6..1019645 100644 --- a/plugins/os-doc-hygiene/openspec/specs/doc-clean/spec.md +++ b/plugins/os-doc-hygiene/openspec/specs/doc-clean/spec.md @@ -1,7 +1,14 @@ # doc-clean Specification ## Purpose -TBD - created by archiving change add-clean. Update Purpose after archive. + +Defines the `clean` skill and patch applier that consume a validated `check` +report and apply its findings git-safely: per-file transactional edits guarded +by content hashes, safety-tier gating that escalates destructive or generative +ops for confirmation, tracked-only true deletion under the lifecycle tier +matrix, and a single reviewable commit per run (with `sweep` composing `check` +then `clean`). + ## Requirements ### Requirement: Per-File Transaction with Content-Hash Guard diff --git a/plugins/os-doc-hygiene/scripts/report_builder.py b/plugins/os-doc-hygiene/scripts/report_builder.py index eb690e4..1af1a57 100644 --- a/plugins/os-doc-hygiene/scripts/report_builder.py +++ b/plugins/os-doc-hygiene/scripts/report_builder.py @@ -572,8 +572,8 @@ class ReportBuilder: lines.append(f"- generated_at: {generated_at}") lines.append(f"- scope: {', '.join(scope_globs) if scope_globs else '(default)'}") lines.append(f"- files scanned: {scan.get('files_scanned', 0)}") - lines.append(f"- candidates: {len(entries)}") - lines.append(f"- cleared: {len(cleared)}") + lines.append(f"- findings: {len(entries)}") + lines.append(f"- cleared: {len(cleared)} of {len(shortlist)} evaluated entries") lines.append("") stale = [e for e in entries if e["category"].get("class") == "stale"] diff --git a/plugins/os-doc-hygiene/tests/test_report_builder.py b/plugins/os-doc-hygiene/tests/test_report_builder.py index 59b8e3e..a126c3e 100644 --- a/plugins/os-doc-hygiene/tests/test_report_builder.py +++ b/plugins/os-doc-hygiene/tests/test_report_builder.py @@ -367,8 +367,8 @@ class TestClearedFiles: result = _build(doc_tree, scan_artifact, _proposals()) md = result["human_report"] # 7 shortlisted, 6 entries → 1 cleared - assert "candidates: 6" in md - assert "cleared: 1" in md + assert "findings: 6" in md + assert "cleared: 1 of 7 evaluated entries" in md assert "docs/clean.md" in md