newsjack 0.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/.mcp.json +9 -0
  2. package/.newsjack-npm +1 -0
  3. package/COMMIT +1 -0
  4. package/LICENSE +21 -0
  5. package/README.md +133 -0
  6. package/VERSION +1 -0
  7. package/bin/newsjack +74 -0
  8. package/package.json +37 -0
  9. package/skills/.gitkeep +0 -0
  10. package/skills/ETHICS.md +265 -0
  11. package/skills/WHY-NOT-SPAM.md +257 -0
  12. package/skills/angle-generator/SKILL.md +224 -0
  13. package/skills/angle-generator/examples.md +517 -0
  14. package/skills/angle-generator/rubric.md +219 -0
  15. package/skills/coverage-tracker/SKILL.md +124 -0
  16. package/skills/coverage-tracker-setup/SKILL.md +84 -0
  17. package/skills/crisis-holding/SKILL.md +336 -0
  18. package/skills/crisis-holding/examples.md +302 -0
  19. package/skills/crisis-holding/rubric.md +218 -0
  20. package/skills/fact-check/SKILL.md +212 -0
  21. package/skills/fact-check/examples.md +195 -0
  22. package/skills/fact-check/rubric.md +228 -0
  23. package/skills/journalist-fit-check/SKILL.md +199 -0
  24. package/skills/journalist-fit-check/examples.md +271 -0
  25. package/skills/journalist-fit-check/rubric.md +251 -0
  26. package/skills/meanest-editor/SKILL.md +112 -0
  27. package/skills/meanest-editor/examples.md +331 -0
  28. package/skills/meanest-editor/rubric.md +275 -0
  29. package/skills/media-list-manager/SKILL.md +204 -0
  30. package/skills/media-list-manager/examples.md +88 -0
  31. package/skills/media-list-manager/rubric.md +67 -0
  32. package/skills/news-search/SKILL.md +56 -0
  33. package/skills/newsjack-detector/SKILL.md +286 -0
  34. package/skills/newsjack-detector/examples.md +118 -0
  35. package/skills/newsjack-detector/references/engine-cli.md +29 -0
  36. package/skills/newsjack-detector/references/harness-routing.md +38 -0
  37. package/skills/newsjack-detector/references/rss-feeds.json +106 -0
  38. package/skills/newsjack-detector/rubric.md +160 -0
  39. package/skills/newsjack-monitor-setup/SKILL.md +202 -0
  40. package/skills/newsjack-monitor-setup/examples.md +106 -0
  41. package/skills/newsjack-triage/SKILL.md +98 -0
  42. package/skills/newsworthiness-check/SKILL.md +179 -0
  43. package/skills/newsworthiness-check/examples.md +232 -0
  44. package/skills/newsworthiness-check/rubric.md +218 -0
  45. package/skills/pr-strategist/SKILL.md +304 -0
  46. package/skills/reactive-comment/SKILL.md +297 -0
  47. package/skills/reactive-comment/examples.md +284 -0
  48. package/skills/reactive-comment/rubric.md +280 -0
  49. package/skills/relevance-coarse-filter/SKILL.md +61 -0
  50. package/skills/story-origin-check/SKILL.md +160 -0
  51. package/skills/voice-extractor/SKILL.md +330 -0
  52. package/skills/voice-extractor/examples.md +227 -0
  53. package/skills/voice-extractor/rubric.md +251 -0
  54. package/skills-manifest.json +254 -0
@@ -0,0 +1,227 @@
1
+ # Voice Extractor - Worked Examples
2
+
3
+ Real-format examples showing how `voice-extractor` behaves in extract, check, and enforce modes.
4
+
5
+ ---
6
+
7
+ ## Example 1: Founder First-Time Voice Init
8
+
9
+ ### Before
10
+
11
+ > "I'm doing my first newsjack voice init. Here are 8 samples in `~/samples/`:
12
+ > 3 tweets, 2 Slack messages to my cofounder, 2 old emails to journalists from
13
+ > 2024, and 1 LinkedIn post. Audience is mostly tech journalists. I write
14
+ > pitches and a bit of social."
15
+
16
+ Sample inventory:
17
+
18
+ | ID | Source | Audience | Date | Words |
19
+ |----|--------|----------|------|------:|
20
+ | s_001 | tweet | public | 2026-05-04 | 28 |
21
+ | s_002 | tweet | public | 2026-05-08 | 41 |
22
+ | s_003 | tweet | public | 2026-05-11 | 36 |
23
+ | s_004 | slack | internal | 2026-04-30 | 96 |
24
+ | s_005 | slack | internal | 2026-05-02 | 122 |
25
+ | s_006 | email | journalist | 2024-11-18 | 310 |
26
+ | s_007 | email | journalist | 2024-12-02 | 275 |
27
+ | s_008 | linkedin | public | 2026-03-19 | 332 |
28
+
29
+ ### Voice Extractor Output
30
+
31
+ ```yaml
32
+ profile_id: jane-doe-personal
33
+ sample_count: 8
34
+ sample_word_count: 1240
35
+ sample_age_p50_days: 27
36
+ register: casual-professional
37
+ intent: [pitches, social]
38
+ extraction:
39
+ confidence: medium
40
+ warnings:
41
+ - "1240 words is usable but light; add 8-10 more native samples for high confidence."
42
+ cadence:
43
+ sentence_length: { mean: 11.2, median: 9, p10: 3, p90: 24, stdev: 6.8 }
44
+ paragraph_length: { mean_sentences: 1.7, one_sentence_paragraph_frequency: 0.55 }
45
+ rhythm_signature: short-burst
46
+ mechanics:
47
+ contractions: yes
48
+ contraction_rate: 0.81
49
+ em_dash_usage: never
50
+ em_dash_per_1k_words: 0.0
51
+ oxford_comma: no
52
+ exclamation_rate_per_1k_words: 0.6
53
+ sentence_initial:
54
+ conjunction_starts_allowed: true
55
+ conjunction_start_rate: 0.18
56
+ uses_however_furthermore_moreover: false
57
+ idioms:
58
+ signature_phrases: ["the shape of this is", "two things at once", "fwiw"]
59
+ signature_words: [actually, basically, fwiw, ship]
60
+ openers:
61
+ observed: ["Quick one:", "Saw this:", "Heads up:"]
62
+ banned_from_use: ["I hope this email finds you well", "I wanted to reach out"]
63
+ ```
64
+
65
+ ### After
66
+
67
+ ```text
68
+ Voice fingerprint: jane-doe-personal
69
+ Saved: ~/.newsjack/voice/jane-doe-personal.yaml
70
+ Active profile: yes
71
+ Samples: 8 (1240 words)
72
+ Register: casual-professional
73
+ Confidence: medium
74
+
75
+ What I captured:
76
+ - Cadence: short-burst, mean 11.2 words/sentence, 55% one-sentence paragraphs
77
+ - Mechanics: contractions yes, em-dashes never, Oxford comma no
78
+ - Signature phrases: the shape of this is; two things at once; fwiw
79
+ - Banned for this profile: em-dashes, however/furthermore/moreover, stock pitch openers, global anti-slop list
80
+
81
+ Warnings:
82
+ - Usable but light. Add 8-10 more native samples when you have them.
83
+
84
+ Refresh after: 2026-08-16
85
+ ```
86
+
87
+ Why this works: the skill accepts the 8-sample set, stamps medium confidence, stores a local fingerprint, and makes the em-dash rule explicit before other skills draft as Jane.
88
+
89
+ ---
90
+
91
+ ## Example 2: Enforce Mode Catches A Bot Pitch
92
+
93
+ ### Before
94
+
95
+ Draft from another newsjack skill:
96
+
97
+ > Hi Sarah — Hope this finds you well. We're excited to announce that Acme has
98
+ > unveiled its revolutionary new platform, which leverages cutting-edge AI to
99
+ > deliver world-class results for enterprise customers. In today's
100
+ > ever-evolving landscape, it's not just a product, it's a paradigm shift.
101
+ > Looking forward to hearing from you. Best, Jane
102
+
103
+ Active fingerprint: `jane-doe-personal@2026-05-18`, confidence `medium`, em-dash usage `never`.
104
+
105
+ ### Voice Check Output
106
+
107
+ ```json
108
+ {
109
+ "verdict": "fail",
110
+ "pass_rate": 0.11,
111
+ "fingerprint_used": "jane-doe-personal@2026-05-18",
112
+ "violations": [
113
+ {"rule": "em_dash_against_fingerprint", "match": "—", "span": [9, 10], "severity": "block", "fix_hint": "fingerprint says em_dash_usage=never; use a comma, period, or colon"},
114
+ {"rule": "banned-opener", "match": "Hope this finds you well", "span": [11, 35], "severity": "block", "fix_hint": "open with the news"},
115
+ {"rule": "banned-word-global", "match": "revolutionary", "span": [76, 89], "severity": "block", "fix_hint": "make a specific claim instead"},
116
+ {"rule": "banned-word-global", "match": "leverages", "span": [125, 134], "severity": "block", "fix_hint": "use 'uses' or rewrite"},
117
+ {"rule": "banned-word-global", "match": "cutting-edge", "span": [138, 150], "severity": "block", "fix_hint": "name the actual method or omit"},
118
+ {"rule": "banned-word-global", "match": "world-class", "span": [171, 182], "severity": "block", "fix_hint": "replace self-awarded praise with evidence"},
119
+ {"rule": "in-todays-world", "match": "In today's ever-evolving landscape", "span": [220, 254], "severity": "block", "fix_hint": "delete the stock setup"},
120
+ {"rule": "not-just-x-its-y", "match": "it's not just a product, it's a paradigm shift", "span": [256, 302], "severity": "block", "fix_hint": "rewrite as a single direct claim"},
121
+ {"rule": "banned-closer", "match": "Looking forward to hearing from you", "span": [304, 339], "severity": "block", "fix_hint": "close with a concrete ask"}
122
+ ],
123
+ "stats": {
124
+ "sentence_length_mean": 24.8,
125
+ "fingerprint_sentence_length_mean": 11.2,
126
+ "drift_score": 0.74
127
+ },
128
+ "regenerate": true
129
+ }
130
+ ```
131
+
132
+ ### After
133
+
134
+ The drafting skill retries with the fingerprint loaded:
135
+
136
+ > Quick one: Acme shipped a search tool today that finds duplicate vendor
137
+ > contracts before finance approves a renewal.
138
+ >
139
+ > 14 companies used it in beta. The cleanest result: one customer found
140
+ > $1.8M in duplicate renewals in two weeks.
141
+ >
142
+ > CEO Maya Chen can talk Thursday or Friday. Worth a look?
143
+ >
144
+ > Jane
145
+
146
+ Why this works: the retry removes block violations, shortens cadence, uses a documented opener shape, keeps contractions, and closes with a concrete ask.
147
+
148
+ ---
149
+
150
+ ## Example 3: Standalone Check On A Launch Tweet
151
+
152
+ ### Before
153
+
154
+ Command:
155
+
156
+ ```bash
157
+ newsjack voice check ~/Documents/launch-tweet.txt
158
+ ```
159
+
160
+ `launch-tweet.txt`:
161
+
162
+ > Excited to unveil our cutting-edge platform — it's not just a tool, it's a
163
+ > paradigm shift for the modern PR practitioner.
164
+
165
+ ### Voice Check Output
166
+
167
+ ```text
168
+ voice-check: launch-tweet.txt
169
+ fingerprint: jane-doe-personal@2026-05-18 (confidence: medium)
170
+ verdict: FAIL (4 blocks, 1 warn)
171
+
172
+ x banned-word-global cutting-edge [22-34]
173
+ x em_dash_against_fingerprint — [44-45]
174
+ x not-just-x-its-y "it's not just a tool, it's a paradigm shift" [46-90]
175
+ x banned-word-global paradigm [76-84]
176
+ ! cadence_drift sentence_length_mean = 22 (fingerprint: 11)
177
+
178
+ suggested rewrite:
179
+ "Shipping our new platform today. Not a paradigm shift. Just the
180
+ thing we wish existed."
181
+
182
+ (rewrite is a hint, not authoritative; run through meanest-editor for the real edit)
183
+ ```
184
+
185
+ ### After
186
+
187
+ > Shipping our new platform today. Not a paradigm shift. Just the thing we wish
188
+ > existed.
189
+
190
+ Why this works: check mode flags the mechanical tells and offers a hint without pretending to be the editorial rewrite layer.
191
+
192
+ ---
193
+
194
+ ## Example 4: Mixed-Register Agency Dump
195
+
196
+ ### Before
197
+
198
+ > "I run PR for 5 clients. Build one voice profile from these 15 samples:
199
+ > 5 casual Slack messages I sent my team, 5 formal client approval emails,
200
+ > and 5 polished blog posts from Acme's CEO."
201
+
202
+ ### Voice Extractor Response
203
+
204
+ ```text
205
+ These are clearly different voices: your internal-casual voice, your formal
206
+ client-approval voice, and Acme's CEO voice. If I average them, I get a
207
+ fingerprint that's none of them.
208
+
209
+ Default path:
210
+ 1. Build your personal agency-sender profile from your own Slack/messages/emails.
211
+ 2. Build a separate Acme profile only with Acme-approved samples and consent.
212
+ 3. Switch active profiles with `newsjack voice use <name>`.
213
+
214
+ Which one should I extract first?
215
+ ```
216
+
217
+ ### After
218
+
219
+ Profiles created separately:
220
+
221
+ ```text
222
+ ~/.newsjack/voice/sarah-agency-personal.yaml
223
+ ~/.newsjack/voice/sarah-client-approval.yaml
224
+ ~/.newsjack/voice/acme-ceo-approved.yaml
225
+ ```
226
+
227
+ Why this works: the skill refuses to blend incompatible registers and preserves the source-doc boundary between sender voice and brand/client voice.
@@ -0,0 +1,251 @@
1
+ # Voice Extractor Rubric
2
+
3
+ Every extraction, check, and enforcement pass is evaluated against this rubric. Each criterion is scored 0-2:
4
+
5
+ - **0** - Missing, unsafe, or contradicted by the source doc.
6
+ - **1** - Present but weak, incomplete, or too generic.
7
+ - **2** - Solid, specific, and grounded in observed user samples.
8
+
9
+ Total possible: 32 points.
10
+
11
+ | Points | Verdict | Meaning |
12
+ |--------|---------|---------|
13
+ | 28-32 | **ship** | Fingerprint/check is usable with normal enforcement. |
14
+ | 20-27 | **ship with warnings** | Usable, but confidence or sample quality limits enforcement. |
15
+ | 10-19 | **rework** | Too much is generic, unconfirmed, or weakly supported. |
16
+ | 0-9 | **refuse / restart** | Unsafe, under-sampled, AI-heavy, or not a real user voice. |
17
+
18
+ ---
19
+
20
+ ## 1. Sample Sufficiency
21
+
22
+ **Trace:** "voice init - Inputs"; "Mode: extract / Phase 1 - Sample intake"; "Refusal 1 - Insufficient samples."
23
+
24
+ **Score 0:** Fewer than 5 samples, or sample metadata is absent.
25
+ **Score 1:** 5+ samples but under 800 total words, stale samples dominate, or source/audience/date metadata is thin.
26
+ **Score 2:** 5-20 samples with source, date, audience, and enough recent native writing to support a fingerprint.
27
+
28
+ Hard rule: fewer than 5 samples is a refusal.
29
+
30
+ ---
31
+
32
+ ## 2. AI-Heavy Corpus Triage
33
+
34
+ **Trace:** "It refuses to"; "Phase 2 - Sample triage"; "Refusal 2 - AI-heavy sample set."
35
+
36
+ **Score 0:** Extracts from a corpus where more than 30% of samples look AI-generated without stopping.
37
+ **Score 1:** Flags AI-heavy samples but does not clearly lower confidence or ask for replacement samples.
38
+ **Score 2:** Stops above the 30% threshold and asks for non-AI samples, or proceeds only with explicit low-confidence consent.
39
+
40
+ Signals: em-dash saturation, "not just X, it's Y", "in today's [adjective] world", tricolons, banned-word density, no typos or fragments.
41
+
42
+ ---
43
+
44
+ ## 3. Register Integrity
45
+
46
+ **Trace:** "It refuses to"; "Trigger"; "Phase 2 - Sample triage"; "Refusal 5 - Cross-register dump."
47
+
48
+ **Score 0:** Averages incompatible voices into one fingerprint.
49
+ **Score 1:** Notices register splits but leaves the profile ambiguous.
50
+ **Score 2:** Captures one clear register or creates separate profiles after user confirmation.
51
+
52
+ Examples: Slack DMs, founder tweets, journalist pitches, board updates, and earnings boilerplate are not automatically the same voice.
53
+
54
+ ---
55
+
56
+ ## 4. Consent And Identity Boundary
57
+
58
+ **Trace:** "What it is"; "Refusal 4 - Voice-stealing"; "Risks."
59
+
60
+ **Score 0:** Builds a fingerprint of a non-participating person from public writing.
61
+ **Score 1:** Warns but still proceeds without consent.
62
+ **Score 2:** Refuses non-consensual third-party fingerprints and allows ghostwriting only when the person is in the loop.
63
+
64
+ Voice is a signature. Treat it like one.
65
+
66
+ ---
67
+
68
+ ## 5. Local Storage And Privacy
69
+
70
+ **Trace:** "What it is"; "Layer + rationale"; "`voice init` - Outputs"; "Junior-engineer implementation hints."
71
+
72
+ **Score 0:** Sends the fingerprint to Medialyst by default or stores raw sample text inside `voice.yaml`.
73
+ **Score 1:** Stores locally but leaks sample text or misses audit hashes.
74
+ **Score 2:** Writes `~/.newsjack/voice/<profile_id>.yaml`, keeps raw text in sample files, stores hashes and metadata, and points `active.yaml` at the active profile.
75
+
76
+ Required fields: `schema_version`, `profile_id`, timestamps, sample stats, intent, register, cadence, mechanics, openers, closers, sentence initials, idioms, banned words, banned structures, topic signatures, sample index, extraction metadata.
77
+
78
+ ---
79
+
80
+ ## 6. Cadence Extraction
81
+
82
+ **Trace:** "`voice init` - Outputs / Cadence"; "Mode: extract / Phase 3 - Extraction."
83
+
84
+ **Score 0:** Uses subjective labels only.
85
+ **Score 1:** Captures some rhythm notes but misses comparable numeric metrics.
86
+ **Score 2:** Computes sentence length mean, median, p10, p90, stdev; 1-3-word sentence frequency; 35+ word sentence frequency; paragraph length; one-sentence paragraph rate; rhythm signature.
87
+
88
+ Cadence must be computed from samples, not inferred from the user's job title or industry.
89
+
90
+ ---
91
+
92
+ ## 7. Mechanics Extraction
93
+
94
+ **Trace:** "`voice init` - Outputs / Mechanics"; "Phase 3 - Extraction"; "Soft pushback - Em-dash override."
95
+
96
+ **Score 0:** Ignores mechanics or normalizes them to generic grammar.
97
+ **Score 1:** Captures obvious mechanics but misses rates or quirks.
98
+ **Score 2:** Captures contractions, contraction rate, em-dash usage, Oxford comma, ellipses, exclamations, questions, parenthetical asides, capitalization quirks, and smart quotes.
99
+
100
+ Em-dash classification is a high-risk field. Confirm it with the user before saving.
101
+
102
+ ---
103
+
104
+ ## 8. Sentence-Initial And Transition Habits
105
+
106
+ **Trace:** "`voice init` - Outputs / Sentence-initial"; "Prompt scaffolding / Phase 3."
107
+
108
+ **Score 0:** Allows stock AI transitions by default.
109
+ **Score 1:** Captures conjunction starts but does not ban absent AI transitions.
110
+ **Score 2:** Measures starts with But/And/So/Or/Yet/Because and bans absent `however`, `furthermore`, `moreover`, `in conclusion`, `in summary`, `imagine if`, and `picture this`.
111
+
112
+ If the samples do not show the transition, do not let the model borrow it from generic LLM voice.
113
+
114
+ ---
115
+
116
+ ## 9. Idiom And Vocabulary Fingerprint
117
+
118
+ **Trace:** "`voice init` - Outputs / Idiom + signature phrases"; "Phase 3 - Extraction."
119
+
120
+ **Score 0:** Produces generic descriptors like "warm, professional, concise."
121
+ **Score 1:** Captures a few phrases but does not separate signature words, real hedges, and banned hedges.
122
+ **Score 2:** Extracts repeated literal phrases, unusual signature words, hedges the user actually uses, and hedges the user never uses.
123
+
124
+ Signature phrases are allowed sparingly. They are not a phrasebook to overfit.
125
+
126
+ ---
127
+
128
+ ## 10. Openers And Closers
129
+
130
+ **Trace:** "`voice init` - Outputs / Openers + closers"; "Phase 4 - User confirmation."
131
+
132
+ **Score 0:** Leaves stock openers and closers available.
133
+ **Score 1:** Lists observed openers or closers but misses banned stock phrases.
134
+ **Score 2:** Captures observed clusters and bans stock phrases such as "I hope this email finds you well," "I wanted to reach out," "Looking forward to hearing from you," and "Please don't hesitate to reach out."
135
+
136
+ Opening and closing patterns must be confirmed with the user.
137
+
138
+ ---
139
+
140
+ ## 11. Banned Words And Structures
141
+
142
+ **Trace:** "Rubric / checks / banned lists"; "Global banned-word list (v0)"; "Structural patterns."
143
+
144
+ **Score 0:** Lets global anti-slop words or AI scaffolds pass.
145
+ **Score 1:** Applies global bans but does not handle user-specific exceptions from real samples.
146
+ **Score 2:** Applies global bans, adds user-specific bans, flags globally banned words that appear in real samples for review, and stores banned structures with ids, patterns, severity, and rationale.
147
+
148
+ Global bans are a category-level rule. Individual words can be allowed only when real user samples prove they are genuinely theirs.
149
+
150
+ ---
151
+
152
+ ## 12. Topic And Perspective Anchors
153
+
154
+ **Trace:** "`voice init` - Outputs / Topic + perspective anchors"; "Phase 3 - Extraction."
155
+
156
+ **Score 0:** Ignores what the user actually writes about and who they write as.
157
+ **Score 1:** Names topics but misses perspective rates.
158
+ **Score 2:** Captures 3-5 recurring themes plus first-person singular, first-person plural, second-person, and third-person rates.
159
+
160
+ This keeps the fingerprint from preserving surface style while drifting away from the user's normal point of view.
161
+
162
+ ---
163
+
164
+ ## 13. User Confirmation
165
+
166
+ **Trace:** "Phase 4 - User confirmation"; "Pushback (soft - argue, but defer)."
167
+
168
+ **Score 0:** Saves without showing a summary.
169
+ **Score 1:** Shows a summary but does not ask about high-risk fields.
170
+ **Score 2:** Shows a one-page summary and asks for overrides on em-dashes, openers/closers, idioms, banned words, and register.
171
+
172
+ Argue when an override makes drafts sound AI-written. Defer when the user confirms.
173
+
174
+ ---
175
+
176
+ ## 14. Decay And Refresh
177
+
178
+ **Trace:** "Trigger / refresh"; "Phase 5 - Stamp + tell the user about decay."
179
+
180
+ **Score 0:** No extraction timestamp or refresh signal.
181
+ **Score 1:** Stores timestamps but does not surface staleness.
182
+ **Score 2:** Stores `last_extracted_at`, sample age stats, and flags refresh at 90 days.
183
+
184
+ Voice drifts. The skill must name the drift.
185
+
186
+ ---
187
+
188
+ ## 15. Check Mode Precision
189
+
190
+ **Trace:** "`voice check <file>` - Output"; "Mode: check"; "Hard refusals"; "Cadence drift"; "Vocabulary drift."
191
+
192
+ **Score 0:** Returns vague critique instead of machine-usable violations.
193
+ **Score 1:** Returns rule names but misses spans, severity, or fix hints.
194
+ **Score 2:** Returns verdict, pass rate, fingerprint id, violations with rule/match/span/severity/fix hint, stats, and regenerate flag.
195
+
196
+ Check mode does not editorialize. It reports tells.
197
+
198
+ ---
199
+
200
+ ## 16. Enforce Mode Contract
201
+
202
+ **Trace:** "`voice enforce` - Contract"; "Mode: enforce"; "Engine-sharing with `meanest-editor`."
203
+
204
+ **Score 0:** Drafting skills ignore the fingerprint or pass failing drafts silently.
205
+ **Score 1:** Drafting skills load the fingerprint but do not retry or warn cleanly.
206
+ **Score 2:** Drafting skills inject `<voice_fingerprint>`, run `voice check`, retry block failures up to 2 times, then return with a visible warning if still failing.
207
+
208
+ `voice-extractor` is the mechanical lint layer. `meanest-editor` is the editorial roast. Keep the boundary clean.
209
+
210
+ ---
211
+
212
+ ## Hard Block Rules
213
+
214
+ These always block unless a rule explicitly says fingerprint confidence changes severity.
215
+
216
+ | Rule ID | Pattern / Trigger | Severity | Trace |
217
+ |---|---|---:|---|
218
+ | `stray-placeholder` | `\{[a-z _]+\}|\[[A-Z_ ]+\]|<<[A-Z_ ]+>>` | block | Hard refusals; check output |
219
+ | `banned-word-global` | Exact match against global list | block | Global banned-word list |
220
+ | `banned-word-user-specific` | Exact match against profile list | block | `voice.yaml` schema |
221
+ | `em_dash_against_fingerprint` | `—` when `em_dash_usage: never` | block | Mechanics; structural patterns |
222
+ | `banned-opener` | Banned phrase used as opener | block | Openers |
223
+ | `banned-closer` | Banned phrase used as closer | block | Closers |
224
+ | `not-just-x-its-y` | `(?i)\bit'?s not just .*?,? it'?s\b` | block | Banned structures |
225
+ | `imagine-if-opener` | `^(Imagine if|Picture this|What if I told you)` | block | Banned structures |
226
+ | `in-todays-adjective-world` | `(?i)\bin today'?s [a-z-]+ world\b` | block | Banned structures |
227
+ | `now-more-than-ever` | `(?i)\bnow more than ever\b` | block | Structural patterns |
228
+ | `ever-evolving-landscape` | `(?i)\bever[- ](evolving|changing) (landscape|world|industry)\b` | block | Structural patterns |
229
+ | `sentence-starts-with-however` | `(?<=[.!?]\s)However[,\s]` when absent from fingerprint | block | Sentence-initial habits |
230
+ | `furthermore-moreover-additionally` | `\b(Furthermore|Moreover|Additionally)\b` when absent from fingerprint | block | Sentence-initial habits |
231
+
232
+ ## Warn Rules
233
+
234
+ | Rule ID | Trigger | Severity | Trace |
235
+ |---|---|---:|---|
236
+ | `cadence_mean_drift` | Sentence length mean drifts more than 40% | warn | Cadence drift |
237
+ | `cadence_p90_drift` | Sentence length p90 drifts more than 50% | warn | Cadence drift |
238
+ | `paragraph_rate_drift` | One-sentence paragraph rate below 50% or above 200% of fingerprint | warn | Cadence drift |
239
+ | `first_person_drop` | First-person singular rate drops more than 50% in pitches/social | warn | Cadence drift |
240
+ | `contraction_rate_drop` | Contraction rate falls below 50% of fingerprint | warn | Cadence drift |
241
+ | `tricolon-three-past-verbs` | More than 1 per 200 words | warn | Structural patterns |
242
+ | `three-adjective-noun-stack` | Three adjective stack before a noun | warn | Structural patterns |
243
+ | `title-case-mid-sentence` | `[a-z]\s+([A-Z][a-z]+\s+){2,}` excluding proper nouns | warn | Structural patterns |
244
+ | `excessive-hedging` | More than 3 of might/could/may/perhaps/possibly/arguably per 200 words | warn | Structural patterns |
245
+ | `signature_absence` | Fewer than 2 signature words or phrases in text over 150 words | warn | Vocabulary drift |
246
+
247
+ Low-confidence fingerprints downgrade warn rules to informational. Hard blocks stay hard.
248
+
249
+ ## Global Banned-Word List
250
+
251
+ `delve`, `tapestry`, `leverage`, `leveraging`, `robust`, `comprehensive`, `holistic`, `synergy`, `paradigm`, `paradigm-shift`, `ecosystem` when metaphorical, `solutions` as a noun for products, `unlock`, `unleash`, `empower`, `empowering`, `revolutionize`, `transform` when paired with industry, `disrupt` in the consultant sense, `seamless`, `seamlessly`, `frictionless`, `supercharge`, `turbocharge`, `game-changing`, `game-changer`, `world-class`, `best-in-class`, `cutting-edge`, `state-of-the-art`, `next-generation`, `next-gen`, `leading`, `innovative`, `innovation` as a buzzword, `revolutionary`, `groundbreaking`, `paradigm-shifting`, `transformative`, `mission-critical`, `core competency`, `value-add`, `value proposition`, `deliverables`, `actionable insights`, `low-hanging fruit`, `move the needle`, `circle back`, `touch base`, `synergize`, `ideate`, `operationalize`, `we are committed to`, `we pride ourselves on`, `we believe that`, `in today's [X] world`, `in this ever-changing landscape`, `now more than ever`.