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,173 @@
1
+ # Cookbook
2
+
3
+ Practical recipes for plugging patina into existing writing and CI workflows. Each recipe is self-contained — copy, adapt, run.
4
+
5
+ For the full flag list see `patina --help` and [`CLI.md`](CLI.md). For tone / profile background see [`README.md`](../README.md#modes).
6
+
7
+ ---
8
+
9
+ ## 1. Batch-score a Hugo content folder
10
+
11
+ You have a Hugo site with many drafts under `content/posts/`. You want a quick AI-likeness scan over the whole folder before publishing.
12
+
13
+ ```bash
14
+ # from your Hugo project root
15
+ patina --lang en --score --batch content/posts/*.md
16
+ ```
17
+
18
+ `--batch` treats every positional arg as an input file, so any glob your shell expands works. `--score` per file prints `overall` plus the category breakdown.
19
+
20
+ For a stricter sweep that flags anything above 30/100, fail the run instead of just printing:
21
+
22
+ ```bash
23
+ patina --lang en --score --gate 30 --batch content/posts/*.md
24
+ ```
25
+
26
+ When any file's `overall` exceeds the gate, patina exits with code `3` ([`CLI.md`](CLI.md) §Exit codes), which is perfect for a pre-publish check.
27
+
28
+ ---
29
+
30
+ ## 2. GitHub Actions integration (minimal workflow YAML)
31
+
32
+ Run patina as a non-blocking quality check on every PR that touches markdown.
33
+
34
+ ```yaml
35
+ # .github/workflows/patina.yml
36
+ name: Patina score
37
+ on:
38
+ pull_request:
39
+ paths: ["**/*.md"]
40
+
41
+ jobs:
42
+ score:
43
+ runs-on: ubuntu-latest
44
+ steps:
45
+ - uses: actions/checkout@v4
46
+ - uses: actions/setup-node@v4
47
+ with:
48
+ node-version: "20"
49
+ - run: |
50
+ git clone --depth 1 https://github.com/devswha/patina.git /tmp/patina
51
+ cd /tmp/patina && npm install --omit=dev && npm link
52
+ - name: Score changed markdown
53
+ run: |
54
+ changed=$(git diff --name-only origin/${{ github.base_ref }}...HEAD -- '*.md')
55
+ [ -z "$changed" ] && echo "no markdown changes" && exit 0
56
+ patina --lang en --score --gate 30 --batch $changed
57
+ env:
58
+ # pick one backend that has a token in repo secrets
59
+ GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY }}
60
+ ```
61
+
62
+ Drop `--gate` while you calibrate the threshold for your project. Swap `GEMINI_API_KEY` for whichever backend you have (`claude` / `codex` / `gemini`) — see [`AUTHENTICATION.md`](AUTHENTICATION.md) for the full list.
63
+
64
+ ---
65
+
66
+ ## 3. Compare Claude vs Gemini output via MAX mode
67
+
68
+ When you want a defensible "best" rewrite, run the same paragraph through multiple backends and let MAX mode pick the lowest-AI result that still passes the MPS (Meaning Preservation Score) floor:
69
+
70
+ ```yaml
71
+ # .patina.yaml (project root)
72
+ max-models: [claude, gemini]
73
+ ```
74
+
75
+ ```bash
76
+ # Skill flavor (Claude Code / Codex CLI / Cursor / OpenCode):
77
+ /patina-max
78
+
79
+ [paste your text here]
80
+ ```
81
+
82
+ ```bash
83
+ # Standalone CLI flavor — same idea, MAX mode runs each backend independently
84
+ patina --lang en --backend claude-cli draft.md > /tmp/claude.txt
85
+ patina --lang en --backend gemini-cli draft.md > /tmp/gemini.txt
86
+ diff /tmp/claude.txt /tmp/gemini.txt
87
+ ```
88
+
89
+ MAX mode requires MPS ≥ 70 on each candidate before comparing scores, so the winner is the *lowest AI-likeness rewrite that still preserves meaning*. See [`GLOSSARY.md`](GLOSSARY.md) for MPS and the [`README.md`](../README.md#max-mode) MAX mode section for the selection rules.
90
+
91
+ ---
92
+
93
+ ## 4. Investigate a false positive with `--diff --audit`
94
+
95
+ A sentence got rewritten when you wanted it preserved. To see exactly which pattern fired, run audit and diff against the same input:
96
+
97
+ ```bash
98
+ patina --lang en --audit draft.md # which patterns the scanner thinks fired
99
+ patina --lang en --diff draft.md # pattern-by-pattern before/after
100
+ ```
101
+
102
+ Cross-reference the firing pattern IDs against [`PATTERNS.md`](PATTERNS.md). If a pattern is consistently mis-firing on your domain (e.g. legal boilerplate that legitimately uses "fundamentally"), add it to `skip-patterns` in your config:
103
+
104
+ ```yaml
105
+ # .patina.yaml
106
+ skip-patterns:
107
+ - en:7 # AI vocabulary words — too aggressive for legal prose
108
+ ```
109
+
110
+ `skip-patterns` is a list key that merges additively across default / global / project configs, so the project-level skip doesn't lose the defaults.
111
+
112
+ ---
113
+
114
+ ## 5. Create a custom profile (copy `blog.md`, edit voice-overrides)
115
+
116
+ When the built-in 12 profiles don't match your house style, fork the closest one:
117
+
118
+ ```bash
119
+ cp profiles/blog.md profiles/my-newsletter.md
120
+ ```
121
+
122
+ Edit the frontmatter — at minimum change `profile:`, then tune `voice-overrides` and `pattern-overrides` to match the voice you want:
123
+
124
+ ```yaml
125
+ ---
126
+ profile: my-newsletter # must match the filename without .md
127
+ name: Internal newsletter profile
128
+ version: 1.0.0
129
+ scope: weekly engineering newsletter
130
+ voice-overrides:
131
+ first-person: amplify # we sign every post
132
+ opinions: amplify # opinionated framing is the point
133
+ humor: allow # dry humor ok
134
+ messiness: reduce # cleaner than personal blog
135
+ pattern-overrides:
136
+ en:
137
+ 14: suppress # bold is allowed for scannable sections
138
+ 7: amplify # AI-vocab cleanup stays strict
139
+ ---
140
+ ```
141
+
142
+ Then opt-in per run:
143
+
144
+ ```bash
145
+ patina --lang en --profile my-newsletter post.md
146
+ ```
147
+
148
+ Voice-override values are `amplify` / `allow` / `reduce` / `suppress`; pattern IDs and their meanings are in [`PATTERNS.md`](PATTERNS.md).
149
+
150
+ ---
151
+
152
+ ## 6. Pre-commit hook wrapper *(optional)*
153
+
154
+ Block commits that introduce too-AI-sounding markdown. Drop this into `.git/hooks/pre-commit` (or wire it up through `pre-commit`/`husky` if you already use them):
155
+
156
+ ```bash
157
+ #!/usr/bin/env bash
158
+ set -euo pipefail
159
+ changed=$(git diff --cached --name-only --diff-filter=ACM -- '*.md')
160
+ [ -z "$changed" ] && exit 0
161
+ patina --lang en --score --gate 30 --batch $changed
162
+ ```
163
+
164
+ `--gate` returns exit code `3` when any file's `overall` exceeds the threshold, which the shell treats as failure and aborts the commit. To bypass once (e.g. you intentionally want hype copy), commit with `--no-verify`.
165
+
166
+ ---
167
+
168
+ ## Where to go next
169
+
170
+ - Tone reference: [`README.md`](../README.md#tones)
171
+ - Free-tier setup (no API key): [`AUTHENTICATION.md`](AUTHENTICATION.md)
172
+ - MPS and other terms: [`GLOSSARY.md`](GLOSSARY.md)
173
+ - Adding patterns or false-positive triage: [`CONTRIBUTING.md`](../CONTRIBUTING.md)
package/docs/DEMO.md ADDED
@@ -0,0 +1,40 @@
1
+ # Demo
2
+
3
+ A copy/paste demo for showing what patina does: remove AI packaging while keeping the claims intact.
4
+
5
+ ## 30-second terminal transcript
6
+
7
+ This transcript uses the checked-in short marketing fixture so the example is reviewable without screenshots or a live model run.
8
+
9
+ ```bash
10
+ $ cat examples/short/marketing-launch.md
11
+ 새롭게 출시된 노션 템플릿 팩은 생산성 향상을 위한 혁신적인 솔루션입니다. 다양한 워크플로우에 최적화된 30개의 템플릿을 제공하며, 사용자 친화적인 디자인으로 누구나 손쉽게 활용 가능합니다. 본 제품은 업무 효율성을 극대화하는 새로운 패러다임을 제시합니다.
12
+
13
+ $ patina --lang ko --tone marketing examples/short/marketing-launch.md
14
+ 새로 나온 노션 템플릿 팩에는 업무 흐름별로 바로 쓸 수 있는 템플릿 30개가 들어 있습니다. 복잡한 설정 없이 복제해서 쓰고, 팀이나 개인 작업 방식에 맞게 손보면 됩니다.
15
+
16
+ 노션을 매번 빈 페이지에서 시작했다면, 이제 그 시간부터 줄이세요.
17
+ ```
18
+
19
+ Full source/expected pair:
20
+ [`examples/short/marketing-launch.md`](../examples/short/marketing-launch.md) →
21
+ [`examples/short/marketing-launch-rewritten.md`](../examples/short/marketing-launch-rewritten.md).
22
+
23
+ ## Before/after snapshots
24
+
25
+ | Genre | Before | After |
26
+ |---|---|---|
27
+ | Korean marketing | “생산성 향상을 위한 혁신적인 솔루션… 업무 효율성을 극대화하는 새로운 패러다임” | “업무 흐름별로 바로 쓸 수 있는 템플릿 30개… 빈 페이지에서 시작했다면, 이제 그 시간부터 줄이세요.” |
28
+ | Academic | “획기적인 성과가 관찰되었으며… 중요한 역할을 수행할 수 있음을 시사한다” | “평균 구축 시간은 72시간에서 10분 이내로 줄었다… 일반화하기에는 주의가 필요하다.” |
29
+ | Technical | “핵심적인 역할을 수행… 차세대 AI 인프라 환경의 표준” | “GPU 자원 관리는 배포 속도와 운영 비용에 직접 영향을 준다… 검토할 만한 선택지다.” |
30
+
31
+ Reference files:
32
+
33
+ - Academic: [`examples/genres/academic.md`](../examples/genres/academic.md) → [`examples/genres/academic-rewritten.md`](../examples/genres/academic-rewritten.md)
34
+ - Technical: [`examples/genres/technical.md`](../examples/genres/technical.md) → [`examples/genres/technical-rewritten.md`](../examples/genres/technical-rewritten.md)
35
+
36
+ ## What to point out in a live demo
37
+
38
+ 1. The output removes inflated claims like “혁신적인 솔루션” and “새로운 패러다임.”
39
+ 2. Concrete facts survive: 30 templates, workflow fit, setup simplicity, and the user action.
40
+ 3. The rewrite is auditable because the source fixture, expected rewrite, and pattern catalog all live in the repo.
package/docs/ETHICS.md ADDED
@@ -0,0 +1,27 @@
1
+ # Ethics and Intended Use
2
+
3
+ Patina removes generic AI-writing packaging while preserving the author's intended meaning. It is an editing aid, not a provenance oracle.
4
+
5
+ ## Patina is for
6
+
7
+ - **Post-AI editing:** cleaning drafts that the author is permitted to create with AI assistance.
8
+ - **Audit trails:** showing which patterns were flagged and why a rewrite changed them.
9
+ - **Voice preservation:** making prose sound less templated without changing claims, numbers, polarity, or causation.
10
+ - **False-positive review:** helping maintainers and editors discuss suspicious passages without accusing a writer.
11
+ - **Contributor research:** improving pattern packs, fixtures, and benchmark methodology in public.
12
+
13
+ ## Patina is not for
14
+
15
+ - **Academic honor-code evasion.** If a school, journal, or publisher requires disclosure, patina does not remove that obligation.
16
+ - **Publisher or workplace AI-disclosure circumvention.** A cleaner sentence is not evidence that AI was not used.
17
+ - **Plagiarism laundering.** Rewriting copied text does not make it yours.
18
+ - **Detector-bypass guarantees.** Scores are editing signals with false positives and false negatives, not guarantees against Turnitin, GPTZero, Originality, or any other detector.
19
+ - **Authorship accusation.** Do not use patina output or score reports as proof that a person used AI.
20
+
21
+ ## What the score means
22
+
23
+ The AI-likeness score estimates how many known surface patterns appear in a text. It is useful for editing prioritization. It is not a moral judgment, authorship proof, or policy-compliance certificate.
24
+
25
+ ## Disclosure stance
26
+
27
+ If a policy asks whether AI assisted the writing, answer that policy honestly. Patina can help make allowed AI-assisted drafts clearer and more faithful to the author's intent, but it cannot convert AI-assisted work into “originally human” work under policies that define originality by process.
@@ -0,0 +1,130 @@
1
+ # Before/After Gallery
2
+
3
+ patina is easiest to understand with examples: the claims stay, the AI packaging goes.
4
+
5
+ ## English: inflated product copy
6
+
7
+ **Before**
8
+
9
+ > AI coding tools represent a transformative leap forward in the software development lifecycle, enabling teams to streamline workflows, enhance collaboration, and unlock unprecedented levels of productivity across the organization.
10
+
11
+ **After**
12
+
13
+ > AI coding tools are useful for the boring parts: test stubs, config files, small refactors. They do not fix a messy codebase, but they can save time when someone still checks the output.
14
+
15
+ **Patterns removed**: inflated stakes, corporate abstractions, three-part benefit stack.
16
+
17
+ ## Korean: benefit stacking
18
+
19
+ **Before**
20
+
21
+ > 본 솔루션은 사용자의 업무 효율성을 극대화하고, 생산성 향상을 도모하며, 더 나은 협업 경험을 제공하는 혁신적인 도구입니다.
22
+
23
+ **After**
24
+
25
+ > 이 도구는 반복 작업을 줄여준다. 문서 정리, 초안 작성, 간단한 협업 흐름처럼 사람이 굳이 매번 손으로 할 필요 없는 일에 잘 맞는다.
26
+
27
+ **Patterns removed**: `혁신적인`, `도모`, abstract benefit stacking, stiff noun-heavy phrasing.
28
+
29
+ ## English: vague balance
30
+
31
+ **Before**
32
+
33
+ > While there are challenges to consider, it is important to recognize that this technology has the potential to create meaningful value when implemented thoughtfully.
34
+
35
+ **After**
36
+
37
+ > The tool is useful, but only if someone checks the output. Without tests or review, it just makes wrong answers arrive faster.
38
+
39
+ **Patterns removed**: generic caveat, vague upside, empty balance.
40
+
41
+ ## Technical: architecture claims
42
+
43
+ **Before**
44
+
45
+ > This architecture provides a robust and scalable foundation for future enhancements, ensuring that teams can effectively adapt to evolving requirements while maintaining operational excellence.
46
+
47
+ **After**
48
+
49
+ > The architecture leaves room for new backends without touching the CLI entry point. That is the useful part. The tradeoff is more config surface, so the defaults need to stay boring and safe.
50
+
51
+ **Patterns removed**: `robust and scalable foundation`, future-proofing claims, operational-excellence filler.
52
+
53
+ ## Korean: instructional / tutorial register
54
+
55
+ **Before**
56
+
57
+ > Git stash는 작업 중인 변경사항을 임시로 저장할 수 있는 매우 유용한 기능입니다. 본 명령어를 활용함으로써 사용자는 현재 작업 내용을 손실 없이 다른 브랜치로 신속하게 전환할 수 있게 됩니다.
58
+
59
+ **After**
60
+
61
+ > Git stash로 작업 중인 변경사항을 잠시 보관하세요. 커밋하기 애매한 수정이 있을 때 유용합니다. stash에 넣어두면 변경사항을 잃지 않고 다른 브랜치로 이동할 수 있습니다.
62
+
63
+ **Patterns removed**: `매우 유용한` (ko-content #4 promotional adjective), `본 명령어를 활용함으로써` (ko-style noun-heavy formal connector), `~할 수 있게 됩니다` (ko-structure #25 inflated future-tense). Use-context ("커밋하기 애매한 수정이 있을 때") added so the tutorial actually teaches *when* to use the command.
64
+
65
+ ## Korean: 1인칭 회고 — abstract metaphor → sensory detail
66
+
67
+ **Before**
68
+
69
+ > 처음 코드 리뷰를 받았던 날을 떠올리면 여전히 마음 한구석이 묘해지는 것을 느낀다. 선배의 피드백 한 줄 한 줄이 마치 거대한 산처럼 다가왔으며, 그 순간은 개발자로서의 성장에 있어 잊을 수 없는 의미 있는 전환점이었다고 표현할 수 있을 것이다.
70
+
71
+ **After**
72
+
73
+ > 처음 코드 리뷰를 받던 날이 아직도 가끔 떠오른다. 선배가 남긴 피드백은 한 줄씩 읽을 때마다 이상하게 크게 느껴졌다. 모니터 앞에서 댓글을 하나씩 열어보던 장면이 선명하다. 손은 마우스 위에 있었고, 머릿속은 자꾸 하얘졌다. 지금 생각하면 그날은 대단한 사건이라기보다, 내가 처음으로 내 코드를 남의 눈으로 본 날에 가까웠다.
74
+
75
+ **Patterns removed**: `마치 거대한 산처럼` (ko-content abstract metaphor), `의미 있는 전환점이었다고 표현할 수 있을 것이다` (ko-structure #25 hedge stack + ko-content inflated significance). Replaced with concrete physical detail (`손은 마우스 위에`, `머릿속은 자꾸 하얘졌다`) — the narrative profile's `concrete-emotions: amplify` setting.
76
+
77
+ ## Korean: SNS marketing — viral-hook signals
78
+
79
+ **Before**
80
+
81
+ > GitHub 역사상 이런 속도는 없었다. 단 60일 만에 별 25만 개. OpenClaw라는 도구가 세운 기록임. 광고 한 번 안 하고 전 세계 개발자들이 미친 듯이 달려든 이유가 뭘까.
82
+
83
+ **After**
84
+
85
+ > GitHub에서 이런 속도는 거의 못 봤다. 60일 만에 별 25만 개. OpenClaw가 만든 기록이다. 광고로 뜬 게 아니다. 개발자들이 새벽 3시에 버그 잡다가 짜증 나던 부분을 정확히 긁었다.
86
+
87
+ **Patterns removed**: `역사상 ... 없었다` (ko-viral-hook #3 source-skipping authority claim), `미친 듯이 달려든` (ko-viral-hook #5 hyperbolic engagement lexicon), `이유가 뭘까` (ko-viral-hook #2 clickbait mystery close → resolved into concrete explanation). The viral-hook pack is **score-only**, but the model still re-frames these signals during a regular rewrite once the content/style packs are applied.
88
+
89
+ ## English: chatbot register
90
+
91
+ **Before**
92
+
93
+ > I'd be happy to help you understand Git stash! That's a great question. Git stash is a very useful command that allows you to temporarily save your changes. Let me know if you have any other questions!
94
+
95
+ **After**
96
+
97
+ > Git stash temporarily saves your in-progress changes so you can switch branches without committing or losing them. It's most useful when a fix or quick task pulls you off the work you're already doing.
98
+
99
+ **Patterns removed**: `I'd be happy to help` + `That's a great question` (en-communication #19 chatbot expressions, #21 sycophancy), `very useful` (en-content promotional adjective), `Let me know if you have any other questions` (en-communication closing politeness). Replaces the chat affect with the actual answer.
100
+
101
+ ## English: viral-hook authority claim
102
+
103
+ **Before**
104
+
105
+ > The fastest growth GitHub has ever seen — devs around the world are absolutely losing their minds. Why is everyone flocking to OpenClaw without any marketing?
106
+
107
+ **After**
108
+
109
+ > OpenClaw hit 250K stars in 60 days with no paid promotion. The popularity didn't come from marketing — it came from one shipped command that replaces a few hours of cluster setup. NVIDIA has since picked it up, which makes the timing easier to read.
110
+
111
+ **Patterns removed**: `the fastest GitHub has ever seen` (en-viral-hook #3 source-skipping authority claim), `absolutely losing their minds` (en-viral-hook #5 hyperbolic lexicon), `Why is everyone ... without any marketing?` (en-viral-hook #2 clickbait mystery close). Concrete numbers + a verifiable corroborating fact replace the unsupported absolutes. Like the Korean SNS example above, viral-hook is score-only — the rewrite drives this through neighboring content/style patterns.
112
+
113
+ ## More gallery material
114
+
115
+ This page shows the canonical short examples. The repo also ships longer fixtures and full case studies you can copy from:
116
+
117
+ - **`examples/short/`** — four short Korean fixtures (marketing, tutorial, essay, email) with paired `*-rewritten.md` files.
118
+ - **`examples/genres/`** — three longer Korean genres (technical, academic, narrative) with paired rewrites.
119
+ - **`examples/tones/`** — the same input rewritten in six tones (`casual`, `professional`, `academic`, `narrative`, `marketing`, `instructional`) plus `auto`. See `examples/tones/RESULTS.md` for the side-by-side.
120
+ - **`examples/viral-hook/`** — case studies (`case-01` through `case-09`) covering the iterative improvement workflow: viral-hook detection, codex/claude/gemini comparisons, voice profiles, multi-genre validation.
121
+ - **`examples/sample-rewritten-*.md`** — the same long-form Korean SNS marketing post rewritten by Codex / Claude / Gemini-3, used in `case-03` for cross-model comparison.
122
+
123
+ ## What patina is checking
124
+
125
+ - Did the rewrite remove AI-writing patterns?
126
+ - Did the rewrite keep the original claims?
127
+ - Did the rewrite introduce anything that was not in the source?
128
+ - Can the change be inspected through `--audit`, `--diff`, or `--score`?
129
+
130
+ The goal is editing quality, not detector evasion. AI detectors are noisy; patina treats the score as a rough signal and the diff as the useful artifact.
@@ -0,0 +1,130 @@
1
+ # Before/After Gallery
2
+
3
+ patina는 예시로 보는 편이 가장 쉽습니다. 주장은 남고, AI 포장은 사라집니다.
4
+
5
+ ## English: 부풀린 제품 카피
6
+
7
+ **Before**
8
+
9
+ > AI coding tools represent a transformative leap forward in the software development lifecycle, enabling teams to streamline workflows, enhance collaboration, and unlock unprecedented levels of productivity across the organization.
10
+
11
+ **After**
12
+
13
+ > AI coding tools are useful for the boring parts: test stubs, config files, small refactors. They do not fix a messy codebase, but they can save time when someone still checks the output.
14
+
15
+ **제거한 패턴**: 부풀린 중요도, 기업식 추상어, 세 갈래 장점 나열.
16
+
17
+ ## Korean: 장점 나열
18
+
19
+ **Before**
20
+
21
+ > 본 솔루션은 사용자의 업무 효율성을 극대화하고, 생산성 향상을 도모하며, 더 나은 협업 경험을 제공하는 혁신적인 도구입니다.
22
+
23
+ **After**
24
+
25
+ > 이 도구는 반복 작업을 줄여준다. 문서 정리, 초안 작성, 간단한 협업 흐름처럼 사람이 굳이 매번 손으로 할 필요 없는 일에 잘 맞는다.
26
+
27
+ **제거한 패턴**: `혁신적인`, `도모`, 추상적인 장점 나열, 딱딱한 명사형 문장.
28
+
29
+ ## English: 흐릿한 균형감
30
+
31
+ **Before**
32
+
33
+ > While there are challenges to consider, it is important to recognize that this technology has the potential to create meaningful value when implemented thoughtfully.
34
+
35
+ **After**
36
+
37
+ > The tool is useful, but only if someone checks the output. Without tests or review, it just makes wrong answers arrive faster.
38
+
39
+ **제거한 패턴**: 일반적인 caveat, 흐릿한 upside, 빈 균형감.
40
+
41
+ ## Technical: 아키텍처 주장
42
+
43
+ **Before**
44
+
45
+ > This architecture provides a robust and scalable foundation for future enhancements, ensuring that teams can effectively adapt to evolving requirements while maintaining operational excellence.
46
+
47
+ **After**
48
+
49
+ > The architecture leaves room for new backends without touching the CLI entry point. That is the useful part. The tradeoff is more config surface, so the defaults need to stay boring and safe.
50
+
51
+ **제거한 패턴**: `robust and scalable foundation`, future-proofing 주장, operational-excellence filler.
52
+
53
+ ## Korean: instructional / tutorial register
54
+
55
+ **Before**
56
+
57
+ > Git stash는 작업 중인 변경사항을 임시로 저장할 수 있는 매우 유용한 기능입니다. 본 명령어를 활용함으로써 사용자는 현재 작업 내용을 손실 없이 다른 브랜치로 신속하게 전환할 수 있게 됩니다.
58
+
59
+ **After**
60
+
61
+ > Git stash로 작업 중인 변경사항을 잠시 보관하세요. 커밋하기 애매한 수정이 있을 때 유용합니다. stash에 넣어두면 변경사항을 잃지 않고 다른 브랜치로 이동할 수 있습니다.
62
+
63
+ **제거한 패턴**: `매우 유용한` (ko-content #4 promotional adjective), `본 명령어를 활용함으로써` (ko-style noun-heavy formal connector), `~할 수 있게 됩니다` (ko-structure #25 inflated future-tense). 튜토리얼이 명령을 *언제* 쓰는지 알려 주도록 사용 맥락("커밋하기 애매한 수정이 있을 때")을 추가했습니다.
64
+
65
+ ## Korean: 1인칭 회고 — abstract metaphor → sensory detail
66
+
67
+ **Before**
68
+
69
+ > 처음 코드 리뷰를 받았던 날을 떠올리면 여전히 마음 한구석이 묘해지는 것을 느낀다. 선배의 피드백 한 줄 한 줄이 마치 거대한 산처럼 다가왔으며, 그 순간은 개발자로서의 성장에 있어 잊을 수 없는 의미 있는 전환점이었다고 표현할 수 있을 것이다.
70
+
71
+ **After**
72
+
73
+ > 처음 코드 리뷰를 받던 날이 아직도 가끔 떠오른다. 선배가 남긴 피드백은 한 줄씩 읽을 때마다 이상하게 크게 느껴졌다. 모니터 앞에서 댓글을 하나씩 열어보던 장면이 선명하다. 손은 마우스 위에 있었고, 머릿속은 자꾸 하얘졌다. 지금 생각하면 그날은 대단한 사건이라기보다, 내가 처음으로 내 코드를 남의 눈으로 본 날에 가까웠다.
74
+
75
+ **제거한 패턴**: `마치 거대한 산처럼` (ko-content abstract metaphor), `의미 있는 전환점이었다고 표현할 수 있을 것이다` (ko-structure #25 hedge stack + ko-content inflated significance). 구체적인 신체 디테일(`손은 마우스 위에`, `머릿속은 자꾸 하얘졌다`)로 바꿨습니다. narrative profile의 `concrete-emotions: amplify` 설정입니다.
76
+
77
+ ## Korean: SNS marketing — viral-hook signals
78
+
79
+ **Before**
80
+
81
+ > GitHub 역사상 이런 속도는 없었다. 단 60일 만에 별 25만 개. OpenClaw라는 도구가 세운 기록임. 광고 한 번 안 하고 전 세계 개발자들이 미친 듯이 달려든 이유가 뭘까.
82
+
83
+ **After**
84
+
85
+ > GitHub에서 이런 속도는 거의 못 봤다. 60일 만에 별 25만 개. OpenClaw가 만든 기록이다. 광고로 뜬 게 아니다. 개발자들이 새벽 3시에 버그 잡다가 짜증 나던 부분을 정확히 긁었다.
86
+
87
+ **제거한 패턴**: `역사상 ... 없었다` (ko-viral-hook #3 source-skipping authority claim), `미친 듯이 달려든` (ko-viral-hook #5 hyperbolic engagement lexicon), `이유가 뭘까` (ko-viral-hook #2 clickbait mystery close → 구체적 설명으로 해결). viral-hook pack은 **score-only**지만, content/style pack이 적용된 regular rewrite에서도 모델이 이런 신호를 다시 잡아냅니다.
88
+
89
+ ## English: chatbot register
90
+
91
+ **Before**
92
+
93
+ > I'd be happy to help you understand Git stash! That's a great question. Git stash is a very useful command that allows you to temporarily save your changes. Let me know if you have any other questions!
94
+
95
+ **After**
96
+
97
+ > Git stash temporarily saves your in-progress changes so you can switch branches without committing or losing them. It's most useful when a fix or quick task pulls you off the work you're already doing.
98
+
99
+ **제거한 패턴**: `I'd be happy to help` + `That's a great question` (en-communication #19 chatbot expressions, #21 sycophancy), `very useful` (en-content promotional adjective), `Let me know if you have any other questions` (en-communication closing politeness). chat affect를 걷어내고 실제 답변만 남겼습니다.
100
+
101
+ ## English: viral-hook authority claim
102
+
103
+ **Before**
104
+
105
+ > The fastest growth GitHub has ever seen — devs around the world are absolutely losing their minds. Why is everyone flocking to OpenClaw without any marketing?
106
+
107
+ **After**
108
+
109
+ > OpenClaw hit 250K stars in 60 days with no paid promotion. The popularity didn't come from marketing — it came from one shipped command that replaces a few hours of cluster setup. NVIDIA has since picked it up, which makes the timing easier to read.
110
+
111
+ **제거한 패턴**: `the fastest GitHub has ever seen` (en-viral-hook #3 source-skipping authority claim), `absolutely losing their minds` (en-viral-hook #5 hyperbolic lexicon), `Why is everyone ... without any marketing?` (en-viral-hook #2 clickbait mystery close). 근거 없는 절대 표현을 구체적인 숫자와 확인 가능한 보강 사실로 바꿨습니다. 위 Korean SNS 예시처럼 viral-hook은 score-only이며, rewrite는 인접한 content/style pattern을 통해 이를 줄입니다.
112
+
113
+ ## 갤러리 추가 자료
114
+
115
+ 이 페이지는 표준 짧은 예시를 보여 줍니다. repo에는 복사해서 볼 수 있는 더 긴 fixture와 case study도 있습니다.
116
+
117
+ - **`examples/short/`** — 네 개의 짧은 Korean fixture(marketing, tutorial, essay, email)와 짝을 이루는 `*-rewritten.md` 파일.
118
+ - **`examples/genres/`** — 세 개의 긴 Korean genre(technical, academic, narrative)와 짝을 이루는 rewrite.
119
+ - **`examples/tones/`** — 같은 입력을 여섯 tone(`casual`, `professional`, `academic`, `narrative`, `marketing`, `instructional`)과 `auto`로 rewrite한 결과. 나란히 보려면 `examples/tones/RESULTS.md`를 참고하세요.
120
+ - **`examples/viral-hook/`** — iterative improvement workflow를 다루는 case study(`case-01`부터 `case-09`): viral-hook detection, codex/claude/gemini comparison, voice profile, multi-genre validation.
121
+ - **`examples/sample-rewritten-*.md`** — 같은 장문의 Korean SNS marketing post를 Codex / Claude / Gemini-3로 rewrite한 결과. `case-03`에서 cross-model comparison에 사용합니다.
122
+
123
+ ## patina가 확인하는 것
124
+
125
+ - rewrite가 AI-writing pattern을 제거했나요?
126
+ - rewrite가 원래 주장을 유지했나요?
127
+ - rewrite가 source에 없던 내용을 추가했나요?
128
+ - 변경을 `--audit`, `--diff`, `--score`로 검토할 수 있나요?
129
+
130
+ 목표는 editing quality이지 detector evasion이 아닙니다. AI detector는 잡음이 많습니다. patina는 score를 대략적인 신호로 보고, diff를 실제로 유용한 산출물로 봅니다.
@@ -0,0 +1,25 @@
1
+ # Exit Codes
2
+
3
+ patina uses stable exit codes so CI and editor integrations can distinguish content gates from setup failures.
4
+
5
+ | Code | Meaning |
6
+ |---:|---|
7
+ | `0` | Success. For `--score --exit-on <n>`, the parsed `overall` score was at or below the threshold. |
8
+ | `1` | Runtime/backend failure: API/auth/backend errors, failed doctor blockers, invalid runtime setup, or unexpected exceptions. |
9
+ | `2` | Input/usage failure: unknown flags, missing required option values, empty stdin, or `--no-interactive` with no input. |
10
+ | `3` | Score gate exceeded. `--score --exit-on <n>` or `--score --gate <n>` completed, but `overall > n`. |
11
+ | `4` | MAX mode could not produce a fully acceptable candidate: all candidates failed, or no candidate reached the MPS floor and patina selected the highest-MPS fallback. |
12
+
13
+ ## Score gates
14
+
15
+ ```bash
16
+ patina --lang en --score --exit-on 30 draft.md
17
+ ```
18
+
19
+ `--gate <n>` remains as a backward-compatible alias for the same behavior. The command still prints the score output; only the process exit code changes to `3` when the gate fails.
20
+
21
+ ## Empty input
22
+
23
+ - Piped empty or whitespace-only stdin exits `2` and prints a three-line `[patina] Error:` message.
24
+ - In an interactive TTY, patina prompts for one-shot stdin and waits until Ctrl-D.
25
+ - `--no-interactive` restores script-safe no-input behavior: no prompt, exit `2`.
package/docs/FAQ.md ADDED
@@ -0,0 +1,67 @@
1
+ # FAQ
2
+
3
+ New to the vocabulary? Start with the [Glossary](GLOSSARY.md) for short
4
+ definitions of MPS, fidelity, burstiness, MATTR, modes, and other recurring
5
+ terms.
6
+
7
+ ## Is patina an AI detector bypass tool?
8
+
9
+ No. patina is an editing and audit tool.
10
+
11
+ AI detectors are noisy, and patina does not treat any score as proof that a text was written by a human or by AI. The useful artifacts are the audit, the diff, and the meaning-preservation checks: what changed, why it changed, and whether the original claims survived.
12
+
13
+ ## What does "Strip the AI packaging" mean?
14
+
15
+ Many model outputs use the same surface habits: inflated stakes, vague balance, benefit stacking, corporate abstractions, metronomic paragraph rhythm, and filler transitions. patina looks for those patterns and rewrites the affected passages into plainer prose.
16
+
17
+ The goal is not to make a text deceptive. The goal is to remove generic model voice while keeping the actual message intact.
18
+
19
+ ## How does patina preserve meaning?
20
+
21
+ patina extracts semantic anchors before rewriting: claims, polarity, causation, numbers, negation, and other high-risk details. After each rewrite phase, it checks whether those anchors are still present and whether their polarity stayed the same.
22
+
23
+ If a rewrite weakens, deletes, or reverses an anchor, patina retries the section or rolls it back.
24
+
25
+ ## What is MPS?
26
+
27
+ MPS means Meaning Preservation Score. It is a rewrite-side safety signal that estimates how many extracted anchors survived the edit.
28
+
29
+ A high MPS does not mean the prose is perfect. It means the rewrite did not obviously drop or flip the claims patina was tracking.
30
+
31
+ ## What does the AI-likeness score mean?
32
+
33
+ The score is a rough editing signal from 0 to 100. Lower is less AI-sounding.
34
+
35
+ It is not a truth machine. The scoring formula is deterministic, but severity assignment can vary by roughly 8-10 points between model runs. Treat the range and the highlighted patterns as more important than the exact number.
36
+
37
+ ## How accurate is it?
38
+
39
+ Current calibration reports 91% editing-hotspot recall on Korean AI text [84.0-95.4%] and 76% on HC3 English ChatGPT samples [66.7-83.3%], each with n=100 and binomial 95% CI. Human-prose false positives are tracked separately as a 13-25% point-estimate range across registers.
40
+
41
+ False positives are expected, especially for encyclopedic, corporate, academic, or heavily edited prose. patina is meant to help edit suspicious passages, not to accuse a writer.
42
+
43
+ See [ETHICS.md](ETHICS.md) for the intended-use position statement.
44
+
45
+ ## Does it work without an API key?
46
+
47
+ Yes, if you already have the Codex CLI installed and logged in. The installer can wire patina into Codex CLI as a backend, so no separate API key is required for that path.
48
+
49
+ Other providers can be configured through the documented backend and provider settings.
50
+
51
+ ## Does it only work in Claude Code?
52
+
53
+ No. patina runs as a skill for Claude Code, Codex CLI, Cursor, and OpenCode, and it also works as a standalone Node.js CLI.
54
+
55
+ ## Which languages are supported?
56
+
57
+ Korean, English, Chinese, and Japanese are supported. Pattern packs are auto-discovered by language prefix, so new languages can be added by contributing new pattern files.
58
+
59
+ ## Can I add my own writing style or patterns?
60
+
61
+ Yes. Use custom profiles for voice preferences and custom pattern packs for local rules. The repo keeps built-in patterns separate from user customizations.
62
+
63
+ ## What should contributors start with?
64
+
65
+ The easiest contributions are small, evidence-backed examples: a before/after pair, a false positive case, a missing AI-writing pattern, or a language-specific phrase that keeps appearing in model output.
66
+
67
+ Good pattern contributions should include both a failing example and a successful rewrite.