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