Files
conorbronsdon__avoid-ai-wri…/package.json
T
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

28 lines
981 B
JSON

{
"name": "avoid-ai-writing-detector",
"version": "3.29.0",
"description": "Deterministic detection engine for the Avoid AI Writing skill \u2014 pattern + stylometric analysis of AI-generated text.",
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/conorbronsdon/avoid-ai-writing.git"
},
"main": "detector/patterns.js",
"files": [
"detector/patterns.js",
"detector/validate.js"
],
"engines": {
"node": ">=18"
},
"scripts": {
"test": "node detector/patterns.test.js && node detector/categories.test.js && node detector/validate.test.js && node scripts/corpus.test.js && node scripts/check-style.test.js",
"self-scan": "node scripts/self-scan.js",
"self-scan:check": "node scripts/self-scan.js --check",
"corpus": "node scripts/corpus.js list",
"corpus:fetch": "node scripts/corpus.js fetch",
"corpus:verify": "node scripts/corpus.js verify",
"fp": "node scripts/fp-measure.js"
}
}