Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion plugins/docs-hygiene/.claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"$schema": "https://json.schemastore.org/claude-code-plugin-manifest.json",
"name": "docs-hygiene",
"version": "0.18.3",
"version": "0.19.0",
"description": "Documentation-hygiene toolkit: compress (flavor-trim markdown with a semantic-diff safety net), audit-noise (classify markdown noise), extract-ssot (deduplicate repeated content into a single source of truth), audit-encapsulation (detect citations into skill-private surfaces), rename-references (sweep stale references after renames), audit-derivability (classify whether a whole document earns its existence \u2014 could a fresh agent re-derive it from the code?), audit-progressive-disclosure (grade instruction files against a load-tier model for split opportunities and hub/spoke disclosure defects), write-for-agents (authoring-time doctrine that fires while agent-consumed markdown is being written), and write-for-humans (the same moment for the other reader — end-user READMEs, RFCs, release notes and guides — resolving the consuming project's own style guide first).",
"author": {
"name": "Melodic Software",
Expand Down
79 changes: 79 additions & 0 deletions plugins/docs-hygiene/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,84 @@
# Changelog — docs-hygiene plugin

## [0.19.0]

### Changed

- **`extract-ssot` reports duplication at every multiplicity; the Rule of Three now gates
artifact creation, not reporting (#3114).** One threshold had been doing two jobs. Gating
*creation of a new SSOT artifact* at three instances is what the cited evidence supports
(~19% failure on curated skills, ~50% on practitioner-authored ones) — but the same number
was also deciding whether the user heard about the duplication at all, so two real defect
classes were discarded in silence: a consumer inlining a recap of an SSOT that already
exists (N=1), and two files asserting the same contract with no declared owner, drifting
apart (N=2).

`identify` now rosters candidates in three labelled buckets with the instance count shown
per candidate: **N=1** (inline recap of an existing SSOT), **N=2** (source-of-truth
bifurcation risk), **N≥3** (Rule of Three met). `verify` Gate 1 assigns that bucket from the
full-reproduction count and emits it in a new `bucket:` output field;
`REFUSE-rule-of-three-fails` is retained as the reason code but now fires only against an
*artifact-creating* remedy (`rule-file` / `new-skill` / `new-action`) below three — never
against reporting, and never against the non-abstracting remedies. Gate 4 gains the
intentional-vs-accidental split: a deliberate two-audience bifurcation still refuses, while
accidental bifurcation with no declared owner PROCEEDs as the N=2 bucket's own defect.

**Lowering the reporting threshold does not lower the abstraction threshold**, because the
sub-three buckets offer only remedies that edit files already present. The 6-test gate is
untouched and still governs every N≥3 extraction.

### Added

- **Two non-abstracting remedies for `extract-ssot` (#3114).** `normalize-wording` (align
divergent phrasings onto the canonical or agreed wording in place) and `name-an-owner`
(declare one existing file the canonical owner and make the other cite it). Neither creates
a file. They join `trim-to-citation` and `edit-existing-rule` in the suggested-output
vocabulary, and they are what make a rule-of-one reporting default safe.
- **Five flags on the `identify` / `batch` surfaces (#3114).** `--min-instances=<N>` (default
`1`; `--min-instances=3` is the regression guard that reproduces the pre-bucket behavior
exactly), `--buckets=<list>`, `--fix` (applies only `trim-to-citation` and
`normalize-wording`, never creates an artifact), `--dry-run`, and `--yes`. Bare invocation
stays read-only: it reports the buckets and stops.
- **Four eval expectations and two new eval cases** covering the N=1 bucket and the
`--min-instances=3` regression guard; the former `refuse-below-rule-of-three` case is now
`two-instances-bucketed-no-new-artifact` and asserts both halves — the candidate is
rostered, and no new artifact is proposed below three.

### Fixed

Four defects in the bucket design above, surfaced by automated review of the shipping PR
(#3114):

- **`trim-to-citation` is part of the N=2 permitted-remedy set.** The bucket contract and the
`verify` permitted-remedies schema had listed only `edit-existing-rule` / `name-an-owner` /
`normalize-wording`, none of which removes two redundant recaps when the canonical home
already exists and is complete — even though the routing rules already prescribed
`trim-to-citation` for that case. N=2 is now described as the two shapes it actually covers:
two consumers recapping an existing home (trim both to citations), or two files asserting one
contract with no declared owner (name one). `REFUSE-rule-of-three-fails` is now stated
positively — it fires only against `rule-file` / `new-skill` / `new-action` below N≥3 —
instead of enumerating the remedies it spares, which is what let the set drift incomplete.
- **Sibling routing thresholds match the new entry point.** `/docs-hygiene:compress`,
`/docs-hygiene:audit-noise`, `/docs-hygiene:audit-derivability`,
`/docs-hygiene:write-for-agents`, and `/docs-hygiene:write-for-humans` each routed cross-file
duplication to `/docs-hygiene:extract-ssot` only at 3+ files, so the sub-three buckets were
unreachable from the flows that feed them. They now route repeated content at any multiplicity;
creating a NEW artifact still waits for the third instance. `/docs-hygiene:compress`'s
`context/integration.md` boundary note, which restated the old 3+ threshold in prose, was
reconciled with the same rule.
- **`verify` Gate 1 counts semantic clusters by reading, not phrase grep.** A paraphrase cluster
(`identify` forms c2/i) shares no verbatim ≥8-word phrase, so a phrase grep found only the
file the phrase was lifted from — assigning a real N=2/N≥3 cluster to N=1 and, with no prior
canonical, returning `REFUSE-not-found`, after which the mandatory `batch` verify filter
dropped the candidate. Gate 1 now counts by evidence shape (phrase grep for literal clusters,
the reading-derived canonical-truth roster for semantic ones) and gained a semantic Tier 0
evidence form; Gate 0's `REFUSE-not-found` fires only when neither grep nor reading resolves
any instance.
- **The `batch` per-dispatch verdict enum covers completed non-abstracting remedies.** Step 8's
schema offered only `EXTRACTED` / `REFUSED-*` / `DEFERRED`, none of which fits a sub-three
bucket that finished its work without creating an artifact; it gains `REMEDIED-{remedy}`, so
the schema and the Step 10 batch-summary example agree.

## [0.18.3]

### Changed
Expand Down
2 changes: 1 addition & 1 deletion plugins/docs-hygiene/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ and authoring axes of doc upkeep.
|---|---|
| `/docs-hygiene:compress` | Tightens markdown by dropping flavor (filler, hedging, articles) while preserving all content, behind a mandatory fresh-context semantic-diff audit that reverts any semantic loss. Supports an optional `caveman` plugin backend (`/caveman:compress`) with a built-in in-session fallback. |
| `/docs-hygiene:audit-noise` | Read-only classifier for five markdown noise shapes (historical citations, ghost refs to ephemeral working directories, "why this file exists" preambles, hard-coupled consumer lists, scope/loading meta-commentary) with tiered findings and per-shape treatment guidance. |
| `/docs-hygiene:extract-ssot` | Deduplicates content repeated across 3+ files into a single named source of truth and migrates call sites to cite it by headingwith refuse-fast verification gates (Rule of Three, Tier-0 evidence) so weak clusters are rejected instead of extracted. |
| `/docs-hygiene:extract-ssot` | Deduplicates repeated content into a single named source of truth and migrates call sites to cite it by heading. Reports duplication at every multiplicity in three labelled buckets — a lone recap of an existing SSOT, a drifting pair with no declared owner, and clusters that meet the Rule of Three — while refuse-fast verification gates (Rule of Three, Tier-0 evidence) keep *creating* a new artifact reserved for 3+ instances; below that, only non-abstracting remedies are offered. |
| `/docs-hygiene:audit-encapsulation` | Detects external citations reaching into skill-private surfaces inside `.claude/skills/<name>/` (private subdirectories, heading anchors, schema files) and routes each violation to a remediation path. Ships its own public-surface contract reference. |
| `/docs-hygiene:rename-references` | Sweeps stale references after renames — the forms plain token grep misses: slash-command tokens, relative paths from moved files, frontmatter chains and globs — via a 12-form pattern library with audit, half-rename detection, and apply modes. |
| `/docs-hygiene:audit-derivability` | Read-only, document-level worth classifier: could a fresh agent re-derive this whole document from the code, config, and structure? Weighs derivability, re-derivation cost, drift risk, and fact ownership into a verdict (delete, convert-to-pointer, keep-as-derivation-cache, keep-owns-facts), splits it by audience, and confirms load-bearing deletions with a fresh-context spot-test. Where the other five trim *inside* a doc, this decides whether the doc should exist. |
Expand Down
2 changes: 1 addition & 1 deletion plugins/docs-hygiene/skills/audit-derivability/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ After the ledger, OFFER to route actionable verdicts (delete / convert-to-pointe
## What this skill is NOT

- **Not `/docs-hygiene:audit-noise`.** That classifies line-level noise *inside* a document worth keeping. This decides whether the whole document is worth keeping. A doc can pass audit-derivability (`keep-owns-facts`) and still have noise lines for audit-noise to trim.
- **Not `/docs-hygiene:extract-ssot`.** That deduplicates a unit repeated across 3+ files into one home. Derivability is re-derivation from CODE/config/structure, not from another markdown file. A doc that duplicates *another doc* is extract-ssot's; a doc that restates *the code* is this skill's.
- **Not `/docs-hygiene:extract-ssot`.** That deduplicates a unit repeated across files into one home, at any multiplicity (a new home is created only at 3+). Derivability is re-derivation from CODE/config/structure, not from another markdown file. A doc that duplicates *another doc* is extract-ssot's; a doc that restates *the code* is this skill's.
- **Not `/docs-hygiene:compress`.** That trims prose flavor within a doc that stays. This deletes or repoints whole docs.
- **Not a doc-drift / staleness detector.** Those ask "does this doc still match the code?" This asks "should this doc exist even when it is perfectly accurate?" — a currently-correct doc can still be dead weight because it is trivially re-derivable and carries drift risk.
- **Not a doc generator or an Edit operation.** It recommends; the author acts.
Expand Down
2 changes: 1 addition & 1 deletion plugins/docs-hygiene/skills/audit-noise/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ Total: <N> file(s) audited, <T1> Tier 1, <T2> Tier 2, <T3> Tier 3 findings.
- **Not `/docs-hygiene:compress`.** The sibling `/docs-hygiene:compress` owns FLAVOR (filler, hedging, articles, redundant restatement); `/docs-hygiene:audit-noise` owns NOISE (the five shapes above). Different concerns; both may apply to the same target iteratively.
- **Not a markdown linter.** Structural GFM conventions belong to the repo's markdown linter (e.g. markdownlint-cli2); `/docs-hygiene:audit-noise` is semantic noise classification.
- **Not an Edit operation.** Read-only: it surfaces findings; the author applies treatments.
- **Not a content deduplicator.** When the noise is the same concept repeated across 3+ files, that is the sibling `/docs-hygiene:extract-ssot`'s territory.
- **Not a content deduplicator.** When the noise is the same concept repeated across files, that is the sibling `/docs-hygiene:extract-ssot`'s territory at any multiplicity — sub-three repetition lands in its non-abstracting buckets, and only minting a new SSOT artifact waits for 3+.

## Sources

Expand Down
2 changes: 1 addition & 1 deletion plugins/docs-hygiene/skills/compress/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ Observed failure points — each traces to a real incident; grown iteratively.
- **Not a code-comment compressor.** Out of scope
- **Not a `/code-review` / `/simplify` shadow.** The bundled `/code-review` and `/simplify` skills review code changes; `/docs-hygiene:compress` rewrites markdown prose. Different concerns
- **Not `/docs-hygiene:audit-noise`.** `/docs-hygiene:compress` owns FLAVOR (filler, hedging, articles, redundant restatement). `/docs-hygiene:audit-noise` owns NOISE classification (historical citations, ghost refs, "Why this file exists" preambles, hard-coupled enumerated consumer lists) per its own taxonomy. Different concerns; both may apply to the same target iteratively
- **Not a content-relocation / cite-don't-recap tool.** When an inline passage recaps detail that already lives in a cited single source of truth (another doc or rule), condensing it is content RELOCATION, not flavor removal — the mandatory semantic-diff net sees the words gone from THIS file and reverts them as SEMANTIC LOSS, blind to the SSOT. Apply "reference, don't duplicate" as a MANUAL editorial pass (verify the cited SSOT actually holds the detail first — an unread pointer is an unverified claim); use `/docs-hygiene:extract-ssot` when the duplicated cluster spans 3+ files
- **Not a content-relocation / cite-don't-recap tool.** When an inline passage recaps detail that already lives in a cited single source of truth (another doc or rule), condensing it is content RELOCATION, not flavor removal — the mandatory semantic-diff net sees the words gone from THIS file and reverts them as SEMANTIC LOSS, blind to the SSOT. Apply "reference, don't duplicate" as a MANUAL editorial pass (verify the cited SSOT actually holds the detail first — an unread pointer is an unverified claim); route the duplicated cluster to `/docs-hygiene:extract-ssot` at any multiplicity (it rosters rule-of-one / -two / -three buckets; only extraction into a NEW artifact waits for 3+ files)

## Sources

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ How `/docs-hygiene:compress` composes with sibling skills in this plugin and wit
| `/docs-hygiene:audit-encapsulation` | parallel concern | No invocation either direction. `/docs-hygiene:audit-encapsulation` detects external citations into skill-private surfaces; `/docs-hygiene:compress` edits the markdown targets it is given. The two skills do not interact at runtime |
| A pre-PR quality gate (if the consumer has one) | calls `/docs-hygiene:compress` | When a pre-PR check surfaces uncommitted `.md` files in the working tree, the user may invoke `/docs-hygiene:compress` (empty arg auto-detects) before PR prep. `/docs-hygiene:compress` does not auto-trigger from any gate; user-gated |

Boundaries with the other bundled siblings — `/docs-hygiene:audit-noise` (noise classification, not flavor) and `/docs-hygiene:extract-ssot` (content relocation across 3+ files, not flavor) — are defined in `../SKILL.md` "What this skill is NOT".
Boundaries with the other bundled siblings — `/docs-hygiene:audit-noise` (noise classification, not flavor) and `/docs-hygiene:extract-ssot` (content relocation at any multiplicity, not flavor — it rosters rule-of-one / -two / -three buckets; only extraction into a NEW artifact waits for 3+ files) — are defined in `../SKILL.md` "What this skill is NOT".

## Public-surface invocation forms

Expand Down
Loading