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
11 changes: 11 additions & 0 deletions docs/conventions/detector-findings/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,17 @@ Notable changes to the detector-findings contract (SemVer). Changing a producer-
the coexistence obligations, or an enforceability verdict is a major bump; additive guidance or a new
adopter row is a minor bump; docs-only clarification is a patch.

## 2.5.1 — 2026-08-23

**Patch** — docs-only clarification of one adopter row's selection text. No producer-owned field's
rule moves, no coexistence obligation changes, and no enforceability verdict changes.

- **`rule-negation-without-positive` now describes paragraph-scoped accumulation (#3195).** The
row had inherited 0.21.1's "the line must close its own sentence" gate, which withheld every
hard-wrapped prohibition. The detector now accumulates a soft-wrapped sentence before classifying
it; the crosswalk row states that, and that a finding is attributed to the first physical line of
the triggering sentence. The other eight shapes stay line-scoped.

## 2.5.0 — 2026-08-23

**Minor under this contract's own rule** — a new adopter's rows are added; no producer-owned field's
Expand Down
2 changes: 1 addition & 1 deletion docs/conventions/detector-findings/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ side.
| ai-slop/audit/rule-stacked-hedging | Two stacked hedges in one phrase ("could potentially", "might possibly", and the catalog's list) on a prose line, outside the exempt contexts above. Mechanical phrase selection, no withholding verdict; counted declines. | A doubled hedge produces no wrong result and weakens no caller (CRITICAL fails). IMPORTANT fails: no stated rule, and redundant hedging has no nameable degradation trigger — the claim's uncertainty is stated either way. SUGGESTION holds: one hedge and two hedges both express the uncertainty; the finding is a redundancy preference. | SUGGESTION | No, remediated by `/ai-slop:audit fix` — choosing which hedge states the real uncertainty is a claim-strength judgment |
| claude-config/audit-instructions/rule-coercive-emphasis | A forced-compliance emphasis marker (`CRITICAL:`, `IMPORTANT:`, `You MUST`, `MANDATORY`, `ALWAYS use`, `NEVER skip`) on an instruction line, **body-scoped**: frontmatter is fenced out, as is any body line quoting a `'trigger phrase'` that appears in the file's own `description`. Case-sensitive — the all-caps marker IS the signal (threshold: any occurrence; the fired marker travels in the `Finding` cell). Mechanical byte-sequence selection with no withholding verdict, so the fail-safe criterion is met by construction; the criteria row's carve-outs (emphasis guarding a destructive or security gate, a stated hard precondition, a document *about* the pattern) are the model lane's, and every fence decline is counted in `## Surfaces`. | CRITICAL fails every limb: instruction prose computes nothing, so no concrete input, caller, or subsequent otherwise-correct change is made to produce a wrong, unsafe, or absent result — what the emphasis changes is how likely a trigger is to fire, which is a distribution over behavior rather than a determined result. IMPORTANT's degradation-with-a-named-trigger limb then matches, and the trigger is nameable rather than hypothetical: the first session in which the over-emphasized instruction fires on input its actual condition does not cover, spending a tool or skill invocation the condition never warranted. Official guidance supplies the mechanism, not merely a preference — prompting written against undertriggering "may now overtrigger", so this is a stated upstream rule the surface violates, not a choice among phrasings that all work. SUGGESTION's catch-all is therefore never reached: the alternatives do not both work, one overtriggers. | IMPORTANT | No — contained to `Location`, but the repair is a **downgrade, never a deletion**: the directive survives verbatim and only its volume changes, and deciding the normal-conditional phrasing that preserves the instruction is a rewrite judgment. Verbatim survival is asserted apart from **sentence-initial capitalization forced by dropping a leading wrapper** (`…MUST resolve` → `Resolve`) — a change the official source's own worked example makes too (`use` → `Use`); any other wording change means the remediation overreached |
| claude-config/audit-instructions/rule-blanket-tool-default | A blanket tool default ("default to using/running/calling", "if in doubt, use", "always use", "use even when") on an instruction line, under the identical body-scope fences and counted declines as the emphasis rule above. Mechanical phrase-list selection, case-folding, no withholding verdict. | The same walk, on the same mechanism and the same official source, which is why the two rules share a tier: a blanket default is the second arm of one defect — prompting written against undertriggering that no longer exists. CRITICAL fails identically (the phrasing determines no wrong result). IMPORTANT's degradation limb matches with the same nameable trigger, sharpened by the guide stating the consequence outright — "Instructions like 'If in doubt, use [tool]' will cause overtriggering" — so the cost is a named behavioral one, not a register preference, and SUGGESTION is never reached. | IMPORTANT | No — contained to `Location`, but the repair replaces the blanket with the targeted condition it stood in for; recovering that condition is judgment, and the instruction itself is kept, never deleted |
| docs-hygiene/audit-noise/rule-negation-without-positive | An **imperative** prohibition (`never`, `do not`, `don't`, `avoid`, `must not`, `should not`) opening the line, on a line that **closes its own sentence**, with no positive alternative stated in that sentence. Both scope gates are load-bearing and measured: without them the rule fired 1053 times on an 85-file sample (99% of all findings), with them 69 — descriptive prose, an already-paired mid-sentence cue, a hard-wrapped continuation and a table row are all out of scope. **Body-scoped**: `detect.sh` never leaves frontmatter, fenced code, exempt sections or opt-out-marked content, and the writer independently re-fences frontmatter and declines any body line quoting a `'trigger phrase'` that appears in the file's own `description` / `when_to_use`. Selection is per SENTENCE, on the backtick-unwrapped line, and case-folded (threshold: any occurrence; the fired prohibition travels in the `Finding` cell). | CRITICAL fails every limb: instruction prose computes nothing, so no concrete input, caller, or subsequent otherwise-correct change is made to produce a wrong, unsafe, or absent result — a prohibition without its positive leaves the target under-specified rather than determined wrong. IMPORTANT's **stated-rule** limb then matches directly, and does so without needing the degradation limb: `docs-hygiene:write-for-agents` "Prompt the positive" is a rule this fleet already adopted in writing — "Write what to do, not what to avoid" — so a bare prohibition is a surface violating a stated rule rather than one phrasing among several that all work. Official guidance supplies the same mechanism (*"Do not use markdown"* → *"Your response should be composed of smoothly flowing prose paragraphs"*). SUGGESTION's catch-all is therefore never reached. | IMPORTANT | No — contained to `Location`, but the repair rewrites to the positive target the prohibition implies, and recovering that target is a rewrite judgment: the constraint must survive while its framing changes. Matches the disposition of both `audit-instructions` rules for the same reason |
| docs-hygiene/audit-noise/rule-negation-without-positive | An **imperative** prohibition (`never`, `do not`, `don't`, `avoid`, `must not`, `should not`) opening the sentence, with no positive alternative stated in that sentence. Soft-wrapped sentences are accumulated across paragraph lines before classification; a finding is attributed to the first physical line of the triggering sentence. The imperative-only gate is load-bearing and measured: without it the rule fired 1053 times on an 85-file sample (99% of all findings) — descriptive prose, an already-paired mid-sentence cue, and a table row are all out of scope. **Body-scoped**: `detect.sh` never leaves frontmatter, fenced code, exempt sections or opt-out-marked content, and the writer independently re-fences frontmatter and declines any body line quoting a `'trigger phrase'` that appears in the file's own `description` / `when_to_use`. Selection is per SENTENCE, on the backtick-unwrapped accumulated paragraph, and case-folded (threshold: any occurrence; the fired prohibition travels in the `Finding` cell). The other eight shapes stay line-scoped. | CRITICAL fails every limb: instruction prose computes nothing, so no concrete input, caller, or subsequent otherwise-correct change is made to produce a wrong, unsafe, or absent result — a prohibition without its positive leaves the target under-specified rather than determined wrong. IMPORTANT's **stated-rule** limb then matches directly, and does so without needing the degradation limb: `docs-hygiene:write-for-agents` "Prompt the positive" is a rule this fleet already adopted in writing — "Write what to do, not what to avoid" — so a bare prohibition is a surface violating a stated rule rather than one phrasing among several that all work. Official guidance supplies the same mechanism (*"Do not use markdown"* → *"Your response should be composed of smoothly flowing prose paragraphs"*). SUGGESTION's catch-all is therefore never reached. | IMPORTANT | No — contained to `Location`, but the repair rewrites to the positive target the prohibition implies, and recovering that target is a rewrite judgment: the constraint must survive while its framing changes. Matches the disposition of both `audit-instructions` rules for the same reason |
| docs-hygiene/audit-noise/rule-negation-hard-guardrail | **Non-emitting.** A prohibition whose sentence also carries a safety-critical marker (`secret`, `credential`, `token`, `password`, `api key`, `force-push`, `--force`, `rm -rf`, `destructive`, `irreversible`, `data loss`, `production`, `security`, `vulnerab`, `rewrite history`) — a hard guardrail whose constraint a positive form cannot carry, where the prohibition IS the correct shape. | **Boundary ground, not a tier test** — the contract's "Findings that never reach a relay". This disposition is argued from the Boundary because a tier test can only ever return a tier, and the claim here is that the candidate is not a defect at all: the sibling `write-for-agents` rule itself preserves the negation "when the positive form genuinely loses the constraint". Reaching for a tier test to justify the non-emission would look argued while arguing nothing. **Fail-safe direction:** the carve-out requires its marker to be PRESENT on the sentence, so absence of that evidence selects the emitting rule above — an unresolved judgment can never withhold. The same holds for the paired-positive boundary (`instead`, `rather than`, `prefer`, `in place of`, `in favour of`) and the worked-example boundary (a `->` / `→` demonstration): each requires positive evidence, and both were checked rather than only the one easier to argue. | *(never reaches the relay)* | n/a — reported to the human only, and suppressed from the human report too, so one candidate carries one disposition on every surface this producer emits to |

The map is flat across the emitting rules on purpose — within each producer's set every emitting rule
Expand Down
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.21.6",
"version": "0.21.7",
"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 — 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
31 changes: 31 additions & 0 deletions plugins/docs-hygiene/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,36 @@
# Changelog — docs-hygiene plugin

## [0.21.7]

### Fixed

- **`audit-noise`'s `negation` shape now accumulates a soft-wrapped sentence
before classifying it (#3195).** 0.21.1's "the line must close its own
sentence" gate withheld every hard-wrapped prohibition: `Do not use markdown`
on one line with `in the summary body.` on the next never reached a verdict,
even though no positive is paired anywhere in that sentence. That is a silent
withhold — the one failure mode the detector-findings admission test asks this
rule set to avoid — and in a hard-wrapped repo it takes every prohibition long
enough to wrap.

`detect.sh` now joins paragraph lines before the `negation` classifier runs.
A wrapped sentence whose positive alternative sits on the continuation is not
flagged; a wrapped sentence with no positive is flagged and attributed to the
first physical line of that sentence (where the cue opens), so the fix action
lands on the instruction's start rather than its wrap continuation. Every
qualifying sentence in the paragraph is a finding (a later imperative is not
dropped after the first). Sibling list items are separate blocks, so a later
item cannot pair an earlier prohibition. Attribution offsets are taken on the
unwrapped join so an earlier inline-code span cannot pull the line number
forward. A search cursor walks the join so two identical sentences do not
both pin to the first occurrence's line. Findings print in line-number order
after the paragraph flush. The
other eight shapes stay line-scoped. Frontmatter, fenced code, exempt
sections and opt-out markers still bound the accumulation.

The "known limitation" bullet in `SKILL.md` is removed: the limitation is
gone, and the scope-gate bullet now describes the accumulation.

## [0.21.6]

### Fixed
Expand Down
Loading