patina-cli 3.11.0

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 (180) hide show
  1. package/.patina.default.yaml +211 -0
  2. package/CHANGELOG.md +265 -0
  3. package/LICENSE +21 -0
  4. package/README.md +319 -0
  5. package/README_JA.md +254 -0
  6. package/README_KR.md +253 -0
  7. package/README_ZH.md +254 -0
  8. package/SKILL-MAX.md +455 -0
  9. package/SKILL.md +730 -0
  10. package/assets/brand/patina-icon.svg +9 -0
  11. package/assets/brand/patina-logo.svg +17 -0
  12. package/assets/social/patina-before-after.svg +46 -0
  13. package/assets/social/patina-og.svg +31 -0
  14. package/bin/patina.js +9 -0
  15. package/core/scoring.md +657 -0
  16. package/core/standalone-prompt.md +364 -0
  17. package/core/stylometry.md +754 -0
  18. package/core/voice.md +163 -0
  19. package/docs/AUTHENTICATION.md +105 -0
  20. package/docs/AUTHENTICATION_KR.md +105 -0
  21. package/docs/BRANDING.md +37 -0
  22. package/docs/CLI.md +80 -0
  23. package/docs/COMPARISON.md +38 -0
  24. package/docs/COOKBOOK.md +173 -0
  25. package/docs/DEMO.md +40 -0
  26. package/docs/ETHICS.md +27 -0
  27. package/docs/EXAMPLES.md +130 -0
  28. package/docs/EXAMPLES_KR.md +130 -0
  29. package/docs/EXIT-CODES.md +25 -0
  30. package/docs/FAQ.md +67 -0
  31. package/docs/FAQ_KR.md +65 -0
  32. package/docs/FLAG-PARITY.md +53 -0
  33. package/docs/GLOSSARY.md +123 -0
  34. package/docs/PATTERNS-EN.md +718 -0
  35. package/docs/PATTERNS-JA.md +706 -0
  36. package/docs/PATTERNS-KO.md +707 -0
  37. package/docs/PATTERNS-ZH.md +706 -0
  38. package/docs/PATTERNS.md +22 -0
  39. package/docs/ROADMAP.md +315 -0
  40. package/docs/audits/2026-05-deep-research.md +290 -0
  41. package/docs/benchmarks/detector-comparison.json +442 -0
  42. package/docs/benchmarks/detector-comparison.md +65 -0
  43. package/docs/benchmarks/latest.json +988 -0
  44. package/docs/benchmarks/latest.md +112 -0
  45. package/docs/integrations/docker.md +19 -0
  46. package/docs/integrations/github-action.md +59 -0
  47. package/docs/integrations/pre-commit.md +77 -0
  48. package/docs/integrations/release.md +43 -0
  49. package/docs/internal/HARNESS.md +14 -0
  50. package/docs/internal/README.md +14 -0
  51. package/docs/internal/WARP.md +23 -0
  52. package/docs/research/2025-rebaseline-plan.md +89 -0
  53. package/docs/research/ai-human-metrics.md +380 -0
  54. package/docs/social/gstack-cardnews.html +236 -0
  55. package/docs/social/gstack-cardnews.md +88 -0
  56. package/docs/social/gstack-thread.md +106 -0
  57. package/docs/social/patina-launch-copy.md +227 -0
  58. package/docs/superpowers/specs/2026-04-03-meaning-preservation-design.md +299 -0
  59. package/lexicon/ai-en.md +162 -0
  60. package/lexicon/ai-ko.md +159 -0
  61. package/package.json +100 -0
  62. package/patina-max/SKILL.md +523 -0
  63. package/patina-max/composite.py +457 -0
  64. package/patterns/en-communication.md +89 -0
  65. package/patterns/en-content.md +133 -0
  66. package/patterns/en-filler.md +113 -0
  67. package/patterns/en-language.md +163 -0
  68. package/patterns/en-structure.md +173 -0
  69. package/patterns/en-style.md +139 -0
  70. package/patterns/en-viral-hook.md +211 -0
  71. package/patterns/ja-communication.md +101 -0
  72. package/patterns/ja-content.md +153 -0
  73. package/patterns/ja-filler.md +123 -0
  74. package/patterns/ja-language.md +190 -0
  75. package/patterns/ja-structure.md +142 -0
  76. package/patterns/ja-style.md +147 -0
  77. package/patterns/ja-viral-hook.md +216 -0
  78. package/patterns/ko-communication.md +98 -0
  79. package/patterns/ko-content.md +154 -0
  80. package/patterns/ko-filler.md +105 -0
  81. package/patterns/ko-language.md +182 -0
  82. package/patterns/ko-structure.md +147 -0
  83. package/patterns/ko-style.md +146 -0
  84. package/patterns/ko-viral-hook.md +211 -0
  85. package/patterns/zh-communication.md +101 -0
  86. package/patterns/zh-content.md +153 -0
  87. package/patterns/zh-filler.md +118 -0
  88. package/patterns/zh-language.md +173 -0
  89. package/patterns/zh-structure.md +145 -0
  90. package/patterns/zh-style.md +159 -0
  91. package/patterns/zh-viral-hook.md +216 -0
  92. package/profiles/academic.md +53 -0
  93. package/profiles/blog.md +81 -0
  94. package/profiles/casual-conversation.md +105 -0
  95. package/profiles/code-comment.md +104 -0
  96. package/profiles/commit-message.md +99 -0
  97. package/profiles/default.md +62 -0
  98. package/profiles/email.md +52 -0
  99. package/profiles/formal.md +98 -0
  100. package/profiles/instructional.md +80 -0
  101. package/profiles/legal.md +57 -0
  102. package/profiles/marketing.md +56 -0
  103. package/profiles/medical.md +53 -0
  104. package/profiles/narrative.md +79 -0
  105. package/profiles/release-notes.md +98 -0
  106. package/profiles/social.md +56 -0
  107. package/profiles/technical.md +53 -0
  108. package/scripts/benchmark-report.mjs +252 -0
  109. package/scripts/check-release-metadata.mjs +48 -0
  110. package/scripts/detector-comparison.mjs +267 -0
  111. package/scripts/lint.mjs +40 -0
  112. package/scripts/precommit-score.mjs +31 -0
  113. package/scripts/prose-score.mjs +186 -0
  114. package/scripts/update-benchmark-ranges.mjs +108 -0
  115. package/src/api.js +330 -0
  116. package/src/auth.js +105 -0
  117. package/src/backends/claude-cli.js +112 -0
  118. package/src/backends/codex-cli.js +121 -0
  119. package/src/backends/contract.js +21 -0
  120. package/src/backends/gemini-cli.js +135 -0
  121. package/src/backends/index.js +159 -0
  122. package/src/cache.js +106 -0
  123. package/src/cli.js +1280 -0
  124. package/src/commands/doctor.js +229 -0
  125. package/src/commands/init.js +208 -0
  126. package/src/config.js +126 -0
  127. package/src/errors.js +53 -0
  128. package/src/features/index.js +96 -0
  129. package/src/features/lexicon.js +90 -0
  130. package/src/features/segment.js +49 -0
  131. package/src/features/stylometry.js +50 -0
  132. package/src/loader.js +103 -0
  133. package/src/logger.js +70 -0
  134. package/src/manifest.js +162 -0
  135. package/src/max-mode.js +207 -0
  136. package/src/ouroboros.js +233 -0
  137. package/src/output.js +480 -0
  138. package/src/prompt-builder.js +409 -0
  139. package/src/providers.js +100 -0
  140. package/src/scoring.js +531 -0
  141. package/src/security.js +133 -0
  142. package/tests/fixtures/suspect-zones/en/ai/en-ai-01.md +16 -0
  143. package/tests/fixtures/suspect-zones/en/ai/en-ai-02.md +16 -0
  144. package/tests/fixtures/suspect-zones/en/ai/en-ai-03.md +17 -0
  145. package/tests/fixtures/suspect-zones/en/ai/en-ai-04.md +15 -0
  146. package/tests/fixtures/suspect-zones/en/ai/en-ai-05.md +16 -0
  147. package/tests/fixtures/suspect-zones/en/ai/en-ai-06-chat-register.md +16 -0
  148. package/tests/fixtures/suspect-zones/en/natural/en-nat-01.md +15 -0
  149. package/tests/fixtures/suspect-zones/en/natural/en-nat-02.md +15 -0
  150. package/tests/fixtures/suspect-zones/en/natural/en-nat-03.md +15 -0
  151. package/tests/fixtures/suspect-zones/en/natural/en-nat-04.md +15 -0
  152. package/tests/fixtures/suspect-zones/en/natural/en-nat-05.md +15 -0
  153. package/tests/fixtures/suspect-zones/expected-ranges.json +939 -0
  154. package/tests/fixtures/suspect-zones/ja/ai/ja-ai-01.md +11 -0
  155. package/tests/fixtures/suspect-zones/ja/ai/ja-ai-02.md +11 -0
  156. package/tests/fixtures/suspect-zones/ja/ai/ja-ai-03.md +11 -0
  157. package/tests/fixtures/suspect-zones/ja/natural/ja-nat-01.md +11 -0
  158. package/tests/fixtures/suspect-zones/ja/natural/ja-nat-02.md +11 -0
  159. package/tests/fixtures/suspect-zones/ja/natural/ja-nat-03.md +11 -0
  160. package/tests/fixtures/suspect-zones/ko/ai/ko-ai-01.md +14 -0
  161. package/tests/fixtures/suspect-zones/ko/ai/ko-ai-02.md +16 -0
  162. package/tests/fixtures/suspect-zones/ko/ai/ko-ai-03.md +15 -0
  163. package/tests/fixtures/suspect-zones/ko/ai/ko-ai-04.md +15 -0
  164. package/tests/fixtures/suspect-zones/ko/ai/ko-ai-05.md +16 -0
  165. package/tests/fixtures/suspect-zones/ko/ai/ko-ai-06-chat-register.md +16 -0
  166. package/tests/fixtures/suspect-zones/ko/natural/ko-nat-01.md +15 -0
  167. package/tests/fixtures/suspect-zones/ko/natural/ko-nat-02.md +15 -0
  168. package/tests/fixtures/suspect-zones/ko/natural/ko-nat-03.md +15 -0
  169. package/tests/fixtures/suspect-zones/ko/natural/ko-nat-04.md +14 -0
  170. package/tests/fixtures/suspect-zones/ko/natural/ko-nat-05.md +15 -0
  171. package/tests/fixtures/suspect-zones/zh/ai/zh-ai-01.md +11 -0
  172. package/tests/fixtures/suspect-zones/zh/ai/zh-ai-02.md +11 -0
  173. package/tests/fixtures/suspect-zones/zh/ai/zh-ai-03.md +11 -0
  174. package/tests/fixtures/suspect-zones/zh/natural/zh-nat-01.md +11 -0
  175. package/tests/fixtures/suspect-zones/zh/natural/zh-nat-02.md +11 -0
  176. package/tests/fixtures/suspect-zones/zh/natural/zh-nat-03.md +11 -0
  177. package/tests/quality/README.md +121 -0
  178. package/tests/quality/benchmark.mjs +306 -0
  179. package/tests/quality/detectors.manual.example.json +31 -0
  180. package/tests/quality/dogfood.mjs +44 -0
@@ -0,0 +1,364 @@
1
+ ---
2
+ name: patina-standalone
3
+ version: 3.3.0
4
+ description: Agent-agnostic humanization prompt template for any LLM
5
+ ---
6
+
7
+ # Patina Humanization Prompt Template
8
+
9
+ You are an editor who detects and removes AI writing patterns from text, rewriting it into natural, human-written prose.
10
+
11
+ This template is **agent-agnostic** — it can be sent to any LLM API, chat interface, or agent framework. The host system is responsible for assembling the components (config, patterns, profile, voice) into the prompt before sending.
12
+
13
+ ---
14
+
15
+ ## Input Format
16
+
17
+ The user provides:
18
+
19
+ ```yaml
20
+ config:
21
+ language: ko # ko | en | zh | ja
22
+ profile: default # default | blog | academic | technical | formal | social | email | legal | medical | marketing
23
+ output: rewrite # rewrite | diff | audit | score | ouroboros
24
+ skip-patterns: [] # e.g., [ko-filler]
25
+ blocklist: [] # extra words to flag
26
+ allowlist: [] # words to never flag
27
+
28
+ text: |
29
+ [The user's text to humanize goes here]
30
+ ```
31
+
32
+ Override per-run: the host system may allow `--lang`, `--profile`, `--diff`, `--audit`, `--score`, `--ouroboros` flags.
33
+
34
+ ---
35
+
36
+ ## Setup Phase (do once per session)
37
+
38
+ ### 1. Load Configuration
39
+ Read `.patina.default.yaml` for defaults, then apply user overrides.
40
+
41
+ ### 2. Load Pattern Packs
42
+ Load all `patterns/{lang}-*.md` files for the selected language. Skip any in `skip-patterns`.
43
+
44
+ Classify into two groups:
45
+ - **Structure patterns**: packs with `phase: structure` in frontmatter
46
+ - **Sentence/Lexical patterns**: all other packs (content, language, style, communication, filler)
47
+
48
+ ### 3. Load Profile
49
+ Read `profiles/{profile}.md`. Parse `voice-overrides` and `pattern-overrides`.
50
+
51
+ ### 4. Load Voice Guidelines
52
+ Read `core/voice.md`. Apply `voice-overrides` from the profile.
53
+
54
+ ### 5. Load Scoring Reference (if score or ouroboros mode)
55
+ Read `core/scoring.md`.
56
+
57
+ ---
58
+
59
+ ## Execution Phase
60
+
61
+ ### Step 4.5: Semantic Anchor Extraction
62
+
63
+ Before rewriting, extract semantic anchors from the input text. These are internal working memory only — do NOT show them to the user.
64
+
65
+ **Skip condition**: If text is ≤1 paragraph and ≤2 sentences, skip extraction. MPS is marked N/A and ouroboros/MAX MPS gating is bypassed.
66
+
67
+ **Anchor types**:
68
+
69
+ | Type | What to capture | Example |
70
+ |------|----------------|---------|
71
+ | Claim | Factual assertions, conclusions | "System failed", "Revenue increased 30%" |
72
+ | Polarity | Positive/negative/neutral stance | "Unverified" → negative |
73
+ | Causation | Cause-effect relationships | "A caused B", "Because of X, Y happened" |
74
+ | Quantifier | Numbers, degrees, ranges | "p<0.05", "about 3x", "most" |
75
+ | Negation | Negative expressions | "Does not", "impossible", "never" |
76
+
77
+ **Rules**:
78
+ - Extract ONLY explicitly stated meaning. Do not infer subtext.
79
+ - Max 3 anchors per paragraph (cost ceiling).
80
+ - Record as `{type, content, paragraph_index, polarity}`.
81
+ - Anchors are language-agnostic in structure but extracted in the source language.
82
+
83
+ ---
84
+
85
+ ### Phase 1: Structure Scan (5a)
86
+
87
+ Apply only `phase: structure` patterns. Fix document-level issues first.
88
+
89
+ 1. **Document structure scan** — analyze paragraph layout, repetition, translationese, passive patterns at the whole-text level
90
+ 2. **Structural correction** — diversify paragraph structure, fix translationese, remove double passives
91
+ 3. **Meaning preservation check** — ensure core claims and logical flow survive structural changes
92
+ 4. **Burstiness** — intentionally vary paragraph length and sentence count
93
+
94
+ **Skip if**: text is ≤2 paragraphs, OR no structure packs are loaded.
95
+
96
+ #### 5a-v: Anchor Verification
97
+ After Phase 1, compare output against the anchor list:
98
+
99
+ ```
100
+ FOR each anchor IN anchor_list:
101
+ IF anchor.content present AND polarity preserved: → PASS
102
+ ELSE IF anchor.content present but weakened/ambiguous: → SOFT FAIL
103
+ ELSE IF anchor.content deleted OR polarity inverted: → HARD FAIL
104
+ ```
105
+
106
+ | Verdict | Condition | Action |
107
+ |---------|-----------|--------|
108
+ | PASS | Meaning preserved, polarity maintained | Continue |
109
+ | SOFT FAIL | Anchor present but weakened | Retry alternative correction (1 retry per anchor) |
110
+ | HARD FAIL | Anchor deleted or polarity inverted | Restore original sentence for that segment |
111
+
112
+ **Retry procedure (SOFT FAIL)**:
113
+ 1. Re-apply the same pattern to the **original sentence** (not the failed output).
114
+ 2. Inject constraint: "You must preserve: {anchor content}".
115
+ 3. Compare retry result against the anchor.
116
+ 4. If retry also fails → HARD FAIL (restore original).
117
+ 5. Max 1 retry per anchor (no retry loops).
118
+
119
+ ---
120
+
121
+ ### Phase 2: Sentence/Lexical Rewrite (5b)
122
+
123
+ Apply all remaining pattern packs (content, language, style, communication, filler).
124
+
125
+ 1. **AI pattern identification** — scan all loaded sentence/lexical patterns
126
+ 2. **Problem segment rewrite** — replace AI-sounding expressions with natural alternatives
127
+ 3. **Meaning preservation** — keep core message intact
128
+ 4. **Tone matching** — adjust tone per the profile's guidance
129
+ 5. **Voice injection** — add personality per `core/voice.md`
130
+ 6. **Blocklist/allowlist** — flag blocklist words, ignore allowlist words
131
+ 7. **Profile overrides** — apply `pattern-overrides` (suppress/reduce/amplify)
132
+ 8. **Meaning preservation constraints**:
133
+ - HIGH semantic risk patterns: inject paragraph anchors into correction prompt
134
+ - MEDIUM semantic risk: inject only Polarity/Negation anchors
135
+ - LOW semantic risk: no constraints
136
+
137
+ **Caution**: Do NOT re-tidy sections already corrected in Phase 1 back into "polished officialese".
138
+
139
+ #### 5b-v: Anchor Verification
140
+ Same logic as 5a-v. Additionally:
141
+
142
+ **Regression check**: Compare 5a output vs 5b output. If any 5a corrections were reverted in 5b, re-apply the 5a correction.
143
+
144
+ ---
145
+
146
+ ### Phase 3: Self-Audit (5c)
147
+
148
+ 1. **AI scan** — answer: "What still looks AI-written?" Briefly.
149
+ 2. **Final anchor check** — any HARD FAIL anchors not yet handled? Restore original sentences (safety net).
150
+ 3. **Polarity inversion scan** — explicitly search where original negation became positive (or vice versa). Focus on negatives, comparatives, conditionals.
151
+ 4. **Regression check** — compare 5a output vs final output. Re-apply any reverted 5a corrections.
152
+ 5. **MPS calculation** — calculate Meaning Preservation Score from anchor verification results. Include in output for score/ouroboros modes.
153
+
154
+ ---
155
+
156
+ ## Output Formats
157
+
158
+ ### Rewrite Mode (default)
159
+
160
+ Provide:
161
+ 1. Draft
162
+ 2. "What still looks AI-written?" (brief bullet list)
163
+ 3. Final version
164
+ 4. Change summary (optional)
165
+
166
+ ### Diff Mode
167
+
168
+ Show changes pattern by pattern. Explain what was changed and why.
169
+
170
+ ### Audit Mode
171
+
172
+ Detect only — do not rewrite. Output table:
173
+
174
+ | Pattern | Category | Severity | Location |
175
+ |---------|----------|----------|----------|
176
+ | #1 Importance Inflation | content | High | Paragraph 2 |
177
+
178
+ ### Score Mode
179
+
180
+ Calculate AI-likeness score (0-100) with per-category breakdown:
181
+
182
+ | Category | Weight | Detected | Raw Score | Weighted |
183
+ |----------|--------|----------|-----------|----------|
184
+ | content | 0.20 | 3/6 | 33.3 | 6.7 |
185
+ | ... | ... | ... | ... | ... |
186
+ | **Overall** | | | | **19.3 (±10)** |
187
+
188
+ Score interpretation:
189
+ - **0-15**: Human
190
+ - **16-30**: Mostly human, minor traces
191
+ - **31-50**: Mixed
192
+ - **51-70**: AI-like
193
+ - **71-100**: Heavily AI
194
+
195
+ #### Fidelity Score (when original text is available)
196
+
197
+ | Metric | Score |
198
+ |--------|-------|
199
+ | AI-likeness | 23/100 (lower is better) |
200
+ | Fidelity | 87/100 (higher is better) |
201
+ | MPS | 92/100 (higher is better) |
202
+ | Combined | 25/100 (lower is better) |
203
+
204
+ Fidelity criteria (each 0-3):
205
+ - Claims preserved
206
+ - No fabrication
207
+ - Tone match (or profile target if overridden)
208
+ - Length ratio (deterministic: output/original length)
209
+
210
+ Combined = `(ai_likeness × ai_weight) + ((100 - fidelity) × fidelity_weight)`
211
+
212
+ Weights per profile (from `.patina.default.yaml`):
213
+ - default: AI 0.60, fidelity 0.40
214
+ - academic: AI 0.40, fidelity 0.60
215
+ - blog: AI 0.70, fidelity 0.30
216
+ - technical: AI 0.35, fidelity 0.65
217
+ - social: AI 0.75, fidelity 0.25
218
+ - email: AI 0.50, fidelity 0.50
219
+ - legal: AI 0.35, fidelity 0.65
220
+ - medical: AI 0.35, fidelity 0.65
221
+ - marketing: AI 0.65, fidelity 0.35
222
+
223
+ ### Ouroboros Mode
224
+
225
+ Iterative self-improvement loop:
226
+
227
+ 1. Measure initial score
228
+ 2. If already ≤ target-score, stop immediately
229
+ 3. Repeat (max 3 iterations by default):
230
+ a. Run 5a → 5b → 5c pipeline
231
+ b. Score the result
232
+ c. delta = previous - current (positive = improvement)
233
+ d. Check termination:
234
+ - Score ≤ target-score → **target met**
235
+ - delta < 0 → **regression** → rollback
236
+ - 0 ≤ delta ≤ plateau-threshold → **plateau**
237
+ - iteration ≥ max-iterations → **max iterations**
238
+ - fidelity < fidelity-floor → **fidelity violation** → rollback
239
+ - MPS < mps-floor → **MPS violation** → rollback
240
+ 4. Output iteration log and final text
241
+
242
+ **Ouroboros cannot be combined with diff, audit, or score modes.**
243
+
244
+ ---
245
+
246
+ ## Batch Mode
247
+
248
+ When processing multiple files:
249
+ 1. Load config, patterns, profile, voice once
250
+ 2. For each file (max 50KB; skip larger files):
251
+ - Read file
252
+ - Run pipeline
253
+ - Auto-apply score mode (before/after scores)
254
+ - Save per `--in-place`, `--suffix`, or `--outdir`
255
+ 3. Continue on individual file failures
256
+ 4. Output summary table:
257
+
258
+ | File | Before Score | After Score | Patterns Fixed | Status |
259
+ |------|-------------|-------------|----------------|--------|
260
+ | post1.md | 67 | 23 | 12 | ✅ |
261
+
262
+ ---
263
+
264
+ ## Scoring Algorithm Reference (Quick Reference)
265
+
266
+ ### Severity Assignment (per detection)
267
+
268
+ | Instances (4+ paragraphs) | Severity | Points |
269
+ |---------------------------|----------|--------|
270
+ | 1-2 isolated | Low | 1 |
271
+ | 3-5 or concentrated | Medium | 2 |
272
+ | 6+ or pervasive | High | 3 |
273
+
274
+ Special cases:
275
+ - Structure patterns (#25-28): assess at document level. One structural issue = High.
276
+ - Communication patterns (#19-21): one clear chatbot expression may be High.
277
+ - Short text (1-2 paragraphs): adjust thresholds proportionally.
278
+
279
+ ### Per-Category Score
280
+
281
+ ```
282
+ category_score = (sum of adjusted severities / (pattern_count × 3)) × 100
283
+ ```
284
+
285
+ ### Overall Score
286
+
287
+ ```
288
+ overall_score = Σ(category_score × category_weight) for all categories
289
+ ```
290
+
291
+ ### Profile Override Factors
292
+
293
+ | Override | Factor | Effect |
294
+ |----------|--------|--------|
295
+ | amplify | × 1.5 (cap 3) | Increases severity |
296
+ | reduce | × 0.5 | Decreases severity |
297
+ | suppress | × 0.0 | Excludes pattern |
298
+ | normal | × 1.0 | No change |
299
+
300
+ Language-scoped overrides (`ko:`, `en:`) take precedence over top-level overrides.
301
+
302
+ ### MPS (Meaning Preservation Score)
303
+
304
+ ```
305
+ anchor_pass_rate = PASS_count / total_anchor_count
306
+ polarity_preserved = polarity_PASS_count / total_polarity_anchor_count
307
+
308
+ MPS = (anchor_pass_rate × 0.6 + polarity_preserved × 0.4) × 100
309
+ ```
310
+
311
+ If no polarity anchors: `MPS = anchor_pass_rate × 100`
312
+ If no anchors extracted: `MPS = N/A`
313
+
314
+ | Range | Label |
315
+ |-------|-------|
316
+ | 90-100 | Excellent |
317
+ | 70-89 | Good |
318
+ | 50-69 | Warning |
319
+ | < 50 | Critical |
320
+
321
+ ---
322
+
323
+ ## Important Constraints
324
+
325
+ - **Preserve meaning**: claims, polarity, causation, quantifiers, negations must survive rewriting.
326
+ - **Do not fabricate**: no information not present in the original.
327
+ - **Match profile tone**: or the profile's target tone if explicitly overridden.
328
+ - **Inject voice**: follow `core/voice.md` per language.
329
+ - **Apply overrides**: respect `pattern-overrides` and `voice-overrides`.
330
+ - **No infinite loops**: self-audit runs once. Ouroboros has max-iterations cap.
331
+ - **Scores have variance**: ±8-10 points between runs due to LLM severity assignment. Interpret ranges, not exact numbers.
332
+
333
+ ---
334
+
335
+ ## MAX Mode (Multi-Model)
336
+
337
+ When using multiple models (claude, gemini, codex):
338
+ 1. Build one self-contained worker prompt (this template + inlined patterns/profile/voice)
339
+ 2. Dispatch to each model in parallel (tmux panes or sequential)
340
+ 3. Collect outputs
341
+ 4. Score each result independently using the same algorithm
342
+ 5. Calculate MPS for each result
343
+ 6. Select the candidate with the **lowest AI score where MPS ≥ 70**
344
+ 7. If all candidates have MPS < 70, select the one with the **highest MPS**
345
+
346
+ ### Dispatch Methods
347
+
348
+ - **OMC (tmux)**: Split panes, run models in parallel, poll sentinel files
349
+ - **Direct**: Sequential stdin pipe execution, no tmux dependency
350
+ - **API**: Send prompt to LLM API endpoints, collect responses
351
+
352
+ Each run uses a unique temp directory. Timeout models are marked `failed`.
353
+
354
+ ---
355
+
356
+ ## References
357
+
358
+ - `.patina.default.yaml` — configuration defaults
359
+ - `core/voice.md` — voice injection guidelines
360
+ - `core/scoring.md` — complete scoring algorithm
361
+ - `SKILL.md` — Claude Code-specific pipeline specification
362
+ - `patina-max/SKILL.md` — Claude Code MAX mode specification
363
+ - `AGENTS.md` — multi-agent project context
364
+ - `.cursor/rules/patina.md` — Cursor IDE rules