asciidoc-pubkit 0.9.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,246 @@
1
+ # Prose evaluation
2
+
3
+ Use a fixed set of Japanese technical paragraphs to compare detector or review
4
+ criteria changes against a project-defined baseline. Keep detection performance,
5
+ readability, and meaning preservation separate so that a clearer rewrite cannot
6
+ hide a lost condition or invented fact.
7
+
8
+ This guide describes the version 1.0.1 development checkout, including the
9
+ `technical-prose-v2` corpus and criteria update. The evaluation runner is not an
10
+ installed gem command. It does not measure Japanese naturalness or AI authorship
11
+ as a single validated score.
12
+
13
+ ## Three different evaluations
14
+
15
+ | Evaluation | Input and method | What the number means |
16
+ | --- | --- | --- |
17
+ | `review score` without `--agent` | A manuscript; candidate count normalized by unmasked prose length | Candidate-density indicator, not correctness or naturalness |
18
+ | `script/evaluate-prose` without `--agent` | Fixed corpus and annotated targets; deterministic analysis | Detector precision, recall, F1, and location accuracy |
19
+ | `script/evaluate-prose --agent codex` or `--agent claude` | Fixed corpus; generated review prompt, rewrite, and separate judge invocation | Readability and checklist preservation before and after rewriting |
20
+
21
+ The default manuscript score is `max(0, 100 - 5 × candidates per 1,000 characters)`.
22
+ A higher score means fewer detected candidates at that text length. Necessary
23
+ repetition can still be a candidate, and fewer candidates alone do not establish
24
+ better prose. See [Manuscript scoring](scoring.md) for the separate optional
25
+ single-manuscript readability rating; that path has no original-versus-revision
26
+ fact checklist.
27
+
28
+ For a detector change, use the deterministic benchmark. For a writing or review
29
+ criteria change, use the optional rewrite-and-judge trials to measure its effect
30
+ on the actual revisions. Criteria can change while deterministic detector scores
31
+ remain identical.
32
+
33
+ ## Fixed test data
34
+
35
+ All examples are original project-authored editorial fixtures. They intentionally
36
+ include patterns associated with generated prose, plus valid technical controls.
37
+ They are not a collected dataset of known AI outputs or a representative sample
38
+ of Japanese writing.
39
+
40
+ | File | Contents and role |
41
+ | --- | --- |
42
+ | [prose_benchmark.ja.adoc](../test/fixtures/prose_benchmark.ja.adoc) | 21 paragraphs used as the actual AsciiDoc input |
43
+ | [prose_benchmark.ja.json](../test/fixtures/prose_benchmark.ja.json) | Matching paragraph IDs and text, 11 annotated detector targets, and preservation checklists |
44
+ | [prose_benchmark.yml](../test/fixtures/prose_benchmark.yml) | Fixed empty configuration that isolates the benchmark from discovered manuscript settings |
45
+ | [prose_evaluation.ja.json](../test/fixtures/prose_evaluation.ja.json) | Detection examples and 20 manual revision pairs with expected `accept`, `reject`, or `needs-evidence` dispositions |
46
+
47
+ The corpus includes framing such as `重要なのは`, metaphorical operations such
48
+ as `地味に効く`, inflected and negative forms, and repeated endings. Controls
49
+ include literal verbs, established technical terms, necessary repetition,
50
+ concurrency requirements, and protected inline code.
51
+
52
+ Eight paragraphs added in `technical-prose-v2` cover quantity targets, required
53
+ order, modifier targets, condition scope, parallel checks, advice versus actual
54
+ behavior, plain style, and punctuation and purpose scope. They have no additional
55
+ detector targets but still reach the reviewer and judge. The checklists include
56
+ explicit editorial constraints as well as technical facts.
57
+
58
+ For example, this pair must be rejected even though its numeral is unchanged:
59
+
60
+ | Original | Revision | Preservation issue |
61
+ | --- | --- | --- |
62
+ | 各ワーカーは最大3回再試行します。 | 全ワーカーで合計3回まで再試行します。 | A per-worker limit became an aggregate limit |
63
+
64
+ Other revision pairs cover reversed recovery order, authentication conditions
65
+ incorrectly extended to audit logging, independent checks made conditional, and
66
+ an unsolicited change from plain to polite style. Acceptable pairs and unresolved
67
+ cases prevent calibration from treating every change as an error.
68
+
69
+ ## What normal tests check
70
+
71
+ Run the complete suite from the repository root with MeCab and UTF-8 IPADIC
72
+ installed:
73
+
74
+ ```sh
75
+ bundle exec rake test
76
+ ```
77
+
78
+ [Prose benchmark tests](../test/prose_benchmark_test.rb) check exact agreement
79
+ between the AsciiDoc input and JSON corpus, source mapping and paragraph order,
80
+ annotated target positions, false positives and duplicates, and both MeCab and
81
+ explicit literal analysis. They also check response validation, comparison
82
+ compatibility, summary calculations, and mechanical verification in a trial
83
+ using a fake evaluator. The fake evaluator makes the workflow test repeatable;
84
+ it does not assess readability or understand the revision pairs.
85
+
86
+ [Default rule tests](../test/default_rules_test.rb) check metaphor detection,
87
+ allow lists, and protected text using the detection examples.
88
+ [Writing tests](../test/writing_test.rb) and
89
+ [review tests](../test/review_test.rb) check that the shared criteria reach writing
90
+ prompts and saved review prompts. Existing sessions retain their saved criteria.
91
+
92
+ Normal tests never invoke Codex or Claude. A passing suite establishes these
93
+ contracts and regressions, not a measured improvement in model-generated prose.
94
+ Literal-mode checks do not validate MeCab; there is no automatic fallback.
95
+
96
+ ## Establish a detector baseline
97
+
98
+ Before changing the detector or review criteria, save a result on the fixed
99
+ corpus. After the change, use a new output directory and compare it:
100
+
101
+ ```sh
102
+ bundle exec ruby script/evaluate-prose --output .pubkit/evaluation/before
103
+ # After changing the detector or review criteria:
104
+ bundle exec ruby script/evaluate-prose --output .pubkit/evaluation/after \
105
+ --compare .pubkit/evaluation/before/report.json
106
+ ```
107
+
108
+ The report scores only `generic-framing`, the four metaphorical-operation
109
+ patterns, and `repeated-ending`. Other rule findings are counted separately.
110
+ Detection matches a target's paragraph and kind. Location accuracy then checks
111
+ its exact Unicode character offset; CLI source columns are one-based. A repeated
112
+ ending target is at the matching ending of the third consecutive sentence.
113
+
114
+ | Report field | Definition |
115
+ | --- | --- |
116
+ | `detection.precision` | Matched targets divided by detected scored candidates, × 100 |
117
+ | `detection.recall` | Matched targets divided by annotated targets, × 100 |
118
+ | `detection.f1` | 2 × matched targets divided by the sum of detected and annotated counts, × 100 |
119
+ | `detection.location_accuracy` | Correctly located matches divided by all matched targets, × 100 |
120
+ | `detection_delta` | After minus before for these four metrics, in percentage points |
121
+
122
+ Duplicate detections count as false positives. Zero denominators are `null`, not
123
+ perfect scores. A correctly detected candidate can still deserve a `keep`
124
+ decision in contextual review.
125
+
126
+ The historical [MeCab baseline](../benchmark/baseline-mecab.json) belongs to the
127
+ original 13-paragraph `technical-prose-v1` corpus. Its precision was 100, recall
128
+ 81.818, F1 90, and location accuracy 77.778. Later detector fixes brought the
129
+ 11-target MeCab results to 100 for all four metrics; literal recall remained
130
+ 81.818. Keep that historical report unchanged. It cannot be compared directly
131
+ with v2: create a new baseline after expanding the corpus.
132
+
133
+ ## Compare review criteria with AI trials
134
+
135
+ First fix the corpus, calibration pairs, and judge rubric. Save an AI baseline
136
+ before changing the review criteria, then change only the intended criteria and
137
+ rerun under the same conditions:
138
+
139
+ ```sh
140
+ bundle exec ruby script/evaluate-prose --agent codex --repeats 3 \
141
+ --output .pubkit/evaluation/ai-before
142
+ # After changing only the review criteria:
143
+ bundle exec ruby script/evaluate-prose --agent codex --repeats 3 \
144
+ --output .pubkit/evaluation/ai-after \
145
+ --compare .pubkit/evaluation/ai-before/report.json
146
+ ```
147
+
148
+ These commands use each CLI's default model. For controlled comparisons, use
149
+ `--model` and `--judge-model` to select fixed writer and judge models available
150
+ in your environment. `--judge-agent` selects a separate evaluator CLI; otherwise
151
+ the writer's CLI is used. Same-model judging can favor the writer's style.
152
+ Claude trials use `--agent claude`. AI trials require MeCab; literal mode is
153
+ available only for deterministic detector evaluation.
154
+
155
+ Each trial performs these steps:
156
+
157
+ 1. Create a fresh review session and generate its actual saved review prompt.
158
+ 2. Supply the prompt and source checklists to the writer, requesting one JSON
159
+ paragraph per corpus ID. Faithful paragraphs can remain unchanged.
160
+ 3. Install revisions in the temporary trial manuscript and run mechanical
161
+ verification for scope, inline preservation, and structure.
162
+ 4. Invoke the judge separately with original and revised text labelled A/B,
163
+ alternating the order across trials. It receives source evidence but no
164
+ candidate findings or expected calibration answers.
165
+ 5. Summarize readability, checklist retention, additions, substitutions,
166
+ calibration, and mechanical verification separately.
167
+
168
+ The writer receives evidence checklists, so the trial measures an
169
+ evidence-assisted review workflow. It does not simulate every manuscript review.
170
+ The judge sees original source evidence, so neutral labels reduce presentation
171
+ bias without guaranteeing full blindness.
172
+
173
+ ## Read the AI results
174
+
175
+ | Metric | Interpretation |
176
+ | --- | --- |
177
+ | `sentence_clarity` | Actors, actions, conditions, and sentence relationships are understandable |
178
+ | `paragraph_coherence` | Sentences form a connected explanation |
179
+ | `fact_retention` | Percentage of supplied checklist entries retained, including explicit editorial constraints |
180
+ | `addition_free_paragraphs` | Percentage with no unsupported additions identified by the judge |
181
+ | `substitution_free_paragraphs` | Percentage with no substitutions identified by the judge |
182
+ | Calibration `accuracy` | Percentage of revision-pair dispositions matching the expected answers |
183
+ | Calibration `balanced_accuracy` | Mean recall across `accept`, `reject`, and `needs-evidence` classes |
184
+ | Mechanical verification pass rate | Percentage of trials passing the existing mechanical verifier |
185
+
186
+ Readability is rated per paragraph on an ordinal scale: 1 means hard to
187
+ understand, 2 means some ambiguity or distracting framing, and 3 means clear.
188
+ Ratings are mapped to 0, 50, and 100 and averaged. These averages are descriptive
189
+ summaries, not validated interval measurements. Inspect the paragraph reasons
190
+ and actual revisions alongside the numbers.
191
+
192
+ `ai.trials` contains each trial's `original`, `revision`, and `delta` metrics;
193
+ `delta` is revision minus original. `ai.summary` retains means, population
194
+ standard deviations, minima, and maxima. `ai_delta` compares these summary means
195
+ between runs. In particular, `ai_delta.delta.sentence_clarity` compares the
196
+ within-trial clarity improvement of the new run with that of the baseline.
197
+
198
+ For an illustrative example, clarity of 50 before rewriting and 75 afterwards
199
+ means a within-trial delta of +25. If the next run's delta is +30, the improvement
200
+ relative to the baseline is +5 points. These are example numbers, not measured
201
+ results. A readability gain with lower retention or new unsupported facts should
202
+ not be accepted merely because it scores higher.
203
+
204
+ One trial is a smoke test. Use at least three to inspect variation; the runner
205
+ provides no significance test. Poor calibration warrants inspection before
206
+ interpreting quality results. `meaning_verified` remains `false` regardless of
207
+ scores or mechanical pass rate.
208
+
209
+ ## Comparison conditions and artifacts
210
+
211
+ Comparisons require the same corpus, document, benchmark identity, scoring
212
+ version, analyzer, and dictionary. Reports with configuration fingerprints also
213
+ check the fixed configuration. AI comparisons additionally require matching
214
+ judge rubric and calibration fingerprints, CLI versions, and actual reported
215
+ writer and judge models. Missing actual model identity prevents AI comparison.
216
+
217
+ Keep CLI user configuration consistent as well. Reports record criteria, rules,
218
+ source, harness, and analyzer fingerprints, but a fingerprint cannot restore old
219
+ content: retain the source revision and any uncommitted changes needed to
220
+ reproduce the run. A changed corpus, judge rubric, or calibration set needs a
221
+ new baseline. Compare the intended criteria or detector change only after the
222
+ other evaluation conditions are fixed.
223
+
224
+ AI trials require installed, authenticated local Codex or Claude CLIs. They may
225
+ call their configured remote model providers and consume account usage. The
226
+ runner uses argument arrays, read-only Codex execution or tool-disabled Claude
227
+ execution, and a per-invocation timeout (`--timeout`, default 300 seconds).
228
+ Missing CLIs, authentication failures, timeouts, and invalid responses fail
229
+ explicitly. See [the adapter](../lib/asciidoc_pubkit/local_evaluator.rb) for the
230
+ required flags; older CLIs may need an update.
231
+
232
+ Outputs are saved under the chosen directory, including `report.json`, AI-mode
233
+ `detection.json`, and per-trial review sessions, verification results, prompts,
234
+ and evaluator responses. Existing output directories are never replaced.
235
+ Partial artifacts remain after a failure. Keep results under ignored `.pubkit/`;
236
+ do not commit private evaluation artifacts.
237
+
238
+ For the version 1.0.1 yomiyasu v1.0.6 adaptation, the expanded v2 deterministic
239
+ benchmark ran before and after the criteria change: precision, recall, F1, and
240
+ location accuracy were all 100, with zero deltas. The suite passed 203 tests and
241
+ 2,552 assertions with real MeCab/IPADIC. These are detector and workflow checks.
242
+ External AI rewrite-and-judge trials have not yet been run for this change, so
243
+ its readability and preservation improvement remains unmeasured.
244
+
245
+ [Development](development.md) · [Manuscript scoring](scoring.md) ·
246
+ [Back to README](../README.md)
@@ -0,0 +1,54 @@
1
+ # References
2
+
3
+ The shared criteria and default questions draw on the following editorial
4
+ sources. Their stylistic choices differ, including whether headings should state
5
+ conclusions. Candidate detection therefore leaves contextual judgment, document
6
+ structure, and final edits to the reviewer.
7
+
8
+ - [natural-japanese](https://github.com/coji/natural-japanese): separates mechanical
9
+ detection from contextual judgment and identifies repetitive framing. Applied
10
+ here: candidate findings feed a contextual review prompt, while phrases such as
11
+ `重要なのは` and `このように` invite inspection rather than automatic deletion.
12
+ - [yomiyasu](https://github.com/nanaism/yomiyasu):
13
+ informs evidence-based review of
14
+ metaphorical operations, distinctions between instructions and capabilities,
15
+ and separate assessment of meaning preservation and readability. Applied here:
16
+ four limited metaphor patterns and third-sentence repetition locations inform
17
+ candidate detection; the shared criteria require evidence for concrete rewrites.
18
+ The 1.0.1 update adapts the structural comparison and sentence-function
19
+ guidance from [v1.0.6, commit 4075fc3](https://github.com/nanaism/yomiyasu/commit/4075fc34fb0333ca1fe42d32cd619338f4a138ba):
20
+ compare modifier and quantity targets, condition scope, parallel relationships,
21
+ and order before and after revision; preserve sentence function separately
22
+ from plain or polite style. The new examples are original project fixtures.
23
+ Markdown-specific bold fixes and numeric style thresholds are not imported.
24
+ - [日本語技術文書の文章規範](https://gist.github.com/k16shikano/fd287c3133457c4fd8f5601d34aa817d):
25
+ informs paragraph logic, evidence scope, and meaningful uncertainty. Applied
26
+ here: the shared criteria start from each paragraph's technical purpose and
27
+ preserve necessary conditions, uncertainty, and exact terminology.
28
+ - [AI臭い文章とは何なのか](https://speakerdeck.com/nasuvitz/ai-kusai-bunshou-toha-nanina-no-ka):
29
+ provides examples of unnecessary contrast, abstract referents, and paired short
30
+ sentences. Applied here: the shared criteria ask reviewers to inspect these
31
+ patterns in context and recover concrete referents and connected explanations.
32
+
33
+ The development evaluation adapts ideas from the following primary research;
34
+ its engineering audience, corpus, and rubric do not reproduce those benchmarks.
35
+ Research texts and datasets are not redistributed here.
36
+
37
+ - [Evaluation of Document-Level Text Simplification in Japanese](https://aclanthology.org/2026.lrec-1.85/)
38
+ (Yamashita et al., LREC 2026): separates information preservation from sentence
39
+ and document simplicity and evaluates LLM judgments against human annotations.
40
+ Its elementary-school audience and Wikipedia corpus differ from this project.
41
+ Applied here: the scoring rubric separates sentence clarity from paragraph
42
+ coherence, and the development judge evaluates fact retention independently.
43
+ - [Evaluating Factuality in Text Simplification](https://aclanthology.org/2022.acl-long.506/)
44
+ (Devaraj et al., ACL 2022): distinguishes insertion, deletion, and substitution
45
+ errors. Applied here: development trials check each source fact and report
46
+ unsupported additions and substitutions separately; a readable rewrite can
47
+ still fail preservation review.
48
+ - [Evaluating Document Simplification: On the Importance of Separately Assessing Simplicity and Meaning Preservation](https://aclanthology.org/2024.readi-1.1/)
49
+ (Cripwell et al., READI 2024): motivates separate readability and preservation
50
+ scores. Applied here: readability dimensions and preservation outcomes remain
51
+ separate in benchmark reports; the direct manuscript score makes no
52
+ preservation claim. SARI-style overlap metrics are not adopted.
53
+
54
+ [Back to README](../README.md)
@@ -0,0 +1,193 @@
1
+ # Prose replacements
2
+
3
+ The replacement commands apply author-supplied mechanical replacement rules without MeCab or an AI
4
+ CLI. Review candidates and glossary variants remain advisory and are never
5
+ implicitly applied. Replacement rules are separate from review rules.
6
+
7
+ ```sh
8
+ asciidoc-pubkit replace check book.adoc --rules replacements.yml
9
+ asciidoc-pubkit replace diff book.adoc --rules replacements.yml
10
+ asciidoc-pubkit replace apply book.adoc --rules replacements.yml
11
+ ```
12
+
13
+ `check` reports original text, proposed text, rule IDs (`rule-1`, etc.), source
14
+ paths, one-based Unicode lines/columns, and a coverage-notice count. Its exit code
15
+ is 1 when replacements are available, 0 otherwise. `diff` previews unified diffs
16
+ without editing; it requires the external `diff` command. `apply` explicitly
17
+ authorizes source replacement without prompting. Successful diff/apply commands
18
+ return 0; invalid rules, conflicts, unsafe edits, and input/output failures return
19
+ 2. Check/diff accept `--output` for a new file only; apply rejects `--output`.
20
+
21
+ Starting with version 0.8.2, invalid rule files report their original YAML file
22
+ and one-based line number on the first error line, followed by the existing
23
+ reason on the next line. Imported files and entries in pattern arrays retain
24
+ their own source locations. For example:
25
+
26
+ ```text
27
+ Error: /path/to/prh.yml:162
28
+ Unsupported regex flags; only optional i is supported (all matches are collected).
29
+ ```
30
+
31
+ Rules are validated before any manuscript is replaced. All replacement commands
32
+ stop with exit code 2 on invalid rules, including errors found in imported files.
33
+
34
+ All three accept `--lang ja`, `--base-dir`, `--config`, and `--only` (an included
35
+ source file). Normal configuration discovery and `review.base_dir`, `language`,
36
+ `attributes`, and `exclude` control parsing and selection. `--rules` is required;
37
+ `review.rules` and glossary entries do not supply replacement rules. There are
38
+ no built-in replacement rules and no automatic search for `prh.yml`.
39
+
40
+ ### Limited prh-format rules
41
+
42
+ The supported format is a strict subset of [prh](https://github.com/prh/prh):
43
+
44
+ ```yaml
45
+ version: 1
46
+ rules:
47
+ - expected: '®'
48
+ pattern: '®'
49
+ - expected: '($1)'
50
+ pattern: '/(([^()\r\n]+))/'
51
+ specs:
52
+ - from: '設定(任意)'
53
+ to: '設定(任意)'
54
+ - expected: '/'
55
+ patterns:
56
+ - '/'
57
+ ```
58
+
59
+ The root requires `version: 1` and accepts optional `rules` and `imports` arrays.
60
+ Starting with version 0.8.1, omitted arrays default to empty. Version 0.8.0
61
+ requires `rules` and rejects `imports`. Each rule requires a string
62
+ `expected` (empty strings permit deletion) and exactly one of `pattern` (a
63
+ nonempty string or, starting with version 0.8.1, a nonempty array of nonempty
64
+ strings) or `patterns` (a nonempty array of nonempty strings). Array-valued
65
+ `pattern` is equivalent to `patterns`; specifying both keys is rejected. Optional
66
+ `specs` is an array of exact `from`/`to` string pairs, validated on load. Specs
67
+ exercise the rule on plain text, not AsciiDoc selection or inline protection.
68
+
69
+ Strings not beginning with `/` match literally. `/.../` denotes a regex; the
70
+ version 0.8.1 also accepts `/.../i` for Ruby case-insensitive matching.
71
+ Version 0.8.0 rejects all flags. All occurrences are collected. The implementation
72
+ uses Ruby regexes with
73
+ a timeout and accepts a limited common syntax: character classes, ordinary
74
+ captures, noncapturing groups, lookarounds, alternatives, anchors, quantifiers,
75
+ and the escapes `\n`, `\r`, `\t`, `\d`, `\D`, `\s`, `\S`, `\w`, `\W`
76
+ and escaped punctuation. Ruby regex character-class behavior applies; this is
77
+ not a JavaScript regex engine or a promise of full prh equivalence. Engine-specific
78
+ groups/escapes and flags other than a single `i` are rejected. A leading literal slash must be expressed
79
+ as an escaped regex, for example `/\//`. Zero-length matches are rejected.
80
+
81
+ Replacement strings support `$1` through `$99` for existing capture groups and
82
+ `$$` for a literal dollar sign. Unsupported dollar references are rejected when
83
+ matched. Missing optional captures expand to empty strings. YAML single quotes
84
+ are recommended to keep backslashes literal. Unknown fields, including
85
+ `options` and `regexpMustEmpty`, and omitted patterns are rejected rather than
86
+ ignored. prh's automatic pattern generation is not supported.
87
+
88
+ For example, version 0.8.1 also accepts:
89
+
90
+ ```yaml
91
+ version: 1
92
+ rules:
93
+ - expected: 'ハードウェア'
94
+ pattern:
95
+ - 'ハードウエア'
96
+ - 'ハードウェアー'
97
+ ```
98
+
99
+ Each array entry uses the same literal/regex syntax and validation as a single
100
+ pattern. Arrays do not change supported flags or overlap handling.
101
+
102
+ ### Limited ECMAScript boundary compatibility
103
+
104
+ Version 0.8.1 translates `\b` and `\B` outside character classes into Ruby
105
+ lookarounds with ECMAScript word-character semantics, following prh's default
106
+ Unicode mode. Word characters are ASCII letters, digits, and underscore; Japanese
107
+ characters are non-word characters. Thus `/\bTips\b/` matches `Tips` in
108
+ `前Tips後`, but not in `Tips2`, `_Tips`, or `ATips`.
109
+ With `/i`, long s (`ſ`) and Kelvin sign (`K`) also count as word characters under
110
+ ECMAScript Unicode case folding. The generated assertions add no capture groups
111
+ and preserve original match offsets. Inside a character class, `\b` means a
112
+ backspace character; `\B` there is rejected. Escaped literal backslashes are
113
+ preserved.
114
+
115
+ Only the boundary assertions emulate ECMAScript. `/i` uses Ruby's
116
+ `Regexp::IGNORECASE`; Unicode case folding can differ from JavaScript (for
117
+ example multi-character folds). Other constructs, including whitespace classes,
118
+ retain Ruby semantics. This is limited prh compatibility, not full ECMAScript
119
+ conformance. Flags `g`, `m`, `s`, `u`, `y`, `d`, and `v` and duplicate `i` are
120
+ rejected; all occurrences are already collected independently of `g`.
121
+
122
+ ### Importing replacement rules
123
+
124
+ Version 0.8.1 supports nested `imports`; version 0.8.0 does not. For example:
125
+
126
+ ```yaml
127
+ version: 1
128
+ imports:
129
+ - ../../rules/prh.yml
130
+ - path: ./terminology.yml
131
+ rules:
132
+ - expected: '®'
133
+ pattern: '®'
134
+ ```
135
+
136
+ Each entry is a nonempty local file path string or a mapping containing exactly
137
+ `path`. Relative paths resolve from the importing YAML file, including nested
138
+ imports, independently of the working directory and manuscript base directory.
139
+ Absolute local paths are also accepted; URL imports are rejected. An import-only
140
+ file may omit `rules`. A file containing only `version: 1` is also valid and
141
+ contributes no rules. With no imported or local rules, `check`, `diff`, and
142
+ `apply` succeed without changing manuscript sources, and `diff` emits no patch.
143
+ Starting with version 0.8.1, a bare `rules:`, `rules: null`, and `rules: ~`
144
+ also contribute no local rules, just like omission or `rules: []`; imported rules
145
+ are still loaded. Other non-array values remain invalid. This normalization
146
+ applies only to `rules`, not to `imports` or individual rule fields.
147
+ Every imported file must use version 1 and pass the same
148
+ strict rule validation and specs as the entry file.
149
+
150
+ Imports are loaded in listed order, recursively before each file's own rules.
151
+ Each physical file is loaded once per plan, including repeated paths, symlink
152
+ aliases, and shared dependencies. Rule IDs are assigned across the flattened
153
+ set. Cycles (including symlink aliases), missing files, and import chains deeper
154
+ than 100 files fail rather than silently omitting rules. Imported and local rules
155
+ are combined, not overridden: overlapping replacement candidates remain errors
156
+ and replacements are still calculated only against the original text.
157
+
158
+ Import options such as `ignoreRules` and `disableImports` remain unsupported and
159
+ are rejected. Source selection and protection are unchanged by imports.
160
+
161
+ ### Selection and preservation
162
+
163
+ Only unambiguously source-mapped running prose in the existing default review
164
+ scope is eligible. Headings, lists, tables, quotations, listing/source, literal,
165
+ and passthrough blocks are excluded. Recognized inline code, quotations, URLs,
166
+ macros, and attribute references are protected by the existing conservative
167
+ inline heuristic, not a complete inline parser. A match overlapping any protected
168
+ span is skipped; matching is performed on the original text, never on blanked
169
+ placeholders. Backtick-to-bold and list-marker conversions are outside this scope.
170
+
171
+ Candidates are calculated once against the original sources; replacement results
172
+ are not searched again. Overlapping edits are conflicts, not resolved by rule
173
+ order. Matches/results containing line breaks are rejected. Source files retain
174
+ UTF-8 bytes, original line endings, and unrelated content; repeated include
175
+ occurrences must not create overlapping edits.
176
+
177
+ Before presenting a plan, the complete captured source set is copied to temporary
178
+ staging and reparsed. Parsing diagnostics, structural changes, new/deleted protected
179
+ inline tokens, and protected-content/source-membership changes reject the plan.
180
+ Relative includes within the base directory are supported. Absolute includes and
181
+ includes whose paths depend on the original filesystem may fail staged validation;
182
+ they are not rewritten or silently accepted. Symlink entrypoints are rejected.
183
+
184
+ Apply stages all changed files beside their destinations, checks all captured
185
+ source bytes against the plan, and renames the prepared files into place while
186
+ preserving permission bits. An ordinary installation error restores sources
187
+ already installed. This is not a crash-atomic transaction across multiple files;
188
+ keep manuscripts under version control and avoid concurrent edits during apply.
189
+ No review session is created or replaced. Existing sessions retain their original
190
+ baselines; applying replacements can make a session stale for prompt generation.
191
+ Mechanical validation does not establish semantic correctness.
192
+
193
+ [Back to README](../README.md)