@gobing-ai/knowledge-kit 0.1.14 → 0.1.15
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 +796 -176
- package/package.json +1 -1
- package/plugins/generations/content-gen/dist/index.js +2 -2
- package/plugins/generations/core-facts-gen/dist/index.js +2 -2
- package/plugins/generations/daily-article-gen/dist/index.js +2 -2
- package/plugins/generations/dailynews-gen/dist/index.js +72 -9
- package/plugins/generations/dailynews-gen/src/index.ts +23 -1
- package/plugins/generations/dailynews-gen/src/script-plan.ts +103 -5
- package/plugins/generations/episode-plan-gen/dist/index.js +2 -2
- package/plugins/generations/gemini-tts/dist/index.js +2 -2
- package/plugins/generations/image-gen/dist/index.js +2 -2
- package/plugins/generations/news-report-gen/dist/index.js +2 -2
- package/plugins/generations/voice-gen/dist/index.js +2 -2
- package/plugins/generations/voxcpm-tts/dist/index.js +2 -2
- package/plugins/ingestions/aihot-ingest/dist/index.js +2 -2
- package/plugins/ingestions/horizon-ingest/dist/index.js +2 -2
- package/plugins/ingestions/last30days-ingest/dist/index.js +2 -2
- package/plugins/ingestions/web-search/dist/index.js +2 -2
- package/plugins/kk/plugin.json +1 -1
- package/plugins/kk/scripts/daily-scheduled-run.ts +4 -0
- package/plugins/kk/scripts/daily-stages.ts +476 -12
- package/plugins/kk/scripts/kk-workflow-stages.ts +20 -4
- package/plugins/kk/skills/content-judge/SKILL.md +5 -4
- package/plugins/kk/skills/content-judge/references/rubrics.md +14 -0
- package/plugins/kk/skills/news-editorial/SKILL.md +122 -0
- package/plugins/kk/skills/news-editorial/references/selection.md +47 -0
- package/plugins/kk/skills/news-editorial/references/style-contract.zh.md +99 -0
- package/plugins/kk/skills/publish/SKILL.md +3 -3
- package/plugins/kk/skills/web-automation/SKILL.md +229 -77
- package/plugins/kk/skills/web-automation/references/browser-launch.md +127 -36
- package/plugins/kk/workflows/kk-daily-ai-voice2.yaml +4 -6
- package/plugins/kk/workflows/kk-daily-ai-voice3.yaml +183 -222
- package/plugins/kk/workflows/kk-daily-publish3.yaml +16 -8
- package/plugins/publishings/bilibili-pub/dist/index.js +5 -3
- package/plugins/publishings/bilibili-pub/dist/profile-check.js +3 -1
- package/plugins/publishings/cnblogs-pub/dist/index.js +5 -3
- package/plugins/publishings/cnblogs-pub/dist/profile-check.js +3 -1
- package/plugins/publishings/csdn-pub/dist/index.js +5 -3
- package/plugins/publishings/csdn-pub/dist/profile-check.js +5 -3
- package/plugins/publishings/emdash-pub/dist/index.js +2 -2
- package/plugins/publishings/infoq-pub/dist/index.js +5 -3
- package/plugins/publishings/infoq-pub/dist/profile-check.js +5 -3
- package/plugins/publishings/jike-pub/dist/index.js +5 -3
- package/plugins/publishings/jike-pub/dist/profile-check.js +5 -3
- package/plugins/publishings/juejin-pub/dist/index.js +5 -3
- package/plugins/publishings/juejin-pub/dist/profile-check.js +5 -3
- package/plugins/publishings/linkedin-pub/dist/index.js +5 -3
- package/plugins/publishings/linkedin-pub/dist/profile-check.js +5 -3
- package/plugins/publishings/medium-pub/dist/index.js +2 -2
- package/plugins/publishings/podcast-pub/dist/index.js +147 -4
- package/plugins/publishings/podcast-pub/src/index.ts +71 -2
- package/plugins/publishings/podcast-pub/src/map.ts +3 -0
- package/plugins/publishings/podcast-pub/src/transcript.ts +195 -0
- package/plugins/publishings/qiita-pub/dist/index.js +2 -2
- package/plugins/publishings/shipinhao-pub/dist/index.js +5 -3
- package/plugins/publishings/shipinhao-pub/dist/profile-check.js +3 -1
- package/plugins/publishings/sspai-pub/dist/index.js +5 -3
- package/plugins/publishings/sspai-pub/dist/profile-check.js +3 -1
- package/plugins/publishings/substack-pub/dist/index.js +5 -3
- package/plugins/publishings/substack-pub/dist/profile-check.js +5 -3
- package/plugins/publishings/surfdash-pub/dist/index.js +2 -2
- package/plugins/publishings/threads-pub/dist/index.js +2 -2
- package/plugins/publishings/wechatmp-pub/dist/index.js +52 -33
- package/plugins/publishings/wechatmp-pub/dist/profile-check.js +5 -3
- package/plugins/publishings/wechatmp-pub/src/flow.ts +70 -33
- package/plugins/publishings/weibo-pub/dist/index.js +5 -3
- package/plugins/publishings/weibo-pub/dist/profile-check.js +5 -3
- package/plugins/publishings/x-pub/dist/index.js +5 -3
- package/plugins/publishings/x-pub/dist/profile-check.js +5 -3
- package/plugins/publishings/xhs-pub/dist/index.js +5 -3
- package/plugins/publishings/xhs-pub/dist/profile-check.js +5 -3
- package/plugins/publishings/xiaoyuzhou-pub/dist/index.js +5 -3
- package/plugins/publishings/xiaoyuzhou-pub/dist/profile-check.js +3 -1
- package/plugins/publishings/zenn-pub/dist/index.js +2 -2
- package/plugins/kk/scripts/daily-voice-style.zh.md +0 -70
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: news-editorial
|
|
3
|
+
description: >-
|
|
4
|
+
Use the news-editorial skill for the editorial judgement of a daily news episode — "curate today's
|
|
5
|
+
news pool", "write the episode script plan", "fix the script plan against these validator errors",
|
|
6
|
+
"apply the daily news style contract". Owns selection and topic boundary, ordering, the balance of
|
|
7
|
+
news, opinion and technical detail, and the style contract. Modes: curate | write | write --fix.
|
|
8
|
+
requires: [cli:kk, local-fs]
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# news-editorial — daily news editorial policy (curate | write | write --fix)
|
|
12
|
+
|
|
13
|
+
## Purpose
|
|
14
|
+
|
|
15
|
+
This skill holds every editorial judgement for a daily news episode: which items to keep, in what order, how
|
|
16
|
+
much opinion and technical detail each gets, and how the spoken words read. Everything deterministic stays
|
|
17
|
+
in code and is **out of scope**: collection and store extraction (`kk store extract`, `decisions/extract/*.yaml`),
|
|
18
|
+
score thresholds (`daily-qc-content`), the VoiceScript builder (fixed greeting and sign-off), validators,
|
|
19
|
+
duration gates, TTS, images and publishing (ADR-045).
|
|
20
|
+
|
|
21
|
+
A workflow reaches this skill through the run snapshot `<work_dir>/20-editorial/news-editorial/` (written by
|
|
22
|
+
`kk stage daily-script-style`). Read files relative to the `SKILL.md` you were pointed at; do not rely on skill
|
|
23
|
+
discovery.
|
|
24
|
+
|
|
25
|
+
## Invocation contract
|
|
26
|
+
|
|
27
|
+
`<mode> [--fix <errors.json>] --in <input> --out <output>`. The calling prompt supplies the paths. Write only
|
|
28
|
+
`--out`, as a single valid file (JSON with no comments or trailing commas). Never edit the input.
|
|
29
|
+
|
|
30
|
+
| Mode | Input → output | Status |
|
|
31
|
+
|---|---|---|
|
|
32
|
+
| `curate` | QC candidates `Doc[]` → kept translated `Doc[]` (`--out-plan`) + exclusions (`--out-excluded`) | Wired (`curate`, policy: `references/selection.md`) |
|
|
33
|
+
| `curate --fix` | QC candidates `Doc[]` + curate validator errors (`--fix`) → corrected plan + exclusions | Wired (`curate-fix`) |
|
|
34
|
+
| `write` | translated plan `Doc[]` + exclusions (`--excluded`) → master script plan JSON | Wired (`script-write`) |
|
|
35
|
+
| `write --fix` | plan `Doc[]` + previous script plan + validator errors → corrected master script plan | Wired (`script-write-fix`) |
|
|
36
|
+
|
|
37
|
+
## Shared rules (every mode)
|
|
38
|
+
|
|
39
|
+
Read `references/style-contract.zh.md` first. Its prose sets the column's identity and the balance of news,
|
|
40
|
+
opinion and technical detail. Its fenced `json` block holds the caps and banned phrases that the dailynews-gen
|
|
41
|
+
validator enforces mechanically, so violating them means the plan is rejected.
|
|
42
|
+
|
|
43
|
+
1. **News first.** Every item tells the listener who (company, lab, team) did what (released, open-sourced,
|
|
44
|
+
raised, sued, disclosed) and when. Commentary is restrained and anchored to that item; technical detail is
|
|
45
|
+
only the one or two sentences needed to understand it.
|
|
46
|
+
2. **Topic boundary (选题边界).** Never retell an item whose mainline is politics or diplomacy, trade controls,
|
|
47
|
+
military affairs, public-policy disputes or social public events, whatever nickname it travels under. Exclude
|
|
48
|
+
it with a Chinese reason. In-scope industry and institutional news is reported normally.
|
|
49
|
+
3. **Fact discipline.** Every fact comes from that item's own plan content. Do not invent anything or borrow
|
|
50
|
+
from other items. Never inflate numbers or actors. Attribute a quote only to its original speaker. Keep
|
|
51
|
+
hedges (据报道 / 称 / 承诺). If the material is thin, write less.
|
|
52
|
+
4. **Copy discipline.** Use reader-facing spoken Chinese. Do not use scaffold labels (可做角度 / 背景 /
|
|
53
|
+
潜在影响) or hedge labels (读者宜另行核实 / 仍待验证), use 「」 for quotes, and never add a greeting,
|
|
54
|
+
sign-off or AI-production footer. The builder adds those.
|
|
55
|
+
|
|
56
|
+
## Mode: write
|
|
57
|
+
|
|
58
|
+
Read the curated plan `Doc[]` (`--in`) and the curate exclusions (`--excluded`). For each doc in `--in`, write:
|
|
59
|
+
|
|
60
|
+
- `lead`: one spoken bridge into the item (≤80 chars). It is not the title and not a rhetorical question.
|
|
61
|
+
- `insight`: 2–4 sentences (≤380 chars) anchored to the doc's named actors, saying why it matters or what to watch. Never restate the doc's facts, numbers or phrasing (the listener has just heard them), give no generic advice or methodology, and add no new facts. The cap is a ceiling, not a target.
|
|
62
|
+
- `card`: optional per-item card slot `{ "copy": "≤12字标题", "points": ["要点1", "要点2"], "subject": "English visual scene" }` (2–4 points).
|
|
63
|
+
|
|
64
|
+
At the episode level, write:
|
|
65
|
+
|
|
66
|
+
- `intro` (≤150 chars): names the top two or three concrete in-scope developments.
|
|
67
|
+
- `outro` (≤150 chars): a short close tying the items together.
|
|
68
|
+
- `excluded`: copy the array from `--excluded` (`21-plan/<date>_03_curate_excluded.json`) verbatim so the script plan records every dropped candidate with its Chinese reason.
|
|
69
|
+
- `cover` (≤240 chars): one concrete visual scene in English for the lead item (objects, settings, symbols, metaphor; no text, letters, numbers, logos, flags, or recognizable people).
|
|
70
|
+
- `cards`: `{ "title": "≤20字总标题", "body": "中文导语段落 + 3-5个话题标签" }` for the episode card series.
|
|
71
|
+
- `social`: `{ "short": "≤140字 X/Threads 短帖", "long": "≤500字 微博/LinkedIn 长帖" }` (plain text, no markdown headings, no emoji spam, grounded in the plan).
|
|
72
|
+
|
|
73
|
+
Output:
|
|
74
|
+
|
|
75
|
+
```json
|
|
76
|
+
{
|
|
77
|
+
"version": 1,
|
|
78
|
+
"intro": "…",
|
|
79
|
+
"outro": "…",
|
|
80
|
+
"cover": "…",
|
|
81
|
+
"cards": { "title": "…", "body": "…" },
|
|
82
|
+
"social": { "short": "…", "long": "…" },
|
|
83
|
+
"items": [
|
|
84
|
+
{
|
|
85
|
+
"id": "…",
|
|
86
|
+
"lead": "…",
|
|
87
|
+
"insight": "…",
|
|
88
|
+
"card": { "copy": "…", "points": ["…", "…"], "subject": "…" }
|
|
89
|
+
}
|
|
90
|
+
],
|
|
91
|
+
"excluded": [{ "id": "…", "reason": "…" }]
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Every doc id in `--in` appears in `items`, and `excluded` carries the curate exclusions; no id may appear in both.
|
|
96
|
+
|
|
97
|
+
## Mode: write --fix
|
|
98
|
+
|
|
99
|
+
Inputs: the plan `Doc[]`, the previous script plan, and `--fix <errors.json>` (`[{itemId, rule}]` from the
|
|
100
|
+
validator). Change only what the errors name and copy everything else unchanged. Fix by rule:
|
|
101
|
+
|
|
102
|
+
| Rule | Fix |
|
|
103
|
+
|---|---|
|
|
104
|
+
| `cap:<field>` | Shorten that field (`intro`, `outro`, `lead`, `insight`, `cover`, `cardCopy`, `cardTitle`, `socialShort`, `socialLong`) below its cap in the contract. Cut opinion, not the actor |
|
|
105
|
+
| `banned:<phrase>` | Rephrase without the phrase (applies to spoken, card and social fields alike) |
|
|
106
|
+
| `redundant-insight` | Rewrite the insight as commentary; drop the restated facts |
|
|
107
|
+
| `duplicate-insight` | Make each insight specific to its own item |
|
|
108
|
+
| `missing-item` / `unknown-id` / `conflict-id` | Make `items` match `--in` and `excluded` match `--excluded` with no overlap |
|
|
109
|
+
| `schema` / `missing-plan` | Write the full master plan per mode `write` |
|
|
110
|
+
|
|
111
|
+
## Mode: curate / curate --fix
|
|
112
|
+
|
|
113
|
+
See `references/selection.md`. Reads QC candidates (`--in`) and writes two JSON files:
|
|
114
|
+
1. `--out-plan` (`21-plan/<date>_03_plan_plan.json`): bare `Doc[]` of **kept** items only, in editorial order (lead first), with `title`, `body` and `metadata.brief` adapted into spoken simplified Chinese.
|
|
115
|
+
2. `--out-excluded` (`21-plan/<date>_03_curate_excluded.json`): `[{"id":"<Doc.id>","reason":"<具体中文原因>"}]` for every dropped candidate (`[]` when none dropped). Every candidate id must land in **exactly one** of the two files.
|
|
116
|
+
|
|
117
|
+
With `--fix <errors.json>` (`missing-plan`, `invalid-json`, `unknown-id`, `missing-item`, `conflict-id`, `empty-plan`), repair the partition so every candidate id is accounted for exactly once and at least one in-scope item is kept.
|
|
118
|
+
|
|
119
|
+
## References
|
|
120
|
+
|
|
121
|
+
- `references/style-contract.zh.md`: the column's style contract and machine block (caps, banned).
|
|
122
|
+
- `references/selection.md`: curate policy (boundary, ordering, depth budget, translation).
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# Curate policy
|
|
2
|
+
|
|
3
|
+
`curate` turns the QC candidates into the episode plan. The deterministic gates have already run before it:
|
|
4
|
+
store thresholds (`decisions/extract/ai-news.yaml`), the QC score floors and the minimum item count
|
|
5
|
+
(`daily-qc-content`). Curate adds judgement, not new numeric thresholds.
|
|
6
|
+
|
|
7
|
+
## Keep or drop
|
|
8
|
+
|
|
9
|
+
- Drop items that cross the topic boundary (SKILL.md shared rule 2) and give a specific Chinese reason.
|
|
10
|
+
- Drop low-value items (pure PR fluff, minor point-release changelogs with no architectural or developer impact, thin stubs with no verifiable actor/action) and give a specific Chinese reason.
|
|
11
|
+
- Merge near-duplicates (the same event from two sources) into the item with the richer facts; drop the duplicate id into `--out-excluded` with a Chinese reason (e.g., `与另一条候选同属一事,已合并至信息更完整条目`). Never let the same story be spoken twice.
|
|
12
|
+
- Keep everything else that has a concrete actor and action. An opinion thread or tutorial with no news event
|
|
13
|
+
stays only when the day is thin, and goes after the news items.
|
|
14
|
+
|
|
15
|
+
## Output invariant (two files)
|
|
16
|
+
|
|
17
|
+
`curate` writes two JSON files:
|
|
18
|
+
1. `--out-plan` (`21-plan/<date>_03_plan_plan.json`): a bare `Doc[]` array containing **only the kept docs**, ordered with the day's lead news item first, with `title`, `body` and `metadata.brief` adapted into spoken simplified Chinese.
|
|
19
|
+
2. `--out-excluded` (`21-plan/<date>_03_curate_excluded.json`): `[{ "id": "<Doc.id>", "reason": "<具体中文原因>" }]` for every dropped candidate (`[]` when nothing is dropped).
|
|
20
|
+
|
|
21
|
+
Every candidate `id` from `21-plan/<date>_04_quality-control-content_candidates.json` (`metadata.docs`) must land in **exactly one** of the two files — never both (`conflict-id`), never neither (`missing-item`), and with no invented ids (`unknown-id`).
|
|
22
|
+
|
|
23
|
+
## Order and balance
|
|
24
|
+
|
|
25
|
+
1. Lead with the day's most consequential concrete news (urgency × impact), not the most technical item.
|
|
26
|
+
2. Mix categories (industry, research, tools) instead of running three reddit technical threads in a row.
|
|
27
|
+
3. Episode length comes from item count and complete facts, not from long commentary. The style contract
|
|
28
|
+
gives the per-driver character rates. If kept items cannot reach the floor, keep more in-scope items rather
|
|
29
|
+
than padding.
|
|
30
|
+
|
|
31
|
+
## Spoken Chinese adaptation
|
|
32
|
+
|
|
33
|
+
For kept items (especially those marked `needsTranslation`), adapt `title`, `body` and `metadata.brief` into spoken simplified Chinese:
|
|
34
|
+
|
|
35
|
+
- Keep every fact, number, name, quote and hedge. This is a full-length spoken adaptation, not a summary;
|
|
36
|
+
the body is about 0.6–0.7× the source.
|
|
37
|
+
- Shrink generic background or concept explainers to one sentence.
|
|
38
|
+
- Titles read as news. Keep product and model names and body URLs verbatim, and use 「」 for quotes.
|
|
39
|
+
- Keep `id`, `sourceUri`, `mediaType` and `metadata` as they are.
|
|
40
|
+
|
|
41
|
+
## Mode: curate --fix
|
|
42
|
+
|
|
43
|
+
When `daily-curate-check` writes `21-plan/<date>_03_curate_errors.json` (`[{ "itemId": "...", "rule": "..." }]`), inspect the rules and rewrite both `--out-plan` and `--out-excluded`:
|
|
44
|
+
- `missing-plan` / `invalid-json` / `empty-plan`: write a valid non-empty `Doc[]` to `--out-plan` and valid `[{id, reason}]` to `--out-excluded`.
|
|
45
|
+
- `missing-item`: add the missing candidate id either to `--out-plan` (translated) or to `--out-excluded` (with a Chinese reason).
|
|
46
|
+
- `conflict-id`: remove the id from one of the two files so it appears in only one.
|
|
47
|
+
- `unknown-id`: remove any id that does not exist in `candidates.json`'s `metadata.docs`.
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# 每日AI乱炖 · 主持风格契约(zh)
|
|
2
|
+
|
|
3
|
+
`kk-daily-ai-voice` 的每一句口播都受这份契约约束(F613 R1;0189 R1 改定位;2026-10-08 改名;ADR-045 起归
|
|
4
|
+
`kk:news-editorial` 技能所有)。`write` 模式与 `dailynews-gen` 的校验器读取同一份机器可读块,因此提示词与
|
|
5
|
+
校验永远一致。
|
|
6
|
+
|
|
7
|
+
## 栏目定位
|
|
8
|
+
|
|
9
|
+
「每日AI乱炖」是「咸话咸说」下的 AI 技术分享栏目,完整名称「咸话咸说之每日AI乱炖」,副题
|
|
10
|
+
「工具、论文与实践随聊」。栏目名突出当天,不是把节目名当成说话人。口播是开发者视角的 AI
|
|
11
|
+
行业动态与技术分享:先让听众及时知道谁、在何时、发布/宣布/披露了什么,再给克制的点评。
|
|
12
|
+
不以任何代称、绰号或「闲聊」包装政治、外交、军事、公共政策争议或社会公共事件主线的内容——
|
|
13
|
+
这类条目在选题/QC 阶段就应被排除(0189 R2);选题边界之内的行业动态与机构信息照常播报。身份与
|
|
14
|
+
经历必须真实:只讲真实做过的实测与实践。制作方式由栏目设置说明,口播、正文和 show notes
|
|
15
|
+
不要再附「文字由 AI 辅助整理,音频为 AI 合成配音」或「本期音频为 AI 合成配音」。
|
|
16
|
+
|
|
17
|
+
## 人设与语域
|
|
18
|
+
|
|
19
|
+
- 口语化普通话,第一人称「我」,像一位冷静、有依据的 AI 技术分享主播。
|
|
20
|
+
- 平实、克制、不炒作:不夸大单一消息的意义,不使用惊叹式渲染或营销话术。
|
|
21
|
+
- 面向普通听众说明「这件事为什么重要」或「怎么用得上」,而不是堆砌术语。
|
|
22
|
+
|
|
23
|
+
## 新闻性、点评与技术细节的平衡(2026-11-08)
|
|
24
|
+
|
|
25
|
+
2026-11-02 起执笔模型换成 codex-sol 后,成稿漂向「主题化议论 + 泛化建议 + 底层细节」,新闻性
|
|
26
|
+
明显下降。三者按以下比例取舍:
|
|
27
|
+
|
|
28
|
+
- 新闻性优先:每一条都要让听众听清主体(公司/机构/团队)、动作(发布、开源、融资、诉讼、
|
|
29
|
+
披露……)和时间;导语与桥段点名具体主体和产品,不把当天新闻改写成抽象议题。
|
|
30
|
+
- 点评克制:每条点评约占该条口播的四分之一到三分之一,锚定这一条的具体主体与事实,说清
|
|
31
|
+
「为什么重要」或「接下来看什么」即可;不写脱离新闻的方法论、选型指南、采购清单或「我的判断
|
|
32
|
+
标准是……我建议……」式说教,不连用多个「我会/我建议/我倾向」。
|
|
33
|
+
- 技术细节点到为止:只保留听懂这条新闻所需的一两句机制说明;通用概念(如什么是 HTTP 请求头、
|
|
34
|
+
KV cache)不展开科普,参数、基准、实现细节择其最关键的一两个。
|
|
35
|
+
- 不重复:同一事实在一条里只讲一次。
|
|
36
|
+
|
|
37
|
+
## 固定开场与收尾
|
|
38
|
+
|
|
39
|
+
开场问候与收尾致谢由 builder 固定输出,计划文本只填充两者之间的内容,节目身份永不漂移:
|
|
40
|
+
|
|
41
|
+
- 开场:`大家好,今天是<日期>。这里是由<主持人>为你带来的咸话咸说之每日AI乱炖。`
|
|
42
|
+
- 收尾:`感谢您的收听,我是<主持人>,祝您拥有充实高效的一天,我们下期节目不见不散!`
|
|
43
|
+
|
|
44
|
+
## 段落角色
|
|
45
|
+
|
|
46
|
+
- `intro`:开场导语,点名今天最重要的两三条动态(谁、做了什么),接在固定问候之后,不超过 150 字;不写「今天我想聊聊怎么判断……」式的议题清单。
|
|
47
|
+
- `lead`:一句话口语桥段,引出下一个主题的【标题】;只做铺垫,不得复述标题本身,不用设问句把新闻改写成抽象问题,不超过 80 字。
|
|
48
|
+
- `insight`:只基于这一条自身可核事实的点评(2–4 句),说清这一条对行业或开发者的意义、或接下来值得关注的节点;不得挪用其他条目的话题,不超过 380 字(这是上限不是目标,常规 150–280 字)。听众刚听完这一条的事实叙述,insight 是点评不是复读:不得复述正文已讲过的事实、数字或成串措辞(最多点到一两个关键词);也不得脱离这条新闻泛泛讲方法论或给通用建议。时长契约:全片按 15–20 分钟口播设计,时长靠覆盖更多条目和完整的事实叙述撑起,不靠拉长点评。字数按配音驱动折算:gemini ≈3.3 字/秒(正文约 4300–5800 字);Voicebox robin-news ≈6.3 字/秒(正文约 5700–7600 字,或增加条目数)。
|
|
49
|
+
- `outro`:简短收束语,接在固定致谢之前,不超过 150 字。
|
|
50
|
+
- `cover`:头版英文具象视觉场景,不超过 240 字符,不含文字、数字、商标、旗帜或可辨识真人。
|
|
51
|
+
- `cards`:小红书图文笔记总标题 `title`(不超过 20 字)与导语 `body`,单条卡片标题 `card.copy`(不超过 12 字)、2–4 条短要点 `card.points`、英文画面 `card.subject`。
|
|
52
|
+
- `social`:面向 X / Threads 的短帖 `short`(不超过 140 字)与面向微博 / LinkedIn 的长帖 `long`(不超过 500 字)。
|
|
53
|
+
|
|
54
|
+
## 机器可读契约
|
|
55
|
+
|
|
56
|
+
`caps` 是各字段的字数上限;`banned` 是任何计划字段都不得出现的短语——包括旧模板的全部罐头
|
|
57
|
+
点评、旧模板的 首先/接着/最后 开头、0133 的研究脚手架标签与对冲语(校验规则
|
|
58
|
+
`banned:<短语>`),以及 0189 R4 退役的旧栏目名(「每日 AI 资讯」「AI科技漫谈」
|
|
59
|
+
「AI Daily Briefing」):任何路径都不得让旧新闻定位复活。
|
|
60
|
+
|
|
61
|
+
```json
|
|
62
|
+
{
|
|
63
|
+
"caps": {
|
|
64
|
+
"intro": 150,
|
|
65
|
+
"outro": 150,
|
|
66
|
+
"lead": 80,
|
|
67
|
+
"insight": 380,
|
|
68
|
+
"cover": 240,
|
|
69
|
+
"cardCopy": 12,
|
|
70
|
+
"cardTitle": 20,
|
|
71
|
+
"socialShort": 140,
|
|
72
|
+
"socialLong": 500
|
|
73
|
+
},
|
|
74
|
+
"banned": [
|
|
75
|
+
"在各种技术光环背后,正是这样专注而不知疲倦的底层攻坚者,为今天整个大模型生态奠定了最坚实的技术基石。",
|
|
76
|
+
"这其实释放了一个非常明确的信号:AI竞争的下半场,已经不再只是单纯拼模型参数,更是电力、能源和全栈工业基础设施的硬核较量。",
|
|
77
|
+
"真正被重新定义的,是硬件层承担的安全与算力责任:把能力做进硅片层更可靠、也更难绕过,但生态锁定的代价需要一起算进去。",
|
|
78
|
+
"我个人觉得,这次最大的看点是内容创作门槛的再次降低。不过正如团队提到的,如何平衡创作自由与防止低质内容泛滥,会是整个行业接下来最值得观察的关键考题。",
|
|
79
|
+
"这项进展反映出资本与产业界正在加速形成合力,后续实际业务场景的落地效果非常值得我们持续跟进。",
|
|
80
|
+
"这项新动态反映出技术演进正在进一步提速,对相关领域的实际影响也非常值得我们持续关注。",
|
|
81
|
+
"首先",
|
|
82
|
+
"接着",
|
|
83
|
+
"最后",
|
|
84
|
+
"可做角度",
|
|
85
|
+
"背景",
|
|
86
|
+
"潜在影响",
|
|
87
|
+
"读者宜另行核实",
|
|
88
|
+
"仍待验证",
|
|
89
|
+
"每日AI资讯",
|
|
90
|
+
"每日 AI 资讯",
|
|
91
|
+
"今日AI科技漫谈",
|
|
92
|
+
"AI科技漫谈",
|
|
93
|
+
"AI Daily Briefing",
|
|
94
|
+
"我是咸话咸说",
|
|
95
|
+
"音频为 AI 合成配音",
|
|
96
|
+
"The audio in this episode is AI-synthesized"
|
|
97
|
+
]
|
|
98
|
+
}
|
|
99
|
+
```
|
|
@@ -25,7 +25,7 @@ not add a `kk publish` noun.
|
|
|
25
25
|
| medium | `medium-pub` | `file-cli` (token API) | `kk executor run medium-pub --in <content.json> --out <result.json>` |
|
|
26
26
|
| wechatmp | `wechatmp-pub` | `file-cli` (`draft/add`) | `kk executor run wechatmp-pub` (default operation `draft`) |
|
|
27
27
|
| x post | `x-pub` | `file-cli` (`POST /2/tweets`) | `kk executor run x-pub` (`options.operation` omitted / `post`) |
|
|
28
|
-
| x article | `x-pub` | `browser` / `script` | `kk executor run x-pub --in <content.json> --out <result.json>` (`options.operation: article`); a missing or expired profile refuses (`ok: false`, naming `
|
|
28
|
+
| x article | `x-pub` | `browser` / `script` | `kk executor run x-pub --in <content.json> --out <result.json>` (`options.operation: article`); a missing or expired profile refuses (`ok: false`, naming `kk bot login x`) before any window opens |
|
|
29
29
|
| juejin | `juejin-pub` | `browser` / `script` | `kk executor run juejin-pub --in <content.json> --out <result.json>` |
|
|
30
30
|
| infoq | `infoq-pub` | `browser` / `script` | `kk executor run infoq-pub --in <content.json> --out <result.json>` |
|
|
31
31
|
| substack | `substack-pub` | `browser` / `script` | `kk executor run substack-pub --in <content.json> --out <result.json>` (needs `SUBSTACK_PUBLICATION_URL`) |
|
|
@@ -43,8 +43,8 @@ credentials. Before the first script-driver run (and after any session expiry),
|
|
|
43
43
|
headed login, then verify reuse read-only:
|
|
44
44
|
|
|
45
45
|
```bash
|
|
46
|
-
|
|
47
|
-
bun plugins/publishings/xhs-pub/src/profile-check.ts check # headless; exit 0 = session verified
|
|
46
|
+
kk bot login xhs # headed; sign in once in the window (adapter-verified)
|
|
47
|
+
bun plugins/publishings/xhs-pub/src/profile-check.ts check # headless; exit 0 = session verified (underlying probe)
|
|
48
48
|
```
|
|
49
49
|
|
|
50
50
|
`check` never signs in — with no saved profile it refuses (exit 1) instead of reporting success.
|
|
@@ -1,101 +1,253 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: web-automation
|
|
3
3
|
description: >-
|
|
4
|
-
Discover, enhance, and automate web tasks with Playwright
|
|
5
|
-
over CDP
|
|
4
|
+
Discover, enhance, and automate web tasks with Playwright, kk bot, or agent-browser
|
|
5
|
+
over CDP — "walk this console and record evidence", "figure out this site's
|
|
6
6
|
UI", "automate this web flow", "reuse my cached login on <channel>", "check
|
|
7
|
-
whether my session on <channel> is still valid", "
|
|
8
|
-
selectors", or when a spur workflow `agent.run` step targets the
|
|
9
|
-
web-automation skill.
|
|
10
|
-
plugins; orchestration is
|
|
11
|
-
transition-flow (see docs/design/web-automation-engine.md).
|
|
12
|
-
requires: [cli:spur, local-fs]
|
|
7
|
+
whether my session on <channel> is still valid", "run a browser collection plan",
|
|
8
|
+
"fix this channel's selectors", or when a spur workflow `agent.run` step targets the
|
|
9
|
+
web-automation skill. Coordinates with the kk bot session lifecycle and collection
|
|
10
|
+
substrate. Owns method and evidence; transport stays in kk plugins; orchestration is
|
|
11
|
+
a @gobing-ai/ts-dual-workflow-engine transition-flow (see docs/design/web-automation-engine.md).
|
|
12
|
+
requires: [cli:kk, cli:spur, local-fs]
|
|
13
13
|
---
|
|
14
14
|
|
|
15
15
|
# web-automation — discover, enhance, automate with a real browser
|
|
16
16
|
|
|
17
17
|
## Purpose
|
|
18
18
|
|
|
19
|
-
Three
|
|
20
|
-
cached login profile**, record **evidence** (screenshots, DOM signals, JSON),
|
|
19
|
+
Three operational lenses over one unified browser automation architecture: drive a **real Chromium on the named bot's
|
|
20
|
+
cached login profile**, record **verifiable evidence** (screenshots, DOM signals, JSON responses),
|
|
21
21
|
and never report an outcome that was not observed.
|
|
22
22
|
|
|
23
|
-
| Operation | When | Output |
|
|
24
|
-
| --- | --- | --- |
|
|
25
|
-
| **discover** |
|
|
26
|
-
| **enhance** |
|
|
27
|
-
| **automate** |
|
|
23
|
+
| Operation | When | Tier & Substrate | Output |
|
|
24
|
+
| --- | --- | --- | --- |
|
|
25
|
+
| **discover** | New/changed site; "figure out this UI", inspect selectors/shadow roots | **Tier 3** (`kk bot open` + CDP/Playwright) | Evidence dir (`frames/`, `signals.json`) + drift list (`docs/design/<channel>-ui-discovery.md`) |
|
|
26
|
+
| **enhance** | Selectors drifted; a plugin or collection plan fails on a live console | **Tier 2 / 3** (`kk bot exec`, probe script) | Root-cause fix in plugin + updated discovery doc in same commit |
|
|
27
|
+
| **automate** | Repeatable web task (data collection, form fill, draft save, health audit) | **Tier 1 / 2** (`kk bot exec`, `runBotCollection`) | Bounded Result + captured artifacts (draft-safe by default, fail-closed) |
|
|
28
28
|
|
|
29
|
-
This skill owns **method**. It does not own transport (that
|
|
30
|
-
|
|
31
|
-
`spur workflow` runs `@gobing-ai/ts-dual-workflow-engine`; see
|
|
32
|
-
`docs/design/web-automation-engine.md` for the layering and the YAML).
|
|
29
|
+
This skill owns **method**. It does not own transport (that belongs to `kind: publish` / `ingestion` plugins) or orchestration
|
|
30
|
+
(that is the engine — `spur workflow` running `@gobing-ai/ts-dual-workflow-engine`; see `docs/design/web-automation-engine.md`).
|
|
33
31
|
|
|
34
|
-
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## The 3-Tier Web Automation Model
|
|
35
|
+
|
|
36
|
+
To keep workflows clean, safe, and robust against anti-bot friction, all web automation tasks follow a strict 3-tier hierarchy:
|
|
37
|
+
|
|
38
|
+
```text
|
|
39
|
+
┌──────────────────────────────────────────────────────────────────────────────┐
|
|
40
|
+
│ Tier 1: Session & Probe Gateway (kk bot CLI) │
|
|
41
|
+
│ • Profile inventory & expiry estimates: kk bot list │
|
|
42
|
+
│ • Headed login & transactional staging: kk bot login <channel> │
|
|
43
|
+
│ • Single-request authenticated queries: kk bot exec <name> <url> │
|
|
44
|
+
│ • Local credential wipe: kk bot logout <name> │
|
|
45
|
+
└──────────────────────────────────────────────────────────────────────────────┘
|
|
46
|
+
│
|
|
47
|
+
▼
|
|
48
|
+
┌──────────────────────────────────────────────────────────────────────────────┐
|
|
49
|
+
│ Tier 2: Declarative Headless Automation (kk bot plan / bot-collection) │
|
|
50
|
+
│ • Canonical CLI runner: kk bot plan <bot> <plan.json> [-o <dir>] [-m <sec>]│
|
|
51
|
+
│ • Bounded multi-step JSON plans (navigate, wait, click, scroll, extract) │
|
|
52
|
+
│ • Declarative network response captures (responses: [{pathPrefix}]) │
|
|
53
|
+
│ • Single profile lease + single headless context launch │
|
|
54
|
+
│ • Fail-closed errors: authentication (auth walls) vs empty vs browser │
|
|
55
|
+
│ • Programmatic runner: runBotCollection in @gobing-ai/publish-harness │
|
|
56
|
+
│ • Low-level probe tool: bun packages/publish-harness/scripts/bot-collection-probe.ts │
|
|
57
|
+
└──────────────────────────────────────────────────────────────────────────────┘
|
|
58
|
+
│
|
|
59
|
+
▼
|
|
60
|
+
┌──────────────────────────────────────────────────────────────────────────────┐
|
|
61
|
+
│ Tier 3: Deep Interactive Automation (Playwright / CDP under withProfileLease)│
|
|
62
|
+
│ • Headed visual inspection & interaction: kk bot open <name> [--login] │
|
|
63
|
+
│ • File uploads (setInputFiles) & shadow-root coordinate clicks via CDP │
|
|
64
|
+
│ • Live DOM accessibility dumps & interactive selector reverse-engineering │
|
|
65
|
+
│ • Strict lease enforcement: withProfileLease prevents concurrent corruption │
|
|
66
|
+
└──────────────────────────────────────────────────────────────────────────────┘
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
---
|
|
70
|
+
|
|
71
|
+
## Tier 1: Session & Profile Lifecycle (`kk bot`)
|
|
72
|
+
|
|
73
|
+
All browser sessions live under the fixed default root:
|
|
74
|
+
|
|
75
|
+
```text
|
|
76
|
+
~/.config/kk/browser-profiles/<name> # persistent profiles (xhs, infoq, juejin, substack, x, wechatmp, etc.)
|
|
77
|
+
~/.config/kk/browser-transactions/ # crash-safe staging and atomic promotion for logins
|
|
78
|
+
~/.config/kk/browser-leases/ # shared lease locks preventing concurrent profile corruption
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### CLI Command Reference
|
|
35
82
|
|
|
36
|
-
|
|
37
|
-
|
|
83
|
+
| Command | Purpose | Input / Options | Behavior |
|
|
84
|
+
| --- | --- | --- | --- |
|
|
85
|
+
| `kk bot list` | Inventory | None | Prints tab-separated columns: `name`, `cached`, `defaultUrl`, `identity`, `lastLogin`, `expires`. Browser-free. |
|
|
86
|
+
| `kk bot login <channel>` / `<url> --save <name>` | Fresh authentication | Channel name or URL (`--save <name>`) | Opens headed in isolated staging; saves adapter-verified evidence or waits for operator confirmation; promotes atomically. |
|
|
87
|
+
| `kk bot open <name> [--login]` | Inspection | Bot name (`--login` optional) | Opens saved default URL headed until operator closes browser. `--login` re-authenticates first. |
|
|
88
|
+
| `kk bot logout <name>` | Wipe credentials | Bot name | Deletes local profile directory behind shared lease. Idempotent. |
|
|
89
|
+
| `kk bot exec <name> <url> [opts]` | Authenticated HTTP | `-X`, `-H`, `-d`, `-o`, `-i`, `-L`, `-f`, `-m` | One headless persistent launch; sends request with profile's cached cookies; writes body as raw bytes. |
|
|
90
|
+
| `kk bot plan <name> <plan.json> [opts]` | Declarative Collection | `-o, --output <dir>`, `-m, --max-time <sec>` | Headless persistent launch under shared lease; runs declarative plan steps and captures; writes artifacts or prints JSON result. |
|
|
38
91
|
|
|
92
|
+
### Session Preflight & Health Check
|
|
93
|
+
|
|
94
|
+
Before triggering automated runs, perform a fast probe. Age-guessing timestamps is banned — probe, don't predict:
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
# 1. Check local profile inventory
|
|
98
|
+
kk bot list
|
|
99
|
+
|
|
100
|
+
# 2. Lightweight authenticated query probe (returns status + headers)
|
|
101
|
+
kk bot exec <channel> <console-url> -i -m 15 -o /tmp/probe.txt
|
|
102
|
+
|
|
103
|
+
# 3. If expired or unauthenticated (HTTP 401/403 or redirect to login):
|
|
104
|
+
kk bot login <channel>
|
|
39
105
|
```
|
|
40
|
-
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
## Tier 2: Declarative Headless Automation (`bot-collection`)
|
|
110
|
+
|
|
111
|
+
For data collection, scraping, site audits, and structured form workflows, **do not write ad-hoc Playwright scripts**.
|
|
112
|
+
Use the declarative `@gobing-ai/publish-harness/bot-collection` substrate:
|
|
113
|
+
|
|
114
|
+
```ts
|
|
115
|
+
import { runBotCollection } from '@gobing-ai/publish-harness/bot-collection';
|
|
116
|
+
|
|
117
|
+
const result = await runBotCollection('wechatmp', {
|
|
118
|
+
steps: [
|
|
119
|
+
{ id: 'nav-home', kind: 'navigate', url: 'https://mp.weixin.qq.com/' },
|
|
120
|
+
{ id: 'wait-dashboard', kind: 'wait', selector: '.weui-desktop-layout', timeoutMs: 15_000 },
|
|
121
|
+
{ id: 'extract-stats', kind: 'extract', selector: '.weui-desktop-mass__item', format: 'text' },
|
|
122
|
+
],
|
|
123
|
+
responses: [
|
|
124
|
+
{ id: 'appmsg-list', pathPrefix: '/cgi-bin/appmsg' },
|
|
125
|
+
],
|
|
126
|
+
timeoutMs: 30_000,
|
|
127
|
+
});
|
|
41
128
|
```
|
|
42
129
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
130
|
+
### Plan Grammar (`BotCollectionPlan`)
|
|
131
|
+
|
|
132
|
+
A plan is a frozen JSON object with `steps[]`, optional `responses[]` captures, and an optional whole-run `timeoutMs`:
|
|
133
|
+
|
|
134
|
+
- **`navigate`**: `{ id, kind: 'navigate', url, waitUntil?: 'load'|'domcontentloaded'|'networkidle'|'commit' }`
|
|
135
|
+
- **`wait`**: `{ id, kind: 'wait', selector?, timeoutMs? }`
|
|
136
|
+
- **`click`**: `{ id, kind: 'click', selector, timeoutMs? }`
|
|
137
|
+
- **`scroll`**: `{ id, kind: 'scroll', deltaY, selector?, timeoutMs? }`
|
|
138
|
+
- **`extract`**: `{ id, kind: 'extract', selector, format: 'text'|'html'|'count', timeoutMs? }`
|
|
139
|
+
- **`request`**: `{ id, kind: 'request', url, method?: 'GET'|'POST', headers?, data? }`
|
|
140
|
+
- **`responses`**: `[{ id, origin?, pathPrefix, optional?: boolean }]`
|
|
47
141
|
|
|
48
|
-
|
|
142
|
+
### Fail-Closed Integrity Rules
|
|
143
|
+
|
|
144
|
+
- **`authentication`**: Fails immediately when an explicit 401/403 occurs on a request, navigation, or required response, or when the final navigation URL path matches `/login|signin|sign-in|auth|sso/i`. Action: alert operator to run `kk bot login <channel>`.
|
|
145
|
+
- **`empty`**: Fails immediately when a declared non-optional capture receives no response, or an `extract`/`request` step yields an empty body. Prevents client-side rendered SPA shells from masquerading as a successful quiet run.
|
|
146
|
+
- **`browser`**: Transport faults, timeouts, navigation drops, and DOM exceptions.
|
|
147
|
+
|
|
148
|
+
### Running Plans via CLI (`kk bot plan`)
|
|
149
|
+
|
|
150
|
+
Execute a collection plan directly from the terminal or a workflow script:
|
|
151
|
+
|
|
152
|
+
```bash
|
|
153
|
+
# Run plan and stream JSON result to stdout
|
|
154
|
+
kk bot plan <channel> <path/to/plan.json> -m 60
|
|
155
|
+
|
|
156
|
+
# Run plan and write 0600 artifact files + result.json / error.json into output dir
|
|
157
|
+
kk bot plan <channel> <path/to/plan.json> -o <path/to/evidence-dir> -m 60
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
Exit codes: `0` = success, `1` = operational failure (`authentication`, `empty`, or `browser`), `2` = usage error (invalid JSON, missing profile, invalid timeout).
|
|
161
|
+
|
|
162
|
+
Low-level debugging can also use the repository probe script:
|
|
49
163
|
|
|
50
164
|
```bash
|
|
51
|
-
|
|
165
|
+
bun packages/publish-harness/scripts/bot-collection-probe.ts \
|
|
166
|
+
--profile <name> \
|
|
167
|
+
--plan <path/to/plan.json> \
|
|
168
|
+
--out <path/to/evidence-dir>
|
|
52
169
|
```
|
|
53
170
|
|
|
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
|
-
`
|
|
171
|
+
---
|
|
172
|
+
|
|
173
|
+
## Tier 3: Deep Interactive Automation (Playwright / CDP)
|
|
174
|
+
|
|
175
|
+
When an activity requires capabilities outside Tier 2 — specifically:
|
|
176
|
+
1. **Interactive UI discovery** (navigating unknown layouts, recording screenshots).
|
|
177
|
+
2. **Shadow-root component piercing** (e.g. XHS creator console shadow boundaries).
|
|
178
|
+
3. **File uploads** (attaching images/videos via `page.setInputFiles`).
|
|
179
|
+
4. **Canvas / complex coordinate dragging**.
|
|
180
|
+
|
|
181
|
+
You MUST wrap the run inside the shared profile lease to prevent profile corruption:
|
|
182
|
+
|
|
183
|
+
```ts
|
|
184
|
+
import { chromium } from 'playwright';
|
|
185
|
+
import { withProfileLease } from '@gobing-ai/publish-harness';
|
|
186
|
+
|
|
187
|
+
const profileName = 'xhs';
|
|
188
|
+
const profileDir = `${process.env.HOME}/.config/kk/browser-profiles/${profileName}`;
|
|
189
|
+
const port = process.env.KK_WEB_CDP ?? '9222';
|
|
190
|
+
|
|
191
|
+
await withProfileLease(profileName, async () => {
|
|
192
|
+
const ctx = await chromium.launchPersistentContext(profileDir, {
|
|
193
|
+
headless: process.env.KK_WEB_HEADLESS === 'true',
|
|
194
|
+
viewport: null,
|
|
195
|
+
args: [
|
|
196
|
+
`--remote-debugging-port=${port}`,
|
|
197
|
+
'--disable-blink-features=AutomationControlled',
|
|
198
|
+
],
|
|
199
|
+
});
|
|
200
|
+
try {
|
|
201
|
+
const page = ctx.pages()[0] ?? (await ctx.newPage());
|
|
202
|
+
// Drive page actions, upload files, or attach agent-browser via CDP...
|
|
203
|
+
} finally {
|
|
204
|
+
await ctx.close();
|
|
205
|
+
}
|
|
206
|
+
});
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
---
|
|
210
|
+
|
|
211
|
+
## Playbook: Common Automation Scenarios
|
|
212
|
+
|
|
213
|
+
### Scenario A: Site Discovery & Reverse-Engineering
|
|
214
|
+
1. Check cached session: `kk bot list`.
|
|
215
|
+
2. Open target page headed: `kk bot open <channel>`.
|
|
216
|
+
3. Inspect DOM, capture layout, dump accessibility tree, take screenshots.
|
|
217
|
+
4. Document selectors, shadow roots, and observed signals into `docs/design/<channel>-ui-discovery.md`.
|
|
218
|
+
5. Close window; `kk bot open` outputs `<name>\tclosed`.
|
|
219
|
+
|
|
220
|
+
### Scenario B: Lightweight Authenticated Scraping
|
|
221
|
+
1. Send direct authenticated request:
|
|
222
|
+
```bash
|
|
223
|
+
kk bot exec <channel> "https://target.com/api/data" -H "Accept: application/json" -o data.json
|
|
224
|
+
```
|
|
225
|
+
2. If the endpoint returns client-rendered HTML shell rather than JSON, escalate to **Scenario C**.
|
|
226
|
+
|
|
227
|
+
### Scenario C: Declarative Headless Data Collection
|
|
228
|
+
1. Draft a `plan.json` with required navigation, waits, and response captures.
|
|
229
|
+
2. Probe run:
|
|
230
|
+
```bash
|
|
231
|
+
bun packages/publish-harness/scripts/bot-collection-probe.ts --profile <channel> --plan plan.json --out .spur/run/evidence
|
|
232
|
+
```
|
|
233
|
+
3. Verify `result.json` shows all artifacts captured with non-empty bodies.
|
|
234
|
+
4. Wire into ingestion plugin or workflow.
|
|
235
|
+
|
|
236
|
+
### Scenario D: Broken Selector Repair (`enhance`)
|
|
237
|
+
1. Replay failing plan or run `kk bot exec`.
|
|
238
|
+
2. Inspect `error.json` / diagnostics (is it `authentication`, `empty`, or `browser`?).
|
|
239
|
+
3. If selector changed, launch `kk bot open <channel>`, observe the updated DOM element.
|
|
240
|
+
4. Update selector in shared helper, re-verify with probe script, commit alongside discovery doc.
|
|
241
|
+
|
|
242
|
+
---
|
|
243
|
+
|
|
244
|
+
## Safety Rails (Non-Negotiable)
|
|
245
|
+
|
|
246
|
+
- **Draft-Safe by Default**: Never click publish/send/submit/delete unless the task explicitly authorizes live actions.
|
|
247
|
+
- **Lease Invariant**: Every browser context touching `~/.config/kk/browser-profiles/<name>` must be acquired through `kk bot`, `runBotCollection`, or `withProfileLease`. Direct un-leased `launchPersistentContext` is banned.
|
|
248
|
+
- **Fail Closed on Quiet Failures**: Missing data and auth walls must fail loud (`authentication` or `empty`). Never treat an empty SPA shell or an auth redirect as a normal quiet response.
|
|
249
|
+
- **Headed vs Headless**:
|
|
250
|
+
- Headless: Session probes (`kk bot list`), authenticated queries (`kk bot exec`), declarative collection (`runBotCollection`).
|
|
251
|
+
- Headed: First-time logins (`kk bot login`), interactive discovery (`kk bot open`), and bot-walled platforms (XHS).
|
|
252
|
+
- **Secrets Invariant**: Zero credentials in repo, code, or logs. All state lives exclusively in `~/.config/kk/` outside Git.
|
|
253
|
+
- **Confidence-Verified Verdicts**: Every workflow outcome verdict must declare `confidence: HIGH | MEDIUM | LOW`. Missing or out-of-enum confidence halts execution.
|