@gobing-ai/knowledge-kit 0.0.36 → 0.0.37
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 +14 -13
- package/package.json +1 -1
- package/plugins/generations/dailynews-gen/dist/index.js +22 -0
- package/plugins/generations/dailynews-gen/src/script-plan.ts +32 -0
- package/plugins/kk/plugin.json +1 -1
- package/plugins/kk/scripts/daily-voice-style.zh.md +1 -1
- package/plugins/kk/workflows/kk-daily-ai-voice2.yaml +1 -1
package/dist/index.js
CHANGED
|
@@ -37325,7 +37325,7 @@ ${section}
|
|
|
37325
37325
|
`;
|
|
37326
37326
|
}
|
|
37327
37327
|
function selectMissingRuns(entries, markdown) {
|
|
37328
|
-
return entries.filter((entry) => entry.status !== "running" && !ledgerHasRun(markdown, entry.runId)).sort((left, right) => (left.startedAt ?? "").localeCompare(right.startedAt ?? "")).map((entry) => entry.runId);
|
|
37328
|
+
return entries.filter((entry) => entry.status !== "running" && entry.isDryRun !== true && !ledgerHasRun(markdown, entry.runId)).sort((left, right) => (left.startedAt ?? "").localeCompare(right.startedAt ?? "")).map((entry) => entry.runId);
|
|
37329
37329
|
}
|
|
37330
37330
|
function rowCells(row) {
|
|
37331
37331
|
const cells = row.replaceAll("\\|", ESCAPED_PIPE_SENTINEL).split("|");
|
|
@@ -47322,9 +47322,9 @@ function registerExecutorCommand(program) {
|
|
|
47322
47322
|
withRunOptions(executor.command("run").description("Invoke a plugin with input/output files and contract validation").argument("<plugin>", "Name of the plugin to invoke")).action(runInvokeAction);
|
|
47323
47323
|
withFaninOptions(executor.command("fan-in").alias("fanin").description("Merge N Doc[] JSON inputs into one deduplicated Doc[] output")).action(runFaninAction);
|
|
47324
47324
|
withFanoutOptions(executor.command("fan-out").alias("fanout").description("Publish one Content JSON to N targets, aggregating per-target results")).action(runFanoutAction);
|
|
47325
|
-
withRunOptions(program.command("invoke", { hidden: true }).description("Alias for `executor run`
|
|
47326
|
-
withFaninOptions(program.command("fanin", { hidden: true }).description("Alias for `executor fan-in`
|
|
47327
|
-
withFanoutOptions(program.command("fanout", { hidden: true }).description("Alias for `executor fan-out`
|
|
47325
|
+
withRunOptions(program.command("invoke", { hidden: true }).description("[deprecated] Alias for `executor run`").argument("<plugin>", "Name of the plugin to invoke")).action(runInvokeAction);
|
|
47326
|
+
withFaninOptions(program.command("fanin", { hidden: true }).description("[deprecated] Alias for `executor fan-in`")).action(runFaninAction);
|
|
47327
|
+
withFanoutOptions(program.command("fanout", { hidden: true }).description("[deprecated] Alias for `executor fan-out`")).action(runFanoutAction);
|
|
47328
47328
|
}
|
|
47329
47329
|
|
|
47330
47330
|
// src/cli.ts
|
|
@@ -47381,9 +47381,10 @@ async function lockReleaseAction(options) {
|
|
|
47381
47381
|
}
|
|
47382
47382
|
}
|
|
47383
47383
|
function registerLockCommand(parent, hidden = false) {
|
|
47384
|
-
const
|
|
47385
|
-
|
|
47386
|
-
lock.command("
|
|
47384
|
+
const legacy = hidden ? "[deprecated] " : "";
|
|
47385
|
+
const lock = parent.command("lock", { hidden }).description(`${legacy}Single-flight locks over the store`);
|
|
47386
|
+
lock.command("acquire").description(`${legacy}Take the named lock for this run; prints {acquired} or {skipped, holder} (exit 0 both ways)`).requiredOption("--name <lock>", "Lock name (e.g. collect)").requiredOption("--run <id>", "Owning run id (re-entrant for the same id)").option("--ttl <ms>", "Claim lifetime for a dead holder, in milliseconds", String(DEFAULT_LOCK_TTL_MS)).option("--db <path>", "Store database path (default: kk config store.db_path, else .works/kk.db)").action(lockAcquireAction);
|
|
47387
|
+
lock.command("release").description(`${legacy}Release the named lock iff this run still owns it; prints {released}`).requiredOption("--name <lock>", "Lock name (e.g. collect)").requiredOption("--run <id>", "Owning run id").option("--db <path>", "Store database path (default: kk config store.db_path, else .works/kk.db)").action(lockReleaseAction);
|
|
47387
47388
|
}
|
|
47388
47389
|
|
|
47389
47390
|
// src/commands/plugin.ts
|
|
@@ -47590,12 +47591,12 @@ function registerPluginCommand(program) {
|
|
|
47590
47591
|
registerStatusVerb(plugin, "status", "List discovered plugins grouped by kind with a per-plugin health mark", false);
|
|
47591
47592
|
plugin.command("check [names...]").description("Run each selected plugin\u2019s readiness probe; exits nonzero on refused or errored plugins").option("--kind <kind>", "Filter plugins by kind (ingestion, generator, publish)").option("--json", "Output machine-readable verdict rows").option("--headed", "Run probes with a visible browser window").option("--timeout <ms>", "Per-plugin probe timeout in milliseconds").option("--plugins-root <dir>", "Exclusive root containing plugins (isolation/tests only)").option("--plugins-path <dir>", "Extra plugin root to union with defaults (repeatable)", collectPath, []).action(checkAction);
|
|
47592
47593
|
plugin.command("login <name>").description("Run the plugin\u2019s interactive login probe with inherited stdio").option("--plugins-root <dir>", "Exclusive root containing plugins (isolation/tests only)").option("--plugins-path <dir>", "Extra plugin root to union with defaults (repeatable)", collectPath, []).action(loginAction);
|
|
47593
|
-
registerStatusVerb(plugin, "list", "Alias for `plugin status`
|
|
47594
|
-
registerStatusVerb(plugin, "doctor", "Alias for `plugin status`
|
|
47595
|
-
const plugins = program.command("plugins", { hidden: true }).description("Alias for `plugin status`
|
|
47596
|
-
registerStatusVerb(plugins, "status", "Alias for `plugin status`
|
|
47597
|
-
registerStatusVerb(plugins, "list", "Alias for `plugin status`
|
|
47598
|
-
registerStatusVerb(plugins, "doctor", "Alias for `plugin status`
|
|
47594
|
+
registerStatusVerb(plugin, "list", "[deprecated] Alias for `plugin status`", true);
|
|
47595
|
+
registerStatusVerb(plugin, "doctor", "[deprecated] Alias for `plugin status`", true);
|
|
47596
|
+
const plugins = program.command("plugins", { hidden: true }).description("[deprecated] Alias for `plugin status`");
|
|
47597
|
+
registerStatusVerb(plugins, "status", "[deprecated] Alias for `plugin status`", true);
|
|
47598
|
+
registerStatusVerb(plugins, "list", "[deprecated] Alias for `plugin status`", true);
|
|
47599
|
+
registerStatusVerb(plugins, "doctor", "[deprecated] Alias for `plugin status`", true);
|
|
47599
47600
|
}
|
|
47600
47601
|
|
|
47601
47602
|
// src/commands/schedule.ts
|
package/package.json
CHANGED
|
@@ -12582,6 +12582,24 @@ function parseStyleContract(markdown) {
|
|
|
12582
12582
|
}
|
|
12583
12583
|
return StyleContractSchema.parse(parsed);
|
|
12584
12584
|
}
|
|
12585
|
+
var REDUNDANT_INSIGHT_SPAN = 14;
|
|
12586
|
+
var REDUNDANT_INSIGHT_CLAUSE_LIMIT = 3;
|
|
12587
|
+
function redundantInsightClauses(insight, reference) {
|
|
12588
|
+
const ref = reference.replace(/[\s\p{P}\p{S}]+/gu, "");
|
|
12589
|
+
let count = 0;
|
|
12590
|
+
for (const clause of insight.split(/[\u3002\uFF01\uFF1F\uFF1B\uFF0C]/)) {
|
|
12591
|
+
const norm = clause.replace(/[\s\p{P}\p{S}]+/gu, "");
|
|
12592
|
+
if (norm.length < REDUNDANT_INSIGHT_SPAN)
|
|
12593
|
+
continue;
|
|
12594
|
+
for (let i = 0;i + REDUNDANT_INSIGHT_SPAN <= norm.length; i++) {
|
|
12595
|
+
if (ref.includes(norm.slice(i, i + REDUNDANT_INSIGHT_SPAN))) {
|
|
12596
|
+
count++;
|
|
12597
|
+
break;
|
|
12598
|
+
}
|
|
12599
|
+
}
|
|
12600
|
+
}
|
|
12601
|
+
return count;
|
|
12602
|
+
}
|
|
12585
12603
|
function validateScriptPlan(plan, docs, style) {
|
|
12586
12604
|
const parsed = ScriptPlanSchema.safeParse(plan);
|
|
12587
12605
|
if (!parsed.success) {
|
|
@@ -12615,6 +12633,10 @@ function validateScriptPlan(plan, docs, style) {
|
|
|
12615
12633
|
errors.push({ itemId: item.id, rule: "cap:lead" });
|
|
12616
12634
|
if (item.insight.length > style.caps.insight)
|
|
12617
12635
|
errors.push({ itemId: item.id, rule: "cap:insight" });
|
|
12636
|
+
const doc = docs.find((entry) => entry.id === item.id);
|
|
12637
|
+
if (doc !== undefined && redundantInsightClauses(item.insight, `${item.lead}${doc.body}`) >= REDUNDANT_INSIGHT_CLAUSE_LIMIT) {
|
|
12638
|
+
errors.push({ itemId: item.id, rule: "redundant-insight" });
|
|
12639
|
+
}
|
|
12618
12640
|
}
|
|
12619
12641
|
const fields = [
|
|
12620
12642
|
{ itemId: "episode", text: valid.intro },
|
|
@@ -104,9 +104,33 @@ export function parseStyleContract(markdown: string): StyleContract {
|
|
|
104
104
|
* - `cap:<field>`: a field over its cap (`intro`/`outro` report `itemId: episode`)
|
|
105
105
|
* - `banned:<phrase>`: a field containing a banned phrase
|
|
106
106
|
* - `duplicate-insight`: the same insight text on two items in one episode
|
|
107
|
+
* - `redundant-insight`: the insight restates the narration — ≥ 3 of its clauses each share a
|
|
108
|
+
* ≥ 14-char verbatim span with the item's spoken facts (lead + doc body). 20261014 episode: the
|
|
109
|
+
* prompt told the planner to restate facts, so the listener heard near-identical wording twice
|
|
110
|
+
* per item. One repeated number is tolerable; three copied clauses is a second narration.
|
|
107
111
|
*
|
|
108
112
|
* All-or-nothing by contract (Q&A): a partially valid plan is never partially applied.
|
|
109
113
|
*/
|
|
114
|
+
/** Verbatim-span length (normalized) that counts a clause as restated, not as a fact mention. */
|
|
115
|
+
const REDUNDANT_INSIGHT_SPAN = 14;
|
|
116
|
+
/** A listener tolerates one restated clause; at this many the item reads as a second narration. */
|
|
117
|
+
const REDUNDANT_INSIGHT_CLAUSE_LIMIT = 3;
|
|
118
|
+
|
|
119
|
+
function redundantInsightClauses(insight: string, reference: string): number {
|
|
120
|
+
const ref = reference.replace(/[\s\p{P}\p{S}]+/gu, '');
|
|
121
|
+
let count = 0;
|
|
122
|
+
for (const clause of insight.split(/[。!?;,]/)) {
|
|
123
|
+
const norm = clause.replace(/[\s\p{P}\p{S}]+/gu, '');
|
|
124
|
+
if (norm.length < REDUNDANT_INSIGHT_SPAN) continue;
|
|
125
|
+
for (let i = 0; i + REDUNDANT_INSIGHT_SPAN <= norm.length; i++) {
|
|
126
|
+
if (ref.includes(norm.slice(i, i + REDUNDANT_INSIGHT_SPAN))) {
|
|
127
|
+
count++;
|
|
128
|
+
break;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
return count;
|
|
133
|
+
}
|
|
110
134
|
export function validateScriptPlan(plan: unknown, docs: Doc[], style: StyleContract): ScriptPlanValidation {
|
|
111
135
|
const parsed = ScriptPlanSchema.safeParse(plan);
|
|
112
136
|
if (!parsed.success) {
|
|
@@ -134,6 +158,14 @@ export function validateScriptPlan(plan: unknown, docs: Doc[], style: StyleContr
|
|
|
134
158
|
for (const item of valid.items) {
|
|
135
159
|
if (item.lead.length > style.caps.lead) errors.push({ itemId: item.id, rule: 'cap:lead' });
|
|
136
160
|
if (item.insight.length > style.caps.insight) errors.push({ itemId: item.id, rule: 'cap:insight' });
|
|
161
|
+
const doc = docs.find((entry) => entry.id === item.id);
|
|
162
|
+
// unknown-id is already reported above; skip the redundancy check rather than double-report.
|
|
163
|
+
if (
|
|
164
|
+
doc !== undefined &&
|
|
165
|
+
redundantInsightClauses(item.insight, `${item.lead}${doc.body}`) >= REDUNDANT_INSIGHT_CLAUSE_LIMIT
|
|
166
|
+
) {
|
|
167
|
+
errors.push({ itemId: item.id, rule: 'redundant-insight' });
|
|
168
|
+
}
|
|
137
169
|
}
|
|
138
170
|
|
|
139
171
|
const fields: { itemId: string; text: string }[] = [
|
package/plugins/kk/plugin.json
CHANGED
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
|
|
30
30
|
- `intro`:开场导语,串起今天几个主题,接在固定问候之后,不超过 150 字。
|
|
31
31
|
- `lead`:一句话口语桥段,引出下一个主题的【标题】;只做铺垫,不得复述标题本身,不超过 80 字。
|
|
32
|
-
- `insight`:只基于这一条自身可核事实的点评(3–6 句),展开这一条自身的机制→意义→实用角度;不得挪用其他条目的话题,不超过 380
|
|
32
|
+
- `insight`:只基于这一条自身可核事实的点评(3–6 句),展开这一条自身的机制→意义→实用角度;不得挪用其他条目的话题,不超过 380 字。听众刚听完这一条的事实叙述,insight 是点评不是复读:不得复述正文已讲过的事实、数字或成串措辞(最多点到一两个关键词),深度来自角度和判断,不是把事实再讲一遍。时长契约:全片按 15–20 分钟口播设计,insight 应写到接近上限——宁可深挖这一条的角度,也不要浅尝辄止。字数按配音驱动折算:gemini ≈3.3 字/秒(正文约 4300–5800 字);Voicebox robin-news ≈6.3 字/秒(正文约 5700–7600 字,或增加条目数)。
|
|
33
33
|
- `outro`:简短收束语,接在固定致谢之前,不超过 150 字。
|
|
34
34
|
|
|
35
35
|
## 机器可读契约
|
|
@@ -457,7 +457,7 @@ nodes:
|
|
|
457
457
|
# ADR-115 error tier: keep this prompt <= 1000 chars.
|
|
458
458
|
input: |
|
|
459
459
|
Read ${vars.work_dir}/21-plan/${vars.run_date}_03_plan_plan.json — a JSON array of docs; don't edit it. Also read the style contract ${vars.work_dir}/24-script/${vars.run_date}_08_script-write_style.md and obey its char caps, duration budget and banned phrases.
|
|
460
|
-
For each doc write a `lead` (a spoken bridge, not containing the title) and an `insight` (
|
|
460
|
+
For each doc write a `lead` (a spoken bridge, not containing the title) and an `insight` (a take, not a recap: the narration just read that doc's facts — never restate its facts, numbers or wording; give only your angle, judgment or what-to-watch, no new facts, keep hedges(据报道), no new degree words).
|
|
461
461
|
intro/outro hook only in-scope items; no greeting or sign-off — the builder adds both. 选题边界:政治/外交、贸易管制、军事、公共政策争议、社会公共事件条目绝不复述;读文章 22-article/*_06_article-write_body.md,其文末注记点名的 id 一并进 excluded,各配中文原因。
|
|
462
462
|
Output only JSON {"version":1,"intro":"…","outro":"…","items":[{"id":"…","lead":"…","insight":"…"}],"excluded":[{"id":"…","reason":"…"}]} to ${vars.work_dir}/24-script/${vars.run_date}_08_script-write_plan.json. Exactly one `items` entry per doc not in `excluded`.
|
|
463
463
|
expectFile: ${vars.work_dir}/24-script/${vars.run_date}_08_script-write_plan.json
|