@gobing-ai/knowledge-kit 0.0.7 → 0.0.9

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.
Files changed (61) hide show
  1. package/dist/index.js +21604 -11844
  2. package/package.json +4 -1
  3. package/plugins/generations/content-gen/package.json +2 -1
  4. package/plugins/generations/content-gen/src/index.ts +9 -8
  5. package/plugins/generations/content-gen/src/storm.ts +12 -4
  6. package/plugins/generations/dailynews-gen/package.json +17 -0
  7. package/plugins/generations/dailynews-gen/plugin.json +7 -0
  8. package/plugins/generations/dailynews-gen/src/index.ts +111 -0
  9. package/plugins/generations/dailynews-gen/src/script-builder.ts +121 -0
  10. package/plugins/generations/dailynews-gen/tsconfig.json +4 -0
  11. package/plugins/generations/voice-gen/package.json +17 -0
  12. package/plugins/generations/voice-gen/plugin.json +6 -0
  13. package/plugins/generations/voice-gen/src/concat.ts +218 -0
  14. package/plugins/generations/voice-gen/src/index.ts +228 -0
  15. package/plugins/generations/voice-gen/src/mp3.ts +65 -0
  16. package/plugins/generations/voice-gen/src/voicebox-client.ts +223 -0
  17. package/plugins/generations/voice-gen/src/voicescript.ts +365 -0
  18. package/plugins/generations/voice-gen/tsconfig.json +8 -0
  19. package/plugins/ingestions/aihot-ingest/package.json +17 -0
  20. package/plugins/ingestions/aihot-ingest/plugin.json +7 -0
  21. package/plugins/ingestions/aihot-ingest/src/client.ts +185 -0
  22. package/plugins/ingestions/aihot-ingest/src/index.ts +137 -0
  23. package/plugins/ingestions/aihot-ingest/src/mapper.ts +42 -0
  24. package/plugins/ingestions/aihot-ingest/tsconfig.json +4 -0
  25. package/plugins/ingestions/karakeep-local/package.json +17 -0
  26. package/plugins/ingestions/karakeep-local/src/index.ts +31 -26
  27. package/plugins/ingestions/karakeep-local/tsconfig.json +4 -0
  28. package/plugins/ingestions/web-search/package.json +4 -1
  29. package/plugins/ingestions/web-search/src/index.ts +139 -16
  30. package/plugins/kk/README.md +9 -3
  31. package/plugins/kk/commands/workflow-run.md +100 -28
  32. package/plugins/kk/config.example.yaml +34 -0
  33. package/plugins/kk/scripts/render-md.ts +8 -3
  34. package/plugins/kk/skills/{judge → content-judge}/SKILL.md +13 -14
  35. package/plugins/kk/skills/{judge → content-judge}/references/workflow-integration.md +13 -11
  36. package/plugins/kk/skills/itc-generating/SKILL.md +147 -0
  37. package/plugins/kk/skills/itc-generating/references/generic-craft.md +80 -0
  38. package/plugins/kk/skills/itc-generating/references/platform-english.md +72 -0
  39. package/plugins/kk/skills/itc-generating/references/platform-wechat.md +60 -0
  40. package/plugins/kk/skills/itc-generating/references/skill-authoring.md +62 -0
  41. package/plugins/kk/skills/storm-research/SKILL.md +10 -3
  42. package/plugins/kk/workflows/judge-gated-publish-example.yaml +101 -0
  43. package/plugins/kk/workflows/kk-daily-ai-voice.yaml +144 -0
  44. package/plugins/kk/workflows/kk-ingest-generate-publish.yaml +72 -0
  45. package/plugins/kk/workflows/kk-itc.yaml +285 -0
  46. package/plugins/kk/workflows/kk-solo-podcast.yaml +374 -0
  47. package/plugins/kk/workflows/validate-voicescript.ts +226 -0
  48. package/plugins/publishings/emdash-pub/package.json +17 -0
  49. package/plugins/publishings/emdash-pub/plugin.json +7 -0
  50. package/plugins/publishings/emdash-pub/src/index.ts +450 -0
  51. package/plugins/publishings/emdash-pub/tsconfig.json +4 -0
  52. package/plugins/publishings/qiita-pub/package.json +2 -1
  53. package/plugins/publishings/qiita-pub/src/index.ts +9 -9
  54. package/plugins/publishings/surfdash-pub/package.json +2 -1
  55. package/plugins/publishings/surfdash-pub/src/index.ts +17 -12
  56. package/plugins/publishings/zenn-pub/package.json +2 -1
  57. package/plugins/publishings/zenn-pub/src/index.ts +11 -11
  58. package/plugins/kk/agents/judge-compliance.md +0 -37
  59. package/plugins/kk/agents/judge-tech.md +0 -35
  60. package/plugins/kk/agents/judge-tone.md +0 -37
  61. /package/plugins/kk/skills/{judge → content-judge}/references/rubrics.md +0 -0
@@ -1,18 +1,20 @@
1
1
  ---
2
2
  name: workflow-run
3
3
  description: >-
4
- Run STORM daily research end to end — a topic sentence XOR a markdown file becomes a
5
- grounded content.md report. Installs the workflow YAML on first run (0056 copy rule),
6
- creates the config with defaults if missing, computes the topic workspace, and shells
7
- spur workflow run against the installed workflow.
8
- argument-hint: "[name] <topic|--in file> [--fixture] [--force]"
4
+ Run STORM daily research or IT content authoring end to end. Installs the workflow
5
+ YAML on first run (two-root copy rule), creates the config with defaults if missing,
6
+ computes the workspace, and shells spur workflow run against the installed workflow.
7
+ argument-hint: "[name] <topic|--in file> [--dir <path>] [--playbook generic|english|wechat] [--research] [--judge] [--outline <a|b|c>] [--writer itc-generating|topic] [--duration <min>] [--language <code>] [--script-approved] [--fixture] [--force]"
9
8
  ---
10
9
 
11
- Thin wrapper around the **storm-research** skill. Read
12
- `plugins/kk/skills/storm-research/SKILL.md` first — it is the craft SSOT (query framing,
13
- evidence verification, better-report practices, fail-loud rows). This command owns the run
14
- procedure: config create, YAML install, topic-id computation, and the `spur workflow run`.
15
- No new `kk` CLI noun (ADR-011) — everything here is shell + the workflow.
10
+ Thin runner around the **storm-research**, **itc-generating** / **topic**, and **kk-solo-podcast**
11
+ capabilities. Read `plugins/kk/skills/storm-research/SKILL.md` or
12
+ `plugins/kk/skills/itc-generating/SKILL.md` for craft; solo-podcast craft is inlined in the
13
+ workflow `agent.run` prompt (no fat skill). This command owns the run procedure: config create,
14
+ YAML install (two-root copy rule) into `$HOME/.config/kk/workflows`, workspace computation, and
15
+ the `spur workflow run` of that **runtime** dest. Design-time SSOT remains
16
+ `plugins/kk/workflows/` in the package/repo. No new `kk` CLI noun (ADR-011) — everything here
17
+ is shell + the workflow.
16
18
 
17
19
  **Args:** `$ARGUMENTS`
18
20
 
@@ -21,14 +23,25 @@ No new `kk` CLI noun (ADR-011) — everything here is shell + the workflow.
21
23
  Parse per the frozen rule:
22
24
 
23
25
  - First token is the workflow **name** when it matches `^[a-z0-9][a-z0-9-]*$` and is not `--in`;
24
- otherwise `name=kk-storm-research` and that token is the topic.
25
- - `--in <file>` → file mode. `--fixture` → force `fixture: "true"`. `--force` → overwrite an
26
- existing dest YAML.
26
+ otherwise `name=kk-storm-research` and that token is the topic. Supported profile names:
27
+ `kk-storm-research` (default), `kk-itc`, `kk-solo-podcast`. Any other name after successful copy → exit 1 listing
28
+ `kk-storm-research`, `kk-itc`, `kk-solo-podcast`.
29
+ - `--in <file>` → file mode. `--force` → overwrite an existing dest YAML / existing `brief.md`.
30
+ - Profile `kk-storm-research`: `--fixture` → force `fixture: "true"`.
31
+ - Profile `kk-itc`: `--dir <path>` (default `./<kebab>`), `--playbook generic|english|wechat` (default `generic`),
32
+ `--research` (`true`|`false`, default `false`), `--judge` (`true`|`false`, default `false`),
33
+ `--outline <a|b|c>` (default empty), `--writer itc-generating|topic` (default `itc-generating`).
34
+ `--fixture` passed with `kk-itc` or `kk-solo-podcast` → exit 1 (`fixture is storm-only`).
35
+ - Profile `kk-solo-podcast`: `--dir <path>` (default `$works_dir/<kebab>`), `--outline <a|b|c>`
36
+ (default empty), `--duration <min>` (default `8`), `--language <code>` (default `en`),
37
+ `--script-approved` (sets `script_approved=true`; default off). `--fixture` is storm-only.
27
38
  - **XOR:** exactly one of `<topic>` / `--in <file>`. Both set or both empty → exit 1, stderr
28
39
  states the XOR rule, no writes.
29
40
 
30
41
  Resolve these before step 2: `NAME`, `TOPIC`, `INPUT_FILE` (empty in sentence mode), `FIXTURE`
31
- (`true`|`false`), `FORCE`.
42
+ (`true`|`false`), `FORCE` (`true`|`false`), `DIR`, `PLAYBOOK`, `RESEARCH`, `JUDGE`, `OUTLINE`,
43
+ `WRITER`, `DURATION` (`8`), `LANGUAGE` (`en`), `SCRIPT_APPROVED` (`true`|`false`),
44
+ `VOICE_PROFILE` (from `VOICEBOX_DEFAULT_PROFILE`, default empty).
32
45
 
33
46
  ## 2. Resolve the config
34
47
 
@@ -68,28 +81,43 @@ from config — env-only.
68
81
 
69
82
  1. `$KK_WORKFLOWS_SOURCE/$NAME.yaml`
70
83
  2. `plugins/kk/workflows/$NAME.yaml`
71
- 3. `.spur/workflows/$NAME.yaml`
72
84
 
73
- - `dest` missing → copy from the first hit. Source missing from all three → exit 1, stderr
74
- lists the roots searched.
85
+ - `dest` missing → copy from the first hit. Source missing from both roots → exit 1, stderr
86
+ lists the roots searched: `no source workflow for $NAME (searched KK_WORKFLOWS_SOURCE, plugins/kk/workflows)`.
75
87
  - `dest` exists + `--force` → overwrite from source.
76
88
  - `dest` exists + identical bytes → no-op.
77
89
  - `dest` exists + different bytes → **warn and leave** (run proceeds with the user's copy).
78
90
 
79
91
  ```bash
80
92
  src=""
81
- for d in "$KK_WORKFLOWS_SOURCE" "plugins/kk/workflows" ".spur/workflows"; do
93
+ for d in "$KK_WORKFLOWS_SOURCE" "plugins/kk/workflows"; do
82
94
  [ -n "$d" ] && [ -f "$d/$NAME.yaml" ] && { src="$d/$NAME.yaml"; break; }
83
95
  done
84
- [ -z "$src" ] && { echo "no source workflow for $NAME (searched KK_WORKFLOWS_SOURCE, plugins/kk/workflows, .spur/workflows)" >&2; exit 1; }
96
+ [ -z "$src" ] && { echo "no source workflow for $NAME (searched KK_WORKFLOWS_SOURCE, plugins/kk/workflows)" >&2; exit 1; }
85
97
  if [ ! -f "$dest" ] || [ "$FORCE" = true ]; then
86
98
  install -d "$(dirname "$dest")" && cp "$src" "$dest"
87
99
  elif ! cmp -s "$src" "$dest"; then
88
100
  echo "warning: $dest differs from install source; leaving user copy (pass --force to replace)" >&2
89
101
  fi
102
+ # Runtime dest is $workflows_dir (default ~/.config/kk/workflows). Copy YAML sidecars
103
+ # that the machine shells (kk-solo-podcast: validate-voicescript.ts).
104
+ if [ "$NAME" = "kk-solo-podcast" ] && [ -n "$src" ]; then
105
+ side="validate-voicescript.ts"
106
+ sdir=$(dirname "$src")
107
+ ddir=$(dirname "$dest")
108
+ if [ -f "$sdir/$side" ]; then
109
+ if [ ! -f "$ddir/$side" ] || [ "$FORCE" = true ]; then
110
+ cp "$sdir/$side" "$ddir/$side"
111
+ elif ! cmp -s "$sdir/$side" "$ddir/$side"; then
112
+ echo "warning: $ddir/$side differs from install source; leaving user copy (pass --force to replace)" >&2
113
+ fi
114
+ fi
115
+ fi
90
116
  ```
91
117
 
92
- ## 4. Compute the topic workspace (0056 `topicId`)
118
+ ## 4. Compute workspace
119
+
120
+ ### Profile `kk-storm-research` (0056 `topicId`)
93
121
 
94
122
  `raw` = `TOPIC` (sentence mode) or the first ATX H1 (`/^#\s+(.+)$/m`) else basename without
95
123
  extension (`--in` mode). Then:
@@ -110,21 +138,65 @@ work_dir="$works_dir/$topic_id"
110
138
  mkdir -p "$work_dir"
111
139
  ```
112
140
 
141
+ ### Profile `kk-itc` (authoring workspace)
142
+
143
+ `raw` = `TOPIC` or file-mode first ATX H1 else basename without extension.
144
+ `kebab` = lower-case, `[^a-z0-9]+` → `-`, trimmed dashes (no length cap, no sha256 hash).
145
+ `work_dir="${DIR:-./$kebab}"`. Empty derived `kebab` → exit 1.
146
+
147
+ ### Profile `kk-solo-podcast`
148
+
149
+ `raw` = `TOPIC` or file-mode first ATX H1 else basename without extension.
150
+ `kebab` = lower-case, `[^a-z0-9]+` → `-`, trimmed dashes (no length cap, no sha256 hash).
151
+ `work_dir="${DIR:-$works_dir/$kebab}"`. Empty derived `kebab` → exit 1.
152
+
113
153
  ## 5. Run the workflow
114
154
 
115
- All values are strings. Bind the vars first: `maxResults` and `fixture` from step 2;
116
- `plugins_path` defaults to `./plugins` in a checkout, else the installed package `plugins/`
117
- path or `KK_PLUGIN_PATH`; `render_script` stays `plugins/kk/scripts/render-md.ts`.
155
+ All values are strings.
156
+
157
+ ### Profile `kk-storm-research`
158
+
159
+ Bind vars: `maxResults` and `fixture` from step 2; `plugins_path` defaults to `./plugins`
160
+ in a checkout, else installed package `plugins/` or `KK_PLUGIN_PATH`; `render_script` is
161
+ `plugins/kk/scripts/render-md.ts`.
118
162
 
119
163
  ```bash
120
164
  spur workflow run "$dest" --vars \
121
165
  "{\"topic\":\"$TOPIC\",\"input_file\":\"$INPUT_FILE\",\"maxResults\":\"$maxResults\",\"fixture\":\"$FIXTURE\",\"work_dir\":\"$work_dir\",\"plugins_path\":\"$plugins_path\",\"render_script\":\"$render_script\"}"
122
166
  ```
123
167
 
168
+ ### Profile `kk-itc`
169
+
170
+ Bind vars: `topic`, `input_file`, `work_dir`, `writer`, `playbook`, `research`, `judge`, `outline`,
171
+ `force`, `rubric` (`tech-accuracy`), `verdictFile` (`.spur/run/${vars.__runId}-itc-verdict.json`), `agent`.
172
+
173
+ ```bash
174
+ spur workflow run "$dest" --vars \
175
+ "{\"topic\":\"$TOPIC\",\"input_file\":\"$INPUT_FILE\",\"work_dir\":\"$work_dir\",\"writer\":\"$WRITER\",\"playbook\":\"$PLAYBOOK\",\"research\":\"$RESEARCH\",\"judge\":\"$JUDGE\",\"outline\":\"$OUTLINE\",\"force\":\"$FORCE\",\"rubric\":\"tech-accuracy\",\"verdictFile\":\".spur/run/\${vars.__runId}-itc-verdict.json\",\"agent\":\"$AGENT\"}"
176
+ ```
177
+
178
+ ### Profile `kk-solo-podcast`
179
+
180
+ Bind vars: `topic`, `input_file`, `work_dir`, `outline`, `script_approved`, `force`,
181
+ `target_duration_min`, `language`, `voice_profile` (from `VOICEBOX_DEFAULT_PROFILE` or empty),
182
+ `validate_script` (`$workflows_dir/validate-voicescript.ts`), `plugins_path` (empty → ADR-012
183
+ default discovery), `agent`. **Always** `spur workflow run "$dest"` — `$dest` is
184
+ `$workflows_dir/kk-solo-podcast.yaml`, never the design-time `plugins/kk/workflows/` path.
185
+
186
+ ```bash
187
+ spur workflow run "$dest" --vars \
188
+ "{\"topic\":\"$TOPIC\",\"input_file\":\"$INPUT_FILE\",\"work_dir\":\"$work_dir\",\"outline\":\"$OUTLINE\",\"script_approved\":\"$SCRIPT_APPROVED\",\"force\":\"$FORCE\",\"target_duration_min\":\"$DURATION\",\"language\":\"$LANGUAGE\",\"voice_profile\":\"$VOICE_PROFILE\",\"validate_script\":\"$workflows_dir/validate-voicescript.ts\",\"plugins_path\":\"\",\"agent\":\"$AGENT\"}"
189
+ ```
190
+
124
191
  ## 6. Report
125
192
 
126
- Print the resolved `work_dir`, then the two artifacts to hand the operator:
127
- `$work_dir/content.md` (report sidecar) and `$work_dir/content.json` (machine contract).
128
- Per the skill's better-report practice (d), skim `content.md` citations against `docs.json`
129
- ids before presenting. If the run ended `failed`, show the failing state
130
- (`spur workflow trace <run-id> --json`) and the skill's fail-loud recovery row.
193
+ - **`kk-storm-research`**: print resolved `work_dir`, then `$work_dir/content.md` (report sidecar)
194
+ and `$work_dir/content.json` (machine contract). Skim `content.md` citations against `docs.json`
195
+ ids before presenting.
196
+ - **`kk-itc`**: print resolved `work_dir`, then `$work_dir/brief.md`, `$work_dir/2-outline/outline-approved.md`,
197
+ and `$work_dir/3-draft/draft-article.md`. If `judge=true`, also print the verdict path.
198
+ - **`kk-solo-podcast`**: print resolved `work_dir`, then `$work_dir/3-script/voicescript.yaml`,
199
+ `$work_dir/4-audio/content.json`, and `$work_dir/4-audio/content.wav`.
200
+
201
+ If the run ended `failed`, show the failing state (`spur workflow trace <run-id> --json`) and the
202
+ fail-loud recovery line.
@@ -0,0 +1,34 @@
1
+ works_dir: "~/.config/kk/works"
2
+ workflows_dir: "~/.config/kk/workflows"
3
+ defaults:
4
+ maxResults: 8
5
+ fixture: false
6
+
7
+ # Plugin credentials — paste values between the quotes.
8
+ # Path: plugins/<collection>/<name>/env — each entry is injected into that plugin's
9
+ # process environment at exec time. A real environment variable always wins
10
+ # over a value here (flag > env > config > compiled default).
11
+ plugins:
12
+ ingestions:
13
+ web-search:
14
+ env:
15
+ FIRECRAWL_API_KEY: "" # firecrawl.dev — required for live research
16
+ generations:
17
+ voice-gen:
18
+ env:
19
+ VOICEBOX_URL: "http://127.0.0.1:17493" # local Voicebox REST origin
20
+ VOICEBOX_DEFAULT_PROFILE: "Robin" # GET /profiles name or id — required for plain-text Docs
21
+ VOICEBOX_TIMEOUT_MS: "600000" # per-generation poll budget (ms)
22
+ VOICEBOX_POLL_MS: "1000" # GET /history/{id} interval
23
+ VOICEBOX_MAX_CHUNK_CHARS: "800" # Voicebox auto-chunk size (100–5000)
24
+ VOICEBOX_CROSSFADE_MS: "50" # Voicebox chunk crossfade (0–500)
25
+ publishings:
26
+ qiita-pub:
27
+ env:
28
+ QIITA_TOKEN: "" # Qiita API v2 token (read_qiita/write_qiita) — required
29
+ zenn-pub:
30
+ env:
31
+ ZENN_REPO: "" # GitHub repo for Zenn CLI deploy — used by zenn-pub
32
+ surfdash-pub:
33
+ env:
34
+ POSTSURFING_BIN: "" # optional — delete if unused; defaults to `postsurfing` on PATH
@@ -6,6 +6,13 @@
6
6
  * resolve `@gobing-ai/kk-core` (private). The render logic below is a COPY of
7
7
  * `packages/kk-core/src/render-md.ts`; keep them byte-identical for the same Content.
8
8
  *
9
+ * NODE-BUILTIN-ONLY — no workspace or `@gobing-ai/*` imports, and therefore raw
10
+ * `console.error` rather than the ts-utils output seam. This script ships to arbitrary
11
+ * user projects and is shelled as `bun <this script>`; an `@gobing-ai/*` import resolves
12
+ * there only because bun auto-installs it from the network, so it fails under
13
+ * `bun --no-install`, offline, or in an air-gapped environment. Enforced by
14
+ * `shipped-script-isolation` in `.spur/rules/boundary/`.
15
+ *
9
16
  * SYNC: packages/kk-core/src/render-md.ts (renderContentMarkdown + helpers)
10
17
  */
11
18
 
@@ -72,10 +79,8 @@ export function renderContentMarkdown(content: ContentInput): string {
72
79
  const heading = content.title?.trim() || 'Untitled';
73
80
  const startsWithHeading = content.body.startsWith(`# ${heading}`);
74
81
  const lead = startsWithHeading ? '' : `# ${heading}\n\n`;
75
- const outlineBlock =
76
- content.outline && content.outline.trim().length > 0 ? `\n\n## Outline\n\n${content.outline.trim()}` : '';
77
82
  const refsBlock = renderReferences(content.references);
78
- return `${lead}${content.body}${outlineBlock}${refsBlock}\n`;
83
+ return `${lead}${content.body}${refsBlock}\n`;
79
84
  }
80
85
 
81
86
  function renderReferences(references: ContentInput['references']): string {
@@ -1,17 +1,17 @@
1
1
  ---
2
- name: judge
3
- description: This skill should be used when an LLM evaluation gate is needed in a knowledge-kit pipeline — "judge this content", "evaluate against rubric", "quality gate before publish", "check technical accuracy", "review brand tone", "compliance check", or when a spur workflow step of type `agent.run` targets the judge skill to emit a PASS/FAIL/NEEDS_REVISION verdict. Centralizes evaluation rubrics, prompt templates, and structured verdict emission for generated Content.
2
+ name: content-judge
3
+ description: This skill should be used when an LLM evaluation gate is needed in a knowledge-kit pipeline — "judge this content", "evaluate against rubric", "quality gate before publish", "check technical accuracy", "review brand tone", "compliance check", or when a spur workflow step of type `agent.run` targets the content-judge skill to emit a PASS/FAIL/NEEDS_REVISION verdict. Centralizes evaluation rubrics, prompt templates, and structured verdict emission for generated Content.
4
4
  version: 0.1.0
5
5
  ---
6
6
 
7
- # judge — LLM-as-judge evaluation skill
7
+ # content-judge — LLM-as-judge evaluation skill
8
8
 
9
9
  ## Purpose
10
10
 
11
11
  Evaluate generated `Content` against a rubric and emit a structured **verdict** that a spur
12
12
  workflow gate can consume. This is the fat skill — the single source of truth for evaluation
13
- logic, prompt templates, and verdict formatting. Thin wrappers (tech-accuracy, brand-tone,
14
- compliance) delegate here with a pre-selected rubric.
13
+ logic, prompt templates, and verdict formatting. The `agent.run` prompt (or `--judge` flag on
14
+ `itc-generating`) selects the rubric; there are no persona subagents.
15
15
 
16
16
  LLM-as-judge is **not** a knowledge-kit plugin kind (ADR-007 amdt 2026-08-07). It runs as an
17
17
  `agent.run` step in a spur workflow; the verdict is a skill output, not a plugin-kind contract.
@@ -20,7 +20,7 @@ LLM-as-judge is **not** a knowledge-kit plugin kind (ADR-007 amdt 2026-08-07). I
20
20
 
21
21
  - A spur workflow needs a quality gate between `generate` and `publish`.
22
22
  - A user asks to "judge", "evaluate", "quality-check", or "gate" generated content.
23
- - A thin wrapper (tech-accuracy / brand-tone / compliance) delegates evaluation.
23
+ - A workflow or skill names a rubric (`tech-accuracy` / `brand-tone` / `compliance` / `general`).
24
24
 
25
25
  ## Verdict output contract
26
26
 
@@ -61,8 +61,8 @@ Every evaluation writes a JSON verdict file. The default path is
61
61
 
62
62
  1. **Read the Content** from the path given in the evaluation request (the `content.json` written
63
63
  by the preceding `kk executor run <generator>` step).
64
- 2. **Select the rubric** — either named in the request (`tech-accuracy`, `brand-tone`,
65
- `compliance`, `general`) or loaded by a thin wrapper. Default: `general`.
64
+ 2. **Select the rubric** — named in the request (`tech-accuracy`, `brand-tone`,
65
+ `compliance`, `general`). Default: `general`.
66
66
  3. **Evaluate each criterion** in the rubric. For each, produce a `pass` / `fail` / `warn` status
67
67
  backed by a specific, quotable evidence reference (quote, section, claim).
68
68
  4. **Score** — weighted aggregate per the rubric's scoring rules. `score` is 0.0–1.0.
@@ -107,7 +107,7 @@ Content to evaluate: {{content_path}}
107
107
  Rubric: {{rubric}} # general | tech-accuracy | brand-tone | compliance
108
108
  Output verdict to: {{verdict_path}}
109
109
 
110
- Load the rubric definition from plugins/kk/skills/judge/references/rubrics.md (section: {{rubric}}).
110
+ Load the rubric definition from plugins/kk/skills/content-judge/references/rubrics.md (section: {{rubric}}).
111
111
  Evaluate the content against every criterion in that rubric.
112
112
  For each criterion, quote the specific passage and assign pass | fail | warn.
113
113
  Decide the verdict: any must-pass fail → FAIL; else score < threshold → NEEDS_REVISION; else PASS.
@@ -119,13 +119,12 @@ Print the verdict path to stdout as the last line.
119
119
 
120
120
  See `references/workflow-integration.md` for the `agent.run` step shape and the shell/`jq` guard
121
121
  that reads the verdict. The example workflow is at
122
- `.spur/workflows/judge-gated-publish-example.yaml`.
122
+ `plugins/kk/workflows/judge-gated-publish-example.yaml`.
123
123
 
124
- ## Thin wrappers
124
+ ## Rubric selection
125
125
 
126
- The wrappers in `plugins/kk/agents/` (tech-accuracy, brand-tone, compliance) are thin: they fix
127
- the `rubric` field and forward to this skill. They do not duplicate evaluation logic. To create a
128
- new persona, add a wrapper that sets the rubric and reuses this skill's procedure verbatim.
126
+ The `agent.run` prompt (or the calling skill) sets `{{rubric}}`. To add a persona, add a rubric
127
+ section in `references/rubrics.md` and name it from the prompt — do not add a subagent wrapper.
129
128
 
130
129
  ## Additional resources
131
130
 
@@ -1,4 +1,4 @@
1
- # Workflow integration — judge in a spur workflow
1
+ # Workflow integration — content-judge in a spur workflow
2
2
 
3
3
  Spur's workflow engine executes one node at a time (`type: parallel` is an inert schema field —
4
4
  see `docs/03_ARCHITECTURE.md`). The judge step is therefore a single `agent.run` node followed
@@ -7,16 +7,18 @@ by a `shell` node that guards the transition to `publish`.
7
7
  ## Step shape
8
8
 
9
9
  ```yaml
10
- - name: judge
11
- type: agent.run
12
- run: |
13
- Evaluate the generated content against the {{rubric}} rubric.
14
- Content: {{content_path}}
15
- Write the verdict to {{verdict_path}}.
16
- skill: judge
10
+ - kind: agent.run
11
+ options:
12
+ role: reviewer
13
+ input: |
14
+ Evaluate the generated content against the {{rubric}} rubric.
15
+ Content: {{content_path}}
16
+ Write the verdict to {{verdict_path}}.
17
+ Load plugins/kk/skills/content-judge/SKILL.md.
18
+ expectFile: "{{verdict_path}}"
17
19
  ```
18
20
 
19
- - `agent.run` spawns an agent that loads the `judge` skill, performs the evaluation, and writes
21
+ - `agent.run` spawns an agent that loads the `content-judge` skill, performs the evaluation, and writes
20
22
  the verdict JSON to `{{verdict_path}}` (typically `.spur/run/verdict-judge.json`).
21
23
  - The verdict file is the only durable artifact. The agent's prose output is not the contract.
22
24
 
@@ -60,7 +62,7 @@ esac
60
62
 
61
63
  For a bounded regenerate-retry loop, wire the workflow so that a `NEEDS_REVISION` verdict routes
62
64
  back to the `generate` step with the verdict's `feedback` as additional input. Cap retries (the
63
- example workflow uses 2). This is workflow-level orchestration — `judge` itself is stateless
65
+ example workflow uses 2). This is workflow-level orchestration — `content-judge` itself is stateless
64
66
  and re-runnable.
65
67
 
66
68
  ```
@@ -73,5 +75,5 @@ generate ──▶ judge ──PASS──▶ publish
73
75
 
74
76
  ## Workflow YAML location
75
77
 
76
- The runnable example lives at `.spur/workflows/judge-gated-publish-example.yaml`. It demonstrates
78
+ The runnable example lives at `plugins/kk/workflows/judge-gated-publish-example.yaml`. It demonstrates
77
79
  `generate → judge → guard → publish` with a 2-retry NEEDS_REVISION loop.
@@ -0,0 +1,147 @@
1
+ ---
2
+ name: itc-generating
3
+ description: >-
4
+ Use the itc-generating skill to produce an approved IT technical draft from a
5
+ topic or Markdown brief, applying the distilled generic IT-writing method and
6
+ an optional platform playbook — "write an article about X applying the IT
7
+ writing method", "generate an IT technical draft on X", "create a technical
8
+ article for WeChat/English platforms". Orchestrates topic (outline + draft),
9
+ optional storm-research, and optional content-judge without enlarging those skills.
10
+ ---
11
+
12
+ # itc-generating — IT technical draft generation (method + orchestration)
13
+
14
+ ## Purpose
15
+
16
+ Turn a topic or Markdown brief into an **approved IT technical draft** by applying the distilled
17
+ IT-writing craft and orchestrating the existing `kk` skills — `topic` (outline + draft), optional
18
+ `storm-research` (evidence), optional `content-judge` (technical-accuracy gate). One fat skill with one
19
+ operation, `create`, whose default is the distilled generic-craft method; it delegates outline
20
+ selection and draft review to `topic` and writes the **same topic artifact paths**. This skill owns
21
+ *which* method and *when* to research/judge — it never reimplements topic-core, research, or
22
+ evaluation (D6).
23
+
24
+ ## When to use
25
+
26
+ - A user asks to write an IT technical article from a topic or brief and wants the distilled
27
+ IT-writing method applied ("write an IT article about X", "produce a technical draft on X").
28
+ - A user wants a specific platform playbook applied to the draft (`--playbook english` / `wechat`).
29
+ - A user wants the same topic artifact contract but with the writing method and optional
30
+ research/judging orchestrated around it.
31
+
32
+ Do **not** use this skill for: a single topic-core step without the method (call `topic` directly);
33
+ research alone (call `storm-research`); evaluating content alone (call `content-judge`); publishing,
34
+ platform adaptation, or image generation (all out of scope); anything requiring a runtime plugin
35
+ (`kk executor run`, `plugin.json`, `GeneratorInput → Content`).
36
+
37
+ ## Invocation contract
38
+
39
+ `$ARGUMENTS` (or the Skill call args) parse as:
40
+
41
+ ```
42
+ [create] <topic-or-brief> [--dir <target>] [--brief <path>]
43
+ [--playbook generic|english|wechat]
44
+ [--research] [--judge]
45
+ [--outline <a|b|c>] [--revise <feedback>] [--force]
46
+ ```
47
+
48
+ | Token | Meaning | Default |
49
+ | --- | --- | --- |
50
+ | `create` | the only operation; may be omitted | `create` |
51
+ | `<topic-or-brief>` | quoted topic phrase, or `--brief <path>` naming a Markdown brief file | required — empty fails loud |
52
+ | `--dir <target>` | workspace directory | `./<kebab-case(topic)>` (same default as `topic`) |
53
+ | `--playbook <p>` | which reference to load as the writing method | `generic` |
54
+ | `--research` | if the workspace has no evidence, run `storm-research` first | off |
55
+ | `--judge` | after an approved draft, run `content-judge` with the `tech-accuracy` rubric | off |
56
+ | `--outline <a\|b\|c>` | explicit outline selection (passed through to `topic`) | operator selects at the gate |
57
+ | `--revise <feedback>` | revision feedback for the draft review gate (passed through to `topic`) | none (approve path) |
58
+ | `--force` | explicit operator approval to replace an existing artifact (passed through to `topic`) | off — never overwrite without it |
59
+
60
+ Flags may appear in any order; the first bare positional token is the topic phrase. An unknown
61
+ operation (anything other than `create`) fails loud and lists `create` as the only valid operation.
62
+
63
+ ## References (loaded on demand, R2)
64
+
65
+ | File | When to load |
66
+ | --- | --- |
67
+ | `references/generic-craft.md` | **always** on every `create` run — the five IT-writing disciplines |
68
+ | `references/platform-english.md` | `--playbook english` — X / Medium / Substack playbook |
69
+ | `references/platform-wechat.md` | `--playbook wechat` — WeChat Official Account playbook |
70
+ | `references/skill-authoring.md` | when reviewing or editing this skill — why it stays lean |
71
+
72
+ The four STORM studies remain in the works dirs (`~/.config/kk/works/`) as provenance; the skill
73
+ body and references do **not** vendor the full reports (D4).
74
+
75
+ ## Artifact contract (reuses topic, D5)
76
+
77
+ All paths are relative to the workspace `--dir`. This skill does **not** invent a parallel
78
+ workspace — it delegates to `topic`, which writes exactly these paths:
79
+
80
+ | Artifact | Path | Written by |
81
+ | --- | --- | --- |
82
+ | Brief | `brief.md` | `topic` `init` |
83
+ | Outline options | `2-outline/outline-option-{a,b,c}.md` | `topic` `outline` |
84
+ | Approved outline | `2-outline/outline-approved.md` | `topic` `outline` (after selection gate) |
85
+ | Draft | `3-draft/draft-article.md` | `topic` `draft` (from approved outline, review gate) |
86
+
87
+ ## create sequence
88
+
89
+ 1. **Input check** (fail loud, R5): empty topic and no `--brief` → stop with recovery. A `--brief`
90
+ path that does not exist → stop with recovery.
91
+ 2. **Target check** (fail loud, R5): if `--dir` exists with a `brief.md` and no `--force` → stop
92
+ with recovery ("initialization target already exists at `<dir>`; pass `--force` after explicit
93
+ operator confirmation to replace, or choose a new `--dir`"). Never overwrite without `--force`.
94
+ 3. **Load the method** — read `references/generic-craft.md` (always) plus the selected playbook if
95
+ `--playbook` is not `generic` (R2). If `--research` and the workspace has no reusable evidence,
96
+ invoke `storm-research` on the topic (XOR: a topic phrase or `--in <file>`); re-run research
97
+ only when the query or sources must change — reuse existing `docs.json` otherwise.
98
+ 4. **Delegate to `topic`** — run `topic create` against `--dir` with the same artifact contract and
99
+ gates: outline options → explicit selection gate (`--outline <a|b|c>` or interactive) → approved
100
+ outline → draft → review gate (approve or bounded `--revise`). This skill never reimplements
101
+ those gates (R1, R3).
102
+ 5. **Apply the method while drafting** — using the loaded references, apply the five disciplines
103
+ (one goal per document, value proposition as scope firewall, explicit prerequisites and POLA,
104
+ show-don't-tell with diagrams/examples, accessibility) plus the platform playbook's constraints
105
+ (e.g. WeChat mobile formatting or English-platform framing). The draft is written by `topic`
106
+ from the approved outline; the method shapes it.
107
+ 6. **Optional judge gate** — if `--judge` and `3-draft/draft-article.md` is approved, invoke
108
+ `content-judge` with the `tech-accuracy` rubric. A non-`PASS` verdict is reported to the operator; it
109
+ does **not** auto-publish and does not auto-revise past `topic`'s 3-round bound.
110
+ 7. **Print** the final artifact paths and stop.
111
+
112
+ ## Fail-loud table (R5)
113
+
114
+ | Condition | Behavior | Recovery instruction |
115
+ | --- | --- | --- |
116
+ | Empty topic and no `--brief` | Stop; no files created | Provide a topic phrase or `--brief <path>` |
117
+ | `--brief` path does not exist | Stop; no files created | Check the path; supply a real Markdown brief |
118
+ | `--research` with neither topic nor `--in` | Stop; nothing written | Pass exactly one of the topic / `--in <file>` to `storm-research` |
119
+ | Missing prerequisite artifact (e.g. outline before draft) | Stop; nothing written | The recovery comes from `topic` — run the prerequisite step first (see `topic` fail-loud table) |
120
+ | Existing initialization target without `--force` | Stop; no overwrite | Confirm with the operator and pass `--force`, or choose a new `--dir` |
121
+ | Unknown operation | Stop; nothing written | Use `create` (the only operation) or call `topic` / `storm-research` / `content-judge` directly |
122
+
123
+ Every stop names the exact missing or existing path and the exact next command. Never silently
124
+ skip, never auto-replace, never delete.
125
+
126
+ ## Invariants
127
+
128
+ - `create` is the **only** operation. Research, illustration, adaptation, and publish operations
129
+ are **not** added to `topic` — this skill delegates to `storm-research` / `content-judge` (R3).
130
+ - Reuse `topic` artifact paths; never invent a parallel workspace (D5).
131
+ - `topic` / `storm-research` / `content-judge` contracts are unchanged (D6) — this skill only orchestrates.
132
+ - No `plugins/kk/commands/itc*.md`, no `kk` CLI noun/verb, no generator `plugin.json` (R4).
133
+ - Never overwrite an existing artifact without `--force`; bound draft revision at `topic`'s 3
134
+ rounds.
135
+ - No live publish, no external side effects beyond the delegated research call, no image generation.
136
+
137
+ ## Prompt template (Skill() / agent.run)
138
+
139
+ ```
140
+ Skill(skill="itc-generating",
141
+ args="<topic-or-brief> [--dir <target>] [--brief <path>] [--playbook generic|english|wechat] [--research] [--judge] [--outline <a|b|c>] [--revise <feedback>] [--force]")
142
+ ```
143
+
144
+ When invoked, follow the `create` sequence above. Load the references the flags select, delegate
145
+ outline selection and draft review to `topic`, and pause for the operator at `topic`'s gates. On
146
+ any stop, output the fail-loud recovery line. The artifact paths under the workspace `--dir` are
147
+ the handoff.
@@ -0,0 +1,80 @@
1
+ # Generic IT-writing craft — five disciplines
2
+
3
+ Distilled from the STORM study "How to Write the Best Generic IT Technical Documentation"
4
+ (works dir `how-to-write-the-best-generic-it-technical-docum-0a71c5a7`, provenance only — this
5
+ reference replaces vendoring the full report). Load this reference on every `create` run; apply
6
+ all five disciplines while authoring the draft.
7
+
8
+ ## 1. Structure and scope (the document architect)
9
+
10
+ - Pick the document types you actually need — and **stop**. There is no universal list; add a
11
+ document only when no existing one's goal absorbs the content.
12
+ - **One document, one goal**, enforced at review: reread after writing and remove or move
13
+ anything that does not serve that goal. Write everything first, then cut.
14
+ - **Write the Value Proposition (VP) first**: a one-page list of what the doc will do for its
15
+ reader (save time, reduce errors, cut training…). It says nothing about format or fonts. Use it
16
+ as a scope-creep firewall — keep content that supports a VP item, remove the rest.
17
+ - **Plan before writing**: research first (history → latest literature → what existing docs
18
+ already cover), then a documentation plan (scope, objectives, estimates, workflows, resources).
19
+ Do not over-invest in placement up front — move a document after it exists.
20
+ - **One goal per section** too: link out to other documents for prerequisites and detail instead
21
+ of inlining everything.
22
+
23
+ ## 2. Write for the reader (the reader advocate)
24
+
25
+ - **Profile the readership** enough to structure and customize for them. Do not assume background,
26
+ environment, context, or that they have read your other docs — link prerequisites instead of
27
+ inlining them.
28
+ - **Show, don't tell**: lead with diagrams (process flows, C4 views), then explain in prose.
29
+ Text-based diagrams (Mermaid, PlantUML) stay easy to update. Use at least one concrete example
30
+ early — a simple example beats an abstract description.
31
+ - **Principle of Least Astonishment (POLA)**: cover the gotchas and non-typical usage up front —
32
+ undocumented prerequisites, surprising defaults, implicit ordering. Name assumptions, defaults,
33
+ and prerequisites explicitly.
34
+ - **Long-form craft**: a succinct, jargon-free title; structure against the five Ws + H; write the
35
+ introduction last, once the content has settled.
36
+ - **Accessibility and inclusive writing** are concrete requirements: follow accessibility
37
+ guidelines for structure/language; use inclusive example names and bias-free language.
38
+
39
+ ## 3. Make it a team discipline (the engineering manager)
40
+
41
+ - **Budget for docs time**: measure how long SME review of writer output takes and factor it into
42
+ each release. Good docs are written once, read hundreds of times.
43
+ - **Close the specialized-skill gap**: technical writing is its own discipline (audience
44
+ understanding + logical presentation); bring in a technical writer or build review processes
45
+ that treat writing with the same rigor as code.
46
+ - **Embed docs in the engineering workflow**: docs reviews inside normal PR review, preview builds
47
+ on each check-in, docs as part of shipping every release — not a post-release afterthought.
48
+ - **Docs are coordination infrastructure** at team scale: they improve knowledge retention and
49
+ underpin quality, consistency, and compliance.
50
+ - **Build documentation mindshare**: state the problem, start in engineering, gather input
51
+ broadly, build a taxonomy, make contribution easy, meet regularly.
52
+
53
+ ## 4. Keep it fresh (the maintenance owner)
54
+
55
+ - **Docs go stale by default**; the countermeasure is procedural — assess doc impact of changes
56
+ each sprint and allocate update time in the release.
57
+ - **Make updates cheap**: prefer simple human-readable formats (Markdown — diffable in Git) and
58
+ text-based diagrams so edits stay cheap.
59
+ - **Institutionalize the lifecycle**: plan → write → review → publish, with research up front and
60
+ maintenance at the end; take occasional content inventories and use reader feedback to fill gaps.
61
+
62
+ ## 5. Tooling and publishing (the pipeline engineer)
63
+
64
+ - **Match tools to doc types and languages**; when in doubt, defer to Markdown and tooling with
65
+ simple human-readable formats. A convenient editor matters — you won't write docs you hate
66
+ editing.
67
+ - **Bake publishing into CI/CD**: build docs from sources and publish on every release; generate
68
+ docs from code artifacts where possible (OpenAPI is the canonical example).
69
+ - **Plan reuse**: write content once and reuse it (CCMS for cross-product scale); audit for
70
+ overlap before duplication spreads.
71
+ - **Adopt (or author) style guides**: shared style guides keep output consistent — don't write
72
+ them from scratch (Write the Docs maintains a living one). During review, get the right experts
73
+ on the right documents and use preview runs to catch errors before publication.
74
+
75
+ ## Applying this in `create`
76
+
77
+ While drafting `3-draft/draft-article.md` (after `topic`'s outline gate), apply: one goal per
78
+ document enforced at the draft-review gate; the Value Proposition as a scope firewall; explicit
79
+ prerequisites and POLA; show-don't-tell with diagrams/examples; and accessibility. The `--judge`
80
+ gate then verifies technical accuracy against the rubric.