Align CONTRIBUTING.md, CLAUDE.md, and the PR checklist on impact-based release notes, Unreleased entries, and release-time versioning. Exempt routine documentation and maintenance without user-facing effect, and remove the three corresponding Unreleased notes from #185.
Reviewed by GPT-5.6 Sol / Codex. Tests, self-scan, count check, SSOT, detector, and plugin-skill-sync passed.
Preserve contributor commits from PRs #181 and #183, record their required changelog entries, and document one good-first issue for a contributor's first PR.
Reviewed with GPT-5.6 Sol / Codex.
CONTRIBUTING.md explains when to bump the README pattern-category
bullet and the checked CLAUDE.md literal. The PR template adds a
matching checklist item. CLAUDE.md clarifies README as canonical
and its own quote as a CI-checked copy.
Fixesconorbronsdon/avoid-ai-writing#170
A new-pattern suggestion currently arrives as a blank issue, so triage
has to ask for the same details every time. The form asks for them up
front: a should-fire example, a must-not-fire example, the false-positive
risk, and whether a regex can reach the pattern at all.
Required fields are the ones triage cannot proceed without. Register and
sources stay optional, since register can usually be read off the
examples and a source only applies when the proposal makes a claim about
how models or people write.
CONTRIBUTING.md links the form from the line that already tells unsure
contributors to open an issue, without restating the fields.
Closes#157
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015w3yGvreSY5CLyBG7zgCKK
Completes the last unchecked action on the #88 decision record, so a
future contributor finds the openly-licensed-vs-paywalled line here
instead of re-arguing it in a PR thread.
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
* detector: derive the engine type count instead of restating it (#91)
TYPE_LABELS has 47 keys. Six places said 45 or 46: both README count
lines, both CATEGORIES.md count sentences, the patterns.js header, and
the package.json description that ships to npm.
Three of the four commits that added a type edited README.md in the same
commit and still left the number alone. That is the argument for a guard
rather than a convention: the count sits inside a 90-word parenthetical
explaining why two counts deliberately differ, so it reads as prose and
survives editing. 660c95c fixed it by hand and added no check; #65
reopened it nine days later.
Corrected where the number does explanatory work (README.md:180,
CATEGORIES.md), deleted where it was a decorative restatement (the
"45-category engine" phrase, the patterns.js header, the npm
description). CLAUDE.md already says the count belongs in one place.
The survivors are now asserted in categories.test.js, which already
computes typeKeys.length and runs under detector-test.yml -- the only
workflow whose paths cover both detector/** and README.md. Extending
check-pattern-count.sh could not work: plugin-skill-sync.yml, which runs
it, does not watch detector/**, so a commit that only adds a key would
never trigger it.
Each site registers as a file plus a one-capture-group regex, and a regex
that stops matching FAILS rather than passes, so a reworded sentence has
to re-register instead of silently dropping its own guard.
Watched it fail, three ways:
README says 46 with 47 keys -> exit 1
48th TYPE_LABELS key added -> exit 1 (two checks)
sentence reworded -> exit 1, names the stale regex
Gates green: npm test, self-scan:check, check-pattern-count 61/112,
sync-plugin-skill 3.22.1.
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
* Address adversarial review: a seventh site, and prose the guard invalidated
The guard change described three more sentences than it updated.
CHANGELOG.md:37 is a seventh site and it is wrong rather than stale. The
v3.22.0 entry says "No new detection categories: the catalog stays at 61
and the engine at 46 types" -- that release added tier1-clarity, taking
the engine to 47. The audit trail recorded "no new categories" for the
release that added one, which is why the README then sat at 45 with
nothing to catch it. Corrected in place with a dated correction note,
following the precedent the 3.22.1 entry set for its own wrong claim.
CATEGORIES.md:19 said categories.test.js "enforces only the engine <->
this-file mapping." False two lines below the number this branch fixed,
since the test now also checks a README sentence. CONTRIBUTING.md:55-57
said "Both must pass" of what is now three checks.
patterns.js header said "type-per-category," which asserts a 1:1
type-to-category mapping that README.md:180 in this same commit denies --
the engine splits vocabulary tiers, so 47 types is not 61 categories. It
traded a stale checkable number for an unguarded wrong claim.
Also split the guard into one test per site, so breaking three sentences
reports three failures instead of aborting on the first, and added a
uniqueness assertion: a regex matching twice would silently verify the
wrong sentence. Failure messages now name the regex.
Watched it fail: three sites broken at once -> 3 failures, exit 1.
Gates green: npm test, self-scan:check, check-pattern-count 61/112.
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
* Third review pass: fix a wrong causal claim, and a guard that reddens a clean repo
The correction note I added to the 3.22.0 entry asserted a causal story
that is false. It said the wrong entry "is why the README then sat at 45
for four days." Checked: the README was already stale at 45 as of
3a34c68 (v3.20.0, 7/29 19:28), roughly 27 hours before the v3.22.0 entry
existed -- and v3.20.0's own entry states its bump correctly ("the engine
goes from 45 to 46"). An accurate changelog sat beside a README that
rotted anyway, so a wrong one did not cause it. That is the stronger
version of this PR's argument and it is also the true one.
Writing an unguarded factual claim into the audit trail, in the PR whose
thesis is that unguarded factual claims rot, is the failure mode this
change exists to fix.
Dropped the uniqueness assertion. Review flagged that a blockquoted
historical number registers as a second match, so following this repo's
own correction convention would fail a repo with no drift in it. The
suggested fix -- filter blockquote lines before matching -- does not work
here either: README.md:180's live statement is itself inside a
blockquote, so filtering removes the site it is meant to guard. Verified
both ways. A guard that reddens a correct repo is worse than the hole it
closes, so the value assertion stands alone and the reasoning is recorded
where the next person will read it.
Watched it behave, four ways:
blockquoted historical number -> exit 0
CATEGORIES.md drift -> exit 1
README drift -> exit 1
README sentence reworded -> exit 1
Gates green: npm test, self-scan:check, check-pattern-count 61/112.
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
* feat: make repo SSOT for the detection engine
Extract the 43-category detection engine + its dependency-free node test
harness from the (winding-down) private web-app repo into detector/, so this
open-source repo is now the canonical source of truth for both the rules
(SKILL.md) and their executable expression (detector/patterns.js).
- detector/patterns.js: zero-dep, build-step-free, runs in node>=18 + browser
- detector/patterns.test.js: 60 fixtures, no deps (node:assert)
- package.json + CI: `npm test` on push/PR touching detector/
- detector/CATEGORIES.md: anti-drift map of SKILL.md sections <-> detector types
- README: "Run the detector" section
The cert/attestation/x402/token layer stays behind in the private app; the
engine is a pure function with no knowledge of it.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* docs: reclassify smart-punct-signature as a partial skill map
Community PR #15 adds a curly-quotation-marks rule under SKILL.md's
Formatting section, so smart-punct-signature is no longer detector-only.
Move it from section B to a partial mapping in section A, noting that the
detector requires 4-signal co-occurrence while the skill rule treats curly
quotes as a weak corroborating signal — the two agree in spirit but differ
in mechanism.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* test: enforce CATEGORIES.md contract; docs: contributor guide + count clarity
- detector/categories.test.js: asserts every detector type is documented in
CATEGORIES.md and no stale type rows remain; wired into `npm test`.
- README + CATEGORIES.md: note that the 42 prose patterns, 43 detector types,
and ~50 SKILL.md sections are different counts on purpose — don't reconcile.
- CONTRIBUTING.md + PR template: encode the regex-vs-judgment decision, the
precision-over-recall bias, npm test, the clean-prose bar, and changelog/
version conventions — the things the first community PR surfaced by hand.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* docs: require contributors to cite sources for empirical claims
Rules that assert how AI or humans write get fact-checked; some turn out
wrong (e.g. the curly-quote premise). Add a "Cite your sources" section to
CONTRIBUTING.md and a checklist item to the PR template.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* test: require detector types to appear in a CATEGORIES.md table, not just prose
Tighten the anti-drift check so a type "documented" by a stray backtick
mention in prose no longer satisfies the gate — it has to land in an actual
mapping-table row, matching the test's own summary line.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>