kotonoha 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md ADDED
@@ -0,0 +1,47 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project are documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [0.1.2] - 2026-09-29
9
+
10
+ ### Added
11
+
12
+ - Add a mandatory rubber-duck review loop to `write` mode. Generated
13
+ documents are revised, structurally rechecked, and reviewed again until
14
+ no actionable findings remain.
15
+ - Distinguish a missing independent reviewer (`review not performed`) from
16
+ a review that reaches its round limit with unresolved findings
17
+ (`review did not converge`).
18
+
19
+ ## [0.1.1] - 2026-09-28
20
+
21
+ ### Added
22
+
23
+ - Add the `kotonoha install` CLI for installing `tech-writer` into a
24
+ project or user skill directory.
25
+ - Add `--target` for selecting a skill directory and `--force` for
26
+ explicitly replacing an existing installation.
27
+ - Add automated tests for default installation, overwrite protection,
28
+ forced replacement, and installation from the packed npm artifact.
29
+
30
+ ### Changed
31
+
32
+ - Document separate npm and source-checkout installation workflows in the
33
+ README.
34
+
35
+ ## [0.1.0] - 2026-09-28
36
+
37
+ ### Added
38
+
39
+ - Publish the initial `tech-writer` skill for structuring README files,
40
+ design documents, API references, PR and issue text, release notes,
41
+ user manuals, code comments, and Qiita and Zenn articles.
42
+ - Add structural linting for headings, code fences, placeholders, and
43
+ suspicious links.
44
+
45
+ [0.1.2]: https://github.com/nahisaho/kotonoha/compare/v0.1.1...v0.1.2
46
+ [0.1.1]: https://github.com/nahisaho/kotonoha/compare/v0.1.0...v0.1.1
47
+ [0.1.0]: https://github.com/nahisaho/kotonoha/releases/tag/v0.1.0
package/README.md CHANGED
@@ -22,6 +22,10 @@ Japanese prose with natural-japanese.
22
22
  descriptions/commit messages/issue reports, release notes, user manuals,
23
23
  code comments, and Qiita/Zenn articles
24
24
  - Doctype-specific structure and checklists to guide writing
25
+ - Iterative rubber-duck review after document creation, with fixes and
26
+ re-review until no actionable findings remain; unavailable reviews are
27
+ reported as `review not performed`, while unresolved review loops are
28
+ reported as `review did not converge`
25
29
  - `scripts/lint.py` for mechanical structural checks (heading-level skips,
26
30
  code blocks missing a language tag, leftover placeholders, suspicious
27
31
  links, etc.); pass `--atomic` for commit messages, PR descriptions, issue
@@ -39,7 +43,34 @@ Japanese prose with natural-japanese.
39
43
  - Python 3.9+ if you want to run the lint script (standard library only,
40
44
  no extra install needed)
41
45
 
42
- ### Install
46
+ ### Install from npm
47
+
48
+ Install the package, then copy `tech-writer` into a skill directory with
49
+ the included CLI:
50
+
51
+ ```bash
52
+ npm install --save-dev kotonoha
53
+ npx kotonoha install
54
+ ```
55
+
56
+ The default destination is `.github/skills/tech-writer` in the current
57
+ project. To install into another supported skill directory, pass its parent
58
+ directory:
59
+
60
+ ```bash
61
+ npx kotonoha install --target .claude/skills
62
+ npx kotonoha install --target ~/.copilot/skills
63
+ ```
64
+
65
+ The command refuses to overwrite an existing `tech-writer` directory. Review
66
+ or back up the existing installation, then pass `--force` only when you
67
+ intend to replace it:
68
+
69
+ ```bash
70
+ npx kotonoha install --force
71
+ ```
72
+
73
+ ### Install from a source checkout
43
74
 
44
75
  Inside this repository, the skill is already placed at
45
76
  `.github/skills/tech-writer`, so no extra setup is needed to use it with
@@ -0,0 +1,104 @@
1
+ #!/usr/bin/env node
2
+
3
+ const fs = require("node:fs");
4
+ const path = require("node:path");
5
+
6
+ const packageJson = require("../package.json");
7
+
8
+ function printUsage() {
9
+ console.log(`Usage:
10
+ kotonoha install [--target <directory>] [--force]
11
+
12
+ Options:
13
+ --target <directory> Skill directory root (default: .github/skills)
14
+ --force Replace an existing tech-writer installation
15
+ --help Show this help
16
+ --version Show the installed kotonoha version`);
17
+ }
18
+
19
+ function fail(message) {
20
+ console.error(`kotonoha: ${message}`);
21
+ process.exitCode = 1;
22
+ }
23
+
24
+ function parseInstallOptions(args) {
25
+ let target = ".github/skills";
26
+ let force = false;
27
+
28
+ for (let index = 0; index < args.length; index += 1) {
29
+ const argument = args[index];
30
+
31
+ if (argument === "--force") {
32
+ force = true;
33
+ continue;
34
+ }
35
+
36
+ if (argument === "--target") {
37
+ const value = args[index + 1];
38
+ if (!value || value.startsWith("--")) {
39
+ throw new Error("--target requires a directory");
40
+ }
41
+ target = value;
42
+ index += 1;
43
+ continue;
44
+ }
45
+
46
+ if (argument.startsWith("--target=")) {
47
+ const value = argument.slice("--target=".length);
48
+ if (!value) {
49
+ throw new Error("--target requires a directory");
50
+ }
51
+ target = value;
52
+ continue;
53
+ }
54
+
55
+ throw new Error(`unknown option: ${argument}`);
56
+ }
57
+
58
+ return { target, force };
59
+ }
60
+
61
+ function install(args) {
62
+ let options;
63
+ try {
64
+ options = parseInstallOptions(args);
65
+ } catch (error) {
66
+ fail(error.message);
67
+ return;
68
+ }
69
+
70
+ const source = path.resolve(__dirname, "..", "skills", "tech-writer");
71
+ const targetRoot = path.resolve(process.cwd(), options.target);
72
+ const destination = path.join(targetRoot, "tech-writer");
73
+
74
+ if (!fs.existsSync(source)) {
75
+ fail(`packaged skill not found at ${source}`);
76
+ return;
77
+ }
78
+
79
+ if (fs.existsSync(destination)) {
80
+ if (!options.force) {
81
+ fail(
82
+ `${destination} already exists; rerun with --force to replace it`,
83
+ );
84
+ return;
85
+ }
86
+ fs.rmSync(destination, { recursive: true, force: true });
87
+ }
88
+
89
+ fs.mkdirSync(targetRoot, { recursive: true });
90
+ fs.cpSync(source, destination, { recursive: true });
91
+ console.log(`Installed tech-writer to ${destination}`);
92
+ }
93
+
94
+ const [command, ...args] = process.argv.slice(2);
95
+
96
+ if (command === "install") {
97
+ install(args);
98
+ } else if (command === "--version" || command === "-v") {
99
+ console.log(packageJson.version);
100
+ } else if (command === "--help" || command === "-h" || command === undefined) {
101
+ printUsage();
102
+ } else {
103
+ fail(`unknown command: ${command}`);
104
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kotonoha",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "A GitHub Copilot CLI skill for structuring and polishing technical documents.",
5
5
  "license": "MIT",
6
6
  "author": "nahisaho",
@@ -12,6 +12,15 @@
12
12
  "url": "https://github.com/nahisaho/kotonoha/issues"
13
13
  },
14
14
  "homepage": "https://github.com/nahisaho/kotonoha#readme",
15
+ "bin": {
16
+ "kotonoha": "bin/kotonoha.js"
17
+ },
18
+ "scripts": {
19
+ "test": "node --test"
20
+ },
21
+ "engines": {
22
+ "node": ">=18"
23
+ },
15
24
  "keywords": [
16
25
  "copilot",
17
26
  "github-copilot",
@@ -21,6 +30,8 @@
21
30
  "markdown"
22
31
  ],
23
32
  "files": [
33
+ "CHANGELOG.md",
34
+ "bin/",
24
35
  "skills/"
25
36
  ]
26
37
  }
@@ -62,9 +62,12 @@ first, then hand Japanese prose to natural-japanese for polish.
62
62
  Infer the mode from the argument or the request:
63
63
 
64
64
  - `write` (default): new document, or restructuring a draft. Runs the full
65
- §1–§4 workflow, starting with the intake loop in §1.
65
+ §1–§5 workflow, starting with the intake loop in §1 and ending only after
66
+ the rubber-duck review loop has no remaining actionable findings. If an
67
+ independent review cannot run or cannot converge, returns the explicit
68
+ review status required by §5 instead of claiming a clean review.
66
69
  - `review`: structural review of an existing document. Does not rewrite;
67
- reports the gap against the doctype checklist (§5).
70
+ reports the gap against the doctype checklist (§6).
68
71
  - `score`: structure-only quick diagnostic. Runs
69
72
  `scripts/lint.py --json <file>` and summarizes the findings (no rewrite).
70
73
 
@@ -110,7 +113,7 @@ hand the user a checklist to fill in. Instead:
110
113
  one-line note) and move on.
111
114
  6. **Once complete, do not ask the user to compose anything.** Synthesize
112
115
  the gathered answers into the best possible generation approach yourself
113
- and immediately continue into §2–§4 in the same turn to produce the
116
+ and immediately continue into §2–§5 in the same turn to produce the
114
117
  document. Skip further confirmation unless the doctype is release-facing
115
118
  and consequential (e.g. a public release note with breaking changes) or
116
119
  the user explicitly asked to see a plan first.
@@ -221,7 +224,51 @@ step 2 as the primary check for those.
221
224
  4. **Reader-goal recheck**: confirm the "what the reader can do after
222
225
  reading" outcome from §1 is actually achievable from this document alone.
223
226
 
224
- ## 5. Doctype checklist summary
227
+ ## 5. Rubber-duck review loop — write mode only
228
+
229
+ After the structural review in §4, use the host's subagent mechanism to
230
+ launch an independent reviewer in the `rubber-duck` role to challenge the
231
+ completed document for meaningful problems that the authoring pass may have
232
+ missed. Prefer a registered `rubber-duck` agent when the host provides one;
233
+ otherwise use an independent general-purpose or critic-style subagent with
234
+ the same review prompt. Treat the reviewer as unavailable only when the host
235
+ has no independent subagent mechanism. Do not substitute the author's own
236
+ self-review: independence is the point of this pass. This loop is mandatory
237
+ for `write` mode; do not run it for `review` or `score` mode.
238
+
239
+ 1. **Start the review with full context**: give the reviewer the target file,
240
+ doctype, intended reader, one-sentence reader outcome from §1, and any
241
+ explicit constraints or assumptions. Ask it to report concrete,
242
+ actionable problems in correctness, logic, missing information, reader
243
+ flow, examples, and stated limitations — not cosmetic preferences.
244
+ 2. **Resolve every valid finding**: edit the document rather than merely
245
+ listing proposed fixes. If a finding conflicts with a stated requirement
246
+ or is factually inapplicable, record a one-line reason for declining it.
247
+ 3. **Re-run the relevant checks after each edit round**: repeat the doctype
248
+ checklist and structural lint from §4 before asking for another
249
+ rubber-duck review. A fix must not introduce a new structural defect.
250
+ 4. **Review again with the prior decisions**: reuse the same reviewer context
251
+ when supported. Otherwise, include the previous findings, applied fixes,
252
+ and declined findings with their reasons in every new review prompt. Ask
253
+ specifically for unresolved or newly introduced actionable findings.
254
+ 5. **Use a bounded convergence rule**: allow at most five rubber-duck rounds
255
+ for a living, multi-section document. For an atomic artifact, run one
256
+ round and finish immediately if it is clean; only continue after an
257
+ actionable finding, with a maximum of three rounds. A round is clean only
258
+ when no unaddressed actionable correctness, logic, completeness,
259
+ reader-flow, example, or limitation findings remain. A finding declined
260
+ with a recorded requirement-based or factual reason is a resolved
261
+ exception rather than an open finding. If another round runs, supply that
262
+ exception back to the reviewer under step 4. Purely cosmetic preferences
263
+ are not actionable.
264
+ 6. **Report non-clean outcomes precisely**: if the host has no independent
265
+ reviewer, label the result `review not performed` and do not claim the
266
+ rubber-duck pass completed. If the round limit is reached with
267
+ unaddressed actionable findings, or findings oscillate between
268
+ contradictory requirements, label it `review did not converge` and
269
+ include the latest unresolved findings and fixes already attempted.
270
+
271
+ ## 6. Doctype checklist summary
225
272
 
226
273
  See each reference file for detail. The items below are for living,
227
274
  multi-section documents (README, design doc, API reference, release notes,