@gobing-ai/knowledge-kit 0.0.36 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +1 -1
- package/dist/board/collect/index.css +654 -16
- package/dist/board/collect/index.js +191 -64
- package/dist/board/daily-voice/index.css +679 -12
- package/dist/board/daily-voice/index.js +185 -66
- package/dist/board/itc/index.css +679 -13
- package/dist/board/itc/index.js +188 -66
- package/dist/index.js +2878 -152
- package/package.json +3 -2
- package/plugins/generations/content-gen/dist/index.js +158 -12
- package/plugins/generations/core-facts-gen/dist/index.js +158 -12
- package/plugins/generations/daily-article-gen/dist/index.js +158 -12
- package/plugins/generations/dailynews-gen/dist/index.js +180 -12
- package/plugins/generations/dailynews-gen/src/script-plan.ts +32 -0
- package/plugins/generations/episode-plan-gen/dist/index.js +158 -12
- package/plugins/generations/gemini-tts/README.md +4 -3
- package/plugins/generations/gemini-tts/dist/index.js +158 -12
- package/plugins/generations/image-gen/dist/index.js +158 -12
- package/plugins/generations/news-report-gen/dist/index.js +158 -12
- package/plugins/generations/omni-voice-gen/README.md +15 -4
- package/plugins/generations/omni-voice-gen/profiles.json +1 -2
- package/plugins/generations/voice-gen/dist/index.js +158 -12
- package/plugins/generations/voxcpm-tts/README.md +21 -1
- package/plugins/generations/voxcpm-tts/dist/index.js +173 -13
- package/plugins/generations/voxcpm-tts/scripts/audit-speaker-consistency.py +109 -0
- package/plugins/generations/voxcpm-tts/src/voxcpm-client.ts +28 -1
- package/plugins/ingestions/aihot-ingest/dist/index.js +158 -12
- package/plugins/ingestions/horizon-ingest/dist/index.js +158 -12
- package/plugins/ingestions/last30days-ingest/dist/index.js +158 -12
- package/plugins/ingestions/web-search/dist/index.js +158 -12
- package/plugins/kk/commands/workflow-run.md +56 -18
- package/plugins/kk/decisions/kk-itc.yaml +46 -0
- package/plugins/kk/decisions/kk-seo-keyword.yaml +57 -0
- package/plugins/kk/decisions/kk-seo-page.yaml +230 -0
- package/plugins/kk/decisions/kk-seo-pair.yaml +21 -0
- package/plugins/kk/decisions/kk-seo-site.yaml +90 -0
- package/plugins/kk/plugin.json +1 -1
- package/plugins/kk/publish-presets/chinese-article.json +14 -0
- package/plugins/kk/publish-presets/technical-article.json +14 -0
- package/plugins/kk/references/smart-seo-attribution.md +85 -0
- package/plugins/kk/scripts/daily-stages.ts +42 -2
- package/plugins/kk/scripts/daily-voice-style.zh.md +1 -1
- package/plugins/kk/scripts/itc-stages.ts +25 -118
- package/plugins/kk/scripts/kk-workflow-stages.ts +38 -1
- package/plugins/kk/scripts/seo-decisions.ts +477 -0
- package/plugins/kk/scripts/seo-enrich.ts +728 -0
- package/plugins/kk/scripts/seo-facts.ts +610 -0
- package/plugins/kk/scripts/seo-fetch.ts +766 -0
- package/plugins/kk/scripts/seo-report.ts +460 -0
- package/plugins/kk/scripts/seo-rules.ts +1882 -0
- package/plugins/kk/scripts/seo-stages.ts +1044 -0
- package/plugins/kk/skills/article-adapt/SKILL.md +2 -2
- package/plugins/kk/skills/smart-seo/SKILL.md +183 -0
- package/plugins/kk/skills/smart-seo/references/method.md +126 -0
- package/plugins/kk/skills/smart-seo/references/narrative.md +125 -0
- package/plugins/kk/skills/smart-seo/references/operations.md +202 -0
- package/plugins/kk/skills/smart-seo/references/seo-geo-sources.md +90 -0
- package/plugins/kk/workflows/feature-verification.yaml +28 -24
- package/plugins/kk/workflows/kk-daily-ai-voice2.yaml +86 -18
- package/plugins/kk/workflows/kk-itc-author.yaml +406 -0
- package/plugins/kk/workflows/kk-itc.yaml +208 -682
- package/plugins/kk/workflows/kk-smart-seo.yaml +251 -0
- package/plugins/publishings/bilibili-pub/dist/index.js +21782 -0
- package/plugins/publishings/bilibili-pub/dist/profile-check.js +20410 -0
- package/plugins/publishings/bilibili-pub/package.json +20 -0
- package/plugins/publishings/bilibili-pub/plugin.json +12 -0
- package/plugins/publishings/bilibili-pub/src/flow.ts +1296 -0
- package/plugins/publishings/bilibili-pub/src/index.ts +139 -0
- package/plugins/publishings/bilibili-pub/src/profile-check.ts +19 -0
- package/plugins/publishings/bilibili-pub/src/selectors.ts +222 -0
- package/plugins/publishings/bilibili-pub/tsconfig.json +4 -0
- package/plugins/publishings/cnblogs-pub/dist/index.js +21383 -0
- package/plugins/publishings/cnblogs-pub/dist/profile-check.js +20412 -0
- package/plugins/publishings/cnblogs-pub/package.json +19 -0
- package/plugins/publishings/cnblogs-pub/plugin.json +12 -0
- package/plugins/publishings/cnblogs-pub/src/flow.ts +708 -0
- package/plugins/publishings/cnblogs-pub/src/index.ts +172 -0
- package/plugins/publishings/cnblogs-pub/src/profile-check.ts +24 -0
- package/plugins/publishings/cnblogs-pub/src/selectors.ts +104 -0
- package/plugins/publishings/cnblogs-pub/tsconfig.json +4 -0
- package/plugins/publishings/csdn-pub/dist/index.js +21552 -0
- package/plugins/publishings/csdn-pub/dist/profile-check.js +20963 -0
- package/plugins/publishings/csdn-pub/package.json +19 -0
- package/plugins/publishings/csdn-pub/plugin.json +12 -0
- package/plugins/publishings/csdn-pub/src/index.ts +1178 -0
- package/plugins/publishings/csdn-pub/src/profile-check.ts +23 -0
- package/plugins/publishings/csdn-pub/tsconfig.json +4 -0
- package/plugins/publishings/emdash-pub/dist/index.js +158 -12
- package/plugins/publishings/emdash-pub/plugin.json +22 -1
- package/plugins/publishings/infoq-pub/dist/index.js +160 -12
- package/plugins/publishings/infoq-pub/dist/profile-check.js +160 -12
- package/plugins/publishings/infoq-pub/plugin.json +21 -0
- package/plugins/publishings/jike-pub/dist/index.js +21379 -0
- package/plugins/publishings/jike-pub/dist/profile-check.js +20951 -0
- package/plugins/publishings/jike-pub/package.json +19 -0
- package/plugins/publishings/jike-pub/plugin.json +12 -0
- package/plugins/publishings/jike-pub/src/index.ts +800 -0
- package/plugins/publishings/jike-pub/src/profile-check.ts +21 -0
- package/plugins/publishings/jike-pub/tsconfig.json +4 -0
- package/plugins/publishings/juejin-pub/dist/index.js +160 -12
- package/plugins/publishings/juejin-pub/dist/profile-check.js +160 -12
- package/plugins/publishings/juejin-pub/plugin.json +21 -0
- package/plugins/publishings/medium-pub/dist/index.js +158 -12
- package/plugins/publishings/medium-pub/plugin.json +22 -1
- package/plugins/publishings/podcast-pub/dist/index.js +158 -12
- package/plugins/publishings/qiita-pub/dist/index.js +158 -12
- package/plugins/publishings/qiita-pub/plugin.json +24 -1
- package/plugins/publishings/shipinhao-pub/dist/index.js +21715 -0
- package/plugins/publishings/shipinhao-pub/dist/profile-check.js +20431 -0
- package/plugins/publishings/shipinhao-pub/package.json +19 -0
- package/plugins/publishings/shipinhao-pub/plugin.json +12 -0
- package/plugins/publishings/shipinhao-pub/src/flow.ts +1323 -0
- package/plugins/publishings/shipinhao-pub/src/index.ts +173 -0
- package/plugins/publishings/shipinhao-pub/src/profile-check.ts +25 -0
- package/plugins/publishings/shipinhao-pub/src/selectors.ts +241 -0
- package/plugins/publishings/shipinhao-pub/tsconfig.json +4 -0
- package/plugins/publishings/sspai-pub/dist/index.js +21371 -0
- package/plugins/publishings/sspai-pub/dist/profile-check.js +20414 -0
- package/plugins/publishings/sspai-pub/package.json +19 -0
- package/plugins/publishings/sspai-pub/plugin.json +12 -0
- package/plugins/publishings/sspai-pub/src/flow.ts +624 -0
- package/plugins/publishings/sspai-pub/src/index.ts +167 -0
- package/plugins/publishings/sspai-pub/src/profile-check.ts +25 -0
- package/plugins/publishings/sspai-pub/src/selectors.ts +122 -0
- package/plugins/publishings/sspai-pub/tsconfig.json +4 -0
- package/plugins/publishings/substack-pub/dist/index.js +160 -12
- package/plugins/publishings/substack-pub/dist/profile-check.js +160 -12
- package/plugins/publishings/substack-pub/plugin.json +21 -0
- package/plugins/publishings/surfdash-pub/dist/index.js +158 -12
- package/plugins/publishings/surfdash-pub/plugin.json +22 -1
- package/plugins/publishings/threads-pub/dist/index.js +158 -12
- package/plugins/publishings/wechatmp-pub/dist/index.js +1669 -502
- package/plugins/publishings/wechatmp-pub/dist/profile-check.js +204 -21
- package/plugins/publishings/wechatmp-pub/plugin.json +32 -0
- package/plugins/publishings/wechatmp-pub/src/cgi-draft.ts +540 -0
- package/plugins/publishings/wechatmp-pub/src/cgi-media.ts +380 -0
- package/plugins/publishings/wechatmp-pub/src/cgi.ts +485 -0
- package/plugins/publishings/wechatmp-pub/src/flow.ts +104 -0
- package/plugins/publishings/weibo-pub/dist/index.js +160 -12
- package/plugins/publishings/weibo-pub/dist/profile-check.js +160 -12
- package/plugins/publishings/weibo-pub/plugin.json +35 -0
- package/plugins/publishings/x-pub/dist/index.js +160 -12
- package/plugins/publishings/x-pub/dist/profile-check.js +160 -12
- package/plugins/publishings/x-pub/plugin.json +40 -0
- package/plugins/publishings/xhs-pub/dist/index.js +160 -12
- package/plugins/publishings/xhs-pub/dist/profile-check.js +160 -12
- package/plugins/publishings/xhs-pub/plugin.json +37 -0
- package/plugins/publishings/xiaoyuzhou-pub/dist/index.js +21491 -0
- package/plugins/publishings/xiaoyuzhou-pub/dist/profile-check.js +20417 -0
- package/plugins/publishings/xiaoyuzhou-pub/package.json +19 -0
- package/plugins/publishings/xiaoyuzhou-pub/plugin.json +12 -0
- package/plugins/publishings/xiaoyuzhou-pub/src/flow.ts +826 -0
- package/plugins/publishings/xiaoyuzhou-pub/src/index.ts +174 -0
- package/plugins/publishings/xiaoyuzhou-pub/src/profile-check.ts +26 -0
- package/plugins/publishings/xiaoyuzhou-pub/src/selectors.ts +125 -0
- package/plugins/publishings/xiaoyuzhou-pub/tsconfig.json +4 -0
- package/plugins/publishings/zenn-pub/dist/index.js +158 -12
- package/plugins/publishings/zenn-pub/plugin.json +22 -1
- package/plugins/generations/omni-voice-gen/voices/robin-news.wav +0 -0
|
@@ -1,733 +1,259 @@
|
|
|
1
1
|
---
|
|
2
|
-
"$schema": "@gobing-ai/spur/schemas/state-machine-workflow.schema.json"
|
|
3
2
|
name: kk-itc
|
|
4
|
-
kind:
|
|
3
|
+
kind: dag
|
|
4
|
+
version: "2"
|
|
5
5
|
description: >-
|
|
6
|
-
IT content authoring
|
|
7
|
-
|
|
8
|
-
initialState: prepare
|
|
9
|
-
terminalStates:
|
|
10
|
-
- done
|
|
11
|
-
- failed
|
|
12
|
-
failureStates:
|
|
13
|
-
- failed
|
|
6
|
+
IT content authoring and publication DAG: prepare -> child authoring FSM -> verify-child-freeze
|
|
7
|
+
-> illustration/SEO branches -> materialize & plan -> target check -> fan-out send -> reconcile-settle -> report
|
|
14
8
|
|
|
15
9
|
vars:
|
|
10
|
+
# Config-backed options default to "" so `workflows.kk-itc` and compiled defaults apply (0303);
|
|
11
|
+
# the frozen `$work_dir/itc-options.json` is the single source every downstream node reads.
|
|
16
12
|
topic: ""
|
|
17
13
|
input_file: ""
|
|
14
|
+
from_collect: ""
|
|
15
|
+
topic_profile: ""
|
|
16
|
+
run_date: ""
|
|
18
17
|
work_dir: ""
|
|
19
|
-
writer: "
|
|
20
|
-
playbook: "
|
|
21
|
-
|
|
22
|
-
judge: "false"
|
|
23
|
-
auto: "false" # auto mode: writer-recommended outline, no draft-review pause, mandatory judge, auto revise loop
|
|
24
|
-
unslop: "false" # run kk:taste-unslop on the draft before review/judge
|
|
25
|
-
max_revisions: "2" # cap on the auto revise loop (interactive stays bounded by the existing 3)
|
|
18
|
+
writer: ""
|
|
19
|
+
playbook: ""
|
|
20
|
+
rubric: "tech-accuracy"
|
|
26
21
|
outline: ""
|
|
22
|
+
research: ""
|
|
23
|
+
judge: ""
|
|
24
|
+
auto: ""
|
|
25
|
+
unslop: ""
|
|
27
26
|
force: "false"
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
browser_target: "" # internal cursor for the browser publish loop (written by itc-publish-next)
|
|
42
|
-
|
|
43
|
-
states:
|
|
27
|
+
max_revisions: ""
|
|
28
|
+
source_locale: ""
|
|
29
|
+
publish_targets: ""
|
|
30
|
+
publish_preset: ""
|
|
31
|
+
publish_live: ""
|
|
32
|
+
cover_enabled: ""
|
|
33
|
+
inline_images: ""
|
|
34
|
+
seo_mode: ""
|
|
35
|
+
agent: "inline"
|
|
36
|
+
__runId: ""
|
|
37
|
+
__definitionDigest: ""
|
|
38
|
+
|
|
39
|
+
nodes:
|
|
44
40
|
- id: prepare
|
|
45
|
-
description: "
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
fi;
|
|
125
|
-
cp "$src" "${vars.work_dir}/2-outline/outline-approved.md";
|
|
126
|
-
|
|
127
|
-
- id: draft-write
|
|
128
|
-
description: "Author full technical draft from approved outline (agent.run)"
|
|
129
|
-
onEnter:
|
|
130
|
-
- kind: agent.run
|
|
131
|
-
options:
|
|
132
|
-
role: scribe
|
|
133
|
-
agent: ${vars.agent}
|
|
134
|
-
input: |
|
|
135
|
-
Invoke the kk:${vars.writer} skill.
|
|
136
|
-
Author the technical draft at ${vars.work_dir}/3-draft-draft-article.md based on approved outline ${vars.work_dir}/2-outline/outline-approved.md and brief ${vars.work_dir}/brief.md using playbook ${vars.playbook}.
|
|
137
|
-
Revision feedback: ${vars.__hitlInput}
|
|
138
|
-
expectFile: ${vars.work_dir}/3-draft-draft-article.md
|
|
139
|
-
|
|
140
|
-
- id: unslop
|
|
141
|
-
description: "De-slop pass — kk:taste-unslop line-edits the draft (writes a new file, then the swap makes it in place)"
|
|
142
|
-
onEnter:
|
|
143
|
-
- kind: agent.run
|
|
144
|
-
options:
|
|
145
|
-
role: scribe
|
|
146
|
-
agent: ${vars.agent}
|
|
147
|
-
input: |
|
|
148
|
-
Invoke the kk:taste-unslop skill.
|
|
149
|
-
Read ${vars.work_dir}/3-draft-draft-article.md and write the line-edited version to ${vars.work_dir}/3-draft-draft-article.new.md, removing slop (AI-tell phrasing, filler, hedging) while preserving the technical claims, code blocks, links, and the approved outline's structure. Do not modify or delete the original file; the pipeline swaps the edited file in.
|
|
150
|
-
expectFile: ${vars.work_dir}/3-draft-draft-article.new.md
|
|
151
|
-
- kind: shell
|
|
152
|
-
options:
|
|
153
|
-
command: mv -f "${vars.work_dir}/3-draft-draft-article.new.md" "${vars.work_dir}/3-draft-draft-article.md"
|
|
154
|
-
|
|
155
|
-
- id: draft-review
|
|
156
|
-
description: "Operator reviews and approves or requests revision on draft-article.md"
|
|
157
|
-
pause: true
|
|
158
|
-
onEnter:
|
|
159
|
-
- kind: hitl.confirm
|
|
160
|
-
options:
|
|
161
|
-
prompt: "Review draft at ${vars.work_dir}/3-draft-draft-article.md. Approve?"
|
|
162
|
-
var: __hitlAnswer
|
|
163
|
-
|
|
164
|
-
- id: draft-revise
|
|
165
|
-
description: "Collect revision feedback from operator (bounded by 3 rounds)"
|
|
166
|
-
pause: true
|
|
167
|
-
onEnter:
|
|
168
|
-
- kind: shell
|
|
169
|
-
options:
|
|
170
|
-
command: >-
|
|
171
|
-
n=$(cat "${vars.work_dir}/.revise-count" 2>/dev/null || echo 0);
|
|
172
|
-
echo $((n + 1)) > "${vars.work_dir}/.revise-count";
|
|
173
|
-
- kind: hitl.input
|
|
174
|
-
options:
|
|
175
|
-
prompt: "Judge feedback (from ${vars.work_dir}/.itc-verdict.json): ${vars.__verdictFeedback}\nProvide specific revision feedback for ${vars.work_dir}/3-draft-draft-article.md:"
|
|
176
|
-
var: __hitlInput
|
|
177
|
-
|
|
178
|
-
- id: draft-autorevise
|
|
179
|
-
description: "Auto mode — apply the judge feedback[] to the draft and consume one revision from the budget"
|
|
180
|
-
onEnter:
|
|
181
|
-
- kind: shell
|
|
182
|
-
options:
|
|
183
|
-
command: >-
|
|
184
|
-
n=$(cat "${vars.work_dir}/.auto-revise-count" 2>/dev/null || echo 0);
|
|
185
|
-
echo $((n + 1)) > "${vars.work_dir}/.auto-revise-count";
|
|
186
|
-
- kind: agent.run
|
|
187
|
-
options:
|
|
188
|
-
role: scribe
|
|
189
|
-
agent: ${vars.agent}
|
|
190
|
-
input: |
|
|
191
|
-
Invoke the kk:${vars.writer} skill.
|
|
192
|
-
Read the draft at ${vars.work_dir}/3-draft-draft-article.md and write a revised version to ${vars.work_dir}/3-draft-draft-article.new.md, applying every item of feedback[] in ${vars.work_dir}/.itc-verdict.json. Do not modify or delete the original file; the pipeline swaps the revised file in.
|
|
193
|
-
expectFile: ${vars.work_dir}/3-draft-draft-article.new.md
|
|
194
|
-
- kind: shell
|
|
195
|
-
options:
|
|
196
|
-
command: mv -f "${vars.work_dir}/3-draft-draft-article.new.md" "${vars.work_dir}/3-draft-draft-article.md"
|
|
197
|
-
|
|
198
|
-
- id: publish-entry
|
|
199
|
-
description: "Publish tail entry — targets are set; route into illustration/materialization"
|
|
200
|
-
|
|
201
|
-
- id: illustrate
|
|
202
|
-
description: "Optional cover/inline illustrations via kk:image-authoring — entered only when a spend var is on (R7)"
|
|
203
|
-
onEnter:
|
|
204
|
-
- kind: agent.run
|
|
205
|
-
options:
|
|
206
|
-
role: scribe
|
|
207
|
-
agent: ${vars.agent}
|
|
208
|
-
input: |
|
|
209
|
-
Invoke the kk:image-authoring skill with KK_NONINTERACTIVE=1 and KK_IMAGE_AUTO_CONFIRM=1 (non-interactive, auto-confirm — the operator approved spend via the cover_enabled/inline_images vars).
|
|
210
|
-
Create ${vars.work_dir}/4-illustrations/ and generate the cover illustration into it as cover.png (cover.jpg acceptable), sized for an article hero image.
|
|
211
|
-
When inline_images=true, also generate inline figures for the draft's key sections as inline-<slug>.png in the same directory.
|
|
212
|
-
Print each written path as the last line of stdout.
|
|
213
|
-
- kind: shell
|
|
214
|
-
options:
|
|
215
|
-
command: >-
|
|
216
|
-
test "${vars.cover_enabled}" = "true" || exit 0;
|
|
217
|
-
ls "${vars.work_dir}"/4-illustrations/cover.* >/dev/null 2>&1 || { echo "cover_enabled=true but no 4-illustrations/cover.* in ${vars.work_dir}" >&2; exit 1; }
|
|
218
|
-
|
|
219
|
-
- id: materialize
|
|
220
|
-
description: "Materialize the approved draft to 4-publish/content.json"
|
|
221
|
-
onEnter:
|
|
222
|
-
- kind: shell
|
|
223
|
-
options:
|
|
224
|
-
command: >-
|
|
225
|
-
kk stage itc-materialize "${vars.work_dir}" "${vars.publish_live}"
|
|
226
|
-
|
|
227
|
-
- id: publish-plan
|
|
228
|
-
description: "Split targets into fan-out groups and browser targets (4-publish/publish-plan.json)"
|
|
229
|
-
onEnter:
|
|
230
|
-
- kind: shell
|
|
231
|
-
options:
|
|
232
|
-
command: >-
|
|
233
|
-
kk stage itc-publish-plan "${vars.work_dir}" "${vars.publish_targets}" "${vars.source_locale}" "${vars.publish_live}"
|
|
234
|
-
|
|
235
|
-
- id: adapt
|
|
236
|
-
description: "Write one adapted Content file per plan variant with adapt:true — kk:article-adapt (R9)"
|
|
237
|
-
onEnter:
|
|
238
|
-
- kind: agent.run
|
|
239
|
-
options:
|
|
240
|
-
role: scribe
|
|
241
|
-
agent: ${vars.agent}
|
|
242
|
-
input: |
|
|
243
|
-
Invoke the kk:article-adapt skill.
|
|
244
|
-
Read ${vars.work_dir}/4-publish/publish-plan.json and, for every entry in variants with adapt=true, read the source ${vars.work_dir}/4-publish/content.json and write ${vars.work_dir}/4-publish/<entry.file>: translate title and body to the variant locale, apply the entry's limits, and keep code blocks, URLs and references unchanged.
|
|
245
|
-
Set format to the variant key's format suffix. Never set metadata.published, metadata.publishStatus or metadata.operation — itc-publish-fanout stamps the draft/live switches at send time.
|
|
246
|
-
- kind: shell
|
|
247
|
-
options:
|
|
248
|
-
command: >-
|
|
249
|
-
kk stage itc-adapt-verify "${vars.work_dir}"
|
|
250
|
-
|
|
251
|
-
- id: publish-gate
|
|
252
|
-
description: "Route to the operator confirm unless auto publishes drafts"
|
|
253
|
-
|
|
254
|
-
- id: publish-confirm
|
|
255
|
-
description: "Operator confirms the send — every target, draft or live mode"
|
|
256
|
-
pause: true
|
|
257
|
-
onEnter:
|
|
258
|
-
- kind: hitl.confirm
|
|
259
|
-
options:
|
|
260
|
-
prompt: >-
|
|
261
|
-
Send to targets [${vars.publish_targets}] in ${vars.publish_live} mode (false = draft,
|
|
262
|
-
true = LIVE)? Review ${vars.work_dir}/4-publish/publish-plan.json first.
|
|
263
|
-
var: __hitlAnswer
|
|
264
|
-
- kind: shell
|
|
265
|
-
options:
|
|
266
|
-
command: >-
|
|
267
|
-
test "${vars.__hitlAnswer}" = "yes" || printf declined > "${vars.work_dir}/4-publish/.publish-declined"
|
|
268
|
-
|
|
269
|
-
- id: publish-fanout
|
|
270
|
-
description: "Send each fan-out group through kk executor fan-out — target failures are data"
|
|
271
|
-
onEnter:
|
|
272
|
-
- kind: shell
|
|
273
|
-
options:
|
|
274
|
-
command: >-
|
|
275
|
-
kk stage itc-publish-fanout "${vars.work_dir}"
|
|
276
|
-
|
|
277
|
-
- id: publish-retry
|
|
278
|
-
description: "Re-send failed fan-out groups once through --retry-from (V5)"
|
|
279
|
-
onEnter:
|
|
280
|
-
- kind: shell
|
|
281
|
-
options:
|
|
282
|
-
command: >-
|
|
283
|
-
n=$(cat "${vars.work_dir}/.publish-retry-count" 2>/dev/null || echo 0);
|
|
284
|
-
echo $((n + 1)) > "${vars.work_dir}/.publish-retry-count";
|
|
285
|
-
kk stage itc-publish-fanout "${vars.work_dir}" --retry
|
|
286
|
-
|
|
287
|
-
- id: publish-agent
|
|
288
|
-
description: "Publish one pending browser target via kk:publish — file-cursor loop bounded by the plan"
|
|
289
|
-
onEnter:
|
|
290
|
-
- kind: file.read.into-var
|
|
291
|
-
options:
|
|
292
|
-
path: ${vars.work_dir}/4-publish/.next-browser
|
|
293
|
-
var: browser_target
|
|
294
|
-
- kind: agent.run
|
|
295
|
-
options:
|
|
296
|
-
role: scribe
|
|
297
|
-
agent: ${vars.agent}
|
|
298
|
-
input: |
|
|
299
|
-
Invoke the kk:publish skill for the browser target ${vars.browser_target}.
|
|
300
|
-
Read ${vars.work_dir}/4-publish/publish-plan.json, find the browser entry whose target is ${vars.browser_target}, and use that variant's file under ${vars.work_dir}/4-publish/ as the Content input.
|
|
301
|
-
When the plan's live is true pass the skill's --live flag; otherwise publish as a draft (V4).
|
|
302
|
-
Always write the Result to ${vars.work_dir}/4-publish/result.${vars.browser_target}.json, including {ok: false, error: ...} when the publish fails.
|
|
303
|
-
expectFile: ${vars.work_dir}/4-publish/result.${vars.browser_target}.json
|
|
304
|
-
- kind: shell
|
|
305
|
-
options:
|
|
306
|
-
command: 'kk stage itc-publish-next "${vars.work_dir}"'
|
|
307
|
-
|
|
308
|
-
- id: judge
|
|
309
|
-
description: "Evaluate technical draft with content-judge (agent.run)"
|
|
310
|
-
onEnter:
|
|
311
|
-
- kind: agent.run
|
|
312
|
-
options:
|
|
313
|
-
role: reviewer
|
|
314
|
-
agent: ${vars.agent}
|
|
315
|
-
input: |
|
|
316
|
-
Invoke the kk:content-judge skill.
|
|
317
|
-
Evaluate the draft at ${vars.work_dir}/3-draft-draft-article.md against the ${vars.rubric} rubric.
|
|
318
|
-
Research evidence: if ${vars.work_dir}/docs.json exists, read it and weigh it when judging.
|
|
319
|
-
Write the verdict JSON to ${vars.work_dir}/.itc-verdict.json per the skill's verdict contract.
|
|
320
|
-
Print the verdict path as the last line of stdout.
|
|
321
|
-
expectFile: ${vars.work_dir}/.itc-verdict.json
|
|
322
|
-
- kind: file.read.into-var
|
|
323
|
-
options:
|
|
324
|
-
path: ${vars.work_dir}/.itc-verdict.json
|
|
325
|
-
var: __verdictFeedback
|
|
326
|
-
|
|
327
|
-
- id: report
|
|
328
|
-
description: "Write the run report, then route to done or failed on its outcome"
|
|
329
|
-
onEnter:
|
|
330
|
-
- kind: shell
|
|
331
|
-
options:
|
|
332
|
-
command: >-
|
|
333
|
-
kk stage itc-report "${vars.work_dir}" "${vars.max_revisions}"
|
|
334
|
-
|
|
335
|
-
- id: done
|
|
336
|
-
description: "Terminal — IT content draft generated and approved successfully"
|
|
337
|
-
- id: failed
|
|
338
|
-
description: "Terminal — IT content workflow failed or rejected"
|
|
339
|
-
|
|
340
|
-
transitions:
|
|
341
|
-
- from: prepare
|
|
342
|
-
to: research
|
|
343
|
-
description: "Research enabled -> proceed to storm-research"
|
|
344
|
-
guard:
|
|
345
|
-
kind: shell
|
|
346
|
-
options:
|
|
347
|
-
command: 'test "${vars.research}" = "true"'
|
|
348
|
-
|
|
349
|
-
- from: prepare
|
|
350
|
-
to: outline-write
|
|
351
|
-
description: "Research disabled -> proceed directly to outline generation"
|
|
352
|
-
guard:
|
|
353
|
-
kind: shell
|
|
354
|
-
options:
|
|
355
|
-
command: 'test "${vars.research}" != "true"'
|
|
356
|
-
|
|
357
|
-
- from: research
|
|
358
|
-
to: outline-write
|
|
359
|
-
description: "Research completed -> proceed to outline generation"
|
|
360
|
-
guard:
|
|
361
|
-
kind: always
|
|
362
|
-
|
|
363
|
-
- from: outline-write
|
|
364
|
-
to: outline-autopick
|
|
365
|
-
description: "Auto mode with no pre-selected outline -> validate the writer recommendation and bind it"
|
|
366
|
-
guard:
|
|
367
|
-
kind: shell
|
|
368
|
-
options:
|
|
369
|
-
command: 'test "${vars.auto}" = "true" -a -z "${vars.outline}"'
|
|
370
|
-
|
|
371
|
-
- from: outline-write
|
|
372
|
-
to: outline-select
|
|
373
|
-
description: "Interactive mode with no pre-selected outline -> pause for operator selection"
|
|
374
|
-
guard:
|
|
375
|
-
kind: shell
|
|
376
|
-
options:
|
|
377
|
-
command: 'test "${vars.auto}" != "true" -a -z "${vars.outline}"'
|
|
378
|
-
|
|
379
|
-
- from: outline-write
|
|
380
|
-
to: outline-commit
|
|
381
|
-
description: "Outline pre-selected -> skip interactive selection"
|
|
382
|
-
guard:
|
|
383
|
-
kind: shell
|
|
384
|
-
options:
|
|
385
|
-
command: 'test -n "${vars.outline}"'
|
|
386
|
-
|
|
387
|
-
- from: outline-select
|
|
388
|
-
to: outline-commit
|
|
389
|
-
description: "Outline selected -> commit approved outline"
|
|
390
|
-
guard:
|
|
391
|
-
kind: always
|
|
392
|
-
|
|
393
|
-
- from: outline-autopick
|
|
394
|
-
to: outline-commit
|
|
395
|
-
description: "Writer recommendation validated and bound -> commit approved outline"
|
|
396
|
-
guard:
|
|
397
|
-
kind: always
|
|
398
|
-
|
|
399
|
-
- from: outline-commit
|
|
400
|
-
to: draft-write
|
|
401
|
-
description: "Approved outline committed -> write draft"
|
|
402
|
-
guard:
|
|
403
|
-
kind: always
|
|
404
|
-
|
|
405
|
-
- from: draft-write
|
|
406
|
-
to: unslop
|
|
407
|
-
description: "Unslop enabled -> de-slop the fresh draft"
|
|
408
|
-
guard:
|
|
409
|
-
kind: shell
|
|
410
|
-
options:
|
|
411
|
-
command: 'test "${vars.unslop}" = "true"'
|
|
412
|
-
|
|
413
|
-
- from: draft-write
|
|
414
|
-
to: draft-review
|
|
415
|
-
description: "Interactive mode without unslop -> pause for operator review"
|
|
416
|
-
guard:
|
|
417
|
-
kind: shell
|
|
418
|
-
options:
|
|
419
|
-
command: 'test "${vars.auto}" != "true" -a "${vars.unslop}" != "true"'
|
|
420
|
-
|
|
421
|
-
- from: draft-write
|
|
422
|
-
to: judge
|
|
423
|
-
description: "Auto mode without unslop -> straight to the judge"
|
|
424
|
-
guard:
|
|
425
|
-
kind: shell
|
|
426
|
-
options:
|
|
427
|
-
command: 'test "${vars.auto}" = "true" -a "${vars.unslop}" != "true"'
|
|
428
|
-
|
|
429
|
-
- from: unslop
|
|
430
|
-
to: judge
|
|
431
|
-
description: "Auto mode -> the de-slopped draft goes to the judge"
|
|
432
|
-
guard:
|
|
433
|
-
kind: shell
|
|
434
|
-
options:
|
|
435
|
-
command: 'test "${vars.auto}" = "true"'
|
|
436
|
-
|
|
437
|
-
- from: unslop
|
|
438
|
-
to: draft-review
|
|
439
|
-
description: "Interactive mode -> pause for operator review of the de-slopped draft"
|
|
440
|
-
guard:
|
|
41
|
+
description: "Freeze the effective options (itc-prepare) bound to this run, then prepare the brief"
|
|
42
|
+
action:
|
|
43
|
+
kind: shell
|
|
44
|
+
options:
|
|
45
|
+
# The entry normally freezes itc-options.json before launch (a collected topic must be
|
|
46
|
+
# chosen first); a direct launch freezes it here. A snapshot from another run is refused.
|
|
47
|
+
command: |
|
|
48
|
+
wd="${vars.work_dir}"; run="${vars.__runId}"; o="$wd/itc-options.json"
|
|
49
|
+
test -n "$wd" || { echo "work_dir is required (derive it with kk stage run itc-prepare)" >&2; exit 1; }
|
|
50
|
+
if [ ! -f "$o" ]; then
|
|
51
|
+
req="$(mktemp)"
|
|
52
|
+
jq -n --arg topic "${vars.topic}" --arg inputFile "${vars.input_file}" --arg fromCollect "${vars.from_collect}" \
|
|
53
|
+
--arg topicProfile "${vars.topic_profile}" --arg runDate "${vars.run_date}" --arg workDir "$wd" --arg parentRunId "$run" \
|
|
54
|
+
--arg writer "${vars.writer}" --arg playbook "${vars.playbook}" --arg sourceLocale "${vars.source_locale}" \
|
|
55
|
+
--arg publishTargets "${vars.publish_targets}" --arg publishPreset "${vars.publish_preset}" --arg seo "${vars.seo_mode}" \
|
|
56
|
+
--arg maxRevisions "${vars.max_revisions}" --arg research "${vars.research}" --arg judge "${vars.judge}" \
|
|
57
|
+
--arg auto "${vars.auto}" --arg unslop "${vars.unslop}" --arg force "${vars.force}" --arg publishLive "${vars.publish_live}" \
|
|
58
|
+
--arg coverEnabled "${vars.cover_enabled}" --arg inlineImages "${vars.inline_images}" \
|
|
59
|
+
'$ARGS.named | with_entries(select(.value != ""))
|
|
60
|
+
| with_entries(if (.key | IN("research","judge","auto","unslop","force","publishLive","coverEnabled","inlineImages"))
|
|
61
|
+
then .value = (.value == "true") else . end)
|
|
62
|
+
| if has("maxRevisions") then .maxRevisions |= tonumber else . end' > "$req" || { rm -f "$req"; exit 1; }
|
|
63
|
+
kk stage run itc-prepare --request "$req" > /dev/null; rc=$?; rm -f "$req"; test "$rc" -eq 0 || exit 1
|
|
64
|
+
fi
|
|
65
|
+
test -f "$o" || { echo "a collected topic must be chosen before launch: run the entry's intake, then itc-prepare --chosen" >&2; exit 1; }
|
|
66
|
+
pr=$(jq -r '.parentRunId' "$o")
|
|
67
|
+
if [ "$pr" != "$run" ] && [ "${vars.force}" != "true" ]; then
|
|
68
|
+
echo "$o belongs to run '$pr', not '$run'; pass force=true to adopt it" >&2; exit 1
|
|
69
|
+
fi
|
|
70
|
+
kind=$(jq -r '.sourceKind' "$o"); val=$(jq -r '.sourceValue' "$o")
|
|
71
|
+
case "$kind" in
|
|
72
|
+
input_file) kk stage run prepare-itc "$wd" "" "$val" "${vars.force}" ;;
|
|
73
|
+
from_collect) kk stage run prepare-itc "$wd" "$(jq -r '.displayTitle' "$o")" "" "${vars.force}" ;;
|
|
74
|
+
*) kk stage run prepare-itc "$wd" "$val" "" "${vars.force}" ;;
|
|
75
|
+
esac
|
|
76
|
+
|
|
77
|
+
- id: child-author
|
|
78
|
+
description: "Run child authoring state machine (outline -> draft -> unslop -> review/judge)"
|
|
79
|
+
dependsOn:
|
|
80
|
+
- prepare
|
|
81
|
+
action:
|
|
82
|
+
kind: shell
|
|
83
|
+
options:
|
|
84
|
+
# The child id is derived from the parent before launch, so an interrupted parent queries
|
|
85
|
+
# and continues the SAME child instead of starting a second one; a paused child stays a
|
|
86
|
+
# distinct non-success for the parent until it is answered and reaches done. The child
|
|
87
|
+
# runs as an owned process: a cancelled parent signals it and cancels its run.
|
|
88
|
+
command: |
|
|
89
|
+
cid="${vars.__runId}-author"
|
|
90
|
+
v=$(jq -c --arg wd "${vars.work_dir}" --arg agent "${vars.agent}" --arg rubric "${vars.rubric}" --arg outline "${vars.outline}" \
|
|
91
|
+
--arg run "${vars.__runId}" --arg dd "${vars.__definitionDigest}" \
|
|
92
|
+
'{work_dir:$wd, agent:$agent, rubric:$rubric, outline:$outline, writer:.writer, playbook:.playbook,
|
|
93
|
+
auto:(.auto|tostring), unslop:(.unslop|tostring), judge:(.judge|tostring), max_revisions:(.maxRevisions|tostring),
|
|
94
|
+
parent_run_id:$run, child_run_id:($run + "-author"), definition_digest:$dd, options_digest:.optionsDigest}' \
|
|
95
|
+
"${vars.work_dir}/itc-options.json") || exit 1
|
|
96
|
+
owned() {
|
|
97
|
+
env -u SPUR_WORKFLOW_RUN_ACTIVE -u SPUR_EXPECTED_DEFINITION_DIGEST "$@" &
|
|
98
|
+
pid=$!
|
|
99
|
+
trap 'kill -TERM "$pid" 2>/dev/null; spur workflow cancel "$cid" >/dev/null 2>&1; exit 143' TERM INT HUP
|
|
100
|
+
wait "$pid"; rc=$?
|
|
101
|
+
trap - TERM INT HUP
|
|
102
|
+
return "$rc"
|
|
103
|
+
}
|
|
104
|
+
st=$(spur workflow trace "$cid" --json 2>/dev/null | jq -r '.run.status // empty')
|
|
105
|
+
case "$st" in
|
|
106
|
+
done) exit 0 ;;
|
|
107
|
+
paused) owned spur workflow continue "$cid" --yes ;;
|
|
108
|
+
"") owned spur workflow run plugins/kk/workflows/kk-itc-author.yaml --run-id "$cid" --vars "$v" ;;
|
|
109
|
+
*) echo "child $cid is $st; refusing to relaunch it" >&2; exit 1 ;;
|
|
110
|
+
esac
|
|
111
|
+
st=$(spur workflow trace "$cid" --json 2>/dev/null | jq -r '.run.status // empty')
|
|
112
|
+
if [ "$st" = paused ]; then echo "child $cid paused: answer it with spur workflow continue $cid, then resume this run" >&2; exit 1; fi
|
|
113
|
+
test "$st" = done || { echo "child $cid ended $st" >&2; exit 1; }
|
|
114
|
+
|
|
115
|
+
- id: verify-child-freeze
|
|
116
|
+
description: "Verify child authoring completion receipt and freeze draft/outline digests"
|
|
117
|
+
dependsOn:
|
|
118
|
+
- child-author
|
|
119
|
+
action:
|
|
441
120
|
kind: shell
|
|
442
121
|
options:
|
|
443
|
-
command:
|
|
444
|
-
|
|
445
|
-
- from: draft-review
|
|
446
|
-
to: judge
|
|
447
|
-
description: "Draft approved and judge enabled -> evaluate quality"
|
|
448
|
-
guard:
|
|
449
|
-
kind: shell
|
|
450
|
-
options:
|
|
451
|
-
command: '{ test -z "${vars.__hitlAnswer}" || test "${vars.__hitlAnswer}" = "yes"; } && test "${vars.judge}" = "true"'
|
|
452
|
-
|
|
453
|
-
- from: draft-review
|
|
454
|
-
to: done
|
|
455
|
-
description: "Draft approved, judge disabled, no publish targets -> complete workflow"
|
|
456
|
-
guard:
|
|
457
|
-
kind: shell
|
|
458
|
-
options:
|
|
459
|
-
command: '{ test -z "${vars.__hitlAnswer}" || test "${vars.__hitlAnswer}" = "yes"; } && test "${vars.judge}" != "true" && test -z "${vars.publish_targets}"'
|
|
460
|
-
|
|
461
|
-
- from: draft-review
|
|
462
|
-
to: publish-entry
|
|
463
|
-
description: "Draft approved, judge disabled, targets set -> enter the publish tail"
|
|
464
|
-
guard:
|
|
465
|
-
kind: shell
|
|
466
|
-
options:
|
|
467
|
-
command: '{ test -z "${vars.__hitlAnswer}" || test "${vars.__hitlAnswer}" = "yes"; } && test "${vars.judge}" != "true" && test -n "${vars.publish_targets}"'
|
|
468
|
-
|
|
469
|
-
- from: draft-review
|
|
470
|
-
to: draft-revise
|
|
471
|
-
description: "Draft rejected with revision budget remaining -> collect feedback"
|
|
472
|
-
guard:
|
|
473
|
-
kind: shell
|
|
474
|
-
options:
|
|
475
|
-
command: 'test "${vars.__hitlAnswer}" = "no" && test "$(cat "${vars.work_dir}/.revise-count" 2>/dev/null || echo 0)" -lt 3'
|
|
476
|
-
|
|
477
|
-
- from: draft-review
|
|
478
|
-
to: failed
|
|
479
|
-
terminalReason: failed-guard
|
|
480
|
-
description: "Draft rejected with revision budget exhausted -> fail"
|
|
481
|
-
guard:
|
|
482
|
-
kind: shell
|
|
483
|
-
options:
|
|
484
|
-
command: 'test "${vars.__hitlAnswer}" = "no" && test "$(cat "${vars.work_dir}/.revise-count" 2>/dev/null || echo 0)" -ge 3'
|
|
485
|
-
|
|
486
|
-
- from: draft-revise
|
|
487
|
-
to: draft-write
|
|
488
|
-
description: "Feedback collected -> rewrite draft"
|
|
489
|
-
guard:
|
|
490
|
-
kind: always
|
|
122
|
+
command: >-
|
|
123
|
+
kk stage run itc-author-complete "${vars.work_dir}" "${vars.__runId}"
|
|
491
124
|
|
|
492
|
-
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
125
|
+
- id: illustrate
|
|
126
|
+
description: "Optional cover/inline illustrations via kk:image-authoring — entered only when a spend var is on (R7)"
|
|
127
|
+
dependsOn:
|
|
128
|
+
- verify-child-freeze
|
|
129
|
+
condition:
|
|
496
130
|
kind: shell
|
|
497
131
|
options:
|
|
498
|
-
command: '
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
to: judge
|
|
502
|
-
description: "Auto mode without unslop -> back to the judge"
|
|
503
|
-
guard:
|
|
504
|
-
kind: shell
|
|
132
|
+
command: 'jq -e ".coverEnabled or .inlineImages" "${vars.work_dir}/itc-options.json" >/dev/null'
|
|
133
|
+
action:
|
|
134
|
+
kind: agent.run
|
|
505
135
|
options:
|
|
506
|
-
|
|
136
|
+
role: scribe
|
|
137
|
+
agent: ${vars.agent}
|
|
138
|
+
input: |
|
|
139
|
+
Invoke the kk:image-authoring skill with KK_NONINTERACTIVE=1 and KK_IMAGE_AUTO_CONFIRM=1 (non-interactive, auto-confirm — the operator approved spend via the cover_enabled/inline_images vars).
|
|
140
|
+
Create ${vars.work_dir}/4-illustrations/ and generate the cover illustration into it as cover.png (cover.jpg acceptable), sized for an article hero image.
|
|
141
|
+
When inline_images=true, also generate inline figures for the draft's key sections as inline-<slug>.png in the same directory.
|
|
142
|
+
Print each written path as the last line of stdout.
|
|
507
143
|
|
|
508
|
-
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
144
|
+
- id: materialize-plan
|
|
145
|
+
description: "Materialize content.json and resolve publication targets into publish-plan.json"
|
|
146
|
+
dependsOn:
|
|
147
|
+
- verify-child-freeze
|
|
148
|
+
- illustrate
|
|
149
|
+
action:
|
|
512
150
|
kind: shell
|
|
513
151
|
options:
|
|
514
152
|
command: >-
|
|
515
|
-
|
|
516
|
-
{ v="$(jq -r 'if (.verdict // "") == "PASS" then (.verdict + (if ((.confidence // "") | test("^(HIGH|MEDIUM|LOW)$")) then "" else "!" end)) else (.verdict // "") end' ${vars.work_dir}/.itc-verdict.json 2>/dev/null)";
|
|
517
|
-
test -z "$v" -o "$v" = PASS; } &&
|
|
518
|
-
test -z "${vars.publish_targets}"
|
|
153
|
+
kk stage run itc-materialize-plan "${vars.work_dir}"
|
|
519
154
|
|
|
520
|
-
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
155
|
+
- id: adapt
|
|
156
|
+
description: "Prepare per-platform variant Content files via kk:article-adapt — runs only for adapt:true variants (R9)"
|
|
157
|
+
dependsOn:
|
|
158
|
+
- materialize-plan
|
|
159
|
+
action:
|
|
160
|
+
kind: agent.run
|
|
161
|
+
options:
|
|
162
|
+
role: scribe
|
|
163
|
+
agent: ${vars.agent}
|
|
164
|
+
input: |
|
|
165
|
+
Invoke the kk:article-adapt skill.
|
|
166
|
+
Read ${vars.work_dir}/4-publish/publish-plan.json and, for each entry in variants with adapt=true, read ${vars.work_dir}/4-publish/content.json and write the variant Content file to ${vars.work_dir}/4-publish/<variant.file>.
|
|
167
|
+
Apply the plan's variant limits and translate title and body into the variant's locale. Never set metadata.published; the publishing states set switches.
|
|
168
|
+
Print each written variant file path as the last line of stdout.
|
|
169
|
+
|
|
170
|
+
- id: adapt-verify
|
|
171
|
+
description: "Verify adapted variant content files"
|
|
172
|
+
dependsOn:
|
|
173
|
+
- adapt
|
|
174
|
+
action:
|
|
524
175
|
kind: shell
|
|
525
176
|
options:
|
|
526
177
|
command: >-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
test -n "${vars.publish_targets}"
|
|
178
|
+
test -f "${vars.work_dir}/4-publish/publish-plan.json" || exit 0;
|
|
179
|
+
kk stage run itc-adapt-verify "${vars.work_dir}"
|
|
530
180
|
|
|
531
|
-
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
181
|
+
- id: check-targets
|
|
182
|
+
description: "Check readiness probes for plannable publish targets"
|
|
183
|
+
dependsOn:
|
|
184
|
+
- materialize-plan
|
|
185
|
+
action:
|
|
535
186
|
kind: shell
|
|
536
187
|
options:
|
|
537
188
|
command: >-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
- from: judge
|
|
552
|
-
to: draft-revise
|
|
553
|
-
description: "Interactive mode, NEEDS_REVISION with revise budget left -> collect revision with the feedback shown"
|
|
554
|
-
guard:
|
|
555
|
-
kind: shell
|
|
556
|
-
options:
|
|
557
|
-
command: '{ test "${vars.auto}" != "true"; } && { v="$(jq -r .verdict ${vars.work_dir}/.itc-verdict.json 2>/dev/null)"; c="$(cat "${vars.work_dir}/.revise-count" 2>/dev/null || echo 0)"; test "$v" = NEEDS_REVISION -a "$c" -lt 3; }'
|
|
558
|
-
|
|
559
|
-
- from: judge
|
|
560
|
-
to: failed
|
|
561
|
-
terminalReason: failed-guard
|
|
562
|
-
description: "Interactive mode, verdict FAIL or revise budget exhausted -> fail"
|
|
563
|
-
guard:
|
|
564
|
-
kind: shell
|
|
565
|
-
options:
|
|
566
|
-
command: '{ test "${vars.auto}" != "true"; } && { v="$(jq -r .verdict ${vars.work_dir}/.itc-verdict.json 2>/dev/null)"; c="$(cat "${vars.work_dir}/.revise-count" 2>/dev/null || echo 0)"; test "$v" = FAIL || { test "$v" = NEEDS_REVISION -a "$c" -ge 3; }; }'
|
|
567
|
-
|
|
568
|
-
# --- 0151 publish tail: materialize -> plan -> gate -> confirm/fanout -> retry -> browser loop ---
|
|
569
|
-
|
|
570
|
-
- from: publish-entry
|
|
571
|
-
to: illustrate
|
|
572
|
-
description: "Cover or inline images approved -> run the illustration step (R7: no image spend while both vars are false)"
|
|
573
|
-
guard:
|
|
574
|
-
kind: shell
|
|
575
|
-
options:
|
|
576
|
-
command: 'test "${vars.cover_enabled}" = "true" -o "${vars.inline_images}" = "true"'
|
|
577
|
-
|
|
578
|
-
- from: publish-entry
|
|
579
|
-
to: materialize
|
|
580
|
-
description: "No illustration spend approved -> materialize directly"
|
|
581
|
-
guard:
|
|
189
|
+
test -f "${vars.work_dir}/4-publish/publish-plan.json" || exit 0;
|
|
190
|
+
kk stage run itc-check-targets "${vars.work_dir}"
|
|
191
|
+
|
|
192
|
+
- id: send-confirm
|
|
193
|
+
description: >-
|
|
194
|
+
Operator approval of a LIVE send: `pause: true` stops the run and RESUME is the approval
|
|
195
|
+
(no action); cancelling is the rejection. Skipped for draft-only or empty plans.
|
|
196
|
+
dependsOn:
|
|
197
|
+
- adapt-verify
|
|
198
|
+
- check-targets
|
|
199
|
+
pause: true
|
|
200
|
+
condition:
|
|
582
201
|
kind: shell
|
|
583
202
|
options:
|
|
584
|
-
command: '
|
|
585
|
-
|
|
586
|
-
- from: illustrate
|
|
587
|
-
to: materialize
|
|
588
|
-
description: "Illustrations written -> materialize the final draft (metadata.coverImage picks up 4-illustrations/cover.*)"
|
|
589
|
-
guard:
|
|
590
|
-
kind: always
|
|
203
|
+
command: 'jq -e ".live == true and (.targets // [] | length) > 0" "${vars.work_dir}/4-publish/publish-plan.json" >/dev/null 2>&1'
|
|
591
204
|
|
|
592
|
-
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
- from: publish-plan
|
|
599
|
-
to: adapt
|
|
600
|
-
description: "The plan has at least one adapt:true variant -> write the adapted variant files (R9)"
|
|
601
|
-
guard:
|
|
205
|
+
- id: fanout-send
|
|
206
|
+
description: "Dispatch target payloads via executor fan-out and record receipts"
|
|
207
|
+
dependsOn:
|
|
208
|
+
- send-confirm
|
|
209
|
+
action:
|
|
602
210
|
kind: shell
|
|
603
211
|
options:
|
|
604
212
|
command: >-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
- from: publish-plan
|
|
609
|
-
to: publish-gate
|
|
610
|
-
description: "Nothing needs adaptation -> route through the send gate"
|
|
611
|
-
guard:
|
|
612
|
-
kind: always
|
|
213
|
+
test -f "${vars.work_dir}/4-publish/publish-plan.json" || exit 0;
|
|
214
|
+
kk stage run itc-send-targets "${vars.work_dir}"
|
|
613
215
|
|
|
614
|
-
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
- from: publish-gate
|
|
621
|
-
to: publish-confirm
|
|
622
|
-
description: "Interactive run or live publish -> pause for the operator answer (V4)"
|
|
623
|
-
guard:
|
|
216
|
+
- id: fanout-recovery
|
|
217
|
+
description: "Retry safe effect-none target failures once within budget"
|
|
218
|
+
dependsOn:
|
|
219
|
+
- fanout-send
|
|
220
|
+
action:
|
|
624
221
|
kind: shell
|
|
625
222
|
options:
|
|
626
223
|
command: >-
|
|
627
|
-
test "${vars.
|
|
628
|
-
|
|
629
|
-
- from: publish-gate
|
|
630
|
-
to: publish-fanout
|
|
631
|
-
description: "Auto draft run -> send without pausing (ADR-022)"
|
|
632
|
-
guard:
|
|
633
|
-
kind: always
|
|
634
|
-
|
|
635
|
-
- from: publish-confirm
|
|
636
|
-
to: publish-fanout
|
|
637
|
-
description: "Operator confirmed -> send"
|
|
638
|
-
guard:
|
|
639
|
-
kind: shell
|
|
640
|
-
options:
|
|
641
|
-
command: 'test "${vars.__hitlAnswer}" = "yes"'
|
|
224
|
+
test -f "${vars.work_dir}/4-publish/publish-plan.json" || exit 0;
|
|
225
|
+
kk stage run itc-send-targets "${vars.work_dir}" --retry
|
|
642
226
|
|
|
643
|
-
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
227
|
+
- id: reconcile-settle
|
|
228
|
+
description: "Reconcile target receipts and settle store selection"
|
|
229
|
+
dependsOn:
|
|
230
|
+
- fanout-recovery
|
|
231
|
+
action:
|
|
647
232
|
kind: shell
|
|
648
233
|
options:
|
|
649
234
|
command: >-
|
|
650
|
-
|
|
235
|
+
kk stage run itc-reconcile-receipts "${vars.work_dir}"
|
|
651
236
|
|
|
652
|
-
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
237
|
+
- id: seo
|
|
238
|
+
description: "Export SEO prepublish request and published pages handoffs"
|
|
239
|
+
dependsOn:
|
|
240
|
+
- verify-child-freeze
|
|
241
|
+
action:
|
|
656
242
|
kind: shell
|
|
657
243
|
options:
|
|
658
244
|
command: >-
|
|
659
|
-
|
|
660
|
-
-a -s "${vars.work_dir}/4-publish/.fanout-failed"
|
|
661
|
-
|
|
662
|
-
- from: publish-fanout
|
|
663
|
-
to: publish-agent
|
|
664
|
-
description: "A browser target has no result.<target>.json -> run the kk:publish loop"
|
|
665
|
-
guard:
|
|
666
|
-
kind: shell
|
|
667
|
-
options:
|
|
668
|
-
# .next-browser cursor: seeded by itc-publish-fanout, recomputed after each kk:publish step
|
|
669
|
-
command: 'test -s "${vars.work_dir}/4-publish/.next-browser"'
|
|
245
|
+
kk stage run itc-export-seo "${vars.work_dir}" "$(jq -r '.seo' "${vars.work_dir}/itc-options.json")"
|
|
670
246
|
|
|
671
|
-
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
guard:
|
|
681
|
-
kind: shell
|
|
682
|
-
options:
|
|
683
|
-
# .next-browser cursor: seeded by itc-publish-fanout, recomputed after each kk:publish step
|
|
684
|
-
command: 'test -s "${vars.work_dir}/4-publish/.next-browser"'
|
|
685
|
-
|
|
686
|
-
- from: publish-retry
|
|
687
|
-
to: report
|
|
688
|
-
description: "Otherwise -> report (remaining fan-out failures are terminal data)"
|
|
689
|
-
guard:
|
|
690
|
-
kind: always
|
|
691
|
-
|
|
692
|
-
- from: publish-agent
|
|
693
|
-
to: publish-agent
|
|
694
|
-
description: "A browser target is still pending -> next cursor iteration (bounded by the plan, V5)"
|
|
695
|
-
guard:
|
|
696
|
-
kind: shell
|
|
697
|
-
options:
|
|
698
|
-
# .next-browser cursor: seeded by itc-publish-fanout, recomputed after each kk:publish step
|
|
699
|
-
command: 'test -s "${vars.work_dir}/4-publish/.next-browser"'
|
|
700
|
-
|
|
701
|
-
- from: publish-agent
|
|
702
|
-
to: report
|
|
703
|
-
description: "Browser list exhausted -> report"
|
|
704
|
-
guard:
|
|
705
|
-
kind: always
|
|
706
|
-
|
|
707
|
-
- from: report
|
|
708
|
-
to: done
|
|
709
|
-
description: "Report outcome done or declined (empty outcome = done in dry-run, mirroring the empty-verdict PASS convention)"
|
|
710
|
-
guard:
|
|
711
|
-
kind: shell
|
|
712
|
-
options:
|
|
713
|
-
command: 'o="$(jq -r .outcome ${vars.work_dir}/5-report/report.json 2>/dev/null)"; test -z "$o" -o "$o" = done -o "$o" = declined'
|
|
714
|
-
|
|
715
|
-
- from: report
|
|
716
|
-
to: failed
|
|
717
|
-
terminalReason: failed-guard
|
|
718
|
-
description: "Report outcome failed -> fail"
|
|
719
|
-
guard:
|
|
720
|
-
kind: shell
|
|
721
|
-
options:
|
|
722
|
-
command: 'o="$(jq -r .outcome ${vars.work_dir}/5-report/report.json 2>/dev/null)"; test -n "$o" -a "$o" != done'
|
|
723
|
-
|
|
724
|
-
- from: judge
|
|
725
|
-
to: failed
|
|
726
|
-
terminalReason: failed-guard
|
|
727
|
-
description: "Catch-all: an out-of-contract verdict string fails the run instead of deadlocking the machine (0149 review P3); a PASS whose confidence is missing or outside HIGH/MEDIUM/LOW reads as `PASS!` and lands here"
|
|
728
|
-
guard:
|
|
247
|
+
- id: report
|
|
248
|
+
description: "Produce final run report summary"
|
|
249
|
+
# Mandatory freeze plus every branch: a skipped optional branch still satisfies the edge,
|
|
250
|
+
# so an all-skipped publication reports, but a report never races an unfinished send.
|
|
251
|
+
dependsOn:
|
|
252
|
+
- verify-child-freeze
|
|
253
|
+
- reconcile-settle
|
|
254
|
+
- seo
|
|
255
|
+
action:
|
|
729
256
|
kind: shell
|
|
730
257
|
options:
|
|
731
258
|
command: >-
|
|
732
|
-
|
|
733
|
-
test -n "$v" -a "$v" != PASS -a "$v" != FAIL -a "$v" != NEEDS_REVISION
|
|
259
|
+
kk stage run itc-report-summary "${vars.work_dir}" "$(jq -r '.maxRevisions' "${vars.work_dir}/itc-options.json")"
|