The acknowledgment-loop type matched "you're asking about", "the question of whether" and "to answer your question". All three fire on ordinary human text: reply openers in email, support and docs, and standard analytical English. Position cannot separate them from the tell, because the false-positive replies are document-initial too, and the tell itself is a restatement that adds nothing, which a regex cannot read. Remove the type, record the reasoning under Skill-only in CATEGORIES.md, add the deletion test and carve-outs to the rule, and pin the three sentences from the issue as must-not-fire fixtures. Fixes #239 Co-authored-by: Conor Bronsdon <120674402+conorbronsdon@users.noreply.github.com> Co-authored-by: Conor Bronsdon <conorbronsdon@users.noreply.github.com>
13 KiB
Category map: references/patterns.md ↔ detector
This table is the anti-drift contract between the human-readable rules in
../references/patterns.md and the executable engine in patterns.js. When you add a rule to
the skill, decide here whether it's regex-detectable (give it a detector type)
or LLM-only judgment (mark it so). When you add a detector type, point it back
at the skill section it enforces.
The engine exposes 53 issue types (see TYPE_LABELS in patterns.js). The
skill has more ### sections than that — the gap is not missing coverage,
it's rules that are judgment calls a regex can't make. The three groups below
account for every entry on both sides.
Three counts coexist on purpose and should not be forced to match: the README's
pattern-category count (the human-facing prose catalog, derived from references/patterns.md
and guarded in CI), the engine's 53 types (which split the vocabulary tiers
and add stylometric signals), and references/patterns.md's ### sections (which also include
writer-side tests with no detectable form). The
categories.test.js enforces the engine ↔ this-file mapping, and checks every
prose statement of the engine type total against TYPE_LABELS.
A. Direct mapping (skill rule → detector type)
Detector type |
Label | references/patterns.md section |
|---|---|---|
tier1 / tier2 / tier3 |
AI vocabulary / Word cluster / Overused word | Words and phrases to replace (load-bearing: immediate abstract-noun allowlist only; literal, predicative, and unlisted forms pass; technical context mode suppresses eight technical-legitimate terms: robust, comprehensive, seamless, ecosystem, leverage, facilitate, underpin, streamline) |
tier1-clarity |
Wordiness | Words and phrases to replace (Tier 1B) |
transition |
AI transition | Transition phrases to remove or rewrite |
template-phrase |
Template phrase | Template phrases (avoid) |
tier3-phrase / tier3-phrase-cluster |
Boilerplate phrase / cluster | Template phrases (avoid) |
chatbot |
Chatbot artifact | Chatbot artifacts |
sycophantic |
Sycophantic tone | Sycophantic tone |
filler |
Filler phrase | Filler phrases |
hollow-intensifier |
Hollow intensifier | Filler phrases (intensifiers), except context-dependent actually (see §C) |
generic-conclusion |
Generic conclusion | Generic conclusions |
social-cta-closer |
Engagement-bait closer | Social endorsement closers |
future-narrative |
Generic future narrative | Generic future-narrative closers |
lets-construction |
"Let's" opener | "Let's" constructions |
reasoning-artifact |
Reasoning artifact | Reasoning chain artifacts |
significance-inflation |
Significance inflation | Significance inflation |
novelty-inflation |
Novelty inflation | Novelty inflation (the invented-concept-labels sub-rule is LLM-judgment only — open-ended coinages aren't regex-matchable) |
real-actual-inflation |
"Real/actual" inflation | "Real/actual" adjective inflation |
vague-attribution |
Vague attribution | Vague attributions |
emotional-flatline |
Stock reaction framing | Stock reaction framing / Superficial -ing analyses (stable API type; style-only for authorship scoring under the precision-first evidence policy) |
lingering-attention |
Lingering-attention claim | Lingering-attention claims (noun-anchored frames only — the bare "I keep coming back to X" stays LLM-judgment, since a following reason clause makes it legitimate and isn't regex-detectable) |
cutoff-disclaimer |
Cutoff disclaimer | Cutoff disclaimers |
false-concession |
False concession | False concession structure |
rhetorical-question |
Rhetorical question | Rhetorical question openers |
formulaic-opener |
Formulaic opener | Formulaic challenges |
speculative-opener |
Speculative scenario opener | Speculative scenario openers |
confidence-calibration |
Confidence stacking | Confidence calibration phrases |
hedge-stack |
Hedge-stacked prediction | Hedge-stacked predictions |
parenthetical-hedge |
Parenthetical hedge | Parenthetical hedging |
hashtag-stuff |
Hashtag stuffing | Hashtag stuffing |
bullet-np-list |
Bullet-NP list | Bullet lists of bare noun phrases |
title-case-header |
Title Case header | Title case headings |
em-dash / formatting |
Em dash overuse / Formatting | Formatting |
uniformity |
Rhythm uniformity | Rhythm and uniformity |
low-ttr |
Low vocabulary diversity | Vocabulary diversity (stylometric) |
ai-placeholder |
Unfilled placeholder | Unfilled placeholders |
ai-citation-markup |
Chatbot citation markup leak | Chatbot citation markup leaks |
ai-utm-source |
AI-tool URL parameter | AI-tool URL parameters |
smart-punct-signature |
Smart-punct signature | Formatting (curly quotation marks) — partial |
unnecessary-hyphenation |
Unnecessary hyphenation | Unnecessary hyphenation (curated open, closed, and position-dependent subclasses only) |
launch-intro |
Launch-copy introduction | Launch-copy dramatic introductions ("Meet X," plus one of "your new favorite", "your new go-to", "the new home of", "the new way to", "the new standard in/for", or a bare home/way/standard at end of clause; and "Think X meets Y". X is ONE capitalized 2-30 character token, so two-token names miss. Bare "Enter X.", bare "Meet X, your new [role]" and "Say hello to X" stay LLM-judgment; person-name variants are disclosed residue — see the entry) |
crowd-contrast |
Dramatized crowd contrast | Dramatized contrast against the crowd (three branches: "was|were|is|are" + "still" + a dismissive verb in -ing, plus the stereotyped "writing|wrote think-pieces" and "play|plays|played|playing catch-up" wordings, which need no marker; the crowd is the closed list "everyone else|others|the industry|the market|the competition", so "every competitor" and "our rivals" miss — ordinary simultaneity without those verbs stays clean; every literal progressive use of them is accepted, disclosed residue, and so are literal "wrote think-pieces" / "played catch-up" contrasts — see the entry) |
fake-casual-prop |
Fake-casual prop | Fake-casual register (six asterisk stage directions and the four (yes|no) x (really|seriously) parentheticals, nothing else. "chef's kiss" requires its apostrophe, and neighbours like "checks calendar" and "(yes, honestly)" are disclosed misses. Verdict closers, label-prefix openers, the self-QA volley and "because of course it does" stay LLM-judgment) |
performed-insight |
Performed-insight phrase | Performed-insight phrases — partial; literal-sense exclusions documented in references/patterns.md |
negation-chain |
Negation chain | Negation chains — partial; three-item deterministic threshold documented in references/patterns.md |
dev-blog-boilerplate |
Dev-blog boilerplate | Dev-blog boilerplate — partial; literal-sense exclusion documented in references/patterns.md |
Partial map:
smart-punct-signaturefires only when curly quotes co-occur with an em-dash, an Oxford comma, and clean typing (≥80 words) — never on curly punctuation alone. The references/patterns.md Formatting rule treats curly quotes as a weak, corroborating signal in plain-text contexts and excludes apostrophes. The two agree in spirit (curly punctuation is never conclusive on its own) but differ in mechanism — so this is a partial map, not 1:1.performed-insightomits literal "the punchline" and "worth naming" senses;dev-blog-boilerplateomits literal "batteries included." Those ambiguous surface forms remain judgment rules rather than deterministic matches.negation-chainrequires three short sentence-initial "no …" items; two-item chains remain judgment calls.
B. Detector-only (stylometric / fingerprint — no skill prose)
These extend the skill with signals that work as math over the whole document, not as a phrase a human editor would look up:
Detector type |
Label | Why it's engine-only |
|---|---|---|
punct-distribution |
Punctuation distribution | Per-paragraph punctuation uniformity |
fnword-trigram-entropy |
Grammar repetition | Function-word trigram entropy |
cross-para-burstiness |
Cross-paragraph rhythm | Sentence-length variance across paragraphs |
normalization-flag |
Bypass-trick chars | Zero-width / homoglyph humanizer-bypass detection |
C. Skill-only (LLM judgment — no detector type)
Rules that require reading for meaning, so they live in the skill prose and are applied by the model, not the regex engine. Listed so future contributors don't mistake their absence for a coverage gap:
- Transformation crutch (P2 unexplained relabeling, evaluated across the passage; literal and explained changes pass)
- False agency (P2 obscured accountable decision-makers; conventional personification, collective actors, emergent change, and causal dependence pass)
- Audience-fit domain-term collision (ambiguous generic proof/proof point in cryptography; separate from vocabulary tiers)
- Consequence-free "This matters because" / "here's why that matters" restatements (concrete consequences pass)
- Repeated empty concession pairs under Manufactured punchlines (P2; meaningful concessions and isolated intentional pairs pass)
- Synonym cycling
- Copula avoidance
- Promotional language
- Context-dependent
actuallyas a hollow intensifier (delete it when it only adds emphasis; keep it when it carries a named correction or expectation gap). The same token performs both jobs, so matching it unconditionally would flag ordinary corrective prose. - Sentence structure: "It's not X — it's Y" / split-sentence form / multi-negation countdown / tailing negation
- Structural issues / Excessive structure / Inline-header lists / Numbered list inflation
- Moral-adjective category errors (including ontological slop on assumptions, gratuitous universal quantifiers)
- Invented contrast-pair mirroring
- Hyphenated modifier stacking
- Unnecessary hyphenation outside the detector's curated subclasses
- False ranges
- Notability name-dropping
- Vague third-party validation
- Self-labeling significance
- Wall-of-text replies (missing line breaks) (tried as a detector — "reply-length, >=4 sentences, zero newlines" — and reverted; it fires on any ordinary short paragraph, not just conversational-reply register, so it stayed judgment-only. See the NOTE in
patterns.jsnear the bullet-NP-list block) - Recap-flattery opener
- Acknowledgment loops (tried as a detector — "you're asking about", "the question of whether", "to answer your question" — and retired (#239): the first opens ordinary replies and support answers ("You're asking about the retry limit. It is five by default..."), the third opens replies to a named earlier question ("To answer your question from Tuesday: the invoice went out on the 3rd..."), and the second is standard academic and analytical English. Both reply openers are document-initial in those examples, so position cannot separate them from the tell. Judging it needs reading whether the restatement adds anything before the answer arrives)
- Narrated candor (tried as a detector and reverted: the phrasings are shared with idiomatic conflict-of-interest disclosure ("in the interest of full disclosure, I own shares in...") and with the ordinary English comparative ("I'd rather die than let you drive"), so any regex tight enough to avoid those stopped matching the tell. Judging it needs reading whether the clause carries information or only announces that information is coming)
- Immaculate typography in casual registers (folded into the Formatting section — same weak-signal tier as curly quotes, not a standalone category)
- Subjectless fragments and agentless passives (docs and changelog registers are carve-outs — the fragment is the correct form there)
- Diff-anchored writing (changelogs, release notes, and migration guides are carve-outs)
- Manufactured punchlines / staccato drama (including repeated setup/reversal punchlines: P2 only when repetition replaces concrete claims; supported reversals and intentional comedy, fiction, speeches, and quotations pass)
- Aphorism formulas (a regex for "X is the Y of Z" would flag ordinary genitive copulas — "Paris is the capital of France")
- Stacked rhetorical questions (interviews, FAQs, and dialogue stack questions legitimately; a regex can't read register)
- Same-opener sentence runs (whether the anaphora is earned is the whole judgment; pronoun-opener runs are ordinary narration)
- Stranded auxiliary contrast (a single instance is legitimate style; only density across a piece distinguishes voice from tic)
- Colon into a triple (three-item lists are often simply true, especially in technical writing — weigh by genre, not per hit)
- When to rewrite from scratch vs. patch
- Severity tiers (P0 / P1 / P2)
- Self-reference escape hatch
- Output format
Partial: the skill's six context profiles map to the engine's broader
options.contextModevalues as documented inreferences/patterns.md#detector-mode-mapping. Onlytechnicalcurrently changes flagging behavior (skips title-case headers and suppresses eight technical-legitimate terms:robust,comprehensive,seamless,ecosystem,leverage,facilitate,underpin,streamline);marketingandpersonalare accepted and reported in stats but score likegeneral. Full profile-based tolerance remains an LLM-side judgment.