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
package/docs/PATTERNS.md
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# Pattern Catalog
|
|
2
|
+
|
|
3
|
+
Patina ships 160 pattern entries across four languages. The language-specific references below expand each pack with pattern numbers, names, watch words, fire conditions, source links, and examples.
|
|
4
|
+
|
|
5
|
+
| Language | Reference | Rewrite-capable patterns | Score/audit-only viral-hook patterns |
|
|
6
|
+
|----------|-----------|--------------------------|--------------------------------------|
|
|
7
|
+
| Korean | [PATTERNS-KO.md](PATTERNS-KO.md) | 32 | 8 |
|
|
8
|
+
| English | [PATTERNS-EN.md](PATTERNS-EN.md) | 32 | 8 |
|
|
9
|
+
| Chinese | [PATTERNS-ZH.md](PATTERNS-ZH.md) | 32 | 8 |
|
|
10
|
+
| Japanese | [PATTERNS-JA.md](PATTERNS-JA.md) | 32 | 8 |
|
|
11
|
+
|
|
12
|
+
## Notes
|
|
13
|
+
|
|
14
|
+
- Rewrite-capable patterns are applied by `--rewrite`, `--diff`, and `--ouroboros` according to their pack metadata and runtime mode.
|
|
15
|
+
- Viral-hook patterns are score/audit-only SNS-marketing signals. They affect `--score` and `--audit`, but rewrite modes skip them because the rhetoric may be intentional.
|
|
16
|
+
- Pattern packs are auto-discovered from `patterns/{lang}-*.md`. To add a language or custom pack, follow [CONTRIBUTING.md](../CONTRIBUTING.md) and the frontmatter format used in the existing packs.
|
|
17
|
+
|
|
18
|
+
## Supporting References
|
|
19
|
+
|
|
20
|
+
- [Scoring](../core/scoring.md) — category weights, AI-likeness score, fidelity, and MPS
|
|
21
|
+
- [Stylometry](../core/stylometry.md) — burstiness, MATTR, and AI-lexicon overlap
|
|
22
|
+
- [Examples](../examples/README.md) — standalone failure/success fixtures used by the pattern docs
|
package/docs/ROADMAP.md
ADDED
|
@@ -0,0 +1,315 @@
|
|
|
1
|
+
# patina Roadmap
|
|
2
|
+
|
|
3
|
+
patina's goal is not to accuse authors or prove provenance. It is to make AI-assisted writing sound less packaged while preserving meaning.
|
|
4
|
+
|
|
5
|
+
This roadmap focuses on two things:
|
|
6
|
+
|
|
7
|
+
1. make the tool measurably better;
|
|
8
|
+
2. make the project easier to trust, try, cite, and contribute to.
|
|
9
|
+
|
|
10
|
+
## Current baseline
|
|
11
|
+
|
|
12
|
+
- GitHub: `devswha/patina`
|
|
13
|
+
- Public scope: Korean, English, Chinese, Japanese AI-writing pattern rewriting
|
|
14
|
+
- Current benchmark layer:
|
|
15
|
+
- deterministic stylometry/lexicon benchmark: `npm run benchmark`
|
|
16
|
+
- Current public calibration claim:
|
|
17
|
+
- Korean editing-hotspot recall: 91% [84.0-95.4%], n=100
|
|
18
|
+
- English HC3 editing-hotspot recall: 76% [66.7-83.3%], n=100
|
|
19
|
+
- human false positives: 13-25% point-estimate range across registers
|
|
20
|
+
- Current distribution gap:
|
|
21
|
+
- package name `patina-cli` is not published on npm as of 2026-05-20
|
|
22
|
+
|
|
23
|
+
## 0. Positioning principles
|
|
24
|
+
|
|
25
|
+
### What patina is
|
|
26
|
+
|
|
27
|
+
- An auditable AI-writing-pattern humanizer
|
|
28
|
+
- A multilingual pattern catalog for AI-sounding prose
|
|
29
|
+
- A meaning-preserving rewrite workflow
|
|
30
|
+
- A benchmarked quality layer for humanization, not authorship accusation
|
|
31
|
+
|
|
32
|
+
### What patina is not
|
|
33
|
+
|
|
34
|
+
- A disciplinary AI detector
|
|
35
|
+
- A provenance proof system
|
|
36
|
+
- A promise that a text was or was not written by AI
|
|
37
|
+
- A detector-bypass product for academic or professional dishonesty
|
|
38
|
+
|
|
39
|
+
Public copy should prefer terms like:
|
|
40
|
+
|
|
41
|
+
- AI-likeness
|
|
42
|
+
- AI-like writing signals
|
|
43
|
+
- suspect zones
|
|
44
|
+
- meaning preservation
|
|
45
|
+
- humanization gain
|
|
46
|
+
|
|
47
|
+
Avoid overclaiming:
|
|
48
|
+
|
|
49
|
+
- AI probability
|
|
50
|
+
- written by AI
|
|
51
|
+
- guaranteed undetectable
|
|
52
|
+
- bypass detector
|
|
53
|
+
|
|
54
|
+
## 1. Quality roadmap
|
|
55
|
+
|
|
56
|
+
### Phase 1 — benchmark credibility
|
|
57
|
+
|
|
58
|
+
Goal: make claims easier to verify and harder to dismiss.
|
|
59
|
+
|
|
60
|
+
- Publish a short benchmark report generated from `tests/quality/results.json`.
|
|
61
|
+
- Add ROC-AUC / PR-AUC and threshold sweep to the deterministic benchmark.
|
|
62
|
+
- Split reports by language, class, and register.
|
|
63
|
+
- Add a visible warning that scores measure AI-likeness, not authorship.
|
|
64
|
+
- Link [`docs/research/ai-human-metrics.md`](research/ai-human-metrics.md) from README.
|
|
65
|
+
|
|
66
|
+
Acceptance criteria:
|
|
67
|
+
|
|
68
|
+
- `npm run benchmark` still passes.
|
|
69
|
+
- Benchmark output includes current binary metrics plus ranked/threshold metrics.
|
|
70
|
+
- README claims are traceable to a specific benchmark report or spec section.
|
|
71
|
+
|
|
72
|
+
### Phase 2 — corpus expansion
|
|
73
|
+
|
|
74
|
+
Goal: reduce synthetic-fixture overfitting.
|
|
75
|
+
|
|
76
|
+
- Add real-world human prose fixtures by register:
|
|
77
|
+
- encyclopedic
|
|
78
|
+
- blog/essay
|
|
79
|
+
- news/reporting
|
|
80
|
+
- academic/technical
|
|
81
|
+
- marketing/social
|
|
82
|
+
- Add generated prose fixtures by model family:
|
|
83
|
+
- GPT
|
|
84
|
+
- Claude
|
|
85
|
+
- Gemini
|
|
86
|
+
- open-weight models where feasible
|
|
87
|
+
- Add edited-AI fixtures:
|
|
88
|
+
- paraphrased
|
|
89
|
+
- translated roundtrip
|
|
90
|
+
- lightly human-edited
|
|
91
|
+
|
|
92
|
+
Acceptance criteria:
|
|
93
|
+
|
|
94
|
+
- At least 100 human + 100 AI paragraphs per primary language before promoting new headline benchmark claims.
|
|
95
|
+
- False positives are reported per register, not only as a single aggregate.
|
|
96
|
+
- Existing headline thresholds remain honest if performance drops.
|
|
97
|
+
|
|
98
|
+
### Phase 3 — deterministic feature expansion
|
|
99
|
+
|
|
100
|
+
Goal: add signals that are not just sentence length or lexicon hits.
|
|
101
|
+
|
|
102
|
+
Candidate features:
|
|
103
|
+
|
|
104
|
+
- function-word divergence
|
|
105
|
+
- punctuation rhythm
|
|
106
|
+
- sentence opener diversity
|
|
107
|
+
- Korean passive/nominalization proxies
|
|
108
|
+
- paragraph shape variation
|
|
109
|
+
|
|
110
|
+
Acceptance criteria:
|
|
111
|
+
|
|
112
|
+
- New features improve recall or precision on expanded corpus.
|
|
113
|
+
- New features do not raise max human false positives beyond the published tolerance.
|
|
114
|
+
- Each feature has before/after examples and a documented failure mode.
|
|
115
|
+
|
|
116
|
+
### Phase 4 — optional LM-probability research
|
|
117
|
+
|
|
118
|
+
Goal: experiment without making the default tool heavy.
|
|
119
|
+
|
|
120
|
+
Candidate tracks:
|
|
121
|
+
|
|
122
|
+
- GLTR-style rank/probability/entropy visualization
|
|
123
|
+
- Binoculars-style cross-perplexity contrast
|
|
124
|
+
- DetectGPT-style curvature experiments
|
|
125
|
+
|
|
126
|
+
Acceptance criteria:
|
|
127
|
+
|
|
128
|
+
- Implemented only as optional research scripts or docs unless they prove lightweight and stable.
|
|
129
|
+
- No default dependency bloat.
|
|
130
|
+
- No user-facing provenance claims.
|
|
131
|
+
|
|
132
|
+
## 2. Product roadmap
|
|
133
|
+
|
|
134
|
+
### Phase 1 — try-it-now experience
|
|
135
|
+
|
|
136
|
+
Goal: reduce the time from landing on README to seeing value.
|
|
137
|
+
|
|
138
|
+
- Maintain the recognizable patina logo / app icon now in `assets/brand/`.
|
|
139
|
+
It should stay dark, faceted, tactile, and simple enough to work at favicon size,
|
|
140
|
+
without copying Obsidian's trade dress.
|
|
141
|
+
- Add an animated terminal demo or short GIF.
|
|
142
|
+
- Add copy-paste sample commands for the 4 most likely users:
|
|
143
|
+
- writer/blogger
|
|
144
|
+
- engineer writing docs
|
|
145
|
+
- Korean marketer/social writer
|
|
146
|
+
- researcher/academic writer
|
|
147
|
+
- Add a `--sample` or documented sample file flow if not already available.
|
|
148
|
+
|
|
149
|
+
Acceptance criteria:
|
|
150
|
+
|
|
151
|
+
- A new user can run one command and see before/after output in under 2 minutes.
|
|
152
|
+
- README demo covers both CLI and skill usage.
|
|
153
|
+
- Logo assets exist in repo-friendly formats (`svg` source plus social preview export) and render clearly on GitHub dark/light backgrounds.
|
|
154
|
+
|
|
155
|
+
### Phase 2 — packaging and distribution
|
|
156
|
+
|
|
157
|
+
Goal: make patina installable from the channels users expect.
|
|
158
|
+
|
|
159
|
+
- Publish npm package if the project is ready for package support.
|
|
160
|
+
- Add signed GitHub releases and changelog highlights.
|
|
161
|
+
- Consider Homebrew only after npm and releases are stable.
|
|
162
|
+
- Add package badges only after packages exist.
|
|
163
|
+
|
|
164
|
+
Acceptance criteria:
|
|
165
|
+
|
|
166
|
+
- Install instructions work from a clean environment.
|
|
167
|
+
- Release artifacts match README claims.
|
|
168
|
+
- Version-bearing files stay synchronized.
|
|
169
|
+
|
|
170
|
+
### Phase 3 — integrations
|
|
171
|
+
|
|
172
|
+
Goal: make patina show up where AI-writing pain happens.
|
|
173
|
+
|
|
174
|
+
- Claude Code / Codex / Cursor / OpenCode install path stays first-class.
|
|
175
|
+
- Add examples for docs cleanup, blog rewrite, and launch-copy cleanup.
|
|
176
|
+
- Consider editor snippets or action recipes after CLI packaging is stable.
|
|
177
|
+
|
|
178
|
+
Acceptance criteria:
|
|
179
|
+
|
|
180
|
+
- Integration docs are tested manually before public launch posts.
|
|
181
|
+
- Each integration has one minimal example and one realistic example.
|
|
182
|
+
|
|
183
|
+
## 3. Community roadmap
|
|
184
|
+
|
|
185
|
+
### Phase 1 — community health basics
|
|
186
|
+
|
|
187
|
+
Goal: make the project safe and easy to contribute to.
|
|
188
|
+
|
|
189
|
+
- Add issue templates:
|
|
190
|
+
- bug report
|
|
191
|
+
- pattern proposal
|
|
192
|
+
- false positive report
|
|
193
|
+
- benchmark/corpus proposal
|
|
194
|
+
- Add PR template.
|
|
195
|
+
- Add `SECURITY.md`.
|
|
196
|
+
- Add `SUPPORT.md`.
|
|
197
|
+
- Add `CODE_OF_CONDUCT.md`.
|
|
198
|
+
|
|
199
|
+
Acceptance criteria:
|
|
200
|
+
|
|
201
|
+
- GitHub community profile is no longer missing basic files.
|
|
202
|
+
- Pattern proposals ask for examples, language, false-positive risk, and expected rewrite.
|
|
203
|
+
|
|
204
|
+
### Phase 2 — contribution flywheel
|
|
205
|
+
|
|
206
|
+
Goal: turn users into pattern contributors.
|
|
207
|
+
|
|
208
|
+
- Label starter issues:
|
|
209
|
+
- `good first issue`
|
|
210
|
+
- `patterns`
|
|
211
|
+
- `benchmark`
|
|
212
|
+
- `docs`
|
|
213
|
+
- Add a “submit a pattern” path from README and FAQ.
|
|
214
|
+
- Publish small “pattern of the week” examples.
|
|
215
|
+
|
|
216
|
+
Acceptance criteria:
|
|
217
|
+
|
|
218
|
+
- A contributor can add a pattern by following docs without asking the maintainer.
|
|
219
|
+
- Pattern PRs include success/failure examples.
|
|
220
|
+
|
|
221
|
+
## 4. Launch roadmap
|
|
222
|
+
|
|
223
|
+
### Pre-launch checklist
|
|
224
|
+
|
|
225
|
+
- README has a crisp one-line promise.
|
|
226
|
+
- Patina logo / icon exists and appears in README/social preview surfaces.
|
|
227
|
+
- Demo GIF or terminal recording exists.
|
|
228
|
+
- Benchmark report is linked.
|
|
229
|
+
- Install path is tested.
|
|
230
|
+
- Issue templates are ready.
|
|
231
|
+
- At least 3 polished real-world examples exist.
|
|
232
|
+
|
|
233
|
+
### Launch surfaces
|
|
234
|
+
|
|
235
|
+
Use one clear story per surface.
|
|
236
|
+
|
|
237
|
+
| Surface | Angle |
|
|
238
|
+
|---|---|
|
|
239
|
+
| Hacker News / Show HN | Auditable AI-writing humanizer with benchmarked meaning preservation |
|
|
240
|
+
| Reddit writing communities | Remove AI packaging without changing your claims |
|
|
241
|
+
| Korean developer/writer communities | Korean-first AI prose cleanup, not just English detector talk |
|
|
242
|
+
| GitHub social/X | Pattern catalog + before/after demos |
|
|
243
|
+
| AI coding communities | Works as Claude Code/Codex/Cursor/OpenCode skill |
|
|
244
|
+
|
|
245
|
+
### Launch rule
|
|
246
|
+
|
|
247
|
+
Do not lead with “bypass AI detectors.” Lead with:
|
|
248
|
+
|
|
249
|
+
> AI-assisted writing often sounds packaged. patina removes that packaging and checks that the meaning survived.
|
|
250
|
+
|
|
251
|
+
## 5. Immediate next actions
|
|
252
|
+
|
|
253
|
+
Last triaged: 2026-05-20, after Wave 1 docs/governance quick wins.
|
|
254
|
+
|
|
255
|
+
Current GitHub issue inventory:
|
|
256
|
+
|
|
257
|
+
- 42 open issues; 100 closed issues; 142 tracked issues total.
|
|
258
|
+
- Open priority split: 2 high, 26 medium, 14 low, and 0 without priority labels.
|
|
259
|
+
- The only open `priority: high` issues are the blocked release-wave items [#203](https://github.com/devswha/patina/issues/203) and [#204](https://github.com/devswha/patina/issues/204).
|
|
260
|
+
|
|
261
|
+
Already done or mostly done:
|
|
262
|
+
|
|
263
|
+
- README links to the roadmap, research notes, benchmark report, detector comparison, demo, launch copy, and community docs.
|
|
264
|
+
- Issue templates, PR template, `SECURITY.md`, `SUPPORT.md`, `CODE_OF_CONDUCT.md`, and `CONTRIBUTING.md` exist.
|
|
265
|
+
- Benchmark report generation exists via `npm run benchmark:report`.
|
|
266
|
+
- Logo, icon, and social preview SVGs live in `assets/brand/` and `assets/social/`.
|
|
267
|
+
- A copy-paste terminal demo lives in [`docs/DEMO.md`](DEMO.md).
|
|
268
|
+
- Launch copy drafts live in [`docs/social/patina-launch-copy.md`](social/patina-launch-copy.md).
|
|
269
|
+
- Main branch protection is enabled. Issue: [#246](https://github.com/devswha/patina/issues/246).
|
|
270
|
+
- MAX warns when every MAX candidate fails `MPS >= 70` and the highest-MPS candidate is selected as fallback. Issue: [#139](https://github.com/devswha/patina/issues/139).
|
|
271
|
+
- Deterministic `callLLM` seams exist across `ouroboros`, `max-mode`, and scoring test paths. Issue: [#130](https://github.com/devswha/patina/issues/130).
|
|
272
|
+
- Localized READMEs have been dogfooded through patina to reduce AI tells. Issue: [#242](https://github.com/devswha/patina/issues/242).
|
|
273
|
+
- zh/ja before-after examples have been backfilled to near parity with ko/en pattern coverage. Issue: [#146](https://github.com/devswha/patina/issues/146).
|
|
274
|
+
- External promotional / solicitation issue policy is documented. Issue: [#245](https://github.com/devswha/patina/issues/245).
|
|
275
|
+
- README hero block is centered. Issue: [#241](https://github.com/devswha/patina/issues/241).
|
|
276
|
+
- Korean companion docs exist for contributing, FAQ, authentication, and examples. Issue: [#202](https://github.com/devswha/patina/issues/202).
|
|
277
|
+
- Priority labels were added for the last unlabeled queue items. Issues: [#99](https://github.com/devswha/patina/issues/99), [#104](https://github.com/devswha/patina/issues/104).
|
|
278
|
+
- Test/backend hardening wave is complete: prompt snapshots, backend contract unification, SIGINT cancellation, structured logging, and progress indicators. Issues: [#169](https://github.com/devswha/patina/issues/169), [#131](https://github.com/devswha/patina/issues/131), [#133](https://github.com/devswha/patina/issues/133), [#132](https://github.com/devswha/patina/issues/132), [#180](https://github.com/devswha/patina/issues/180).
|
|
279
|
+
- Scoring/stylometry quality wave is complete: zh/ja char n-grams, deterministic shadow scoring, manifest v2 observability, response cache, and voice anchors. Issues: [#151](https://github.com/devswha/patina/issues/151), [#136](https://github.com/devswha/patina/issues/136), [#134](https://github.com/devswha/patina/issues/134), [#135](https://github.com/devswha/patina/issues/135), [#137](https://github.com/devswha/patina/issues/137).
|
|
280
|
+
- Pattern/profile wave is complete: zh/ja risk notes, comparison-adverb backport, zh/ja profile overrides, overlap audit, developer-prose profiles, and viral-hook expansion to 8 score-only patterns per language. Issues: [#147](https://github.com/devswha/patina/issues/147), [#148](https://github.com/devswha/patina/issues/148), [#149](https://github.com/devswha/patina/issues/149), [#152](https://github.com/devswha/patina/issues/152), [#153](https://github.com/devswha/patina/issues/153), [#154](https://github.com/devswha/patina/issues/154).
|
|
281
|
+
|
|
282
|
+
Next executable wave order (snapshot: 2026-05-20 after PR #273):
|
|
283
|
+
|
|
284
|
+
### Blocked release wave — keep visible, do not start yet
|
|
285
|
+
|
|
286
|
+
These are the only open high-priority issues. They stay blocked until package ownership, release credentials, versioning, and support policy are settled.
|
|
287
|
+
|
|
288
|
+
1. Settle npm support policy, then publish `patina-cli` / `patina-humanizer` with release workflow. Issue: [#203](https://github.com/devswha/patina/issues/203).
|
|
289
|
+
2. Ship `devswha/patina-action@v1` for PR-comment scoring after the release/versioning path is stable. Issue: [#204](https://github.com/devswha/patina/issues/204).
|
|
290
|
+
|
|
291
|
+
### Wave 1 — medium, executable after release policy is unblocked
|
|
292
|
+
|
|
293
|
+
1. Add zh/ja AI-lexicon files for stylometry overlap detection. Issue: [#104](https://github.com/devswha/patina/issues/104).
|
|
294
|
+
2. Let CLI backends participate in standalone MAX. Issue: [#141](https://github.com/devswha/patina/issues/141).
|
|
295
|
+
3. Reduce MAX prompt weight by opting into a minimal default. Issue: [#143](https://github.com/devswha/patina/issues/143).
|
|
296
|
+
4. Add MAX pane-liveness watchdogs for dead tmux panes. Issue: [#144](https://github.com/devswha/patina/issues/144).
|
|
297
|
+
5. Make `patina auth login <backend>` launch the real login flow. Issue: [#186](https://github.com/devswha/patina/issues/186).
|
|
298
|
+
6. Add JSDoc public exports and publish generated API reference. Issue: [#191](https://github.com/devswha/patina/issues/191).
|
|
299
|
+
7. Tie this roadmap to a GitHub Project board or Milestones. Issue: [#195](https://github.com/devswha/patina/issues/195).
|
|
300
|
+
|
|
301
|
+
### Wave 2 — research calibration, parked unless explicitly scheduled
|
|
302
|
+
|
|
303
|
+
These are medium-priority but research-heavy. Keep them out of the critical path until release blockers and the core quality loop have stable owner time.
|
|
304
|
+
|
|
305
|
+
1. Re-baseline AI catch rate against 2025+ models. Issue: [#155](https://github.com/devswha/patina/issues/155).
|
|
306
|
+
2. Run the lexicon freshness audit with per-entry corpus provenance. Issue: [#160](https://github.com/devswha/patina/issues/160).
|
|
307
|
+
3. Establish quarterly pattern-freshness review with corpus refresh and emerging-pattern triage. Issue: [#165](https://github.com/devswha/patina/issues/165).
|
|
308
|
+
|
|
309
|
+
### Wave 3 — low-priority parked ecosystem and research
|
|
310
|
+
|
|
311
|
+
Do not start these until npm publication, action v1, and medium MAX/auth/docs work have a stable release path:
|
|
312
|
+
|
|
313
|
+
- False-positive and benchmark calibration: [#99](https://github.com/devswha/patina/issues/99), [#156](https://github.com/devswha/patina/issues/156), [#157](https://github.com/devswha/patina/issues/157), [#158](https://github.com/devswha/patina/issues/158), [#159](https://github.com/devswha/patina/issues/159), [#163](https://github.com/devswha/patina/issues/163).
|
|
314
|
+
- Documentation site exploration: [#199](https://github.com/devswha/patina/issues/199).
|
|
315
|
+
- Editor/platform integrations and distribution experiments: [#206](https://github.com/devswha/patina/issues/206), [#207](https://github.com/devswha/patina/issues/207), [#208](https://github.com/devswha/patina/issues/208), [#209](https://github.com/devswha/patina/issues/209), [#210](https://github.com/devswha/patina/issues/210), [#211](https://github.com/devswha/patina/issues/211), [#212](https://github.com/devswha/patina/issues/212).
|
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
# patina 저장소 심층 분석 보고서
|
|
2
|
+
|
|
3
|
+
## 경영진 요약
|
|
4
|
+
|
|
5
|
+
`devswha/patina`는 방향이 분명한 저장소다. 패턴 기반으로 AI 글쓰기 흔적을 탐지하고, 감사 가능한 방식으로 다시 쓰기를 수행하며, 한국어·영어·중국어·일본어에 대해 총 126개 패턴을 운영한다. 공개 문서와 코드 기준으로 보면, 이 도구는 standalone Node CLI이자 entity["company","Anthropic","ai company"] Claude Code·entity["company","OpenAI","ai company"] Codex CLI 계열 워크플로에 연결되는 스킬형 도구로 설계되어 있고, rewrite·audit·score·diff·ouroboros·MAX 실행 경로를 이미 갖추고 있다. 또한 backend와 provider를 분리했고, 패턴 팩·프로필·voice·scoring 문서를 프롬프트에 명시적으로 주입하는 구조라 추적 가능성도 좋다. citeturn18view0turn18view1turn26view6turn15view0turn14view2turn23view13
|
|
6
|
+
|
|
7
|
+
하지만 현재 구현의 가장 큰 병목은 “패턴 기반”이라는 제품 포지셔닝에 비해 실제 판단의 핵심이 LLM 호출에 과도하게 묶여 있다는 점이다. README는 점수식이 deterministic이고 LLM severity assignment만 확률적이라고 설명하지만 동시에 런 간 ±8–10점 변동이 있음을 인정한다. 코드에서도 `scoreText`, `scoreMPS`, `scoreFidelity`가 모두 별도 LLM 판단에 의존하고, JSON 파싱 실패 시 `null` 또는 raw text로 조용히 떨어지며, 온도도 0이 아니라 0.1이다. 결과적으로 정확도, 재현성, 비용, 지연시간이 한 번에 흔들린다. citeturn18view3turn25view4turn25view5turn25view6turn25view7
|
|
8
|
+
|
|
9
|
+
가장 시급한 문제는 두 군데다. 첫째, MAX 모드는 후보를 여러 모델로 생성한 뒤도 평가를 `models[0]` 하나로 다시 수행하며, 원문도 `prompt.split('## Input Text')[1]`로 역추출한다. 둘째, Ouroboros는 `combinedScore`를 계산하지만 실제 중단·rollback 판단은 거의 `currentScore`와 단순 floor 규칙에 의해 결정된다. 즉, 좋은 평가 신호를 계산해 놓고도 제어 로직은 덜 정교한 신호에 매여 있다. citeturn28view1turn28view3turn27view1turn27view5turn13view4
|
|
10
|
+
|
|
11
|
+
우선순위는 명확하다.
|
|
12
|
+
첫째, **평가기 분리와 원문 전달 경로 정리**가 P0다.
|
|
13
|
+
둘째, **구조화 출력과 스키마 검증**이 P0다.
|
|
14
|
+
셋째, **패턴 카탈로그의 데이터화와 selective retrieval**이 P0다.
|
|
15
|
+
넷째, **다국어 로컬 stylometry·lexicon 계층**이 P0다.
|
|
16
|
+
이 네 가지를 먼저 넣으면 정확도와 강건성은 올라가고, 프롬프트 길이와 비용은 내려갈 가능성이 가장 크다. 그 다음 단계로 scoring/MPS/fidelity 재보정, backend hardening, 테스트·벤치마크 체계, 비밀키·CLI UX·재현성 패키지를 붙이는 것이 합리적이다. citeturn26view6turn18view0turn18view4turn25view5turn25view6turn45view0turn45view5
|
|
17
|
+
|
|
18
|
+
## 현재 구조와 관찰된 강점
|
|
19
|
+
|
|
20
|
+
현재 CLI의 메인 실행 경로는 비교적 단순하다. `src/cli.js`는 provider를 선택하고, config를 로드한 뒤, 언어별 패턴 팩과 profile, `core/voice.md`, `core/scoring.md`를 읽어서 단일 프롬프트를 만들고, 그 결과를 일반 rewrite 경로, MAX 경로, Ouroboros 경로 중 하나로 보낸다. backend는 `openai-http`와 `codex-cli` 두 가지이며, provider preset은 openai, gemini, groq, together 네 개를 갖고 있다. 기본 배포는 Node 18 이상, 런타임 의존성은 `js-yaml` 하나뿐이라 구조 자체는 가볍다. citeturn9view6turn15view0turn14view2turn14view6turn44view0turn44view2turn44view3
|
|
21
|
+
|
|
22
|
+
패턴 로딩과 프롬프트 구성도 일관성은 있다. `buildPrompt`는 로드된 각 패턴 팩을 `## Pattern Packs` 아래에 그대로 붙이고, 그 뒤에 profile, voice, scoring algorithm, 모드별 instructions, input text를 이어 붙인다. rewrite 모드는 구조 패턴을 다루는 Phase 1, 어휘·문체 패턴을 다루는 Phase 2, 의미 보존과 polarity inversion 등을 다시 보는 Phase 3 self-audit로 나뉜다. config는 언어별 자동 패턴 팩 발견, `skip-patterns`, `blocklist`, `allowlist`, Ouroboros weight/threshold를 이미 지원한다. citeturn26view6turn26view0turn26view1turn26view2turn23view5turn23view6turn23view7turn23view8turn23view9turn23view10
|
|
23
|
+
|
|
24
|
+
이 구조의 강점은 “감사 가능성”이다. audit 모드는 pattern ID와 name을 정확히 쓰라고 강제하고, category도 로드된 패턴 팩 이름을 그대로 쓰게 한다. 즉, black-box paraphraser가 아니라 “어떤 규칙을 근거로 고쳤는지”를 역추적하기 쉬운 설계다. 또 backend/provider를 분리해 API key가 없을 때 codex-cli로 자동 fallback하는 부분도 실제 사용자 관점에서는 마찰을 줄인다. citeturn26view3turn26view4turn15view0turn45view0
|
|
25
|
+
|
|
26
|
+
```mermaid
|
|
27
|
+
flowchart LR
|
|
28
|
+
A[CLI] --> B[config/pattern/profile/voice load]
|
|
29
|
+
B --> C[buildPrompt]
|
|
30
|
+
C --> D{mode}
|
|
31
|
+
D -->|rewrite| E[backend invoke]
|
|
32
|
+
D -->|MAX| F[multi-model generation]
|
|
33
|
+
D -->|Ouroboros| G[iterative rewrite loop]
|
|
34
|
+
E --> H[output]
|
|
35
|
+
F --> I[LLM scoreText + LLM MPS]
|
|
36
|
+
I --> H
|
|
37
|
+
G --> J[LLM scoreText + LLM MPS + LLM fidelity]
|
|
38
|
+
J --> H
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
다만 이 그림이 보여주듯, 현재 runtime의 “판단” 계층은 거의 전부 LLM 호출 위에 놓여 있다. 따라서 구조적 명료성은 있지만, 판정 안정성은 아직 소프트웨어적으로 충분히 고정되어 있지 않다. 이 점이 이후 개선안의 핵심 전제다. citeturn25view4turn25view5turn25view6turn27view5turn28view1
|
|
42
|
+
|
|
43
|
+
## 차원별 핵심 진단
|
|
44
|
+
|
|
45
|
+
| 차원 | 현재 상태 | 왜 문제인가 |
|
|
46
|
+
| --- | --- | --- |
|
|
47
|
+
| CLI | 현재 공개 help와 파서에는 `--lang`, `--profile`, `--diff`, `--audit`, `--score`, `--ouroboros`, `--batch`, `--in-place`, `--suffix`, `--outdir`, `--models`, `--model`, `--api-key`, `--base-url`, `--backend`, `--provider`가 보이지만, `--config`, `--patterns-dir`, `--profiles-dir`, `--lexicon-dir` 같은 커스텀 경로 플래그는 없다. | 사용자별 패턴/프로필/사전 자산을 붙이는 UX가 약하고, parser가 수동 `switch` 구조라 플래그 추가 때 누락 위험도 크다. citeturn45view0turn45view1turn45view5turn45view6 |
|
|
48
|
+
| prompt-builder | 모든 로드된 패턴 팩 본문을 프롬프트에 그대로 삽입한다. 패턴은 4개 언어 126개이며, 패턴 디렉터리도 언어×카테고리로 전부 분리돼 있다. | 감사성은 높지만 prompt token 비용이 팩 수에 거의 선형으로 늘어난다. 또한 “실제로 필요한 패턴만 골라 읽는” retrieval 계층이 없다. citeturn18view0turn20view0turn26view6 |
|
|
49
|
+
| scoring | `scoreText`는 category weight와 점수식 설명을 프롬프트에 넣고 LLM에게 strict JSON을 요구하지만, 실패하면 `overall: null`로 떨어진다. | 점수화의 핵심이 LLM severity assignment에 의존하고, 포맷 실패가 조용히 삼켜져 강건성이 약하다. README도 런 간 ±8–10점 변동을 인정한다. citeturn25view4turn25view7turn18view3 |
|
|
50
|
+
| MPS/fidelity | MPS는 `(pass_rate×0.6 + polarity_preserved×0.4)×100`이고, fidelity는 claim/no-fabrication/tone + 길이 bucket을 12점 만점으로 환산한다. 길이 bucket은 문자 길이 비율 중심이다. | 의미 보존 판단이 수치·날짜·고유명사·조건절 같은 고위험 anchor를 충분히 분리하지 못할 수 있고, 문자 길이 비율은 CJK나 압축적 문체에서 왜곡되기 쉽다. citeturn25view5turn25view6turn25view7 |
|
|
51
|
+
| combined score | `combinedScore`는 `ai-likeness`와 `100-fidelity`를 가중합으로 계산하며 profile별 weight도 config에 있다. | 계산해 놓고도 현재 제어 로직에서 핵심 decision variable로 쓰이지 않는다. design intent와 runtime control이 어긋나 있다. citeturn13view4turn23view10turn27view5 |
|
|
52
|
+
| MAX orchestration | MAX는 각 후보를 생성한 뒤 `scoreText`와 `scoreMPS`를 모두 `models[0]`으로 재채점하고, MPS 원문은 `prompt.split('## Input Text')[1]`로 뽑는다. | 평가 편향과 파싱 취약성이 동시에 존재한다. 생성 모델이 여러 개인데 평가기가 사실상 하나이며, source text 전달도 brittle하다. citeturn28view1turn28view3 |
|
|
53
|
+
| Ouroboros | Ouroboros는 target score, plateau, fidelity floor, MPS floor, rollback을 갖고 있지만, 중단 판단은 `currentScore`, `delta`, floor 위주다. `combined`는 로그에만 남는다. | iterative refinement를 하면서도 실제 결정은 단순 AI-likeness 중심이라, 의미 보존과 자연스러움 사이 균형을 충분히 활용하지 못한다. citeturn14view8turn27view0turn27view3turn27view5 |
|
|
54
|
+
| multilingual | 패턴 카탈로그는 4개 언어를 지원하지만, README의 stylometric/AI-lexicon 설명은 EN 약 108개, KO 약 102개만 명시한다. | zh/ja에 대해 pattern 지원은 있어도 stylometry/lexicon calibration은 약할 가능성이 높다. 특히 paraphrase·translation·summarization처럼 semantic-invariant 과제는 탐지가 더 어렵다는 외부 연구와도 맞물린다. citeturn18view0turn18view4turn33view1 |
|
|
55
|
+
| testing/CI | `npm test` 엔트리포인트는 현재 `node --test tests/e2e/*.test.js`만 가리킨다. | e2e 중심 smoke는 가능해도, 점수식·파서·패턴 스키마·Unicode edge case를 잡는 unit/property/quality benchmark 층이 약하다. citeturn44view0turn44view1 |
|
|
56
|
+
| security | 공개 help는 `--api-key <key>`와 여러 provider 환경변수를 직접 안내한다. | 명령행 인자는 shell history나 process list에 노출될 수 있어 비밀정보 전달 수단으로 바람직하지 않다. GitHub 문서와 CWE도 command line 전달을 피하라고 권고한다. citeturn45view0turn45view1turn41search1turn41search3 |
|
|
57
|
+
| reproducibility/UX | 현재 help에는 `--json`, `--save-run`, prompt hash, manifest, config hash 같은 실험 기록 옵션이 보이지 않는다. | README가 score variance를 인정하고 있어도 사용자가 어떤 model/provider/pattern set으로 결과가 나왔는지 재현하기 어렵다. 또한 MAX의 model naming과 provider naming 체계가 분리돼 초심자에게 혼동을 줄 수 있다. citeturn18view3turn23view13turn45view0turn45view1 |
|
|
58
|
+
|
|
59
|
+
## 우선순위 개선안
|
|
60
|
+
|
|
61
|
+
### 평가기 분리와 원문 전달 경로 정리
|
|
62
|
+
|
|
63
|
+
**설명**
|
|
64
|
+
현재 MAX는 후보 생성 후 평가를 `models[0]` 하나로 다시 수행하고, 원문은 `prompt.split('## Input Text')[1]`로 되짚어 쓴다. Ouroboros도 rewrite에 사용한 것과 동일한 `model`을 scoring/MPS/fidelity 판단에 재사용한다. 이 구조는 평가 편향, brittle parsing, self-grading 과신을 한꺼번에 만든다. citeturn28view1turn28view3turn27view1
|
|
65
|
+
|
|
66
|
+
**기술 접근**
|
|
67
|
+
`src/cli.js`에서 `sourceText`와 `evaluator` 설정을 `runMaxMode`·`runOuroboros`에 명시적으로 전달하고, `src/max-mode.js`에서는 `prompt.split`을 제거해 원문을 직접 받도록 바꿔야 한다. `src/ouroboros.js`와 `src/scoring.js`에는 생성 모델과 독립적인 evaluator model/provider를 넣고, 가능하면 로컬 feature gate를 먼저 통과한 후보만 evaluator에게 보내는 2단계 구조가 좋다. iterative self-feedback 자체는 Self-Refine와 Reflexion류 연구에서 효과가 있었지만, 외부 검증기 없이 자기비평만 믿는 구조는 신뢰성이 떨어질 수 있다는 반론 연구도 있다. patina는 “외부 검증기 우선, 자기비평 보조”로 설계하는 편이 더 안전하다. citeturn35search0turn34search0turn35search3
|
|
68
|
+
|
|
69
|
+
**수정 파일**
|
|
70
|
+
`src/cli.js`, `src/max-mode.js`, `src/ouroboros.js`, `src/scoring.js`, `.patina.default.yaml`
|
|
71
|
+
|
|
72
|
+
**구현 난이도**
|
|
73
|
+
M
|
|
74
|
+
|
|
75
|
+
**기대 효과**
|
|
76
|
+
정확도 상승, 의미 보존 안정화, MAX 선택 편향 감소, 파싱 취약성 제거
|
|
77
|
+
|
|
78
|
+
**리스크와 트레이드오프**
|
|
79
|
+
평가 모델을 분리하면 비용은 늘 수 있다. 다만 evaluator를 경량 모델이나 로컬 검사와 조합하면 총비용 증가를 통제할 수 있다.
|
|
80
|
+
|
|
81
|
+
**우선순위**
|
|
82
|
+
P0
|
|
83
|
+
|
|
84
|
+
### 구조화 출력과 스키마 검증 계층 도입
|
|
85
|
+
|
|
86
|
+
**설명**
|
|
87
|
+
현재 scoring 계열 함수는 “strict JSON”을 요구하지만 실제로는 자유 텍스트를 받아 `extractJson`으로 잘라낸 뒤 `JSON.parse`하고 실패 시 `null`로 떨어진다. 이는 실패를 조용히 숨기는 방식이라, 운영 환경에서 partial failure를 탐지하기 어렵다. citeturn13view0turn25view4turn25view5turn25view6
|
|
88
|
+
|
|
89
|
+
**기술 접근**
|
|
90
|
+
핵심은 `src/api.js`와 `src/scoring.js`에 schema-first 계층을 넣는 것이다. 지원 모델에는 OpenAI Structured Outputs 스타일의 JSON schema 응답을 사용하고, provider가 이를 완전히 보장하지 못할 때는 `Ajv`로 런타임 검증·coercion·error surface를 통일하면 된다. `Ajv`는 JSON schema를 빠른 JS validator로 컴파일하고 캐시하므로 patina처럼 반복적으로 동일 schema를 쓰는 케이스에 적합하다. malformed output은 `p-retry`로 짧게 재시도하고, 최종 실패는 “점수 없음”으로 삼키지 말고 명시적 오류 타입으로 올려야 한다. OpenAI 문서도 JSON mode보다 Structured Outputs를 권장하고, schema adherence와 refusal detection을 분리해 다루라고 안내한다. citeturn40search0turn40search1turn40search2turn38search4turn38search5turn37search0
|
|
91
|
+
|
|
92
|
+
**수정 파일**
|
|
93
|
+
`src/api.js`, `src/scoring.js`, `src/providers.js`, `src/schemas/score.js`, `src/schemas/mps.js`, `src/schemas/fidelity.js`
|
|
94
|
+
|
|
95
|
+
**구현 난이도**
|
|
96
|
+
M
|
|
97
|
+
|
|
98
|
+
**기대 효과**
|
|
99
|
+
강건성 상승, 포맷 오류 추적 가능, 재현성 개선, 디버깅 시간 감소
|
|
100
|
+
|
|
101
|
+
**리스크와 트레이드오프**
|
|
102
|
+
provider별 structured output 지원 수준이 다르다. 따라서 “provider capability map + Ajv fallback” 이중 구조가 필요하다.
|
|
103
|
+
|
|
104
|
+
**우선순위**
|
|
105
|
+
P0
|
|
106
|
+
|
|
107
|
+
### 패턴 카탈로그를 데이터화하고 selective retrieval로 전환
|
|
108
|
+
|
|
109
|
+
**설명**
|
|
110
|
+
지금 patina의 패턴 카탈로그는 수량과 언어 범위 면에서는 강하다. 하지만 runtime 관점에서는 “필요한 패턴 검색”이 아니라 “로딩된 패턴 팩 전체 삽입” 모델에 가깝다. 이 방식은 문서가 길수록 prompt 비용과 latency를 키운다. citeturn18view0turn20view0turn26view6
|
|
111
|
+
|
|
112
|
+
**기술 접근**
|
|
113
|
+
각 `patterns/*.md`에 `id`, `lang`, `category`, `signals`, `examples`, `counterexamples`, `severity`, `profiles`, `locale-notes` 같은 frontmatter를 추가하고, `src/loader.js`에서 이를 읽어 `src/pattern-index.js`로 inverted index를 만든 뒤 top-K retrieval을 해야 한다. retrieval은 처음부터 복잡한 vector search일 필요가 없다. 로컬 lexicon hit, punctuation/style cue, discourse marker, short regex set, profile/language prior를 합친 BM25 유사 스코어면 충분하다. `src/prompt-builder.js`는 “전체 팩”이 아니라 “선정된 패턴 + 카테고리별 최소 커버리지”만 넣고, 부족하면 second pass를 수행하도록 바꾸는 게 좋다. 이 변경은 패턴 품질 관리에도 도움이 된다. 패턴 검증용 `tools/validate-patterns.mjs`를 만들면 누락된 ID, 중복 번호, 잘못된 카테고리, 번역 품질 저하를 CI에서 잡을 수 있다. citeturn26view6turn23view6turn23view7turn23view8
|
|
114
|
+
|
|
115
|
+
**수정 파일**
|
|
116
|
+
`patterns/*.md`, `src/loader.js`, `src/prompt-builder.js`, `src/pattern-index.js`, `tools/validate-patterns.mjs`
|
|
117
|
+
|
|
118
|
+
**구현 난이도**
|
|
119
|
+
M
|
|
120
|
+
|
|
121
|
+
**기대 효과**
|
|
122
|
+
지연시간 감소, 비용 절감, 패턴 품질 관리 향상, 프롬프트 집중도 향상
|
|
123
|
+
|
|
124
|
+
**리스크와 트레이드오프**
|
|
125
|
+
retriever recall이 낮으면 중요한 패턴을 놓칠 수 있다. 이를 막으려면 category floor와 fallback second pass가 필요하다.
|
|
126
|
+
|
|
127
|
+
**우선순위**
|
|
128
|
+
P0
|
|
129
|
+
|
|
130
|
+
### 다국어 로컬 stylometry·lexicon 계층 구축
|
|
131
|
+
|
|
132
|
+
**설명**
|
|
133
|
+
README는 stylometric pre-pass로 burstiness CV와 MATTR, AI-lexicon overlap을 설명하지만, 공개 설명 기준 lexicon 수치는 EN/KO만 선명하게 제시된다. 반면 패턴은 4개 언어를 지원한다. 이는 zh/ja에서 “패턴 catalog는 넓지만 style signal은 상대적으로 얕은” 비대칭을 강하게 시사한다. 또 HC3 Plus는 요약·번역·패러프레이즈 같은 semantic-invariant 과제가 탐지를 더 어렵게 만든다고 보여준다. patina는 바로 그런 rewrite 환경에 놓이는 도구다. citeturn18view4turn18view0turn33view1
|
|
134
|
+
|
|
135
|
+
**기술 접근**
|
|
136
|
+
`src/features/segment.js`를 새로 만들고 `Intl.Segmenter`가 있으면 locale-sensitive word/sentence segmentation을 사용하되, 없으면 fallback을 두는 식으로 구현하는 것이 가장 가볍다. 그 위에 `src/features/stylometry.js`에서 MATTR, sentence-length CV, punctuation entropy, discourse-opener repetition, parenthesis/em-dash density, hedge/disclaimer density, function-word ratio를 계산하고, `src/features/lexicon.js`에서 ko/en/zh/ja 전부의 AI-lexicon과 domain/profile allowlist를 관리하면 된다. 더 나아가 ambiguous case에만 `onnxruntime-node` 기반의 소형 다국어 classifier를 붙이면 rule-only보다 높은 정확도를 기대할 수 있다. 외부 연구도 DetectGPT와 Binoculars처럼 pure prompting이 아닌 별도 statistical/model-based signal이 zero-shot detection에 효과적일 수 있음을 보여준다. citeturn42search4turn42search3turn43search0turn43search2turn33view3turn32view1turn32view0
|
|
137
|
+
|
|
138
|
+
**수정 파일**
|
|
139
|
+
`src/features/segment.js`, `src/features/stylometry.js`, `src/features/lexicon.js`, `lexicon/ko*.txt`, `lexicon/en*.txt`, `lexicon/zh*.txt`, `lexicon/ja*.txt`, 필요시 `models/detector.onnx`
|
|
140
|
+
|
|
141
|
+
**구현 난이도**
|
|
142
|
+
L
|
|
143
|
+
|
|
144
|
+
**기대 효과**
|
|
145
|
+
다국어 정확도 상승, LLM 의존도 감소, 비용 절감, score variance 축소
|
|
146
|
+
|
|
147
|
+
**리스크와 트레이드오프**
|
|
148
|
+
로컬 모델을 넣으면 배포 크기와 설치 복잡도가 증가한다. 따라서 “rule/stylometry 먼저, ONNX는 optional” 경로가 적절하다.
|
|
149
|
+
|
|
150
|
+
**우선순위**
|
|
151
|
+
P0
|
|
152
|
+
|
|
153
|
+
### scoring·MPS·fidelity 알고리즘 재보정과 제어 로직 일치화
|
|
154
|
+
|
|
155
|
+
**설명**
|
|
156
|
+
현재 MPS와 fidelity는 구조가 단순하고 이해하기 쉽다는 장점이 있지만, 실제 rewrite 품질에서 중요한 숫자·날짜·고유명사·인과·조건절 보존을 충분히 세분화하지 않는다. 게다가 `combinedScore`가 계산되는데도 control loop는 사실상 `currentScore` 중심으로 돈다. 이건 코드가 이미 더 좋은 신호를 계산하고도 활용하지 못한다는 뜻이다. citeturn25view5turn25view6turn13view4turn27view5
|
|
157
|
+
|
|
158
|
+
**기술 접근**
|
|
159
|
+
`src/scoring.js`에서 MPS를 “anchor type별 weighted preservation”으로 바꾸는 것이 좋다. 최소한 entity, number/date, polarity, causation, conditional, domain term을 분리해야 한다. fidelity의 길이 항목도 문자 길이 ratio 대신 segment/token ratio로 바꾸고, contradiction penalty를 따로 두는 편이 낫다. 그리고 `src/ouroboros.js`는 중단 기준을 `decisionScore = α·AI + β·(100-fidelity) + γ·semanticRisk` 같은 형태로 바꿔야 한다. MAX의 tie-break 역시 “MPS 통과 후보 중 최소 AI”보다 “decisionScore 최소”가 더 일관된다. 외부 데이터셋은 HC3와 HC3 Plus를 baseline으로 쓰고, patina의 자체 500-paragraph calibration corpus를 언어·도메인별로 확장해 profile별 threshold를 다시 맞추는 게 바람직하다. citeturn33view0turn33view1turn18view4
|
|
160
|
+
|
|
161
|
+
**수정 파일**
|
|
162
|
+
`src/scoring.js`, `src/ouroboros.js`, `src/max-mode.js`, `.patina.default.yaml`, `.omc/research/*`
|
|
163
|
+
|
|
164
|
+
**구현 난이도**
|
|
165
|
+
L
|
|
166
|
+
|
|
167
|
+
**기대 효과**
|
|
168
|
+
정확도 상승, 의미 왜곡 감소, profile/language별 calibration 향상
|
|
169
|
+
|
|
170
|
+
**리스크와 트레이드오프**
|
|
171
|
+
평가식이 복잡해지면 해석성이 떨어질 수 있다. 그래서 최종 출력에는 각 항목별 subscore와 penalty reason을 반드시 남겨야 한다.
|
|
172
|
+
|
|
173
|
+
**우선순위**
|
|
174
|
+
P1
|
|
175
|
+
|
|
176
|
+
### backend/provider 계층 하드닝과 비용 제어
|
|
177
|
+
|
|
178
|
+
**설명**
|
|
179
|
+
patina는 backend와 provider를 분리한 점은 좋지만, 공개된 코드만 보면 retry/backoff/concurrency budget/cost budget 같은 운영 보호장치가 충분히 노출되어 있지 않다. MAX는 여러 모델을 동시에 던지는 구조라 provider별 실패율과 지연 편차를 그대로 맞게 된다. citeturn15view0turn14view2turn14view6turn28view1
|
|
180
|
+
|
|
181
|
+
**기술 접근**
|
|
182
|
+
가장 현실적인 접근은 `src/api.js`에서 Node의 built-in fetch 경로를 유지하되, `AbortController`, `p-limit`, `p-retry`를 얹는 것이다. Node 문서에 따르면 fetch는 Undici 기반이므로 굳이 무거운 HTTP client를 추가하지 않아도 된다. 여기에 `src/providers.js`에 capability map을 넣어 “structured output 지원 여부, timeout, retryable status, free-tier 특성, max concurrency, cost metadata”를 명시하면 된다. 사용자는 `--max-concurrency`, `--budget-tokens`, `--budget-cost`, `--fail-open`, `--fail-closed` 같은 운영 플래그를 통해 성능과 품질을 조절할 수 있다. `p-limit`는 동시 실행 수 관리에, `p-retry`는 지수 backoff와 abort signal 처리에 적합하다. citeturn36search5turn37search1turn37search0
|
|
183
|
+
|
|
184
|
+
**수정 파일**
|
|
185
|
+
`src/api.js`, `src/providers.js`, `src/backends/index.js`, `src/max-mode.js`, `src/cli.js`
|
|
186
|
+
|
|
187
|
+
**구현 난이도**
|
|
188
|
+
M
|
|
189
|
+
|
|
190
|
+
**기대 효과**
|
|
191
|
+
지연시간 tail 감소, rate-limit 내성 증가, 비용 예측 가능성 향상
|
|
192
|
+
|
|
193
|
+
**리스크와 트레이드오프**
|
|
194
|
+
운영 플래그가 많아지면 UX가 무거워질 수 있다. 기본 preset을 잘 잡아야 한다.
|
|
195
|
+
|
|
196
|
+
**우선순위**
|
|
197
|
+
P1
|
|
198
|
+
|
|
199
|
+
### 테스트·CI·품질 벤치마크 계층 확장
|
|
200
|
+
|
|
201
|
+
**설명**
|
|
202
|
+
현재 `npm test`는 `tests/e2e/*.test.js`만 대상으로 한다. 이 자체가 나쁘다는 뜻은 아니지만, 지금 patina가 안고 있는 위험은 e2e smoke만으로 잡기 어렵다. parser edge case, Unicode segmentation, score schema drift, rollback invariant, pattern metadata 품질은 unit/property/benchmark 계층이 필요하다. citeturn44view0turn44view1
|
|
203
|
+
|
|
204
|
+
**기술 접근**
|
|
205
|
+
Node의 내장 `node:test`는 유지하되, 세 층을 추가하는 것이 맞다. `tests/unit`에는 parseArgs/config precedence/scoring formula/pattern schema test를 넣고, `tests/property`에는 `fast-check`로 “임의 Unicode 입력에서도 crash하지 않는다”, “mock backend에서 score JSON은 항상 schema를 만족한다”, “rollback 후 점수와 원문 연결성이 보존된다” 같은 invariant를 돌린다. `tests/quality`에는 HC3, HC3 Plus, repo calibration corpus, 내부 ko/ja/zh/en human/AI pairs를 넣고 AUROC, TPR@1% FPR, false positive on human prose, MPS/fidelity 평균, human blind preference를 측정해야 한다. GitHub Actions는 Node 18/20/22 matrix와 mock/live-smoke를 분리해 운영하는 편이 좋다. `fast-check`는 seed 기반 reproducibility를 지원해 flaky test에도 유리하다. citeturn36search0turn36search2turn36search4turn33view0turn33view1
|
|
206
|
+
|
|
207
|
+
**수정 파일**
|
|
208
|
+
`package.json`, `.github/workflows/ci.yml`, `tests/unit/**`, `tests/property/**`, `tests/quality/**`, `artifacts/**`
|
|
209
|
+
|
|
210
|
+
**구현 난이도**
|
|
211
|
+
M
|
|
212
|
+
|
|
213
|
+
**기대 효과**
|
|
214
|
+
회귀 방지, score drift 조기 탐지, 릴리스 신뢰성 향상
|
|
215
|
+
|
|
216
|
+
**리스크와 트레이드오프**
|
|
217
|
+
quality benchmark 구축에는 데이터 정제 비용이 든다. 그러나 이 투자가 없으면 scoring/MPS 조정의 효과를 검증할 방법이 없다.
|
|
218
|
+
|
|
219
|
+
**우선순위**
|
|
220
|
+
P1
|
|
221
|
+
|
|
222
|
+
### 비밀키 처리, 커스텀 경로 UX, 실행 산출물 재현성 패키지
|
|
223
|
+
|
|
224
|
+
**설명**
|
|
225
|
+
현재 help는 `--api-key <key>` 사용을 직접 노출하고, 환경변수도 여러 provider 키를 나열한다. 동시에 사용자가 커스텀 config/path를 넘기거나, 실행 결과를 manifest로 저장하는 옵션은 공개 help에서 보이지 않는다. model/provider naming도 single-model path와 MAX path 사이에 분리돼 초심자 입장에서 혼동 여지가 있다. citeturn45view0turn45view1turn23view13
|
|
226
|
+
|
|
227
|
+
**기술 접근**
|
|
228
|
+
보안 측면에선 `--api-key`를 즉시 제거할 필요는 없지만, 기본 권장 흐름은 `--api-key-stdin` 또는 `PATINA_API_KEY_FILE`로 전환해야 한다. GitHub 문서와 CWE는 command line을 통한 secret 전달을 피하라고 명시한다. UX 측면에선 Node 18 compatibility를 유지하려면 최신 Commander보다 `yargs`가 더 안전하다. `yargs`는 명령·옵션·help generation이 강하고, 현재 수동 parser를 대체하기 좋다. `src/cli.js`, `src/config.js`, `src/loader.js`, `src/output.js`에 `--config`, `--patterns-dir`, `--profiles-dir`, `--lexicon-dir`, `--voice-file`, `--json`, `--save-run`을 추가하고, 실행 후에는 `manifest.json`에 package version, repo SHA, config hash, prompt hash, selected patterns, provider/model, token usage, score breakdown, evaluator 정보를 남기는 것이 좋다. Commander 최신판은 Node 20+를 요구하는 반면, 현재 patina는 Node >=18을 목표로 한다는 점도 `yargs` 쪽이 더 맞는 이유다. citeturn41search1turn41search3turn39search1turn38search3turn44view3
|
|
229
|
+
|
|
230
|
+
**수정 파일**
|
|
231
|
+
`src/cli.js`, `src/config.js`, `src/loader.js`, `src/output.js`, `AUTHENTICATION.md`, `README.md`
|
|
232
|
+
|
|
233
|
+
**구현 난이도**
|
|
234
|
+
M
|
|
235
|
+
|
|
236
|
+
**기대 효과**
|
|
237
|
+
보안 향상, 사용자 설정 유연성 증가, 디버깅/재현성 개선
|
|
238
|
+
|
|
239
|
+
**리스크와 트레이드오프**
|
|
240
|
+
CLI 파서 전환은 호환성 문제가 생길 수 있다. 최소 1개 릴리스 동안 deprecated alias를 유지하는 것이 좋다.
|
|
241
|
+
|
|
242
|
+
**우선순위**
|
|
243
|
+
P1
|
|
244
|
+
|
|
245
|
+
## 로드맵과 검증 계획
|
|
246
|
+
|
|
247
|
+
현재 구조를 유지하면서도 품질을 빠르게 올리려면, “모듈 교체”보다 “판단 계층 분리 → 출력 강제화 → 패턴/특징 검색화” 순서로 가는 편이 맞다. 외부 연구를 보면 iterative refinement 자체는 분명 가치가 있지만, self-critique만으로는 회귀를 막기 어렵다. 그래서 patina의 다음 버전은 “한 번 더 잘 쓰게 만드는 시스템”이 아니라 “잘못된 후보를 가려내고 설명 가능한 근거로 통과시키는 시스템”으로 이동해야 한다. citeturn35search0turn34search0turn35search3turn32view0turn32view1
|
|
248
|
+
|
|
249
|
+
```mermaid
|
|
250
|
+
flowchart LR
|
|
251
|
+
A[CLI and config] --> B[run manifest]
|
|
252
|
+
B --> C[local segmenter and stylometry]
|
|
253
|
+
C --> D[pattern retriever top-K]
|
|
254
|
+
D --> E[multi-generator or single generator]
|
|
255
|
+
E --> F[evaluator]
|
|
256
|
+
C --> F
|
|
257
|
+
F --> G{decision score pass?}
|
|
258
|
+
G -- yes --> H[final output plus manifest]
|
|
259
|
+
G -- no --> I[rollback or targeted refinement]
|
|
260
|
+
I --> E
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
### 권장 일정
|
|
264
|
+
|
|
265
|
+
| 기간 | 마일스톤 | 핵심 산출물 |
|
|
266
|
+
| --- | --- | --- |
|
|
267
|
+
| 1주–2주 | 정확도·강건성 긴급 보강 | evaluator 분리, `sourceText` 직접 전달, structured output schema, malformed output retry, MAX/Ouroboros 회귀 테스트 |
|
|
268
|
+
| 3주–5주 | 비용·다국어 품질 개선 | pattern metadata schema, top-K retrieval, ko/en/zh/ja lexicon 정비, 로컬 stylometry feature extractor, decision score 재설계 |
|
|
269
|
+
| 6주–8주 | 운영 품질 고도화 | provider capability map, concurrency/cost budget, property-based tests, quality benchmark, `--config`·`--save-run`·`--api-key-stdin` 도입 |
|
|
270
|
+
|
|
271
|
+
### 권장 검증 세트
|
|
272
|
+
|
|
273
|
+
| 계층 | 테스트 항목 | 지표 |
|
|
274
|
+
| --- | --- | --- |
|
|
275
|
+
| unit | parseArgs, config precedence, pattern schema, score formula, rollback invariant | pass rate 100%, snapshot diff 0 |
|
|
276
|
+
| property | 임의 Unicode 입력, 랜덤 파일 배치, malformed model output, random allow/blocklist 조합 | no-crash, schema validity, shrinkable counterexample |
|
|
277
|
+
| e2e | rewrite/audit/score/diff/ouroboros/MAX를 mock backend와 live smoke로 실행 | success rate, JSON failure rate, rollback rate |
|
|
278
|
+
| quality benchmark | HC3, HC3 Plus, repo calibration corpus, 내부 ko/ja/zh/en paired set | AUROC, macro-F1, TPR@1% FPR, human prose FP, MPS, fidelity, blind human preference |
|
|
279
|
+
| performance/cost | 짧은 문서·긴 문서·배치 처리·MAX 병렬 처리 | p50/p95 latency, input/output tokens, cost per 1k chars, retries per request |
|
|
280
|
+
| reproducibility | 동일 config/model/seed로 5회 반복 | score variance, selected-pattern stability, manifest completeness |
|
|
281
|
+
|
|
282
|
+
### 권장 데이터셋과 기준선
|
|
283
|
+
|
|
284
|
+
QC용 외부 벤치마크는 최소 HC3와 HC3 Plus를 포함해야 한다. HC3는 human-vs-ChatGPT 비교 코퍼스라 탐지 baseline으로 유용하고, HC3 Plus는 summarization·translation·paraphrasing 같은 semantic-invariant task를 포함해 patina의 실제 사용 맥락과 더 가깝다. 여기에 README가 언급하는 repo 내부 500-paragraph calibration corpus를 언어·도메인별로 재정비해 쓰면 된다. 특히 법률·의학·기술문서·SNS 글처럼 profile별 문체 차이가 큰 텍스트를 분리해야 threshold와 false positive를 제대로 잡을 수 있다. citeturn33view0turn33view1turn18view4
|
|
285
|
+
|
|
286
|
+
### 최종 우선순위 제안
|
|
287
|
+
|
|
288
|
+
실제로 한 번에 다 하지 말고, 다음 순서로 자르는 것이 가장 효율적이다.
|
|
289
|
+
|
|
290
|
+
먼저 **P0 네 가지**를 한다. 평가기 분리, structured outputs, pattern retrieval, 로컬 multilingual stylometry다. 이 단계가 끝나면 patina는 “LLM에게 다 맡기는 humanizer”에서 “로컬 신호와 외부 평가기를 결합하는 hybrid editor”로 바뀐다. 그 다음에 scoring/MPS/fidelity 재보정과 backend hardening을 붙이면 정확도와 비용이 같이 안정된다. 마지막으로 테스트·CI·secrets·custom path·manifest를 정리하면 운영 가능한 도구가 된다. 지금 저장소는 이미 좋은 문제정의와 패턴 자산을 갖고 있으므로, 핵심은 새 기능을 더하는 것보다 **판단·검증·기록 계층을 소프트웨어적으로 고정하는 것**이다. citeturn18view0turn26view6turn25view4turn25view5turn25view6
|