asciidoc-pubkit 0.8.7 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +27 -0
- data/README.md +85 -1404
- data/docs/architecture.md +264 -0
- data/docs/configuration.md +48 -0
- data/docs/custom-rules.md +69 -0
- data/docs/development.md +138 -0
- data/docs/document-commands.md +68 -0
- data/docs/english-review-research.md +314 -0
- data/docs/installation.md +134 -0
- data/docs/list-review.md +50 -0
- data/docs/references.md +48 -0
- data/docs/replacements.md +193 -0
- data/docs/review-workflow.md +267 -0
- data/docs/rules-and-coverage.md +158 -0
- data/docs/scoring.md +37 -0
- data/docs/writing.md +24 -0
- data/lib/asciidoc_pubkit/cli.rb +8 -1
- data/lib/asciidoc_pubkit/document_commands.rb +215 -0
- data/lib/asciidoc_pubkit.rb +2 -1
- metadata +22 -5
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
# How review and scoring work
|
|
2
|
+
|
|
3
|
+
### Features
|
|
4
|
+
|
|
5
|
+
- **Structure-aware AsciiDoc parsing.** Asciidoctor parses local includes,
|
|
6
|
+
conditionals, attributes and section hierarchy before review targets are
|
|
7
|
+
selected. Prose selection distinguishes paragraphs from lists, tables,
|
|
8
|
+
quotations and code blocks; supported inline constructs are masked rather
|
|
9
|
+
than treated as ordinary prose.
|
|
10
|
+
- **Separate heading and prose review.** Each scan selects one
|
|
11
|
+
scope with its own rules, prompt and edit permissions. Heading review uses
|
|
12
|
+
the outline and body as context while protecting body text; prose review
|
|
13
|
+
protects headings. Mixed heading forms are accepted by default. See
|
|
14
|
+
[Heading review](review-workflow.md#heading-review).
|
|
15
|
+
- **Source-aligned static analysis.** Candidates identify the original source
|
|
16
|
+
file, line and one-based Unicode column, with a rule ID and review question.
|
|
17
|
+
Source text is checked against parser locations; unresolved mappings produce
|
|
18
|
+
coverage notices instead of guessed edit targets. Matches locate passages
|
|
19
|
+
for review, not proven defects.
|
|
20
|
+
- **Japanese morphological analysis.** MeCab with UTF-8 IPADIC recognizes
|
|
21
|
+
configured inflected predicates and adjectives, retaining original surfaces,
|
|
22
|
+
dictionary forms and negative-form information in morphological prose
|
|
23
|
+
findings. Literal matching is available only through explicit selection.
|
|
24
|
+
- **Contextual review in one prompt.** A single Markdown file carries saved
|
|
25
|
+
criteria, settings, candidates and manuscript evidence. All selected prose
|
|
26
|
+
paragraphs appear once, including those without candidates, with heading and
|
|
27
|
+
neighboring context. The reviewer records decisions and checks meaning;
|
|
28
|
+
generating the prompt does not edit the manuscript or invoke a model.
|
|
29
|
+
- **Book-specific rules and terminology.** Strict YAML rule sets, a glossary,
|
|
30
|
+
allow lists and exclusions adapt candidate detection to the manuscript.
|
|
31
|
+
Heading rules can express a book's preferred form while allowing justified
|
|
32
|
+
exceptions. Resolved rules and criteria are saved with each session.
|
|
33
|
+
- **Baseline-based preservation checks.** Source snapshots and artifact hashes
|
|
34
|
+
make the review baseline reproducible and detect stale or altered evidence.
|
|
35
|
+
Verification checks protected content, source membership, structure and
|
|
36
|
+
analyzer identity after external edits. It keeps `meaning_verified: false`;
|
|
37
|
+
semantic correctness remains a review judgment.
|
|
38
|
+
- **Local analysis and distinct scoring paths.** Default analysis runs locally
|
|
39
|
+
without a model call. Prose scoring reports candidate density; explicit
|
|
40
|
+
`review score --agent` optionally invokes an installed Codex or Claude CLI
|
|
41
|
+
for readability ratings. Candidate density, model judgments and development
|
|
42
|
+
benchmark accuracy remain separate measures.
|
|
43
|
+
|
|
44
|
+
### Concept
|
|
45
|
+
|
|
46
|
+
The goal is Japanese technical prose that readers can understand, use, and
|
|
47
|
+
verify, with claims bounded by evidence and technical meaning preserved.
|
|
48
|
+
Clarity includes a paragraph's purpose, concrete operations and referents,
|
|
49
|
+
actors and objects, conditions and consequences, logical connections, and its
|
|
50
|
+
relationship to headings, figures, tables, and code. "Who does what" is one
|
|
51
|
+
part of that goal. Clear prose also retains precise terminology, necessary
|
|
52
|
+
negation, uncertainty, and implementation constraints.
|
|
53
|
+
|
|
54
|
+
The toolkit supports that goal through shared writing criteria, contextual
|
|
55
|
+
review prompts, source-aligned candidate detection, baseline verification,
|
|
56
|
+
and distinct scoring and development evaluation paths. Mechanical rules locate
|
|
57
|
+
passages to inspect; the reviewer judges their meaning from context and source
|
|
58
|
+
evidence. The writing and review prompts guide a human or external agent in
|
|
59
|
+
planning and revising complete paragraphs. They do not automatically reconstruct
|
|
60
|
+
subjects and objects or rewrite manuscripts. Model-based readability evaluation
|
|
61
|
+
is available only through explicit `review score --agent`.
|
|
62
|
+
|
|
63
|
+
The table identifies both implemented mechanisms and guidance carried by the
|
|
64
|
+
prompts. A criterion in a prompt is a review instruction, not a guarantee that
|
|
65
|
+
the code can detect or verify it.
|
|
66
|
+
|
|
67
|
+
| Supported principle or behavior | How it is realized | Implementation or criteria |
|
|
68
|
+
| --- | --- | --- |
|
|
69
|
+
| 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) |
|
|
70
|
+
| 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) |
|
|
71
|
+
| 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) |
|
|
72
|
+
| 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) |
|
|
73
|
+
| 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) |
|
|
74
|
+
| 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) |
|
|
75
|
+
| 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) |
|
|
76
|
+
| 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) |
|
|
77
|
+
| 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) |
|
|
78
|
+
| 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) |
|
|
79
|
+
| 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) |
|
|
80
|
+
| 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) |
|
|
81
|
+
| 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) |
|
|
82
|
+
|
|
83
|
+
This section explains the implementation independently of command syntax.
|
|
84
|
+
[Review workflow](review-workflow.md#review-workflow) covers commands and session handling;
|
|
85
|
+
[Score an AsciiDoc manuscript](scoring.md#score-an-asciidoc-manuscript) covers scoring options.
|
|
86
|
+
The diagrams use GitHub-supported Mermaid fenced blocks.
|
|
87
|
+
|
|
88
|
+
### Shared components and prose selection
|
|
89
|
+
|
|
90
|
+
Both paths resolve the same settings and parse the AsciiDoc entry file with
|
|
91
|
+
Asciidoctor, including local includes. `Document` selects running-prose paragraphs
|
|
92
|
+
and maps them back to their source files. Ambiguous mappings become coverage
|
|
93
|
+
notices; the analyzer does not guess locations. Headings provide context, while
|
|
94
|
+
code, tables, quotations, lists, and protected blocks are excluded from prose
|
|
95
|
+
analysis. Inline code, quoted spans, links, and other protected constructs are
|
|
96
|
+
masked with spaces that preserve character offsets and newlines.
|
|
97
|
+
|
|
98
|
+
```mermaid
|
|
99
|
+
flowchart TD
|
|
100
|
+
A["AsciiDoc entry and local includes"] --> D["Document: parse and map running prose"]
|
|
101
|
+
C["Settings: options, configuration, resolved rules"] --> D
|
|
102
|
+
D --> P["Paragraphs with source locations and headings"]
|
|
103
|
+
D --> N["Coverage notices and parser diagnostics"]
|
|
104
|
+
P --> M["Rules: mask protected inline content"]
|
|
105
|
+
C --> M
|
|
106
|
+
M --> F["Candidate detection"]
|
|
107
|
+
F --> R["Session: review baseline and evidence"]
|
|
108
|
+
F --> S["Score: manuscript indicators"]
|
|
109
|
+
P -->|"Original prose and headings"| S
|
|
110
|
+
N --> R
|
|
111
|
+
N --> S
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
`Settings` resolves rule precedence as command-line `--rules`, configuration
|
|
115
|
+
`review.rules`, then packaged defaults. A custom rule file replaces the whole
|
|
116
|
+
set. `Rules` returns review candidates with one-based Unicode line and column
|
|
117
|
+
positions; a match does not establish a defect. `Session` saves evidence for a
|
|
118
|
+
later review, while `Score` returns a report directly without creating a session.
|
|
119
|
+
Parser diagnostics must be resolved before scanning or scoring.
|
|
120
|
+
|
|
121
|
+
### Review: collect, judge, and verify
|
|
122
|
+
|
|
123
|
+
Scanning freezes the source baseline, resolved settings and rules, analyzer
|
|
124
|
+
identity, and writing criteria. The session consists of `manifest.json`,
|
|
125
|
+
`document.json`, `findings.json`, and `baseline/`. Prompt generation checks
|
|
126
|
+
artifact integrity and rejects sources changed since the scan. It emits one
|
|
127
|
+
Markdown file containing the saved criteria, context, every selected paragraph
|
|
128
|
+
in document order, and its candidate evidence, including paragraphs with no
|
|
129
|
+
candidates. Generating that prompt requires no analyzer or model invocation.
|
|
130
|
+
|
|
131
|
+
```mermaid
|
|
132
|
+
sequenceDiagram
|
|
133
|
+
actor Reviewer as Human or external agent
|
|
134
|
+
participant CLI as pubkit CLI
|
|
135
|
+
participant Sources as Manuscript files
|
|
136
|
+
participant Session as Saved review session
|
|
137
|
+
Reviewer->>CLI: review scan FILE
|
|
138
|
+
CLI->>Sources: Parse prose and detect candidates
|
|
139
|
+
CLI->>Session: Save evidence and source baseline
|
|
140
|
+
Reviewer->>CLI: review prompt SESSION
|
|
141
|
+
CLI->>Session: Check integrity and read saved evidence
|
|
142
|
+
CLI->>Sources: Check sources still match scan
|
|
143
|
+
CLI-->>Reviewer: One Markdown review prompt
|
|
144
|
+
Reviewer->>Sources: Judge context and edit prose externally
|
|
145
|
+
Reviewer->>CLI: review verify SESSION
|
|
146
|
+
CLI->>Session: Read original baseline and settings
|
|
147
|
+
CLI->>Sources: Reparse and compare protected content
|
|
148
|
+
CLI-->>Reviewer: Mechanical result, notices, remaining candidates
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
The reviewer decides whether to keep or revise each paragraph and checks source
|
|
152
|
+
evidence before adding claims. `scan`, `prompt`, and `verify` never invoke an AI
|
|
153
|
+
CLI or edit manuscripts. Verification compares the included source set, content
|
|
154
|
+
outside reviewed prose, protected inline tokens, document structure, and analyzer
|
|
155
|
+
identity against the saved baseline. Numeric changes produce manual-review
|
|
156
|
+
notices; remaining candidates alone do not fail verification. A passing result
|
|
157
|
+
means these mechanical checks passed, with `meaning_verified: false`.
|
|
158
|
+
|
|
159
|
+
### Detection: contextual rules and token boundaries
|
|
160
|
+
|
|
161
|
+
MeCab with UTF-8 IPADIC is the default analyzer. It supplies surfaces, dictionary
|
|
162
|
+
forms, part of speech, and source-aligned token spans. Explicit literal mode
|
|
163
|
+
matches configured surface strings; there is no silent fallback. Both modes
|
|
164
|
+
apply glossary, configured prose style, and sentence-ending checks.
|
|
165
|
+
|
|
166
|
+
```mermaid
|
|
167
|
+
flowchart TD
|
|
168
|
+
P["Masked running prose"] --> B{"Selected tokenizer"}
|
|
169
|
+
B -->|"mecab, default"| T["MeCab and IPADIC tokens with source offsets"]
|
|
170
|
+
T --> L["Lemma rules with allow lists and contextual overlap checks"]
|
|
171
|
+
T --> X["Four enabled contextual predicate patterns"]
|
|
172
|
+
B -->|"literal, explicit"| E["Exact configured terms"]
|
|
173
|
+
P --> Q["Exact framing and contextual phrases"]
|
|
174
|
+
L --> F["Candidate findings"]
|
|
175
|
+
X --> O["Prefer most specific phrase; apply allow lists"]
|
|
176
|
+
E --> O
|
|
177
|
+
Q --> O
|
|
178
|
+
O --> F
|
|
179
|
+
P --> G["Glossary, style, and repeated endings"]
|
|
180
|
+
G --> F
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
Morphological rules match configured noun and adjective lemmas, canonical verb
|
|
184
|
+
forms, adjacent compound nouns, and sahen nouns followed by `する` or `できる`.
|
|
185
|
+
Predicate spans extend through adjacent auxiliaries, dependent verbs, and
|
|
186
|
+
supported connective particles. Negative auxiliaries preserve polarity;
|
|
187
|
+
negative-only rules require that evidence. Unknown tokens are not guessed.
|
|
188
|
+
|
|
189
|
+
The four contextual patterns combine an exact prefix (`地味に`, `静かに`,
|
|
190
|
+
`時間を`, or `側に`) with a known independent verb lemma (`効く`, `壊れる`,
|
|
191
|
+
`溶かす`, or `倒す`). The canonical phrase must be enabled in the resolved rules.
|
|
192
|
+
For example, `地味に効かなかった` is collected as one complete candidate with
|
|
193
|
+
lemma `地味に効く` and `negative: true`. Protected text and paragraph boundaries
|
|
194
|
+
cannot bridge the pattern. Longer contextual phrases suppress contained matches,
|
|
195
|
+
including when the longer phrase is allowed. These limited patterns suggest
|
|
196
|
+
reviewing the actual effect or operation; they do not prove a metaphor is wrong.
|
|
197
|
+
|
|
198
|
+
Sentence-ending analysis splits each paragraph at `。`, `!`, and `?`, retaining
|
|
199
|
+
source offsets. It extracts supported endings such as `検証します` and `です`,
|
|
200
|
+
then checks consecutive windows of three sentences. A sentence without a matching
|
|
201
|
+
ending breaks the run. The first matching run produces one informational
|
|
202
|
+
candidate at the ending of its third sentence. Precise technical repetition may
|
|
203
|
+
be worth retaining; this is not a requirement to vary verbs.
|
|
204
|
+
|
|
205
|
+
### Scoring: density and optional readability judgment
|
|
206
|
+
|
|
207
|
+
Scoring first runs the shared candidate detector. For the default
|
|
208
|
+
`candidate-density-v1`, let `N` be all findings, including informational ones,
|
|
209
|
+
and `C` be non-whitespace Unicode characters after inline masking:
|
|
210
|
+
|
|
211
|
+
```text
|
|
212
|
+
density = N * 1000 / C
|
|
213
|
+
score = max(0, 100 - 5 * density)
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
The score is rounded to three decimals. No unmasked prose yields `null`.
|
|
217
|
+
More candidates per 1,000 characters lower the score; short texts are particularly
|
|
218
|
+
sensitive. Changing rules, allow lists, or the detector can change the score of
|
|
219
|
+
an unchanged manuscript. This heuristic is a review indicator, not a calibrated
|
|
220
|
+
quality measure or a probability that AI wrote the text.
|
|
221
|
+
|
|
222
|
+
```mermaid
|
|
223
|
+
flowchart TD
|
|
224
|
+
P["Selected prose and detected candidates"] --> D["Compute candidate density and mechanical score"]
|
|
225
|
+
D --> A{"Explicit agent option and nonempty prose?"}
|
|
226
|
+
A -->|"No"| R["Text or JSON report"]
|
|
227
|
+
A -->|"Yes"| I["Paragraph IDs, text, headings, and readability rubric"]
|
|
228
|
+
I --> J["Installed Codex or Claude CLI; configured model provider"]
|
|
229
|
+
J --> V["Validate IDs, integer ratings, and reasons"]
|
|
230
|
+
V --> M["Map ratings to 0, 50, 100 and average"]
|
|
231
|
+
M --> R
|
|
232
|
+
D --> K["Retain mechanical score in JSON"]
|
|
233
|
+
K --> R
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
With explicit `--agent`, `llm-readability-v1` asks a fresh local CLI invocation to
|
|
237
|
+
rate each paragraph's sentence clarity and paragraph coherence separately from
|
|
238
|
+
1 to 3. The rubric targets engineers familiar with the technical terms. The
|
|
239
|
+
input contains paragraph IDs, original text, and headings, without candidate
|
|
240
|
+
findings or file paths. The CLI may connect to its configured model provider.
|
|
241
|
+
The response must contain every supplied ID exactly once, integer ratings in
|
|
242
|
+
range, and nonempty reasons. Invalid responses fail scoring.
|
|
243
|
+
|
|
244
|
+
Ratings of 1, 2, and 3 map to 0, 50, and 100. Each dimension averages equally
|
|
245
|
+
across scored paragraphs; the displayed score averages the two dimension means.
|
|
246
|
+
JSON retains both dimensions, paragraph reasons, evaluator identity, and the
|
|
247
|
+
mechanical score. These ordinal averages summarize a fallible judgment. There
|
|
248
|
+
is no reference manuscript or fact checklist in this single-document path, so
|
|
249
|
+
it does not assess preservation or establish technical accuracy. Temporary CLI
|
|
250
|
+
artifacts are removed after the invocation, and manuscripts remain unchanged.
|
|
251
|
+
|
|
252
|
+
| Result | What it measures | Evidence needed |
|
|
253
|
+
| --- | --- | --- |
|
|
254
|
+
| Candidate-density score | Detected cues per text length | Current prose and resolved rules |
|
|
255
|
+
| Optional readability score | Model judgment of clarity and coherence | Current prose, context, and rubric |
|
|
256
|
+
| Development benchmark accuracy | Detector agreement and location accuracy | Fixed corpus with annotated targets |
|
|
257
|
+
| Review verification | Mechanical preservation after editing | Original session baseline and current files |
|
|
258
|
+
|
|
259
|
+
See the [development prose benchmark](development.md#development-prose-benchmark) for
|
|
260
|
+
before/after trials with gold targets, separate fact checklists, and evaluator
|
|
261
|
+
calibration. Its precision, recall, and F1 evaluate the detector rather than
|
|
262
|
+
providing a score for an arbitrary manuscript.
|
|
263
|
+
|
|
264
|
+
[Back to README](../README.md)
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Configuration
|
|
2
|
+
|
|
3
|
+
`scan` and `score` search upward from the entrypoint directory for the nearest
|
|
4
|
+
`.asciidoc-pubkit.yml`. Use `--config FILE` to select a different file. CLI options
|
|
5
|
+
override configuration values; unspecified values use built-in defaults.
|
|
6
|
+
The CLI loads one configuration file, not merged book/repository files.
|
|
7
|
+
|
|
8
|
+
```yaml
|
|
9
|
+
review:
|
|
10
|
+
language: ja
|
|
11
|
+
style: desu-masu
|
|
12
|
+
tokenizer: mecab
|
|
13
|
+
# heading_rules: heading-rules.yml # Separate heading rule set
|
|
14
|
+
# Optional overrides (dictionary paths are relative to this file):
|
|
15
|
+
# mecab_command: /opt/homebrew/bin/mecab
|
|
16
|
+
# mecab_dictionary: /opt/homebrew/lib/mecab/dic/ipadic
|
|
17
|
+
base_dir: .
|
|
18
|
+
glossary: glossary.yml
|
|
19
|
+
exclude:
|
|
20
|
+
- generated/**
|
|
21
|
+
allows: []
|
|
22
|
+
attributes:
|
|
23
|
+
edition: print
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Configuration paths are relative to the configuration file. Without configuration,
|
|
27
|
+
the base directory is the entrypoint's directory. Exclusion patterns match source
|
|
28
|
+
paths relative to the base directory; excluded files can still supply attributes
|
|
29
|
+
and are preserved by verification. The default style is `preserve`; explicit
|
|
30
|
+
alternatives are `desu-masu` and `dearu`. Only `ja` is currently supported.
|
|
31
|
+
|
|
32
|
+
A glossary maps canonical terms to variant strings:
|
|
33
|
+
|
|
34
|
+
```yaml
|
|
35
|
+
JavaScript:
|
|
36
|
+
- Javascript
|
|
37
|
+
- Java Script
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Variants are review candidates, not automatic replacement instructions. In MeCab
|
|
41
|
+
mode, `allows` can suppress a canonical dictionary form (all its inflections) or
|
|
42
|
+
an exact matched surface (that occurrence's form only). In literal mode it
|
|
43
|
+
suppresses exact dictionary entries. It does not disable glossary checks.
|
|
44
|
+
Regex patterns are not interpreted in glossary or allow-list entries. Unknown
|
|
45
|
+
configuration keys are rejected. A bare `mecab_command` is resolved through PATH;
|
|
46
|
+
use an absolute path for an explicit executable override.
|
|
47
|
+
|
|
48
|
+
[Back to README](../README.md)
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# Customize review rules
|
|
2
|
+
|
|
3
|
+
The UTF-8 YAML file [`data/review-rules.ja.yml`](../data/review-rules.ja.yml) is
|
|
4
|
+
included in the gem and loaded by default. Edit that file when running a local
|
|
5
|
+
checkout, or copy it to a project-owned file for custom rules. No Ruby changes
|
|
6
|
+
are required to update candidate terms.
|
|
7
|
+
|
|
8
|
+
```sh
|
|
9
|
+
asciidoc-pubkit review scan book.adoc --rules ./review-rules.yml
|
|
10
|
+
make run ARGS="review scan book.adoc --rules ./review-rules.yml"
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
For an installed gem, copy the default file with:
|
|
14
|
+
|
|
15
|
+
```sh
|
|
16
|
+
ruby -rasciidoc_pubkit -e 'puts File.read(AsciidocPubkit::RuleSet::DEFAULT_PATH)' > review-rules.yml
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Alternatively, configure a path in `.asciidoc-pubkit.yml`:
|
|
20
|
+
|
|
21
|
+
```yaml
|
|
22
|
+
review:
|
|
23
|
+
rules: review-rules.yml
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Precedence is `--rules`, then `review.rules`, then the packaged default.
|
|
27
|
+
CLI paths are relative to the current working directory; configuration paths
|
|
28
|
+
are relative to the configuration file. A custom file replaces the entire rule
|
|
29
|
+
set; it is not merged with defaults. Start by copying the standard file.
|
|
30
|
+
|
|
31
|
+
### Rule file format (schema version 1)
|
|
32
|
+
|
|
33
|
+
All top-level fields below are required. Unknown keys and invalid types are
|
|
34
|
+
rejected. YAML aliases and object tags are not supported.
|
|
35
|
+
|
|
36
|
+
| Field | Format and behavior |
|
|
37
|
+
| --- | --- |
|
|
38
|
+
| `schema_version` | Integer `1` |
|
|
39
|
+
| `terms` | Mapping containing all five categories listed below |
|
|
40
|
+
| `verbs` | Mapping from canonical verb forms to nonempty arrays of MeCab/IPADIC dictionary forms; each dictionary form belongs to only one canonical form |
|
|
41
|
+
| `sahen` | Array of nouns matched with a following `する` or potential `できる` verb |
|
|
42
|
+
| `negative_only` | Array of canonical predicates restricted to negative forms; use the noun plus `する` for sahen predicates |
|
|
43
|
+
| `compound_nouns` | Array of terms matched across contiguous noun tokens; each must also appear in `abstract-reference.terms` |
|
|
44
|
+
|
|
45
|
+
Each `terms` category must contain `terms` (an array of unique nonempty strings)
|
|
46
|
+
and `question` (a nonempty review instruction string). The required categories
|
|
47
|
+
are `abstract-reference`, `weak-predicate`, `vague-degree`, `contextual-phrase`,
|
|
48
|
+
and `generic-framing`. Empty term arrays disable that category's literal
|
|
49
|
+
candidates. Empty `verbs`, `sahen`, and `compound_nouns` collections disable their
|
|
50
|
+
respective morphological matchers. Keep `negative_only` consistent with the
|
|
51
|
+
configured predicates.
|
|
52
|
+
|
|
53
|
+
In literal mode, all category term lists use exact phrase matching. In MeCab
|
|
54
|
+
mode, abstract nouns and degree adjectives use dictionary forms, while predicates
|
|
55
|
+
use `verbs` and `sahen`; add a predicate's desired literal surface to
|
|
56
|
+
`weak-predicate.terms` as well if literal mode should detect it. Contextual and
|
|
57
|
+
generic framing phrases use literal matching in both modes, with the
|
|
58
|
+
MeCab exception for the four configured contextual predicate patterns described
|
|
59
|
+
in [rules and coverage](rules-and-coverage.md). Questions apply to
|
|
60
|
+
both detectors. Glossary, style, repeated-ending checks, inline exclusions, and
|
|
61
|
+
morphological suffix handling remain implemented in Ruby.
|
|
62
|
+
|
|
63
|
+
A scan saves the resolved rule contents and source path in `manifest.json`.
|
|
64
|
+
Prompt generation and verification use the saved contents, even if the original
|
|
65
|
+
YAML file is subsequently edited or removed. Start a new session to apply rule
|
|
66
|
+
changes. Sessions require the same tool version that created them; preserve old
|
|
67
|
+
baselines and start a separate new session when upgrading.
|
|
68
|
+
|
|
69
|
+
[Back to README](../README.md)
|
data/docs/development.md
ADDED
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
# Development
|
|
2
|
+
|
|
3
|
+
```sh
|
|
4
|
+
bundle install
|
|
5
|
+
bundle exec rake test
|
|
6
|
+
bundle exec ruby -Ilib exe/asciidoc-pubkit --help
|
|
7
|
+
gem build asciidoc-pubkit.gemspec
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
The tests exercise include-boundary mapping, inline masking, configuration,
|
|
11
|
+
contextual prompts, stale inputs, protected-content verification, and real MeCab
|
|
12
|
+
analysis of inflections, negative predicates, Unicode positions, and long lines.
|
|
13
|
+
Install MeCab and UTF-8 IPADIC before running the complete test suite.
|
|
14
|
+
GitHub Actions is configured for Ruby 3.2, 3.3, 3.4, and 4.0 on Linux.
|
|
15
|
+
|
|
16
|
+
[`test/fixtures/prose_evaluation.ja.json`](../test/fixtures/prose_evaluation.ja.json)
|
|
17
|
+
contains original Japanese technical prose for candidate regression and manual
|
|
18
|
+
revision evaluation. Automated tests check metaphor candidates in both
|
|
19
|
+
tokenizers, source positions, inline exclusions, and allow lists. The revision
|
|
20
|
+
pairs are manual evaluation cases, not an automated semantic checker or a
|
|
21
|
+
measured AI benchmark. Compare source and revision separately for readability,
|
|
22
|
+
information loss, and unsupported additions, using each case's review axes and
|
|
23
|
+
expected disposition. Cover conditions, negation, numbers, versions, actors,
|
|
24
|
+
causes, implementation requirements, and necessary repetition. Record the
|
|
25
|
+
model, prompt, source evidence, and human judgments when evaluating actual
|
|
26
|
+
generated revisions; fewer findings alone do not establish an improvement.
|
|
27
|
+
|
|
28
|
+
### Development prose benchmark
|
|
29
|
+
|
|
30
|
+
The checkout provides `script/evaluate-prose` for measuring future detector and
|
|
31
|
+
prompt changes. This is a development tool, not an installed gem command; the
|
|
32
|
+
benchmark CLI calls are separate from the optional `review score --agent` path.
|
|
33
|
+
The fixed
|
|
34
|
+
[`prose_benchmark.ja.adoc`](../test/fixtures/prose_benchmark.ja.adoc) contains 13
|
|
35
|
+
original editorial paragraphs with intentionally vague framing and metaphors,
|
|
36
|
+
inflection variants, and valid technical prose controls. Its
|
|
37
|
+
[`annotations`](../test/fixtures/prose_benchmark.ja.json) contain 11 review targets
|
|
38
|
+
and separate source fact checklists. It is a small synthetic regression corpus,
|
|
39
|
+
not an AI authorship dataset or a representative measure of prose quality.
|
|
40
|
+
|
|
41
|
+
Run the deterministic benchmark before and after a change:
|
|
42
|
+
|
|
43
|
+
```sh
|
|
44
|
+
bundle exec ruby script/evaluate-prose --output .pubkit/evaluation/before
|
|
45
|
+
# After changing the detector or prompt:
|
|
46
|
+
bundle exec ruby script/evaluate-prose --output .pubkit/evaluation/after \
|
|
47
|
+
--compare .pubkit/evaluation/before/report.json
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
The report measures candidate precision, recall, F1, and location accuracy on a
|
|
51
|
+
0–100 scale for `generic-framing`, metaphorical operations, and `repeated-ending`.
|
|
52
|
+
Other rule findings are counted separately and are not judged against these
|
|
53
|
+
annotations. Detection matches a target's paragraph and kind; location accuracy
|
|
54
|
+
then checks the one-based source position, represented internally as a zero-based
|
|
55
|
+
Unicode character offset within that paragraph. The annotated repeated-ending
|
|
56
|
+
location is the matching ending of the third sentence in the consecutive run.
|
|
57
|
+
A candidate can be correctly detected even when the reviewer should keep it.
|
|
58
|
+
Zero denominators are reported as `null`, not perfect scores. Duplicate detections
|
|
59
|
+
count as false positives. These scores measure the detector, not the manuscript.
|
|
60
|
+
|
|
61
|
+
The checked-in [`MeCab baseline`](../benchmark/baseline-mecab.json), captured before
|
|
62
|
+
the detector changes, has precision 100, recall 81.818, F1 90, and location
|
|
63
|
+
accuracy 77.778. It misses two inflected metaphor phrases and mislocates two
|
|
64
|
+
repeated-ending candidates. Reports record source, criteria, rules, corpus, and
|
|
65
|
+
dictionary fingerprints. Comparisons reject changed corpora, scoring versions,
|
|
66
|
+
analyzers, or dictionaries. Reports with configuration fingerprints also reject
|
|
67
|
+
changed benchmark configuration. A fixed empty configuration
|
|
68
|
+
keeps these trials independent of auto-discovered manuscript settings.
|
|
69
|
+
The 0.6.2 location correction raises location accuracy to 100 without
|
|
70
|
+
changing precision, recall, or F1 on this corpus. Adding the four MeCab predicate
|
|
71
|
+
patterns then raises precision, recall, F1, and location accuracy to 100 on these
|
|
72
|
+
11 targets. This is regression evidence for the fixed synthetic corpus, not
|
|
73
|
+
evidence of general performance on unseen manuscripts; literal recall remains
|
|
74
|
+
81.818.
|
|
75
|
+
Record your own baseline when dictionary fingerprints
|
|
76
|
+
differ. `--tokenizer literal` explicitly selects a separate limited-mode run;
|
|
77
|
+
there is no automatic fallback, and literal results do not validate MeCab.
|
|
78
|
+
|
|
79
|
+
### Optional local AI evaluation
|
|
80
|
+
|
|
81
|
+
Use an installed, authenticated Codex or Claude CLI to perform rewrite and judge
|
|
82
|
+
trials explicitly. A local CLI may call its configured remote model provider and
|
|
83
|
+
consume account usage; this is not an offline model test. Normal `rake test`
|
|
84
|
+
does not run either CLI. For example:
|
|
85
|
+
|
|
86
|
+
```sh
|
|
87
|
+
bundle exec ruby script/evaluate-prose --agent codex --repeats 3 \
|
|
88
|
+
--output .pubkit/evaluation/ai-before
|
|
89
|
+
bundle exec ruby script/evaluate-prose --agent codex --repeats 3 \
|
|
90
|
+
--output .pubkit/evaluation/ai-after \
|
|
91
|
+
--compare .pubkit/evaluation/ai-before/report.json
|
|
92
|
+
# Or use Claude:
|
|
93
|
+
bundle exec ruby script/evaluate-prose --agent claude \
|
|
94
|
+
--output .pubkit/evaluation/claude-before
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Each trial generates the actual saved review prompt, requests paragraph revisions
|
|
98
|
+
as JSON, and runs the existing mechanical verifier. A fresh judge invocation
|
|
99
|
+
evaluates both original and revised prose with neutral A/B labels, alternating
|
|
100
|
+
their order across trials. The judge sees source evidence but no findings, tool
|
|
101
|
+
revision labels, or expected calibration answers. The writer receives the source
|
|
102
|
+
fact checklist in addition to the review prompt, so this measures an evidence-
|
|
103
|
+
assisted workflow rather than every real-world manuscript review.
|
|
104
|
+
|
|
105
|
+
Sentence clarity and paragraph coherence are separately rated 1–3 and displayed
|
|
106
|
+
as 0, 50, or 100 before averaging. These ordinal averages are descriptive
|
|
107
|
+
summaries, not validated interval measurements. Fact retention measures the
|
|
108
|
+
percentage of annotated source facts preserved; addition-free and substitution-
|
|
109
|
+
free paragraph percentages remain separate. Known acceptable, incorrect, and
|
|
110
|
+
unsupported revisions from `prose_evaluation.ja.json` calibrate the judge using
|
|
111
|
+
accuracy and balanced accuracy across the three dispositions. Inspect poor
|
|
112
|
+
calibration before interpreting quality scores. No combined AI-likeness score or
|
|
113
|
+
semantic pass is produced: `meaning_verified` remains `false`.
|
|
114
|
+
Mechanical verification results and their pass rate are also reported separately.
|
|
115
|
+
Quality scores from a trial with preservation violations remain visible for
|
|
116
|
+
diagnosis; a completed evaluation does not authorize accepting that revision.
|
|
117
|
+
|
|
118
|
+
One trial is a smoke test; use at least three to inspect variation. Reports retain
|
|
119
|
+
individual scores, means, population standard deviations, and ranges. They do
|
|
120
|
+
not perform a significance test. Same-model judging can favor the writer's style;
|
|
121
|
+
`--judge-agent` and `--judge-model` select a separate evaluator. `--model` selects
|
|
122
|
+
the writer model; omitted model options use each CLI's default. AI comparisons
|
|
123
|
+
require the same reported writer and judge models, CLI versions, rubric, and
|
|
124
|
+
calibration corpus. CLI defaults can change, so retain the recorded model IDs
|
|
125
|
+
and use explicit model options for controlled comparisons. Score changes can
|
|
126
|
+
reflect sampling variation as well as implementation changes.
|
|
127
|
+
|
|
128
|
+
The runner uses argument arrays rather than shell interpolation, read-only Codex
|
|
129
|
+
execution or tool-disabled Claude execution, and a per-invocation timeout
|
|
130
|
+
(`--timeout`, default 300 seconds). The CLI may still load its user configuration;
|
|
131
|
+
use consistent settings for comparisons. Current adapters require the flags
|
|
132
|
+
shown by `codex exec --help` and `claude --help`; older CLI versions may need an
|
|
133
|
+
update. Missing CLIs, authentication errors, timeouts, and malformed responses
|
|
134
|
+
fail explicitly. Existing output directories are never replaced. Partial
|
|
135
|
+
artifacts remain available after failures. Results, prompts, responses, and review
|
|
136
|
+
sessions belong under ignored `.pubkit/`; do not commit private evaluation runs.
|
|
137
|
+
|
|
138
|
+
[Back to README](../README.md)
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# Document commands
|
|
2
|
+
|
|
3
|
+
Version 1.0.0 provides four read-only document commands. They require neither
|
|
4
|
+
MeCab nor an AI CLI, accept documents in any language, and do not create review
|
|
5
|
+
sessions or change manuscripts.
|
|
6
|
+
|
|
7
|
+
```sh
|
|
8
|
+
asciidoc-pubkit document toc book.adoc --depth 2 --numbered
|
|
9
|
+
asciidoc-pubkit document info book.adoc --json
|
|
10
|
+
asciidoc-pubkit document check-xrefs book.adoc --json
|
|
11
|
+
asciidoc-pubkit document index . --output index.adoc --title "Index"
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
All four require exactly one input. Use `--help` for command-specific options.
|
|
15
|
+
Output defaults to stdout. `--output FILE` creates a new file and rejects existing
|
|
16
|
+
files and symlinks. Diagnostics go to stderr. These commands do not discover
|
|
17
|
+
`.asciidoc-pubkit.yml` or load review rules. Use repeatable `-a NAME=VALUE` options
|
|
18
|
+
for Asciidoctor attributes and `--base-dir DIR` for the local include boundary.
|
|
19
|
+
The default boundary is the input file's directory, or the scanned directory for
|
|
20
|
+
`index`. Local includes and conditional directives are parsed normally; source
|
|
21
|
+
files and symlink targets must remain within that boundary. Remote includes are
|
|
22
|
+
rejected. `/shared/` has no special mapping or automatic exclusion: migrate such
|
|
23
|
+
references to local includes within the configured boundary.
|
|
24
|
+
|
|
25
|
+
`toc` prints parsed section titles in document order, with two spaces per nesting
|
|
26
|
+
level. It includes book parts and their child chapters, but excludes the document
|
|
27
|
+
title and apparent headings inside code blocks. `--numbered` uses outline
|
|
28
|
+
positions (`1.`, `1-1.`, etc.), independently of Asciidoctor's publication
|
|
29
|
+
numbering. `--depth` must be a positive integer and limits the Asciidoctor section
|
|
30
|
+
level: chapters are level 1 and book parts are level 0. It does not generate or
|
|
31
|
+
rewrite heading text.
|
|
32
|
+
|
|
33
|
+
`info` prints `key: value` lines or a JSON object with `--json`. Its fields are
|
|
34
|
+
`doctitle`, `subtitle`, `description`, `keywords`, `lang`, `uuid`, `author`,
|
|
35
|
+
`producer`, and `creator`. Missing attributes become empty strings. Metadata is
|
|
36
|
+
extracted from the parsed document, including active local includes.
|
|
37
|
+
|
|
38
|
+
`check-xrefs` reports unresolved local `xref:ID[]` and `<<ID,label>>` references,
|
|
39
|
+
including fragments targeting the entry document or an included file. It
|
|
40
|
+
recognizes explicit and generated IDs and attribute-expanded targets. It scans
|
|
41
|
+
macro-enabled block text, list items, table cells, and titles; comments and
|
|
42
|
+
ordinary code blocks are excluded. References to separate documents and remote
|
|
43
|
+
URLs are outside its scope. This is a limited syntax scan, not complete rendered
|
|
44
|
+
link validation: complex inline passthroughs and custom macros are not analyzed.
|
|
45
|
+
Text output has `file:line`, a tab, and the missing ID; JSON output is an array of
|
|
46
|
+
`refid`, `file`, and `line` objects. Locations use Asciidoctor source cursors;
|
|
47
|
+
table cells, list continuations, and multiline titles may identify the enclosing node's start
|
|
48
|
+
rather than the exact token line. Duplicate occurrences of one ID on the same
|
|
49
|
+
source line are reported once.
|
|
50
|
+
|
|
51
|
+
`index` recursively scans lowercase `.adoc` files, skips hidden subdirectories
|
|
52
|
+
and its output path, and uses each document's ID and title. It produces an
|
|
53
|
+
AsciiDoc alphabetical cross-reference list for English names: parenthesized
|
|
54
|
+
text and subtitles after `:` or `:` are removed; remaining titles must be ASCII
|
|
55
|
+
and contain a letter. Documents without IDs are omitted. Titles are deduplicated
|
|
56
|
+
case-insensitively, preferring the shallowest relative path and then lexical path
|
|
57
|
+
order. `--title` adds a document title with `[#book-index]`; alphabetical groups
|
|
58
|
+
use discrete level-2 headings (`=== A`). This indexes document titles, not all
|
|
59
|
+
section headings. The generated references are useful when those documents are
|
|
60
|
+
included in the consuming book; the command does not verify that membership.
|
|
61
|
+
|
|
62
|
+
Success returns 0. `check-xrefs` returns 1 when local references are unresolved.
|
|
63
|
+
Invalid inputs/options, include or parse errors, and output failures return 2;
|
|
64
|
+
no output file is created on a parse error. Warnings remain visible on stderr.
|
|
65
|
+
Unlike the original directory index script, an input parse error fails the whole
|
|
66
|
+
index instead of silently omitting the file.
|
|
67
|
+
|
|
68
|
+
[Back to README](../README.md)
|