Commit Graph

40 Commits

Author SHA1 Message Date
Conor Bronsdon e79254c892 fix: prepare CLI package release 2026-09-11 12:29:32 -07:00
Conor Bronsdon 66da51290c fix: treat em dashes as style-only guidance 2026-09-06 08:37:06 -07:00
Conor Bronsdon 28ba61bc9f fix: preserve prose quote boundaries around malformed bare URLs 2026-09-06 08:02:44 -07:00
Conor Bronsdon f654266ef9 Address release review: editable inputs, valid links, and catalog guidance 2026-09-05 13:04:13 -07:00
Conor Bronsdon b902d8db71 Clarify Tier 1 exceptions and same-line load-bearing boundary 2026-09-05 12:45:01 -07:00
Conor Bronsdon 9c1a048a45 Regenerate release bundles from repaired canonical sources 2026-09-05 12:35:39 -07:00
Conor Bronsdon 0aa0def0ee Split canonical skill and ship complete Claude bundle 2026-09-05 12:34:24 -07:00
UniversePeak 3dd72f5ec6 Fix automatic marks inference and malformed link scanning 2026-09-06 03:11:15 +08:00
Conor Bronsdon 7552fa3aa3 Keep explained transformations exempt from rewriting 2026-09-05 11:43:43 -07:00
Conor Bronsdon b43142a0e0 Include clarity rules in P2 triage and preserve explained summaries 2026-09-05 11:38:43 -07:00
Conor Bronsdon c5ec5b8a93 Complete catalog clarity rules with source-preserving guidance 2026-09-05 11:28:59 -07:00
Conor Bronsdon 081b495614 Narrow repeated reversal punchlines and integrate current main 2026-09-05 11:24:54 -07:00
odinfree d8c235186f Add detector trio from #108: launch intros, crowd contrast, fake-casual props (#128)
* Add detector trio from #108: launch intros, crowd contrast, fake-casual props

Three regex-detectable patterns from the welttowelt merged-system diff,
each with a must-fire and a must-not-fire fixture:

- launch-intro: sentence-initial imperative product introductions
  ("Enter X.", "Meet X, your new...", "Think X meets Y"). "Say hello
  to X" stays judgment-only ("Say hello to Grandma." is ordinary prose).
- crowd-contrast: the trailing "while everyone else..." clause, gated
  on a dismissive verb so literal simultaneity never fires.
- fake-casual-prop: stage directions, wink asides, and "because of
  course it does". Verdict closers and label-prefix openers stay
  LLM-judgment per the precision-over-recall policy.

Catalog 62 -> 65, engine 48 -> 51, word table unchanged at 112.

* Apply review fixes to the #128 detector trio

Addresses the three detector-surface items in the CHANGES_REQUESTED review,
plus the prose-scoping follow-up comment. Each item was reproduced against
the PR head before being changed.

1. `launch-intro`: the bare `Enter X.` surface is judgment-only. It matched
   "Enter Password." and "Enter Amount." verbatim, and "Enter Username —
   your work email." through the dash terminator; neither a terminator
   change nor a field-name denylist reaches the period-terminated class.
   The `Meet X, your new favorite…` and `Think X meets Y` surfaces stay.
   The three UI forms and "Enter Flowdesk." are pinned as must-not-fire.

2. `crowd-contrast`: the progressive branch is restricted to `-ing` forms.
   `(?:e|es|ed|ing)` let the adjective ("was still deliberate about"), the
   passive ("was still debated by pundits") and the bare present through;
   all three are now must-not-fire fixtures.

3. `fake-casual-prop`: `because of course …` is judgment-only. The present
   tense plus `did` gate does not hold — "The build failed because of
   course it did." is the ordinary human grumble in the same form. Two
   grumbles are pinned as must-not-fire.

Also scopes the prose claim: the "was still" marker gates the
debate/speculation branch only, and the two stereotyped variants
("wrote think-pieces", "played catch-up") match on their own wording.
SKILL.md, detector/CATEGORIES.md and the CHANGELOG say the same thing,
and the generated plugin/cursor copies are regenerated from SKILL.md.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* Disclose the crowd-contrast residue that was measured, not assumed

Beyond the review. A fresh-eyes pass turned up sentences that fire and
that the entry's disclosure did not cover; every one was reproduced
against this branch before being written down.

- Branch one fires on any literal progressive use of its verbs, not only
  on "was still debating": "while the market was still speculating about
  the price" and "while others were still arguing about procedure" are
  ordinary wire copy and both fire.
- Branches two and three fire on literal contrasts of their own: "while
  everyone else wrote think-pieces from Washington" (a real reporting
  contrast) and "while everyone else played catch-up in the spring"
  (sports and classroom narrative).
- The wink-aside regex accepts all four of (yes|no) x (really|seriously);
  the entry named two.

No regex changes: these are accepted under precision-over-recall, and
narrowing them is the maintainer's call, not a review item. The prose now
states what the engine does instead of a tighter gate it does not enforce.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* Tighten two surfaces and make every entry state what its regex does

Cross-family review (Codex / GPT-5.6). Each item was reproduced against
`land-pr-128` before the change and re-measured after.

Regex changes, both false positives on ordinary prose:

1. `fake-casual-prop`: `chef['’]?s\s+kiss` made the apostrophe optional, so
   "At midnight, *chefs kiss* their spouses goodbye" fired. The apostrophe
   is now required, straight or curly.
2. `launch-intro`: `the\s+new\s+(?:standard|way|home)\b` let the head noun
   swallow the first word of a compound noun — "Meet Rosa, the new home
   secretary" and "Meet Emma, the new way station manager" both fired. Each
   head now needs the tail launch copy actually has (`home of`, `way to`,
   `standard in|for`) or an end of clause. "Meet Riverside, the new home of
   our Saturday farmers market." still fires.

Not changed, disclosed instead: "Meet Alice, your new favorite aunt" and
"Think Alice meets Bob at noon" fire. They are person-name variants of the
two surfaces the maintainer asked to keep, so narrowing them would cost the
surfaces themselves.

Test change: the `(yes, really)` positive shared a fixture with
`*checks notes*` and only asserted that some `fake-casual-prop` existed, so
replacing the wink regex with a never-match left it green. It is now an
independent case asserting the matched text.

Prose: the three entries and the CATEGORIES rows now state the actual gates
— the four `Meet` heads and the one-token 2-30 character name; the
`was|were|is|are` + `still` + `-ing` branch, the `writing|wrote` branch and
the `play|plays|played|playing` branch; the six stage directions and four
parentheticals — plus the measured misses that follow from closed lists:
two-token names ("Meet North Star", "Think Google Docs meets Microsoft
Word"), crowds outside the list ("every competitor", "our rivals"), and
register neighbours ("*checks calendar*", "(yes, honestly)").

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

---------

Co-authored-by: welttowelt <welttowelt@users.noreply.github.com>
Co-authored-by: Conor Bronsdon <120674402+conorbronsdon@users.noreply.github.com>
Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-03 12:24:44 -07:00
tech nasty 3bd64f19f4 Add seven rhetorical-tic categories from Simon Willison's LLM cliché highlighter (#138)
* Add seven rhetorical-tic categories from Simon Willison's LLM cliche highlighter

Three with detector types (performed-insight, negation-chain,
dev-blog-boilerplate) plus fixtures; four as skill-only judgment rules
with reasons recorded in CATEGORIES.md. Counts bumped per the CI
contracts (69 pattern categories, 51 engine types); version 3.28.0.

* Address review: sync 3.28.0 release artifacts, narrow detector precision

- Bump package.json, plugin.json, and regenerate the bundled skill and
  cursor rule (plugin-skill-sync now passes locally).
- negation-chain: the no-chain must open its sentence (mid-sentence
  inventories stay clean); the did-not chain is comma-joined with the
  subject elided (sequential narration stays clean).
- performed-insight: sit-with requires a boundary or 'for a moment'
  after that/this; the 'only X I trust' branch is dropped; sentence-
  initial 'Turns out' uses a lookbehind so the issue text and index no
  longer consume the previous sentence boundary.
- dev-blog-boilerplate: 'it just works' no longer matches the phrasal
  'it just works out'.
- Must-not-fire fixtures added for every reproduction in the review,
  plus a text/index regression assertion for Turns out.

* Narrow rhetorical-tic detector precision

* Align narrowed detector docs and slogan coverage

---------

Co-authored-by: tech nasty <262050521+t3chnaztea@users.noreply.github.com>
Co-authored-by: Conor Bronsdon <120674402+conorbronsdon@users.noreply.github.com>
2026-08-28 21:15:27 -07:00
jeffhuen 4e79a67871 feat: add rendered Markdown source mode (#137)
* feat: add rendered Markdown source mode

* fix: address rendered Markdown review regressions

* fix: close rendered HTML comments before code masking

---------

Co-authored-by: Conor Bronsdon <120674402+conorbronsdon@users.noreply.github.com>
2026-08-28 11:59:06 -07:00
宇宙的山峰 40328bd292 docs: restrict edit mode to prose files (#136)
Co-authored-by: Conor Bronsdon <120674402+conorbronsdon@users.noreply.github.com>
2026-08-24 10:41:23 -07:00
Michael Hall 0bdab7bfbb docs: document npx skills as a universal install method (#131)
* docs: document npx skills as a universal install method

Points users at vercel-labs/skills (npx skills add) as the fastest way to
install this skill into any of its 75+ supported agents, with npx skills
update covering future updates. Existing manual per-platform steps stay as
a no-Node fallback.

* address review feedback: pin npx version, dedupe count, add changelog entry

- Pin npx skills invocations to @latest explicitly and note it runs
  third-party code, with a pointer to pinning a specific version instead.
- State the "75+ agents" figure once instead of in two places.
- Add the 3.25.1 CHANGELOG entry this repo's conventions expect for a
  notable change, even though no rule/detector content changed.

* address maintainer review: pin skills@1.5.23, fix behavior claims, add repository field

- Pin npx invocations to skills@1.5.23 instead of @latest for a reproducible
  install, and note the CLI's Node >=22.20.0 requirement.
- Correct the install description: for a root-level skill like this one, the
  CLI's GitHub blob fast path installs SKILL.md only, not the whole repo
  (per vercel-labs/skills src/blob.ts). git clone remains the documented
  route for the detector, tests, and other repo tooling. Drops the now-
  redundant raw-SKILL.md-URL example since the shorthand does the same thing.
- Correct the update description: skills update prompts for project/global
  scope and refreshes the selected scope, not every install across both.
- Add metadata.repository to SKILL.md's frontmatter so a copy installed via
  the SKILL.md-only fast path still links back to the project. Synced to the
  plugin copy via the existing sync-plugin-skill.sh.

* fix: vary sentence structure instead of repeating em-dash appositive

Self-audit with the avoid-ai-writing skill flagged the same "clause —
appositive clause" shape used six times in ~600 words across the new
Quick Install prose. Split into separate sentences, semicolons, and
commas as appropriate, keeping one dash for genuine variety instead of
zero.

* docs: clarify skills CLI install behavior

---------

Co-authored-by: Conor Bronsdon <120674402+conorbronsdon@users.noreply.github.com>
2026-08-24 10:27:58 -07:00
Mahin Nadir ca2206c2f5 Bind voice-profile targets to Never-inject guardrails (fixes #100) (#133)
* Bind voice-profile targets to Never-inject guardrails (fixes #100)

* fix-ups for #133: sync generated copies, changelog, and formatting

- drop the unrelated Dockerfile
- give the guardrail intro line its own paragraph (leading space folded
  it into the previous one) and fix the professional-profile comma splice
- bump plugin.json to 3.25.1 and regenerate the bundled plugin skill and
  cursor rule via the sync scripts
- add the 3.25.1 changelog entry crediting @mahinNadir

npm test green (39/39 check-style, full suite passes).

---------

Co-authored-by: Conor Bronsdon <120674402+conorbronsdon@users.noreply.github.com>
2026-08-21 18:09:23 -07:00
cland4449 8277224829 Add paraprosdokian detection category (v3.26.0)
LLMs deploy twist-ending sentences as a default wit move, clustering in
hooks, closers, and list-final items. The reversal substitutes a rhythm
trick for a claim, so flag it in analytical and professional prose.
Includes the scale-then-deflate marketing variant ("Four steps, and only
one of them is yours."). LLM-judgment rule with no detector type: spotting
a twist requires reading setup and payoff together, which a regex cannot.
Engine stays at 48 types and the word table at 112.

Catalog goes from 62 to 63 categories, P1 severity. Cursor port and
plugin copy synced, counts verified against CI scripts.
2026-08-17 10:02:12 +10:00
welttowelt 6f77e683cf Add catalog-only entries from #108: false agency, transformation crutch, domain-term collision
Judgment-only rules per the precision-over-recall policy, with the
carve-outs written as operative entry text per review:

- False agency: literal verbs and collective-actor shorthand ("the
  market rewards shipping") are protected in the entry itself.
- Transformation crutch: literal and mechanism-stated transformations
  stay unflagged.
- ZK/crypto domain-term collision ships as two genre-scoped Tier 3
  phrase rows (skipped by the deterministic engine); the cross-genre
  generalization is held as a note.
- "This matters because" joins the persuasive-authority tropes;
  the concession-fragment reassurance pair joins manufactured
  punchlines.

Catalog 65 -> 67, README Tier 3 phrase count 10 -> 12; engine stays
at 51, word table at 112.
2026-08-16 18:16:28 +02:00
welttowelt 7b5fdc73b2 Add detector trio from #108: launch intros, crowd contrast, fake-casual props
Three regex-detectable patterns from the welttowelt merged-system diff,
each with a must-fire and a must-not-fire fixture:

- launch-intro: sentence-initial imperative product introductions
  ("Enter X.", "Meet X, your new...", "Think X meets Y"). "Say hello
  to X" stays judgment-only ("Say hello to Grandma." is ordinary prose).
- crowd-contrast: the trailing "while everyone else..." clause, gated
  on a dismissive verb so literal simultaneity never fires.
- fake-casual-prop: stage directions, wink asides, and "because of
  course it does". Verdict closers and label-prefix openers stay
  LLM-judgment per the precision-over-recall policy.

Catalog 62 -> 65, engine 48 -> 51, word table unchanged at 112.
2026-08-16 18:14:31 +02:00
Conor Bronsdon 3c0fd8a266 Add actually as a cut-first writing signal (#126)
Co-authored-by: Codex <codex@openai.com>
2026-08-12 21:06:47 -07:00
Michael Hall 46087cea58 feat: detect unnecessary hyphenation (#120)
* feat: detect unnecessary hyphenation

* fix(detector): harden hyphenation masking

* fix(detector): mask long path components

* fix(detector): keep zero-weight copyedits out of AI highlights

buildSentenceRegions() mapped every text-bearing issue into
highlight_sentence_for_ai, so a copyedit-only document scored 0 and
classified HUMAN_ONLY while still reporting an AI-highlighted region.

Rename SUMMARY_ONLY_TYPES to NON_HIGHLIGHT_TYPES, since the set now
covers both anchorless summary signals and anchored style-only findings,
and add unnecessary-hyphenation to it. The finding stays in issues[] at
P2 with its weight of 0; scoring and trinary classification are
unchanged.

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

---------

Co-authored-by: Conor Bronsdon <cmbronsdon@gmail.com>
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
2026-08-12 17:45:12 -07:00
Conor Bronsdon a575602b3d release: 3.23.1 — constructor false-positive fix, automated npm publishing (#117)
Version bumped across all five sites (SKILL.md, plugin copy, plugin.json,
package.json, cursor rules regenerated via the sync scripts). First release
through the guarded publish pipeline from #113.

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-08-05 12:24:51 -07:00
Clay f666087e52 feat: optional --style house-style layer (config-driven, points at Vale) (#99)
* 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>
2026-08-03 17:48:46 -07:00
Conor Bronsdon 2c82c30c23 cursor-rules: regenerate from SKILL.md and guard against drift (#98)
The Cursor port was a hand-made copy stranded at v3.16.0 while
SKILL.md reached v3.22.3 — its own README said 'no automated sync
today, open an issue if drift becomes a problem.' It did.

scripts/sync-cursor-rules.sh now generates the .mdc from SKILL.md:
Cursor frontmatter with the version derived from the SKILL.md
frontmatter, plus the three portability rewrites a copied-out rule
needs (no repo self-reference, no CATEGORIES.md citation, manual
preservation check instead of node detector/validate.js). Each
rewrite is anchored on exact upstream text and exits non-zero if the
anchor stops matching once, so an upstream edit to a ported span
breaks CI here instead of silently shipping a wrong rule.

plugin-skill-sync workflow regenerates the rule on every SKILL.md
change and fails on drift; cursor-rules/** added to its path filters
so a hand-edit to the .mdc alone can't dodge the check.

Negative control run: mutating a ported span in SKILL.md makes the
script exit 1 with an actionable message; restoring it regenerates
byte-identically (second run idempotent).

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-08-03 12:35:44 -07:00
mrlsecurity 22529c2338 Add "verbatim" as a Tier 3 (density-gated) word (#63)
Adds "verbatim" to the word table at Tier 3, so it flags only on overuse rather than always. Contributed by @mrlsecurity at Tier 1; moved to Tier 3 on review since the case is redundancy, not AI-specific frequency, and always-flagging over-fires on ordinary human writing.
2026-07-29 10:55:44 -07:00
wilu222 53ae05a88e v3.16.0: add "load-bearing" (metaphor) to Tier 1 (#55)
Adds metaphorical "load-bearing" as a Tier 1 phrase — an LLM tell for labeling any dependency an argument rests on ("load-bearing assumption/claim/invariant"). Matches the hyphenated compound only; unhyphenated "load bearing" is ordinary English.

Construction carve-out exempts attributive use before a literal structural noun (wall, beam, column, joist, truss, member, footing, slab, stud, partition, masonry, lintel, pier, rafter, girder, capacity), with an optional material/position adjective in between. Abstract-capable nouns (structure, element, frame, foundation) are excluded so the metaphor still fires on "the load-bearing structure of his argument".

Known gap: predicative use ("the wall is load-bearing") still flags — the tell lives in the subject, which a lookahead cannot reach. Carve-out design tracked in #56.

Sources: Marek Suppa, Yaniv Bernstein, Developers Digest, HN 48905248, r/ClaudeAI.
2026-07-16 12:22:58 -07:00
Conor Bronsdon 500ff59006 v3.15.0: conversational-register patterns (wall-of-text, recap-flattery) (#53)
* v3.15.0: conversational-register patterns (wall-of-text, recap-flattery)

Adds three catalog entries prompted by a real-world GitHub issue exchange
where a maintainer called out an assisted-sounding reply with "I prefer
to talk human to human" (name/repo withheld):

- Wall-of-text replies: reply-length text delivered as one unbroken
  paragraph with no line breaks, where humans in conversational registers
  break at thought boundaries instead. Documented as an LLM-judgment
  rule after a first-pass detector implementation broke an existing
  calibration fixture and, on review, would have fired on any ordinary
  short paragraph rather than anything AI-specific.
- Recap-flattery opener: summarizing the reader's own work back at them
  with praise before getting to the point. LLM-judgment rule.
- Immaculate typography in casual registers: folded into the existing
  Formatting section at the same weak-signal tier as curly quotes, plus
  its inverse (preserve a human's typos when editing their casual text).

Catalog goes from 51 to 53 detection categories; the deterministic
engine stays at 45 types (no new type — see the CATEGORIES.md §C note
and the NOTE in patterns.js for why the detector attempt was reverted).
Also catches the Cursor port up from v3.12.0 to v3.15.0, closing a gap
where it had missed the 3.13.0 and 3.14.0 rule changes.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Review fixups: recap-flattery dedup line + wall-of-text carve-out

Two neighbor-standard gaps found in adversarial review of the new
conversational-register rules:

- Recap-flattery opener now explicitly distinguishes from Sycophantic
  tone and Acknowledgment loops (every adjacent category carries a
  "Distinct from X" clause; without it the skill's audience would file
  dupes against those two).
- Wall-of-text replies now carries an explicit legitimate-use carve-out
  (a single dense paragraph is correct in blog/docs/formal registers),
  per CONTRIBUTING's precision-over-recall rule. Notes why a tolerance
  matrix row is the wrong scoping home: a plain issue comment
  auto-detects to the `blog` profile, so a skip-on-blog cell would
  suppress the rule in the exact register it targets.

Ported to cursor-rules/.mdc and synced to the plugin copy.
Contracts still green: npm test (45 detector types), pattern count 53.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-08 12:59:44 -07:00
Conor Bronsdon f8d756ae5d Sync Cursor port to v3.12.0 (#46)
Catch the Cursor .mdc port up to SKILL.md, which advanced from 3.7.2 to
3.12.0 while the port stayed pinned. Ports the rule changes only; no
change to SKILL.md, the detector, or plugins.

- 3.8.0: Self-labeling significance section
- 3.9.0: Social endorsement closers tolerance-matrix row (section body
  was already present)
- 3.10.0: List-label periods section
- 3.11.0: split-sentence variant of the "It's not X, it's Y" rule
- 3.12.0: "quietly" Tier 2 word-table row
- #11: AI-tool fingerprint sections (unfilled placeholders, chatbot
  citation markup leaks, AI-tool URL parameters)

Frontmatter version reference bumped to v3.12.0. The two "with the Edit
tool" phrasings stay omitted, matching the port's existing Cursor
adaptation.

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 00:00:28 -07:00
Conor Bronsdon 13b644c548 Add "match inflected forms" rule to the word-replacement section (#37)
The word table half-covered morphological variants and was inconsistent
about it (some rows list `x / xly`, most don't), so an auditor reading
`genuine` / `leverage` / `robust` had no instruction to extend to
`genuinely` / `leveraging` / `robustly`. Rather than enumerate every
inflection in every row, add one interpretive rule: each entry covers the
listed word and its variants (adverb, gerund, plural, comparative, verb
conjugations) unless a variant has a distinct legitimate sense, judged by
context. Future-proofs new entries and closes the gap that let "genuinely"
through. Applies to the LLM/prose path; detector regex parity is a
separate follow-up.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 16:02:01 -07:00
Conor Bronsdon 15c1083cc1 Fix em-dash mojibake (U+FFFD) in skill docs (#36)
10 spots in SKILL.md (mirrored in cursor-rules and the synced plugin copy)
had the Unicode replacement character where an em dash belonged, from a
lossy cp1252 round-trip somewhere in the file's history. Affected the
rhetorical-question/list-intro tells, the six voice-profile definitions
(linkedin/blog/technical-blog/investor-email/docs/casual), and one
profile-matrix table cell. Restored each to an em dash, matching the
surviving uncorrupted twin at the `technical` profile line. Byte-level
substitution only; no other content or line-ending changes.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 15:36:49 -07:00
Conor Bronsdon 98209a1c3c Add "genuinely" to hollow-intensifiers rule and word table (#35)
The detector regex already matched /\bgenuine(?:ly)?\b/, but the SKILL.md
prose and word-removal table only named the adjective "genuine", so
LLM-driven /clean-ai-writing audits could miss the adverb. Spell it out
across SKILL.md, the cursor-rules mirror, and the synced plugin copy.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 14:33:37 -07:00
Conor Bronsdon 4331560d02 Detect social endorsement closers (#29) (#30)
* Add social endorsement closer detection (#29)

LLMs commonly close LinkedIn/X share posts with a generic curatorial
sign-off teeing up a link — "This one is worth your time:", "Do yourself
a favor and read this", "Thank me later". The endorsement is
demonstrative-anchored and could sit under any link, which is the tell.

- New detector `type` social-cta-closer (engine 43 → 44 types), weighted
  like formulaic-opener (8) so the length divisor doesn't wash it out on
  a short post. Severity high (P1).
- New SKILL.md "Social endorsement closers" section (catalog 47 → 48),
  plus P1-list and tolerance-matrix rows (strict on linkedin).
- Demonstrative anchors ("this one", "do yourself a favor", "won't want
  to miss") keep it off plain human endorsements ("the book is worth
  reading, but the middle drags"). Distinct from the bare "worth
  [verb]ing" word-table entry and from infomercial mid-flow hooks.
- Tests: 3 fixtures (LinkedIn share post, bare-CTA variants, human-prose
  negative). Mirrored into cursor-rules + synced plugin skill; counts
  updated across README/CATEGORIES/package.json; version 3.8.0 → 3.9.0.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Harden social-cta-closer regexes against review findings

Two-agent review (code-reviewer + test-analyzer) found that 6 of the 10
closer patterns dropped their anchor and fired on ordinary prose, and
that the contraction branches missed curly apostrophes — so the detector
skipped the exact "you won't" form its own docs ship as the canonical
example (LinkedIn/Word/macOS auto-curl to U+2019).

Precision fixes:
- Apostrophe classes now admit U+2019 across every contraction branch
  (won't / don't / can't / one's / you'll), matching the house style of
  the existing smart-punct detector.
- "do yourself a favor and read THIS/IT" — gated to a demonstrative
  object, so "...read the runbook" no longer matches.
- "miss this" / "bookmark this" — trailing-terminal lookahead, so the
  closing-line shape fires but "miss this meeting" / "bookmark this page"
  don't.
- "thank me later" / "save this for later" — sentence-initial lookbehind
  (kept match text clean), so "she will thank me later" / "I usually save
  this for later" don't.
- "trust me, ..." — dropped the bare "this one" branch that caught
  "trust me, this one took all afternoon."

Tests: branch-coverage fixture (one positive per regex so a typo fails
loudly), a curly-apostrophe fixture, and a 7-case literal-prose negative
table built from the reviewers' false-positive probes. 66 checks green;
count + plugin-sync gates pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 00:17:42 -07:00
Conor Bronsdon efdbb6a862 v3.7.2: calibrate curly-quotes rule per missed #15 review (#27)
The #15 merge shipped the un-tightened rule and missed the inline review
suggestions. Applies them now:
- Reframe curly quotes/apostrophes from a "strong" tell to a WEAK,
  corroborating signal — meaningful mainly in plain-text contexts
  (code, commit messages, plaintext drafts), since Word/Docs/macOS/iOS
  auto-curl by default.
- Stop flagging curly apostrophes (U+2019) standalone (every
  contraction has one — discriminates nothing).
- Fix the German low-9 example; keep consistent with the deterministic
  detector's co-occurrence logic (#16).

Verbatim from @conorbronsdon's #15 inline suggestions. Mirrored to the
Cursor rule, version 3.7.1 -> 3.7.2, bundled skill re-synced.

Co-authored-by: augustasas <augustasas@users.noreply.github.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 02:06:11 -07:00
Conor Bronsdon 4190d0fb8d Merge main into #15 + reconcile curly-quotes rule (v3.7.1)
Brings @augustasas's curly-quotation-marks rule up to date with main and
reconciles it with the overlapping "mixed straight/curly punctuation"
bullet that shipped in 3.7.0: keeps his stronger fingerprint framing
(curly-in-otherwise-ASCII = copy-paste-from-chat tell) plus his
publication-typography and locale carve-outs, and folds the mixed-case
note into it as one clause. One coherent Formatting rule, not two.

Mirrored to the Cursor rule, version 3.7.0 -> 3.7.1, bundled skill
re-synced.

Co-authored-by: augustasas <augustasas@users.noreply.github.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 01:47:43 -07:00
Conor Bronsdon b5241a35df v3.7.0: catalog candidates — mixed punctuation, hyphenated pairs, gap-filling, authority tropes (#24)
Closes #22. Ports the four catalog candidates from competitive research:
- Formatting: mixed straight/curly punctuation (paste-from-chat tell)
- New: hyphenated-pair overuse (density + attributive/predicate error)
- New: speculative gap-filling (hedged guesses dressed as background)
- Confidence calibration: extended with persuasive-authority tropes

Adapted from blader/humanizer (P21/P26/P27) + Wikipedia "Signs of AI
writing." Mirrored to the Cursor rule, version 3.6.0 -> 3.7.0,
CHANGELOG, bundled skill re-synced.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 01:09:14 -07:00
Conor Bronsdon ee686b7ab3 v3.6.0: voice profiles + edit mode + iterate-to-convergence (#23)
* v3.6.0: voice profiles + edit mode + iterate-to-convergence

Implements the low-risk product features from the competitive feature
spec (P1.C). Deferred: --score (#21) and 4 catalog candidates (#22).

- Voice profiles: optional persona axis (casual/professional/technical/
  warm/blunt), orthogonal to the audience context profiles, with
  concrete craft-backed targets (sentence length, contractions, hedging,
  jargon, rhythm) + optional calibration to a writing sample + a
  composition rule (voice = target, context = strictness, resolve
  toward stricter).
- Edit mode: third mode that edits a named file in place via the Edit
  tool with minimal, human-preserving changes, then verifies.
- Iterate to convergence: capped (N=2) audit->rewrite loop generalizing
  the existing second pass.
- Documented optional flags alongside natural-language triggers.

Mirrored to the Cursor rule, version 3.5.0 -> 3.6.0, CHANGELOG, bundled
skill re-synced.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Address sub-agent review of #23

- Voice/context composition: fix the worked example that contradicted
  its own "resolve toward stricter" rule (blunt+blog em-dashes), and
  state explicitly that a voice positive-target applies even where a
  context profile skips that category. Also drops a copula-avoidance
  "means" the skill flags elsewhere.
- Edit mode: add guardrail — don't edit quoted/code/third-party text
  (flag instead); confirm scope on large files.
- Iterate: clarify the built-in corrective pass IS pass 2 (--iterate
  doesn't stack), and cut hedge/filler phrasing.
- Docs staleness: README "Two modes" -> "Three modes" (+ Edit bullet,
  voice note, description) and CLAUDE.md "two modes" -> "three modes".

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 01:01:25 -07:00
Conor Bronsdon 12b4c41e13 v3.5.0: catalog adds from competitive audit (P38/P41/P43 + P40) (#20)
* v3.5.0: add P38/P41/P43 catalog entries + sharpen P40

Ports the unambiguous catalog wins from the competitive audit of
Aboudjem/humanizer-skill (the P33-P35 fingerprints already shipped in
#11; these are the remaining "P1.B" spec adds):

- Infomercial engagement hooks (P41) — "The catch?", "The kicker?",
  "Here's the thing." — distinct from rhetorical-question openers.
- Paragraph-reshuffle immunity (P38) — writer-side structure test.
- Treadmill effect / low information density (P43) — writer-side
  content test, "what's actually new here?"
- Superficial -ing analyses — extended to the declarative
  meaning-telling variant (P40).

Mirrored to the Cursor rule, version bumped 3.4.0 -> 3.5.0 (SKILL.md +
plugin.json + CLAUDE.md), bundled plugin skill re-synced, CHANGELOG
updated with source attribution.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Tighten P43 entry: cut aphoristic "density is the antidote" line

Self-audit flagged it as mildly significance-inflating (adjacent to the
"generic conclusions" pattern the skill itself flags) and redundant with
the preceding sentence. Dogfooding.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 00:01:33 -07:00
Conor Bronsdon a64723d73c feat: position-pivot preface + Cursor rule port (#10)
* feat: position-pivot preface + Cursor rule port

Two low-hanging-fruit items from the May 2026 competitive landscape
research (private docs at avoid-ai-writing-app/docs/competitive/).

1. SKILL.md preface — "What this skill is and isn't"

   Frames the skill explicitly as a writing-quality nudge, not a
   forensic AI detector. The independent-audit evidence against
   detection-as-forensics is now overwhelming:

   - Liang et al. (Stanford, Patterns 2023): 61.3% of TOEFL essays
     flagged AI; 19.8% unanimously misclassified by 7 detectors
   - Jabarian & Imas (BFI WP 2025-116, 2025): OSS detectors
     misclassify up to 78% of human text
   - Adversarial paraphrasing (arXiv:2506.07001, June 2025): defeats
     every detection method tested, including those trained against
     paraphrase, with ~88% T@1%F reduction
   - Turnitin lost its first lawsuit Feb 2026 (Newby v. Adelphi);
     downstream cases pending at Yale, Michigan, Palo Alto HS

   The skill's framing now disavows the forensic use case explicitly:
   patterns are real and worth fixing in your own writing; they are
   NOT evidence about anyone else's. Inoculates the project against
   the reputational + liability risk hitting Turnitin et al.

2. Cursor rule — `cursor-rules/avoid-ai-writing.mdc`

   Modern `.cursor/rules/*.mdc` format port of SKILL.md. Activates on
   prose file globs (.md, .mdx, .txt, .rst, .adoc) — no
   alwaysApply, so the rule doesn't interfere with code work. Body is
   byte-for-byte SKILL.md content; only the frontmatter differs.

   Opens a new distribution channel: `PatrickJS/awesome-cursorrules`
   (39.5K stars) has zero prose-humanizer entries. First-mover
   opportunity. Submission to the awesome-cursorrules list is the
   natural follow-up.

   README.md updated with install snippet pointing at raw.githubusercontent
   so users can grab the file with one curl.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs: add Vocabulary diversity (stylometric) section

First stylometric signal documented in the spec. TTR threshold (< 0.40
on >= 200-word samples) matches the detector implementation in
avoid-ai-writing-app#TBD. Three other stylometric signals on the roadmap
(sentence-length burstiness as continuous, function-word z-scores,
POS-bigram log-odds) named but not yet implemented.

Driven by the May 2026 competitive-landscape research
(detection-research lens): academic detectors lean heavily on
stylometric features, current avoid-ai-writing is regex-only. Layering
stylometry closes the methodological gap without requiring transformer
inference or a POS tagger dependency for this first signal.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs: soften preface from prohibition to calibration

Feedback: the prior wording ("do not use it to make decisions",
"not evidence about anyone else's") was overcorrected. The right
framing is signals-not-proof, not signals-not-allowed. Detector
output is legitimate input; just not the sole basis for adverse
action. Updated preface accordingly.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* chore(cursor-rules): re-sync after preface softening

Body re-extracted from SKILL.md after the previous commit's wording
update. Frontmatter unchanged.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-16 22:48:32 -07:00