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.
- package/.patina.default.yaml +211 -0
- package/CHANGELOG.md +265 -0
- package/LICENSE +21 -0
- package/README.md +319 -0
- package/README_JA.md +254 -0
- package/README_KR.md +253 -0
- package/README_ZH.md +254 -0
- package/SKILL-MAX.md +455 -0
- package/SKILL.md +730 -0
- package/assets/brand/patina-icon.svg +9 -0
- package/assets/brand/patina-logo.svg +17 -0
- package/assets/social/patina-before-after.svg +46 -0
- package/assets/social/patina-og.svg +31 -0
- package/bin/patina.js +9 -0
- package/core/scoring.md +657 -0
- package/core/standalone-prompt.md +364 -0
- package/core/stylometry.md +754 -0
- package/core/voice.md +163 -0
- package/docs/AUTHENTICATION.md +105 -0
- package/docs/AUTHENTICATION_KR.md +105 -0
- package/docs/BRANDING.md +37 -0
- package/docs/CLI.md +80 -0
- package/docs/COMPARISON.md +38 -0
- package/docs/COOKBOOK.md +173 -0
- package/docs/DEMO.md +40 -0
- package/docs/ETHICS.md +27 -0
- package/docs/EXAMPLES.md +130 -0
- package/docs/EXAMPLES_KR.md +130 -0
- package/docs/EXIT-CODES.md +25 -0
- package/docs/FAQ.md +67 -0
- package/docs/FAQ_KR.md +65 -0
- package/docs/FLAG-PARITY.md +53 -0
- package/docs/GLOSSARY.md +123 -0
- package/docs/PATTERNS-EN.md +718 -0
- package/docs/PATTERNS-JA.md +706 -0
- package/docs/PATTERNS-KO.md +707 -0
- package/docs/PATTERNS-ZH.md +706 -0
- package/docs/PATTERNS.md +22 -0
- package/docs/ROADMAP.md +315 -0
- package/docs/audits/2026-05-deep-research.md +290 -0
- package/docs/benchmarks/detector-comparison.json +442 -0
- package/docs/benchmarks/detector-comparison.md +65 -0
- package/docs/benchmarks/latest.json +988 -0
- package/docs/benchmarks/latest.md +112 -0
- package/docs/integrations/docker.md +19 -0
- package/docs/integrations/github-action.md +59 -0
- package/docs/integrations/pre-commit.md +77 -0
- package/docs/integrations/release.md +43 -0
- package/docs/internal/HARNESS.md +14 -0
- package/docs/internal/README.md +14 -0
- package/docs/internal/WARP.md +23 -0
- package/docs/research/2025-rebaseline-plan.md +89 -0
- package/docs/research/ai-human-metrics.md +380 -0
- package/docs/social/gstack-cardnews.html +236 -0
- package/docs/social/gstack-cardnews.md +88 -0
- package/docs/social/gstack-thread.md +106 -0
- package/docs/social/patina-launch-copy.md +227 -0
- package/docs/superpowers/specs/2026-04-03-meaning-preservation-design.md +299 -0
- package/lexicon/ai-en.md +162 -0
- package/lexicon/ai-ko.md +159 -0
- package/package.json +100 -0
- package/patina-max/SKILL.md +523 -0
- package/patina-max/composite.py +457 -0
- package/patterns/en-communication.md +89 -0
- package/patterns/en-content.md +133 -0
- package/patterns/en-filler.md +113 -0
- package/patterns/en-language.md +163 -0
- package/patterns/en-structure.md +173 -0
- package/patterns/en-style.md +139 -0
- package/patterns/en-viral-hook.md +211 -0
- package/patterns/ja-communication.md +101 -0
- package/patterns/ja-content.md +153 -0
- package/patterns/ja-filler.md +123 -0
- package/patterns/ja-language.md +190 -0
- package/patterns/ja-structure.md +142 -0
- package/patterns/ja-style.md +147 -0
- package/patterns/ja-viral-hook.md +216 -0
- package/patterns/ko-communication.md +98 -0
- package/patterns/ko-content.md +154 -0
- package/patterns/ko-filler.md +105 -0
- package/patterns/ko-language.md +182 -0
- package/patterns/ko-structure.md +147 -0
- package/patterns/ko-style.md +146 -0
- package/patterns/ko-viral-hook.md +211 -0
- package/patterns/zh-communication.md +101 -0
- package/patterns/zh-content.md +153 -0
- package/patterns/zh-filler.md +118 -0
- package/patterns/zh-language.md +173 -0
- package/patterns/zh-structure.md +145 -0
- package/patterns/zh-style.md +159 -0
- package/patterns/zh-viral-hook.md +216 -0
- package/profiles/academic.md +53 -0
- package/profiles/blog.md +81 -0
- package/profiles/casual-conversation.md +105 -0
- package/profiles/code-comment.md +104 -0
- package/profiles/commit-message.md +99 -0
- package/profiles/default.md +62 -0
- package/profiles/email.md +52 -0
- package/profiles/formal.md +98 -0
- package/profiles/instructional.md +80 -0
- package/profiles/legal.md +57 -0
- package/profiles/marketing.md +56 -0
- package/profiles/medical.md +53 -0
- package/profiles/narrative.md +79 -0
- package/profiles/release-notes.md +98 -0
- package/profiles/social.md +56 -0
- package/profiles/technical.md +53 -0
- package/scripts/benchmark-report.mjs +252 -0
- package/scripts/check-release-metadata.mjs +48 -0
- package/scripts/detector-comparison.mjs +267 -0
- package/scripts/lint.mjs +40 -0
- package/scripts/precommit-score.mjs +31 -0
- package/scripts/prose-score.mjs +186 -0
- package/scripts/update-benchmark-ranges.mjs +108 -0
- package/src/api.js +330 -0
- package/src/auth.js +105 -0
- package/src/backends/claude-cli.js +112 -0
- package/src/backends/codex-cli.js +121 -0
- package/src/backends/contract.js +21 -0
- package/src/backends/gemini-cli.js +135 -0
- package/src/backends/index.js +159 -0
- package/src/cache.js +106 -0
- package/src/cli.js +1280 -0
- package/src/commands/doctor.js +229 -0
- package/src/commands/init.js +208 -0
- package/src/config.js +126 -0
- package/src/errors.js +53 -0
- package/src/features/index.js +96 -0
- package/src/features/lexicon.js +90 -0
- package/src/features/segment.js +49 -0
- package/src/features/stylometry.js +50 -0
- package/src/loader.js +103 -0
- package/src/logger.js +70 -0
- package/src/manifest.js +162 -0
- package/src/max-mode.js +207 -0
- package/src/ouroboros.js +233 -0
- package/src/output.js +480 -0
- package/src/prompt-builder.js +409 -0
- package/src/providers.js +100 -0
- package/src/scoring.js +531 -0
- package/src/security.js +133 -0
- package/tests/fixtures/suspect-zones/en/ai/en-ai-01.md +16 -0
- package/tests/fixtures/suspect-zones/en/ai/en-ai-02.md +16 -0
- package/tests/fixtures/suspect-zones/en/ai/en-ai-03.md +17 -0
- package/tests/fixtures/suspect-zones/en/ai/en-ai-04.md +15 -0
- package/tests/fixtures/suspect-zones/en/ai/en-ai-05.md +16 -0
- package/tests/fixtures/suspect-zones/en/ai/en-ai-06-chat-register.md +16 -0
- package/tests/fixtures/suspect-zones/en/natural/en-nat-01.md +15 -0
- package/tests/fixtures/suspect-zones/en/natural/en-nat-02.md +15 -0
- package/tests/fixtures/suspect-zones/en/natural/en-nat-03.md +15 -0
- package/tests/fixtures/suspect-zones/en/natural/en-nat-04.md +15 -0
- package/tests/fixtures/suspect-zones/en/natural/en-nat-05.md +15 -0
- package/tests/fixtures/suspect-zones/expected-ranges.json +939 -0
- package/tests/fixtures/suspect-zones/ja/ai/ja-ai-01.md +11 -0
- package/tests/fixtures/suspect-zones/ja/ai/ja-ai-02.md +11 -0
- package/tests/fixtures/suspect-zones/ja/ai/ja-ai-03.md +11 -0
- package/tests/fixtures/suspect-zones/ja/natural/ja-nat-01.md +11 -0
- package/tests/fixtures/suspect-zones/ja/natural/ja-nat-02.md +11 -0
- package/tests/fixtures/suspect-zones/ja/natural/ja-nat-03.md +11 -0
- package/tests/fixtures/suspect-zones/ko/ai/ko-ai-01.md +14 -0
- package/tests/fixtures/suspect-zones/ko/ai/ko-ai-02.md +16 -0
- package/tests/fixtures/suspect-zones/ko/ai/ko-ai-03.md +15 -0
- package/tests/fixtures/suspect-zones/ko/ai/ko-ai-04.md +15 -0
- package/tests/fixtures/suspect-zones/ko/ai/ko-ai-05.md +16 -0
- package/tests/fixtures/suspect-zones/ko/ai/ko-ai-06-chat-register.md +16 -0
- package/tests/fixtures/suspect-zones/ko/natural/ko-nat-01.md +15 -0
- package/tests/fixtures/suspect-zones/ko/natural/ko-nat-02.md +15 -0
- package/tests/fixtures/suspect-zones/ko/natural/ko-nat-03.md +15 -0
- package/tests/fixtures/suspect-zones/ko/natural/ko-nat-04.md +14 -0
- package/tests/fixtures/suspect-zones/ko/natural/ko-nat-05.md +15 -0
- package/tests/fixtures/suspect-zones/zh/ai/zh-ai-01.md +11 -0
- package/tests/fixtures/suspect-zones/zh/ai/zh-ai-02.md +11 -0
- package/tests/fixtures/suspect-zones/zh/ai/zh-ai-03.md +11 -0
- package/tests/fixtures/suspect-zones/zh/natural/zh-nat-01.md +11 -0
- package/tests/fixtures/suspect-zones/zh/natural/zh-nat-02.md +11 -0
- package/tests/fixtures/suspect-zones/zh/natural/zh-nat-03.md +11 -0
- package/tests/quality/README.md +121 -0
- package/tests/quality/benchmark.mjs +306 -0
- package/tests/quality/detectors.manual.example.json +31 -0
- package/tests/quality/dogfood.mjs +44 -0
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
version: "3.11.0"
|
|
2
|
+
language: ko # Korean (default) -- auto-loads all ko-*.md patterns
|
|
3
|
+
# language: en -- English -- auto-loads all en-*.md patterns
|
|
4
|
+
# language: zh -- Chinese -- auto-loads all zh-*.md patterns
|
|
5
|
+
# language: ja -- Japanese -- auto-loads all ja-*.md patterns
|
|
6
|
+
# Override with CLI: --lang en / --lang zh / --lang ja
|
|
7
|
+
profile: default
|
|
8
|
+
output: rewrite # rewrite | diff | audit | score
|
|
9
|
+
|
|
10
|
+
# Tone categorization (v3.10): named voice axis. Six v1 tones for ko/en.
|
|
11
|
+
# Resolution: explicit --tone > config tone > config profile.
|
|
12
|
+
# auto = heuristic single-tone detection at SKILL.md Phase 4.5b.
|
|
13
|
+
# Unset = profile-only legacy behavior (regression-safe default).
|
|
14
|
+
tone: # one of: casual, professional, academic, narrative, marketing, instructional, auto
|
|
15
|
+
# Override with CLI: --tone <name>
|
|
16
|
+
# zh/ja with explicit tone: warns and falls back to profile.
|
|
17
|
+
|
|
18
|
+
# Optional path to 1-3 user-written paragraphs. CLI --voice-sample wins.
|
|
19
|
+
# Used as a style/register anchor only; facts stay sourced from the input text.
|
|
20
|
+
voice-sample:
|
|
21
|
+
|
|
22
|
+
# Supported languages: ko, en, zh, ja
|
|
23
|
+
|
|
24
|
+
# patterns 목록은 기본 언어(ko)의 팩을 문서화합니다.
|
|
25
|
+
# 실제 로딩은 Glob patterns/{lang}-*.md로 자동 탐색합니다.
|
|
26
|
+
# 특정 팩을 제외하려면 skip-patterns를 사용하세요.
|
|
27
|
+
patterns:
|
|
28
|
+
- ko-structure
|
|
29
|
+
- ko-content
|
|
30
|
+
- ko-language
|
|
31
|
+
- ko-style
|
|
32
|
+
- ko-communication
|
|
33
|
+
- ko-filler
|
|
34
|
+
- ko-viral-hook # score-only — detection without rewrite
|
|
35
|
+
|
|
36
|
+
# English packs (auto-discovered when language: en):
|
|
37
|
+
# - en-structure (5 patterns: #25-28, #30)
|
|
38
|
+
# - en-content
|
|
39
|
+
# - en-language
|
|
40
|
+
# - en-style
|
|
41
|
+
# - en-communication
|
|
42
|
+
# - en-filler (4 patterns: #22-24, #31)
|
|
43
|
+
|
|
44
|
+
# Chinese packs (auto-discovered when language: zh):
|
|
45
|
+
# - zh-structure (5 patterns: #25-28, #30)
|
|
46
|
+
# - zh-content
|
|
47
|
+
# - zh-language
|
|
48
|
+
# - zh-style
|
|
49
|
+
# - zh-communication
|
|
50
|
+
# - zh-filler (4 patterns: #22-24, #31)
|
|
51
|
+
|
|
52
|
+
# Japanese packs (auto-discovered when language: ja):
|
|
53
|
+
# - ja-structure (5 patterns: #25-28, #30)
|
|
54
|
+
# - ja-content
|
|
55
|
+
# - ja-language
|
|
56
|
+
# - ja-style
|
|
57
|
+
# - ja-communication
|
|
58
|
+
# - ja-filler (4 patterns: #22-24, #31)
|
|
59
|
+
|
|
60
|
+
skip-patterns: [] # additive merge across default/global/project configs
|
|
61
|
+
blocklist: [] # additive merge: 추가로 감지할 어휘
|
|
62
|
+
allowlist: [] # additive merge: 감지에서 제외할 어휘
|
|
63
|
+
# Other arrays (for example max-models) are replaced by the higher-precedence
|
|
64
|
+
# config so users can intentionally choose an exact provider list.
|
|
65
|
+
|
|
66
|
+
# MAX mode: multi-model humanization
|
|
67
|
+
# claude uses `claude -p`, gemini uses `gemini -p '' --output-format text`,
|
|
68
|
+
# codex uses `codex exec --skip-git-repo-check --output-last-message <file>`
|
|
69
|
+
# Supported models: claude, codex, gemini
|
|
70
|
+
# Override with CLI: --models claude,gemini,codex
|
|
71
|
+
max-models:
|
|
72
|
+
- claude
|
|
73
|
+
- gemini
|
|
74
|
+
|
|
75
|
+
# Dispatch mode for MAX mode CLI execution
|
|
76
|
+
# omc: tmux pane parallel dispatch (recommended, requires oh-my-claudecode + tmux)
|
|
77
|
+
# - Uses a unique temp dir per run
|
|
78
|
+
# - Waits only for selected models and marks timed-out runs as failed
|
|
79
|
+
# - All providers receive the prompt via stdin
|
|
80
|
+
# direct: sequential stdin dispatch (fallback; apply the same per-model timeout)
|
|
81
|
+
# api: HTTP API dispatch (no local CLI needed; requires PATINA_API_KEY env var)
|
|
82
|
+
# - Uses OpenAI-compatible chat completions endpoint
|
|
83
|
+
# - Works with Anthropic, OpenAI, Google AI Studio, OpenRouter, etc.
|
|
84
|
+
# - Requires curl and jq
|
|
85
|
+
# - Model IDs configurable via PATINA_MODEL_* env vars
|
|
86
|
+
dispatch: omc
|
|
87
|
+
|
|
88
|
+
# Scoring: LLM score remains canonical, with a deterministic shadow score
|
|
89
|
+
# from src/features/* for reproducible drift checks.
|
|
90
|
+
scoring:
|
|
91
|
+
deterministic:
|
|
92
|
+
enabled: true
|
|
93
|
+
divergence-threshold: 20 # warn and prefer the more pessimistic score above this delta
|
|
94
|
+
combined-weight: 0 # default off for combinedScore; users may opt in (e.g. 0.2)
|
|
95
|
+
|
|
96
|
+
# Ouroboros: iterative self-improvement loop
|
|
97
|
+
# Runs the full humanization pipeline repeatedly until the AI score converges.
|
|
98
|
+
# Enable via config or CLI flag: --ouroboros
|
|
99
|
+
ouroboros:
|
|
100
|
+
enabled: false # opt-in; --ouroboros CLI flag overrides to true
|
|
101
|
+
target-score: 30 # stop when overall score <= this value (0-100)
|
|
102
|
+
max-iterations: 3 # hard limit on loop iterations
|
|
103
|
+
plateau-threshold: 10 # stop if score improves by less than this between iterations
|
|
104
|
+
category-weights:
|
|
105
|
+
ko:
|
|
106
|
+
content: 0.18
|
|
107
|
+
language: 0.18
|
|
108
|
+
style: 0.18
|
|
109
|
+
communication: 0.13
|
|
110
|
+
filler: 0.08
|
|
111
|
+
structure: 0.15
|
|
112
|
+
viral-hook: 0.10 # score-only pack (excluded from rewrite)
|
|
113
|
+
en:
|
|
114
|
+
content: 0.20
|
|
115
|
+
language: 0.20
|
|
116
|
+
style: 0.20
|
|
117
|
+
communication: 0.12
|
|
118
|
+
filler: 0.08
|
|
119
|
+
structure: 0.10
|
|
120
|
+
viral-hook: 0.10 # score-only pack (excluded from rewrite)
|
|
121
|
+
zh:
|
|
122
|
+
content: 0.18
|
|
123
|
+
language: 0.18
|
|
124
|
+
style: 0.18
|
|
125
|
+
communication: 0.13
|
|
126
|
+
filler: 0.08
|
|
127
|
+
structure: 0.15
|
|
128
|
+
viral-hook: 0.10 # score-only pack (excluded from rewrite)
|
|
129
|
+
ja:
|
|
130
|
+
content: 0.18
|
|
131
|
+
language: 0.18
|
|
132
|
+
style: 0.18
|
|
133
|
+
communication: 0.13
|
|
134
|
+
filler: 0.08
|
|
135
|
+
structure: 0.15
|
|
136
|
+
viral-hook: 0.10 # score-only pack (excluded from rewrite)
|
|
137
|
+
fidelity-floor: 70 # stop ouroboros if fidelity drops below this
|
|
138
|
+
mps-floor: 70 # stop ouroboros if MPS (meaning preservation) drops below this
|
|
139
|
+
combined-weights:
|
|
140
|
+
default:
|
|
141
|
+
ai-likeness: 0.60
|
|
142
|
+
fidelity: 0.40
|
|
143
|
+
academic:
|
|
144
|
+
ai-likeness: 0.40
|
|
145
|
+
fidelity: 0.60
|
|
146
|
+
blog:
|
|
147
|
+
ai-likeness: 0.70
|
|
148
|
+
fidelity: 0.30
|
|
149
|
+
technical:
|
|
150
|
+
ai-likeness: 0.35
|
|
151
|
+
fidelity: 0.65
|
|
152
|
+
social:
|
|
153
|
+
ai-likeness: 0.75
|
|
154
|
+
fidelity: 0.25
|
|
155
|
+
email:
|
|
156
|
+
ai-likeness: 0.50
|
|
157
|
+
fidelity: 0.50
|
|
158
|
+
legal:
|
|
159
|
+
ai-likeness: 0.35
|
|
160
|
+
fidelity: 0.65
|
|
161
|
+
medical:
|
|
162
|
+
ai-likeness: 0.35
|
|
163
|
+
fidelity: 0.65
|
|
164
|
+
marketing:
|
|
165
|
+
ai-likeness: 0.65
|
|
166
|
+
fidelity: 0.35
|
|
167
|
+
severity-points:
|
|
168
|
+
high: 3
|
|
169
|
+
medium: 2
|
|
170
|
+
low: 1
|
|
171
|
+
|
|
172
|
+
# Stylometry: deterministic statistical preprocessing (SKILL.md Step 4.6)
|
|
173
|
+
# Calculates burstiness (sentence-length CV) and MATTR (lexical diversity) per
|
|
174
|
+
# paragraph, marks suspect zones, and feeds them into 5a/5b as internal memory.
|
|
175
|
+
# See core/stylometry.md for the full algorithm reference.
|
|
176
|
+
stylometry:
|
|
177
|
+
enabled: true # set false to bypass 4.6단계 entirely
|
|
178
|
+
languages: [ko, en, zh, ja] # zh/ja use deterministic character-token fallback
|
|
179
|
+
burstiness:
|
|
180
|
+
bands:
|
|
181
|
+
low: 0.30 # CV < 0.30 → low (suspect). Calibrated v3.5.1 from
|
|
182
|
+
# 0.25 against 300 external paragraphs (HC3 + Wikipedia).
|
|
183
|
+
high: 0.50 # CV > 0.50 → high
|
|
184
|
+
ttr:
|
|
185
|
+
window: 50 # MATTR window in tokens
|
|
186
|
+
bands:
|
|
187
|
+
low: 0.55 # MATTR < 0.55 → low (suspect)
|
|
188
|
+
high: 0.70 # MATTR > 0.70 → high
|
|
189
|
+
sentence_zoom:
|
|
190
|
+
similarity_threshold: 0.20 # adjacent sentences within ±20% token count → grouped as sub-flag
|
|
191
|
+
skip:
|
|
192
|
+
min_paragraphs: 2
|
|
193
|
+
min_sentences: 2
|
|
194
|
+
|
|
195
|
+
# AI-Lexicon Overlap (SKILL.md Step 4.7)
|
|
196
|
+
# Matches paragraphs against an AI-favored phrase dictionary not covered
|
|
197
|
+
# by the 28-pattern catalog. Computes density per 1000 tokens; high
|
|
198
|
+
# density paragraphs are flagged SUSPECT under the 3-signal OR rule
|
|
199
|
+
# (burstiness OR MATTR OR lexicon_density).
|
|
200
|
+
# See core/stylometry.md §16 for the full algorithm.
|
|
201
|
+
lexicon:
|
|
202
|
+
enabled: true
|
|
203
|
+
languages: [en, ko] # zh/ja deferred (no curated lexicon yet)
|
|
204
|
+
density_threshold: 2.0 # matches per 1000 tokens; > threshold → SUSPECT
|
|
205
|
+
# Lexicon files auto-discovered via Glob lexicon/ai-{lang}.md
|
|
206
|
+
# See lexicon/ai-en.md (108 entries) and lexicon/ai-ko.md (90 entries).
|
|
207
|
+
# Calibrated against 400 paragraphs (HC3 + Wikipedia + NamuWiki):
|
|
208
|
+
# AI catch 66% → 76% with Wikipedia FP staying at 25% boundary.
|
|
209
|
+
skip:
|
|
210
|
+
min_paragraphs: 2
|
|
211
|
+
min_sentences: 2
|
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to patina. Dates are release dates (YYYY-MM-DD).
|
|
4
|
+
|
|
5
|
+
## Release entry template
|
|
6
|
+
|
|
7
|
+
```md
|
|
8
|
+
## X.Y.Z — YYYY-MM-DD
|
|
9
|
+
|
|
10
|
+
**Short release title.**
|
|
11
|
+
|
|
12
|
+
Semver rationale: patch | minor | major — explain whether this changes patterns, schemas, CLI behavior, or docs only.
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## 3.11.0 — 2026-05-20
|
|
16
|
+
|
|
17
|
+
**Launch-readiness polish for trust, benchmarks, and distribution.**
|
|
18
|
+
|
|
19
|
+
Semver rationale: minor — adds CI/release/distribution surfaces and documentation, while preserving the core rewrite pipeline and existing CLI behavior.
|
|
20
|
+
|
|
21
|
+
### New
|
|
22
|
+
|
|
23
|
+
- Prepared npm release metadata for `patina-cli` plus the `patina-humanizer` alias package.
|
|
24
|
+
- Added a release workflow for npm provenance publishing and GHCR image publishing.
|
|
25
|
+
- Added deterministic GitHub Action and pre-commit scoring surfaces for Markdown review.
|
|
26
|
+
- Added Dockerfile-based container runtime for API-backed CLI use.
|
|
27
|
+
|
|
28
|
+
### Quality
|
|
29
|
+
|
|
30
|
+
- Added release metadata checks so package/config/skill/changelog versions stay synchronized.
|
|
31
|
+
- Added deterministic prose-score tests and pre-commit E2E coverage.
|
|
32
|
+
- Expanded the deterministic suspect-zone benchmark to ko/en/zh/ja with checked-in per-fixture metric ranges.
|
|
33
|
+
- Added an offline detector-comparison harness and 2025+ re-baseline plan for future benchmark evidence.
|
|
34
|
+
|
|
35
|
+
## 3.10.0 — 2026-05-06
|
|
36
|
+
|
|
37
|
+
**Tone categorization v1 (6 tones + `auto`).**
|
|
38
|
+
|
|
39
|
+
A first-class `tone` axis sits on top of profiles, giving users an explicit
|
|
40
|
+
voice category without having to memorize the profile catalog. Tone resolution
|
|
41
|
+
is `--tone` CLI > `tone:` config > `profile:` config; absence of any tone keeps
|
|
42
|
+
v3.9.0 behavior intact (regression-safe profile-only path).
|
|
43
|
+
|
|
44
|
+
### New
|
|
45
|
+
|
|
46
|
+
- **`--tone <name>` flag and `tone:` config field.** Six v1 tones plus `auto`:
|
|
47
|
+
`casual`, `professional`, `academic`, `narrative`, `marketing`,
|
|
48
|
+
`instructional`. Unknown values fail fast with the valid list.
|
|
49
|
+
- **Two new profile backbones:** `profiles/narrative.md` and
|
|
50
|
+
`profiles/instructional.md` (ko + en sections each). zh/ja sections are
|
|
51
|
+
intentionally omitted for v1.
|
|
52
|
+
- **Phase 4.5b heuristic auto-detection.** When `--tone auto`, deterministic
|
|
53
|
+
lexical and structural signals select a single tone with `tone_evidence`
|
|
54
|
+
(1–3 strings) and `tone_confidence` (`low`/`medium`/`high`). No fallback on
|
|
55
|
+
low confidence — always commits to a single tone (A5).
|
|
56
|
+
- **Phase 5b tone override layer.** Resolved tone applies a per-tone override
|
|
57
|
+
pack on top of profile overrides. **Tone overrides replace profile overrides
|
|
58
|
+
on conflict; they do not stack** (idempotent application).
|
|
59
|
+
- **Phase 6 YAML footer.** Every output mode (`rewrite`, `diff`, `audit`,
|
|
60
|
+
`score`) emits a trailing footer block:
|
|
61
|
+
```
|
|
62
|
+
---
|
|
63
|
+
tone: <resolved | null>
|
|
64
|
+
tone_source: user | auto | unsupported_language_fallback | profile_only | skipped_short_input
|
|
65
|
+
tone_evidence: [...]
|
|
66
|
+
tone_confidence: low | medium | high | null
|
|
67
|
+
---
|
|
68
|
+
```
|
|
69
|
+
Body text in `rewrite` mode contains zero tone metadata leakage.
|
|
70
|
+
- **12 fixture pairs** under `examples/tones/` (6 tones × ko/en) showing the
|
|
71
|
+
documented behavioral direction per tone.
|
|
72
|
+
|
|
73
|
+
### Behavior
|
|
74
|
+
|
|
75
|
+
- **zh/ja with any `--tone` (including `auto`)** emits a warning to stderr
|
|
76
|
+
and the YAML footer (`tone_source: unsupported_language_fallback`), then
|
|
77
|
+
continues in profile-only mode. Phase 4.5b heuristics only cover ko/en
|
|
78
|
+
signals, so `auto` on zh/ja would silently degrade to residual
|
|
79
|
+
`professional` without useful evidence — the fallback is intentional.
|
|
80
|
+
- **legal/medical fidelity preserved within `professional` tone.** When the
|
|
81
|
+
active profile is `legal` or `medical`, `combined-weights.{legal|medical}`
|
|
82
|
+
(fidelity 0.65) is forced regardless of tone resolution. Tone overrides
|
|
83
|
+
cannot lower the fidelity floor (R2).
|
|
84
|
+
- **Short-input bypass.** Texts with `<2 paragraphs OR <2 sentences` skip
|
|
85
|
+
Phase 4.5b detection entirely and emit `tone_source: skipped_short_input`
|
|
86
|
+
with `tone_evidence: ["input too short"]`. This is distinct from the
|
|
87
|
+
residual-default path (auto detection ran but no signal cluster reached
|
|
88
|
+
threshold), which keeps `tone_source: auto`.
|
|
89
|
+
|
|
90
|
+
### Quality
|
|
91
|
+
|
|
92
|
+
- **`hasToneFooter()` validates all 4 keys.** Detection now requires `tone`,
|
|
93
|
+
`tone_source`, `tone_evidence`, and `tone_confidence` to be present in the
|
|
94
|
+
fenced block. Partial model-emitted footers no longer suppress the CLI
|
|
95
|
+
authoritative footer.
|
|
96
|
+
- **`resolveTone()` validates `cliTone` input.** Both CLI and config tone
|
|
97
|
+
values are now validated against the allowed tone list, ensuring fail-fast
|
|
98
|
+
behavior regardless of caller.
|
|
99
|
+
- **17 tone unit tests** covering `resolveTone()` priority chain, edge cases
|
|
100
|
+
(empty config, zh/ja fallback, invalid values), backbone profile mapping,
|
|
101
|
+
and `formatOutput` footer emission/deduplication.
|
|
102
|
+
|
|
103
|
+
### CLI wiring (standalone Node CLI)
|
|
104
|
+
|
|
105
|
+
The standalone `src/cli.js` CLI threads `--tone` through `src/config.js`
|
|
106
|
+
(`resolveTone()`), `src/loader.js` (`toneToBackboneProfile()`),
|
|
107
|
+
`src/prompt-builder.js` (tone context block), and `src/output.js`
|
|
108
|
+
(YAML footer emission for all 4 modes). `--tone bogus` fails fast with the
|
|
109
|
+
valid list. CLI > config > unset priority is preserved. Profile-only
|
|
110
|
+
invocations (`patina --profile blog input.md`, no `--tone` and no `tone:`
|
|
111
|
+
config) behave identically to v3.9.0 except for the appended YAML footer.
|
|
112
|
+
|
|
113
|
+
## 3.9.0 — 2026-05-05
|
|
114
|
+
|
|
115
|
+
**Standalone CLI security hardening (issues #88, #89, #90).**
|
|
116
|
+
|
|
117
|
+
Three boundary-validation fixes for the standalone `patina` CLI. None of them
|
|
118
|
+
affect the `/patina` skill flow inside Claude Code / Codex CLI / Cursor /
|
|
119
|
+
OpenCode (the skill runs prompts, not the Node CLI), but anyone running
|
|
120
|
+
`patina` from a shell — especially against untrusted input text — should
|
|
121
|
+
upgrade.
|
|
122
|
+
|
|
123
|
+
### Breaking change
|
|
124
|
+
|
|
125
|
+
- **codex-cli auto-fallback removed.** Previously, when no API key was set
|
|
126
|
+
and `codex` was installed and authenticated, patina silently used the
|
|
127
|
+
codex-cli backend. This sent the user's input to a coding agent, where
|
|
128
|
+
prompt injection in the document body could ask the agent to inspect or
|
|
129
|
+
modify files. The auto-fallback is now removed; codex-cli requires
|
|
130
|
+
explicit `--backend codex-cli` (or `--model codex…`). The error message
|
|
131
|
+
when no API key is found suggests this opt-in.
|
|
132
|
+
|
|
133
|
+
### Hardening
|
|
134
|
+
|
|
135
|
+
- **Profile name validation** (`src/security.js`, `src/loader.js`). `--profile`
|
|
136
|
+
values and the `profile:` field in `.patina.yaml` must now match
|
|
137
|
+
`/^[A-Za-z0-9_][A-Za-z0-9_-]*$/`. This blocks `../../README` and similar
|
|
138
|
+
path-traversal reads that would have leaked unrelated `.md` files into the
|
|
139
|
+
LLM prompt.
|
|
140
|
+
- **Base URL validation** (`src/api.js`, `src/security.js`). Plaintext
|
|
141
|
+
`http://` is rejected for non-loopback hosts by default. Loopback (`127.*`,
|
|
142
|
+
`localhost`, `::1`) is still allowed for tests and local mocks. Override
|
|
143
|
+
with `--allow-insecure-base-url` or `PATINA_ALLOW_INSECURE_BASE_URL=1` for
|
|
144
|
+
trusted private endpoints. `https://` works as before.
|
|
145
|
+
- **Codex sandbox** (`src/backends/codex-cli.js`). When `--backend codex-cli`
|
|
146
|
+
is used, codex now runs with `--sandbox read-only` from a fresh tempdir
|
|
147
|
+
cwd (`-C <tmpdir>`), so a prompt-injected agent cannot reach the caller's
|
|
148
|
+
repo or write outside the temp dir.
|
|
149
|
+
|
|
150
|
+
### Migration
|
|
151
|
+
|
|
152
|
+
If you depended on the silent codex-cli auto-fallback, add `--backend
|
|
153
|
+
codex-cli` to your invocation, or set `PATINA_API_KEY` / `--provider`. Run
|
|
154
|
+
`patina auth status` to see backend availability and how to authenticate.
|
|
155
|
+
|
|
156
|
+
## 3.8.0 — 2026-05-04
|
|
157
|
+
|
|
158
|
+
**Korean lexicon re-curation via differential-frequency mining.**
|
|
159
|
+
|
|
160
|
+
v3.7.0's Korean lexicon was author-curated and contributed only +1pp on AI catch in our paired ko/AI corpus (vs +10pp on English). v3.8.0 mines the corpus for high-signal Korean phrases via differential frequency against NamuWiki human prose, surfacing 12 register markers AI text uses heavily but humans rarely.
|
|
161
|
+
|
|
162
|
+
Mining rule (`.omc/research/v3_8_ko_lexicon_mine.py`):
|
|
163
|
+
- 어절 doc-frequency: AI count ≥ 4 AND ratio AI / (human + 1) ≥ 4.0
|
|
164
|
+
- Reject domain artifacts (proper nouns, year-tokens)
|
|
165
|
+
- Keep only register markers (passive evaluation, encyclopedic verbs, quantifier scaffolding)
|
|
166
|
+
|
|
167
|
+
Added entries (`lexicon/ai-ko.md`, 90 → 102 entries):
|
|
168
|
+
- Strict (8): `평가된다`, `꼽힌다`, `가리킨다`, `사례로`, `다수의`, `알려져`, `일컬어진다`, `평가받다`
|
|
169
|
+
- Phrases (4): `가운데 하나로`, `자리 잡았다`, `알려져 있다`, `~의 사례로`
|
|
170
|
+
|
|
171
|
+
500-paragraph cross-source result:
|
|
172
|
+
|
|
173
|
+
| Source | v3.7.0 | v3.8.0 | Δ |
|
|
174
|
+
|--------|--------|--------|---|
|
|
175
|
+
| HC3 ChatGPT (en) | 76% | 76% | 0pp |
|
|
176
|
+
| HC3 human (en) | 19% | 19% | 0pp |
|
|
177
|
+
| Wikipedia (en) | 25% | 25% | 0pp |
|
|
178
|
+
| NamuWiki (ko) | 13% | 13% | 0pp |
|
|
179
|
+
| ko/AI corpus | 83% | **91%** | **+8pp** |
|
|
180
|
+
|
|
181
|
+
Clean Pareto improvement: AI catch +8pp on Korean with zero false-positive regression. Korean catch rate is now stronger than English (91% vs 76%).
|
|
182
|
+
|
|
183
|
+
Acceptance gates met: AI recall 91% ≥ 75% · max FP 25% ≤ 25% · ko regression 0pp ≤ +5pp.
|
|
184
|
+
|
|
185
|
+
## 3.7.0 — 2026-05-04
|
|
186
|
+
|
|
187
|
+
**AI-lexicon overlap signal (new step 4.7).**
|
|
188
|
+
|
|
189
|
+
A flat dictionary (`lexicon/ai-en.md` 108 entries, `lexicon/ai-ko.md` 90 entries) flags AI-favored phrases the 28-pattern catalog does not enumerate. Densities are computed per 1000 tokens; the 4.6 hot rule extends to a 3-signal OR (burstiness OR MATTR OR lexicon_density > 2.0).
|
|
190
|
+
|
|
191
|
+
Calibration (`.omc/research/v3_7_lexicon_eval.py` vs 400 paragraphs):
|
|
192
|
+
|
|
193
|
+
| Source | v3.5.1 | v3.7.0 | Δ |
|
|
194
|
+
|--------|--------|--------|---|
|
|
195
|
+
| HC3 ChatGPT (en) | 66% | **76%** | +10pp |
|
|
196
|
+
| HC3 human (en) | 12% | 19% | +7pp |
|
|
197
|
+
| Wikipedia (en) | 23% | 25% | +2pp |
|
|
198
|
+
| NamuWiki (ko) | 11% | 13% | +2pp |
|
|
199
|
+
|
|
200
|
+
All acceptance gates met (AI ≥ 75%, max FP ≤ 25%, NamuWiki regression ≤ +5pp) — first Pareto improvement over the v3.5.1 wall.
|
|
201
|
+
|
|
202
|
+
Drop list (post-eval, see `core/stylometry.md` §16): `intersection`, `principles`, `mindset`, `iterative`, `responsible`, `methodologies`, `redefine`, `accessible`, `equitable`, `one of the most`, `in conjunction with`, `the power of` — fired more on academic prose than on AI text.
|
|
203
|
+
|
|
204
|
+
Skipped v3.6 (n-gram dropped, §15 negative finding).
|
|
205
|
+
|
|
206
|
+
## 3.5.1 — 2026
|
|
207
|
+
|
|
208
|
+
**Stylometric calibration patch.**
|
|
209
|
+
|
|
210
|
+
Raised `stylometry.burstiness.bands.low` from 0.25 to 0.30 after external validation against 300 paragraphs (HC3 ChatGPT 100 + HC3 human 100 + Wikipedia 100). v3.5.0 caught 57% of real AI text; v3.5.1 catches 66% with HC3 human FP 12% and Wikipedia FP 23%.
|
|
211
|
+
|
|
212
|
+
Sweep showed no threshold combo satisfies both AI ≥ 70% and max FP ≤ 20% — Wikipedia's encyclopedic register naturally has uniform sentence length. MATTR threshold unchanged (0.55). v3.5.x is an advisory marker for the LLM, not a sole-decision gate. Calibration evidence in `core/stylometry.md` §13.
|
|
213
|
+
|
|
214
|
+
## 3.5.0 — 2026
|
|
215
|
+
|
|
216
|
+
**Stylometric Suspect Zone Detection.**
|
|
217
|
+
|
|
218
|
+
New step 4.6 inserted between anchor extraction and the pattern phases. Deterministic burstiness (sentence-length CV) and MATTR (window=50) signals flag suspect paragraphs the 28-pattern catalog misses. Languages: ko + en in v1; zh + ja deferred to v2 roadmap. LLM receives a `<suspect-zones>` meta block plus `«P{n} SUSPECT»` paragraph prefixes as internal working memory. New file: `core/stylometry.md`.
|
|
219
|
+
|
|
220
|
+
## 3.4.0 — 2026
|
|
221
|
+
|
|
222
|
+
**Free-tier ergonomics + 4 new patterns.**
|
|
223
|
+
|
|
224
|
+
- New `codex-cli` backend (no API key — uses local `codex` CLI's ChatGPT OAuth)
|
|
225
|
+
- `patina auth status` / `patina auth login` subcommands with auto-fallback when no API key is set
|
|
226
|
+
- `--provider` shortcuts for Gemini / Groq / Together AI free tiers
|
|
227
|
+
- Pattern additions: #30 (rhetorical question openers) and #31 (conclusion signal words) across all 4 languages, plus #32 (comparative adverb overuse) for KO `보다` and JA `より`
|
|
228
|
+
- Default profile expanded to match other profiles' structure
|
|
229
|
+
- GitHub Actions CI workflow added
|
|
230
|
+
|
|
231
|
+
## 3.3.0
|
|
232
|
+
|
|
233
|
+
**Meaning Preservation System (MPS).** Ensures humanized text maintains original intent and claims. Semantic anchors (claims, polarity, causation, numbers) are extracted before rewriting and verified after each phase.
|
|
234
|
+
|
|
235
|
+
## 3.2.0
|
|
236
|
+
|
|
237
|
+
**Ouroboros scoring system.** Pattern-based AI-likeness scoring (0-100), `--score` mode with category breakdown, `--ouroboros` iterative self-improvement loop with configurable termination (target/plateau/regression/max-iterations).
|
|
238
|
+
|
|
239
|
+
## 3.1.1
|
|
240
|
+
|
|
241
|
+
**MAX mode reliability fixes.** Per-run temp directory, model-scoped wait loop + timeout handling, Gemini stdin dispatch, Codex CLI compatibility (`--output-last-message`, no `-q`).
|
|
242
|
+
|
|
243
|
+
## 3.1.0
|
|
244
|
+
|
|
245
|
+
**MAX mode.** Installable `/patina-max` skill entrypoint + provider-aware dispatch (`claude -p` / `gemini -p` for Claude/Gemini, `codex exec` for Codex).
|
|
246
|
+
|
|
247
|
+
## 3.0.0
|
|
248
|
+
|
|
249
|
+
**Multi-language framework.** `--lang` flag, English patterns (24) from blader/humanizer, skill renamed to `patina`.
|
|
250
|
+
|
|
251
|
+
## 2.2.0
|
|
252
|
+
|
|
253
|
+
Loanword overuse pattern (#28), badges, repo rename.
|
|
254
|
+
|
|
255
|
+
## 2.1.0
|
|
256
|
+
|
|
257
|
+
2-Phase pipeline, structure patterns, blog profile, examples.
|
|
258
|
+
|
|
259
|
+
## 2.0.0
|
|
260
|
+
|
|
261
|
+
Plugin architecture: pattern packs, profiles, config.
|
|
262
|
+
|
|
263
|
+
## 1.0.0
|
|
264
|
+
|
|
265
|
+
Initial Korean adaptation (24 patterns).
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 devswha
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|