* feat: optional --style house-style layer (config-driven, points at Vale)
Implements the config-driven design recorded in #88, which #76 and the fork
review converged on. No bundled guides: the layer applies register/voice
directives and removes AI tells on top of whatever mechanics you enforce.
--style ./house.json applies a user-supplied JSON config (register +
mechanics) and scripts/check-style.js verifies the CHECKABLE mechanics
deterministically: quotes and latinAbbrev gate the exit code (0 clean /
1 hard / 2 tool error), headings, emDash and spellNumbersUpTo are advisory,
serialComma is never checked. The docs scope the verb accordingly rather
than claiming "mechanics are verified" flatly. examples/ ships two generic,
guide-neutral starters plus the schema, and links #88 for the licensing
rule.
A bare --style "APA" is a best-effort fallback, not a feature: SKILL.md
instructs the model to print a no-compliance-claim status line and not to
reproduce the guide's text. Those are instructions rather than checked
rules, and the docs say so instead of asserting the behaviour as fact.
--style is listed in the SKILL.md invocation line and has an explicit
composition rule with --voice/--context, since the file specifies
composition for every other axis.
README: the "House style is a different job" section said "There's no
--style input", which this makes false. The first paragraph now describes
the config input and reconciles with the heading (enforcing a PUBLISHED
guide is the different job). The Vale paragraph and the heading anchor are
unchanged.
cursor-rules: the ported rule would have told a Cursor user to run
scripts/check-style.js and read examples/, neither of which ships in the
.mdc. Two anchored spans in sync-cursor-rules.sh rewrite those the way
span 3 already handles detector/validate.js, so the port stays
self-contained. Worth noting the drift guard only covers edits to anchored
spans, not newly added SKILL.md sections that introduce repo references.
The checker went through three adversarial review rounds, and each round
found the previous round's fix had introduced a new way to hard-fail a
correct document or to miss a real one. The tests pin all of them: markdown
link titles, reference definitions (including escaped quotes in a title),
HTML attribute values, nested and tilde fences, BOM'd frontmatter, URLs
containing parentheses, parentheticals that wrap or span a code block, and
a stray "(" that must not suppress later findings, and prose containing a
comparison ("n<N ... >") that must not be mistaken for an HTML tag. Masking runs refdef ->
links -> tags, in that order, because masking a link destination first
makes an ordinary "[a](url): text" line look like a reference definition.
Link masking walks to the matching paren and scans linearly; the regex form
was quadratic (22.7s on a hostile line, now 4ms). resolveConfig decides
path-vs-name by shape so a cwd file can't shadow a bundled example, the CLI
parses by position, a config with "mechanics": null or [] exits 2 rather
than a false-green 0, and advisory findings print instead of hiding behind
--json.
Version 3.22.3 -> 3.23.0 in SKILL.md frontmatter, package.json and
plugin.json; CHANGELOG entry under a dated heading; plugin and cursor
copies regenerated.
No detector changes: catalog counts unchanged (61 / 112). 32 tests in
scripts/check-style.test.js under npm test; detector-test.yml path filters
extended to scripts/** and examples/**.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* style: mask indented code, tighten frontmatter open, announce the resolved mode
Review fixes applied on top of the submitted branch:
- Indented code blocks (4+ spaces / tab after a blank line, outside a list)
are masked, so pasted terminal output can't hard-fail a correct document.
Lazy continuation and list-item content stay checked; a code block nested
in a list item needs a fence. Was the largest undocumented false positive.
- A document opening with a thematic break is no longer read as frontmatter
(which silently swallowed everything to the next ---).
- The bare-name traversal regex was dead code its test never reached; a bare
name is a single path segment by construction, so the guard is now a
comment stating that argument, and a test pins dot-bearing names.
- Config runs open by naming the resolved config, mirroring the fallback's
status line, so which of the two modes ran is always explicit in output.
- Known-limitations lists gain the double-backtick span and next-line
reference-definition title gaps; examples/README.md joins the self-scan
budgets; CHANGELOG updated; cursor-rule anchors follow the SKILL.md edit.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Conor Bronsdon <120674402+conorbronsdon@users.noreply.github.com>
Adds a preservation validator, a self-scan with PROOF.md, over-correction guardrails, a false-positive intake, and a two-class control corpus with the project's first FPR, TPR, and AUC.
Splits Tier 1 into 1A frequency markers and 1B clarity edits, and fixes two detector defects the measurement found (#67, #69).
Findings and open decisions: #70, #71, #72, #73.
* 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>