@gobing-ai/knowledge-kit 0.0.32 → 0.0.33

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 (65) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/dist/index.js +32320 -15021
  3. package/package.json +4 -4
  4. package/plugins/generations/content-gen/dist/index.js +10 -9
  5. package/plugins/generations/core-facts-gen/dist/index.js +13 -12
  6. package/plugins/generations/daily-article-gen/dist/index.js +14 -13
  7. package/plugins/generations/daily-article-gen/src/index.ts +1 -1
  8. package/plugins/generations/dailynews-gen/dist/index.js +10 -9
  9. package/plugins/generations/episode-plan-gen/dist/index.js +58 -15
  10. package/plugins/generations/episode-plan-gen/src/index.ts +76 -6
  11. package/plugins/generations/gemini-tts/README.md +11 -0
  12. package/plugins/generations/gemini-tts/dist/index.js +10 -9
  13. package/plugins/generations/image-gen/dist/index.js +154 -151
  14. package/plugins/generations/image-gen/src/compose/chromium.ts +60 -42
  15. package/plugins/generations/news-report-gen/dist/index.js +13 -12
  16. package/plugins/generations/voice-gen/dist/index.js +10 -9
  17. package/plugins/ingestions/aihot-ingest/dist/index.js +13 -12
  18. package/plugins/ingestions/horizon-ingest/dist/index.js +13 -12
  19. package/plugins/ingestions/karakeep-local/dist/index.js +13 -13
  20. package/plugins/ingestions/last30days-ingest/dist/index.js +13 -12
  21. package/plugins/ingestions/web-search/dist/index.js +11 -10
  22. package/plugins/kk/README.md +38 -0
  23. package/plugins/kk/decisions/extract/ai-news.yaml +21 -0
  24. package/plugins/kk/decisions/kk-items.yaml +113 -0
  25. package/plugins/kk/plugin.json +1 -1
  26. package/plugins/kk/schedules/cron.tmpl +15 -0
  27. package/plugins/kk/schedules/launchd.plist.tmpl +77 -0
  28. package/plugins/kk/scripts/daily-stages.ts +1533 -0
  29. package/plugins/kk/scripts/kk-workflow-stages.ts +247 -1365
  30. package/plugins/kk/skills/content-safety/SKILL.md +38 -7
  31. package/plugins/kk/skills/web-automation/SKILL.md +100 -0
  32. package/plugins/kk/skills/web-automation/references/browser-launch.md +86 -0
  33. package/plugins/kk/workflows/kk-collect.yaml +258 -0
  34. package/plugins/kk/workflows/kk-daily-ai-voice.yaml +9 -3
  35. package/plugins/kk/workflows/kk-daily-ai-voice2.yaml +655 -0
  36. package/plugins/kk/workflows/kk-daily-safety.yaml +170 -0
  37. package/plugins/publishings/emdash-pub/dist/index.js +10 -9
  38. package/plugins/publishings/infoq-pub/dist/index.js +152 -59
  39. package/plugins/publishings/infoq-pub/plugin.json +1 -0
  40. package/plugins/publishings/infoq-pub/src/index.ts +167 -55
  41. package/plugins/publishings/infoq-pub/src/profile-check.ts +4 -2
  42. package/plugins/publishings/juejin-pub/dist/index.js +111 -30
  43. package/plugins/publishings/juejin-pub/plugin.json +1 -0
  44. package/plugins/publishings/juejin-pub/src/index.ts +49 -9
  45. package/plugins/publishings/medium-pub/dist/index.js +10 -9
  46. package/plugins/publishings/podcast-pub/dist/index.js +10 -9
  47. package/plugins/publishings/qiita-pub/dist/index.js +10 -9
  48. package/plugins/publishings/substack-pub/dist/index.js +105 -28
  49. package/plugins/publishings/substack-pub/plugin.json +1 -0
  50. package/plugins/publishings/substack-pub/src/index.ts +39 -8
  51. package/plugins/publishings/substack-pub/src/profile-check.ts +2 -0
  52. package/plugins/publishings/surfdash-pub/dist/index.js +10 -9
  53. package/plugins/publishings/wechatmp-pub/dist/index.js +115 -31
  54. package/plugins/publishings/wechatmp-pub/plugin.json +1 -0
  55. package/plugins/publishings/wechatmp-pub/src/index.ts +42 -9
  56. package/plugins/publishings/wechatmp-pub/src/profile-check.ts +84 -40
  57. package/plugins/publishings/x-pub/dist/index.js +114 -35
  58. package/plugins/publishings/x-pub/plugin.json +1 -0
  59. package/plugins/publishings/x-pub/src/index.ts +68 -14
  60. package/plugins/publishings/xhs-pub/dist/index.js +100 -54
  61. package/plugins/publishings/xhs-pub/plugin.json +1 -0
  62. package/plugins/publishings/xhs-pub/src/index.ts +8 -4
  63. package/plugins/publishings/xhs-pub/src/page.ts +4 -17
  64. package/plugins/publishings/xhs-pub/src/profile-check.ts +28 -15
  65. package/plugins/publishings/zenn-pub/dist/index.js +10 -9
@@ -14642,7 +14642,7 @@ var init_zod = __esm(() => {
14642
14642
  init_external();
14643
14643
  });
14644
14644
 
14645
- // ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.15/node_modules/@gobing-ai/ts-utils/dist/errors.js
14645
+ // ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.18/node_modules/@gobing-ai/ts-utils/dist/errors.js
14646
14646
  var ErrorCode;
14647
14647
  var init_errors3 = __esm(() => {
14648
14648
  ErrorCode = {
@@ -14653,7 +14653,7 @@ var init_errors3 = __esm(() => {
14653
14653
  };
14654
14654
  });
14655
14655
 
14656
- // ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.15/node_modules/@gobing-ai/ts-utils/dist/api-response.js
14656
+ // ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.18/node_modules/@gobing-ai/ts-utils/dist/api-response.js
14657
14657
  var API_ERROR_CODES, ERROR_CODE_TO_HTTP, CLIENT_SAFE_CODES;
14658
14658
  var init_api_response = __esm(() => {
14659
14659
  init_errors3();
@@ -14676,13 +14676,13 @@ var init_api_response = __esm(() => {
14676
14676
  CLIENT_SAFE_CODES = new Set([ErrorCode.NotFound, ErrorCode.Validation, ErrorCode.Conflict]);
14677
14677
  });
14678
14678
 
14679
- // ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.15/node_modules/@gobing-ai/ts-utils/dist/cursor.js
14679
+ // ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.18/node_modules/@gobing-ai/ts-utils/dist/cursor.js
14680
14680
  var init_cursor = () => {};
14681
14681
 
14682
- // ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.15/node_modules/@gobing-ai/ts-utils/dist/event-severity.js
14682
+ // ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.18/node_modules/@gobing-ai/ts-utils/dist/event-severity.js
14683
14683
  var init_event_severity = () => {};
14684
14684
 
14685
- // ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.15/node_modules/@gobing-ai/ts-utils/dist/output.js
14685
+ // ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.18/node_modules/@gobing-ai/ts-utils/dist/output.js
14686
14686
  function processStream(name) {
14687
14687
  const proc = globalThis.process;
14688
14688
  const stream = proc?.[name];
@@ -14700,7 +14700,7 @@ function echoError(message, target = defaultStderrTarget ?? processStream("stder
14700
14700
  }
14701
14701
  var defaultStderrTarget;
14702
14702
 
14703
- // ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.15/node_modules/@gobing-ai/ts-utils/dist/index.js
14703
+ // ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.18/node_modules/@gobing-ai/ts-utils/dist/index.js
14704
14704
  var init_dist = __esm(() => {
14705
14705
  init_api_response();
14706
14706
  init_cursor();
@@ -21698,7 +21698,7 @@ var init_dist2 = __esm(() => {
21698
21698
  $visitAsync = visit.visitAsync;
21699
21699
  });
21700
21700
 
21701
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.15/node_modules/@gobing-ai/ts-runtime/dist/config.js
21701
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.18+ea28d47622d670ff/node_modules/@gobing-ai/ts-runtime/dist/config.js
21702
21702
  var configSchema;
21703
21703
  var init_config = __esm(() => {
21704
21704
  init_dist2();
@@ -21722,7 +21722,7 @@ var init_config = __esm(() => {
21722
21722
  });
21723
21723
  });
21724
21724
 
21725
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.15/node_modules/@gobing-ai/ts-runtime/dist/file-system-node.js
21725
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.18+ea28d47622d670ff/node_modules/@gobing-ai/ts-runtime/dist/file-system-node.js
21726
21726
  import { appendFileSync, cpSync, createReadStream, createWriteStream, existsSync, mkdirSync, readdirSync, readFileSync, realpathSync, renameSync, rmSync, statSync, writeFileSync } from "fs";
21727
21727
  import { dirname, resolve as resolvePath } from "path";
21728
21728
  function createNodeFileSystem(root, paths) {
@@ -21898,18 +21898,19 @@ var PluginManifestSchema = exports_external.looseObject({
21898
21898
  name: exports_external.string().min(1),
21899
21899
  kind: PluginKindSchema,
21900
21900
  entry: exports_external.string().min(1),
21901
+ check: exports_external.string().min(1).optional(),
21901
21902
  version: exports_external.string().optional(),
21902
21903
  description: exports_external.string().optional(),
21903
21904
  operations: exports_external.record(exports_external.string(), PluginOperationSchema).optional()
21904
21905
  });
21905
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.15/node_modules/@gobing-ai/ts-runtime/dist/index.js
21906
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.18+ea28d47622d670ff/node_modules/@gobing-ai/ts-runtime/dist/index.js
21906
21907
  init_file_system_node();
21907
21908
  init_config();
21908
21909
 
21909
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.15/node_modules/@gobing-ai/ts-runtime/dist/fs.js
21910
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.18+ea28d47622d670ff/node_modules/@gobing-ai/ts-runtime/dist/fs.js
21910
21911
  init_file_system_node();
21911
21912
 
21912
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.15/node_modules/@gobing-ai/ts-runtime/dist/path.js
21913
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.18+ea28d47622d670ff/node_modules/@gobing-ai/ts-runtime/dist/path.js
21913
21914
  function normalizeSeparators(path) {
21914
21915
  return path.replaceAll("\\", "/");
21915
21916
  }
@@ -21943,7 +21944,7 @@ function dirnamePath(path) {
21943
21944
  return normalized.slice(0, index);
21944
21945
  }
21945
21946
 
21946
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.15/node_modules/@gobing-ai/ts-runtime/dist/fs.js
21947
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.18+ea28d47622d670ff/node_modules/@gobing-ai/ts-runtime/dist/fs.js
21947
21948
  async function ensureDirForFile(path, fs = createNodeFileSystem()) {
21948
21949
  await fs.ensureDir(dirnamePath(path));
21949
21950
  }
@@ -14642,7 +14642,7 @@ var init_zod = __esm(() => {
14642
14642
  init_external();
14643
14643
  });
14644
14644
 
14645
- // ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.15/node_modules/@gobing-ai/ts-utils/dist/errors.js
14645
+ // ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.18/node_modules/@gobing-ai/ts-utils/dist/errors.js
14646
14646
  var ErrorCode;
14647
14647
  var init_errors3 = __esm(() => {
14648
14648
  ErrorCode = {
@@ -14653,7 +14653,7 @@ var init_errors3 = __esm(() => {
14653
14653
  };
14654
14654
  });
14655
14655
 
14656
- // ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.15/node_modules/@gobing-ai/ts-utils/dist/api-response.js
14656
+ // ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.18/node_modules/@gobing-ai/ts-utils/dist/api-response.js
14657
14657
  var API_ERROR_CODES, ERROR_CODE_TO_HTTP, CLIENT_SAFE_CODES;
14658
14658
  var init_api_response = __esm(() => {
14659
14659
  init_errors3();
@@ -14676,13 +14676,13 @@ var init_api_response = __esm(() => {
14676
14676
  CLIENT_SAFE_CODES = new Set([ErrorCode.NotFound, ErrorCode.Validation, ErrorCode.Conflict]);
14677
14677
  });
14678
14678
 
14679
- // ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.15/node_modules/@gobing-ai/ts-utils/dist/cursor.js
14679
+ // ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.18/node_modules/@gobing-ai/ts-utils/dist/cursor.js
14680
14680
  var init_cursor = () => {};
14681
14681
 
14682
- // ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.15/node_modules/@gobing-ai/ts-utils/dist/event-severity.js
14682
+ // ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.18/node_modules/@gobing-ai/ts-utils/dist/event-severity.js
14683
14683
  var init_event_severity = () => {};
14684
14684
 
14685
- // ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.15/node_modules/@gobing-ai/ts-utils/dist/output.js
14685
+ // ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.18/node_modules/@gobing-ai/ts-utils/dist/output.js
14686
14686
  function processStream(name) {
14687
14687
  const proc = globalThis.process;
14688
14688
  const stream = proc?.[name];
@@ -14700,7 +14700,7 @@ function echoError(message, target = defaultStderrTarget ?? processStream("stder
14700
14700
  }
14701
14701
  var defaultStderrTarget;
14702
14702
 
14703
- // ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.15/node_modules/@gobing-ai/ts-utils/dist/index.js
14703
+ // ../../node_modules/.bun/@gobing-ai+ts-utils@0.5.18/node_modules/@gobing-ai/ts-utils/dist/index.js
14704
14704
  var init_dist = __esm(() => {
14705
14705
  init_api_response();
14706
14706
  init_cursor();
@@ -21698,7 +21698,7 @@ var init_dist2 = __esm(() => {
21698
21698
  $visitAsync = visit.visitAsync;
21699
21699
  });
21700
21700
 
21701
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.15/node_modules/@gobing-ai/ts-runtime/dist/config.js
21701
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.18+ea28d47622d670ff/node_modules/@gobing-ai/ts-runtime/dist/config.js
21702
21702
  var configSchema;
21703
21703
  var init_config = __esm(() => {
21704
21704
  init_dist2();
@@ -21722,7 +21722,7 @@ var init_config = __esm(() => {
21722
21722
  });
21723
21723
  });
21724
21724
 
21725
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.15/node_modules/@gobing-ai/ts-runtime/dist/file-system-node.js
21725
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.18+ea28d47622d670ff/node_modules/@gobing-ai/ts-runtime/dist/file-system-node.js
21726
21726
  import { appendFileSync, cpSync, createReadStream, createWriteStream, existsSync, mkdirSync, readdirSync, readFileSync, realpathSync, renameSync, rmSync, statSync, writeFileSync } from "fs";
21727
21727
  import { dirname, resolve as resolvePath } from "path";
21728
21728
  function createNodeFileSystem(root, paths) {
@@ -21897,11 +21897,12 @@ var PluginManifestSchema = exports_external.looseObject({
21897
21897
  name: exports_external.string().min(1),
21898
21898
  kind: PluginKindSchema,
21899
21899
  entry: exports_external.string().min(1),
21900
+ check: exports_external.string().min(1).optional(),
21900
21901
  version: exports_external.string().optional(),
21901
21902
  description: exports_external.string().optional(),
21902
21903
  operations: exports_external.record(exports_external.string(), PluginOperationSchema).optional()
21903
21904
  });
21904
- // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.15/node_modules/@gobing-ai/ts-runtime/dist/index.js
21905
+ // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.5.18+ea28d47622d670ff/node_modules/@gobing-ai/ts-runtime/dist/index.js
21905
21906
  init_file_system_node();
21906
21907
  init_config();
21907
21908
 
@@ -24036,7 +24037,7 @@ var ConfigError = class extends Error {
24036
24037
  }
24037
24038
  };
24038
24039
 
24039
- // ../../node_modules/.bun/@gobing-ai+ts-infra@0.5.15+c7cc99588d9d7f09/node_modules/@gobing-ai/ts-infra/dist/logger.js
24040
+ // ../../node_modules/.bun/@gobing-ai+ts-infra@0.5.18+54f059b6897bbcdb/node_modules/@gobing-ai/ts-infra/dist/logger.js
24040
24041
  var ROOT_CATEGORY = "app";
24041
24042
  function toLogTapeLevel(level) {
24042
24043
  return level === "warn" ? "warning" : level;
@@ -11,6 +11,7 @@ It is a Claude Code / Superskill plugin, **not** a kk-core product plugin.
11
11
  | `hooks/` | Hook definitions |
12
12
  | `rules/` | Agent rules |
13
13
  | `workflows/` | Design-time product YAML SSOT (ADR-009). Runtime dest is `$HOME/.config/kk/workflows` via `/workflow-run` |
14
+ | `schedules/` | launchd/cron **templates** for the shipped workflows (`kk schedule render` prints them) |
14
15
 
15
16
  `agents/` is reserved for thin wrappers of fat skills. It is empty: `judge-tech` /
16
17
  `judge-tone` / `judge-compliance` were retired (2026-08-19). Rubric selection lives on
@@ -26,3 +27,40 @@ Capability files **omit a leading `kk-`**. `superskill install` prefixes the plu
26
27
  `skills/content-judge` installs as `kk:content-judge` (not `kk:kk-content-judge`). Same for `topic`,
27
28
  `storm-research`, `itc-generating`, `explain-things` (via `/tell-me`), and `/workflow-run`. Product workflow YAML (`kk-storm-research.yaml`)
28
29
  keeps its existing name — that is a workflow stem, not an installable agent capability.
30
+
31
+ ## Schedule
32
+
33
+ `spur` **has no scheduler**, so kk ships templates and `kk schedule render` prints the artifact for
34
+ the platform — **installing it is an operator action** (kk never writes a crontab or a
35
+ `LaunchAgents` plist):
36
+
37
+ ```bash
38
+ # launchd (macOS): every 6 h at 04:00/10:00/16:00/22:00 local (StartCalendarInterval), one shared log
39
+ # 1. the log directory must exist — launchd opens StandardOutPath but never creates its parent
40
+ mkdir -p "$PWD/.works/kk-collect"
41
+ # 2. render + bootstrap (the plist carries the PATH launchd's default lacks)
42
+ kk schedule render kk-collect --platform launchd --repo "$PWD" \
43
+ > ~/Library/LaunchAgents/ai.gobing.kk-collect.plist
44
+ launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/ai.gobing.kk-collect.plist
45
+
46
+ # cron: the same 6-hourly cadence (the rendered line carries its own mkdir + PATH).
47
+ # Merge, never replace: `| crontab -` discards every other job in the operator's crontab.
48
+ crontab -l > /tmp/kk-collect.cron 2>/dev/null || :
49
+ kk schedule render kk-collect --platform cron --repo "$PWD" >> /tmp/kk-collect.cron
50
+ crontab /tmp/kk-collect.cron
51
+ ```
52
+
53
+ Both rendered artifacts set `PATH` themselves (`{{home}}/.bun/bin`, `/opt/homebrew/bin`,
54
+ `/usr/local/bin`, then the system dirs). That is what the workflow's **children** need — `kk`, `jq` and
55
+ the plugins are all `#!/usr/bin/env bun` or PATH-resolved, and `launchd`/`cron` start with a minimal
56
+ `PATH`. It is **not** what resolves the scheduler's own command: launchd looks up a *relative*
57
+ `ProgramArguments[0]` with its fixed `_PATH_STDPATH` before the job environment exists, so the plist
58
+ also carries an absolute `Program` (`{{home}}/.bun/bin/spur`) while keeping `ProgramArguments` as the
59
+ frozen argv. Set both to wherever `spur`/`bun` actually live, and `mkdir -p` the log directory first
60
+ (cron's `>>` aborts before the command runs when its directory is missing).
61
+
62
+ `kk-collect` collects every ingestion source into the kk store and never publishes. Two ticks that
63
+ overlap are **one** collection: the first state takes `kk store lock acquire --name collect` and a
64
+ tick that finds the claim inside its TTL exits 0 (`skipped`) without collecting. Before relying on
65
+ the schedule, check the store is reachable from the scheduled checkout (`kk store migrate`), and
66
+ `tail -f "$PWD/.works/kk-collect/launchd.log"` after the first launch.
@@ -0,0 +1,21 @@
1
+ # ai-news topic profile (task 0210 R1, design kk-collect-and-daily-voice2.md §4).
2
+ #
3
+ # The episode pool for the daily AI-news workflow: every labelled item in the
4
+ # launch/industry categories with a substantive body and real audience signal,
5
+ # most time-sensitive first. `kk store extract --topic ai-news` compiles this into
6
+ # one parameterized query over `items` + `labels` — a new topic is a new file here,
7
+ # never a code change.
8
+ #
9
+ # Keys are decision ids from the sibling catalog (plugins/kk/decisions/kk-items.yaml);
10
+ # an unknown key or decision id fails loud with `kk.store.profile.invalid`.
11
+ # `limit` is omitted: the compiler's episode-cap default (20) applies unless
12
+ # `kk store extract --limit` overrides it.
13
+ topic: ai-news
14
+ where:
15
+ kk-item-category: { in: [ai-news, ai-industry] }
16
+ # quality 2, not 3: real ingest bodies (last30days/aihot summaries) are stub-length, so the
17
+ # heuristic labeler tops out at 1-2 and a gte-3 gate empties every real pool (task 0212 dogfood
18
+ # finding). Raise this back when a full-text ingest source lands.
19
+ kk-item-quality: { gte: 2 }
20
+ kk-item-importance: { gte: 3 }
21
+ order: [kk-item-urgency desc, kk-item-impact desc, first_seen_at desc]
@@ -0,0 +1,113 @@
1
+ # kk item-label decision catalog (task 0209, design §4).
2
+ #
3
+ # One decision per item label `kk store label` writes: the MECE category plus the
4
+ # four 0–5 QC dimensions. The rubric texts and the choice vocabulary mirror
5
+ # episode-plan-gen's keyword heuristic (`classifyCategory` / `scoreDimensions`), so a
6
+ # model answer and a heuristic answer are directly comparable rows in `labels`.
7
+ #
8
+ # Resolution: registered through `decisions.paths` in `.spur/config.yaml`
9
+ # (project-relative `plugins/kk/decisions`). No kk workflow reads this catalog as a
10
+ # `decide` action; `kk store label` calls `spur decision run` and degrades to the
11
+ # heuristic when the backend does not answer.
12
+ $schema: "@gobing-ai/spur/schemas/decision-catalog.schema.json"
13
+ version: 1
14
+
15
+ defaults:
16
+ # ADR-125 value, in lockstep with config/decisions/task-pipeline.yaml. A model answer
17
+ # below this resolves to the decision's declared fallback with source: default.
18
+ minConfidence: 0.8
19
+
20
+ decisions:
21
+ kk-item-category:
22
+ type: choice
23
+ description: Which MECE category does this collected item belong to?
24
+ parameters:
25
+ title:
26
+ type: string
27
+ description: Item title (the heuristic's first keyword surface).
28
+ source:
29
+ type: string
30
+ description: Ingest plugin that produced the item (e.g. aihot, rss, polymarket).
31
+ criteria:
32
+ ai-news: Launch, release, announcement or product news about AI — the company/lab keyword surface.
33
+ ai-technical: Engineering substance — APIs, SDKs, tutorials, benchmarks, architectures, inference.
34
+ ai-research: Research output — papers, alignment, evaluations, novel findings.
35
+ ai-industry: Company and market signals — funding, acquisitions, valuation, policy, regulation, litigation.
36
+ non-ai: No AI signal survives the keyword scan, or a deny rule (non-AI source, junk phrase, non-AI tag) wins.
37
+ fallback: non-ai
38
+
39
+ kk-item-quality:
40
+ type: score
41
+ description: How substantive is the item's body (length and sourcedness)?
42
+ parameters:
43
+ title:
44
+ type: string
45
+ description: Item title.
46
+ source:
47
+ type: string
48
+ description: Ingest plugin that produced the item.
49
+ criteria:
50
+ - Empty or unusable body — nothing to read.
51
+ - Headline echo — a stub body under 300 characters, source mention only.
52
+ - Around 1.5k characters — a short but substantive report.
53
+ - Around 3k characters — a fully developed report.
54
+ - Around 4.5k characters — a detailed report with context.
55
+ - Around 6k characters or more, or any substantive body carrying a verifiable source URL.
56
+ fallback: 2
57
+
58
+ kk-item-importance:
59
+ type: score
60
+ description: How much does the item matter to an AI audience (source tier plus relevance)?
61
+ parameters:
62
+ title:
63
+ type: string
64
+ description: Item title.
65
+ source:
66
+ type: string
67
+ description: Ingest plugin that produced the item.
68
+ criteria:
69
+ - No audience signal at all.
70
+ - Tail source or unknown origin — incidental aggregation.
71
+ - Tail source (reddit, youtube, github, polymarket) — worth a slot on a thin day.
72
+ - Ranked feed (rss, horizon) — a horizon-ranked story.
73
+ - Human-curated front page (aihot) — the editor's own pick.
74
+ - Any tier whose relevance score is 0.8 or higher — a signal-confirmed story.
75
+ fallback: 2
76
+
77
+ kk-item-urgency:
78
+ type: score
79
+ description: How time-sensitive is the item relative to the plan date?
80
+ parameters:
81
+ title:
82
+ type: string
83
+ description: Item title.
84
+ source:
85
+ type: string
86
+ description: Ingest plugin that produced the item.
87
+ criteria:
88
+ - No publication date and no curated-recency signal — urgency cannot be judged (the heuristic never files this level).
89
+ - Published more than 7 days before the plan date — stale, archive material.
90
+ - Published 3 to 7 days before the plan date — cooling (the heuristic never files this level).
91
+ - Published within the last 7 days, or an undated same-day curated source — the default.
92
+ - Published 1 to 2 days before the plan date — still breaking.
93
+ - Published on or after the plan date — same-day news.
94
+ fallback: 2
95
+
96
+ kk-item-impact:
97
+ type: score
98
+ description: How large is the item's measured engagement?
99
+ parameters:
100
+ title:
101
+ type: string
102
+ description: Item title.
103
+ source:
104
+ type: string
105
+ description: Ingest plugin that produced the item.
106
+ criteria:
107
+ - No engagement recorded at all — unmeasurable reach (the heuristic never files this level).
108
+ - Engagement magnitude 1 or less — a single mention.
109
+ - Engagement magnitude above 1 — the item is being shared.
110
+ - Engagement magnitude above 10 — a discussion thread.
111
+ - Engagement magnitude above 100 — a widely shared story.
112
+ - Engagement magnitude above 1000 — a breakout story.
113
+ fallback: 2
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "kk",
3
- "version": "0.0.32",
3
+ "version": "0.0.33",
4
4
  "description": "knowledge-kit Claude Code plugin: skills, commands, subagents, hooks, and rules"
5
5
  }
@@ -0,0 +1,15 @@
1
+ # kk-collect — standalone 6-hourly collection (04:00/10:00/16:00/22:00 local) into the kk store.
2
+ #
3
+ # Rendered by `kk schedule render kk-collect --platform cron --repo <checkout>`; kk never edits
4
+ # the operator's crontab. Operator action (plugins/kk/README.md §Schedule) — MERGE, never replace:
5
+ #
6
+ # crontab -l > /tmp/kk-collect.cron 2>/dev/null || :
7
+ # kk schedule render kk-collect --platform cron --repo "$PWD" >> /tmp/kk-collect.cron
8
+ # crontab /tmp/kk-collect.cron
9
+ #
10
+ # `kk store lock` is the single-flight guard, so an overlapping tick exits 0 without collecting.
11
+ #
12
+ # `mkdir -p` + an explicit PATH are load-bearing, not decoration: cron runs with a minimal PATH (no
13
+ # `spur`/`kk`/`jq`/`bun`) and its `>>` redirect fails on a missing directory BEFORE the command runs,
14
+ # so a bare line would produce no log and no tick. The README install steps mirror this.
15
+ 0 4,10,16,22 * * * cd {{repo}} && mkdir -p .works/kk-collect && PATH="{{home}}/.bun/bin:/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin" spur workflow run plugins/kk/workflows/kk-collect.yaml >> {{repo}}/.works/kk-collect/launchd.log 2>&1
@@ -0,0 +1,77 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+ <!-- kk-collect — standalone 6-hourly collection (04:00/10:00/16:00/22:00 local) into the kk store.
4
+
5
+ Rendered by `kk schedule render kk-collect --platform launchd --repo <checkout>`; kk never
6
+ installs it. Operator action (plugins/kk/README.md §Schedule):
7
+
8
+ kk schedule render kk-collect --platform launchd --repo "$PWD" \
9
+ > ~/Library/LaunchAgents/ai.gobing.kk-collect.plist
10
+ launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/ai.gobing.kk-collect.plist
11
+
12
+ StartCalendarInterval fires at 04:00/10:00/16:00/22:00 local wall-clock time (6 h cadence);
13
+ hours the machine is asleep through coalesce into one run at wake (launchd.plist(5)), where cron
14
+ would skip. The engine runs one node at a time and `kk store lock` is the single-flight guard,
15
+ so overlap is answered with `skipped`, never with two collectors. -->
16
+ <plist version="1.0">
17
+ <dict>
18
+ <key>Label</key>
19
+ <string>ai.gobing.kk-collect</string>
20
+ <!-- launchd resolves a RELATIVE ProgramArguments[0] with its own _PATH_STDPATH
21
+ (/usr/bin:/bin:/usr/sbin:/sbin) before the job environment exists, so a bare `spur` fails with
22
+ posix_spawn error 0x2 no matter what PATH this plist sets (man launchd.plist: ProgramArguments).
23
+ `Program` is the absolute executable launchd execs; ProgramArguments keeps R6's frozen argv. -->
24
+ <key>Program</key>
25
+ <string>{{home}}/.bun/bin/spur</string>
26
+ <key>ProgramArguments</key>
27
+ <array>
28
+ <string>spur</string>
29
+ <string>workflow</string>
30
+ <string>run</string>
31
+ <string>plugins/kk/workflows/kk-collect.yaml</string>
32
+ </array>
33
+ <key>WorkingDirectory</key>
34
+ <string>{{repo}}</string>
35
+ <key>StartCalendarInterval</key>
36
+ <array>
37
+ <dict>
38
+ <key>Hour</key>
39
+ <integer>4</integer>
40
+ <key>Minute</key>
41
+ <integer>0</integer>
42
+ </dict>
43
+ <dict>
44
+ <key>Hour</key>
45
+ <integer>10</integer>
46
+ <key>Minute</key>
47
+ <integer>0</integer>
48
+ </dict>
49
+ <dict>
50
+ <key>Hour</key>
51
+ <integer>16</integer>
52
+ <key>Minute</key>
53
+ <integer>0</integer>
54
+ </dict>
55
+ <dict>
56
+ <key>Hour</key>
57
+ <integer>22</integer>
58
+ <key>Minute</key>
59
+ <integer>0</integer>
60
+ </dict>
61
+ </array>
62
+ <!-- The job environment applies only AFTER exec, so it is not what resolves `spur` above —
63
+ it is what the workflow's own children need (`kk`, `jq`, `bun` are all `#!/usr/bin/env bun`
64
+ or PATH-resolved). -->
65
+ <key>EnvironmentVariables</key>
66
+ <dict>
67
+ <key>PATH</key>
68
+ <string>{{home}}/.bun/bin:/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin</string>
69
+ </dict>
70
+ <key>StandardOutPath</key>
71
+ <string>{{repo}}/.works/kk-collect/launchd.log</string>
72
+ <key>StandardErrorPath</key>
73
+ <string>{{repo}}/.works/kk-collect/launchd.log</string>
74
+ <key>RunAtLoad</key>
75
+ <false/>
76
+ </dict>
77
+ </plist>