@gobing-ai/knowledge-kit 0.1.11 → 0.1.13
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/index.js +2372 -1722
- package/package.json +1 -1
- package/plugins/generations/image-gen/README.md +108 -0
- package/plugins/generations/image-gen/assets/sample/cover__clean-webapp-ui.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/cover__cute.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/cover__daily-news.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/cover__editorial.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/cover__fresh.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/cover__minimalist.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/cover__photorealistic.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/cover__sketch.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/cover__technical-diagram.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/cover__vibrant.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/cover__warm.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/cover__xhs-knowledge.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/daily-news-cover__clean-webapp-ui.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/daily-news-cover__cute.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/daily-news-cover__daily-news.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/daily-news-cover__editorial.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/daily-news-cover__fresh.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/daily-news-cover__minimalist.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/daily-news-cover__photorealistic.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/daily-news-cover__sketch.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/daily-news-cover__technical-diagram.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/daily-news-cover__vibrant.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/daily-news-cover__warm.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/daily-news-cover__xhs-knowledge.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/free__clean-webapp-ui.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/free__cute.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/free__daily-news.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/free__editorial.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/free__fresh.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/free__minimalist.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/free__photorealistic.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/free__sketch.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/free__technical-diagram.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/free__vibrant.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/free__warm.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/free__xhs-knowledge.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/illustration__clean-webapp-ui.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/illustration__cute.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/illustration__daily-news.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/illustration__editorial.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/illustration__fresh.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/illustration__minimalist.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/illustration__photorealistic.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/illustration__sketch.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/illustration__technical-diagram.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/illustration__vibrant.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/illustration__warm.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/illustration__xhs-knowledge.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/xhs-card__clean-webapp-ui.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/xhs-card__cute.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/xhs-card__daily-news.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/xhs-card__editorial.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/xhs-card__fresh.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/xhs-card__minimalist.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/xhs-card__photorealistic.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/xhs-card__sketch.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/xhs-card__technical-diagram.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/xhs-card__vibrant.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/xhs-card__warm.jpg +0 -0
- package/plugins/generations/image-gen/assets/sample/xhs-card__xhs-knowledge.jpg +0 -0
- package/plugins/generations/image-gen/dist/index.js +102 -58
- package/plugins/generations/image-gen/scripts/compose-e2e-artifact.ts +5 -21
- package/plugins/generations/image-gen/scripts/gen-samples.ts +208 -0
- package/plugins/generations/image-gen/src/compose/chromium.ts +2 -3
- package/plugins/generations/image-gen/src/presets.ts +6 -3
- package/plugins/generations/image-gen/src/providers/errors.ts +16 -1
- package/plugins/generations/image-gen/src/providers/minimax.ts +46 -17
- package/plugins/ingestions/web-search/src/index.ts +1 -1
- package/plugins/kk/README.md +18 -0
- package/plugins/kk/commands/image-extract.md +1 -0
- package/plugins/kk/commands/image-generate.md +1 -0
- package/plugins/kk/commands/tell-me.md +1 -0
- package/plugins/kk/commands/workflow-run.md +7 -1
- package/plugins/kk/decisions/extract/it-topics.yaml +24 -0
- package/plugins/kk/decisions/kk-itc.yaml +6 -4
- package/plugins/kk/plugin.json +1 -1
- package/plugins/kk/publish-presets/daily-ai-voice-migration.json +146 -0
- package/plugins/kk/publish-presets/daily-ai-voice.json +15 -7
- package/plugins/kk/schedules/kk-collect.grok-bot.md.tmpl +69 -0
- package/plugins/kk/schedules/kk-daily-ai-voice3.cron.tmpl +18 -0
- package/plugins/kk/schedules/kk-daily-publish3-cn-peak.cron.tmpl +15 -5
- package/plugins/kk/schedules/kk-daily-publish3-overseas.cron.tmpl +9 -4
- package/plugins/kk/scripts/daily-scheduled-run.ts +91 -41
- package/plugins/kk/scripts/daily-stages.ts +394 -53
- package/plugins/kk/scripts/kk-workflow-stages.ts +190 -0
- package/plugins/kk/scripts/safety-artifact-check.ts +70 -28
- package/plugins/kk/scripts/voice3-publish-window.ts +202 -0
- package/plugins/kk/skills/article-adapt/SKILL.md +1 -0
- package/plugins/kk/skills/audio-authoring/SKILL.md +1 -0
- package/plugins/kk/skills/content-judge/SKILL.md +1 -0
- package/plugins/kk/skills/content-safety/SKILL.md +1 -0
- package/plugins/kk/skills/content-safety/references/platforms/podcast-salty.md +41 -0
- package/plugins/kk/skills/content-safety/references/platforms/surfdash.md +36 -0
- package/plugins/kk/skills/content-safety/references/platforms/xhs.md +39 -0
- package/plugins/kk/skills/explain-things/SKILL.md +1 -0
- package/plugins/kk/skills/image-authoring/SKILL.md +1 -0
- package/plugins/kk/skills/itc-generating/SKILL.md +1 -0
- package/plugins/kk/skills/publish/SKILL.md +1 -0
- package/plugins/kk/skills/smart-seo/SKILL.md +1 -0
- package/plugins/kk/skills/storm-research/SKILL.md +1 -0
- package/plugins/kk/skills/taste-unslop/SKILL.md +1 -0
- package/plugins/kk/skills/topic/SKILL.md +1 -0
- package/plugins/kk/skills/web-automation/SKILL.md +1 -0
- package/plugins/kk/skills/xhs-images/SKILL.md +1 -0
- package/plugins/kk/workflows/kk-collect.yaml +3 -3
- package/plugins/kk/workflows/kk-daily-ai-voice2.yaml +21 -19
- package/plugins/kk/workflows/kk-daily-ai-voice3.yaml +163 -63
- package/plugins/kk/workflows/kk-daily-publish3.yaml +82 -26
- package/plugins/kk/workflows/kk-daily-safety.yaml +39 -31
- package/plugins/kk/workflows/kk-itc-author.yaml +75 -0
- package/plugins/kk/workflows/kk-itc-publish-tail.yaml +25 -3
- package/plugins/kk/workflows/kk-itc.yaml +36 -4
- package/plugins/publishings/linkedin-pub/dist/index.js +21333 -0
- package/plugins/publishings/linkedin-pub/dist/profile-check.js +21005 -0
- package/plugins/publishings/linkedin-pub/package.json +19 -0
- package/plugins/publishings/linkedin-pub/plugin.json +12 -0
- package/plugins/publishings/linkedin-pub/src/index.ts +705 -0
- package/plugins/publishings/linkedin-pub/src/profile-check.ts +17 -0
- package/plugins/publishings/linkedin-pub/tsconfig.json +4 -0
- package/plugins/publishings/surfdash-pub/dist/index.js +53 -24
- package/plugins/publishings/surfdash-pub/src/index.ts +72 -25
- package/plugins/publishings/threads-pub/dist/index.js +7 -0
- package/plugins/publishings/threads-pub/src/index.ts +12 -0
- package/plugins/publishings/wechatmp-pub/dist/index.js +176 -32
- package/plugins/publishings/wechatmp-pub/src/flow.ts +298 -52
- package/plugins/publishings/weibo-pub/dist/index.js +100 -7
- package/plugins/publishings/weibo-pub/src/index.ts +111 -11
- package/plugins/publishings/x-pub/dist/index.js +7 -0
- package/plugins/publishings/x-pub/src/index.ts +11 -0
- package/plugins/publishings/xhs-pub/dist/index.js +164 -12
- package/plugins/publishings/xhs-pub/dist/profile-check.js +11 -1
- package/plugins/publishings/xhs-pub/src/flow.ts +194 -23
- package/plugins/publishings/xhs-pub/src/page.ts +26 -0
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 1,
|
|
3
|
+
"name": "daily-ai-voice-migration",
|
|
4
|
+
"targets": [
|
|
5
|
+
{
|
|
6
|
+
"id": "surfdash.article",
|
|
7
|
+
"plugin": "surfdash-pub",
|
|
8
|
+
"operation": "post",
|
|
9
|
+
"variant": "article",
|
|
10
|
+
"tier": 0,
|
|
11
|
+
"window": "after-generate",
|
|
12
|
+
"mode": "draft",
|
|
13
|
+
"required": true
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
"id": "podcast.episode",
|
|
17
|
+
"plugin": "podcast-pub",
|
|
18
|
+
"operation": "episode",
|
|
19
|
+
"variant": "episode",
|
|
20
|
+
"tier": 0,
|
|
21
|
+
"window": "after-generate",
|
|
22
|
+
"mode": "draft",
|
|
23
|
+
"required": true
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
"id": "wechatmp.podcast",
|
|
27
|
+
"plugin": "wechatmp-pub",
|
|
28
|
+
"operation": "播客",
|
|
29
|
+
"variant": "episode",
|
|
30
|
+
"tier": 1,
|
|
31
|
+
"window": "after-generate",
|
|
32
|
+
"mode": "off"
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
"id": "xhs.podcast",
|
|
36
|
+
"plugin": "xhs-pub",
|
|
37
|
+
"operation": "发播客",
|
|
38
|
+
"variant": "episode",
|
|
39
|
+
"tier": 1,
|
|
40
|
+
"window": "after-generate",
|
|
41
|
+
"mode": "draft"
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
"id": "wechatmp.article",
|
|
45
|
+
"plugin": "wechatmp-pub",
|
|
46
|
+
"operation": "文章",
|
|
47
|
+
"variant": "article",
|
|
48
|
+
"tier": 2,
|
|
49
|
+
"window": "after-generate",
|
|
50
|
+
"mode": "draft",
|
|
51
|
+
"options": {
|
|
52
|
+
"collection": "每日AI资讯"
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
"id": "xhs.article",
|
|
57
|
+
"plugin": "xhs-pub",
|
|
58
|
+
"operation": "写长文",
|
|
59
|
+
"variant": "article",
|
|
60
|
+
"tier": 2,
|
|
61
|
+
"window": "after-generate",
|
|
62
|
+
"mode": "draft"
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
"id": "xhs.cards",
|
|
66
|
+
"plugin": "xhs-pub",
|
|
67
|
+
"operation": "上传图文",
|
|
68
|
+
"variant": "cards",
|
|
69
|
+
"tier": 3,
|
|
70
|
+
"window": "after-generate",
|
|
71
|
+
"mode": "off"
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
"id": "weibo.article",
|
|
75
|
+
"plugin": "weibo-pub",
|
|
76
|
+
"operation": "article",
|
|
77
|
+
"variant": "article",
|
|
78
|
+
"tier": 2,
|
|
79
|
+
"window": "cn-peak",
|
|
80
|
+
"mode": "draft"
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
"id": "x.article",
|
|
84
|
+
"plugin": "x-pub",
|
|
85
|
+
"operation": "article",
|
|
86
|
+
"variant": "article",
|
|
87
|
+
"tier": 2,
|
|
88
|
+
"window": "cn-peak",
|
|
89
|
+
"mode": "off"
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
"id": "x.post",
|
|
93
|
+
"plugin": "x-pub",
|
|
94
|
+
"operation": "post",
|
|
95
|
+
"variant": "social:x",
|
|
96
|
+
"tier": 3,
|
|
97
|
+
"window": "overseas-rss",
|
|
98
|
+
"mode": "dummy"
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
"id": "weibo.post",
|
|
102
|
+
"plugin": "weibo-pub",
|
|
103
|
+
"operation": "post",
|
|
104
|
+
"variant": "social:weibo",
|
|
105
|
+
"tier": 3,
|
|
106
|
+
"window": "overseas-rss",
|
|
107
|
+
"mode": "dummy"
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
"id": "threads.post",
|
|
111
|
+
"plugin": "threads-pub",
|
|
112
|
+
"operation": "post",
|
|
113
|
+
"variant": "social:threads",
|
|
114
|
+
"tier": 3,
|
|
115
|
+
"window": "overseas-rss",
|
|
116
|
+
"mode": "dummy"
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
"id": "linkedin.post",
|
|
120
|
+
"plugin": "linkedin-pub",
|
|
121
|
+
"operation": "post",
|
|
122
|
+
"variant": "social:linkedin",
|
|
123
|
+
"tier": 3,
|
|
124
|
+
"window": "overseas-rss",
|
|
125
|
+
"mode": "dummy"
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
"id": "shipinhao.cards",
|
|
129
|
+
"plugin": "shipinhao-pub",
|
|
130
|
+
"operation": "图文",
|
|
131
|
+
"variant": "cards",
|
|
132
|
+
"tier": 3,
|
|
133
|
+
"window": "overseas-rss",
|
|
134
|
+
"mode": "off"
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
"id": "threads.images",
|
|
138
|
+
"plugin": "threads-pub",
|
|
139
|
+
"operation": "post-images",
|
|
140
|
+
"variant": "cards",
|
|
141
|
+
"tier": 3,
|
|
142
|
+
"window": "overseas-rss",
|
|
143
|
+
"mode": "off"
|
|
144
|
+
}
|
|
145
|
+
]
|
|
146
|
+
}
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"variant": "episode",
|
|
27
27
|
"tier": 1,
|
|
28
28
|
"window": "after-generate",
|
|
29
|
-
"mode": "
|
|
29
|
+
"mode": "off"
|
|
30
30
|
},
|
|
31
31
|
{
|
|
32
32
|
"plugin": "xhs-pub",
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
"variant": "article",
|
|
54
54
|
"tier": 2,
|
|
55
55
|
"window": "after-generate",
|
|
56
|
-
"mode": "
|
|
56
|
+
"mode": "draft"
|
|
57
57
|
},
|
|
58
58
|
{
|
|
59
59
|
"plugin": "xhs-pub",
|
|
@@ -61,7 +61,7 @@
|
|
|
61
61
|
"variant": "cards",
|
|
62
62
|
"tier": 3,
|
|
63
63
|
"window": "after-generate",
|
|
64
|
-
"mode": "
|
|
64
|
+
"mode": "draft"
|
|
65
65
|
},
|
|
66
66
|
{
|
|
67
67
|
"plugin": "weibo-pub",
|
|
@@ -77,7 +77,7 @@
|
|
|
77
77
|
"variant": "article",
|
|
78
78
|
"tier": 2,
|
|
79
79
|
"window": "cn-peak",
|
|
80
|
-
"mode": "
|
|
80
|
+
"mode": "off"
|
|
81
81
|
},
|
|
82
82
|
{
|
|
83
83
|
"plugin": "x-pub",
|
|
@@ -85,7 +85,7 @@
|
|
|
85
85
|
"variant": "social:x",
|
|
86
86
|
"tier": 3,
|
|
87
87
|
"window": "overseas-rss",
|
|
88
|
-
"mode": "
|
|
88
|
+
"mode": "dummy"
|
|
89
89
|
},
|
|
90
90
|
{
|
|
91
91
|
"plugin": "weibo-pub",
|
|
@@ -93,7 +93,7 @@
|
|
|
93
93
|
"variant": "social:weibo",
|
|
94
94
|
"tier": 3,
|
|
95
95
|
"window": "overseas-rss",
|
|
96
|
-
"mode": "
|
|
96
|
+
"mode": "dummy"
|
|
97
97
|
},
|
|
98
98
|
{
|
|
99
99
|
"plugin": "threads-pub",
|
|
@@ -101,7 +101,15 @@
|
|
|
101
101
|
"variant": "social:threads",
|
|
102
102
|
"tier": 3,
|
|
103
103
|
"window": "overseas-rss",
|
|
104
|
-
"mode": "
|
|
104
|
+
"mode": "dummy"
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
"plugin": "linkedin-pub",
|
|
108
|
+
"operation": "post",
|
|
109
|
+
"variant": "social:linkedin",
|
|
110
|
+
"tier": 3,
|
|
111
|
+
"window": "overseas-rss",
|
|
112
|
+
"mode": "dummy"
|
|
105
113
|
},
|
|
106
114
|
{
|
|
107
115
|
"plugin": "shipinhao-pub",
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# kk-collect — Grok Bot cloud routine
|
|
2
|
+
|
|
3
|
+
Rendered by `kk schedule render kk-collect --platform grok-bot --bot {{bot}} [--tz {{tz}}] [--cron {{cron}}]`;
|
|
4
|
+
kk never creates the routine. **Operator action:** paste this definition into the Grok Bot's routine
|
|
5
|
+
editor (https://docs.x.ai/grok-bot/skills-routines-and-automations) and create it there.
|
|
6
|
+
|
|
7
|
+
The cloud boundary is ADR-044 (`docs/00_ADR.md`): `kk.db` never leaves the Mac — this routine runs
|
|
8
|
+
store-free, browser-free work only, and pushes its output to the `kk-cloud-sync` branch for the Mac
|
|
9
|
+
to import.
|
|
10
|
+
|
|
11
|
+
## Owner Bot
|
|
12
|
+
|
|
13
|
+
{{bot}}
|
|
14
|
+
|
|
15
|
+
## Schedule
|
|
16
|
+
|
|
17
|
+
`{{cron}}` in `{{tz}}` (the routine's schedule must match this expression and timezone).
|
|
18
|
+
|
|
19
|
+
## Inputs
|
|
20
|
+
|
|
21
|
+
- The Bot needs `kk` and `spur` (sp-bot-bootstrap) in its checkout, plus the three source plugins'
|
|
22
|
+
credentials (`aihot`, `last30days`, `horizon`) provided as Bot secrets.
|
|
23
|
+
- Push access to the `kk-cloud-sync` branch (the Bot's GitHub connector).
|
|
24
|
+
- The fan-in source list below is copied from `plugins/kk/workflows/kk-collect.yaml:116-121` —
|
|
25
|
+
update the rendered routine whenever that file's source list changes (drift hazard).
|
|
26
|
+
|
|
27
|
+
## Steps
|
|
28
|
+
|
|
29
|
+
1. `stamp="$(date -u +%Y%m%dT%H%MZ)"` (UTC, `YYYYMMDDTHHMMZ` — the kk-collect stamp format).
|
|
30
|
+
2. `kk stage collect-prepare "$stamp" 10 "AI news" 6` — the store-free prefix: writes only
|
|
31
|
+
`.works/kk-collect/<stamp>` and `.spur/runs/kk-collect/*`, touching no database.
|
|
32
|
+
3. Fan-in the three sources (no `kk store` — the output file IS the artifact):
|
|
33
|
+
```bash
|
|
34
|
+
work_dir="$(cat .spur/runs/kk-collect/work-dir.txt)"
|
|
35
|
+
kk executor fan-in \
|
|
36
|
+
--source "aihot-ingest:${work_dir}/10-ingest/source.json" \
|
|
37
|
+
--source "last30days-ingest:${work_dir}/10-ingest/last30days.json" \
|
|
38
|
+
--source "horizon-ingest:${work_dir}/10-ingest/horizon.json" \
|
|
39
|
+
--source-timeout-override "horizon-ingest:2700000" \
|
|
40
|
+
--out "sync/kk-collect/$stamp.json"
|
|
41
|
+
```
|
|
42
|
+
4. Commit `sync/kk-collect/$stamp.json` and push it to the `kk-cloud-sync` branch.
|
|
43
|
+
|
|
44
|
+
## Expected result
|
|
45
|
+
|
|
46
|
+
`sync/kk-collect/<stamp>.json` on `kk-cloud-sync`, a blended `Doc[]` from the three sources, with
|
|
47
|
+
`<stamp>` equal to the run's UTC minute stamp.
|
|
48
|
+
|
|
49
|
+
## Approval boundary
|
|
50
|
+
|
|
51
|
+
Collect only — the routine never runs `kk store`, `kk store label`, a generator or a publisher, and
|
|
52
|
+
it never installs anything itself; creating the routine in the Grok Bot is an explicit operator
|
|
53
|
+
action. Publishing stays Mac-local under ADR-022's live-publish consent gate.
|
|
54
|
+
|
|
55
|
+
## Missing / stale (ADR-044)
|
|
56
|
+
|
|
57
|
+
| Situation | Behavior |
|
|
58
|
+
| --------- | -------- |
|
|
59
|
+
| Inputs or credentials missing at run time | print `no-content: <reason>` and exit with no side effects — in particular, no empty artifact is committed |
|
|
60
|
+
| Artifact older than 26 h when the Mac imports | the Mac's `kk store ingest` ignores it (logged) |
|
|
61
|
+
| Same artifact seen again | imported at most once — idempotent by the `cloud-<stamp>` run id |
|
|
62
|
+
|
|
63
|
+
## Mac import
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
git fetch origin kk-cloud-sync
|
|
67
|
+
git show origin/kk-cloud-sync:sync/kk-collect/<stamp>.json > /tmp/kk-collect-cloud.json
|
|
68
|
+
kk store ingest --run cloud-<stamp> --in /tmp/kk-collect-cloud.json
|
|
69
|
+
```
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# kk-daily-ai-voice3 — shadow generation run (task 0334 R1/R6).
|
|
2
|
+
#
|
|
3
|
+
# 04:30 America/Los_Angeles, the same cadence as the voice2 daily run it shadows. The entry is
|
|
4
|
+
# defined in the zone the machine already runs in, so it needs no DST adjustment.
|
|
5
|
+
#
|
|
6
|
+
# Shadow posture is baked into the launch: `auto_publish` stays false, so this entry only
|
|
7
|
+
# prepares, researches and generates — it publishes NOTHING on its own. The nested publish3
|
|
8
|
+
# window runs only when an operator launch flips `publish_window` away from `after-generate`
|
|
9
|
+
# (rehearsal flags in docs/design/kk-daily-ai-voice3.md). The workspace namespace stays
|
|
10
|
+
# kk-daily-ai-voice2 (voice3 prepares under it) until the operator's cutover changes it.
|
|
11
|
+
#
|
|
12
|
+
# Rendered by `kk schedule render kk-daily-ai-voice3 --platform cron --repo <checkout>`;
|
|
13
|
+
# kk never edits the operator's crontab. MERGE, never replace:
|
|
14
|
+
#
|
|
15
|
+
# crontab -l > /tmp/kk-voice3.cron 2>/dev/null || :
|
|
16
|
+
# kk schedule render kk-daily-ai-voice3 --platform cron --repo "$PWD" >> /tmp/kk-voice3.cron
|
|
17
|
+
# crontab /tmp/kk-voice3.cron
|
|
18
|
+
30 4 * * * cd {{repo}} && mkdir -p .works/kk-daily-ai-voice3 && PATH="{{home}}/.bun/bin:/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin" TZ=America/Los_Angeles spur workflow run plugins/kk/workflows/kk-daily-ai-voice3.yaml --vars '{"auto_publish":"false"}' >> {{repo}}/.works/kk-daily-ai-voice3/generation.log 2>&1
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# kk-daily-publish3-cn-peak — domestic live window (
|
|
1
|
+
# kk-daily-publish3-cn-peak — domestic live window (tasks 0323 R5, 0334 R1-R3).
|
|
2
2
|
#
|
|
3
3
|
# Fires at 17:00 local because the audience window is 09:00 Asia/Shanghai and launchd/cron
|
|
4
4
|
# intervals follow the MACHINE's zone; the first node (`publish-matrix-wait-until 09:00
|
|
@@ -6,7 +6,17 @@
|
|
|
6
6
|
# so the entry never needs editing twice a year.
|
|
7
7
|
#
|
|
8
8
|
# `live_channels` is baked in: this installed line IS the operator's ADR-022 consent for a live
|
|
9
|
-
# send. Nothing in the workflow or the preset can produce `live` on its own.
|
|
9
|
+
# send. Nothing in the workflow or the preset can produce `live` on its own. The window is
|
|
10
|
+
# consent-scoped to tokens with a cn-peak row (weibo-pub). Every live launch
|
|
11
|
+
# stops at the `send-confirm` gate and waits for the operator's manual resume; the entry never
|
|
12
|
+
# delivers unattended.
|
|
13
|
+
#
|
|
14
|
+
# The launch goes through plugins/kk/scripts/voice3-publish-window.ts (task 0334): a crontab
|
|
15
|
+
# command ends at the first UNESCAPED percent sign, so inline `date +%F` shell silently truncates
|
|
16
|
+
# the entry — the launcher owns the LA date math, resolves the GENERATION bundle from the
|
|
17
|
+
# effective works root (never the publish3 output directory), refuses a missing/mismatched
|
|
18
|
+
# bundle, validates the token list against the preset's cn-peak rows, and only then execs spur.
|
|
19
|
+
# The rehearsal pins the shipped default preset; change it at cutover.
|
|
10
20
|
#
|
|
11
21
|
# Rendered by `kk schedule render kk-daily-publish3-cn-peak --platform cron --repo <checkout>`;
|
|
12
22
|
# kk never edits the operator's crontab. MERGE, never replace:
|
|
@@ -15,6 +25,6 @@
|
|
|
15
25
|
# kk schedule render kk-daily-publish3-cn-peak --platform cron --repo "$PWD" >> /tmp/kk-cn-peak.cron
|
|
16
26
|
# crontab /tmp/kk-cn-peak.cron
|
|
17
27
|
#
|
|
18
|
-
# `run_date` is computed at tick time in America/Los_Angeles: a run that starts
|
|
19
|
-
# still "today" for the day dir the 04:30 generation wrote.
|
|
20
|
-
0 17 * * * cd {{repo}} && mkdir -p .works/kk-daily-publish3 && PATH="{{home}}/.bun/bin:/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin" TZ=America/Los_Angeles
|
|
28
|
+
# `run_date` is computed at tick time in America/Los_Angeles by the launcher: a run that starts
|
|
29
|
+
# at 17:00 PDT is still "today" for the day dir the 04:30 generation wrote.
|
|
30
|
+
0 17 * * * cd {{repo}} && mkdir -p .works/kk-daily-publish3 && PATH="{{home}}/.bun/bin:/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin" TZ=America/Los_Angeles bun {{repo}}/plugins/kk/scripts/voice3-publish-window.ts --window cn-peak --preset daily-ai-voice --live-channels weibo-pub >> {{repo}}/.works/kk-daily-publish3/cn-peak.log 2>&1
|
|
@@ -1,17 +1,22 @@
|
|
|
1
|
-
# kk-daily-publish3-overseas — overseas window behind the podcast RSS gate (
|
|
1
|
+
# kk-daily-publish3-overseas — overseas window behind the podcast RSS gate (tasks 0323 R5, 0334 R1-R2).
|
|
2
2
|
#
|
|
3
3
|
# 07:00 America/Los_Angeles, which needs no DST adjustment: the entry is defined in the zone the
|
|
4
4
|
# machine already runs in. The gated date is the PREVIOUS day, because the observed episodes land
|
|
5
|
-
# 13:43–15:22 PDT (after this tick) —
|
|
5
|
+
# 13:43–15:22 PDT (after this tick) — the launcher derives yesterday's LA date for `run_date`.
|
|
6
6
|
#
|
|
7
7
|
# The gate decides whether anything publishes: a miss cancels the overseas targets and runs
|
|
8
|
-
# `diagnose` + the tier-0-only repair. This line carries no
|
|
8
|
+
# `diagnose` + the tier-0-only repair. This line carries no live consent; the overseas channels
|
|
9
9
|
# in the shipped preset are `draft`, so a live overseas post stays an operator launch.
|
|
10
10
|
#
|
|
11
|
+
# plugins/kk/scripts/voice3-publish-window.ts (task 0334) owns the date math because a crontab
|
|
12
|
+
# command ends at the first UNESCAPED percent sign — the old inline `date -v-1d +%Y%m%d` shell
|
|
13
|
+
# truncated silently. The launcher resolves the GENERATION bundle (voice2 namespace, effective
|
|
14
|
+
# works root) and refuses a missing/mismatched bundle before any spur process starts.
|
|
15
|
+
#
|
|
11
16
|
# Rendered by `kk schedule render kk-daily-publish3-overseas --platform cron --repo <checkout>`;
|
|
12
17
|
# kk never edits the operator's crontab. MERGE, never replace:
|
|
13
18
|
#
|
|
14
19
|
# crontab -l > /tmp/kk-overseas.cron 2>/dev/null || :
|
|
15
20
|
# kk schedule render kk-daily-publish3-overseas --platform cron --repo "$PWD" >> /tmp/kk-overseas.cron
|
|
16
21
|
# crontab /tmp/kk-overseas.cron
|
|
17
|
-
0 7 * * * cd {{repo}} && mkdir -p .works/kk-daily-publish3 && PATH="{{home}}/.bun/bin:/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin" TZ=America/Los_Angeles
|
|
22
|
+
0 7 * * * cd {{repo}} && mkdir -p .works/kk-daily-publish3 && PATH="{{home}}/.bun/bin:/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin" TZ=America/Los_Angeles bun {{repo}}/plugins/kk/scripts/voice3-publish-window.ts --window overseas-rss >> {{repo}}/.works/kk-daily-publish3/overseas.log 2>&1
|
|
@@ -16,6 +16,9 @@ const { values } = parseArgs({
|
|
|
16
16
|
'retry-agent': { type: 'string', default: 'claude' },
|
|
17
17
|
'required-channels': { type: 'string', default: 'wechat,locales,cms-resync' },
|
|
18
18
|
'wechat-live': { type: 'boolean', default: false },
|
|
19
|
+
workflow: { type: 'string', default: 'kk-daily-ai-voice2' },
|
|
20
|
+
window: { type: 'string' },
|
|
21
|
+
'publish-preset': { type: 'string' },
|
|
19
22
|
},
|
|
20
23
|
});
|
|
21
24
|
const timeoutMs = Number(values['timeout-ms']);
|
|
@@ -31,15 +34,28 @@ const workDir = join(resolve(values['works-dir'] ?? join(repo, '.works')), 'kk-d
|
|
|
31
34
|
const receiptPath = resolve(values.receipt ?? join(workDir, 'schedule-receipt.json'));
|
|
32
35
|
const startedAt = now.toISOString();
|
|
33
36
|
mkdirSync(dirname(receiptPath), { recursive: true });
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
37
|
+
// voice3 shares the voice2 workspace (F08); only the vars and the publish seam differ.
|
|
38
|
+
const isVoice3 = values.workflow === 'kk-daily-ai-voice3';
|
|
39
|
+
const vars = isVoice3
|
|
40
|
+
? {
|
|
41
|
+
auto_publish: 'true',
|
|
42
|
+
...(values['publish-preset'] !== undefined ? { publish_preset: values['publish-preset'] } : {}),
|
|
43
|
+
...(values.window ? { window: values.window } : {}),
|
|
44
|
+
skip_review: 'true',
|
|
45
|
+
agent: values.agent,
|
|
46
|
+
agent_retry: values['retry-agent'],
|
|
47
|
+
work_dir: workDir,
|
|
48
|
+
run_date: stamp,
|
|
49
|
+
}
|
|
50
|
+
: {
|
|
51
|
+
publish_enabled: 'true',
|
|
52
|
+
skip_review: 'true',
|
|
53
|
+
agent: values.agent,
|
|
54
|
+
agent_retry: values['retry-agent'],
|
|
55
|
+
wechat_live: values['wechat-live'] === true ? 'true' : 'false',
|
|
56
|
+
work_dir: workDir,
|
|
57
|
+
run_date: stamp,
|
|
58
|
+
};
|
|
43
59
|
writeFileSync(receiptPath, JSON.stringify({ runId, startedAt, status: 'running', workDir }, null, 2));
|
|
44
60
|
let interrupted = false;
|
|
45
61
|
let timedOut = false;
|
|
@@ -51,7 +67,7 @@ const child = spawn(
|
|
|
51
67
|
'--no-logo',
|
|
52
68
|
'workflow',
|
|
53
69
|
'run',
|
|
54
|
-
|
|
70
|
+
`plugins/kk/workflows/${values.workflow}.yaml`,
|
|
55
71
|
'--run-id',
|
|
56
72
|
runId,
|
|
57
73
|
'--vars',
|
|
@@ -135,7 +151,9 @@ if (child.pid !== undefined && (timedOut || interrupted || exitCode !== 0)) {
|
|
|
135
151
|
await Bun.sleep(100);
|
|
136
152
|
}
|
|
137
153
|
const workflowStatus = timedOut ? 'timed-out' : interrupted ? 'interrupted' : exitCode === 0 ? 'done' : 'failed';
|
|
138
|
-
const primaryPublishStatus =
|
|
154
|
+
const primaryPublishStatus = isVoice3
|
|
155
|
+
? readOptional(join(workDir, '4-publish', 'publish-status.after-generate.txt'))
|
|
156
|
+
: readOptional(join(workDir, '31-publish', `${stamp}_17_publish_publish-status.txt`));
|
|
139
157
|
const runSummary = readOptional(join(workDir, 'run-report.summary.txt'));
|
|
140
158
|
const cleanup: { command: string; exitCode: number | null }[] = [];
|
|
141
159
|
let reservationRecovery: { status: string; reason: string; released?: number } = {
|
|
@@ -168,21 +186,23 @@ if (workflowStatus !== 'done' || runSummary?.startsWith('no-content:')) {
|
|
|
168
186
|
run?: { runId?: string; workflowName?: string; status?: string; startedAt?: string };
|
|
169
187
|
events?: { kind?: string; node?: string; status?: string }[];
|
|
170
188
|
};
|
|
171
|
-
const sendNodes =
|
|
172
|
-
'publish-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
189
|
+
const sendNodes = isVoice3
|
|
190
|
+
? new Set(['publish', 'send', 'send-retry', 'repair', 'send-confirm'])
|
|
191
|
+
: new Set([
|
|
192
|
+
'publish-surfdash',
|
|
193
|
+
'publish-podcast',
|
|
194
|
+
'xhs-publish',
|
|
195
|
+
'wechat-publish',
|
|
196
|
+
'translate-localize',
|
|
197
|
+
'translate',
|
|
198
|
+
'translate-retry',
|
|
199
|
+
'translate-sync',
|
|
200
|
+
'publish-classify',
|
|
201
|
+
]);
|
|
182
202
|
const validTrace =
|
|
183
203
|
trace.status === 0 &&
|
|
184
204
|
parsed.run?.runId === runId &&
|
|
185
|
-
parsed.run?.workflowName ===
|
|
205
|
+
parsed.run?.workflowName === values.workflow &&
|
|
186
206
|
parsed.run?.status === (workflowStatus === 'done' ? 'done' : 'failed') &&
|
|
187
207
|
Date.parse(parsed.run.startedAt ?? '') >= Date.parse(startedAt) - 1000 &&
|
|
188
208
|
Date.parse(parsed.run.startedAt ?? '') <= Date.now() &&
|
|
@@ -227,7 +247,7 @@ if (workflowStatus !== 'done' || runSummary?.startsWith('no-content:')) {
|
|
|
227
247
|
// potentially aired story. Keep the reservation and the original failure visible.
|
|
228
248
|
}
|
|
229
249
|
}
|
|
230
|
-
const ledger = spawnSync('kk', ['ledger', 'sync', '--workflow',
|
|
250
|
+
const ledger = spawnSync('kk', ['ledger', 'sync', '--workflow', values.workflow, '--work-dir', workDir], {
|
|
231
251
|
cwd: repo,
|
|
232
252
|
encoding: 'utf-8',
|
|
233
253
|
timeout: 20000,
|
|
@@ -244,33 +264,63 @@ const requiredChannels = values['required-channels']
|
|
|
244
264
|
.split(',')
|
|
245
265
|
.map((channel) => channel.trim())
|
|
246
266
|
.filter(Boolean);
|
|
247
|
-
let channelCompleteness: { channel: string; state: string; detail?: string }[] =
|
|
267
|
+
let channelCompleteness: { channel: string; state: string; detail?: string; required?: boolean; dummy?: boolean }[] =
|
|
268
|
+
[];
|
|
248
269
|
try {
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
row
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
270
|
+
if (isVoice3) {
|
|
271
|
+
const outcome = JSON.parse(
|
|
272
|
+
readOptional(join(workDir, '4-publish', 'outcome.after-generate.json')) ?? 'null',
|
|
273
|
+
) as { rows?: unknown } | null;
|
|
274
|
+
if (Array.isArray(outcome?.rows)) {
|
|
275
|
+
channelCompleteness = outcome.rows.flatMap(
|
|
276
|
+
(row): { channel: string; state: string; required: boolean; dummy: boolean }[] => {
|
|
277
|
+
if (row === null || typeof row !== 'object') return [];
|
|
278
|
+
const r = row as { id?: unknown; required?: unknown; dummy?: unknown; status?: unknown };
|
|
279
|
+
if (typeof r.id !== 'string' || typeof r.status !== 'string') return [];
|
|
280
|
+
return [
|
|
281
|
+
{
|
|
282
|
+
channel: r.id,
|
|
283
|
+
state: r.status === 'succeeded' ? 'done' : r.status,
|
|
284
|
+
required: r.required === true,
|
|
285
|
+
dummy: r.dummy === true,
|
|
286
|
+
},
|
|
287
|
+
];
|
|
288
|
+
},
|
|
289
|
+
);
|
|
290
|
+
}
|
|
291
|
+
} else {
|
|
292
|
+
const parsed = JSON.parse(
|
|
293
|
+
readOptional(join(workDir, '31-publish', `${stamp}_17_publish_completeness.json`)) ?? 'null',
|
|
294
|
+
) as { rows?: unknown } | null;
|
|
295
|
+
if (Array.isArray(parsed?.rows)) {
|
|
296
|
+
channelCompleteness = parsed.rows.filter(
|
|
297
|
+
(row): row is { channel: string; state: string; detail?: string } =>
|
|
298
|
+
row !== null &&
|
|
299
|
+
typeof row === 'object' &&
|
|
300
|
+
typeof row.channel === 'string' &&
|
|
301
|
+
typeof row.state === 'string',
|
|
302
|
+
);
|
|
303
|
+
}
|
|
260
304
|
}
|
|
261
305
|
} catch {}
|
|
262
|
-
const missingRequiredChannels =
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
306
|
+
const missingRequiredChannels = isVoice3
|
|
307
|
+
? channelCompleteness
|
|
308
|
+
.filter((row) => row.required === true && row.dummy !== true)
|
|
309
|
+
.filter((row) => row.state !== 'done')
|
|
310
|
+
.map((row) => row.channel)
|
|
311
|
+
: requiredChannels.filter((channel) => {
|
|
312
|
+
const rows = channelCompleteness.filter((row) => row.channel === channel);
|
|
313
|
+
return rows.length !== 1 || rows[0]?.state !== 'done';
|
|
314
|
+
});
|
|
266
315
|
// A terminal green workflow can mean "no content" or failed delivery. Make that observable to
|
|
267
316
|
// the scheduler instead of equating the workflow's process exit with a published edition.
|
|
317
|
+
// A voice3 outcome classified 'full' already proves every non-dummy row succeeded (0326 R2).
|
|
268
318
|
const status =
|
|
269
319
|
workflowStatus !== 'done'
|
|
270
320
|
? workflowStatus
|
|
271
321
|
: runSummary?.startsWith('no-content:')
|
|
272
322
|
? 'no-content'
|
|
273
|
-
: primaryPublishStatus === 'full' && missingRequiredChannels.length
|
|
323
|
+
: primaryPublishStatus === 'full' && !(!isVoice3 && missingRequiredChannels.length > 0)
|
|
274
324
|
? 'done'
|
|
275
325
|
: 'incomplete';
|
|
276
326
|
const receipt = {
|