asciidoc-pubkit 0.8.7 → 1.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.
data/README.md CHANGED
@@ -1,4 +1,3 @@
1
- ![](https://img.shields.io/badge/status-Work%20In%20Progress-8A2BE2)
2
1
  ![GitHub tag (latest SemVer)](https://img.shields.io/github/v/tag/cybergarage/asciidoc-pubkit)
3
2
  [![Gem Version](https://img.shields.io/gem/v/asciidoc-pubkit.svg)](https://rubygems.org/gems/asciidoc-pubkit)
4
3
  [![Build Status](https://github.com/cybergarage/asciidoc-pubkit/actions/workflows/test.yml/badge.svg)](https://github.com/cybergarage/asciidoc-pubkit/actions/workflows/test.yml)
@@ -7,68 +6,55 @@
7
6
 
8
7
  A toolkit for authoring and reviewing AsciiDoc books.
9
8
 
10
- Version 0.8.7 provides shared Japanese technical writing criteria, an authoring
11
- prompt, separate prose, heading, and list review prompts, manuscript scoring, and
12
- baseline verification for edited manuscripts, plus explicit prose-only mechanical
13
- replacements using a limited prh-format rule set.
9
+ Version 1.0.0 provides document inspection, explicit prose-only mechanical
10
+ replacements, and Japanese manuscript review. Inspect a book's outline,
11
+ metadata, and local cross-references; preview and apply your replacement rules;
12
+ then review and verify edits against a saved baseline.
13
+
14
14
  The CLI, diagnostics, documentation, and generated instructions are in English.
15
- Japanese text is retained in manuscript excerpts, rule dictionaries, and fixtures.
15
+ Japanese manuscript excerpts and rule terms retain their original text.
16
16
 
17
17
  ## Available features
18
18
 
19
- The following commands are available in version 0.8.7.
19
+ The following commands are available in version 1.0.0.
20
20
 
21
21
  | Feature | Commands | Behavior |
22
22
  | --- | --- | --- |
23
- | [Writing criteria and prompts](#writing-commands) | `writing criteria`, `writing prompt` | Print Japanese prose criteria or generate a writing prompt without a manuscript or MeCab |
24
- | [Replacement preview](#prose-replacements) | `replace check`, `replace diff` | Report mechanical replacement candidates or preview a diff for mapped running prose; preserve source files |
25
- | [Replacement application](#prose-replacements) | `replace apply` | Apply author-supplied rules after checking protected content and document structure; no MeCab or AI required |
26
- | [Prose review](#review-workflow) | `review scan` | Collect mapped Japanese running prose and contextual review candidates with MeCab/IPADIC by default |
27
- | [List review](#list-review) | `review scan --scope lists` | Review mapped single-line list text in a separate session |
28
- | [Heading review](#heading-review) | `review scan --scope headings` | Collect editable section titles separately, retaining the outline and read-only body evidence |
29
- | [Review prompts](#prompt) | `review prompt` | Generate one Markdown prompt from a saved session for review and editing by an external reviewer |
30
- | [Baseline verification](#verify) | `review verify` | Check edited sources against a saved baseline for mechanical preservation; meaning is not verified |
31
- | [Manuscript scoring](#score-an-asciidoc-manuscript) | `review score` | Report a prose candidate-density score; explicit `--agent codex` or `--agent claude` optionally invokes a local AI CLI for readability ratings |
32
-
33
- Version 0.8.1 additionally supports nested replacement-rule imports,
34
- omitted/null `rules`, arrays in `pattern`, `/i`, and limited ECMAScript word
35
- boundaries. See [Prose replacements](#prose-replacements) for supported syntax
36
- and preservation limits. Only `replace apply` edits manuscripts directly;
37
- review prompts supply instructions for an external reviewer.
38
-
39
- ## Status
40
-
41
- Version 0.6.3 adds separate heading review with `review scan --scope headings`.
42
- See [Heading review](#heading-review).
43
-
44
- Version 0.8.0 adds explicit prose replacements with `replace apply`;
45
- see [Prose replacements](#prose-replacements). Review and scoring do not edit
46
- manuscripts. The CLI does not publish books. EPUB, image,
47
- and book scaffolding commands are planned extensions, not available features.
48
-
49
- Ruby 3.2 or later is required. Asciidoctor is installed as a gem dependency.
50
- Starting with version 0.1.1, the default review backend requires the external MeCab
51
- command and a UTF-8 IPADIC dictionary. Node.js and textlint are not required.
52
- Explicit `--tokenizer literal` mode provides limited phrase matching without MeCab.
53
-
54
- Version 0.6.2 also provides `review score FILE` for a manuscript score.
55
- It uses local candidate analysis by default; `--agent codex` or `--agent claude`
56
- explicitly asks an installed CLI to evaluate readability and may connect to its
57
- configured model provider. No scoring mode edits manuscripts.
58
-
59
- Version 0.1.1 added morphological analysis. Version 0.1.0 used literal matching.
60
-
61
- The CLI has `writing`, `review`, and `replace` command groups. All default to `--lang ja`.
62
- Language-specific criteria live under `data/writing/<language>/`; review rules
63
- use `data/review-rules.<language>.yml`. Writing and review have separate lists
64
- of supported languages, so a future writing language need not imply review
65
- support. Other languages are reserved for future implementations and now
66
- return an explicit error. A review session saves its language and the criteria
67
- used to generate its prompt.
68
-
69
- ## Install from RubyGems
70
-
71
- Install the CLI from [RubyGems](https://rubygems.org/gems/asciidoc-pubkit):
23
+ | [Document outline](docs/document-commands.md#document-commands) | `document toc` | Print parsed section titles, including book parts and chapters, with optional depth and outline numbering |
24
+ | [Book metadata](docs/document-commands.md#document-commands) | `document info` | Extract book attributes as text or JSON |
25
+ | [Cross-reference checks](docs/document-commands.md#document-commands) | `document check-xrefs` | Report unresolved local cross-references with source locations |
26
+ | [Document-title index](docs/document-commands.md#document-commands) | `document index` | Generate an alphabetical AsciiDoc index from English document titles and IDs |
27
+ | [Replacement preview](docs/replacements.md#prose-replacements) | `replace check`, `replace diff` | Report mechanical replacement candidates or preview a diff for mapped running prose; preserve source files |
28
+ | [Replacement application](docs/replacements.md#prose-replacements) | `replace apply` | Apply author-supplied rules after checking protected content and document structure; no MeCab or AI required |
29
+ | [Prose review](docs/review-workflow.md#review-workflow) | `review scan` | Collect mapped Japanese running prose and contextual review candidates with MeCab/IPADIC by default |
30
+ | [List review](docs/list-review.md#list-review) | `review scan --scope lists` | Review mapped single-line list text in a separate session |
31
+ | [Heading review](docs/review-workflow.md#heading-review) | `review scan --scope headings` | Collect editable section titles separately, retaining the outline and read-only body evidence |
32
+ | [Review prompts](docs/review-workflow.md#prompt) | `review prompt` | Generate one Markdown prompt from a saved session for review and editing by an external reviewer |
33
+ | [Baseline verification](docs/review-workflow.md#verify) | `review verify` | Check edited sources against a saved baseline for mechanical preservation; meaning is not verified |
34
+ | [Manuscript scoring](docs/scoring.md#score-an-asciidoc-manuscript) | `review score` | Report a prose candidate-density score; explicit `--agent codex` or `--agent claude` optionally invokes a local AI CLI for readability ratings |
35
+ | [Writing criteria and prompts](docs/writing.md#writing-commands) | `writing criteria`, `writing prompt` | Print Japanese prose criteria or generate a writing prompt without a manuscript or MeCab |
36
+
37
+ ## Requirements and scope
38
+
39
+ Ruby 3.2 or later is required; RubyGems installs Asciidoctor and the other Ruby
40
+ dependencies. Document inspection and replacement require neither MeCab nor an
41
+ AI CLI. Japanese review and scoring use external MeCab with UTF-8 IPADIC by
42
+ default. See [installation and analyzer setup](docs/installation.md).
43
+ Explicit `--tokenizer literal` offers limited phrase matching without MeCab.
44
+
45
+ Document commands accept any language. Writing, replacement, and review support
46
+ `--lang ja` only. English review is a [research proposal](docs/english-review-research.md),
47
+ not an available feature. Node.js and textlint are not required.
48
+
49
+ Only `replace apply` edits manuscripts directly. Review prompts guide an external
50
+ human or agent; scan, prompt, verify, and scoring do not edit manuscripts.
51
+ Only explicit `review score --agent codex` or `--agent claude` invokes an
52
+ installed AI CLI, which may use its configured model provider.
53
+ Findings are review candidates; verification checks mechanical preservation and
54
+ keeps `meaning_verified: false`. The CLI does not publish books or provide EPUB,
55
+ image, or book scaffolding commands.
56
+
57
+ ## Install
72
58
 
73
59
  ```sh
74
60
  gem install asciidoc-pubkit
@@ -76,1375 +62,70 @@ asciidoc-pubkit --version
76
62
  asciidoc-pubkit --help
77
63
  ```
78
64
 
79
- Ruby 3.2 or later is required. RubyGems installs the required Ruby dependencies;
80
- no repository clone or Node.js installation is needed. MeCab and IPADIC must be
81
- installed separately when using version 0.1.1 or later in the default mode.
82
-
83
- Generate a writing prompt without an existing manuscript:
84
-
85
- ```sh
86
- asciidoc-pubkit writing criteria --lang ja
87
- asciidoc-pubkit writing prompt --lang ja --output writing-prompt.md
88
- ```
89
-
90
- Run the review workflow from your manuscript directory:
91
-
92
- ```sh
93
- asciidoc-pubkit review scan book.adoc --output .pubkit/review
94
- asciidoc-pubkit review prompt .pubkit/review --output review-prompt.md
95
- # Ask your agent to review the prompt and edit the referenced manuscript.
96
- asciidoc-pubkit review verify .pubkit/review --output verification.json
97
- ```
98
-
99
- To update an existing installation:
100
-
101
- ```sh
102
- gem update asciidoc-pubkit
103
- ```
104
-
105
- ### Use Bundler in a manuscript project
106
-
107
- Add the gem to your project's `Gemfile` to manage its version with Bundler:
108
-
109
- ```ruby
110
- source 'https://rubygems.org'
111
- gem 'asciidoc-pubkit', '~> 0.8.7'
112
- ```
113
-
114
- Then install dependencies and run the CLI through Bundler:
115
-
116
- ```sh
117
- bundle install
118
- bundle exec asciidoc-pubkit review scan book.adoc --output .pubkit/review
119
- bundle exec asciidoc-pubkit review prompt .pubkit/review --output review-prompt.md
120
- bundle exec asciidoc-pubkit review verify .pubkit/review --output verification.json
121
- ```
122
-
123
- Commit `Gemfile` and `Gemfile.lock` in the manuscript project to keep the selected
124
- version reproducible. Use `bundle update asciidoc-pubkit` to update it deliberately.
65
+ To update, run `gem update asciidoc-pubkit`. For Bundler, add
66
+ `gem 'asciidoc-pubkit', '~> 1.0.0'` to your project's `Gemfile` and run commands
67
+ through `bundle exec`. See [source installation and local checkout usage](docs/installation.md).
125
68
 
126
- ## Install from source
69
+ ## Quick start
127
70
 
128
- ```sh
129
- git clone https://github.com/cybergarage/asciidoc-pubkit.git
130
- cd asciidoc-pubkit
131
- bundle install
132
- gem build asciidoc-pubkit.gemspec
133
- gem install ./asciidoc-pubkit-0.8.7.gem
134
- asciidoc-pubkit --version
135
- ```
136
-
137
- The gem name and CLI name are `asciidoc-pubkit`; the Ruby require path is
138
- `asciidoc_pubkit`, and the namespace is `AsciidocPubkit`.
139
-
140
- ## Writing commands
141
-
142
- `writing criteria` prints the packaged common criteria. `writing prompt` adds
143
- task instructions around those same criteria. Neither command needs an AsciiDoc
144
- file, a review session, MeCab, or network access. Both accept `--lang ja` and
145
- `--output FILE`; output defaults to stdout, and an existing output file is never
146
- overwritten. The prompt asks the agent to read project instructions and evidence;
147
- it does not supply source facts or authorize edits. Book-specific voice and
148
- format still come from the book. The OSS-only prose style profile remains with
149
- the book workflow, not the shared default.
150
-
151
- ```sh
152
- asciidoc-pubkit writing criteria --lang ja
153
- asciidoc-pubkit writing prompt --lang ja --output writing-prompt.md
154
- ```
155
-
156
- For example, `--lang en` exits with an unsupported-language error. No English
157
- review or writing criteria are shipped in 0.8.7.
158
-
159
- For a small trial, use `examples/book.adoc` as the scan input. Its Japanese
160
- paragraphs deliberately contain review candidates; its code block must remain
161
- unchanged.
162
-
163
- ## Prose replacements
164
-
165
- Available starting with version 0.8.0.
166
- It applies author-supplied mechanical replacement rules without MeCab or an AI
167
- CLI. Review candidates and glossary variants remain advisory and are never
168
- implicitly applied. Replacement rules are separate from review rules.
71
+ Run these commands from the manuscript directory:
169
72
 
170
73
  ```sh
74
+ asciidoc-pubkit document toc book.adoc --depth 2 --numbered
75
+ asciidoc-pubkit document info book.adoc --json
76
+ asciidoc-pubkit document check-xrefs book.adoc
171
77
  asciidoc-pubkit replace check book.adoc --rules replacements.yml
172
78
  asciidoc-pubkit replace diff book.adoc --rules replacements.yml
173
79
  asciidoc-pubkit replace apply book.adoc --rules replacements.yml
174
- ```
175
-
176
- `check` reports original text, proposed text, rule IDs (`rule-1`, etc.), source
177
- paths, one-based Unicode lines/columns, and a coverage-notice count. Its exit code
178
- is 1 when replacements are available, 0 otherwise. `diff` previews unified diffs
179
- without editing; it requires the external `diff` command. `apply` explicitly
180
- authorizes source replacement without prompting. Successful diff/apply commands
181
- return 0; invalid rules, conflicts, unsafe edits, and input/output failures return
182
- 2. Check/diff accept `--output` for a new file only; apply rejects `--output`.
183
-
184
- Starting with version 0.8.2, invalid rule files report their original YAML file
185
- and one-based line number on the first error line, followed by the existing
186
- reason on the next line. Imported files and entries in pattern arrays retain
187
- their own source locations. For example:
188
-
189
- ```text
190
- Error: /path/to/prh.yml:162
191
- Unsupported regex flags; only optional i is supported (all matches are collected).
192
- ```
193
-
194
- Rules are validated before any manuscript is replaced. All replacement commands
195
- stop with exit code 2 on invalid rules, including errors found in imported files.
196
-
197
- All three accept `--lang ja`, `--base-dir`, `--config`, and `--only` (an included
198
- source file). Normal configuration discovery and `review.base_dir`, `language`,
199
- `attributes`, and `exclude` control parsing and selection. `--rules` is required;
200
- `review.rules` and glossary entries do not supply replacement rules. There are
201
- no built-in replacement rules and no automatic search for `prh.yml`.
202
-
203
- ### Limited prh-format rules
204
-
205
- The supported format is a strict subset of [prh](https://github.com/prh/prh):
206
-
207
- ```yaml
208
- version: 1
209
- rules:
210
- - expected: '®'
211
- pattern: '&reg;'
212
- - expected: '($1)'
213
- pattern: '/(([^()\r\n]+))/'
214
- specs:
215
- - from: '設定(任意)'
216
- to: '設定(任意)'
217
- - expected: '/'
218
- patterns:
219
- - '/'
220
- ```
221
-
222
- The root requires `version: 1` and accepts optional `rules` and `imports` arrays.
223
- Starting with version 0.8.1, omitted arrays default to empty. Version 0.8.0
224
- requires `rules` and rejects `imports`. Each rule requires a string
225
- `expected` (empty strings permit deletion) and exactly one of `pattern` (a
226
- nonempty string or, starting with version 0.8.1, a nonempty array of nonempty
227
- strings) or `patterns` (a nonempty array of nonempty strings). Array-valued
228
- `pattern` is equivalent to `patterns`; specifying both keys is rejected. Optional
229
- `specs` is an array of exact `from`/`to` string pairs, validated on load. Specs
230
- exercise the rule on plain text, not AsciiDoc selection or inline protection.
231
-
232
- Strings not beginning with `/` match literally. `/.../` denotes a regex; the
233
- version 0.8.1 also accepts `/.../i` for Ruby case-insensitive matching.
234
- Version 0.8.0 rejects all flags. All occurrences are collected. The implementation
235
- uses Ruby regexes with
236
- a timeout and accepts a limited common syntax: character classes, ordinary
237
- captures, noncapturing groups, lookarounds, alternatives, anchors, quantifiers,
238
- and the escapes `\n`, `\r`, `\t`, `\d`, `\D`, `\s`, `\S`, `\w`, `\W`
239
- and escaped punctuation. Ruby regex character-class behavior applies; this is
240
- not a JavaScript regex engine or a promise of full prh equivalence. Engine-specific
241
- groups/escapes and flags other than a single `i` are rejected. A leading literal slash must be expressed
242
- as an escaped regex, for example `/\//`. Zero-length matches are rejected.
243
-
244
- Replacement strings support `$1` through `$99` for existing capture groups and
245
- `$$` for a literal dollar sign. Unsupported dollar references are rejected when
246
- matched. Missing optional captures expand to empty strings. YAML single quotes
247
- are recommended to keep backslashes literal. Unknown fields, including
248
- `options` and `regexpMustEmpty`, and omitted patterns are rejected rather than
249
- ignored. prh's automatic pattern generation is not supported.
250
-
251
- For example, version 0.8.1 also accepts:
252
-
253
- ```yaml
254
- version: 1
255
- rules:
256
- - expected: 'ハードウェア'
257
- pattern:
258
- - 'ハードウエア'
259
- - 'ハードウェアー'
260
- ```
261
-
262
- Each array entry uses the same literal/regex syntax and validation as a single
263
- pattern. Arrays do not change supported flags or overlap handling.
264
-
265
- ### Limited ECMAScript boundary compatibility
266
-
267
- Version 0.8.1 translates `\b` and `\B` outside character classes into Ruby
268
- lookarounds with ECMAScript word-character semantics, following prh's default
269
- Unicode mode. Word characters are ASCII letters, digits, and underscore; Japanese
270
- characters are non-word characters. Thus `/\bTips\b/` matches `Tips` in
271
- `前Tips後`, but not in `Tips2`, `_Tips`, or `ATips`.
272
- With `/i`, long s (`ſ`) and Kelvin sign (`K`) also count as word characters under
273
- ECMAScript Unicode case folding. The generated assertions add no capture groups
274
- and preserve original match offsets. Inside a character class, `\b` means a
275
- backspace character; `\B` there is rejected. Escaped literal backslashes are
276
- preserved.
277
-
278
- Only the boundary assertions emulate ECMAScript. `/i` uses Ruby's
279
- `Regexp::IGNORECASE`; Unicode case folding can differ from JavaScript (for
280
- example multi-character folds). Other constructs, including whitespace classes,
281
- retain Ruby semantics. This is limited prh compatibility, not full ECMAScript
282
- conformance. Flags `g`, `m`, `s`, `u`, `y`, `d`, and `v` and duplicate `i` are
283
- rejected; all occurrences are already collected independently of `g`.
284
-
285
- ### Importing replacement rules
286
-
287
- Version 0.8.1 supports nested `imports`; version 0.8.0 does not. For example:
288
-
289
- ```yaml
290
- version: 1
291
- imports:
292
- - ../../rules/prh.yml
293
- - path: ./terminology.yml
294
- rules:
295
- - expected: '®'
296
- pattern: '&reg;'
297
- ```
298
-
299
- Each entry is a nonempty local file path string or a mapping containing exactly
300
- `path`. Relative paths resolve from the importing YAML file, including nested
301
- imports, independently of the working directory and manuscript base directory.
302
- Absolute local paths are also accepted; URL imports are rejected. An import-only
303
- file may omit `rules`. A file containing only `version: 1` is also valid and
304
- contributes no rules. With no imported or local rules, `check`, `diff`, and
305
- `apply` succeed without changing manuscript sources, and `diff` emits no patch.
306
- Starting with version 0.8.1, a bare `rules:`, `rules: null`, and `rules: ~`
307
- also contribute no local rules, just like omission or `rules: []`; imported rules
308
- are still loaded. Other non-array values remain invalid. This normalization
309
- applies only to `rules`, not to `imports` or individual rule fields.
310
- Every imported file must use version 1 and pass the same
311
- strict rule validation and specs as the entry file.
312
-
313
- Imports are loaded in listed order, recursively before each file's own rules.
314
- Each physical file is loaded once per plan, including repeated paths, symlink
315
- aliases, and shared dependencies. Rule IDs are assigned across the flattened
316
- set. Cycles (including symlink aliases), missing files, and import chains deeper
317
- than 100 files fail rather than silently omitting rules. Imported and local rules
318
- are combined, not overridden: overlapping replacement candidates remain errors
319
- and replacements are still calculated only against the original text.
320
-
321
- Import options such as `ignoreRules` and `disableImports` remain unsupported and
322
- are rejected. Source selection and protection are unchanged by imports.
323
-
324
- ### Selection and preservation
325
-
326
- Only unambiguously source-mapped running prose in the existing default review
327
- scope is eligible. Headings, lists, tables, quotations, listing/source, literal,
328
- and passthrough blocks are excluded. Recognized inline code, quotations, URLs,
329
- macros, and attribute references are protected by the existing conservative
330
- inline heuristic, not a complete inline parser. A match overlapping any protected
331
- span is skipped; matching is performed on the original text, never on blanked
332
- placeholders. Backtick-to-bold and list-marker conversions are outside this scope.
333
-
334
- Candidates are calculated once against the original sources; replacement results
335
- are not searched again. Overlapping edits are conflicts, not resolved by rule
336
- order. Matches/results containing line breaks are rejected. Source files retain
337
- UTF-8 bytes, original line endings, and unrelated content; repeated include
338
- occurrences must not create overlapping edits.
339
-
340
- Before presenting a plan, the complete captured source set is copied to temporary
341
- staging and reparsed. Parsing diagnostics, structural changes, new/deleted protected
342
- inline tokens, and protected-content/source-membership changes reject the plan.
343
- Relative includes within the base directory are supported. Absolute includes and
344
- includes whose paths depend on the original filesystem may fail staged validation;
345
- they are not rewritten or silently accepted. Symlink entrypoints are rejected.
346
-
347
- Apply stages all changed files beside their destinations, checks all captured
348
- source bytes against the plan, and renames the prepared files into place while
349
- preserving permission bits. An ordinary installation error restores sources
350
- already installed. This is not a crash-atomic transaction across multiple files;
351
- keep manuscripts under version control and avoid concurrent edits during apply.
352
- No review session is created or replaced. Existing sessions retain their original
353
- baselines; applying replacements can make a session stale for prompt generation.
354
- Mechanical validation does not establish semantic correctness.
355
-
356
- ## Score an AsciiDoc manuscript
357
-
358
- Pass any AsciiDoc entry file directly; no review session or gold annotations are
359
- required. Output defaults to a short English report with a score out of 100.
360
-
361
- ```sh
362
- asciidoc-pubkit review score book.adoc
363
- asciidoc-pubkit review score book.adoc --json --output score.json
364
- asciidoc-pubkit review score book.adoc --agent codex
365
- asciidoc-pubkit review score book.adoc --agent claude --json
366
- ```
367
-
368
- Without `--agent`, the report shows a mechanical candidate-density indicator.
369
- With `--agent`, it shows a model readability rating and retains the mechanical
370
- score in JSON. See [How review and scoring work](#how-review-and-scoring-work)
371
- for the analysis pipeline, formulas, and interpretation of these different scores.
372
- Successful scoring exits 0 regardless of the score; input, configuration,
373
- analyzer, evaluator, or output failures exit 2. No scoring mode establishes
374
- technical accuracy or meaning preservation; `meaning_verified` remains `false`.
375
-
376
- Scoring uses the same configuration discovery, custom rules, glossary, allows,
377
- style, language, base directory, include handling, and prose coverage as scanning.
378
- It accepts `--only`, `--config`, `--rules`, `--base-dir`, `--tokenizer`, `--style`,
379
- `--lang ja`, and repeated `--attribute` options. Excluded, unmapped, and protected
380
- blocks are not prose-scored. Coverage notices remain important when interpreting
381
- a score. MeCab/IPADIC is the default; literal mode must be selected explicitly.
382
-
383
- AI evaluation requires an installed, authenticated Codex or Claude CLI, and may
384
- send the selected paragraph text and headings to its configured provider and
385
- consume account usage. It receives no candidate findings or source file paths.
386
- `--model` selects the evaluator model, and `--timeout` sets the invocation timeout
387
- (default 300 seconds); both require `--agent`. Temporary evaluation files are
388
- removed after scoring. Use `--json --output FILE` to retain the result. Output
389
- files are never overwritten, and existing output is rejected before invoking an
390
- evaluator. A file with no unmasked prose is not sent to an evaluator.
391
-
392
- ## Run from a local checkout
393
-
394
- Use the `run` Make target to execute the checkout without installing the
395
- asciidoc-pubkit gem. Ruby dependencies and, for the default tokenizer, MeCab and
396
- UTF-8 IPADIC must already be installed.
397
-
398
- ```sh
399
- make run ARGS="--version"
400
- make run ARGS="review scan examples/book.adoc"
401
- make run ARGS='review scan "manuscripts/my book.adoc"'
402
- ```
403
-
404
- With no `ARGS`, `make run` displays CLI help. Set `RUBY` to choose another Ruby
405
- executable. `ARGS` is shell command-line text; quote paths containing spaces and
406
- use only trusted arguments.
407
-
408
- To run from a manuscript directory, select the checkout's Makefile with `-f`.
409
- Relative manuscript paths and output paths remain relative to your current
410
- working directory:
411
-
412
- ```sh
413
- make -f "$HOME/Src/asciidoc-pubkit/Makefile" run ARGS="review scan book.adoc"
414
- ```
415
-
416
- Use `ARGS` instead of `make review scan book.adoc`: Make interprets positional
417
- words as build targets, not CLI arguments. Avoid `make -C` when manuscript paths
418
- should remain relative to the current directory, because it changes directories.
419
-
420
- ## Install the morphological analyzer
421
-
422
- On macOS with Homebrew:
423
-
424
- ```sh
425
- brew install mecab mecab-ipadic
426
- mecab -D
427
- ```
428
-
429
- On Ubuntu or Debian:
430
-
431
- ```sh
432
- sudo apt-get update
433
- sudo apt-get install mecab mecab-ipadic-utf8
434
- mecab -D
435
- ```
436
-
437
- Use a UTF-8 IPADIC dictionary. If the default dictionary is different, configure
438
- `review.mecab_dictionary` with the IPADIC directory reported by your package
439
- manager. UniDic and other feature layouts are rejected explicitly. MeCab and
440
- IPADIC are separately installed dependencies, not bundled inside this gem.
441
-
442
- The tool checks MeCab availability, dictionary encoding, and feature layout.
443
- It never silently falls back to literal matching. To deliberately run without
444
- morphological analysis:
445
-
446
- ```sh
447
- asciidoc-pubkit review scan book.adoc --tokenizer literal --output .pubkit/literal-review
448
- ```
449
-
450
- ## Review workflow
451
-
452
- Run the following commands from the manuscript project directory:
453
-
454
- ```sh
80
+ # Establish a review baseline after mechanical replacements.
455
81
  asciidoc-pubkit review scan book.adoc --output .pubkit/review
456
82
  asciidoc-pubkit review prompt .pubkit/review --output review-prompt.md
457
- # Ask your agent to read review-prompt.md and revise the referenced manuscript.
83
+ # Ask your reviewer to read the prompt and edit the referenced manuscript.
458
84
  asciidoc-pubkit review verify .pubkit/review --output verification.json
459
85
  ```
460
86
 
461
- All three commands leave manuscript files unchanged. Only the agent edits them.
462
- `prompt` and `verify` output files must not already exist.
463
- Without `--output`, `prompt` writes Markdown and `verify` writes JSON to stdout.
464
- `scan` defaults to `.pubkit/review` and prints a short summary. Prose scan output
465
- and prompts explicitly direct reviewers to a separate `--scope lists` session
466
- for list text; the prose baseline must remain intact.
467
-
468
- ### Scan
469
-
470
- ```sh
471
- asciidoc-pubkit review scan book.adoc --only chapters/introduction.adoc
472
- asciidoc-pubkit review scan chapter.adoc --style desu-masu
473
- asciidoc-pubkit review scan book.adoc --attribute edition=print --base-dir .
474
- ```
475
-
476
- If the session directory already exists, an interactive terminal asks
477
- `Replace it? [y/N]`. Only `y` or `yes` (case-insensitive) replaces it; any other
478
- answer or end of input cancels with exit status 2. Replacement resets the review
479
- baseline and removes old session contents. Use a different `--output` path to
480
- keep the previous review pass. The old session remains intact if scanning fails
481
- before the replacement is installed.
482
-
483
- For batch execution:
484
-
485
- ```sh
486
- # Answer yes automatically and replace an existing review session.
487
- asciidoc-pubkit review scan book.adoc --yes # short form: -y
488
- # Never ask; exit with status 2 if the output already exists.
489
- asciidoc-pubkit review scan book.adoc --no-input
490
- ```
491
-
492
- Non-terminal stdin also disables prompting. `--yes --no-input` permits
493
- replacement without reading stdin. These options apply to `scan` only;
494
- regular files, symlinks, directories without a review session layout, and
495
- sessions containing the current manuscript sources cannot be replaced.
496
-
497
- An entrypoint or a standalone chapter can be scanned. Includes and conditionals
498
- are processed by Asciidoctor. Match the publishing build's attributes and base
499
- directory to review the intended edition. `--only` selects one included source
500
- file while retaining the book's attributes and heading hierarchy. Its path is
501
- relative to the current working directory, as are other CLI path arguments.
502
-
503
- Asciidoctor runs in safe mode. Local includes must resolve inside the base
504
- directory. Remote includes and project-specific Asciidoctor extensions are not
505
- supported. In particular, custom `/shared/` include conventions must be converted
506
- to ordinary local paths before using this release. Parser diagnostics cause the
507
- scan to fail rather than silently accepting incomplete input.
508
-
509
- The session contains:
510
-
511
- ```text
512
- .pubkit/review/
513
- manifest.json # Schema, tool version, inputs, settings, hashes, protection data
514
- findings.json # Candidate locations, rule IDs, severity, and review questions
515
- document.json # Paragraphs, heading hierarchy, structure, and coverage notices
516
- baseline/ # Exact copies of the participating source files
517
- ```
518
-
519
- Sessions use absolute source paths and are local working artifacts. Regenerate a
520
- session after moving a project. Keep `.pubkit/` and generated prompts out of Git
521
- when they contain private manuscript material. Rule settings and glossary contents
522
- are frozen into the session; scan again after changing them.
523
-
524
- ### Heading review
525
-
526
- Review headings, prose, and list text in separate sessions. The default scan scope
527
- remains `prose`; `--scope headings` selects section titles and `--scope lists` selects
528
- supported list text. There is no combined scope.
529
- Default output directories are `.pubkit/review` for prose and `.pubkit/headings`
530
- for headings, so separate scans do not replace each other by default.
531
- The scope is saved at scan time; `prompt` and `verify` use that saved scope.
532
- Neither scan nor prompt invokes an AI CLI or edits a manuscript. Give the generated
533
- prompt to your reviewer separately.
534
-
535
- ```sh
536
- asciidoc-pubkit review scan book.adoc --scope headings --output .pubkit/headings
537
- asciidoc-pubkit review prompt .pubkit/headings --mode diagnose --output headings-diagnosis.md
538
- # Generate a revision prompt when ready to edit:
539
- asciidoc-pubkit review prompt .pubkit/headings --mode revise --output headings-review.md
540
- # After the external review and edits:
541
- asciidoc-pubkit review verify .pubkit/headings
542
-
543
- # Establish a fresh prose baseline after finishing heading edits:
544
- asciidoc-pubkit review scan book.adoc --scope prose --output .pubkit/prose
545
- asciidoc-pubkit review prompt .pubkit/prose --output prose-review.md
546
- asciidoc-pubkit review verify .pubkit/prose
547
- ```
548
-
549
- Heading prompts contain the full parsed section outline, selected headings and
550
- all selected source-mapped prose paragraphs once as read-only evidence. They
551
- compare parents, siblings, descendants and the corresponding body. Body content
552
- outside prose coverage is not supplied; insufficient evidence must be recorded
553
- as `needs-evidence`. `--only` and `review.exclude` select editable headings and
554
- body evidence while retaining the full outline as context. All excerpts are data,
555
- never executable reviewer instructions. Both criteria files and resolved rules
556
- are frozen in the session.
557
-
558
- Default heading rules accept term labels, noun phrases, questions, action
559
- phrases, principles, conclusions and learning directions. They flag limited
560
- promotional/vague phrases, glossary variants and identical sibling titles as
561
- review candidates. They do not apply prose weak-predicate or sentence-ending
562
- rules, require nominalization, or impose a character limit. Role and body
563
- agreement are contextual reviewer judgments, not mechanically proven findings.
564
-
565
- Only plain ATX section titles whose source cursor and original title match are
566
- editable. Document titles, old-style underlined headings, attribute-expanded
567
- and converted inline titles and physical title lines reused by multiple includes remain protected.
568
- Unresolved section titles receive coverage notices. Verification permits only selected title text changes while
569
- protecting the body, title markers, hierarchy, order, section IDs, references,
570
- attributes, includes and other protected content. A title-derived section ID
571
- change fails verification. Starting with version 0.8.7, heading scans preserve
572
- generated IDs by default. Eligible generated headings save an exact `permitted_id_anchor` in
573
- their metadata. A reviewer may insert only that
574
- anchor immediately before its selected heading, for example:
575
-
576
- ```adoc
577
- [#_手動圧縮の入口]
578
- == 手動圧縮と拡張からの起動
579
- ```
580
-
581
- Verification allows this exact addition while requiring the same section ID,
582
- hierarchy, order, and protected body. Existing explicit anchors remain protected;
583
- other anchors and reference migrations are outside this permission. No additional
584
- ID-preservation option is required. Previously saved permissions remain unchanged;
585
- start a separate new session to obtain the default permissions, keeping the old
586
- baseline intact. Scan and prompt never insert anchors or rewrite
587
- manuscripts. Numeric title changes
588
- are manual-review notices, and remaining candidates do not fail verification.
589
- `meaning_verified` remains `false`.
590
-
591
- Version 0.8.7 uses session schema 3. Earlier sessions must be recreated; preserve or
592
- finish an ongoing review with its original tool before establishing a new baseline.
593
- `review score` continues to support prose only and rejects `--scope`.
87
+ Replacement requires author-supplied [replacement rules](docs/replacements.md);
88
+ review candidates are never applied as replacements. `replace check` exits 1
89
+ when candidates exist. Output files must be new.
594
90
 
595
- Heading rules use `--heading-rules FILE`, then configuration
596
- `review.heading_rules`, then `data/heading-rules.ja.yml`. A custom file replaces
597
- the entire heading rule set. Each scan loads only the rules for its selected
598
- scope; an unavailable rule file for the other scope does not prevent it.
599
- `--heading-rules` requires `--scope headings`;
600
- prose `--rules` and `--style` cannot be passed to a heading scan.
91
+ Prose, headings, and lists use separate review sessions. For a complete review,
92
+ finish and verify headings first, then prose, then lists, creating each baseline
93
+ after the preceding phase. See the [review workflow](docs/review-workflow.md)
94
+ and [list review](docs/list-review.md) for supported spans and coverage limits.
601
95
 
602
- ```yaml
603
- schema_version: 1
604
- terms:
605
- book-heading-cue:
606
- terms: [シームレス]
607
- question: 'Check the claimed behavior against the section evidence.'
608
- fixed_titles: [はじめに, 参考文献, まとめ]
609
- duplicate_siblings: true
610
- style: mixed
611
- ```
612
-
613
- All five keys are required; unknown keys, invalid types and YAML aliases are
614
- rejected. `terms` maps nonempty rule names to exactly `terms` (unique nonempty
615
- strings) and `question` (nonempty English guidance). `fixed_titles` contains
616
- unique nonempty titles exempt from mechanical candidates; it does not expand
617
- the edit scope or prove correctness. `duplicate_siblings` is boolean. `style`
618
- is `mixed` (default), `nominal`, or `action`; explicit preferences generate
619
- advisory ending cues rather than a complete grammatical classification. Keep
620
- questions, principles and justified exceptions. Heading phrase and glossary
621
- matches respect exact `review.allows` entries, protected inline masking and
622
- one-based Unicode source columns. MeCab remains the default; only explicit
623
- `--tokenizer literal` disables it.
624
-
625
- ### Prompt
96
+ To score prose or generate writing guidance:
626
97
 
627
98
  ```sh
628
- asciidoc-pubkit review prompt .pubkit/review --mode revise --output review-prompt.md
629
- asciidoc-pubkit review prompt .pubkit/review --mode diagnose
630
- ```
631
-
632
- `revise` is the default and asks the agent to edit relevant prose. `diagnose` asks
633
- for findings and proposed revisions without editing. Both modes require the agent
634
- to distinguish **revise**, **keep**, and **needs-evidence** decisions. Each decision
635
- needs a passage-specific reason. Whether a matched string remains or disappears
636
- cannot determine that decision; unchanged paragraphs and remaining candidates
637
- must not receive automatic `keep` records. Unreviewed items remain pending.
638
-
639
- Version 0.8.4 prompts require the reviewer to reconcile decisions with actual
640
- edits (or proposed revisions in diagnose mode), review paragraphs or headings
641
- without candidates, and inspect newly detected or remaining candidates after
642
- verification. They request separate reports for mechanical preservation,
643
- candidate decisions, and paragraph or heading quality review, with counts and
644
- unresolved items. Protected-scope concerns are separate proposals, not evidence
645
- of editorial approval. Pending items make the review incomplete.
646
- Version 0.8.5 further requires an individual role or claim, located
647
- evidence, a considered direct alternative, and the rationale for each candidate
648
- decision. A stock reason with an appended quotation is insufficient. For `入口`,
649
- the shared criteria ask whether creation, invocation, configuration, reference,
650
- or a learning role can be stated directly even when the referent is clear.
651
- Remaining role metaphors must be checked against those individual decisions.
652
-
653
- These are reviewer instructions: the gem does not validate a decision ledger
654
- or prove that an AI or human followed the instructions. Keep session metadata
655
- and baseline snapshots immutable; format only authorized manuscript spans.
656
-
657
- The single Markdown output includes every selected paragraph once, in document
658
- order, with the shared criteria saved at scan time, candidates, saved settings,
659
- and preservation instructions. Paragraph
660
- text uses fenced text blocks; metadata uses compact JSON. File and heading context
661
- is shared by consecutive paragraphs, and candidates inherit their file and
662
- paragraph ID. Adjacent entries provide neighboring context without repeating text.
663
- The prompt asks the agent to read manageable ranges with neighboring paragraphs
664
- at boundaries and track completed paragraph IDs and candidate decisions. It also
665
- requires review of paragraphs with no machine matches. Large manuscripts can
666
- still exceed a context window if the entire prompt is loaded at once. Initial
667
- support is for local prose correction, not chapter reorganization.
668
-
669
- Source hashes are checked before generating a prompt. Modified sources, modified
670
- session artifacts, and incompatible session versions require a fresh scan.
671
- `review scan`, `review prompt`, and `review verify` accept `--lang ja`; prompt and
672
- verify check the value against the session language. A non-Japanese language in
673
- `--lang`, `review.language`, or an explicit AsciiDoc `:lang:` attribute is rejected.
674
- An omitted `:lang:` attribute uses the selected review language.
675
-
676
- ### Verify
677
-
678
- ```sh
679
- asciidoc-pubkit review verify .pubkit/review
680
- ```
681
-
682
- For prose sessions, verification compares the current source set, document structure, content outside
683
- reviewed paragraphs, and recognized protected inline tokens with the baseline.
684
- It reports remaining candidates and numeric changes separately. Existing candidates
685
- do not make verification fail. Numeric changes require manual review but do not
686
- by themselves fail mechanical verification.
687
-
688
- Non-prose comparison ignores empty separator lines and trailing whitespace;
689
- listing, literal, and passthrough block content is additionally compared as parsed
690
- lines. Inline protection is heuristic, not a complete AsciiDoc inline parser.
691
- Successful verification does not prove meaning preservation, technical accuracy,
692
- or release readiness: `meaning_verified` is always `false`. Verification does
693
- not read candidate decision records or certify editorial completion. A passing
694
- mechanical result must be reported separately from the reviewer's quality and
695
- completion assessment.
696
-
697
- | Exit code | Meaning |
698
- | --- | --- |
699
- | `0` | Command completed; verification found no mechanical violations |
700
- | `1` | Verification found protected-content, structure, source, or parsing issues |
701
- | `2` | Invalid arguments, configuration, session, scan input, or output failure |
702
-
703
- ## How review and scoring work
704
-
705
- ### Features
706
-
707
- - **Structure-aware AsciiDoc parsing.** Asciidoctor parses local includes,
708
- conditionals, attributes and section hierarchy before review targets are
709
- selected. Prose selection distinguishes paragraphs from lists, tables,
710
- quotations and code blocks; supported inline constructs are masked rather
711
- than treated as ordinary prose.
712
- - **Separate heading and prose review.** Each scan selects one
713
- scope with its own rules, prompt and edit permissions. Heading review uses
714
- the outline and body as context while protecting body text; prose review
715
- protects headings. Mixed heading forms are accepted by default. See
716
- [Heading review](#heading-review).
717
- - **Source-aligned static analysis.** Candidates identify the original source
718
- file, line and one-based Unicode column, with a rule ID and review question.
719
- Source text is checked against parser locations; unresolved mappings produce
720
- coverage notices instead of guessed edit targets. Matches locate passages
721
- for review, not proven defects.
722
- - **Japanese morphological analysis.** MeCab with UTF-8 IPADIC recognizes
723
- configured inflected predicates and adjectives, retaining original surfaces,
724
- dictionary forms and negative-form information in morphological prose
725
- findings. Literal matching is available only through explicit selection.
726
- - **Contextual review in one prompt.** A single Markdown file carries saved
727
- criteria, settings, candidates and manuscript evidence. All selected prose
728
- paragraphs appear once, including those without candidates, with heading and
729
- neighboring context. The reviewer records decisions and checks meaning;
730
- generating the prompt does not edit the manuscript or invoke a model.
731
- - **Book-specific rules and terminology.** Strict YAML rule sets, a glossary,
732
- allow lists and exclusions adapt candidate detection to the manuscript.
733
- Heading rules can express a book's preferred form while allowing justified
734
- exceptions. Resolved rules and criteria are saved with each session.
735
- - **Baseline-based preservation checks.** Source snapshots and artifact hashes
736
- make the review baseline reproducible and detect stale or altered evidence.
737
- Verification checks protected content, source membership, structure and
738
- analyzer identity after external edits. It keeps `meaning_verified: false`;
739
- semantic correctness remains a review judgment.
740
- - **Local analysis and distinct scoring paths.** Default analysis runs locally
741
- without a model call. Prose scoring reports candidate density; explicit
742
- `review score --agent` optionally invokes an installed Codex or Claude CLI
743
- for readability ratings. Candidate density, model judgments and development
744
- benchmark accuracy remain separate measures.
745
-
746
- ### Concept
747
-
748
- The goal is Japanese technical prose that readers can understand, use, and
749
- verify, with claims bounded by evidence and technical meaning preserved.
750
- Clarity includes a paragraph's purpose, concrete operations and referents,
751
- actors and objects, conditions and consequences, logical connections, and its
752
- relationship to headings, figures, tables, and code. "Who does what" is one
753
- part of that goal. Clear prose also retains precise terminology, necessary
754
- negation, uncertainty, and implementation constraints.
755
-
756
- The toolkit supports that goal through shared writing criteria, contextual
757
- review prompts, source-aligned candidate detection, baseline verification,
758
- and distinct scoring and development evaluation paths. Mechanical rules locate
759
- passages to inspect; the reviewer judges their meaning from context and source
760
- evidence. The writing and review prompts guide a human or external agent in
761
- planning and revising complete paragraphs. They do not automatically reconstruct
762
- subjects and objects or rewrite manuscripts. Model-based readability evaluation
763
- is available only through explicit `review score --agent`.
764
-
765
- The table identifies both implemented mechanisms and guidance carried by the
766
- prompts. A criterion in a prompt is a review instruction, not a guarantee that
767
- the code can detect or verify it.
768
-
769
- | Supported principle or behavior | How it is realized | Implementation or criteria |
770
- | --- | --- | --- |
771
- | Write for a technical purpose and the reader's decisions | Shared criteria ask what a paragraph explains and what an engineer can decide or verify; writing prompts include those criteria | [Paragraph purpose](data/writing/ja/criteria.md#start-with-the-paragraphs-technical-purpose), [Writing](lib/asciidoc_pubkit/writing.rb) |
772
- | Make actors, objects, actions, conditions, and results recoverable | Review instructions ask the reviewer to resolve omitted elements from context, while allowing unambiguous omission | [Paragraph revision](data/writing/ja/criteria.md#revise-the-complete-paragraph), [Review prompt](lib/asciidoc_pubkit/session.rb) |
773
- | Replace vague abstraction, weak predicates, and metaphors with concrete explanations | Rules locate limited terms and inflected predicates; the criteria require identifying the actual referent, operation, policy, or effect before revising | [Concrete referents](data/writing/ja/criteria.md#replace-abstraction-with-the-thing-being-discussed), [Metaphor criteria](data/writing/ja/criteria.md#explain-metaphorical-operations-from-evidence), [Rules](lib/asciidoc_pubkit/rules.rb) |
774
- | Distinguish reader instructions, actual behavior, and available capabilities | The shared criteria preserve the difference between requests, automatic execution, and optional operations | [Instructions, behavior, and capabilities](data/writing/ja/criteria.md#distinguish-instructions-behavior-and-capabilities) |
775
- | Connect claims into coherent paragraphs | Prompts include all selected paragraphs and neighboring context; criteria require explicit referents, comparisons, causal relationships, and complete paragraph revision | [Relationships](data/writing/ja/criteria.md#make-relationships-explicit), [Review prompt](lib/asciidoc_pubkit/session.rb) |
776
- | Keep claims within their evidence and preserve meaning | Review guidance asks for implementation, test, or primary-source evidence and checks omissions and unsupported additions; unresolved facts remain unresolved | [Evidence and scope](data/writing/ja/criteria.md#keep-claims-within-their-evidence-and-purpose), [Paragraph revision](data/writing/ja/criteria.md#revise-the-complete-paragraph) |
777
- | Preserve technical distinctions, terminology, and justified prose choices | Criteria protect identifiers, values, conditions, negation, and necessary repetition; glossary rules, allow lists, and contextual questions support project terminology | [Terminology](data/writing/ja/criteria.md#preserve-exact-technical-terminology), [Packaged rules](data/review-rules.ja.yml), [Settings](lib/asciidoc_pubkit/settings.rb) |
778
- | Review generated-prose patterns without mechanical deletion | Framing, contextual phrases, style, and repeated-ending checks produce candidates; shared criteria reject fixed sentence-length targets and needless synonym changes | [Generated-prose patterns](data/writing/ja/criteria.md#remove-generated-prose-patterns-without-flattening-the-meaning), [Rules](lib/asciidoc_pubkit/rules.rb) |
779
- | Keep headings, illustrations, tables, and code consistent with the explanation | Writing criteria address scope, comparisons, identifiers, and conceptual simplifications; review prompts constrain edits to the selected scope and protect other elements | [Headings, figures, and code](data/writing/ja/criteria.md#headings-and-the-relation-to-figures-and-code), [Review scope](lib/asciidoc_pubkit/session.rb) |
780
- | Make detection traceable and coverage explicit | Asciidoctor source mapping, offset-preserving inline masking, and MeCab/IPADIC produce source-aligned evidence; ambiguous or excluded passages have coverage notices | [Document](lib/asciidoc_pubkit/document.rb), [Morphology](lib/asciidoc_pubkit/morphology.rb), [Rules](lib/asciidoc_pubkit/rules.rb) |
781
- | Preserve a reproducible and safe review baseline | Sessions save source snapshots, resolved rules, criteria, and analyzer identity; integrity checks and verification protect content outside editable prose | [Session](lib/asciidoc_pubkit/session.rb), [Rule validation](lib/asciidoc_pubkit/rule_set.rb) |
782
- | Keep manuscript indicators, readability judgments, and detector accuracy distinct | Default scoring measures candidate density; optional local CLI evaluation judges readability; annotated development benchmarks measure detection and evaluate preservation separately | [Score](lib/asciidoc_pubkit/score.rb), [Local evaluator](lib/asciidoc_pubkit/local_evaluator.rb), [Development benchmark](benchmark/prose.rb) |
783
- | Make automation explicit and its limits visible | Default analysis runs locally with no model call; only explicit scoring requests invoke an external CLI. Manuscripts are not edited, and verification retains `meaning_verified: false` | [CLI](lib/asciidoc_pubkit/cli.rb), [Local evaluator](lib/asciidoc_pubkit/local_evaluator.rb), [Session](lib/asciidoc_pubkit/session.rb) |
784
-
785
- This section explains the implementation independently of command syntax.
786
- [Review workflow](#review-workflow) covers commands and session handling;
787
- [Score an AsciiDoc manuscript](#score-an-asciidoc-manuscript) covers scoring options.
788
- The diagrams use GitHub-supported Mermaid fenced blocks.
789
-
790
- ### Shared components and prose selection
791
-
792
- Both paths resolve the same settings and parse the AsciiDoc entry file with
793
- Asciidoctor, including local includes. `Document` selects running-prose paragraphs
794
- and maps them back to their source files. Ambiguous mappings become coverage
795
- notices; the analyzer does not guess locations. Headings provide context, while
796
- code, tables, quotations, lists, and protected blocks are excluded from prose
797
- analysis. Inline code, quoted spans, links, and other protected constructs are
798
- masked with spaces that preserve character offsets and newlines.
799
-
800
- ```mermaid
801
- flowchart TD
802
- A["AsciiDoc entry and local includes"] --> D["Document: parse and map running prose"]
803
- C["Settings: options, configuration, resolved rules"] --> D
804
- D --> P["Paragraphs with source locations and headings"]
805
- D --> N["Coverage notices and parser diagnostics"]
806
- P --> M["Rules: mask protected inline content"]
807
- C --> M
808
- M --> F["Candidate detection"]
809
- F --> R["Session: review baseline and evidence"]
810
- F --> S["Score: manuscript indicators"]
811
- P -->|"Original prose and headings"| S
812
- N --> R
813
- N --> S
814
- ```
815
-
816
- `Settings` resolves rule precedence as command-line `--rules`, configuration
817
- `review.rules`, then packaged defaults. A custom rule file replaces the whole
818
- set. `Rules` returns review candidates with one-based Unicode line and column
819
- positions; a match does not establish a defect. `Session` saves evidence for a
820
- later review, while `Score` returns a report directly without creating a session.
821
- Parser diagnostics must be resolved before scanning or scoring.
822
-
823
- ### Review: collect, judge, and verify
824
-
825
- Scanning freezes the source baseline, resolved settings and rules, analyzer
826
- identity, and writing criteria. The session consists of `manifest.json`,
827
- `document.json`, `findings.json`, and `baseline/`. Prompt generation checks
828
- artifact integrity and rejects sources changed since the scan. It emits one
829
- Markdown file containing the saved criteria, context, every selected paragraph
830
- in document order, and its candidate evidence, including paragraphs with no
831
- candidates. Generating that prompt requires no analyzer or model invocation.
832
-
833
- ```mermaid
834
- sequenceDiagram
835
- actor Reviewer as Human or external agent
836
- participant CLI as pubkit CLI
837
- participant Sources as Manuscript files
838
- participant Session as Saved review session
839
- Reviewer->>CLI: review scan FILE
840
- CLI->>Sources: Parse prose and detect candidates
841
- CLI->>Session: Save evidence and source baseline
842
- Reviewer->>CLI: review prompt SESSION
843
- CLI->>Session: Check integrity and read saved evidence
844
- CLI->>Sources: Check sources still match scan
845
- CLI-->>Reviewer: One Markdown review prompt
846
- Reviewer->>Sources: Judge context and edit prose externally
847
- Reviewer->>CLI: review verify SESSION
848
- CLI->>Session: Read original baseline and settings
849
- CLI->>Sources: Reparse and compare protected content
850
- CLI-->>Reviewer: Mechanical result, notices, remaining candidates
851
- ```
852
-
853
- The reviewer decides whether to keep or revise each paragraph and checks source
854
- evidence before adding claims. `scan`, `prompt`, and `verify` never invoke an AI
855
- CLI or edit manuscripts. Verification compares the included source set, content
856
- outside reviewed prose, protected inline tokens, document structure, and analyzer
857
- identity against the saved baseline. Numeric changes produce manual-review
858
- notices; remaining candidates alone do not fail verification. A passing result
859
- means these mechanical checks passed, with `meaning_verified: false`.
860
-
861
- ### Detection: contextual rules and token boundaries
862
-
863
- MeCab with UTF-8 IPADIC is the default analyzer. It supplies surfaces, dictionary
864
- forms, part of speech, and source-aligned token spans. Explicit literal mode
865
- matches configured surface strings; there is no silent fallback. Both modes
866
- apply glossary, configured prose style, and sentence-ending checks.
867
-
868
- ```mermaid
869
- flowchart TD
870
- P["Masked running prose"] --> B{"Selected tokenizer"}
871
- B -->|"mecab, default"| T["MeCab and IPADIC tokens with source offsets"]
872
- T --> L["Lemma rules with allow lists and contextual overlap checks"]
873
- T --> X["Four enabled contextual predicate patterns"]
874
- B -->|"literal, explicit"| E["Exact configured terms"]
875
- P --> Q["Exact framing and contextual phrases"]
876
- L --> F["Candidate findings"]
877
- X --> O["Prefer most specific phrase; apply allow lists"]
878
- E --> O
879
- Q --> O
880
- O --> F
881
- P --> G["Glossary, style, and repeated endings"]
882
- G --> F
883
- ```
884
-
885
- Morphological rules match configured noun and adjective lemmas, canonical verb
886
- forms, adjacent compound nouns, and sahen nouns followed by `する` or `できる`.
887
- Predicate spans extend through adjacent auxiliaries, dependent verbs, and
888
- supported connective particles. Negative auxiliaries preserve polarity;
889
- negative-only rules require that evidence. Unknown tokens are not guessed.
890
-
891
- The four contextual patterns combine an exact prefix (`地味に`, `静かに`,
892
- `時間を`, or `側に`) with a known independent verb lemma (`効く`, `壊れる`,
893
- `溶かす`, or `倒す`). The canonical phrase must be enabled in the resolved rules.
894
- For example, `地味に効かなかった` is collected as one complete candidate with
895
- lemma `地味に効く` and `negative: true`. Protected text and paragraph boundaries
896
- cannot bridge the pattern. Longer contextual phrases suppress contained matches,
897
- including when the longer phrase is allowed. These limited patterns suggest
898
- reviewing the actual effect or operation; they do not prove a metaphor is wrong.
899
-
900
- Sentence-ending analysis splits each paragraph at `。`, `!`, and `?`, retaining
901
- source offsets. It extracts supported endings such as `検証します` and `です`,
902
- then checks consecutive windows of three sentences. A sentence without a matching
903
- ending breaks the run. The first matching run produces one informational
904
- candidate at the ending of its third sentence. Precise technical repetition may
905
- be worth retaining; this is not a requirement to vary verbs.
906
-
907
- ### Scoring: density and optional readability judgment
908
-
909
- Scoring first runs the shared candidate detector. For the default
910
- `candidate-density-v1`, let `N` be all findings, including informational ones,
911
- and `C` be non-whitespace Unicode characters after inline masking:
912
-
913
- ```text
914
- density = N * 1000 / C
915
- score = max(0, 100 - 5 * density)
916
- ```
917
-
918
- The score is rounded to three decimals. No unmasked prose yields `null`.
919
- More candidates per 1,000 characters lower the score; short texts are particularly
920
- sensitive. Changing rules, allow lists, or the detector can change the score of
921
- an unchanged manuscript. This heuristic is a review indicator, not a calibrated
922
- quality measure or a probability that AI wrote the text.
923
-
924
- ```mermaid
925
- flowchart TD
926
- P["Selected prose and detected candidates"] --> D["Compute candidate density and mechanical score"]
927
- D --> A{"Explicit agent option and nonempty prose?"}
928
- A -->|"No"| R["Text or JSON report"]
929
- A -->|"Yes"| I["Paragraph IDs, text, headings, and readability rubric"]
930
- I --> J["Installed Codex or Claude CLI; configured model provider"]
931
- J --> V["Validate IDs, integer ratings, and reasons"]
932
- V --> M["Map ratings to 0, 50, 100 and average"]
933
- M --> R
934
- D --> K["Retain mechanical score in JSON"]
935
- K --> R
936
- ```
937
-
938
- With explicit `--agent`, `llm-readability-v1` asks a fresh local CLI invocation to
939
- rate each paragraph's sentence clarity and paragraph coherence separately from
940
- 1 to 3. The rubric targets engineers familiar with the technical terms. The
941
- input contains paragraph IDs, original text, and headings, without candidate
942
- findings or file paths. The CLI may connect to its configured model provider.
943
- The response must contain every supplied ID exactly once, integer ratings in
944
- range, and nonempty reasons. Invalid responses fail scoring.
945
-
946
- Ratings of 1, 2, and 3 map to 0, 50, and 100. Each dimension averages equally
947
- across scored paragraphs; the displayed score averages the two dimension means.
948
- JSON retains both dimensions, paragraph reasons, evaluator identity, and the
949
- mechanical score. These ordinal averages summarize a fallible judgment. There
950
- is no reference manuscript or fact checklist in this single-document path, so
951
- it does not assess preservation or establish technical accuracy. Temporary CLI
952
- artifacts are removed after the invocation, and manuscripts remain unchanged.
953
-
954
- | Result | What it measures | Evidence needed |
955
- | --- | --- | --- |
956
- | Candidate-density score | Detected cues per text length | Current prose and resolved rules |
957
- | Optional readability score | Model judgment of clarity and coherence | Current prose, context, and rubric |
958
- | Development benchmark accuracy | Detector agreement and location accuracy | Fixed corpus with annotated targets |
959
- | Review verification | Mechanical preservation after editing | Original session baseline and current files |
960
-
961
- See the [development prose benchmark](#development-prose-benchmark) for
962
- before/after trials with gold targets, separate fact checklists, and evaluator
963
- calibration. Its precision, recall, and F1 evaluate the detector rather than
964
- providing a score for an arbitrary manuscript.
965
-
966
- ## Configuration
967
-
968
- `scan` and `score` search upward from the entrypoint directory for the nearest
969
- `.asciidoc-pubkit.yml`. Use `--config FILE` to select a different file. CLI options
970
- override configuration values; unspecified values use built-in defaults.
971
- The initial release loads one configuration file, not merged book/repository files.
972
-
973
- ```yaml
974
- review:
975
- language: ja
976
- style: desu-masu
977
- tokenizer: mecab
978
- # heading_rules: heading-rules.yml # Separate heading rule set
979
- # Optional overrides (dictionary paths are relative to this file):
980
- # mecab_command: /opt/homebrew/bin/mecab
981
- # mecab_dictionary: /opt/homebrew/lib/mecab/dic/ipadic
982
- base_dir: .
983
- glossary: glossary.yml
984
- exclude:
985
- - generated/**
986
- allows: []
987
- attributes:
988
- edition: print
989
- ```
990
-
991
- Configuration paths are relative to the configuration file. Without configuration,
992
- the base directory is the entrypoint's directory. Exclusion patterns match source
993
- paths relative to the base directory; excluded files can still supply attributes
994
- and are preserved by verification. The default style is `preserve`; explicit
995
- alternatives are `desu-masu` and `dearu`. Only `ja` is currently supported.
996
-
997
- A glossary maps canonical terms to variant strings:
998
-
999
- ```yaml
1000
- JavaScript:
1001
- - Javascript
1002
- - Java Script
1003
- ```
1004
-
1005
- Variants are review candidates, not automatic replacement instructions. In MeCab
1006
- mode, `allows` can suppress a canonical dictionary form (all its inflections) or
1007
- an exact matched surface (that occurrence's form only). In literal mode it
1008
- suppresses exact dictionary entries. It does not disable glossary checks.
1009
- Regex patterns are not interpreted in glossary or allow-list entries. Unknown
1010
- configuration keys are rejected. A bare `mecab_command` is resolved through PATH;
1011
- use an absolute path for an explicit executable override.
1012
-
1013
- ## Rules and coverage
1014
-
1015
- | Rule | Severity | Purpose |
1016
- | --- | --- | --- |
1017
- | `abstract-reference` | hint | Ask what an abstract noun refers to |
1018
- | `weak-predicate` | hint | Ask whether an operation's purpose or result is clear |
1019
- | `contextual-phrase` | hint | Check whether a qualification changes interpretation or action; preserve necessary negation |
1020
- | `generic-framing` | hint | Check whether an introduction or recap adds a claim, scope, or consequence |
1021
- | `vague-degree` | hint | Ask what depth, level, scope, or comparison is intended |
1022
- | `repeated-ending` | info | Identify three consecutive sentences with the same detected ending |
1023
- | `glossary-variant` | warning | Identify project-specific terminology variants |
1024
- | `style-candidate` | hint | Check selected polite/plain endings against an explicit style |
1025
-
1026
- MeCab mode matches noun and adjective tokens and dictionary forms of verbs.
1027
- Sahen predicates are matched as a noun followed by `する` or the potential
1028
- `できる`; standalone sahen nouns are not treated as verbal predicates. A configured
1029
- sahen predicate takes precedence over a matching standalone noun rule. Auxiliary sequences retain
1030
- negation, past tense, passive forms, and progressive forms in the reported surface.
1031
- The added reach predicate is negative-only; the existing handling predicate is
1032
- reviewed in both affirmative and negative forms. Glossary variants and generic
1033
- framing phrases continue to use literal matching. Contextual phrases suppress
1034
- overlapping morphological candidates. Except for the four predicate patterns
1035
- described below, they use literal matching. Compound
1036
- nouns are matched across adjacent noun tokens. Selection and narrowing verbs
1037
- include potential forms; predicate surfaces also preserve causative auxiliaries.
1038
-
1039
- Default terms group components, actors, relationships, and resources under
1040
- `abstract-reference`; operations under `weak-predicate`; and compressed noun
1041
- relationships, referents, sufficiency, and negative qualifications under
1042
- `contextual-phrase`. `木` and `余白` invite a context-dependent katakana terminology
1043
- review, not mandatory replacement. `明示選択` and `欠落理由` invite checking whether
1044
- `明示的選択` and `欠落した理由` clarify the intended relationship. Shared phrases such
1045
- as `ではありません` cover longer qualifications without listing every sentence.
1046
- `generic-framing` also flags `このように` and `要するに` as possible recaps.
1047
- These are candidates for contextual review, not banned expressions. A necessary
1048
- condition, uncertainty, or distinction must survive a revision; a redundant
1049
- disclaimer can instead be removed or folded into a more precise main claim.
1050
-
1051
- Version 0.8.5 extends the existing `入口` question and shared criteria
1052
- without adding another prose matcher. A known referent alone does not justify
1053
- vague role wording; direct alternatives are evaluated against the actual
1054
- operation, conditions, and technical usage. The heading `heading-vague-topic`
1055
- rule also includes `入口`; proposed title changes must preserve generated IDs
1056
- or be reported for a separate authorized migration. Lists remain excluded and
1057
- are not included in prose or heading body evidence. Reports about outside-scope
1058
- concerns cover only content actually inspected, not unreviewed excluded blocks.
1059
- If baseline or artifact integrity fails, preserve the evidence and stop editing;
1060
- never update snapshot hashes or replace the baseline to claim a successful review.
1061
-
1062
- Version 0.8.3 also includes scoped candidates such as `構築入口`,
1063
- `エラーを回収する`, `ツールを呼ぶ`, `したりできます`, and `設計の肝`.
1064
- These additions use the exact surfaces listed in the YAML in both modes;
1065
- they do not add general inflection coverage or ban everyday verbs. Existing
1066
- `木`, `持つ`, `書く`, `別です`, and `ではありません` rules cover related examples.
1067
- The shared criteria explain context-dependent terminology, precise operations,
1068
- direct predicates, and objective tone. They distinguish invocation from
1069
- execution, configuration text from configuration changes, assumptions from
1070
- requirements, and collecting errors from catching them. Suggested alternatives
1071
- are not automatic replacement rules. Start a new review session to include
1072
- updated rules and criteria; existing sessions retain their saved versions.
1073
-
1074
- Version 0.8.4 also configures `呼ぶ`, `読み取る`, `拾う`, and the sahen predicate
1075
- `回収する` as weak-predicate candidates. MeCab matches their inflections for
1076
- any object, including `指示と宣言を読み取ります` and `最後のdetailsを拾います`.
1077
- This broadens review cues, not mandatory terminology changes; everyday and
1078
- technically valid uses can be retained with a specific reason. Literal mode
1079
- matches only the selected surfaces in the YAML. Longer contextual phrases take
1080
- precedence. `木全体` is an explicit contextual phrase in both modes because
1081
- IPADIC can parse `木全` as a surname; this narrowly addresses that segmentation
1082
- case without treating all names or compounds containing `木` as trees.
1083
-
1084
- Version 0.8.5 additionally reviews `拡張点`, `使えます`, `積み重なります`,
1085
- `開放しています`, `見落とします`, `扱えます`, `使っています`, and selected indirect
1086
- phrases. Existing tracking rules cover `追えます`. MeCab uses configured lemmas
1087
- for use, potential handling, accumulation, oversight, and sahen opening;
1088
- literal mode uses the listed surfaces. The shared examples distinguish an
1089
- extension point from its mechanism, layers from a stack, system detection from
1090
- human oversight, and processing from control. Revisions preserve actors,
1091
- capabilities and obligations, sequence, visibility, counts, and distribution.
1092
- These additions need a fresh scan and are contextual review guidance.
1093
-
1094
- Metaphorical-operation candidates include limited exact surfaces of
1095
- `地味に効く`, `静かに壊れる`, `時間を溶かす`, and `側に倒す`, including selected polite,
1096
- past, and connective forms listed in the packaged YAML. They use contextual
1097
- phrase matching in both tokenizers; this is not complete inflection coverage or
1098
- syntactic analysis. Bare verbs such as `効く`, `壊れる`, `溶かす`, and `倒す` are
1099
- not added as general metaphor candidates. Identify the actual effect, policy,
1100
- work, or failure state from evidence rather than applying a fixed replacement.
1101
- Keep valid technical meanings and necessary negation.
1102
-
1103
- Version 0.6.2 additionally matches these four phrases with MeCab/IPADIC
1104
- verb lemmas and adjacent predicate auxiliaries. For example, `地味に効かなかった`,
1105
- `静かに壊れていた`, `時間を溶かしてしまった`, and `側に倒しました` retain their
1106
- complete surfaces and polarity. A pattern is enabled only when its canonical
1107
- phrase (`地味に効く`, `静かに壊れる`, `時間を溶かす`, or `側に倒す`) is present in
1108
- the resolved `contextual-phrase.terms`. Removing those canonical entries from
1109
- custom rules disables their morphological patterns; remaining exact surfaces
1110
- still work. No YAML schema change is required. Allow lists accept the canonical
1111
- phrase or exact detected surface. The most specific overlapping phrase wins,
1112
- including allowed phrases. Masked inline content, unknown tokens, and paragraph
1113
- boundaries cannot bridge a pattern. This remains a limited contextual heuristic,
1114
- not a syntactic or semantic determination of metaphor. Literal mode retains
1115
- exact surfaces and does not acquire this inflection coverage.
1116
-
1117
- In version 0.6.2, a `repeated-ending` candidate points to the ending
1118
- of the third sentence in the first consecutive run within each paragraph.
1119
- A sentence without a matching ending interrupts the run. The candidate remains
1120
- informational because precise technical repetition can be necessary.
1121
-
1122
- The shared criteria distinguish reader instructions, actual system behavior,
1123
- and available capabilities. They also separate readability from checks for
1124
- missing information and unsupported additions. Sentence length, punctuation,
1125
- and list density are contextual cues, not fixed acceptance thresholds. These
1126
- updates are included in 0.6.2; start a new session to use updated criteria and rules.
1127
-
1128
- Literal term matching suppresses matches strictly contained in a longer matched
1129
- term, across categories. The longer term also suppresses contained matches when
1130
- it is allowed; separate occurrences remain candidates. Glossary and style checks
1131
- are independent. In MeCab mode, predicates outside a contextual phrase can still
1132
- be reported separately.
1133
-
1134
- Morphological candidates include `lemma`, `part_of_speech`, `negative`, and
1135
- `detector` alongside the original `match`, line, and column. Negation detection
1136
- covers common IPADIC negative auxiliaries; it is not full semantic analysis of
1137
- negation scope or double negatives. Unknown tokens are not guessed. Kana/kanji
1138
- variants of the alignment and gathering verbs have explicit canonical mappings;
1139
- other spelling variants are not automatically normalized.
1140
-
1141
- The session records the MeCab version and dictionary file hashes. Verification
1142
- reports analyzer changes instead of treating results from different dictionaries
1143
- as directly comparable. Prompt generation uses saved evidence and does not need
1144
- MeCab. Changed rules or dictionary settings require a new scan.
1145
-
1146
- Version 0.8.7 uses session schema 3; version 0.8.5 uses schema 2.
1147
- Sessions with a different schema or tool version cannot be loaded. Keep the original baseline for
1148
- an ongoing review and finish it with the original version, or start a new review
1149
- pass in a different directory:
1150
-
1151
- ```sh
1152
- asciidoc-pubkit review scan book.adoc --output .pubkit/review-0.8.7
1153
- ```
1154
-
1155
- Severity describes review priority, not proof of an error. There is no AI-authorship
1156
- score and no requirement to eliminate every match.
1157
-
1158
- In the default prose scope, only source-mapped running-prose paragraphs are reviewed. Headings, list items and
1159
- their continuations, tables, quotations, code, and passthrough blocks are excluded
1160
- from prose review. Common inline literals, macros, attribute references, URLs, and
1161
- Japanese quotation spans are masked. Complex inline syntax can exceed the masking
1162
- heuristic; review its diagnostics with care.
1163
-
1164
- Source locations are checked against original lines because Asciidoctor block
1165
- locations can be inaccurate at include boundaries. If a location cannot be matched
1166
- unambiguously, the paragraph is skipped with a coverage notice. Columns are
1167
- one-based Unicode character positions, not byte offsets or display widths.
1168
- An empty findings array does not establish full coverage or good prose.
1169
-
1170
- ## List review
1171
-
1172
- Use a separate session to review list descriptions, including reference-list text:
1173
-
1174
- ```sh
1175
- asciidoc-pubkit review scan book.adoc --scope lists --output .pubkit/lists
1176
- asciidoc-pubkit review prompt .pubkit/lists --output lists-review.md
1177
- asciidoc-pubkit review verify .pubkit/lists
1178
- ```
1179
-
1180
- The default output directory is `.pubkit/lists`. This scope reuses prose rules,
1181
- glossary, style, analyzer, and shared writing criteria. It does not include running
1182
- prose or edit headings. Each selected item appears once with heading context;
1183
- read additional evidence separately when its technical role cannot be established.
1184
-
1185
- Only exact source-mapped, single-line simple unordered or ordered item text is
1186
- editable, including supported nested outline lists. Multiline, description,
1187
- checklist, compound, ambiguous, and reused-source items remain protected with
1188
- coverage notices. List markers, nesting, structure, links, and other inline tokens
1189
- remain protected. Candidate columns include the source marker and indentation.
1190
- Session JSON retains the `paragraphs` and `paragraph_id` keys, with
1191
- `kind: list-item` and source `column`, `prefix`, and `suffix` metadata.
1192
-
1193
- Default prose scanning, scoring, and mechanical replacement keep their existing
1194
- prose scope. Heading body evidence continues to omit lists. A successful verify
1195
- checks preservation and does not establish editorial completion.
1196
-
1197
- ## Development
1198
-
1199
- ```sh
1200
- bundle install
1201
- bundle exec rake test
1202
- bundle exec ruby -Ilib exe/asciidoc-pubkit --help
1203
- gem build asciidoc-pubkit.gemspec
1204
- ```
1205
-
1206
- The tests exercise include-boundary mapping, inline masking, configuration,
1207
- contextual prompts, stale inputs, protected-content verification, and real MeCab
1208
- analysis of inflections, negative predicates, Unicode positions, and long lines.
1209
- Install MeCab and UTF-8 IPADIC before running the complete test suite.
1210
- GitHub Actions is configured for Ruby 3.2, 3.3, 3.4, and 4.0 on Linux.
1211
-
1212
- [`test/fixtures/prose_evaluation.ja.json`](test/fixtures/prose_evaluation.ja.json)
1213
- contains original Japanese technical prose for candidate regression and manual
1214
- revision evaluation. Automated tests check metaphor candidates in both
1215
- tokenizers, source positions, inline exclusions, and allow lists. The revision
1216
- pairs are manual evaluation cases, not an automated semantic checker or a
1217
- measured AI benchmark. Compare source and revision separately for readability,
1218
- information loss, and unsupported additions, using each case's review axes and
1219
- expected disposition. Cover conditions, negation, numbers, versions, actors,
1220
- causes, implementation requirements, and necessary repetition. Record the
1221
- model, prompt, source evidence, and human judgments when evaluating actual
1222
- generated revisions; fewer findings alone do not establish an improvement.
1223
-
1224
- ### Development prose benchmark
1225
-
1226
- The checkout provides `script/evaluate-prose` for measuring future detector and
1227
- prompt changes. This is a development tool, not an installed gem command; the
1228
- benchmark CLI calls are separate from the optional `review score --agent` path.
1229
- The fixed
1230
- [`prose_benchmark.ja.adoc`](test/fixtures/prose_benchmark.ja.adoc) contains 13
1231
- original editorial paragraphs with intentionally vague framing and metaphors,
1232
- inflection variants, and valid technical prose controls. Its
1233
- [`annotations`](test/fixtures/prose_benchmark.ja.json) contain 11 review targets
1234
- and separate source fact checklists. It is a small synthetic regression corpus,
1235
- not an AI authorship dataset or a representative measure of prose quality.
1236
-
1237
- Run the deterministic benchmark before and after a change:
1238
-
1239
- ```sh
1240
- bundle exec ruby script/evaluate-prose --output .pubkit/evaluation/before
1241
- # After changing the detector or prompt:
1242
- bundle exec ruby script/evaluate-prose --output .pubkit/evaluation/after \
1243
- --compare .pubkit/evaluation/before/report.json
1244
- ```
1245
-
1246
- The report measures candidate precision, recall, F1, and location accuracy on a
1247
- 0–100 scale for `generic-framing`, metaphorical operations, and `repeated-ending`.
1248
- Other rule findings are counted separately and are not judged against these
1249
- annotations. Detection matches a target's paragraph and kind; location accuracy
1250
- then checks the one-based source position, represented internally as a zero-based
1251
- Unicode character offset within that paragraph. The annotated repeated-ending
1252
- location is the matching ending of the third sentence in the consecutive run.
1253
- A candidate can be correctly detected even when the reviewer should keep it.
1254
- Zero denominators are reported as `null`, not perfect scores. Duplicate detections
1255
- count as false positives. These scores measure the detector, not the manuscript.
1256
-
1257
- The checked-in [`MeCab baseline`](benchmark/baseline-mecab.json), captured before
1258
- the detector changes, has precision 100, recall 81.818, F1 90, and location
1259
- accuracy 77.778. It misses two inflected metaphor phrases and mislocates two
1260
- repeated-ending candidates. Reports record source, criteria, rules, corpus, and
1261
- dictionary fingerprints. Comparisons reject changed corpora, scoring versions,
1262
- analyzers, or dictionaries. Reports with configuration fingerprints also reject
1263
- changed benchmark configuration. A fixed empty configuration
1264
- keeps these trials independent of auto-discovered manuscript settings.
1265
- The 0.6.2 location correction raises location accuracy to 100 without
1266
- changing precision, recall, or F1 on this corpus. Adding the four MeCab predicate
1267
- patterns then raises precision, recall, F1, and location accuracy to 100 on these
1268
- 11 targets. This is regression evidence for the fixed synthetic corpus, not
1269
- evidence of general performance on unseen manuscripts; literal recall remains
1270
- 81.818.
1271
- Record your own baseline when dictionary fingerprints
1272
- differ. `--tokenizer literal` explicitly selects a separate limited-mode run;
1273
- there is no automatic fallback, and literal results do not validate MeCab.
1274
-
1275
- ### Optional local AI evaluation
1276
-
1277
- Use an installed, authenticated Codex or Claude CLI to perform rewrite and judge
1278
- trials explicitly. A local CLI may call its configured remote model provider and
1279
- consume account usage; this is not an offline model test. Normal `rake test`
1280
- does not run either CLI. For example:
1281
-
1282
- ```sh
1283
- bundle exec ruby script/evaluate-prose --agent codex --repeats 3 \
1284
- --output .pubkit/evaluation/ai-before
1285
- bundle exec ruby script/evaluate-prose --agent codex --repeats 3 \
1286
- --output .pubkit/evaluation/ai-after \
1287
- --compare .pubkit/evaluation/ai-before/report.json
1288
- # Or use Claude:
1289
- bundle exec ruby script/evaluate-prose --agent claude \
1290
- --output .pubkit/evaluation/claude-before
1291
- ```
1292
-
1293
- Each trial generates the actual saved review prompt, requests paragraph revisions
1294
- as JSON, and runs the existing mechanical verifier. A fresh judge invocation
1295
- evaluates both original and revised prose with neutral A/B labels, alternating
1296
- their order across trials. The judge sees source evidence but no findings, tool
1297
- revision labels, or expected calibration answers. The writer receives the source
1298
- fact checklist in addition to the review prompt, so this measures an evidence-
1299
- assisted workflow rather than every real-world manuscript review.
1300
-
1301
- Sentence clarity and paragraph coherence are separately rated 1–3 and displayed
1302
- as 0, 50, or 100 before averaging. These ordinal averages are descriptive
1303
- summaries, not validated interval measurements. Fact retention measures the
1304
- percentage of annotated source facts preserved; addition-free and substitution-
1305
- free paragraph percentages remain separate. Known acceptable, incorrect, and
1306
- unsupported revisions from `prose_evaluation.ja.json` calibrate the judge using
1307
- accuracy and balanced accuracy across the three dispositions. Inspect poor
1308
- calibration before interpreting quality scores. No combined AI-likeness score or
1309
- semantic pass is produced: `meaning_verified` remains `false`.
1310
- Mechanical verification results and their pass rate are also reported separately.
1311
- Quality scores from a trial with preservation violations remain visible for
1312
- diagnosis; a completed evaluation does not authorize accepting that revision.
1313
-
1314
- One trial is a smoke test; use at least three to inspect variation. Reports retain
1315
- individual scores, means, population standard deviations, and ranges. They do
1316
- not perform a significance test. Same-model judging can favor the writer's style;
1317
- `--judge-agent` and `--judge-model` select a separate evaluator. `--model` selects
1318
- the writer model; omitted model options use each CLI's default. AI comparisons
1319
- require the same reported writer and judge models, CLI versions, rubric, and
1320
- calibration corpus. CLI defaults can change, so retain the recorded model IDs
1321
- and use explicit model options for controlled comparisons. Score changes can
1322
- reflect sampling variation as well as implementation changes.
1323
-
1324
- The runner uses argument arrays rather than shell interpolation, read-only Codex
1325
- execution or tool-disabled Claude execution, and a per-invocation timeout
1326
- (`--timeout`, default 300 seconds). The CLI may still load its user configuration;
1327
- use consistent settings for comparisons. Current adapters require the flags
1328
- shown by `codex exec --help` and `claude --help`; older CLI versions may need an
1329
- update. Missing CLIs, authentication errors, timeouts, and malformed responses
1330
- fail explicitly. Existing output directories are never replaced. Partial
1331
- artifacts remain available after failures. Results, prompts, responses, and review
1332
- sessions belong under ignored `.pubkit/`; do not commit private evaluation runs.
1333
-
1334
- ## Customize review rules
1335
-
1336
- The UTF-8 YAML file [`data/review-rules.ja.yml`](data/review-rules.ja.yml) is
1337
- included in the gem and loaded by default. Edit that file when running a local
1338
- checkout, or copy it to a project-owned file for custom rules. No Ruby changes
1339
- are required to update candidate terms.
1340
-
1341
- ```sh
1342
- asciidoc-pubkit review scan book.adoc --rules ./review-rules.yml
1343
- make run ARGS="review scan book.adoc --rules ./review-rules.yml"
1344
- ```
1345
-
1346
- For an installed gem, copy the default file with:
1347
-
1348
- ```sh
1349
- ruby -rasciidoc_pubkit -e 'puts File.read(AsciidocPubkit::RuleSet::DEFAULT_PATH)' > review-rules.yml
1350
- ```
1351
-
1352
- Alternatively, configure a path in `.asciidoc-pubkit.yml`:
1353
-
1354
- ```yaml
1355
- review:
1356
- rules: review-rules.yml
99
+ asciidoc-pubkit review score book.adoc
100
+ asciidoc-pubkit writing criteria --lang ja
101
+ asciidoc-pubkit writing prompt --lang ja --output writing-prompt.md
1357
102
  ```
1358
103
 
1359
- Precedence is `--rules`, then `review.rules`, then the packaged default.
1360
- CLI paths are relative to the current working directory; configuration paths
1361
- are relative to the configuration file. A custom file replaces the entire rule
1362
- set; it is not merged with defaults. Start by copying the standard file.
104
+ Existing review sessions require the exact tool version that created them.
105
+ Before upgrading, finish ongoing reviews with that version or preserve their
106
+ baselines and start a new review in a separate directory with v1.0.0. A new
107
+ scan cannot verify preservation relative to an earlier baseline.
1363
108
 
1364
- ### Rule file format (schema version 1)
109
+ ## Documentation
1365
110
 
1366
- All top-level fields below are required. Unknown keys and invalid types are
1367
- rejected. YAML aliases and object tags are not supported.
1368
-
1369
- | Field | Format and behavior |
111
+ | Guide | Contents |
1370
112
  | --- | --- |
1371
- | `schema_version` | Integer `1` |
1372
- | `terms` | Mapping containing all five categories listed below |
1373
- | `verbs` | Mapping from canonical verb forms to nonempty arrays of MeCab/IPADIC dictionary forms; each dictionary form belongs to only one canonical form |
1374
- | `sahen` | Array of nouns matched with a following `する` or potential `できる` verb |
1375
- | `negative_only` | Array of canonical predicates restricted to negative forms; use the noun plus `する` for sahen predicates |
1376
- | `compound_nouns` | Array of terms matched across contiguous noun tokens; each must also appear in `abstract-reference.terms` |
1377
-
1378
- Each `terms` category must contain `terms` (an array of unique nonempty strings)
1379
- and `question` (a nonempty review instruction string). The required categories
1380
- are `abstract-reference`, `weak-predicate`, `vague-degree`, `contextual-phrase`,
1381
- and `generic-framing`. Empty term arrays disable that category's literal
1382
- candidates. Empty `verbs`, `sahen`, and `compound_nouns` collections disable their
1383
- respective morphological matchers. Keep `negative_only` consistent with the
1384
- configured predicates.
1385
-
1386
- In literal mode, all category term lists use exact phrase matching. In MeCab
1387
- mode, abstract nouns and degree adjectives use dictionary forms, while predicates
1388
- use `verbs` and `sahen`; add a predicate's desired literal surface to
1389
- `weak-predicate.terms` as well if literal mode should detect it. Contextual and
1390
- generic framing phrases use literal matching in both modes, with the
1391
- MeCab exception for the four configured contextual predicate patterns described
1392
- above. Questions apply to
1393
- both detectors. Glossary, style, repeated-ending checks, inline exclusions, and
1394
- morphological suffix handling remain implemented in Ruby.
1395
-
1396
- A scan saves the resolved rule contents and source path in `manifest.json`.
1397
- Prompt generation and verification use the saved contents, even if the original
1398
- YAML file is subsequently edited or removed. Start a new session to apply rule
1399
- changes. Older sessions without a rule snapshot fall back to the currently
1400
- installed default file; start a new session for reproducible custom-rule reviews.
1401
-
1402
- ## References
1403
-
1404
- The shared criteria and default questions draw on the following editorial
1405
- sources. Their stylistic choices differ, including whether headings should state
1406
- conclusions. Candidate detection therefore leaves contextual judgment, document
1407
- structure, and final edits to the reviewer.
1408
-
1409
- - [natural-japanese](https://github.com/coji/natural-japanese): separates mechanical
1410
- detection from contextual judgment and identifies repetitive framing. Applied
1411
- here: candidate findings feed a contextual review prompt, while phrases such as
1412
- `重要なのは` and `このように` invite inspection rather than automatic deletion.
1413
- - [yomiyasu](https://github.com/nanaism/yomiyasu):
1414
- informs evidence-based review of
1415
- metaphorical operations, distinctions between instructions and capabilities,
1416
- and separate assessment of meaning preservation and readability. Applied here:
1417
- four limited metaphor patterns and third-sentence repetition locations inform
1418
- candidate detection; the shared criteria require evidence for concrete rewrites.
1419
- - [日本語技術文書の文章規範](https://gist.github.com/k16shikano/fd287c3133457c4fd8f5601d34aa817d):
1420
- informs paragraph logic, evidence scope, and meaningful uncertainty. Applied
1421
- here: the shared criteria start from each paragraph's technical purpose and
1422
- preserve necessary conditions, uncertainty, and exact terminology.
1423
- - [AI臭い文章とは何なのか](https://speakerdeck.com/nasuvitz/ai-kusai-bunshou-toha-nanina-no-ka):
1424
- provides examples of unnecessary contrast, abstract referents, and paired short
1425
- sentences. Applied here: the shared criteria ask reviewers to inspect these
1426
- patterns in context and recover concrete referents and connected explanations.
1427
-
1428
- The development evaluation adapts ideas from the following primary research;
1429
- its engineering audience, corpus, and rubric do not reproduce those benchmarks.
1430
- Research texts and datasets are not redistributed here.
1431
-
1432
- - [Evaluation of Document-Level Text Simplification in Japanese](https://aclanthology.org/2026.lrec-1.85/)
1433
- (Yamashita et al., LREC 2026): separates information preservation from sentence
1434
- and document simplicity and evaluates LLM judgments against human annotations.
1435
- Its elementary-school audience and Wikipedia corpus differ from this project.
1436
- Applied here: the scoring rubric separates sentence clarity from paragraph
1437
- coherence, and the development judge evaluates fact retention independently.
1438
- - [Evaluating Factuality in Text Simplification](https://aclanthology.org/2022.acl-long.506/)
1439
- (Devaraj et al., ACL 2022): distinguishes insertion, deletion, and substitution
1440
- errors. Applied here: development trials check each source fact and report
1441
- unsupported additions and substitutions separately; a readable rewrite can
1442
- still fail preservation review.
1443
- - [Evaluating Document Simplification: On the Importance of Separately Assessing Simplicity and Meaning Preservation](https://aclanthology.org/2024.readi-1.1/)
1444
- (Cripwell et al., READI 2024): motivates separate readability and preservation
1445
- scores. Applied here: readability dimensions and preservation outcomes remain
1446
- separate in benchmark reports; the direct manuscript score makes no
1447
- preservation claim. SARI-style overlap metrics are not adopted.
113
+ | [Installation](docs/installation.md) | RubyGems, Bundler, source, local checkout, MeCab/IPADIC |
114
+ | [Document commands](docs/document-commands.md) | Outline, metadata, cross-references, English-title indexes |
115
+ | [Prose replacements](docs/replacements.md) | Rule format, imports, regex compatibility, preview/apply, preservation |
116
+ | [Review workflow](docs/review-workflow.md) | Scanning, heading review, prompts, sessions, verification, exit codes |
117
+ | [List review](docs/list-review.md) | Separate list sessions, editable items, protected syntax |
118
+ | [Scoring](docs/scoring.md) | Candidate density, optional AI readability ratings, output |
119
+ | [Writing](docs/writing.md) | Shared Japanese criteria and writing prompts |
120
+ | [Configuration](docs/configuration.md) | Discovery, precedence, paths, glossary, exclusions |
121
+ | [Rules and coverage](docs/rules-and-coverage.md) | Candidate detection, source positions, scope, session compatibility |
122
+ | [Custom review rules](docs/custom-rules.md) | Complete rule replacement, strict YAML schema, saved rules |
123
+ | [Architecture](docs/architecture.md) | Review principles, analysis pipeline, scoring algorithms |
124
+ | [Development](docs/development.md) | Tests, synthetic benchmark, explicit AI evaluation trials |
125
+ | [References](docs/references.md) | Editorial and research foundations |
126
+ | [English review proposal](docs/english-review-research.md) | Future design research; English review is not implemented |
127
+
128
+ See [CHANGELOG.md](CHANGELOG.md) for release history.
1448
129
 
1449
130
  ## License
1450
131