Skip to content

feat(docs-hygiene): bucket extract-ssot candidates by multiplicity, gate artifact creation not reporting (0.19.0) - #3142

Merged
kyle-sexton merged 5 commits into
mainfrom
claude/work-items-integration-b0fszs
Aug 23, 2026
Merged

feat(docs-hygiene): bucket extract-ssot candidates by multiplicity, gate artifact creation not reporting (0.19.0)#3142
kyle-sexton merged 5 commits into
mainfrom
claude/work-items-integration-b0fszs

Conversation

@kyle-sexton

@kyle-sexton kyle-sexton commented Aug 23, 2026

Copy link
Copy Markdown
Contributor

Closes #3114

Summary

The Rule of Three was doing two jobs in /docs-hygiene:extract-ssot: gating creation of a new SSOT artifact (correct — the failure mode the cited ~19%/~50% extraction-failure evidence is about) and gating whether duplication is reported at all (wrong). Two real defect classes never reached the user: 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 independently (N=2). This PR separates the two gates: reporting happens at every multiplicity, artifact creation still refuses below three.

Fix

  • identify now rosters candidates in three labelled buckets — N=1 (inline recap of an existing SSOT; admitted only when a canonical home exists), N=2 (source-of-truth bifurcation risk), N≥3 — showing bucket membership and instance count per candidate. Sub-three buckets offer only non-abstracting remedies; rule-file / new-skill / new-action stay reserved for N≥3 behind the unchanged 6-test gate.
  • Two new non-abstracting remedies: normalize-wording (align divergent phrasings in place) and name-an-owner (declare one existing file canonical, make the other cite it). Neither creates a file.
  • verify Gate 1 assigns the bucket (new bucket: + permitted-remedies: output fields) instead of refusing on count; REFUSE-rule-of-three-fails fires only against an artifact-creating remedy below three. Gate 4 splits intentional two-audience bifurcation (still refuses) from accidental bifurcation (the N=2 bucket's own defect), making anti-pattern fix(markdown-formatter): harden hook + simplify plumbing #11 reachable in practice.
  • Five flags on the identify/batch surfaces, documented in the action router and argument-hint: --min-instances (default 1; =3 is the regression guard reproducing pre-bucket behavior exactly), --buckets, --fix (non-abstracting remedies only, never creates an artifact), --dry-run, --yes. Bare invocation stays read-only.
  • context/decision-framework.md documents the reporting-gate vs abstraction-gate split; the frontmatter description no longer promises refusal below three; evals gain N=1, N=2, and --min-instances=3 regression cases plus explicit no-new-artifact-below-three expectations (evals 1, 2, 8, 9).
  • docs-hygiene 0.18.30.19.0 with a matching CHANGELOG entry.

Verification

  • npx markdownlint-cli2 over the 8 changed markdown files — 0 issues.
  • typos and editorconfig-checker over the changed surface — clean.
  • check-jsonschema against the claude-code-plugin-manifest schema for plugin.json — valid; manifest duplicate-key detector — clean.
  • scripts/check-changelog-parity.sh in all four modes (--check, --check-bump origin/main, --check-order, --check-preserved origin/main) — all pass.
  • evals.json parses (jq/json.tool) and keeps the existing entry shape; ids 1–9 enumerate in file order.
  • Fresh-context verifier pass over the diff against all 11 issue acceptance criteria plus internal-consistency and version-parity checks: 13/13 PASS (e.g. actions/verify.md Gate 1 assigns rather than refuses; no surviving text routes a sub-three candidate to an artifact-creating output).

Related

🤖 Generated with Claude Code

https://claude.ai/code/session_01FdD9bt2ckihbEiS3K4nEgP


Generated by Claude Code

…ate artifact creation not reporting (0.19.0)

The Rule of Three was doing two jobs in extract-ssot: gating creation of a
new SSOT artifact (correct, and what the cited failure-rate evidence is
about) and gating whether duplication was reported to the user at all
(wrong). 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 (N=2).

identify now rosters candidates in three labelled buckets (N=1, N=2, N>=3)
with the instance count per candidate, and admits an N=1 candidate only
when an existing canonical home is what the site recaps instead of cites.
verify Gate 1 assigns that bucket 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 below three. Gate 4 splits
intentional two-audience bifurcation (still refuses) from accidental
bifurcation with no declared owner (the N=2 bucket's own defect).

Adds two non-abstracting remedies, normalize-wording and name-an-owner,
and five flags on the identify/batch surfaces: --min-instances (default 1;
=3 is the regression guard reproducing the pre-bucket behavior), --buckets,
--fix, --dry-run, --yes. Bare invocation stays read-only. The 6-test gate
is untouched and still governs every N>=3 extraction.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FdD9bt2ckihbEiS3K4nEgP
@claude

claude Bot commented Aug 23, 2026

Copy link
Copy Markdown
Contributor

Claude finished @kyle-sexton's task in 1m 6s —— View job


Security review (/review:security-review)

  • Gather context (PR diff, files, custom instructions)
  • Run /review:security-review per custom instructions
  • Post findings

No security review performed — skip gate triggered.

Per the skip gate in /review:security-review: "Change has no security-relevant surface after reading the diff."

All 10 changed files are markdown documentation and JSON config for the docs-hygiene plugin's extract-ssot skill:

  • plugin.json (version bump), CHANGELOG.md, README.md
  • skills/extract-ssot/{SKILL.md,actions/*.md,context/*.md,evals/evals.json}

I reviewed the full diff (gh pr diff 3142) and specifically checked the action files (identify.md, batch.md, verify.md) since they define subagent-dispatch instructions and contain shell snippets (git ls-files, git check-ignore, etc.). These are read-only, internal, git-tracked-file operations with no untrusted external input, no execution sinks, no auth/access-control logic, no secrets/token handling, and no GitHub Actions workflow changes (no pull_request_target, workflow_run, permissions:, or ${{ }} template usage).

This is prose/prompt-authoring content for a documentation-hygiene skill — no exploitable code path exists in this diff. No findings to report.

@github-actions

github-actions Bot commented Aug 23, 2026

Copy link
Copy Markdown

Last security-reviewed head: 9e721c75720d51d91726d64d1f433820b5f46a93. On the next push, the relevance gate compares only the commits since this SHA; delete this comment to force a full re-review.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: b442322c98

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread plugins/docs-hygiene/skills/extract-ssot/actions/verify.md
Comment thread plugins/docs-hygiene/skills/extract-ssot/actions/identify.md Outdated
Comment thread plugins/docs-hygiene/skills/extract-ssot/SKILL.md
…ds, and semantic-cluster counting (0.19.0)

Three defects in the multiplicity-bucket design shipped in b442322, each
surfaced by automated review of the PR.

1. `trim-to-citation` was missing from the N=2 permitted-remedy set in the
   bucket contract and in verify's permitted-remedies schema, even though the
   routing rules already prescribed it for "N=2, home exists". A candidate was
   therefore constrained to remedies that cannot remove two redundant recaps of
   an already-complete canonical home. The N=2 description now covers both of
   its shapes — two consumers recapping an existing home (trim both to
   citations) and two files asserting one contract with no declared owner (name
   one). `REFUSE-rule-of-three-fails` is restated positively (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.

2. The sibling boundaries in compress, audit-noise, audit-derivability, and
   write-for-agents still routed cross-file duplication to extract-ssot only at
   3+ files, leaving the sub-three buckets 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.

3. verify Gate 1 counted every cluster by discriminating-phrase grep. A semantic
   cluster (identify forms c2/i) shares no verbatim >=8-word phrase, so the grep
   found only the file the phrase came from — assigning a real N=2/N>=3 cluster
   to N=1 and, with no prior canonical, returning REFUSE-not-found, after which
   batch's mandatory verify filter dropped it. Gate 1 now counts by evidence
   shape and gained a semantic Tier 0 evidence form; Gate 0's REFUSE-not-found
   fires only when neither grep nor reading resolves an instance.

The core invariant is unchanged: no artifact-creating output below N>=3, and
trim-to-citation / normalize-wording / name-an-owner / edit-existing-rule never
create a file. Version stays 0.19.0; the CHANGELOG entry is extended.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FdD9bt2ckihbEiS3K4nEgP
@claude

claude Bot commented Aug 23, 2026

Copy link
Copy Markdown
Contributor

Claude finished @kyle-sexton's task in 47s —— View job


Security review (/review:security-review)

  • Gather context (PR diff, files, custom instructions)
  • Run /review:security-review per custom instructions
  • Post findings

No security review performed — skip gate triggered.

Per the skip gate in /review:security-review: "Change has no security-relevant surface after reading the diff."

The prior review (head b442322) already cleared this PR — all changed files are markdown documentation and JSON config for the docs-hygiene plugin's extract-ssot skill. Per the relevance-gate note, I diffed only the commits since that reviewed head:

git diff b442322..c3e11bc — 10 files changed, all markdown (CHANGELOG.md, five sibling SKILL.md routing-threshold tweaks, extract-ssot/SKILL.md, extract-ssot/actions/{batch,identify,verify}.md, context/decision-framework.md). This commit addresses the two Codex review threads on this PR (semantic-cluster counting in verify.md Gate 0/1, trim-to-citation added to the N=2 permitted-remedy set) plus the sibling-routing threshold fix.

I read the full diff, including the verify.md/identify.md/batch.md changes since these define subagent-dispatch instructions. Same conclusion as before: no execution sinks, no auth/access-control logic, no secrets/token handling, no untrusted external input, and no GitHub Actions workflow changes (permissions:, pull_request_target, workflow_run, ${{ }} template usage — none present). This is prose/prompt-authoring content for a documentation-hygiene skill.

No findings to report.

…r-humans and compress integration note (0.19.0)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FdD9bt2ckihbEiS3K4nEgP
@claude

claude Bot commented Aug 23, 2026

Copy link
Copy Markdown
Contributor

Claude finished @kyle-sexton's task in 50s —— View job


Security review (/review:security-review)

  • Gather context (PR diff, files, custom instructions)
  • Run /review:security-review per custom instructions
  • Post findings

No security review performed — skip gate triggered.

Per the skip gate in /review:security-review: "This head already has a successful security review that still applies" combined with "Change has no security-relevant surface after reading the diff."

The prior review (head c3e11bc) already cleared this PR. Per the relevance-gate note, I diffed only the commit since that reviewed head:

git diff c3e11bc..c3d51a1 — 1 commit, 2 files changed, 4 insertions / 2 deletions, both prose-only edits to markdown skill documentation:

Neither file contains executable code, shell snippets, or GitHub Actions workflow configuration — no execution sinks, no auth/access-control logic, no secrets/token handling, no untrusted external input, no permissions:, pull_request_target, workflow_run, or ${{ }} template usage. This is prose-only documentation content with no exploitable code path.

No findings to report.

@claude

claude Bot commented Aug 23, 2026

Copy link
Copy Markdown
Contributor

Claude finished @kyle-sexton's task in 2m 45s —— View job


Code review (/review:code-review)

  • Gather context (PR diff, files, custom instructions)
  • Invoke /review:code-review per custom instructions
  • Post findings

Note: the review:code-review Skill invocation errored out in this environment (returned <error>Execute skill: review:code-review</error> on repeated attempts with no further detail). I proceeded with the equivalent manual review — full diff read (origin/main...HEAD restricted to plugins/docs-hygiene/, 16 files, ~1180 diff lines) — scoped to correctness and maintainability per that lane's mandate (security is out of scope here; the security lane already cleared this PR twice).

This PR is already in good shape: both prior Codex P1 findings (N=2 trim-to-citation omission, semantic-cluster miscounting in verify.md Gate 1) and the P2 sibling-routing-threshold finding are fixed in the current head, and the fixes are internally consistent across identify.md, verify.md, batch.md, SKILL.md, decision-framework.md, and anti-patterns.md. evals.json parses cleanly with ids 1–9 in file order.

1 finding, posted inline:

  • P2 — plugins/docs-hygiene/CHANGELOG.md:61-66 — the "Sibling routing thresholds match the new entry point" bullet enumerates only compress, audit-noise, audit-derivability, and write-for-agents. The final commit (c3d51a1) applied the identical fix to write-for-humans/SKILL.md too, but the CHANGELOG bullet was never updated to name it — so the changelog now under-reports its own change set, on a PR whose subject is exactly this class of drift.
    Permalink:
    - **Sibling routing thresholds match the new entry point.** `/docs-hygiene:compress`,
    `/docs-hygiene:audit-noise`, `/docs-hygiene:audit-derivability`, and
    `/docs-hygiene:write-for-agents` 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.

Everything else checked out: bucket-permitted-remedy tables agree verbatim across identify.md, verify.md, SKILL.md, and decision-framework.md; REFUSE-rule-of-three-fails is now stated positively everywhere it's referenced; the non-abstracting invariant (nothing below N≥3 creates an artifact) has no counter-example in the diff; batch.md's verify-filter no longer drops semantic sub-three candidates; version bump (0.18.3 → 0.19.0) and CHANGELOG entry ordering are present and match plugin.json.
· branch claude/work-items-integration-b0fszs

Comment thread plugins/docs-hygiene/CHANGELOG.md Outdated
@github-actions

github-actions Bot commented Aug 23, 2026

Copy link
Copy Markdown

Claude has reviewed this PR 3 times. The lane skips further automatic reviews after 5; deleting this comment resets the count.

…uting-threshold sweep (0.19.0)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FdD9bt2ckihbEiS3K4nEgP
@claude

claude Bot commented Aug 23, 2026

Copy link
Copy Markdown
Contributor

Claude finished @kyle-sexton's task in 2m 1s —— View job


Code review (/review:code-review)

  • Gather context (PR diff, files, custom instructions)
  • Invoke /review:code-review per custom instructions
  • Post findings

Note: the review:code-review Skill invocation errored out again in this environment (<error>Execute skill: review:code-review</error> on repeated attempts). Proceeded with the equivalent manual review — full diff read (origin/main...HEAD restricted to plugins/docs-hygiene/, 16 files) scoped to correctness and maintainability per that lane's mandate (security is out of scope; the security lane already cleared this PR).

This is a re-review at head f4b6305 (prior review was posted at head c3d51a1). The only commit since then (f4b6305, "changelog sibling enumeration matches the full routing-threshold sweep") fixes the sole P2 finding from the previous review — the CHANGELOG "Sibling routing thresholds" bullet now names /docs-hygiene:write-for-humans alongside the other four siblings. Confirmed fixed.

I re-read the full diff end to end (not just the incremental commit) to catch anything the incremental reviews missed: identify.md, verify.md, batch.md, SKILL.md, decision-framework.md, anti-patterns.md, evals.json, the five sibling routing files, plugin.json/README.md/CHANGELOG.md. Bucket tables, permitted-remedy sets, and REFUSE-rule-of-three-fails phrasing agree verbatim across identify.md, verify.md, SKILL.md, and decision-framework.md; evals.json parses cleanly with ids 1–9 sequential in file order; version bump (0.18.3 → 0.19.0) is consistent across plugin.json and the CHANGELOG.

1 new finding, posted inline:

  • P2 — plugins/docs-hygiene/skills/extract-ssot/actions/batch.md:230 — the new N=2 example row in the Step 10 batch-summary table uses OWNER-NAMED as a verdict value, but Step 8 "Per-dispatch capture" (line 191, unchanged by this PR) still defines the subagent verdict enum as EXTRACTED | REFUSED-{reason} | DEFERRED. None of those three values actually fits a completed non-abstracting remedy (name-an-owner, trim-to-citation, normalize-wording, edit-existing-rule never create an artifact, so EXTRACTED overclaims). A subagent following Step 8 as written has no correct value to emit for exactly the new outcome this PR introduces.
    Permalink:
    ## Step 8 — Per-dispatch capture
    Each subagent return value contains:
    ```yaml
    candidate: <name>
    verdict: EXTRACTED | REFUSED-{reason} | DEFERRED
    files-modified: [...]
    new-lessons: [free-form patterns observed]
    sanity-check-evidence: [...]
    ```
    `new-lessons` is the field where empirical patterns surface for the orchestrator to codify.
    ## Step 9 — Lesson append
    After all waves complete, the orchestrator (main session) reviews `new-lessons` from all dispatches:
    - Cross-check against existing lessons.md (avoid duplicate Lesson N entries)
    - For genuinely novel patterns: append `## Lesson N+1: <name>` per `context/lessons.md` "Append guidance for future batches"
    - The Source field references THIS batch's audit log
    - The Encoded-in field documents which downstream artifacts (anti-patterns.md, verify gates) should consume the new lesson
    Subagent-reported lessons are synthesis until the orchestrator re-verifies them with its own grep — verify each novel-lesson claim before the lessons.md append.
    If no novel patterns surface, no append. Don't force.
    ## Step 10 — Batch audit log
    Append to the working notes:
    ```markdown
    ---
    type: batch
    date: <ISO-8601 UTC, e.g. 2026-06-04T14:30:00Z>
    batch-size: <N>
    ---
    ## Batch summary
    | # | Candidate | Bucket | Verify | Verdict | Wave | Files modified |
    |---|-----------|--------|--------|---------|------|----------------|
    | 1 | C1 | N≥3 | PROCEED | EXTRACTED | 1 | path1, path2 |
    | 2 | C2 | N≥3 | PROCEED | REFUSED-low-roi | 1 | (none) |
    | 3 | C3 | N=1 | REFUSE-already-cites-canonical | (skipped) | (n/a) | (none) |
    | 4 | C4 | N=2 | PROCEED | OWNER-NAMED | 2 | path3, path4 |
    | ... | | | | | | |

Everything else checked out — no other internal-consistency gaps found across the diff.
· branch claude/work-items-integration-b0fszs

Comment thread plugins/docs-hygiene/skills/extract-ssot/actions/batch.md Outdated
…g remedies (0.19.0)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FdD9bt2ckihbEiS3K4nEgP
@claude

claude Bot commented Aug 23, 2026

Copy link
Copy Markdown
Contributor

Claude finished @kyle-sexton's task in 49s —— View job


Security review (/review:security-review)

  • Gather context (PR diff, files, custom instructions)
  • Run /review:security-review per custom instructions
  • Post findings

Note: the review:security-review Skill invocation errored in this environment (<error>Execute skill: review:security-review</error> on repeated attempts, same as the code-review lane hit earlier in this PR's cycle — see the Refs #3147 follow-up). Proceeded with the equivalent manual review.

No security review performed — skip gate triggered.

Per the skip gate in /review:security-review: "This head already has a successful security review that still applies" combined with "Change has no security-relevant surface after reading the diff."

The prior review (head c3d51a1) already cleared this PR twice. Per the relevance-gate note, I diffed only the commits since that reviewed head:

git diff c3d51a1..9e721c7 — 2 files changed, 19 insertions / 8 deletions:

  • plugins/docs-hygiene/CHANGELOG.md — prose edit adding a fourth bullet ("The batch per-dispatch verdict enum covers completed non-abstracting remedies") and folding write-for-humans into the sibling-routing bullet.
  • plugins/docs-hygiene/skills/extract-ssot/actions/batch.md — extends the Step 8 subagent-dispatch verdict schema with a new REMEDIED-{remedy} value and fixes the Step 10 example row to use it instead of the undocumented OWNER-NAMED.

Both files are markdown documentation/prompt-authoring content for the docs-hygiene plugin's extract-ssot skill — a data-format/enum-label change, not code. No execution sinks, no auth/access-control logic, no secrets/token handling, no untrusted external input, and no GitHub Actions workflow changes (no permissions:, pull_request_target, workflow_run, or ${{ }} template usage). This resolves the last outstanding code-review finding (the OWNER-NAMED/enum mismatch flagged in this PR's manual code-review pass) and introduces no new security-relevant surface.

No findings to report.
· branch claude/work-items-integration-b0fszs

@claude

claude Bot commented Aug 23, 2026

Copy link
Copy Markdown
Contributor

Claude finished @kyle-sexton's task in 1m 17s —— View job


Code review (/review:code-review)

  • Gather context (PR diff, files, custom instructions)
  • Invoke /review:code-review per custom instructions
  • Post findings

Note: the review:code-review Skill invocation errored again in this environment (<error>Execute skill: review:code-review</error> on repeated attempts). Proceeded with the equivalent manual review per the skill's own instructions (plugins/review/skills/code-review/SKILL.md), scoped to correctness and maintainability (security is out of scope for this lane; the security lane already cleared this PR three times).

Skip-gate check: this head (9e721c7) already has a prior successful review from this lane at head f4b6305, which found one P2 finding (the batch.md verdict-enum gap). Per the skip gate, I reviewed only the incremental diff since that reviewed head:

git diff f4b6305..9e721c7 — 1 commit ("batch verdict enum covers completed non-abstracting remedies"), 2 files, 12 insertions / 3 deletions:

  • plugins/docs-hygiene/skills/extract-ssot/actions/batch.md — Step 8's verdict enum (line 191) is extended from EXTRACTED | REFUSED-{reason} | DEFERRED to EXTRACTED | REMEDIED-{remedy} | REFUSED-{reason} | DEFERRED, with {remedy} scoped to the four non-abstracting remedies. The Step 10 example row (line 235) now uses REMEDIED-name-an-owner in place of the previously out-of-schema OWNER-NAMED.
  • plugins/docs-hygiene/CHANGELOG.md — "Three defects" → "Four defects", with a new bullet describing this fix, keeping the stated count in sync with the enumerated list.

Confirmed fixed, with no new issues introduced:

  • No other reference to the old three-value enum or to OWNER-NAMED remains anywhere in the plugin (verify.md, SKILL.md, evals.json checked — none define or depend on the verdict enum).
  • The --min-instances/--buckets filter (batch.md:97-105) and the ≥80%-refusal abort check (batch.md:104, counts only REFUSE-*) are unaffected by the new enum value — REMEDIED-* correctly falls outside both.
  • CHANGELOG defect count (4) matches the 4 enumerated bullets.

No findings to report on this incremental commit. I attempted to re-run markdownlint-cli2 and check-changelog-parity.sh --check for independent confirmation but those Bash invocations required interactive approval unavailable in this run — not independently verified this pass; the PR description's own verification claims are author-reported for this point.

· branch claude/work-items-integration-b0fszs

@kyle-sexton
kyle-sexton merged commit 5aa7d2c into main Aug 23, 2026
50 checks passed
@kyle-sexton
kyle-sexton deleted the claude/work-items-integration-b0fszs branch August 23, 2026 04:45
kyle-sexton pushed a commit that referenced this pull request Aug 23, 2026
Resolves two conflicts in docs-hygiene, both from #3142 bumping the plugin to
0.19.0 while this branch carried 0.18.4:

- plugin.json: version becomes 0.19.1, this branch's fix on top of 0.19.0.
- CHANGELOG.md: this branch's entry re-headed [0.19.1] and ordered above
  [0.19.0]; both entries kept in full.

#3140 also landed on main during this branch's life, so the sibling
`code-tidying/audit-comment-residue` parse it ports from is now present. The
gate and the two-step unescape here are identical to it, so the two porcelain
parsers converge rather than failing in opposite directions on renames. Noted
in the changelog entry.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CXYVz59XVYS7NEjMB5UyHq
kyle-sexton added a commit that referenced this pull request Aug 23, 2026
….19.1) (#3171)

Closes #3143

## Summary

`audit-noise`'s `git status --porcelain` parse dropped files whose paths
git
treats specially. Both defects are the silent-false-negative class: the
file
did not error, it simply disappeared from the target list, so a run over
a tree
containing one reported clean.

## Fix

**Rename split is gated on the status letter, not the path text.** It
previously
fired on any record whose path contained `" -> "`, so a file literally
named
`notes -> draft.md` was reduced to `draft.md` — a name that resolves to
nothing.
It now gates on `[RC]` in *either* column, which is narrower and still
catches a
rename recorded in the index or the worktree.

**`\\` is now unescaped as well as `\"`.** Git C-quotes a path for an
embedded
backslash too, so `back\-slash.md` stayed escaped and resolved to
nothing. Both
escapes are undone, `\"` before `\\`.

#3140 landed on `main` while this branch was in flight. The gate and the
two-step unescape here are **identical** to the ones it gave
`code-tidying/audit-comment-residue`, so the two porcelain parsers now
converge
rather than failing in opposite directions on renames — which is what
#3143
asked for.

`audit-noise`'s `SKILL.md` does not mirror this parse — it uses a plain
`grep '\.md$'` pipeline — so the conditional "mirrored parser" half of
the issue
does not apply here.

`docs-hygiene` 0.19.1.

## Verification

- `detect.test.sh`: **all 66 checks pass**, including 5 new cases.
- **Discriminator check**: reverting only `detect.sh` to the old parse
fails
exactly the two new defect cases (`' -> '` path, backslash path) and
nothing
else — so neither case passes vacuously. The rename cases pass under
both
implementations by design; they are regression guards showing the new
gate
  does not cost the `old -> new` handling it narrows.
- All 7 `docs-hygiene` suites pass, re-run after merging `main`; nothing
outside
  this skill references `audit-noise/scripts/detect.sh`.
- `shellcheck`, `shfmt -d`, `markdownlint-cli2`, `typos`,
`editorconfig-checker`: clean.
- `check-fixture-git-isolation.sh --check`,
`check-plugin-manifest-presence.sh`,
`check-changelog-parity.sh --check` / `--check-order` / `--check-bump` /
  `--check-preserved` against `origin/main`: pass.

The suite also picks up the `unset GIT_DIR GIT_WORK_TREE GIT_CONFIG`
isolation
line that 0.18.3's sweep missed on this file.

**Known residual, recorded at the parse site rather than left
implicit:** git's
octal escapes (`\NNN`) for control and non-ASCII bytes are still not
decoded, so
those paths continue to miss. Converging on `git status --porcelain -z`
would
close the class outright rather than extending the string parse a third
time.

## Related

- Refs #3140 — the sibling `code-tidying/audit-comment-residue` parse
fix this
issue was deferred out of; now landed, and this change converges with
it.
- Refs #3126 — the original `audit-comment-residue` defect report.
- Refs #2872 — the fixture git-isolation convention this suite now
satisfies.
- Refs #3142 — bumped `docs-hygiene` to 0.19.0 mid-flight; merged in, so
this
  PR ships 0.19.1.

Co-authored-by: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(docs-hygiene): extract-ssot — bucket candidates by rule-of-one/two/three and gate artifact creation, not reporting

2 participants