@geolonia/yuuhitsu 0.2.4 → 0.3.1

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/README.ja.md ADDED
@@ -0,0 +1,383 @@
1
+ # yuuhitsu (右筆)
2
+
3
+ AI を活用したドキュメント操作 CLI
4
+
5
+ ## 概要
6
+
7
+ **yuuhitsu**(右筆、封建時代の日本で「秘書」や「書記」を意味する)は、AI を使用してドキュメント操作を自動化するコマンドラインツールです。この名前は、封建領主に仕え、公式文書の執筆・管理を代行した書記に由来しています — このツールはエンジニアに対して同様の役割を果たし、翻訳、ドキュメント生成、ドキュメント同期を担います。
8
+
9
+ ### 主な機能
10
+
11
+ * **Markdown 翻訳**:構造、コードブロック、フォーマットを保持しながらドキュメントを翻訳
12
+ * **用語集管理**:プロジェクトレベルの用語集により、すべての翻訳で一貫した用語を維持
13
+ * **マルチプロバイダー対応**:設定ファイルの 1 行を変更するだけで、Claude(Anthropic)、Gemini(Google)、Ollama(ローカル)を切り替え可能
14
+ * **ローカル品質管理**:構文チェック、意味チェック、LLM ジャッジチェックによる公開前の自動 QC
15
+ * **ドライランモード**:API 呼び出しを行わずに操作のプレビューが可能
16
+
17
+ ## 機能
18
+
19
+ ### 翻訳
20
+
21
+ yuuhitsu は AST(remark)パイプラインを使用して、段落レベルで Markdown ドキュメントを翻訳します:
22
+
23
+ 1. **解析** — remark が Markdown を mdast AST に解析します
24
+ 2. **抽出** — `extractBlockNodes()` が段落全体と見出しノードを Markdown 単位として収集し、各ブロック内のインライン要素(コードスパン、太字、斜体、リンク)を保持します
25
+ 3. **バッチ処理** — ノードは推定トークン数に基づいて API バッチにグループ化されます(`--max-tokens-per-batch`、デフォルト:4000 文字 ÷ 4)
26
+ 4. **翻訳** — Claude の構造化出力(tool\_use)は 1:1 の ID マッピングが保証された JSON レスポンスを返します;Gemini と Ollama はテキストモードの JSON を使用します
27
+ 5. **適用** — 翻訳されたテキストは remark を通じて再解析され、AST に書き戻されます;その後、ドキュメント全体がシリアライズされます
28
+
29
+ **なぜ段落レベルのチャンクなのか?**
30
+
31
+ 以前のリリース(0.1.x)ではテキストをインライン要素の境界で分割していました — たとえば、`"When \`AUTH\_ENABLED=true\`, a token is required."`を`"When "`と`", a token is required."`に分割するなどです。LLM は各フラグメントのコンテキストを持たず、英語と日本語の混在、フレーズの重複、意味の逆転などの問題が生じました。段落レベルのチャンク処理(0.3.0)により、このクラスのエラーが解消されます。
32
+
33
+ **保持されるもの(LLM に送信されないもの):**
34
+
35
+ * フェンスコードブロック(` ``` `...` ``` `):AST によってそのまま保持
36
+ * インラインコード(`` `...` ``):各段落ブロック内で保持
37
+ * ドキュメント構造(見出し、リスト、テーブル、HR、リンク):AST のラウンドトリップによって確定的に処理
38
+
39
+ ### 用語集の管理
40
+
41
+ プロジェクトレベルの用語集を管理して、すべての翻訳にわたって一貫した用語を徹底します。
42
+
43
+ * **`glossary init`**:サンプル用語を含む `glossary.yaml` のスケルトンを生成します
44
+ * **`glossary check`**:ドキュメント内の禁止用語や不整合な用語を検出します — Markdown(`.md`)と JSON i18n ファイル(`.json`)をサポート;違反は行番号またはキーパスとともに報告されます
45
+ * **`glossary fix`**:ドキュメント内の `severity: auto-fix` 用語を自動置換します
46
+ * **`glossary sync`**:設定されたすべての言語における翻訳カバレッジをレポートし、欠落エントリのスタブを作成します
47
+ * **`glossary review`**:すべての用語集の用語とその翻訳の Markdown レポートを生成します
48
+
49
+ `yuuhitsu.config.yaml` に `glossary` のパスが設定されている場合、`translate` コマンドは自動的に用語集を AI プロンプトに注入し、正規の用語が使用され、禁止されたバリアントが回避されることを保証します。
50
+
51
+ **重大度レベル**(`glossary.yaml` で用語ごとに設定):
52
+
53
+ | Level | Behaviour |
54
+ | ---------- | ------------------------------------------ |
55
+ | `block` | Hard error — CI fails |
56
+ | `warn` | Warning — CI passes, human review required |
57
+ | `auto-fix` | Automatically replaced by `glossary fix` |
58
+
59
+ ### ローカル品質管理
60
+
61
+ yuuhitsu には公開前 QC スクリプト(`scripts/local-qc.ts`)が同梱されており、`npm publish` のたびに実際の翻訳済みフィクスチャリポジトリに対して実行されます。これにより、ユニットテストでは検出できない構文のリグレッションとセマンティックな品質低下の両方を捕捉します。
62
+
63
+ **構文チェック:**
64
+
65
+ | Check | Description |
66
+ | --------------- | ------------------------------------------------------------------------------------ |
67
+ | bare-fence | Fenced code blocks without a language tag |
68
+ | five-axis | EN/JA mix, duplicate phrase, heading integrity, anchor validity across fixture files |
69
+ | markdownlint | Common Markdown lint rules |
70
+ | vitepress-build | VitePress build succeeds on the fixture repo |
71
+
72
+ **セマンティックチェック:**
73
+
74
+ | Check | Description |
75
+ | ----------------- | ----------------------------------------------------- |
76
+ | en-ja-mix | Paragraphs that mix English and Japanese unexpectedly |
77
+ | duplicate-phrase | Same phrase repeated twice within one paragraph |
78
+ | heading-integrity | Headings match between EN and JA versions |
79
+ | anchor-validity | Internal anchor links resolve correctly |
80
+
81
+ **LLM ジャッジ:**
82
+
83
+ * モデル:`claude-sonnet-4-6`
84
+ * 閾値:フィクスチャごとの平均スコア ≥ 4.0、フィクスチャごとの最低スコア ≥ 3.5(スケール 1〜5)
85
+ * `LOCAL_QC_FIXTURE_REPO` 内のデフォルトフィクスチャファイル全 7 件をカバー
86
+
87
+ **設定:**
88
+
89
+ ```bash
90
+ # Point to your translated fixture repository
91
+ export LOCAL_QC_FIXTURE_REPO=/home/user/workspace/my-docs # default: /home/hal/workspace/geonicdb-docs
92
+
93
+ # Run QC manually
94
+ npm run local-qc
95
+
96
+ # QC runs automatically before publish
97
+ npm publish # triggers prepublishOnly → local-qc.ts
98
+ ```
99
+
100
+ QC スクリプトはすべてのプルリクエストに対して `.github/workflows/local-qc.yml` 経由で GitHub Actions CI でも実行されます。
101
+
102
+ ## クイックスタート
103
+
104
+ ### インストール
105
+
106
+ ```bash
107
+ npm install -g @geolonia/yuuhitsu
108
+ ```
109
+
110
+ ### 基本的な使い方
111
+
112
+ ```bash
113
+ # Translate a document to Japanese
114
+ yuuhitsu translate --input README.md --lang ja
115
+
116
+ # Translate to English
117
+ yuuhitsu translate --input docs.md --lang en --output docs.en.md
118
+
119
+ # Preview without API calls
120
+ yuuhitsu translate --input README.md --lang ja --dry-run
121
+
122
+ # Use a specific config file
123
+ yuuhitsu translate --input README.md --lang ja --config ./custom.config.yaml
124
+ ```
125
+
126
+ ## 設定
127
+
128
+ プロジェクトのルートに `yuuhitsu.config.yaml` ファイルを作成します:
129
+
130
+ ```yaml
131
+ # AI Provider Selection
132
+ provider: claude # Options: claude, gemini, ollama
133
+ model: claude-sonnet-4-6
134
+
135
+ # Optional Settings
136
+ outputDir: ./translated
137
+ templates: ./templates
138
+ glossary: ./glossary.yaml # Path to glossary file (enables auto-injection during translation)
139
+ log:
140
+ enabled: true
141
+ path: ./yuuhitsu.log
142
+ ```
143
+
144
+ ### 環境変数
145
+
146
+ API 認証用の `.env` ファイルを作成するか、環境変数を設定します:
147
+
148
+ ```bash
149
+ # For Claude (Anthropic) — recommended
150
+ ANTHROPIC_API_KEY=your_api_key_here
151
+
152
+ # For Gemini (Google)
153
+ GOOGLE_API_KEY=your_api_key_here
154
+
155
+ # Ollama requires no API key (runs locally)
156
+
157
+ # For Local QC
158
+ LOCAL_QC_FIXTURE_REPO=/path/to/your/translated-docs-repo
159
+ ```
160
+
161
+ ### サポートされているプロバイダー
162
+
163
+ | Provider | SDK | Environment Variable | Use Case |
164
+ | -------- | --------------------- | -------------------- | ------------------------------------------- |
165
+ | Claude | `@anthropic-ai/sdk` | `ANTHROPIC_API_KEY` | High-quality translation, structured output |
166
+ | Gemini | `@google/genai` | `GOOGLE_API_KEY` | Fast processing, cost-effective |
167
+ | Ollama | `openai` (compatible) | *(none)* | Local execution, privacy, offline use |
168
+
169
+ ## コマンド
170
+
171
+ ### `translate`
172
+
173
+ Markdown ドキュメントを言語間で翻訳します。
174
+
175
+ **グローバルオプション**(サブコマンドの前):
176
+
177
+ * `--config <path>`:設定ファイルのパス(デフォルト:`./yuuhitsu.config.yaml`)
178
+ * `--dry-run`:API 呼び出しを行わずに実行内容を表示します
179
+ * `--verbose`:詳細な出力を有効にします
180
+
181
+ **オプション:**
182
+
183
+ * `--input <path>`(必須):入力 Markdown ファイルのパスまたは glob パターン(例:`docs/en/**/*.md`)
184
+ * `--output <path>`:出力ファイルのパス(デフォルト:`<input>.<lang>.md`)
185
+ * `--output-dir <dir>`:バッチ翻訳の出力ディレクトリ(ディレクトリ構造を保持します)
186
+ * `--lang <code>`(必須):ターゲット言語コード(例:`en`、`ja`、`zh`、`es`)
187
+ * `--max-tokens-per-batch <N>`:API バッチ呼び出しごとの推定最大トークン数(デフォルト:`4000`)。見出しが少ない大きなドキュメントの場合は増やし、API のコンテキスト制限に達した場合は減らしてください。
188
+ * `--max-chunk-lines <N>`:翻訳チャンクごとの最大行数(レガシーフォールバック;デフォルト:`150`)。AST パスがバイパスされた場合にのみ使用されます。
189
+
190
+ **単一ファイルの例:**
191
+
192
+ ```bash
193
+ yuuhitsu translate \
194
+ --input ./docs/guide.md \
195
+ --output ./docs/guide.ja.md \
196
+ --lang ja \
197
+ --max-tokens-per-batch 4000
198
+ ```
199
+
200
+ **バッチ翻訳の例:**
201
+
202
+ ```bash
203
+ yuuhitsu translate \
204
+ --input "docs/en/**/*.md" \
205
+ --output-dir docs/ja \
206
+ --lang ja
207
+ ```
208
+
209
+ ### `glossary`
210
+
211
+ 用語の一貫性を保つためにプロジェクトの用語集を管理します。
212
+
213
+ #### `glossary init`
214
+
215
+ 現在のディレクトリに `glossary.yaml` のスケルトンを生成します。
216
+
217
+ **オプション:**
218
+
219
+ * `--output <path>`:用語集ファイルの出力パス(デフォルト:`glossary.yaml`)
220
+ * `--force`:既存の用語集ファイルを上書きする
221
+
222
+ ```bash
223
+ yuuhitsu glossary init
224
+ yuuhitsu glossary init --output ./docs/glossary.yaml
225
+ ```
226
+
227
+ #### `glossary check`
228
+
229
+ ドキュメント内の禁止用語や不統一な用語を検出します。
230
+
231
+ Markdown(`.md`)と JSON i18n ファイル(`.json`)の両方をサポートします。`.json` ファイルを指定した場合、違反はキーパス(例:`dashboard.title`)として報告されます。
232
+
233
+ **スキップされる箇所(チェック対象外):**
234
+
235
+ * フェンスコードブロック(` ``` `...` ``` `)
236
+ * インラインコード(`` `...` ``)
237
+ * URL(`http://` / `https://`)
238
+ * フロントマター(`---`...`---`)
239
+ * Markdown リンクの URL パス部分
240
+
241
+ **オプション:**
242
+
243
+ * `--input <file>`(必須):チェック対象のドキュメントファイル(Markdown または JSON i18n ファイル)
244
+ * `--glossary <path>`(必須):用語集ファイルのパス
245
+ * `--lang <code>`(必須):チェックする言語コード(例:`ja`、`en`)
246
+ * `--severity-filter <levels>`:報告する重要度レベルをカンマ区切りで指定(例:`block,warn`)。デフォルト:全レベル。
247
+ * `--format <format>`:出力形式:`text`、`json`、`sarif`(デフォルト:`text`)
248
+
249
+ ```bash
250
+ # Check a Markdown document
251
+ yuuhitsu glossary check --input README.md --glossary glossary.yaml --lang ja
252
+
253
+ # Check only block-level violations
254
+ yuuhitsu glossary check --input README.md --glossary glossary.yaml --lang ja --severity-filter block
255
+
256
+ # Output SARIF for GitHub Code Scanning
257
+ yuuhitsu glossary check --input README.md --glossary glossary.yaml --lang ja --format sarif
258
+
259
+ # Check a JSON i18n file
260
+ yuuhitsu glossary check --input locales/ja/common.json --glossary glossary.yaml --lang ja
261
+ ```
262
+
263
+ #### `glossary fix`
264
+
265
+ ドキュメント内の `severity: auto-fix` 用語を自動置換します。
266
+
267
+ **オプション:**
268
+
269
+ * `--input <file>`(必須):修正対象のドキュメントファイル
270
+ * `--glossary <path>`(必須):用語集ファイルのパス
271
+ * `--lang <code>`(必須):言語コード
272
+ * `--dry-run`:ファイルを変更せずに置換内容をプレビュー表示する
273
+
274
+ ```bash
275
+ yuuhitsu glossary fix --input README.md --glossary glossary.yaml --lang ja
276
+ yuuhitsu glossary fix --input README.md --glossary glossary.yaml --lang ja --dry-run
277
+ ```
278
+
279
+ #### `glossary sync`
280
+
281
+ 翻訳カバレッジを報告し、不足しているエントリのスタブを作成します。
282
+
283
+ ```bash
284
+ yuuhitsu glossary sync --glossary glossary.yaml
285
+ ```
286
+
287
+ #### `glossary review`
288
+
289
+ すべての用語集の用語とその翻訳を Markdown レポートとして生成します。
290
+
291
+ ```bash
292
+ yuuhitsu glossary review --glossary glossary.yaml
293
+ yuuhitsu glossary review --glossary glossary.yaml --output glossary-report.md
294
+ ```
295
+
296
+ ### 用語集ファイルのフォーマット
297
+
298
+ ```yaml
299
+ version: 1
300
+ languages: [ja, en]
301
+ terms:
302
+ - canonical: "API"
303
+ type: noun
304
+ translations:
305
+ ja: "API"
306
+ en: "API"
307
+ do_not_use:
308
+ ja: ["API", "えーぴーあい"]
309
+ - canonical: "webhook"
310
+ type: noun
311
+ severity: warn # block | warn | auto-fix (default: block)
312
+ translations:
313
+ ja: "Webhook"
314
+ en: "webhook"
315
+ do_not_use:
316
+ ja: ["ウェブフック"]
317
+ en: ["web hook"]
318
+ ```
319
+
320
+ | Field | Description |
321
+ | ---------------------- | ------------------------------------------------- |
322
+ | `version` | Schema version (currently `1`) |
323
+ | `languages` | List of language codes managed by this glossary |
324
+ | `terms[].canonical` | The authoritative (source-language) term |
325
+ | `terms[].type` | Term type (e.g., `noun`, `verb`) |
326
+ | `terms[].severity` | `block` (default), `warn`, or `auto-fix` |
327
+ | `terms[].translations` | Map of language code → translated term |
328
+ | `terms[].do_not_use` | Map of language code → list of forbidden variants |
329
+
330
+ ## 開発
331
+
332
+ ```bash
333
+ # Clone the repository
334
+ git clone https://github.com/geolonia/yuuhitsu.git
335
+ cd yuuhitsu
336
+
337
+ # Install dependencies
338
+ npm install
339
+
340
+ # Run tests
341
+ npm test
342
+
343
+ # Build the project
344
+ npm run build
345
+
346
+ # Run locally (development)
347
+ npm run dev -- translate --input test.md --lang ja
348
+ ```
349
+
350
+ ### テストの実行
351
+
352
+ ```bash
353
+ # Run all unit tests
354
+ npm test
355
+
356
+ # Watch mode
357
+ npm run test:watch
358
+
359
+ # Integration tests (requires ANTHROPIC_API_KEY)
360
+ npm run test:integration
361
+
362
+ # Type checking
363
+ npm run lint
364
+
365
+ # Local QC (requires LOCAL_QC_FIXTURE_REPO)
366
+ npm run local-qc
367
+ ```
368
+
369
+ ## 変更履歴
370
+
371
+ 完全なバージョン履歴については [CHANGELOG.md](./CHANGELOG.md) を参照してください。
372
+
373
+ **0.3.0 のハイライト:**
374
+
375
+ * 段落レベルのチャンク再設計(`extractBlockNodes`) — インライン要素の分割による EN/JA の混在、重複フレーズ、意味の逆転を排除
376
+ * トークン数ベースのバッチ処理(`--max-tokens-per-batch`、デフォルト: 4000) — 行数ベースの `--max-nodes-per-batch` を置き換え
377
+ * ローカル QC(`scripts/local-qc.ts`) — prepublishOnly フック + LLM ジャッジ(`claude-sonnet-4-6`、平均 ≥ 4.0)を使用した GitHub Actions CI
378
+
379
+ ## ライセンス
380
+
381
+ MIT — [LICENSE](./LICENSE) を参照
382
+
383
+ Copyright (c) 2026 Geolonia Inc.