patina-cli 3.11.0 → 4.0.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 +29 -29
- package/CHANGELOG.md +53 -0
- package/NOTICE +21 -0
- package/README.md +117 -224
- package/README_JA.md +134 -77
- package/README_KR.md +132 -74
- package/README_ZH.md +137 -80
- package/SKILL.md +11 -20
- package/artifacts/rebaseline-2025/README.md +147 -0
- package/artifacts/rebaseline-2025/human-controls.public.jsonl +250 -0
- package/artifacts/rebaseline-2025/intake.example.jsonl +2 -0
- package/artifacts/rebaseline-2025/intake.local.example.jsonl +25 -0
- package/artifacts/rebaseline-2025/prompts.template.jsonl +7 -0
- package/artifacts/rebaseline-2025/sources.ko-public.jsonl +39 -0
- package/assets/brand/patina-badge.svg +18 -0
- package/assets/brand/patina-mark.svg +8 -0
- package/assets/demo/README.md +79 -0
- package/core/scoring.md +12 -12
- package/core/standalone-prompt.md +3 -1
- package/core/stylometry.md +93 -22
- package/docs/API.md +1554 -0
- package/docs/AUTHENTICATION.md +50 -26
- package/docs/AUTHENTICATION_KR.md +54 -29
- package/docs/BRANDING.md +9 -8
- package/docs/CLI.md +55 -14
- package/docs/COOKBOOK.md +8 -21
- package/docs/DEMO.md +32 -5
- package/docs/EXIT-CODES.md +2 -3
- package/docs/FALSE-POSITIVES.md +63 -0
- package/docs/FAQ.md +9 -1
- package/docs/FAQ_KR.md +3 -1
- package/docs/FLAG-PARITY.md +33 -47
- package/docs/ISSUE-WAVES.md +57 -0
- package/docs/PATTERNS-EN.md +67 -3
- package/docs/PATTERNS-JA.md +68 -2
- package/docs/PATTERNS-KO.md +70 -7
- package/docs/PATTERNS-ZH.md +67 -3
- package/docs/PATTERNS.md +5 -5
- package/docs/RESEARCH-DOCS-PLATFORM.md +54 -0
- package/docs/ROADMAP.md +46 -66
- package/docs/TRANSLATIONESE-KO.md +51 -0
- package/docs/audits/2026-05-deep-research.md +3 -1
- package/docs/benchmarks/README.md +51 -0
- package/docs/benchmarks/detector-comparison.json +69 -9
- package/docs/benchmarks/detector-comparison.md +10 -5
- package/docs/benchmarks/katfish-ko-latest.json +657 -0
- package/docs/benchmarks/katfish-ko-latest.md +77 -0
- package/docs/benchmarks/latest.json +1183 -108
- package/docs/benchmarks/latest.md +84 -60
- package/docs/benchmarks/lexicon-freshness-en-2026-05-22.json +1121 -0
- package/docs/benchmarks/lexicon-freshness-en-2026-05-22.md +136 -0
- package/docs/benchmarks/rebaseline-latest.json +381 -0
- package/docs/benchmarks/rebaseline-latest.md +121 -0
- package/docs/benchmarks/register-stratified-latest.json +164 -0
- package/docs/benchmarks/register-stratified-latest.md +99 -0
- package/docs/benchmarks/register-stratified.md +43 -0
- package/docs/integrations/github-action.md +44 -11
- package/docs/integrations/playground.md +58 -0
- package/docs/integrations/pre-commit.md +5 -5
- package/docs/integrations/release.md +5 -3
- package/docs/integrations/static-sites.md +83 -0
- package/docs/research/2025-rebaseline-plan.md +71 -2
- package/docs/research/2026-rebaseline.md +102 -0
- package/docs/research/adversarial-mps.md +41 -0
- package/docs/research/ai-human-metrics.md +35 -23
- package/docs/research/human-eval-panel.md +42 -0
- package/docs/research/judge-agreement.md +24 -0
- package/docs/research/ko-2025-corpus-sources.md +135 -0
- package/docs/research/lexicon-freshness-audit.md +64 -0
- package/docs/research/zh-ja-lexicon-calibration.md +60 -0
- package/docs/social/patina-launch-copy.md +173 -100
- package/docs/social/patina-launch-execution.md +94 -0
- package/docs/social/patina-launch-korean-first.md +83 -0
- package/docs/social/signs-of-ai-writing.md +26 -0
- package/docs/social/signs-of-ai-writing_KR.md +26 -0
- package/lexicon/ai-en.md +21 -24
- package/lexicon/ai-ja.md +158 -0
- package/lexicon/ai-ko.md +9 -9
- package/lexicon/ai-zh.md +158 -0
- package/lexicon/provenance/ai-en.json +970 -0
- package/lexicon/provenance/ai-ja.json +542 -0
- package/lexicon/provenance/ai-ko.json +866 -0
- package/lexicon/provenance/ai-zh.json +542 -0
- package/package.json +49 -8
- package/patterns/en-communication.md +5 -0
- package/patterns/en-content.md +5 -0
- package/patterns/en-filler.md +5 -0
- package/patterns/en-language.md +29 -1
- package/patterns/en-structure.md +5 -0
- package/patterns/en-style.md +5 -0
- package/patterns/en-viral-hook.md +42 -2
- package/patterns/ja-communication.md +5 -0
- package/patterns/ja-content.md +5 -0
- package/patterns/ja-filler.md +5 -0
- package/patterns/ja-language.md +33 -1
- package/patterns/ja-structure.md +12 -0
- package/patterns/ja-style.md +5 -0
- package/patterns/ja-viral-hook.md +41 -2
- package/patterns/ko-communication.md +5 -0
- package/patterns/ko-content.md +5 -0
- package/patterns/ko-filler.md +5 -0
- package/patterns/ko-language.md +33 -1
- package/patterns/ko-structure.md +25 -6
- package/patterns/ko-style.md +5 -0
- package/patterns/ko-viral-hook.md +38 -2
- package/patterns/zh-communication.md +5 -0
- package/patterns/zh-content.md +5 -0
- package/patterns/zh-filler.md +5 -0
- package/patterns/zh-language.md +37 -1
- package/patterns/zh-structure.md +12 -0
- package/patterns/zh-style.md +5 -0
- package/patterns/zh-viral-hook.md +38 -2
- package/playground/README.md +55 -0
- package/playground/analytics.js +4 -0
- package/playground/analyzer.js +883 -0
- package/playground/app.js +157 -0
- package/playground/data/lexicons.js +343 -0
- package/playground/index.html +138 -0
- package/playground/styles.css +267 -0
- package/profiles/namuwiki.md +111 -0
- package/scripts/adversarial-mps-report.mjs +201 -0
- package/scripts/badge-json.mjs +79 -0
- package/scripts/benchmark-report.mjs +56 -9
- package/scripts/check-release-metadata.mjs +0 -2
- package/scripts/detector-comparison.mjs +7 -7
- package/scripts/generate-playground-data.mjs +77 -0
- package/scripts/katfish-calibration.mjs +464 -0
- package/scripts/lexicon-freshness.mjs +485 -0
- package/scripts/lint.mjs +1 -1
- package/scripts/precommit-score.mjs +4 -3
- package/scripts/prose-score.mjs +81 -5
- package/scripts/rebaseline-intake.mjs +242 -0
- package/scripts/rebaseline-score.mjs +268 -0
- package/scripts/rebaseline-summary.mjs +773 -0
- package/scripts/rebaseline-web-collect.mjs +410 -0
- package/scripts/update-benchmark-ranges.mjs +1 -0
- package/src/api.js +69 -105
- package/src/auth.js +50 -2
- package/src/backends/claude-cli.js +19 -4
- package/src/backends/codex-cli.js +19 -3
- package/src/backends/contract.js +230 -1
- package/src/backends/gemini-cli.js +18 -5
- package/src/backends/index.js +87 -12
- package/src/backends/kimi-cli.js +161 -0
- package/src/cli.js +577 -567
- package/src/commands/doctor.js +2 -2
- package/src/config.js +29 -0
- package/src/errors.js +53 -1
- package/src/features/discourse-tells.js +68 -0
- package/src/features/index.js +82 -8
- package/src/features/lexicon.js +40 -6
- package/src/features/markup-leakage.js +69 -0
- package/src/features/segment.js +41 -0
- package/src/features/signal-strength.js +81 -0
- package/src/features/stylometry.js +231 -1
- package/src/features/translationese.js +127 -0
- package/src/loader.js +76 -0
- package/src/logger.js +22 -23
- package/src/model-defaults.js +55 -0
- package/src/ouroboros.js +31 -0
- package/src/output.js +102 -90
- package/src/prompt-builder.js +103 -68
- package/src/providers.js +51 -4
- package/src/scoring.js +210 -2
- package/src/security.js +75 -0
- package/tests/fixtures/live-quality/en/public-docs-01.md +26 -0
- package/tests/fixtures/live-quality/ko/public-docs-01.md +26 -0
- package/tests/fixtures/suspect-zones/expected-ranges.json +207 -16
- package/tests/fixtures/suspect-zones/ja/ai/ja-ai-04-lexicon.md +11 -0
- package/tests/fixtures/suspect-zones/ja/natural/ja-nat-04-lexicon-cold.md +11 -0
- package/tests/fixtures/suspect-zones/ko/ai/ko-ai-02.md +4 -5
- package/tests/fixtures/suspect-zones/ko/ai/ko-ai-07-ko-diagnostic.md +11 -0
- package/tests/fixtures/suspect-zones/zh/ai/zh-ai-04-lexicon.md +11 -0
- package/tests/fixtures/suspect-zones/zh/natural/zh-nat-04-lexicon-cold.md +11 -0
- package/tests/quality/README.md +188 -11
- package/tests/quality/adversarial-mps/fixtures.jsonl +10 -0
- package/tests/quality/benchmark.mjs +39 -1
- package/tests/quality/dogfood.mjs +5 -3
- package/tests/quality/live-fixtures.jsonl +2 -0
- package/tests/quality/live-quality.mjs +596 -0
- package/tests/quality/ranking-metrics.mjs +136 -0
- package/tests/quality/rebaseline-manifest.example.jsonl +5 -0
- package/vercel.json +53 -0
- package/SKILL-MAX.md +0 -455
- package/docs/internal/HARNESS.md +0 -14
- package/docs/internal/README.md +0 -14
- package/docs/internal/WARP.md +0 -23
- package/patina-max/SKILL.md +0 -523
- package/patina-max/composite.py +0 -457
- package/src/cache.js +0 -106
- package/src/commands/init.js +0 -208
- package/src/manifest.js +0 -162
- package/src/max-mode.js +0 -207
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# Lexicon freshness audit
|
|
2
|
+
|
|
3
|
+
Status: English remine complete; multilingual provenance sidecars complete with honest legacy/null fields.
|
|
4
|
+
Related issue: #160.
|
|
5
|
+
|
|
6
|
+
Patina lexicons are detection hypotheses. They should not be described as fresh model-era evidence unless each entry has a corpus source and a false-positive check.
|
|
7
|
+
|
|
8
|
+
## Current frontmatter status
|
|
9
|
+
|
|
10
|
+
| file | entries | current snapshot status | provenance | action |
|
|
11
|
+
|---|---:|---|---|---|
|
|
12
|
+
| `lexicon/ai-en.md` | 88 | `current` | `lexicon/provenance/ai-en.json` | keep; recheck at the next quarterly HAP-E or 2025+ paired refresh |
|
|
13
|
+
| `lexicon/ai-ko.md` | 96 | `partial` | `lexicon/provenance/ai-ko.json` | keep; rerun against 2026 KO positive + human-control pairs before threshold changes |
|
|
14
|
+
| `lexicon/ai-zh.md` | 60 | `needs-external-calibration` | `lexicon/provenance/ai-zh.json` | calibrate before broad claims |
|
|
15
|
+
| `lexicon/ai-ja.md` | 60 | `needs-external-calibration` | `lexicon/provenance/ai-ja.json` | calibrate before broad claims |
|
|
16
|
+
|
|
17
|
+
English was re-mined on 2026-05-22 against the HAP-E English paired corpus:
|
|
18
|
+
8,290 GPT-4o continuations versus 8,290 paired human `chunk_2` controls across
|
|
19
|
+
academic, blog, fiction, news, spoken, and TV/movie registers. Raw corpus text
|
|
20
|
+
stays in `artifacts/rebaseline-2025/private/`; only the aggregate report is
|
|
21
|
+
tracked.
|
|
22
|
+
|
|
23
|
+
Evidence:
|
|
24
|
+
|
|
25
|
+
- aggregate report: `docs/benchmarks/lexicon-freshness-en-2026-05-22.md`
|
|
26
|
+
- aggregate JSON: `docs/benchmarks/lexicon-freshness-en-2026-05-22.json`
|
|
27
|
+
- validation command: `npm run lexicon:freshness`
|
|
28
|
+
|
|
29
|
+
## English remine result
|
|
30
|
+
|
|
31
|
+
| decision | entries | rule |
|
|
32
|
+
|---|---:|---|
|
|
33
|
+
| kept | 88 | ≥4× hot-vs-cold document-frequency lift, at least one hot hit, cold document-frequency ≤5% |
|
|
34
|
+
| dropped | 20 | below the lift floor or zero hot hits |
|
|
35
|
+
|
|
36
|
+
Dropped English entries:
|
|
37
|
+
|
|
38
|
+
- strict: `state-of-the-art`, `enable`, `workflow`, `framework`, `dimensions`, `unleash`, `elevated`
|
|
39
|
+
- phrases: `a wide range of`, `a host of`, `in the age of`, `gain a deeper understanding`, `key drivers`, `driving force`, `play a key role`, `close the gap`, `end-to-end`, `to ensure that`, `it is essential to`, `under the hood`, `on the other hand`
|
|
40
|
+
|
|
41
|
+
## Per-entry remine gate
|
|
42
|
+
|
|
43
|
+
A refreshed entry needs:
|
|
44
|
+
|
|
45
|
+
```yaml
|
|
46
|
+
added: YYYY-MM-DD or null when the legacy add date is unknown
|
|
47
|
+
source: <snapshot id or corpus manifest path>
|
|
48
|
+
last_validated: YYYY-MM-DD or null when not yet externally validated
|
|
49
|
+
lift: <hot/cold document-frequency ratio or null>
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Promotion floor from `process/pattern-freshness.md`:
|
|
53
|
+
|
|
54
|
+
- ≥4× hot-vs-cold document-frequency lift;
|
|
55
|
+
- cold document-frequency ≤5%, unless the entry is register-scoped;
|
|
56
|
+
- no severe false positives in matched controls;
|
|
57
|
+
- no private text checked into the repo.
|
|
58
|
+
|
|
59
|
+
## Next action
|
|
60
|
+
|
|
61
|
+
Do not re-add dropped English entries without a newer paired-corpus lift report.
|
|
62
|
+
For KO/ZH/JA, the sidecar fields exist but some `added`, `last_validated`, or
|
|
63
|
+
`lift` values remain `null` instead of invented. Treat those languages as
|
|
64
|
+
partial or calibration-pending until their own paired hot/cold reports land.
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# zh/ja AI-Lexicon Calibration Notes
|
|
2
|
+
|
|
3
|
+
This note documents the first checked-in zh/ja AI-lexicon pass for issue #104.
|
|
4
|
+
The goal is high precision: the lexicon should add signal when AI-style
|
|
5
|
+
scaffolding is dense, without turning ordinary Chinese or Japanese prose hot on
|
|
6
|
+
one phrase.
|
|
7
|
+
|
|
8
|
+
## Shipped packs
|
|
9
|
+
|
|
10
|
+
| file | entries | shape | matching note |
|
|
11
|
+
|---|---:|---|---|
|
|
12
|
+
| `lexicon/ai-zh.md` | 60 | phrase-only | substring + `~` wildcard |
|
|
13
|
+
| `lexicon/ai-ja.md` | 60 | phrase-only | substring + `~` wildcard |
|
|
14
|
+
|
|
15
|
+
Both packs avoid strict entries by default because zh/ja tokenization uses the
|
|
16
|
+
character fallback. Custom strict entries still work through the CJK substring
|
|
17
|
+
fallback added in `src/features/lexicon.js`.
|
|
18
|
+
|
|
19
|
+
## Regression corpus
|
|
20
|
+
|
|
21
|
+
The committed regression corpus now has 39 fixtures overall. The zh/ja slice in
|
|
22
|
+
this note remains:
|
|
23
|
+
|
|
24
|
+
| language | AI | natural | expected FP |
|
|
25
|
+
|---|---:|---:|---:|
|
|
26
|
+
| zh | 4 | 4 | 0 |
|
|
27
|
+
| ja | 4 | 4 | 0 |
|
|
28
|
+
|
|
29
|
+
The new lexicon-specific fixtures are:
|
|
30
|
+
|
|
31
|
+
- `tests/fixtures/suspect-zones/zh/ai/zh-ai-04-lexicon.md`
|
|
32
|
+
- `tests/fixtures/suspect-zones/zh/natural/zh-nat-04-lexicon-cold.md`
|
|
33
|
+
- `tests/fixtures/suspect-zones/ja/ai/ja-ai-04-lexicon.md`
|
|
34
|
+
- `tests/fixtures/suspect-zones/ja/natural/ja-nat-04-lexicon-cold.md`
|
|
35
|
+
|
|
36
|
+
`npm run benchmark` reports 100% fixture accuracy with zh/ja precision and
|
|
37
|
+
recall at 4/4 each. The lexicon-specific AI fixtures are lexicon-only hot: their
|
|
38
|
+
burstiness and MATTR detectors stay cold while lexicon density crosses the
|
|
39
|
+
threshold.
|
|
40
|
+
|
|
41
|
+
## Expansion rule
|
|
42
|
+
|
|
43
|
+
Before adding more entries, test candidates against at least these classes:
|
|
44
|
+
|
|
45
|
+
1. AI/guidance prose that uses broad summary scaffolds.
|
|
46
|
+
2. Wikipedia/news-style human prose.
|
|
47
|
+
3. Personal narrative or sensory prose.
|
|
48
|
+
4. Domain-heavy technical prose where repeated nouns are normal.
|
|
49
|
+
|
|
50
|
+
Drop any candidate that appears at similar frequency in class 2 or 4. A phrase
|
|
51
|
+
that is common in human explanatory writing should move to the pattern catalog
|
|
52
|
+
only if it has a rewrite strategy; otherwise it should stay out of the lexicon.
|
|
53
|
+
|
|
54
|
+
## Remaining calibration risk
|
|
55
|
+
|
|
56
|
+
The committed fixture set is a regression gate, not a full 200-paragraph external
|
|
57
|
+
corpus. The original #104 acceptance target called for HC3 zh and curated ja
|
|
58
|
+
AI-vs-human calibration. This PR adds the lexicon packs and local gates so the
|
|
59
|
+
feature can be exercised safely, but future expansion should still run the larger
|
|
60
|
+
external corpus before raising entry counts or lowering the density threshold.
|
|
@@ -1,10 +1,56 @@
|
|
|
1
|
-
# patina Launch Copy
|
|
1
|
+
# patina Launch Copy and Playbook
|
|
2
2
|
|
|
3
|
-
Use this file as the source of truth for public launch posts. The positioning is deliberately
|
|
3
|
+
Use this file as the source of truth for public launch posts. The positioning is deliberately **auditable cleanup / editing tool**, not detector bypass.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Execution checklist:
|
|
6
|
+
[`docs/social/patina-launch-execution.md`](patina-launch-execution.md).
|
|
7
|
+
|
|
8
|
+
## Launch sequence
|
|
9
|
+
|
|
10
|
+
Run the launch in this order. Do not skip the Korean-first pass: it is the wedge that makes patina different from generic English humanizers.
|
|
11
|
+
|
|
12
|
+
| Order | Surface | Primary angle | Launch state |
|
|
13
|
+
|---:|---|---|---|
|
|
14
|
+
| 1 | Korean communities: GeekNews, Velog, Clien | Korean AI tells plus auditable edits | Ready after final score pass |
|
|
15
|
+
| 2 | Show HN | Local, auditable, benchmarked prose cleanup | Ready after final score pass |
|
|
16
|
+
| 3 | Product Hunt | Visual demo plus “keep the meaning” | Ready after final score pass |
|
|
17
|
+
| 4 | Reddit / X / Threads / LinkedIn | Local/no-key angle or editing/voice angle | Reuse the channel drafts below |
|
|
18
|
+
|
|
19
|
+
## Prerequisite checklist
|
|
20
|
+
|
|
21
|
+
| Item | Status | Launch impact |
|
|
22
|
+
|---|---|---|
|
|
23
|
+
| npm package live (#203) | Done | Use `npx patina-cli` in posts. |
|
|
24
|
+
| GitHub Action v1 (#204) | Done | Mention PR comments and README score badge. |
|
|
25
|
+
| README score badge (#282) | Done | Use as adoption/social proof. |
|
|
26
|
+
| Ethics framing (#164, [`docs/ETHICS.md`](../ETHICS.md)) | Done | Never imply detector evasion. |
|
|
27
|
+
| Comparison page (#213, [`docs/COMPARISON.md`](../COMPARISON.md)) | Done | Cite only factual comparisons. |
|
|
28
|
+
| Web playground (#208) | Ready | Use <https://patina.vibetip.help/> as the try-it-now URL. |
|
|
29
|
+
| Shareable card generator (#283) | Helpful | Product Hunt and X work better with it. |
|
|
30
|
+
| “Signs of AI writing” guide (#285) | Helpful | Use as top-of-funnel content. |
|
|
31
|
+
|
|
32
|
+
## Non-negotiable rules
|
|
33
|
+
|
|
34
|
+
- Score every final post before publishing. Target `<= 30`.
|
|
35
|
+
- Attach the score screenshot or CLI output to the internal launch thread.
|
|
36
|
+
- Lead with the writing problem. Mention the tool after the reader recognizes the problem.
|
|
37
|
+
- Do not use “bypass,” “undetectable,” or “beats detectors.”
|
|
38
|
+
- Avoid hype vocabulary, emoji-bullet stacks, and tidy three-item slogans.
|
|
39
|
+
- Link the playground from every broad-launch post: <https://patina.vibetip.help/>. Keep the repo link nearby for source, install, and issues.
|
|
6
40
|
|
|
7
|
-
|
|
41
|
+
Score command:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
node scripts/precommit-score.mjs docs/social/patina-launch-copy.md
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Last local score check: 2026-05-23, `docs/social/patina-launch-copy.md` scored 6.3% (`node scripts/precommit-score.mjs docs/social/patina-launch-copy.md`).
|
|
48
|
+
|
|
49
|
+
Korean-first launch drafts are now split out for exact channel copying:
|
|
50
|
+
[`docs/social/patina-launch-korean-first.md`](patina-launch-korean-first.md).
|
|
51
|
+
Last score check on 2026-05-23: Korean-first drafts 0.0%, this file 6.3%.
|
|
52
|
+
|
|
53
|
+
## Positioning
|
|
8
54
|
|
|
9
55
|
Short tagline:
|
|
10
56
|
|
|
@@ -14,38 +60,54 @@ Long tagline:
|
|
|
14
60
|
|
|
15
61
|
> A pattern-based cleanup tool for AI-sounding text. It shows what changed, why it changed, and whether the original claims survived.
|
|
16
62
|
|
|
17
|
-
|
|
63
|
+
One-sentence description:
|
|
64
|
+
|
|
65
|
+
> patina finds recurring AI-writing habits in Korean, English, Chinese, and Japanese, rewrites the affected passages, and keeps the edit auditable.
|
|
18
66
|
|
|
19
|
-
|
|
20
|
-
- Check the current benchmark: [`docs/benchmarks/latest.md`](../benchmarks/latest.md).
|
|
21
|
-
- If comparing tools, link the factual comparison page: [`docs/COMPARISON.md`](../COMPARISON.md).
|
|
22
|
-
- Use the launch social preview when the surface supports images: [`assets/social/patina-og.svg`](../../assets/social/patina-og.svg).
|
|
23
|
-
- Keep claims to "editing signal" and "suspect-zone benchmark"; do not imply authorship proof.
|
|
24
|
-
- Link issues for useful feedback: false positives, missing patterns, benchmark fixtures.
|
|
67
|
+
## Assets to attach
|
|
25
68
|
|
|
26
|
-
|
|
69
|
+
- Social preview: [`assets/social/patina-og.svg`](../../assets/social/patina-og.svg)
|
|
70
|
+
- Before/after card: [`assets/social/patina-before-after.svg`](../../assets/social/patina-before-after.svg)
|
|
71
|
+
- Static badge fallback: [`assets/brand/patina-badge.svg`](../../assets/brand/patina-badge.svg)
|
|
72
|
+
- Benchmark report: [`docs/benchmarks/latest.md`](../benchmarks/latest.md)
|
|
73
|
+
- Comparison page: [`docs/COMPARISON.md`](../COMPARISON.md)
|
|
27
74
|
|
|
28
|
-
|
|
75
|
+
## Korean communities
|
|
29
76
|
|
|
30
|
-
|
|
31
|
-
- a way to fake authorship
|
|
32
|
-
- proof that text is human-written
|
|
33
|
-
- a universal paraphraser
|
|
77
|
+
Title options:
|
|
34
78
|
|
|
35
|
-
|
|
79
|
+
```text
|
|
80
|
+
patina — 한국어·영어 AI 글의 “AI 티”를 찾아서 지워주는 오픈소스
|
|
81
|
+
AI가 쓴 티 나는 문장, 패턴으로 잡아서 고쳐주는 도구를 만들었습니다
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Post body:
|
|
85
|
+
|
|
86
|
+
```text
|
|
87
|
+
GPT한테 글을 맡기면 어딘가 티가 납니다. “~적인”, “~하고 있다”, 갑자기 늘어나는 한자어, 너무 반듯한 목록 같은 것들요.
|
|
88
|
+
|
|
89
|
+
patina는 그런 패턴을 찾아서 고칩니다. 한국어, 영어, 중국어, 일본어를 지원하고, Claude Code / Codex / Cursor / OpenCode 스킬이나 Node CLI로 쓸 수 있습니다.
|
|
90
|
+
|
|
91
|
+
핵심은 AI detector 우회가 아니라 편집입니다. 어떤 표현을 잡았는지, 왜 바꿨는지, 원래 주장과 의미가 보존됐는지를 audit / diff / score로 확인할 수 있게 만들었습니다.
|
|
36
92
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
93
|
+
API 키 없이도 쓸 수 있습니다. codex, claude, gemini CLI 중 하나에 로그인돼 있으면 됩니다.
|
|
94
|
+
|
|
95
|
+
웹에서 먼저:
|
|
96
|
+
https://patina.vibetip.help/
|
|
97
|
+
|
|
98
|
+
레포:
|
|
99
|
+
https://github.com/devswha/patina
|
|
100
|
+
|
|
101
|
+
특히 한국어 오탐 사례가 궁금합니다. 사람이 쓴 글인데 patina가 AI 티로 잡는 문장이 있으면 이 글 댓글로 편하게 붙여주셔도 됩니다.
|
|
102
|
+
웹에서 바로 신고: 플레이그라운드(https://patina.vibetip.help/)에서 '오탐 신고' 버튼을 누르면 걸린 문장이 자동으로 채워진 GitHub 폼이 열립니다.
|
|
103
|
+
```
|
|
42
104
|
|
|
43
105
|
## Show HN
|
|
44
106
|
|
|
45
107
|
Title:
|
|
46
108
|
|
|
47
109
|
```text
|
|
48
|
-
Show HN:
|
|
110
|
+
Show HN: Patina – rewrite AI text patterns in Korean/English/Chinese/Japanese
|
|
49
111
|
```
|
|
50
112
|
|
|
51
113
|
Post body:
|
|
@@ -53,141 +115,144 @@ Post body:
|
|
|
53
115
|
```text
|
|
54
116
|
Hi HN,
|
|
55
117
|
|
|
56
|
-
I built
|
|
118
|
+
I built Patina because I kept editing the same LLM tells out of drafts: inflated adjectives, neat three-part lists, hedging on hedging, and in Korean, suffixes like “~적”, progressive “~고 있다”, and needless Sino-Korean phrasing.
|
|
57
119
|
|
|
58
|
-
|
|
120
|
+
Patina turns those habits into a pattern catalog for Korean, English, Chinese, and Japanese. It can rewrite the affected passages, but it is not a black-box paraphraser. It shows what changed, why it changed, and whether claims, numbers, polarity, causation, and negation survived the edit.
|
|
59
121
|
|
|
60
|
-
|
|
122
|
+
It runs as a skill in Claude Code, Codex CLI, Cursor, and OpenCode, or as a standalone Node CLI:
|
|
61
123
|
|
|
62
|
-
|
|
124
|
+
npx patina-cli --lang en draft.md
|
|
63
125
|
|
|
64
|
-
|
|
65
|
-
"Coffee has emerged as a pivotal cultural phenomenon that has fundamentally transformed social interactions across the globe. This beloved beverage serves as a catalyst for community building, fosters meaningful connections, and facilitates cross-cultural dialogue."
|
|
126
|
+
If you are already logged into codex, claude, or gemini CLI, you can use it without adding an API key.
|
|
66
127
|
|
|
67
|
-
|
|
68
|
-
"Coffee has quietly changed how people meet. Sit across from someone long enough, and something like a real connection tends to form — even between people from very different cultures."
|
|
128
|
+
This is not meant as a detector-bypass tool. I treat the score as an editing signal, not proof of authorship. False positives are documented because the useful output is the audit and diff, not a verdict.
|
|
69
129
|
|
|
70
|
-
|
|
130
|
+
Try:
|
|
131
|
+
https://patina.vibetip.help/
|
|
71
132
|
|
|
72
133
|
Repo:
|
|
73
134
|
https://github.com/devswha/patina
|
|
74
135
|
|
|
75
|
-
I
|
|
136
|
+
The feedback I want most: human text that Patina wrongly flags, missing pattern families, and examples where the rewrite preserved the wrong thing.
|
|
76
137
|
```
|
|
77
138
|
|
|
78
|
-
##
|
|
139
|
+
## Product Hunt
|
|
140
|
+
|
|
141
|
+
Tagline:
|
|
79
142
|
|
|
80
143
|
```text
|
|
81
|
-
|
|
144
|
+
Strip the AI packaging. Keep the meaning.
|
|
145
|
+
```
|
|
82
146
|
|
|
83
|
-
|
|
147
|
+
Description:
|
|
84
148
|
|
|
85
|
-
|
|
149
|
+
```text
|
|
150
|
+
Patina finds the habits that make text read as AI-written — in Korean, English, Chinese, and Japanese — and rewrites them out. It is not a black-box paraphraser: it shows what changed, why it changed, and whether your claims survived. Use it in Claude Code, Codex, Cursor, OpenCode, or as a Node CLI.
|
|
151
|
+
```
|
|
86
152
|
|
|
87
|
-
|
|
88
|
-
“Coffee has emerged as a pivotal cultural phenomenon that has fundamentally transformed social interactions across the globe. This beloved beverage serves as a catalyst for community building, fosters meaningful connections, and facilitates cross-cultural dialogue.”
|
|
153
|
+
Maker comment:
|
|
89
154
|
|
|
90
|
-
|
|
91
|
-
|
|
155
|
+
```text
|
|
156
|
+
I built Patina because I was tired of removing the same AI tells from drafts by hand. Two details matter to me: it works on Korean, where most English-first humanizers miss the obvious tells, and it is auditable. Every edit should have a reason and a meaning-preservation check.
|
|
92
157
|
|
|
93
|
-
|
|
94
|
-
https://github.com/devswha/patina
|
|
158
|
+
I do not want this framed as “make text undetectable.” Detectors are noisy. Patina is an editing pass: find the synthetic packaging, remove it, and keep the claim intact.
|
|
95
159
|
|
|
96
|
-
|
|
160
|
+
Try it on something you wrote at https://patina.vibetip.help/ and tell me where it is wrong. False positives are the most useful reports.
|
|
97
161
|
```
|
|
98
162
|
|
|
99
|
-
##
|
|
163
|
+
## Reddit
|
|
100
164
|
|
|
101
|
-
###
|
|
165
|
+
### r/LocalLLaMA
|
|
102
166
|
|
|
103
167
|
```text
|
|
104
|
-
I built
|
|
168
|
+
I built Patina, a local-friendly tool for cleaning up AI-sounding prose.
|
|
169
|
+
|
|
170
|
+
It runs through the CLI you already use. If you are logged into codex, claude, or gemini, you can run Patina without adding a separate API key. It also works as a Claude Code / Codex / Cursor / OpenCode skill.
|
|
171
|
+
|
|
172
|
+
The tool finds recurring LLM writing habits, rewrites the affected text, and checks whether the original claims survived. It supports Korean, English, Chinese, and Japanese.
|
|
105
173
|
|
|
106
|
-
|
|
174
|
+
This is not an “undetectable text” project. The score is an editing signal. The useful artifact is the audit: what pattern fired, what changed, and whether meaning drifted.
|
|
107
175
|
|
|
108
|
-
|
|
109
|
-
|
|
176
|
+
Try:
|
|
177
|
+
https://patina.vibetip.help/
|
|
110
178
|
|
|
179
|
+
Repo:
|
|
111
180
|
https://github.com/devswha/patina
|
|
181
|
+
|
|
182
|
+
I am looking for false positives and missing pattern families, especially outside English.
|
|
112
183
|
```
|
|
113
184
|
|
|
114
|
-
###
|
|
185
|
+
### r/writing or r/Korean
|
|
115
186
|
|
|
116
187
|
```text
|
|
117
|
-
|
|
188
|
+
I built a tool that spots and rewrites AI-sounding patterns in writing, including Korean.
|
|
118
189
|
|
|
119
|
-
AI
|
|
190
|
+
The goal is not to hide authorship. It is to make AI-assisted drafts easier to edit. Patina points out habits like inflated phrasing, tidy generic structure, and Korean AI tells such as “~적인”, “~하고 있다”, and needless formal nouns.
|
|
120
191
|
|
|
121
|
-
|
|
122
|
-
```
|
|
192
|
+
It then rewrites the affected passages and checks that the original meaning survived. You can see the audit and diff instead of trusting a black-box paraphrase.
|
|
123
193
|
|
|
124
|
-
|
|
194
|
+
Try:
|
|
195
|
+
https://patina.vibetip.help/
|
|
125
196
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
“Coffee has emerged as a pivotal cultural phenomenon that has fundamentally transformed social interactions across the globe...”
|
|
197
|
+
Repo:
|
|
198
|
+
https://github.com/devswha/patina
|
|
130
199
|
|
|
131
|
-
|
|
200
|
+
If you have human-written text that gets flagged, I would love to see it. Those examples are the best way to reduce false positives.
|
|
132
201
|
```
|
|
133
202
|
|
|
134
|
-
|
|
203
|
+
## X / Threads
|
|
135
204
|
|
|
136
|
-
|
|
137
|
-
After:
|
|
205
|
+
### Korean thread
|
|
138
206
|
|
|
139
|
-
|
|
207
|
+
```text
|
|
208
|
+
1/ AI가 쓴 글은 티가 납니다. “~적인”, 너무 반듯한 목록, 갑자기 늘어나는 한자어 같은 것들요.
|
|
140
209
|
|
|
141
|
-
|
|
210
|
+
patina는 그런 패턴을 찾아서 고칩니다. KO / EN / ZH / JA.
|
|
142
211
|
```
|
|
143
212
|
|
|
144
|
-
### 5
|
|
145
|
-
|
|
146
213
|
```text
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
If a rewrite drops or flips an anchor, it retries or rolls back the change.
|
|
214
|
+
2/ 그냥 다시 써주는 도구는 많습니다.
|
|
150
215
|
|
|
151
|
-
|
|
216
|
+
patina는 뭘 왜 바꿨는지, 원래 의미가 보존됐는지까지 보여주는 편집 도구에 가깝습니다.
|
|
152
217
|
```
|
|
153
218
|
|
|
154
|
-
|
|
219
|
+
```text
|
|
220
|
+
3/ API 키 없이도 쓸 수 있습니다.
|
|
221
|
+
|
|
222
|
+
codex / claude / gemini CLI 중 하나만 로그인돼 있으면 Node CLI나 에디터 스킬로 바로 돌릴 수 있습니다.
|
|
223
|
+
```
|
|
155
224
|
|
|
156
225
|
```text
|
|
157
|
-
|
|
226
|
+
4/ 목표는 detector 우회가 아닙니다.
|
|
158
227
|
|
|
159
|
-
|
|
160
|
-
- 91% Korean editing-hotspot recall [84.0-95.4%], n=100
|
|
161
|
-
- 76% English HC3 editing-hotspot recall [66.7-83.3%], n=100
|
|
162
|
-
- 13-25% human-prose false-positive point-estimate range across registers
|
|
163
|
-
- Latest fixture benchmark: https://github.com/devswha/patina/blob/main/docs/benchmarks/latest.md
|
|
228
|
+
점수는 편집 신호일 뿐이고, 중요한 건 audit / diff / meaning check입니다.
|
|
164
229
|
|
|
165
|
-
|
|
230
|
+
https://github.com/devswha/patina
|
|
166
231
|
```
|
|
167
232
|
|
|
168
|
-
###
|
|
233
|
+
### English single post
|
|
169
234
|
|
|
170
235
|
```text
|
|
171
|
-
|
|
236
|
+
I built Patina: an AI-writing cleanup tool that works on Korean, shows its edits, and checks whether the meaning survived.
|
|
172
237
|
|
|
173
|
-
|
|
238
|
+
Not detector bypass. Just auditable editing for text that sounds too packaged.
|
|
174
239
|
|
|
240
|
+
Claude Code / Codex / Cursor / OpenCode / Node CLI.
|
|
175
241
|
https://github.com/devswha/patina
|
|
176
242
|
```
|
|
177
243
|
|
|
178
|
-
##
|
|
244
|
+
## LinkedIn
|
|
179
245
|
|
|
180
246
|
```text
|
|
181
|
-
|
|
247
|
+
Every team ships AI-assisted writing now: docs, release notes, support replies, launch posts. The problem is not that the writing is AI-assisted. The problem is that it often reads like it.
|
|
182
248
|
|
|
183
|
-
|
|
249
|
+
I built Patina for the editing pass after generation. It finds the habits that make prose feel machine-written, rewrites the affected passages, and checks whether the original claims survived.
|
|
184
250
|
|
|
185
|
-
|
|
251
|
+
The important part for work is auditability. You can see what changed and why instead of trusting a black-box paraphrase.
|
|
186
252
|
|
|
187
|
-
|
|
188
|
-
https://github.com/devswha/patina
|
|
253
|
+
It supports Korean, English, Chinese, and Japanese, and runs as an editor skill or Node CLI.
|
|
189
254
|
|
|
190
|
-
|
|
255
|
+
https://github.com/devswha/patina
|
|
191
256
|
```
|
|
192
257
|
|
|
193
258
|
## Maintainer reply templates
|
|
@@ -195,33 +260,41 @@ https://github.com/devswha/patina
|
|
|
195
260
|
### Detector-bypass concern
|
|
196
261
|
|
|
197
262
|
```text
|
|
198
|
-
Fair concern. I do not think of
|
|
263
|
+
Fair concern. I do not think of Patina as a detector-bypass tool. AI detectors are noisy anyway.
|
|
199
264
|
|
|
200
|
-
The goal is editing: find repeated writing habits that make LLM output feel synthetic, rewrite those parts, and keep the meaning checkable through audit
|
|
265
|
+
The goal is editing: find repeated writing habits that make LLM output feel synthetic, rewrite those parts, and keep the meaning checkable through audit, diff, and score modes.
|
|
201
266
|
```
|
|
202
267
|
|
|
203
268
|
### False positives
|
|
204
269
|
|
|
205
270
|
```text
|
|
206
|
-
False positives are real. Human prose can trigger
|
|
271
|
+
False positives are real. Human prose can trigger Patina, especially encyclopedic, corporate, academic, or heavily edited writing.
|
|
207
272
|
|
|
208
|
-
That is why I treat the score as a rough editing signal, not a truth machine. The diff and
|
|
273
|
+
That is why I treat the score as a rough editing signal, not a truth machine. The diff and highlighted patterns matter more than the exact number.
|
|
209
274
|
```
|
|
210
275
|
|
|
211
276
|
### Install help
|
|
212
277
|
|
|
213
278
|
```text
|
|
214
|
-
Install:
|
|
279
|
+
Install (standalone CLI, nothing to trust beyond npm):
|
|
215
280
|
|
|
216
|
-
|
|
281
|
+
npx patina-cli --lang en input.txt
|
|
217
282
|
|
|
218
|
-
|
|
283
|
+
Or inside Claude Code:
|
|
219
284
|
|
|
220
285
|
/patina --lang en
|
|
221
286
|
|
|
222
287
|
[paste text]
|
|
223
288
|
|
|
224
|
-
|
|
289
|
+
Prefer a one-line installer? Review the script first, then:
|
|
225
290
|
|
|
226
|
-
patina
|
|
291
|
+
curl -fsSL https://raw.githubusercontent.com/devswha/patina/main/install.sh | bash
|
|
227
292
|
```
|
|
293
|
+
|
|
294
|
+
## Post-launch triage
|
|
295
|
+
|
|
296
|
+
- Collect false-positive reports under the `false-positive` label.
|
|
297
|
+
- Use <https://github.com/devswha/patina/issues/new?template=false_positive.yml> for public false-positive reports.
|
|
298
|
+
- Turn repeated missing patterns into pattern issues with examples.
|
|
299
|
+
- Add strong before/after examples to `docs/EXAMPLES.md` or `examples/`.
|
|
300
|
+
- Re-score public copy after edits; keep the launch thread evidence attached.
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# patina Launch Execution Packet
|
|
2
|
+
|
|
3
|
+
Last prepared: 2026-05-23.
|
|
4
|
+
|
|
5
|
+
Use this packet when the maintainer is ready to post. Agents may prepare copy,
|
|
6
|
+
score proof, and follow-up notes, but should not publish from maintainer-owned
|
|
7
|
+
accounts.
|
|
8
|
+
|
|
9
|
+
## Current source files
|
|
10
|
+
|
|
11
|
+
| Purpose | File |
|
|
12
|
+
|---|---|
|
|
13
|
+
| Broad channel copy | [`patina-launch-copy.md`](patina-launch-copy.md) |
|
|
14
|
+
| Korean-first copy | [`patina-launch-korean-first.md`](patina-launch-korean-first.md) |
|
|
15
|
+
| Top-of-funnel English guide | [`signs-of-ai-writing.md`](signs-of-ai-writing.md) |
|
|
16
|
+
| Top-of-funnel Korean guide | [`signs-of-ai-writing_KR.md`](signs-of-ai-writing_KR.md) |
|
|
17
|
+
|
|
18
|
+
## Pre-post checklist
|
|
19
|
+
|
|
20
|
+
Run these before copying any post into a public channel:
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
node scripts/precommit-score.mjs \
|
|
24
|
+
docs/social/patina-launch-copy.md \
|
|
25
|
+
docs/social/patina-launch-korean-first.md \
|
|
26
|
+
docs/social/signs-of-ai-writing.md \
|
|
27
|
+
docs/social/signs-of-ai-writing_KR.md
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Latest local result:
|
|
31
|
+
|
|
32
|
+
| File | Score | Status |
|
|
33
|
+
|---|---:|---|
|
|
34
|
+
| `docs/social/patina-launch-copy.md` | 6.3% | pass |
|
|
35
|
+
| `docs/social/patina-launch-korean-first.md` | 0.0% | pass |
|
|
36
|
+
| `docs/social/signs-of-ai-writing.md` | 0.0% | pass |
|
|
37
|
+
| `docs/social/signs-of-ai-writing_KR.md` | 20.0% | pass |
|
|
38
|
+
|
|
39
|
+
Confirm the links used in broad posts:
|
|
40
|
+
|
|
41
|
+
- Playground: <https://patina.vibetip.help/>
|
|
42
|
+
- Repository: <https://github.com/devswha/patina>
|
|
43
|
+
- False-positive form: <https://github.com/devswha/patina/issues/new?template=false_positive.yml>
|
|
44
|
+
- Benchmark report: [`docs/benchmarks/latest.md`](../benchmarks/latest.md)
|
|
45
|
+
|
|
46
|
+
## Posting order
|
|
47
|
+
|
|
48
|
+
| Order | Channel | Copy source | Maintainer action |
|
|
49
|
+
|---:|---|---|---|
|
|
50
|
+
| 1 | GeekNews | `patina-launch-korean-first.md` → GeekNews | Post or mark deferred in the maintainer launch note. |
|
|
51
|
+
| 2 | Velog | `patina-launch-korean-first.md` → Velog | Post or mark deferred in the maintainer launch note. |
|
|
52
|
+
| 3 | Clien-style short post | `patina-launch-korean-first.md` → Clien-style short post | Post or mark deferred in the maintainer launch note. |
|
|
53
|
+
| 4 | Show HN | `patina-launch-copy.md` → Show HN | Post with playground + repo links. |
|
|
54
|
+
| 5 | Product Hunt | `patina-launch-copy.md` → Product Hunt | Use brand/social assets and maker comment. |
|
|
55
|
+
| 6 | Reddit | `patina-launch-copy.md` → Reddit | Pick LocalLLaMA or writing/Korean angle. |
|
|
56
|
+
| 7 | X / Threads / LinkedIn | `patina-launch-copy.md` → X / Threads | Use short copy and link playground first. |
|
|
57
|
+
|
|
58
|
+
## Maintainer update template
|
|
59
|
+
|
|
60
|
+
After each channel action, add a short entry to the maintainer launch note:
|
|
61
|
+
|
|
62
|
+
```text
|
|
63
|
+
Channel:
|
|
64
|
+
Status: posted | queued | deferred
|
|
65
|
+
URL:
|
|
66
|
+
Copy source:
|
|
67
|
+
Score command:
|
|
68
|
+
Score result:
|
|
69
|
+
Notes / feedback:
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
If a post is deferred, record the reason instead of leaving the checkbox
|
|
73
|
+
ambiguous.
|
|
74
|
+
|
|
75
|
+
## Feedback triage
|
|
76
|
+
|
|
77
|
+
Capture useful launch feedback with enough detail to reproduce it:
|
|
78
|
+
|
|
79
|
+
- language and register,
|
|
80
|
+
- copied paragraph or a private/non-redistributable note,
|
|
81
|
+
- score output,
|
|
82
|
+
- expected behavior,
|
|
83
|
+
- whether the reporter allows the text to be used as a fixture.
|
|
84
|
+
|
|
85
|
+
Public false-positive reports should use:
|
|
86
|
+
<https://github.com/devswha/patina/issues/new?template=false_positive.yml>.
|
|
87
|
+
|
|
88
|
+
## Close criteria for the launch note
|
|
89
|
+
|
|
90
|
+
Keep the maintainer launch note open until each channel is either:
|
|
91
|
+
|
|
92
|
+
- posted with URL and score proof,
|
|
93
|
+
- queued with owner/date,
|
|
94
|
+
- or explicitly deferred with reason.
|