kotonoha 0.3.0 → 0.4.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/CHANGELOG.md CHANGED
@@ -7,6 +7,43 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.4.1] - 2026-10-19
11
+
12
+ ### Added
13
+
14
+ - Add an Obsidian knowledge-note template and doctype guide with core
15
+ Templates variables, YAML properties, wikilinks, a callout, and tasks.
16
+ - Add an independent `obsidian-vault` skill for scoped convention discovery, note
17
+ creation, related-note suggestions, link diagnosis and approval-gated
18
+ Japanese proofreading saves on Linux local files.
19
+ - Add a locked offline launcher, content-bound plans and success receipts,
20
+ protected Obsidian syntax, and an independent 100-note acceptance fixture.
21
+
22
+ ### Changed
23
+
24
+ - Rename the development Skill from `obsidian` to `obsidian-vault`, including
25
+ its installation name and `test:obsidian-vault` runner. Historical approval
26
+ records retain their original paths; the execution contract is relocated
27
+ without changing its approved bytes.
28
+
29
+ ## [0.4.0] - 2026-10-19
30
+
31
+ ### Added
32
+
33
+ - Add duplicate-particle/word, Japanese bracket, and paragraph style-mixing
34
+ diagnostics, plus a minimal-edit `proofread` skill mode.
35
+ - Add a Markdown-aware invariant gate with protected-content checks and
36
+ required hash-bound semantic review of edits.
37
+
38
+ ### Fixed
39
+
40
+ - Avoid treating obligation expressions as double-negative errors and
41
+ conclusion questions as formulaic assertions.
42
+ - Keep shorter fence markers and fence-like info strings inside code blocks
43
+ out of prose diagnostics.
44
+ - Require the invariant gate and current semantic review to pass before
45
+ claiming Japanese prose optimization completed.
46
+
10
47
  ## [0.3.0] - 2026-09-30
11
48
 
12
49
  ### Added
package/README-ja.md CHANGED
@@ -53,10 +53,29 @@ kotonohaは文書構造と技術的な不変条件を固定してから日本語
53
53
  | 証拠に基づく解説・提言 | 技術・事業White Paper | `white-paper` |
54
54
  | 情報提供依頼 | RFI | `rfi` |
55
55
  | 提案依頼 | RFP | `rfp` |
56
+ | ナレッジノート | Obsidianのノート、再利用可能なテンプレート | `obsidian` |
56
57
  | 技術記事 | Zenn記事 | `zenn` |
57
58
  | 技術記事 | Qiita記事 | `qiita` |
58
59
 
59
- 再利用可能なテンプレートには、README、設計判断、ユーザーマニュアル、PR説明があります。要件定義、システム設計、テスト、運用、移行、セキュリティの各文書にも対応しています。技術提案、Blueprint、White Paper、RFI、RFP、Qiita記事のテンプレートも含まれます。すべての文書種別には、`skills/tech-writer/references/doctypes/`配下に専用の構成ガイドとレビューチェックリストがあります。
60
+ 再利用可能なテンプレートには、README、設計判断、ユーザーマニュアル、PR説明があります。要件定義、システム設計、テスト、運用、移行、セキュリティの各文書にも対応しています。技術提案、Blueprint、White Paper、RFI、RFP、Obsidianノート、Qiita記事のテンプレートも含まれます。すべての文書種別には、`skills/tech-writer/references/doctypes/`配下に専用の構成ガイドとレビューチェックリストがあります。
61
+
62
+ Obsidianでは、[`obsidian.md`](skills/tech-writer/assets/templates/obsidian.md)をVault内のテンプレートフォルダーにコピーし、標準のTemplatesプラグインでそのフォルダーを指定します。名前を付けた空のノートで **Templates: Insert template** を実行すると、タイトルと挿入日が展開されます。プロパティ、内部リンク、コールアウト、タスクを含み、コミュニティプラグインは不要です。kotonohaはVaultの設定を変更しません。詳しい設定方法と制約は、[Obsidianガイド](skills/tech-writer/references/doctypes/obsidian.md)を参照してください。
63
+
64
+ ## Obsidian Vaultの操作
65
+
66
+ 専用の`obsidian-vault`は、Vaultの規約確認、ノート新規作成、関連ノート候補、内部リンク診断、日本語添削を担当します。
67
+ 文書構成はtech-writer、日本語表現はjapanese-proseを利用するため、3つのSkillを同じ場所へ導入してください。
68
+ 初期対応はLinux、CPython 3.12、uvです。Obsidianアプリ、MCP、プラグインには依存しません。
69
+
70
+ Vault、読み取り範囲、モデルに渡す情報を利用者が明示し、保存する場合は正確な差分と計画を承認します。
71
+ 保存は専用CLIのapplyだけで行い、添削時の記法保護とハッシュ付き意味レビューを迂回しません。
72
+ 未解決リンクを誤りと断定せず、自動修復もしません。
73
+ 処理はオフライン・lock付きで起動します。依存関係の初回準備は別途の許可が必要です。
74
+ 依頼例、コマンド、コピーの保持と復旧は[操作ガイド](skills/obsidian-vault/references/workflow.md)を参照してください。
75
+
76
+ 保存は確認できたローカルFSに限定し、シンボリックリンク、維持できない属性、複数ハードリンクを拒否します。
77
+ 拡張属性付きファイルも保存非対応であり、SELinuxラベルなどの削除を回避策にしません。
78
+ 最終照合直後の外部編集やLLMの誤判断は完全には防げず、ホストを隔離する機能でもありません。
60
79
 
61
80
  ## consulting-analystの機能
62
81
 
@@ -97,7 +116,7 @@ White Paper向けの分析を作成して
97
116
 
98
117
  - GitHub Copilot CLIがインストールされていること
99
118
  - tech-writerの構造lintを実行する場合はPython 3.9以上
100
- - 同梱`japanese-prose`の文章lint、読解負荷分析、アウトライン抽出、用語検査を実行する場合はPython 3.10以上と`uv`。GiNZA、`ja_ginza`、spaCyは初回実行時に`uv`が解決
119
+ - 同梱`japanese-prose`の文章lint、読解負荷分析、アウトライン抽出、用語検査、編集前後の不変条件検査を実行する場合はPython 3.10以上と`uv`。GiNZA、`ja_ginza`、spaCy、Markdown解析用の依存関係は、各スクリプトの初回実行時に`uv`が解決
101
120
 
102
121
  ### npmからインストール
103
122
 
@@ -110,19 +129,20 @@ npx kotonoha install
110
129
 
111
130
  ### 同梱スキルをまとめてインストール
112
131
 
113
- `kotonoha install`は、まだ存在しない同梱スキルをすべてインストールします。次のコマンドは、`consulting-analyst`、`tech-writer`、`japanese-prose`、`presentation-planner`を`.github/skills/`へインストールします。
132
+ `kotonoha install`は、まだ存在しない同梱スキルをすべてインストールします。次のコマンドは、`consulting-analyst`、`tech-writer`、`japanese-prose`、`obsidian-vault`、`presentation-planner`を`.github/skills/`へインストールします。
114
133
 
115
134
  ```bash
116
135
  npm install --save-dev kotonoha
117
136
  npx kotonoha install --skill all
118
137
  ```
119
138
 
120
- `--skill all`が既定値であるため、`npx kotonoha install`も同じ動作です。4つのスキルがインストールされたことを確認します。
139
+ `--skill all`が既定値であるため、`npx kotonoha install`も同じ動作です。5つのスキルがインストールされたことを確認します。
121
140
 
122
141
  ```bash
123
142
  test -f .github/skills/consulting-analyst/SKILL.md
124
143
  test -f .github/skills/tech-writer/SKILL.md
125
144
  test -f .github/skills/japanese-prose/SKILL.md
145
+ test -f .github/skills/obsidian-vault/SKILL.md
126
146
  test -f .github/skills/presentation-planner/SKILL.md
127
147
  ```
128
148
 
@@ -136,6 +156,10 @@ npx kotonoha install --skill all --force
136
156
 
137
157
  kotonohaには独自開発の`japanese-prose`が同梱されるため、文章最適化スキルを別途インストールする必要はありません。`npx kotonoha install`により`tech-writer`と同じスキルルートへ配置され、GiNZAを使った文章lint、読解負荷検査、用語抽出、アウトライン検査、反復的な文章レビューをローカルで実行できます。この実装はkotonoha向けにゼロから開発しており、`natural-japanese`のソースコードを含みません。GiNZAの依存関係とライセンス情報は`skills/japanese-prose/NOTICE.md`に記録しています。
138
158
 
159
+ 文章lintでは、隣接する助詞・単語の重複、和文括弧の不整合、同一段落内の敬体・常体の混在も確認します。指摘は自動置換の指示ではなく、文脈を確認する対象です。`proofread`モードでは、任意の言い換えを避け、誤字と文法上の誤りだけを最小限に修正します。100点満点のスコアは確認箇所を探す補助であり、訂正精度や品質の保証ではありません。
160
+
161
+ 編集前の原文は変更せずに保存します。同梱の`scripts/invariants.py`が、数値、識別子、コード、表、リンク、指定された固有名詞・専門用語などの変更を検査します。編集した文章には、原文と編集後のファイルのハッシュに対応した意味保存レビューが必要です。機械的な一致だけでは、意味が保たれたとは判定しません。レビュー形式と終了コードは、[`review-workflow.md`](skills/japanese-prose/references/review-workflow.md)を参照してください。
162
+
139
163
  自然言語で指示するときは、GiNZAを明示する必要はありません。「日本語文書を自然にする」「読みやすくする」「簡潔にする」「AIらしい定型表現を減らす」といった依頼をすると、同梱の文章最適化ワークフローが呼び出されます。
140
164
 
141
165
  ```text
@@ -150,6 +174,7 @@ README-ja.mdの日本語を自然で読みやすい表現に修正して
150
174
  目的に応じて、次のようにモードを指定できます。
151
175
 
152
176
  - ファイルを修正する: `README-ja.mdの日本語表現を最適化して`
177
+ - 誤りだけを修正する: `README-ja.mdをproofreadモードで校正して。任意の言い換えはせず、誤字と文法上の誤りだけを最小限に修正して`
153
178
  - 修正せずにレビューする: `README-ja.mdの日本語をレビューして。ファイルは修正しないで`
154
179
  - 採点だけ行う: `README-ja.mdの日本語表現を100点満点で採点して`
155
180
  - すべての診断を実行する: `README-ja.mdをfullモードで日本語表現最適化して`
@@ -157,7 +182,9 @@ README-ja.mdの日本語を自然で読みやすい表現に修正して
157
182
 
158
183
  新しい日本語文書では、`このリポジトリの日本語READMEを作成して`のように依頼すると、`tech-writer`が下書きと構造レビューを行い、rubber-duck reviewの前にGiNZAベースの文章最適化を実行します。文章最適化を確実に指定する場合は、`<ファイル名>を技術文書として作成または修正し、GiNZAによる日本語表現最適化まで実施して`と指示します。
159
184
 
160
- 既定のインストール先は、現在のプロジェクトの`.github/skills/consulting-analyst`、`.github/skills/tech-writer`、`.github/skills/japanese-prose`、`.github/skills/presentation-planner`です。スキルを1つだけインストールする場合や、対応している別のディレクトリを使用する場合は、次のように指定します。
185
+ 既定のインストール先は、現在のプロジェクトの`.github/skills/`です。
186
+ consulting-analyst、tech-writer、japanese-prose、obsidian-vault、presentation-plannerをそれぞれのサブディレクトリに配置します。
187
+ スキルを1つだけインストールする場合や、対応している別のディレクトリを使用する場合は、次のように指定します。
161
188
 
162
189
  ```bash
163
190
  npx kotonoha install --skill consulting-analyst
package/README.md CHANGED
@@ -9,6 +9,8 @@ technical documents without losing the reader. `japanese-prose` improves
9
9
  Japanese wording with GiNZA-based diagnostics. `presentation-planner` turns
10
10
  source material into a reusable presentation scenario, slide outline, design
11
11
  specification, and handoff for a dedicated PPTX creation skill.
12
+ The `obsidian-vault` skill applies scoped Vault conventions and link diagnostics
13
+ and saves new or proofread notes only after explicit plan approval.
12
14
 
13
15
  [English](./README.md) | [日本語](./README-ja.md)
14
16
 
@@ -54,8 +56,8 @@ review.
54
56
  descriptions/commit messages/issue reports, release notes, user manuals,
55
57
  code comments, requirements definitions, system designs, test plans,
56
58
  operations runbooks, migration plans, security designs, technical proposals,
57
- Blueprints, White Papers, RFI/RFP procurement documents, and Qiita/Zenn
58
- articles
59
+ Blueprints, White Papers, RFI/RFP procurement documents, Obsidian notes
60
+ and templates, and Qiita/Zenn articles
59
61
  - Doctype-specific structure and checklists to guide writing
60
62
  - Original GiNZA-based `japanese-prose` lint, reading-load review, terminology
61
63
  checks, and iterative prose optimization without changing IDs, facts,
@@ -95,16 +97,47 @@ review.
95
97
  | Evidence-led publication | Technical or business White Paper | `white-paper` |
96
98
  | Request for information | RFI | `rfi` |
97
99
  | Request for proposal | RFP | `rfp` |
100
+ | Vault knowledge note | Obsidian note or reusable template | `obsidian` |
98
101
  | Technical article | Zenn article | `zenn` |
99
102
  | Technical article | Qiita article | `qiita` |
100
103
 
101
104
  Reusable templates are included for README, design decisions, user manuals,
102
105
  PR descriptions, requirements definitions, system designs, test plans,
103
106
  operations runbooks, migration plans, security designs, technical proposals,
104
- Blueprints, White Papers, RFI, RFP, and Qiita articles. Every supported
107
+ Blueprints, White Papers, RFI, RFP, Obsidian notes, and Qiita articles. Every supported
105
108
  doctype includes dedicated structure guidance and a review checklist under
106
109
  `skills/tech-writer/references/doctypes/`.
107
110
 
111
+ For Obsidian, copy
112
+ [`obsidian.md`](skills/tech-writer/assets/templates/obsidian.md) into your
113
+ vault's template folder and select that folder in the core Templates plugin.
114
+ Create and name an empty note, then run **Templates: Insert template**.
115
+ The template includes YAML properties, core title/date variables, wikilinks,
116
+ a callout, and a task; no community plugins are required. Kotonoha does not
117
+ configure your vault. See the [Obsidian guide](skills/tech-writer/references/doctypes/obsidian.md)
118
+ for setup, placeholder handling, and limitations.
119
+
120
+ ## Working with an Obsidian Vault
121
+
122
+ Use the dedicated `obsidian-vault` skill for Vault conventions, note creation,
123
+ related-note proposals, internal-link diagnosis and Japanese proofreading.
124
+ Its local CLI requires Linux, CPython 3.12 and uv; it does not require
125
+ Obsidian, MCP or plugins. Install `tech-writer` and `japanese-prose` alongside
126
+ it for creation and proofreading, or install all skills.
127
+
128
+ The user explicitly selects the Vault, read scopes and model-context consent.
129
+ Only `apply` writes a single approved `.md` note; a hash-bound plan, protected
130
+ syntax checks and an exact semantic review are required for changed edits.
131
+ Unresolved links are observations, not automatic repair requests.
132
+ Runtime commands use `uv run --offline --locked --python 3.12`; dependency
133
+ bootstrap needs separate consent. See the [Japanese workflow guide](skills/obsidian-vault/references/workflow.md)
134
+ for requests, command examples, data retention and recovery.
135
+
136
+ Saving is limited to verified local filesystems and conservatively refuses
137
+ symlinks, unsupported ownership/modes, multiple hard links and all xattrs,
138
+ including SELinux labels. Post-check external edits and LLM mistakes cannot
139
+ be eliminated. The skill is not a host sandbox.
140
+
108
141
  ## What consulting-analyst does
109
142
 
110
143
  - Defines the decision-maker, decision question, outcome, scope, and evidence
@@ -155,7 +188,8 @@ handoff without inventing missing evidence.
155
188
 
156
189
  - GitHub Copilot CLI installed
157
190
  - Python 3.9+ for tech-writer's structural lint
158
- - Python 3.10+ and `uv` for the bundled GiNZA diagnostics such as prose lint,
191
+ - Python 3.10+ and `uv` for the edit-invariant gate and bundled GiNZA
192
+ diagnostics such as prose lint,
159
193
  reading-load analysis, outline extraction, and terminology checks; `uv`
160
194
  resolves GiNZA, `ja_ginza`, and spaCy on first use
161
195
 
@@ -173,7 +207,7 @@ npx kotonoha install
173
207
 
174
208
  `kotonoha install` installs every packaged skill that is not already present.
175
209
  The following commands install `consulting-analyst`, `tech-writer`,
176
- `japanese-prose`, and `presentation-planner` into `.github/skills/`:
210
+ `japanese-prose`, `obsidian-vault`, and `presentation-planner` into `.github/skills/`:
177
211
 
178
212
  ```bash
179
213
  npm install --save-dev kotonoha
@@ -181,12 +215,13 @@ npx kotonoha install --skill all
181
215
  ```
182
216
 
183
217
  `--skill all` is the default, so `npx kotonoha install` has the same behavior.
184
- Confirm that all four skills were installed:
218
+ Confirm that all five skills were installed:
185
219
 
186
220
  ```bash
187
221
  test -f .github/skills/consulting-analyst/SKILL.md
188
222
  test -f .github/skills/tech-writer/SKILL.md
189
223
  test -f .github/skills/japanese-prose/SKILL.md
224
+ test -f .github/skills/obsidian-vault/SKILL.md
190
225
  test -f .github/skills/presentation-planner/SKILL.md
191
226
  ```
192
227
 
@@ -209,6 +244,20 @@ scratch for kotonoha and does not include `natural-japanese` source code.
209
244
  GiNZA dependency and license information is recorded in
210
245
  `skills/japanese-prose/NOTICE.md`.
211
246
 
247
+ The lint also flags adjacent duplicate particles/words, Japanese bracket
248
+ mismatches, and polite/plain style mixing within a paragraph. Findings are
249
+ review targets, not automatic replacements. Use `proofread` mode for minimal
250
+ typo/grammar corrections without optional stylistic rewriting. The 0–100
251
+ score is a triage aid, not correction accuracy or a quality certificate.
252
+
253
+ Before editing, the workflow saves an immutable original. The bundled
254
+ `scripts/invariants.py` checks protected content and requires a hash-bound
255
+ semantic review of changed prose. Numbers, identifiers, code, tables, links,
256
+ and caller-supplied proper names/domain terms cannot be silently changed.
257
+ Mechanical equality alone does not establish preserved meaning. See
258
+ [`review-workflow.md`](skills/japanese-prose/references/review-workflow.md)
259
+ for the review format and gate exit codes.
260
+
212
261
  You do not need to name GiNZA explicitly in a natural-language request.
213
262
  Requests to make a Japanese document more natural, readable, concise, or less
214
263
  formulaic invoke the bundled prose-optimization workflow. For example:
@@ -225,6 +274,7 @@ and repetitive AI-like phrasing, then fix the findings.
225
274
  You can specify the intended mode more precisely:
226
275
 
227
276
  - Edit the file: `Optimize the Japanese prose in README-ja.md.`
277
+ - Correct errors only: `Proofread README-ja.md; make minimal typo/grammar corrections without stylistic rewrites.`
228
278
  - Review without editing: `Review the Japanese in README-ja.md, but do not modify the file.`
229
279
  - Score only: `Score the Japanese prose in README-ja.md out of 100.`
230
280
  - Run every diagnostic: `Run the full Japanese prose optimization workflow on README-ja.md.`
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "kotonoha",
3
- "version": "0.3.0",
4
- "description": "GitHub Copilot CLI skills for consulting analysis, technical writing, Japanese prose, and PPTX planning.",
3
+ "version": "0.4.1",
4
+ "description": "GitHub Copilot CLI skills for consulting analysis, technical writing, Japanese prose, Obsidian vaults, and PPTX planning.",
5
5
  "license": "MIT",
6
6
  "author": "nahisaho",
7
7
  "repository": {
@@ -17,7 +17,8 @@
17
17
  },
18
18
  "scripts": {
19
19
  "test": "node --test",
20
- "test:ginza": "uv run skills/japanese-prose/scripts/test_engine.py"
20
+ "test:ginza": "uv run skills/japanese-prose/scripts/test_engine.py",
21
+ "test:obsidian-vault": "uv run --offline --locked --python 3.12 skills/obsidian-vault/scripts/test_vault.py"
21
22
  },
22
23
  "engines": {
23
24
  "node": ">=18"
@@ -32,6 +33,7 @@
32
33
  "strategy",
33
34
  "documentation",
34
35
  "markdown",
36
+ "obsidian",
35
37
  "presentation",
36
38
  "pptx",
37
39
  "powerpoint",
@@ -1,4 +1,4 @@
1
- # GiNZA dependency notice
1
+ # Diagnostic dependency notices
2
2
 
3
3
  This skill is an original kotonoha implementation and does not include source
4
4
  code from `coji/natural-japanese`.
@@ -15,3 +15,9 @@ datasets.
15
15
  The implementation targets GiNZA 5.2.x and uses token surface forms, lemmas,
16
16
  universal part-of-speech tags, dependency relationships, sentence boundaries,
17
17
  and named-entity labels.
18
+
19
+ The edit-invariant gate uses
20
+ [markdown-it-py](https://github.com/executablebooks/markdown-it-py), distributed
21
+ under the MIT License, to parse Markdown without treating short fences
22
+ inside longer fenced code blocks as prose. Its dependencies are resolved by
23
+ `uv` when `scripts/invariants.py` is run.
@@ -6,10 +6,10 @@ description: >-
6
6
  reviewing, or scoring Japanese prose; when the user asks for more natural,
7
7
  readable, concise, or less AI-like Japanese; or when tech-writer delegates
8
8
  its sentence-level quality pass. Owns wording, sentence rhythm, reading
9
- load, terminology review, and formulaic-expression detection. Does not own
10
- technical-document structure or presentation storylines.
9
+ load, typo and grammar review, terminology, and edit-invariant checks.
10
+ Does not own technical-document structure or presentation storylines.
11
11
  license: MIT
12
- argument-hint: "[write|review|score] [quick|full] <target file or request>"
12
+ argument-hint: "[write|proofread|review|score] [quick|full] <target file or request>"
13
13
  ---
14
14
 
15
15
  # japanese-prose
@@ -39,6 +39,8 @@ acceptance criteria, approval states, or normative force.
39
39
  - `write`: write or rewrite Japanese prose. Use `quick` unless the document
40
40
  is external-facing, high-risk, or longer than roughly 10,000 Japanese
41
41
  characters.
42
+ - `proofread`: correct demonstrable typos and grammatical errors with minimal
43
+ edits. Do not perform optional stylistic rewrites or chase a higher score.
42
44
  - `review`: report problems and proposed corrections without editing.
43
45
  - `score`: run diagnostics and report the 0–100 score without rewriting.
44
46
  - `quick`: run prose lint once, review findings in context, edit, and rerun
@@ -50,33 +52,57 @@ acceptance criteria, approval states, or normative force.
50
52
  ## Workflow
51
53
 
52
54
  1. Read the target, audience, intended outcome, and calling skill's frozen
53
- invariants.
55
+ invariants. Before editing, save an immutable copy of the entire original
56
+ file as `<workdir>/prose-original.md`. Keep this separate from diagnostic
57
+ baselines, which may change between rounds.
54
58
  2. Read `references/writing-guidelines.md` before generating or rewriting
55
- prose.
59
+ prose. Resolve `<japanese-prose-dir>` to the directory containing this
60
+ loaded skill; do not assume the shell is running in that directory.
56
61
  3. Run the GiNZA prose diagnostic:
57
62
 
58
63
  ```bash
59
- uv run scripts/lint.py <target-file> --genre tech --json > <workdir>/prose-baseline.json
64
+ uv run <japanese-prose-dir>/scripts/lint.py <target-file> --genre tech --json > <workdir>/prose-baseline.json
60
65
  ```
61
66
 
62
67
  4. For `full` mode, also run:
63
68
 
64
69
  ```bash
65
- uv run scripts/lint.py <target-file> --genre tech --reading-load --json
66
- uv run scripts/outline.py <target-file>
67
- uv run scripts/terms.py <target-file> --json
70
+ uv run <japanese-prose-dir>/scripts/lint.py <target-file> --genre tech --reading-load --json
71
+ uv run <japanese-prose-dir>/scripts/outline.py <target-file>
72
+ uv run <japanese-prose-dir>/scripts/terms.py <target-file> --json
68
73
  ```
69
74
 
70
- 5. Classify each finding as `fix` or `keep`. A detector identifies a review
71
- target; it does not authorize blind replacement.
72
- 6. Apply only fixes that improve the intended reader's understanding while
73
- preserving the frozen invariants.
75
+ 5. Read the entire prose for typos, particle errors, subject/predicate
76
+ mismatches, and incorrect inflections even when lint reports no findings.
77
+ Classify each finding as `fix` or `keep`. A detector identifies a review
78
+ target; it does not authorize blind replacement. Adjacent duplicate
79
+ particles/words, Japanese bracket mismatches, and within-paragraph style
80
+ mixing are proofreading targets, not proof of an error.
81
+ 6. Correct demonstrable errors first. In `write` mode, then consider optional
82
+ wording changes that serve the reader's stated goal. Keep these separate
83
+ from necessary corrections. Preserve acceptable wording when a change
84
+ merely substitutes a synonym or removes a legitimate qualification.
85
+ Never infer a factual or proper-name correction from plausibility alone.
74
86
  7. Rerun the prose diagnostic with
75
87
  `--baseline <workdir>/prose-baseline.json` to classify new, persisting,
76
88
  and resolved findings. Replace the baseline only after recording the
77
89
  decisions for the current round.
78
- 8. Stop when every finding has a decision, no new actionable finding appears,
79
- and the document passes the checks in `references/review-workflow.md`.
90
+ 8. Run the edit-invariant gate against the immutable original:
91
+
92
+ ```bash
93
+ uv run <japanese-prose-dir>/scripts/invariants.py <workdir>/prose-original.md <target-file> --protect <proper-name-or-domain-term> --json
94
+ ```
95
+
96
+ Repeat `--protect` for each frozen proper name or domain term; omit it only
97
+ when there are none. Exit 2 blocks changed protected content. Any edit
98
+ requires a contextual semantic review, even if all mechanical checks
99
+ pass: exit 3 means that review is pending or rejected, not completion.
100
+ Follow `references/review-workflow.md` to record the hash-bound review,
101
+ then rerun with `--review <workdir>/semantic-review.json --json`.
102
+ Recheck after every subsequent edit; a stale review cannot approve it.
103
+ 9. Stop only when every finding has a decision, no new actionable finding
104
+ appears, and the invariant gate returns `passed`. If the gate cannot run,
105
+ report the failure rather than declaring completion.
80
106
 
81
107
  Allow at most three edit-and-diagnose rounds per invocation. If actionable
82
108
  findings or invariant violations remain, report that the optimization did not
@@ -108,4 +134,7 @@ Report:
108
134
  - findings fixed and findings deliberately kept
109
135
  - any skipped diagnostic and its reason
110
136
  - invariant verification result
137
+ - necessary corrections versus optional wording changes
138
+ - semantic review status and any remaining uncertainty; mechanical equality
139
+ is not a guarantee of preserved meaning
111
140
  - `completed` or `did not converge`
@@ -40,6 +40,61 @@ Read only headings and paragraph openings. The argument must still be
40
40
  predictable. Then read the finished prose continuously and verify that local
41
41
  rewrites did not damage transitions or create repeated explanations.
42
42
 
43
+ ## Require a semantic review of edits
44
+
45
+ Run `scripts/invariants.py` on the immutable pre-edit file and the edited
46
+ file. It protects numbers and known quantity units in occurrence order,
47
+ uppercase identifiers, URL/link destinations, frontmatter, heading levels,
48
+ inline code, fenced/indented code, Markdown tables, HTML, and caller-supplied
49
+ `--protect` terms. The Markdown parser recognizes nested and long fences.
50
+ The check is conservative: it may block a legitimate reorder or protected
51
+ content correction. Such changes need separate authorization, not a
52
+ reviewer override of a failed invariant.
53
+
54
+ Mechanical equality cannot establish equivalent meaning. For every changed
55
+ passage, compare the original and edited text, including nearby context:
56
+
57
+ - `actors`: who performs or receives each action is unchanged
58
+ - `negation`: polarity and the scope of negation are unchanged
59
+ - `conditions`: prerequisites, exceptions, acceptance criteria, and approval states are unchanged
60
+ - `modality`: obligations, recommendations, permissions, and uncertainty are unchanged
61
+ - `scope`: limitations such as 「だけ」「すべて」「少なくとも」 are unchanged
62
+ - `causality`: causal and temporal relationships are unchanged
63
+ - `quantity_bindings`: each quantity still refers to the same object or action
64
+ - `terminology`: proper names and domain concepts are unchanged
65
+ - `structure`: section identity, order, quoted meaning, and traceability are unchanged
66
+
67
+ Record the review as JSON. Copy `before_sha256` and `after_sha256` from the
68
+ gate output, identify the actual reviewer, and set a check to `true` only
69
+ after inspecting it. Do not infer approval from a score, an unchanged token
70
+ count, or the absence of warnings. A review can be performed by the agent or
71
+ a human, but an agent review is not a human approval or a semantic proof.
72
+
73
+ ```json
74
+ {
75
+ "before_sha256": "<hash from the gate>",
76
+ "after_sha256": "<hash from the gate>",
77
+ "reviewer": "<actual reviewer identifier>",
78
+ "checks": {
79
+ "actors": false,
80
+ "negation": false,
81
+ "conditions": false,
82
+ "modality": false,
83
+ "scope": false,
84
+ "causality": false,
85
+ "quantity_bindings": false,
86
+ "terminology": false,
87
+ "structure": false
88
+ }
89
+ }
90
+ ```
91
+
92
+ Rerun the gate with `--review <review-file>`. Exit codes are 0 for `passed`,
93
+ 1 for input/runtime errors, 2 for protected-content violations, and 3 for
94
+ missing, stale, incomplete, or rejected semantic reviews. Subsequent edits
95
+ invalidate the review. If equivalence is uncertain, keep the original
96
+ wording or report the unresolved concern.
97
+
43
98
  ## Convergence
44
99
 
45
100
  The review is complete when:
@@ -47,4 +102,6 @@ The review is complete when:
47
102
  - every finding has a `fix` or `keep` decision
48
103
  - rerunning diagnostics produces no new actionable finding
49
104
  - frozen invariants match the pre-edit document
105
+ - `scripts/invariants.py` returns `passed` with a current semantic review
106
+ for changed text
50
107
  - the reader can reach the requested outcome without an unstated inference
@@ -22,3 +22,9 @@ A high score does not prove that facts are correct, the argument is complete,
22
22
  or the prose is natural. A low score does not require every finding to be
23
23
  changed. Always report the finding categories and contextual decisions beside
24
24
  the score.
25
+
26
+ Proofreading findings and style/readability findings contribute to the same
27
+ triage score, but they are not interchangeable measures of quality. Report
28
+ the categories separately. Do not use this score as typo-detection recall,
29
+ correction accuracy, semantic fidelity, or evidence that an LLM-assisted
30
+ rewrite is better. A correctly repaired typo may leave the score unchanged.
@@ -76,10 +76,14 @@ def iter_content_lines(text: str) -> Iterable[tuple[int, str]]:
76
76
 
77
77
  fence = FENCE_RE.match(raw)
78
78
  if fence:
79
- marker = fence.group(1)[0]
79
+ marker = fence.group(1)
80
80
  if not fence_marker:
81
81
  fence_marker = marker
82
- elif marker == fence_marker:
82
+ elif (
83
+ marker[0] == fence_marker[0]
84
+ and len(marker) >= len(fence_marker)
85
+ and not raw[fence.end():].strip()
86
+ ):
83
87
  fence_marker = ""
84
88
  yield index, ""
85
89
  continue