@gobing-ai/knowledge-kit 0.0.17 → 0.0.18

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 (74) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/README.md +74 -0
  3. package/dist/index.js +46 -100
  4. package/package.json +19 -1
  5. package/plugins/generations/content-gen/dist/index.js +42 -94
  6. package/plugins/generations/core-facts-gen/dist/index.js +51 -100
  7. package/plugins/generations/daily-article-gen/dist/index.js +57 -99
  8. package/plugins/generations/daily-article-gen/src/index.ts +12 -4
  9. package/plugins/generations/dailynews-gen/dist/index.js +57 -102
  10. package/plugins/generations/dailynews-gen/src/script-builder.ts +9 -1
  11. package/plugins/generations/episode-plan-gen/dist/index.js +120 -113
  12. package/plugins/generations/episode-plan-gen/src/index.ts +102 -22
  13. package/plugins/generations/image-gen/dist/index.js +63 -115
  14. package/plugins/generations/news-report-gen/dist/index.js +117 -99
  15. package/plugins/generations/news-report-gen/src/index.ts +117 -1
  16. package/plugins/generations/omni-voice-gen/src/omni_voice_gen/pipeline.py +1 -1
  17. package/plugins/generations/omni-voice-gen/src/omni_voice_gen/voicescript.py +8 -0
  18. package/plugins/generations/voice-gen/dist/index.js +101 -117
  19. package/plugins/generations/voice-gen/src/concat.ts +34 -0
  20. package/plugins/generations/voice-gen/src/index.ts +6 -4
  21. package/plugins/generations/voice-gen/src/voicescript.ts +8 -0
  22. package/plugins/ingestions/aihot-ingest/dist/index.js +47 -97
  23. package/plugins/ingestions/horizon-ingest/dist/index.js +47 -96
  24. package/plugins/ingestions/karakeep-local/dist/index.js +217 -266
  25. package/plugins/ingestions/last30days-ingest/dist/index.js +42 -91
  26. package/plugins/ingestions/web-search/dist/index.js +68 -117
  27. package/plugins/kk/plugin.json +1 -1
  28. package/plugins/kk/scripts/kk-workflow-stages.ts +320 -62
  29. package/plugins/kk/skills/publish/SKILL.md +80 -0
  30. package/plugins/kk/workflows/kk-daily-ai-voice.yaml +107 -107
  31. package/plugins/kk/workflows/leftover-publish-fanout-example.yaml +53 -0
  32. package/plugins/publishings/emdash-pub/dist/index.js +42 -91
  33. package/plugins/publishings/infoq-pub/dist/index.js +21994 -0
  34. package/plugins/publishings/infoq-pub/package.json +17 -0
  35. package/plugins/publishings/infoq-pub/plugin.json +7 -0
  36. package/plugins/publishings/infoq-pub/src/index.ts +123 -0
  37. package/plugins/publishings/infoq-pub/tsconfig.json +4 -0
  38. package/plugins/publishings/juejin-pub/dist/index.js +21994 -0
  39. package/plugins/publishings/juejin-pub/package.json +17 -0
  40. package/plugins/publishings/juejin-pub/plugin.json +7 -0
  41. package/plugins/publishings/juejin-pub/src/index.ts +123 -0
  42. package/plugins/publishings/juejin-pub/tsconfig.json +4 -0
  43. package/plugins/publishings/medium-pub/dist/index.js +22041 -0
  44. package/plugins/publishings/medium-pub/package.json +17 -0
  45. package/plugins/publishings/medium-pub/plugin.json +7 -0
  46. package/plugins/publishings/medium-pub/src/index.ts +215 -0
  47. package/plugins/publishings/medium-pub/tsconfig.json +4 -0
  48. package/plugins/publishings/podcast-pub/dist/index.js +183 -123
  49. package/plugins/publishings/podcast-pub/src/index.ts +47 -3
  50. package/plugins/publishings/podcast-pub/src/show-notes.ts +153 -34
  51. package/plugins/publishings/qiita-pub/dist/index.js +42 -91
  52. package/plugins/publishings/substack-pub/dist/index.js +21994 -0
  53. package/plugins/publishings/substack-pub/package.json +17 -0
  54. package/plugins/publishings/substack-pub/plugin.json +7 -0
  55. package/plugins/publishings/substack-pub/src/index.ts +123 -0
  56. package/plugins/publishings/substack-pub/tsconfig.json +4 -0
  57. package/plugins/publishings/surfdash-pub/dist/index.js +172 -103
  58. package/plugins/publishings/surfdash-pub/src/index.ts +32 -2
  59. package/plugins/publishings/wechatmp-pub/dist/index.js +22119 -0
  60. package/plugins/publishings/wechatmp-pub/package.json +17 -0
  61. package/plugins/publishings/wechatmp-pub/plugin.json +7 -0
  62. package/plugins/publishings/wechatmp-pub/src/index.ts +304 -0
  63. package/plugins/publishings/wechatmp-pub/tsconfig.json +4 -0
  64. package/plugins/publishings/x-pub/dist/index.js +22110 -0
  65. package/plugins/publishings/x-pub/package.json +17 -0
  66. package/plugins/publishings/x-pub/plugin.json +7 -0
  67. package/plugins/publishings/x-pub/src/index.ts +222 -0
  68. package/plugins/publishings/x-pub/tsconfig.json +4 -0
  69. package/plugins/publishings/xhs-pub/dist/index.js +21994 -0
  70. package/plugins/publishings/xhs-pub/package.json +17 -0
  71. package/plugins/publishings/xhs-pub/plugin.json +7 -0
  72. package/plugins/publishings/xhs-pub/src/index.ts +123 -0
  73. package/plugins/publishings/xhs-pub/tsconfig.json +4 -0
  74. package/plugins/publishings/zenn-pub/dist/index.js +42 -91
@@ -19,7 +19,12 @@ vars:
19
19
  limit: "10"
20
20
  language: "zh"
21
21
  voice_profile: "robin-news"
22
- voice_generator: "omni-voice-gen"
22
+ # 20260917: voice driver switch — ominivoice (default, omni-voice-gen) | voicebox (voice-gen).
23
+ vdriver: "ominivoice"
24
+ # 20260917 review #7: 8s intro sting prepended to every daily output; empty = skip.
25
+ intro_music: ".works/kk-daily-ai-voice/AI每日资讯_8秒播客片头.mp3"
26
+ # 20260917 review #4/#6: surfdash checkout the patch stage commits to.
27
+ surfdash_root: "/Users/robin/xprojects/surfdash"
23
28
  title: ""
24
29
  cursor: ""
25
30
  state_file: ""
@@ -28,6 +33,7 @@ vars:
28
33
  cover_enabled: "true"
29
34
  plan_max_items: "20"
30
35
  plan_translate_enabled: "true"
36
+ article_write_enabled: "true"
31
37
  plugins_path: ""
32
38
  last30days_topic: "AI news"
33
39
  horizon_hours: "24"
@@ -35,10 +41,12 @@ vars:
35
41
  last30days_enabled: "false"
36
42
  run_date: ""
37
43
  agent: "inline"
38
- surfdash_post_path: ""
39
44
  surfdash_en_post_path: ""
40
45
  surfdash_ja_post_path: ""
41
- qc_categories: "ai-news,ai-industry"
46
+ # 20260917 funnel: allowlist widened to the whole AI taxonomy in lockstep with
47
+ # episode-plan-gen's DEFAULT_FILTER_CONFIG — genuine technical/research stories died on
48
+ # category:not-in-allowlist. `non-ai` stays excluded (that is the point of the gate).
49
+ qc_categories: "ai-news,ai-technical,ai-research,ai-industry"
42
50
  # 0098 dogfood calibration (r7, owner-approved 0099): quality 3→2, impact 2→1 — the shipped
43
51
  # defaults rejected 20/20 live candidates (strongest ai-news items died solely on impact:1<2).
44
52
  # These pins must move in lockstep with episode-plan-gen's DEFAULT_FILTER_CONFIG (env wins).
@@ -124,14 +132,30 @@ states:
124
132
  # ADR-115 error tier: keep this prompt <= 1000 chars (0133 R3; 0138 R4a adds the copy discipline).
125
133
  input: |
126
134
  Read ${vars.work_dir}/2-plan/${vars.run_date}_04_quality-control-content_candidates.json — metadata.docs (Doc[]) is the plan; don't edit it.
127
- For items with needsTranslation, translate "title" and "body" into natural, concise simplified Chinese.
128
- Titles read as a news event (subject + action + object) from the body — e.g. "OpenAI 发布 Sora 应用,集成 Sora 2 模型". Keep product/model/company names verbatim, preserve body URLs, use 「」 not ASCII double quotes.
135
+ For items with needsTranslation, translate "title", "body", and "metadata.brief" (when present) into natural simplified Chinese.
136
+ Titles read as a news event (subject + action + object) — e.g. "OpenAI 发布 Sora 应用,集成 Sora 2 模型". Keep product/model/company names verbatim, preserve body URLs, use 「」 not ASCII double quotes.
129
137
  Copy discipline: reader-facing news copy — no scaffold labels (「可做角度」「为什么现在值得注意」「社区讨论」「背景」「潜在影响」「影响」), no duplicated labels or hedging (「读者宜另行核实」「仍待验证」) — merge their substance into prose or drop.
130
138
  Keep other fields (id, sourceUri, mediaType, metadata), technical terms as-is; no trailing commas or comments.
131
139
  Output strictly valid JSON — a same-length, same-order array with the same ids — to ${vars.work_dir}/2-plan/${vars.run_date}_03_plan_plan.json.
132
140
  expectFile: ${vars.work_dir}/2-plan/${vars.run_date}_03_plan_plan.json
133
141
  allowAppend: false
134
142
 
143
+ - id: article-write
144
+ description: "Write the morning-news prose article from the translated plan via agent.run (3-format split: surfdash gets prose, not a news list)"
145
+ onEnter:
146
+ - kind: agent.run
147
+ options:
148
+ role: scribe
149
+ agent: ${vars.agent}
150
+ # ADR-115 error tier: keep this prompt <= 1000 chars (0133 R3).
151
+ input: |
152
+ Read ${vars.work_dir}/2-plan/${vars.run_date}_03_plan_plan.json — metadata.docs (Doc[]) is the translated plan; don't edit it.
153
+ Write a morning-news prose article in natural simplified Chinese: title line "# 每日 AI 资讯 — ${vars.run_date}", an intro paragraph (2–3 sentences), then one section per item (## numbered title, 2–4 sentences of flowing prose, source link [来源:<label>](<sourceUri>) inline), a closing paragraph tying items together.
154
+ Narrative register — smooth transitions between items, no list-like bulleting, no scaffold labels (「可做角度」「背景」「潜在影响」), no hedging (「读者宜另行核实」「仍待验证」). Keep facts/URLs from the plan verbatim; product/model names as-is; 「」 quotes.
155
+ Output the markdown to ${vars.work_dir}/2-article/${vars.run_date}_06_article-write_body.md.
156
+ expectFile: ${vars.work_dir}/2-article/${vars.run_date}_06_article-write_body.md
157
+ allowAppend: false
158
+
135
159
  - id: article
136
160
  description: "Generate the dated daily article from the episode plan (daily-article-gen template)"
137
161
  onEnter:
@@ -205,7 +229,7 @@ states:
205
229
  bun "$st" daily-wrap-docs "${vars.work_dir}" "${vars.run_date}" "${vars.voice_profile}"
206
230
 
207
231
  - id: generate
208
- description: "Invoke voice generator plugin (voice_generator var) to generate audio"
232
+ description: "Invoke voice driver plugin (vdriver var: ominivoice -> omni-voice-gen, voicebox -> voice-gen) to generate audio"
209
233
  onEnter:
210
234
  - kind: shell
211
235
  options:
@@ -215,7 +239,20 @@ states:
215
239
  st="$pkg/plugins/kk/scripts/kk-workflow-stages.ts";
216
240
  [ -f "$st" ] || st="plugins/kk/scripts/kk-workflow-stages.ts";
217
241
  [ -f "$st" ] || echo "kk-workflow-stages.ts not found at $st — install or refresh the kk package (bun link in a checkout)" >&2;
218
- bun "$st" daily-generate "${vars.work_dir}" "${vars.run_date}" "${vars.plugins_path}" "${vars.transcode_mp3}" "${vars.voice_generator}"
242
+ OMNIVOICE_SPEED=1.06 bun "$st" daily-generate "${vars.work_dir}" "${vars.run_date}" "${vars.plugins_path}" "${vars.transcode_mp3}" "${vars.vdriver}"
243
+
244
+ - id: intro-music
245
+ description: "Prepend the 8s intro sting (intro_music var; empty = skip) to the generated wav, update duration/audioPath"
246
+ onEnter:
247
+ - kind: shell
248
+ options:
249
+ command: >-
250
+ kbin="$(command -v kk 2>/dev/null)";
251
+ pkg="$(dirname "$(dirname "$(realpath "$kbin" 2>/dev/null)")")";
252
+ st="$pkg/plugins/kk/scripts/kk-workflow-stages.ts";
253
+ [ -f "$st" ] || st="plugins/kk/scripts/kk-workflow-stages.ts";
254
+ [ -f "$st" ] || echo "kk-workflow-stages.ts not found at $st — install or refresh the kk package (bun link in a checkout)" >&2;
255
+ bun "$st" daily-intro "${vars.work_dir}" "${vars.run_date}" "${vars.intro_music}"
219
256
 
220
257
  - id: quality-control
221
258
  description: "Verify audio quality, speech rate, and silence/repetition QC metrics"
@@ -295,8 +332,8 @@ states:
295
332
  [ -f "$st" ] || echo "kk-workflow-stages.ts not found at $st — install or refresh the kk package (bun link in a checkout)" >&2;
296
333
  bun "$st" daily-publish-classify "${vars.work_dir}" "${vars.run_date}"
297
334
 
298
- - id: publish-partial
299
- description: "Partial publish — at least one target published, at least one failed; echo warning, write a .spur/run marker, preserve result.json for --retry-from, continue to done (task 0118: surfdash failure = no-URL fallback notes; podcast failure = its own partial)"
335
+ - id: patch-surfdash
336
+ description: "20260917 #4/#6 — patch published surfdash posts: podcast cover URL into image/og_image frontmatter + podcast cross-link (zh/en/ja), commit+push"
300
337
  onEnter:
301
338
  - kind: shell
302
339
  options:
@@ -306,10 +343,10 @@ states:
306
343
  st="$pkg/plugins/kk/scripts/kk-workflow-stages.ts";
307
344
  [ -f "$st" ] || st="plugins/kk/scripts/kk-workflow-stages.ts";
308
345
  [ -f "$st" ] || echo "kk-workflow-stages.ts not found at $st — install or refresh the kk package (bun link in a checkout)" >&2;
309
- bun "$st" daily-publish-partial "${vars.work_dir}" "${vars.run_date}"
346
+ bun "$st" daily-patch-surfdash "${vars.work_dir}" "${vars.run_date}" "${vars.surfdash_root}"
310
347
 
311
- - id: run-report
312
- description: "Assemble the per-run report (scores+aggregates+rejected counts+step timing) from existing artifacts — news-report-gen; output-only, never throws; 0117"
348
+ - id: publish-partial
349
+ description: "Partial publish — at least one target published, at least one failed; echo warning, write a .spur/run marker, preserve result.json for --retry-from, continue to done (task 0118: surfdash failure = no-URL fallback notes; podcast failure = its own partial)"
313
350
  onEnter:
314
351
  - kind: shell
315
352
  options:
@@ -319,10 +356,10 @@ states:
319
356
  st="$pkg/plugins/kk/scripts/kk-workflow-stages.ts";
320
357
  [ -f "$st" ] || st="plugins/kk/scripts/kk-workflow-stages.ts";
321
358
  [ -f "$st" ] || echo "kk-workflow-stages.ts not found at $st — install or refresh the kk package (bun link in a checkout)" >&2;
322
- bun "$st" daily-run-report "${vars.work_dir}" "${vars.run_date}" "${vars.plugins_path}" "${vars.qc_min_quality}" "${vars.qc_min_importance}" "${vars.qc_min_urgency}" "${vars.qc_min_impact}"
359
+ bun "$st" daily-publish-partial "${vars.work_dir}" "${vars.run_date}"
323
360
 
324
- - id: translate-en
325
- description: "Scaffold en draft from the zh article via surfdash-pub scaffold-locale (postPath from publish result; done-no-content/none-publish runs carry no zh path and skip)"
361
+ - id: run-report
362
+ description: "Assemble the per-run report (scores+aggregates+rejected counts+step timing) from existing artifacts — news-report-gen; output-only, never throws; 0117"
326
363
  onEnter:
327
364
  - kind: shell
328
365
  options:
@@ -332,32 +369,10 @@ states:
332
369
  st="$pkg/plugins/kk/scripts/kk-workflow-stages.ts";
333
370
  [ -f "$st" ] || st="plugins/kk/scripts/kk-workflow-stages.ts";
334
371
  [ -f "$st" ] || echo "kk-workflow-stages.ts not found at $st — install or refresh the kk package (bun link in a checkout)" >&2;
335
- bun "$st" daily-translate-en "${vars.work_dir}" "${vars.run_date}" "${vars.plugins_path}"
336
- - kind: file.read.into-var
337
- options:
338
- path: ${vars.work_dir}/3-publish/${vars.run_date}_20_translate-en_zh-post-path.txt
339
- var: surfdash_post_path
340
- - kind: file.read.into-var
341
- options:
342
- path: ${vars.work_dir}/3-publish/${vars.run_date}_20_translate-en_en-post-path.txt
343
- var: surfdash_en_post_path
372
+ bun "$st" daily-run-report "${vars.work_dir}" "${vars.run_date}" "${vars.plugins_path}" "${vars.qc_min_quality}" "${vars.qc_min_importance}" "${vars.qc_min_urgency}" "${vars.qc_min_impact}"
344
373
 
345
- - id: translate-en-agent
346
- description: "Translate the en draft in place via agent.run"
347
- onEnter:
348
- - kind: agent.run
349
- options:
350
- role: scribe
351
- agent: ${vars.agent}
352
- input: |
353
- Translate the English draft post at ${vars.surfdash_en_post_path} from Chinese to English.
354
- Edit the file in place: translate the title in frontmatter and the whole markdown body to natural English. Keep frontmatter keys, dates, URLs, code, and the assets/ image reference untouched. Keep the draft: true flag.
355
- Read the surfdash translator glossary if present at the surfdash checkout root under .agents/skills/surfdash-translator/glossary.md and apply its terminology.
356
- Do not wait for operator confirmation. The file must end fully in English.
357
- expectFile: ${vars.surfdash_en_post_path}
358
-
359
- - id: translate-ja
360
- description: "Scaffold ja draft from the zh article via surfdash-pub scaffold-locale (sed-derived path as cache pre-check; plugin's draftPath is authoritative once scaffolded)"
374
+ - id: translate
375
+ description: "Locales — surfdash-pub scaffolds en/ja drafts (deterministic, plugin-owned), agent translates both, sync into the surfdash CMS"
361
376
  onEnter:
362
377
  - kind: shell
363
378
  options:
@@ -367,29 +382,26 @@ states:
367
382
  st="$pkg/plugins/kk/scripts/kk-workflow-stages.ts";
368
383
  [ -f "$st" ] || st="plugins/kk/scripts/kk-workflow-stages.ts";
369
384
  [ -f "$st" ] || echo "kk-workflow-stages.ts not found at $st — install or refresh the kk package (bun link in a checkout)" >&2;
370
- bun "$st" daily-translate-ja "${vars.work_dir}" "${vars.run_date}" "${vars.plugins_path}"
385
+ bun "$st" daily-translate-localize "${vars.work_dir}" "${vars.run_date}" "${vars.plugins_path}"
371
386
  - kind: file.read.into-var
372
387
  options:
373
- path: ${vars.work_dir}/3-publish/${vars.run_date}_22_translate-ja_ja-post-path.txt
388
+ path: ${vars.work_dir}/3-publish/${vars.run_date}_20_translate-localize_en-post-path.txt
389
+ var: surfdash_en_post_path
390
+ - kind: file.read.into-var
391
+ options:
392
+ path: ${vars.work_dir}/3-publish/${vars.run_date}_20_translate-localize_ja-post-path.txt
374
393
  var: surfdash_ja_post_path
375
-
376
- - id: translate-ja-agent
377
- description: "Translate the ja draft in place via agent.run"
378
- onEnter:
379
394
  - kind: agent.run
380
395
  options:
381
396
  role: scribe
382
397
  agent: ${vars.agent}
383
398
  input: |
384
- Translate the Japanese draft post at ${vars.surfdash_ja_post_path} from Chinese to Japanese.
385
- Edit the file in place: translate the title in frontmatter and the whole markdown body to natural Japanese. Keep frontmatter keys, dates, URLs, code, and the assets/ image reference untouched. Keep the draft: true flag.
386
- Read the surfdash translator glossary if present at the surfdash checkout root under .agents/skills/surfdash-translator/glossary.md and apply its terminology.
387
- Do not wait for operator confirmation. The file must end fully in Japanese.
388
- expectFile: ${vars.surfdash_ja_post_path}
389
-
390
- - id: translate-sync
391
- description: "Sync the zh post and its en/ja locale variants into the surfdash CMS (surfdash-pub sync operation)"
392
- onEnter:
399
+ Translate en/ja draft posts of the zh article — two independent files:
400
+ English draft: ${vars.surfdash_en_post_path}
401
+ Japanese draft: ${vars.surfdash_ja_post_path}
402
+ For each: if its path above is empty, skip that locale. Otherwise edit the file in place — translate the frontmatter title and the whole markdown body to natural English/Japanese respectively. Keep frontmatter keys, dates, URLs, code, and the assets/ image reference untouched. Set draft: false (the translated post publishes to the site) and remove any canonical: frontmatter line pointing at a different locale's URL.
403
+ Keep frontmatter valid YAML: double-quote any value containing ': '. Read the surfdash translator glossary if present at the surfdash checkout root under .agents/skills/surfdash-translator/glossary.md and apply its terminology.
404
+ Do not wait for operator confirmation. Each edited file must end fully in its target language.
393
405
  - kind: shell
394
406
  options:
395
407
  command: >-
@@ -398,7 +410,7 @@ states:
398
410
  st="$pkg/plugins/kk/scripts/kk-workflow-stages.ts";
399
411
  [ -f "$st" ] || st="plugins/kk/scripts/kk-workflow-stages.ts";
400
412
  [ -f "$st" ] || echo "kk-workflow-stages.ts not found at $st — install or refresh the kk package (bun link in a checkout)" >&2;
401
- bun "$st" daily-translate-sync "${vars.work_dir}" "${vars.run_date}" "${vars.plugins_path}" "${vars.surfdash_post_path}"
413
+ bun "$st" daily-translate-sync "${vars.work_dir}" "${vars.run_date}" "${vars.plugins_path}" "${vars.work_dir}/3-publish/${vars.run_date}_20_translate-localize_zh-post-path.txt"
402
414
 
403
415
  - id: done
404
416
  description: "Terminal — Daily AI news pipeline completed (collect → QC'd plan → article/cover/script/voice → publish/locales)"
@@ -444,17 +456,41 @@ transitions:
444
456
  options:
445
457
  command: 'test "${vars.plan_translate_enabled}" = "true"'
446
458
 
459
+ - from: quality-control-content
460
+ to: article-write
461
+ description: "Candidates passed QC, plan-translate disabled, prose enabled -> straight to article-write"
462
+ guard:
463
+ kind: shell
464
+ options:
465
+ command: 'test "${vars.plan_translate_enabled}" != "true" && test "${vars.article_write_enabled}" = "true"'
466
+
447
467
  - from: quality-control-content
448
468
  to: article
449
- description: "Candidates passed QC, plan-translate disabled -> straight to article"
469
+ description: "Prose disabled -> package the template article directly"
470
+ guard:
471
+ kind: shell
472
+ options:
473
+ command: 'test "${vars.article_write_enabled}" != "true"'
474
+
475
+ - from: plan-translate
476
+ to: article-write
477
+ description: "Plan translated and prose enabled -> write prose article from plan"
450
478
  guard:
451
479
  kind: shell
452
480
  options:
453
- command: 'test "${vars.plan_translate_enabled}" != "true"'
481
+ command: 'test "${vars.article_write_enabled}" = "true"'
454
482
 
455
483
  - from: plan-translate
456
484
  to: article
457
- description: "Plan translated -> generate article from plan"
485
+ description: "Plan translated, prose disabled -> package the template article"
486
+ guard:
487
+ kind: shell
488
+ options:
489
+ command: 'test "${vars.article_write_enabled}" != "true"'
490
+
491
+ - from: article-write
492
+ to: article
493
+ description: "Prose body written -> package article content"
458
494
  guard:
459
495
  kind: always
460
496
 
@@ -570,12 +606,16 @@ transitions:
570
606
  kind: always
571
607
 
572
608
  - from: publish
609
+ to: patch-surfdash
610
+ description: "Publish classified -> patch surfdash posts with cover + podcast cross-link"
611
+ guard:
612
+ kind: always
613
+
614
+ - from: patch-surfdash
573
615
  to: run-report
574
- description: "Publish full (all targets published) -> assemble run report first"
616
+ description: "Posts patched -> assemble run report"
575
617
  guard:
576
- kind: shell
577
- options:
578
- command: 'test "$(cat "${vars.work_dir}/3-publish/${vars.run_date}_17_publish_publish-status.txt")" = "full"'
618
+ kind: always
579
619
 
580
620
  - from: publish
581
621
  to: publish-partial
@@ -600,8 +640,8 @@ transitions:
600
640
  kind: always
601
641
 
602
642
  - from: run-report
603
- to: translate-en
604
- description: "Run report assembled after full publish -> scaffold + translate en locale"
643
+ to: translate
644
+ description: "Run report assembled after full publish -> scaffold + translate en/ja locales + sync"
605
645
  guard:
606
646
  kind: shell
607
647
  options:
@@ -615,48 +655,8 @@ transitions:
615
655
  options:
616
656
  command: 'test "$(cat "${vars.work_dir}/3-publish/${vars.run_date}_17_publish_publish-status.txt")" = "partial"'
617
657
 
618
- - from: translate-en
619
- to: translate-en-agent
620
- description: "zh post published and en draft scaffolded -> agent translates en draft in place"
621
- guard:
622
- kind: shell
623
- options:
624
- command: 'test -n "${vars.surfdash_post_path}" && test -f "${vars.surfdash_en_post_path}"'
625
-
626
- - from: translate-en
627
- to: translate-ja
628
- description: "no zh post path -> skip en locale"
629
- guard:
630
- kind: always
631
-
632
- - from: translate-en-agent
633
- to: translate-ja
634
- description: "en draft translated -> scaffold ja locale"
635
- guard:
636
- kind: always
637
-
638
- - from: translate-ja
639
- to: translate-ja-agent
640
- description: "zh post published and ja draft scaffolded -> agent translates ja draft in place"
641
- guard:
642
- kind: shell
643
- options:
644
- command: 'test -n "${vars.surfdash_post_path}" && test -f "${vars.surfdash_ja_post_path}"'
645
-
646
- - from: translate-ja
647
- to: translate-sync
648
- description: "no zh post path -> skip ja locale"
649
- guard:
650
- kind: always
651
-
652
- - from: translate-ja-agent
653
- to: translate-sync
654
- description: "ja draft translated -> sync all locales into the CMS"
655
- guard:
656
- kind: always
657
-
658
- - from: translate-sync
658
+ - from: translate
659
659
  to: done
660
- description: "zh post + locales synced into surfdash CMS -> episode complete"
660
+ description: "zh post + en/ja locales scaffolded, translated, and synced into the surfdash CMS -> episode complete"
661
661
  guard:
662
662
  kind: always
@@ -0,0 +1,53 @@
1
+ "$schema": "@gobing-ai/spur/schemas/state-machine-workflow.schema.json"
2
+ kind: state-machine
3
+ name: leftover-publish-fanout-example
4
+ description: >-
5
+ Example: fan out two leftover file-cli channels (medium-pub, wechatmp-pub),
6
+ then sequence one agent-default CMS channel (juejin-pub) as agent.run.
7
+ kk fanout does not spawn an LLM.
8
+ initialState: fanout-file-cli
9
+ terminalStates:
10
+ - done
11
+ - failed
12
+ failureStates:
13
+ - failed
14
+ vars:
15
+ contentFile: ".spur/run/content.json"
16
+ fanoutFile: ".spur/run/fanout-result.json"
17
+ juejinFile: ".spur/run/juejin-result.json"
18
+ spurBin: "spur"
19
+ states:
20
+ - id: fanout-file-cli
21
+ description: "kk fanout over leftover file-cli channels (medium + wechatmp draft)"
22
+ onEnter:
23
+ - kind: shell
24
+ options:
25
+ command: >-
26
+ kk fanout --in ${vars.contentFile}
27
+ --targets medium-pub,wechatmp-pub
28
+ --out ${vars.fanoutFile}
29
+ - id: agent-juejin
30
+ description: "Agent-default CMS channel — workflow agent.run, not kk fanout"
31
+ onEnter:
32
+ - kind: agent.run
33
+ options:
34
+ role: coder
35
+ input: |
36
+ Invoke the kk:publish skill for juejin.
37
+ Drive ~/.config/kk/browser-profiles/juejin as driver=agent.
38
+ Then `kk executor run juejin-pub --in ${vars.contentFile} --out ${vars.juejinFile}`.
39
+ Do not embed an LLM in the plugin process. Do not call kk fanout for this channel.
40
+ expectFile: ${vars.juejinFile}
41
+ - id: done
42
+ description: "Fan-out aggregate plus agent CMS Result written"
43
+ - id: failed
44
+ description: "A file-cli target or the agent CMS step failed loud"
45
+ transitions:
46
+ - from: fanout-file-cli
47
+ to: agent-juejin
48
+ guard:
49
+ kind: always
50
+ - from: agent-juejin
51
+ to: done
52
+ guard:
53
+ kind: always