@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.
- package/dist/index.js +21604 -11844
- package/package.json +4 -1
- package/plugins/generations/content-gen/package.json +2 -1
- package/plugins/generations/content-gen/src/index.ts +9 -8
- package/plugins/generations/content-gen/src/storm.ts +12 -4
- package/plugins/generations/dailynews-gen/package.json +17 -0
- package/plugins/generations/dailynews-gen/plugin.json +7 -0
- package/plugins/generations/dailynews-gen/src/index.ts +111 -0
- package/plugins/generations/dailynews-gen/src/script-builder.ts +121 -0
- package/plugins/generations/dailynews-gen/tsconfig.json +4 -0
- package/plugins/generations/voice-gen/package.json +17 -0
- package/plugins/generations/voice-gen/plugin.json +6 -0
- package/plugins/generations/voice-gen/src/concat.ts +218 -0
- package/plugins/generations/voice-gen/src/index.ts +228 -0
- package/plugins/generations/voice-gen/src/mp3.ts +65 -0
- package/plugins/generations/voice-gen/src/voicebox-client.ts +223 -0
- package/plugins/generations/voice-gen/src/voicescript.ts +365 -0
- package/plugins/generations/voice-gen/tsconfig.json +8 -0
- package/plugins/ingestions/aihot-ingest/package.json +17 -0
- package/plugins/ingestions/aihot-ingest/plugin.json +7 -0
- package/plugins/ingestions/aihot-ingest/src/client.ts +185 -0
- package/plugins/ingestions/aihot-ingest/src/index.ts +137 -0
- package/plugins/ingestions/aihot-ingest/src/mapper.ts +42 -0
- package/plugins/ingestions/aihot-ingest/tsconfig.json +4 -0
- package/plugins/ingestions/karakeep-local/package.json +17 -0
- package/plugins/ingestions/karakeep-local/src/index.ts +31 -26
- package/plugins/ingestions/karakeep-local/tsconfig.json +4 -0
- package/plugins/ingestions/web-search/package.json +4 -1
- package/plugins/ingestions/web-search/src/index.ts +139 -16
- package/plugins/kk/README.md +9 -3
- package/plugins/kk/commands/workflow-run.md +100 -28
- package/plugins/kk/config.example.yaml +34 -0
- package/plugins/kk/scripts/render-md.ts +8 -3
- package/plugins/kk/skills/{judge → content-judge}/SKILL.md +13 -14
- package/plugins/kk/skills/{judge → content-judge}/references/workflow-integration.md +13 -11
- package/plugins/kk/skills/itc-generating/SKILL.md +147 -0
- package/plugins/kk/skills/itc-generating/references/generic-craft.md +80 -0
- package/plugins/kk/skills/itc-generating/references/platform-english.md +72 -0
- package/plugins/kk/skills/itc-generating/references/platform-wechat.md +60 -0
- package/plugins/kk/skills/itc-generating/references/skill-authoring.md +62 -0
- package/plugins/kk/skills/storm-research/SKILL.md +10 -3
- package/plugins/kk/workflows/judge-gated-publish-example.yaml +101 -0
- package/plugins/kk/workflows/kk-daily-ai-voice.yaml +144 -0
- package/plugins/kk/workflows/kk-ingest-generate-publish.yaml +72 -0
- package/plugins/kk/workflows/kk-itc.yaml +285 -0
- package/plugins/kk/workflows/kk-solo-podcast.yaml +374 -0
- package/plugins/kk/workflows/validate-voicescript.ts +226 -0
- package/plugins/publishings/emdash-pub/package.json +17 -0
- package/plugins/publishings/emdash-pub/plugin.json +7 -0
- package/plugins/publishings/emdash-pub/src/index.ts +450 -0
- package/plugins/publishings/emdash-pub/tsconfig.json +4 -0
- package/plugins/publishings/qiita-pub/package.json +2 -1
- package/plugins/publishings/qiita-pub/src/index.ts +9 -9
- package/plugins/publishings/surfdash-pub/package.json +2 -1
- package/plugins/publishings/surfdash-pub/src/index.ts +17 -12
- package/plugins/publishings/zenn-pub/package.json +2 -1
- package/plugins/publishings/zenn-pub/src/index.ts +11 -11
- package/plugins/kk/agents/judge-compliance.md +0 -37
- package/plugins/kk/agents/judge-tech.md +0 -35
- package/plugins/kk/agents/judge-tone.md +0 -37
- /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
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
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
|
|
12
|
-
`plugins/kk/skills/storm-research/SKILL.md`
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
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
|
-
-
|
|
26
|
-
|
|
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
|
|
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"
|
|
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
|
|
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
|
|
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.
|
|
116
|
-
|
|
117
|
-
|
|
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
|
-
|
|
127
|
-
`$work_dir/content.
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
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}${
|
|
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.
|
|
14
|
-
|
|
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
|
|
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** —
|
|
65
|
-
`compliance`, `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
|
-
|
|
122
|
+
`plugins/kk/workflows/judge-gated-publish-example.yaml`.
|
|
123
123
|
|
|
124
|
-
##
|
|
124
|
+
## Rubric selection
|
|
125
125
|
|
|
126
|
-
The
|
|
127
|
-
|
|
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
|
-
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
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
|
|
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.
|