Skip to content

docs: repo-wide authoring-doctrine pass, and repair the grammar the em-dash purge left behind - #3461

Merged
kyle-sexton merged 4 commits into
mainfrom
claude/docs-hygiene-repo-audit-jkx5oc
Aug 28, 2026
Merged

docs: repo-wide authoring-doctrine pass, and repair the grammar the em-dash purge left behind#3461
kyle-sexton merged 4 commits into
mainfrom
claude/docs-hygiene-repo-audit-jkx5oc

Conversation

@kyle-sexton

Copy link
Copy Markdown
Contributor

No linked issue

Summary

A recall-side re-run of the two authoring-doctrine skills, docs-hygiene:write-for-agents and docs-hygiene:write-for-humans, across the whole tracked markdown corpus in two strictly separated lanes.

The 2026-08-26 sweep already ran these as its lanes L7 and L8, so a re-run needs a stated reason that is not "it has been a while". This is it, in that sweep's own words: it ran serially in one context, and "No subagent-spawn tool was available ... Every substitute for fan-out was a corpus-wide mechanical detector plus sampled adjudication, which trades recall for precision. The numbers above are precision-side results and should not be read as completeness" (docs/specs/docs-hygiene-sweep-yield-measurement.md). This pass closes that recall gap by reading every file end to end instead of grepping for cues. It deliberately does not re-run the noise, compression, or derivability lanes, which that record closes for this corpus.

The largest result was not a doctrine violation. Reading the corpus surfaced a regression left by the #2891 em-dash purge: where its mechanical substitution ran without the restructure step its own rewrite guide requires, it left broken grammar in shipped instruction surfaces, including three places where the meaning changed.

Fix

Two commits.

f38d1c16 applies 117 verified authoring-doctrine edits across 83 files: unresolvable cross-references, stale counts and inventories, pointers whose targets no longer exist, and self-contradicting recaps.

93c17eea repairs 17 grammar breaks across 11 skill bodies. The three that changed meaning rather than readability:

  • implement-dispatch/SKILL.mdwhen the caller passes --wave-cap <N>. was a subordinate clause with no main clause, so Cap at that N read as an unconditional rule and contradicted the 3-5 by default line above it.
  • docpage-digest/SKILL.md — a dedent inverted the instruction: Truncate the host+path prefix, never the hash so the whole slug is <= 40 chars reads as do not truncate the hash in order to keep it <= 40.
  • implement/SKILL.md — two consecutive verbless sentences left Never the producing context auditing itself as a free-floating prohibition with no antecedent.

Repairs on paths in scripts/em-dash-purged-paths.txt restructure rather than reintroduce an em dash, and never substitute a parenthesis, en dash, or spaced hyphen.

Scope and method. 1,084 files read end to end across 90 batches: 995 agents lane, 86 humans lane, and 3 graded separately because lane purity barred both lanes from the write-for-humans tree itself. 274 files were excluded for stated reasons: changelogs and ADRs (historical record), vendored and upstream trees, generated regions, and deliberately defective eval fixtures.

219 findings were raised and all 219 independently verified by agents that did not produce them, with the producing rationale withheld and a default-refute posture: 197 confirmed, 22 refuted, and 15 more where the defect stood but the proposed fix was rejected. Verification caught a worker justifying an edit by citing a .claude/ai-slop.json exemption that does not exist, and another whose replacement would have changed a table's meaning.

102 findings are report-only and are not in this diff, each held for a checkable reason: the fix would rename a heading with inbound anchors (lychee.toml sets include_fragments = "full"), land inside a BEGIN GENERATED region, touch prose a test digest-pins, or force a paragraph rewrap. Notably planning/skills/interview/SKILL.md carries real purge damage inside a section interview-defenses.test.sh:531 pins, so it is routed to that plugin's owner rather than edited here.

Two structural defects found while reading are also fixed: a closing fence carrying trailing text in autonomy/skills/setup/templates/return-capture.md (the JSON block never closed, so 45 lines rendered as code), and a 5 minutes liveness constant in claude-config/skills/audit-pass/reference/run-state-and-resumability.md that contradicted the same file's own correction that the default stale_after_s is 30 minutes.

Verification

Gate Result
scripts/check-purged-em-dashes.sh 21 declared paths, 30 files scanned, no em dashes
scripts/check-changed-skills.sh origin/main 28 skills checked, 0 failed; all base-ref trigger phrases preserved
markdownlint-cli2 0 issues across all changed files
typos clean
editorconfig-checker clean
scripts/affected-tests.sh --run 17 shell suites passed
pytest (7 selected suites) 667 passed, 271 subtests
plugins/planning/tests/interview-defenses.test.sh passes; no digest-pinned section touched

The 18 selected vitest suites are NOT RUN by the shell runner per its own contract. They fail identically with ERR_MODULE_NOT_FOUND on a stashed tree at origin/main (vitest is absent from this environment), so they are unaffected by this change.

Related

  • docs/specs/docs-hygiene-sweep-yield-measurement.md — the prior sweep's recall limitation that motivates this re-run
  • docs/specs/docs-hygiene-sweep-unapplied-remediations.md — the prior L7/L8 backlog this extends; all 13 open L7 items verified already applied, and the 6 open L8 items were resolved rather than rediscovered
  • docs/adr/0008-admit-only-present-text-defects-to-the-instruction-audit-catalog.md — every finding anchors to text that is present; absences are routed, not filed
  • .claude/rules/vendor-docs-are-not-style.md — the declared house style the humans lane resolved to, superseding the skill's bundled default set
  • Refs De-slop campaign: purge em dashes and AI tells from this repo's own corpus via /ai-slop:audit fix #2891 — the em-dash purge campaign whose residue this repairs

One item needs a human decision and is deliberately not fixed here. plugins/kindle-dedrm/README.md:25-32 warns "Private marketplace only. Carve out before publishing" and instructs that if the marketplace is ever made public, the plugin should be removed from marketplace.json first. Three sources now say the marketplace is public (README.md:3, docs/CI-RUNNER-ROUTING.md:3, .github/runner-policy.json), and .claude-plugin/marketplace.json:388 still publishes the entry. Correcting the word "private" alone would delete the warning's trigger while leaving the plugin published, and carving it out is a policy call that belongs to a maintainer.


Generated by Claude Code

claude added 2 commits August 28, 2026 06:39
…-humans)

Recall-side re-run of the two authoring-doctrine lanes over the whole tracked
markdown corpus, in two strictly separated lanes.

The 2026-08-26 sweep ran these same two skills as its lanes L7 and L8, but ran
serially in one context with no subagent-spawn tool, and its own record states:
"Every substitute for fan-out was a corpus-wide mechanical detector plus sampled
adjudication, which trades recall for precision. The numbers above are
precision-side results and should not be read as completeness."
(docs/specs/docs-hygiene-sweep-yield-measurement.md). This pass closes that
recall gap by reading every file end to end. It does not re-run the noise,
compression or derivability lanes, which that record closes for this corpus.

Scope: 1,084 files read end to end across 90 batches (995 agents lane, 86 humans
lane, 3 graded by the orchestrator because lane purity barred both lanes from
them). 274 files excluded for stated reasons: changelogs and ADRs (historical
record), vendored and upstream trees, generated regions, and deliberately
defective eval fixtures.

Findings: 219 raised, 219 independently verified by agents that did not produce
them, with the producing rationale withheld and a default-refute posture.
197 confirmed, 22 refuted, 15 fixes rejected as unsafe while the defect stood.
117 edits met every gate and are applied here; 102 findings are report-only
because their fix would rename a heading with inbound anchors, land inside a
generated region, touch test-pinned prose, or force a paragraph rewrap.

Also fixed, found while reading:
- plugins/autonomy/skills/setup/templates/return-capture.md: a closing fence
  carried trailing text on the same line, so the JSON block opened 14 lines
  earlier never closed and the rest of the template rendered as code.
- plugins/claude-config/skills/audit-pass/reference/run-state-and-resumability.md:
  the liveness test cited "5 minutes" against the same file's own correction
  that the default stale_after_s is 30 minutes.

Validation: check-purged-em-dashes clean (21 paths, 30 files); check-changed-skills
28 skills 0 failed, all base-ref trigger phrases preserved; markdownlint 0 issues
over 85 files; typos and editorconfig-checker clean; affected-tests.sh --run
17 shell suites passed; 667 pytest assertions passed. The selected vitest suites
fail identically at origin/main (vitest absent from this environment), so they
are untouched by this change.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KjPedw5YscNaAm1kaC837T
The #2891 de-slop campaign deleted ~12,561 em dashes across 411 files in 92
commits. Its own rewrite guide requires that "em dashes become periods or
commas, OR the sentence is restructured". Where the substitution ran without
the restructure step it left broken grammar in shipped instruction surfaces.

21 instances were found and verified against the files; 18 confirmed, 3 refuted
as clipped-but-grammatical (this fleet writes in a deliberately telegraphic
register, so terseness alone is not a defect). 17 are repaired here across 11
skill bodies.

Under 0.5% of substitutions broke, but the failures are systematic rather than
random: four reproducible mechanical shapes, five of them the same structural
bug where a wrapped "   - continuation" line was dedented to column 0 with no
joining punctuation.

The three that changed meaning rather than readability:

- implement-dispatch/SKILL.md: "when the caller passes `--wave-cap <N>`." was a
  subordinate clause with no main clause, so "Cap at that N" read as an
  unconditional rule and contradicted the "3-5 by default" line above it.
- docpage-digest/SKILL.md: a dedent inverted the instruction. "Truncate the
  host+path prefix, never the hash so the whole slug is <= 40 chars" reads as
  "do not truncate the hash in order to keep it <= 40".
- implement/SKILL.md: two consecutive verbless sentences left "Never the
  producing context auditing itself" as a free-floating prohibition with no
  antecedent, so a reader could not tell what must not audit what.

Repairs on paths in scripts/em-dash-purged-paths.txt restructure instead of
reintroducing an em dash, and never substitute a parenthesis, en dash, or
spaced hyphen. Held back: planning/skills/interview/SKILL.md carries real
damage (a stranded "Which..." relative clause) inside a section that
plugins/planning/tests/interview-defenses.test.sh digest-pins, so it is routed
to that plugin's owner rather than edited here.

Validation: check-purged-em-dashes clean (21 paths, 30 files); markdownlint
0 issues; typos and editorconfig-checker clean; check-changed-skills 11 skills
0 failed; affected-tests.sh --run 17 shell suites passed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KjPedw5YscNaAm1kaC837T
@github-actions github-actions Bot deleted a comment from claude Bot Aug 28, 2026
@github-actions github-actions Bot deleted a comment from claude Bot Aug 28, 2026
@claude

claude Bot commented Aug 28, 2026

Copy link
Copy Markdown
Contributor

Claude encountered an error after 0s —— View job


I'll analyze this and get back to you.

@claude

claude Bot commented Aug 28, 2026

Copy link
Copy Markdown
Contributor

Claude encountered an error after 0s —— View job


I'll analyze this and get back to you.

@github-actions

github-actions Bot commented Aug 28, 2026

Copy link
Copy Markdown

Warning

Automated security review did not complete — this is an infrastructure failure, not a review verdict.

Treat any Claude comment on this PR (including a placeholder like "I'll analyze this and get back to you") as incomplete, not "no findings."

The check is green on purpose, and it is not evidence. It certifies that a security pass ran, and this one did not complete — but the cause is outside this PR's control, so merging is deliberately left unblocked rather than locking every merge for the length of the outage. Nothing was reviewed at this head. Where this check is required, it is satisfied without that evidence; a human should review security-sensitive changes here before merging.

Re-run the job, or workflow_dispatch this workflow with the PR number, to retry the review (ci-workflows#227). A new push also retries it only if the caller's pull_request triggers include synchronize (the canonical security caller keeps it). An automatic retry may already have run — it is skipped when a partial review could duplicate comments, or when the failure class needs an operator.

Re-running does NOT help for every class:

  • rate-limit that persists across re-runs, or auth — the credential or usage budget needs an operator; retrying will not clear it.
  • a run that exhausted its turn budget ("subtype":"error_max_turns" above) will exhaust it again. As the PR author, split the change into smaller PRs; raising --max-turns is a change to the caller workflow, not something you can set on this PR.

@github-actions

github-actions Bot commented Aug 28, 2026

Copy link
Copy Markdown

Warning

Automated review did not complete — this is an infrastructure failure, not a review verdict.

Treat any Claude comment on this PR (including a placeholder like "I'll analyze this and get back to you") as incomplete, not "no findings."

Re-run the job, or workflow_dispatch this workflow with the PR number, to retry the review. A new push re-triggers this lane only if the caller's pull_request triggers include synchronize (the canonical caller omits it).
An automatic retry may already have run — it is skipped when a partial review could duplicate comments, or when the failure class needs an operator (auth).

The changelog-parity gate rejects a change set that modifies shipped files under
plugins/<name>/ while the manifest still carries a published version: reusing a
published version number is not allowed, because the install cache keys on
`version` rather than commit, so an unbumped plugin never reaches a consumer.

Each of the 45 touched plugins gets a patch bump and a '## [<version>]' entry.
Entry text is derived per plugin from the findings that actually landed in it,
not from a template: which files were touched, and whether the edit repaired
em-dash purge damage, an unresolvable pointer, a drifted count, a stale recap,
or an ambiguous sentence.

Also merges origin/main to clear the stale-base-overlap gate: the branch was two
commits behind, and #3457 had since touched two files this change set also edits
(plugins/kindle-dedrm/README.md and
plugins/session-flow/skills/find-handoff/reference/rung-1-known-location.md).
A stale-base squash can silently revert recently landed fixes on overlapping
paths, so the base is refreshed rather than merged stale. The merge was clean and
both sides' changes are present.

Validation: check-changelog-parity --check, --check-bump origin/main and
--check-preserved origin/main all pass; check-purged-em-dashes clean;
markdownlint 0 issues over 140 changed markdown files; typos and
editorconfig-checker clean.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KjPedw5YscNaAm1kaC837T
@github-actions github-actions Bot deleted a comment from claude Bot Aug 28, 2026
@github-actions github-actions Bot deleted a comment from claude Bot Aug 28, 2026
@claude

claude Bot commented Aug 28, 2026

Copy link
Copy Markdown
Contributor

Claude encountered an error after 0s —— View job


I'll analyze this and get back to you.

@claude

claude Bot commented Aug 28, 2026

Copy link
Copy Markdown
Contributor

Claude encountered an error after 0s —— View job


I'll analyze this and get back to you.

@kyle-sexton
kyle-sexton merged commit daa9e14 into main Aug 28, 2026
56 checks passed
@kyle-sexton
kyle-sexton deleted the claude/docs-hygiene-repo-audit-jkx5oc branch August 28, 2026 07:02
kyle-sexton pushed a commit that referenced this pull request Aug 28, 2026
…registered copies

The registry alone only ever looks where it is told. A new lane could inline
the operable floor, its author forget the entry, the six registered paths still
agree, CI go green, and the next contract change strand that seventh copy. That
is the same blindness this gate exists for, one level up, and it is not
hypothetical: the first report of this coupling named five copies and building
the registry found six.

The check now scans every tracked file for the floor's opening bullet before
comparing anything and fails on a carrier its registry does not name. Discovery
reuses the anchored marker test the comparison uses, so the blockquoted
launch-prompt shape is not a hole. Tracked rather than on-disk is the corpus
every sibling gate reads: a scratch file ships to nobody, and staging it is what
makes it a copy this repository carries. The registry stays, because it carries
each consumer's comparison mode, which no scan can infer.

A file may carry the marker as data rather than as a consumer copy, and declares
that inline with a reason (loop-lane-floor-carrier-ok:) on the shape the CI
workflow's lane-coverage-ok and the hooks' silent-skip-ok already use. The
reason is mandatory, an annotation on a registered path fails as stale, and
--list enumerates every exemption. This gate's own suite is the first such file.

Also in this change:

- Merges current origin/main. #3461 claimed rate-limit-guard 0.7.17 and
  docs-hygiene 0.21.21 after this branch was cut, so both renumber to 0.7.18 and
  0.21.22 and the two changelog conflicts are resolved keeping main's entries.
- Corrects this branch's own miscount. The rate-limit-guard entry said all six
  copies had drifted; three had. The other three matched the contract byte for
  byte and moved with it here. Same correction where the loop-lane changelog
  said two unpurged copies rather than three.
- Corrects what values mode tolerates. Normalization strips backticks and
  emphasis as well as blockquote markers and wrapping, so markup is free in that
  mode too, not only line breaks. Every word is still asserted. Section 6 and
  both changelogs now say what the script header already said.
- Adopts the liveness-assertion convention properly: the script header names its
  taxonomy row (Gate / classifier) and how it satisfies fail-loud, and the
  convention gains its Adopters row and a 1.1.0 entry.
- Removes two restatements of floor values sitting outside the compared block:
  section 6 no longer names the 90% threshold, and rate-limit-guard's setup
  probe no longer names the 10-minute staleness window.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QkMx972GYEQ3vCb98pLw8m
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.

2 participants