@gobing-ai/knowledge-kit 0.0.16 → 0.0.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/README.md +74 -0
  3. package/dist/index.js +46 -100
  4. package/package.json +19 -1
  5. package/plugins/generations/content-gen/dist/index.js +42 -94
  6. package/plugins/generations/core-facts-gen/dist/index.js +51 -100
  7. package/plugins/generations/daily-article-gen/dist/index.js +98 -100
  8. package/plugins/generations/daily-article-gen/src/index.ts +80 -6
  9. package/plugins/generations/dailynews-gen/dist/index.js +144 -130
  10. package/plugins/generations/dailynews-gen/src/script-builder.ts +141 -33
  11. package/plugins/generations/episode-plan-gen/dist/index.js +124 -115
  12. package/plugins/generations/episode-plan-gen/src/index.ts +111 -24
  13. package/plugins/generations/image-gen/dist/index.js +63 -115
  14. package/plugins/generations/news-report-gen/dist/index.js +164 -100
  15. package/plugins/generations/news-report-gen/src/index.ts +199 -7
  16. package/plugins/generations/omni-voice-gen/src/omni_voice_gen/pipeline.py +17 -1
  17. package/plugins/generations/omni-voice-gen/src/omni_voice_gen/qc.py +4 -22
  18. package/plugins/generations/omni-voice-gen/src/omni_voice_gen/voicescript.py +8 -0
  19. package/plugins/generations/voice-gen/dist/index.js +136 -117
  20. package/plugins/generations/voice-gen/src/concat.ts +34 -0
  21. package/plugins/generations/voice-gen/src/index.ts +6 -4
  22. package/plugins/generations/voice-gen/src/voicescript.ts +61 -0
  23. package/plugins/ingestions/aihot-ingest/dist/index.js +47 -97
  24. package/plugins/ingestions/horizon-ingest/dist/index.js +47 -96
  25. package/plugins/ingestions/karakeep-local/dist/index.js +217 -266
  26. package/plugins/ingestions/last30days-ingest/dist/index.js +42 -91
  27. package/plugins/ingestions/web-search/dist/index.js +68 -117
  28. package/plugins/kk/commands/workflow-run.md +25 -2
  29. package/plugins/kk/plugin.json +1 -1
  30. package/plugins/kk/scripts/kk-workflow-stages.ts +522 -163
  31. package/plugins/kk/scripts/validate-voicescript.ts +55 -0
  32. package/plugins/kk/skills/publish/SKILL.md +80 -0
  33. package/plugins/kk/workflows/kk-daily-ai-voice.yaml +125 -120
  34. package/plugins/kk/workflows/leftover-publish-fanout-example.yaml +53 -0
  35. package/plugins/publishings/emdash-pub/dist/index.js +42 -91
  36. package/plugins/publishings/infoq-pub/dist/index.js +21994 -0
  37. package/plugins/publishings/infoq-pub/package.json +17 -0
  38. package/plugins/publishings/infoq-pub/plugin.json +7 -0
  39. package/plugins/publishings/infoq-pub/src/index.ts +123 -0
  40. package/plugins/publishings/infoq-pub/tsconfig.json +4 -0
  41. package/plugins/publishings/juejin-pub/dist/index.js +21994 -0
  42. package/plugins/publishings/juejin-pub/package.json +17 -0
  43. package/plugins/publishings/juejin-pub/plugin.json +7 -0
  44. package/plugins/publishings/juejin-pub/src/index.ts +123 -0
  45. package/plugins/publishings/juejin-pub/tsconfig.json +4 -0
  46. package/plugins/publishings/medium-pub/dist/index.js +22041 -0
  47. package/plugins/publishings/medium-pub/package.json +17 -0
  48. package/plugins/publishings/medium-pub/plugin.json +7 -0
  49. package/plugins/publishings/medium-pub/src/index.ts +215 -0
  50. package/plugins/publishings/medium-pub/tsconfig.json +4 -0
  51. package/plugins/publishings/podcast-pub/dist/index.js +183 -123
  52. package/plugins/publishings/podcast-pub/src/index.ts +47 -3
  53. package/plugins/publishings/podcast-pub/src/show-notes.ts +153 -34
  54. package/plugins/publishings/qiita-pub/dist/index.js +42 -91
  55. package/plugins/publishings/substack-pub/dist/index.js +21994 -0
  56. package/plugins/publishings/substack-pub/package.json +17 -0
  57. package/plugins/publishings/substack-pub/plugin.json +7 -0
  58. package/plugins/publishings/substack-pub/src/index.ts +123 -0
  59. package/plugins/publishings/substack-pub/tsconfig.json +4 -0
  60. package/plugins/publishings/surfdash-pub/dist/index.js +172 -103
  61. package/plugins/publishings/surfdash-pub/src/index.ts +32 -2
  62. package/plugins/publishings/wechatmp-pub/dist/index.js +22119 -0
  63. package/plugins/publishings/wechatmp-pub/package.json +17 -0
  64. package/plugins/publishings/wechatmp-pub/plugin.json +7 -0
  65. package/plugins/publishings/wechatmp-pub/src/index.ts +304 -0
  66. package/plugins/publishings/wechatmp-pub/tsconfig.json +4 -0
  67. package/plugins/publishings/x-pub/dist/index.js +22110 -0
  68. package/plugins/publishings/x-pub/package.json +17 -0
  69. package/plugins/publishings/x-pub/plugin.json +7 -0
  70. package/plugins/publishings/x-pub/src/index.ts +222 -0
  71. package/plugins/publishings/x-pub/tsconfig.json +4 -0
  72. package/plugins/publishings/xhs-pub/dist/index.js +21994 -0
  73. package/plugins/publishings/xhs-pub/package.json +17 -0
  74. package/plugins/publishings/xhs-pub/plugin.json +7 -0
  75. package/plugins/publishings/xhs-pub/src/index.ts +123 -0
  76. package/plugins/publishings/xhs-pub/tsconfig.json +4 -0
  77. package/plugins/publishings/zenn-pub/dist/index.js +42 -91
@@ -14642,72 +14642,6 @@ var init_zod = __esm(() => {
14642
14642
  init_external();
14643
14643
  });
14644
14644
 
14645
- // ../../node_modules/.bun/@gobing-ai+ts-utils@0.4.39/node_modules/@gobing-ai/ts-utils/dist/errors.js
14646
- var ErrorCode;
14647
- var init_errors3 = __esm(() => {
14648
- ErrorCode = {
14649
- NotFound: "NOT_FOUND",
14650
- Validation: "VALIDATION",
14651
- Conflict: "CONFLICT",
14652
- Internal: "INTERNAL"
14653
- };
14654
- });
14655
-
14656
- // ../../node_modules/.bun/@gobing-ai+ts-utils@0.4.39/node_modules/@gobing-ai/ts-utils/dist/api-response.js
14657
- var API_ERROR_CODES, ERROR_CODE_TO_HTTP, CLIENT_SAFE_CODES;
14658
- var init_api_response = __esm(() => {
14659
- init_errors3();
14660
- API_ERROR_CODES = {
14661
- SUCCESS: 0,
14662
- NOT_FOUND: 404,
14663
- VALIDATION_ERROR: 422,
14664
- BAD_REQUEST: 400,
14665
- UNAUTHORIZED: 401,
14666
- FORBIDDEN: 403,
14667
- CONFLICT: 409,
14668
- INTERNAL_ERROR: 500
14669
- };
14670
- ERROR_CODE_TO_HTTP = {
14671
- [ErrorCode.NotFound]: API_ERROR_CODES.NOT_FOUND,
14672
- [ErrorCode.Validation]: API_ERROR_CODES.VALIDATION_ERROR,
14673
- [ErrorCode.Conflict]: API_ERROR_CODES.CONFLICT,
14674
- [ErrorCode.Internal]: API_ERROR_CODES.INTERNAL_ERROR
14675
- };
14676
- CLIENT_SAFE_CODES = new Set([ErrorCode.NotFound, ErrorCode.Validation, ErrorCode.Conflict]);
14677
- });
14678
-
14679
- // ../../node_modules/.bun/@gobing-ai+ts-utils@0.4.39/node_modules/@gobing-ai/ts-utils/dist/cursor.js
14680
- var init_cursor = () => {};
14681
-
14682
- // ../../node_modules/.bun/@gobing-ai+ts-utils@0.4.39/node_modules/@gobing-ai/ts-utils/dist/event-severity.js
14683
- var init_event_severity = () => {};
14684
-
14685
- // ../../node_modules/.bun/@gobing-ai+ts-utils@0.4.39/node_modules/@gobing-ai/ts-utils/dist/output.js
14686
- function processStream(name) {
14687
- const proc = globalThis.process;
14688
- const stream = proc?.[name];
14689
- if (stream === undefined) {
14690
- throw new Error(`No ${name} target available: set one via setDefaultOutputTargets or pass an explicit target`);
14691
- }
14692
- return stream;
14693
- }
14694
- function writeLine(message, target) {
14695
- target.write(`${message}
14696
- `);
14697
- }
14698
- function echoError(message, target = defaultStderrTarget ?? processStream("stderr")) {
14699
- writeLine(message, target);
14700
- }
14701
- var defaultStderrTarget;
14702
-
14703
- // ../../node_modules/.bun/@gobing-ai+ts-utils@0.4.39/node_modules/@gobing-ai/ts-utils/dist/index.js
14704
- var init_dist = __esm(() => {
14705
- init_api_response();
14706
- init_cursor();
14707
- init_errors3();
14708
- init_event_severity();
14709
- });
14710
-
14711
14645
  // ../../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/nodes/identity.js
14712
14646
  var require_identity = __commonJS((exports) => {
14713
14647
  var ALIAS = Symbol.for("yaml.alias");
@@ -17612,15 +17546,15 @@ var require_timestamp = __commonJS((exports) => {
17612
17546
  throw new Error("!!timestamp expects a date, starting with yyyy-mm-dd");
17613
17547
  const [, year, month, day, hour, minute, second] = match.map(Number);
17614
17548
  const millisec = match[7] ? Number((match[7] + "00").substr(1, 3)) : 0;
17615
- let date6 = Date.UTC(year, month - 1, day, hour || 0, minute || 0, second || 0, millisec);
17549
+ let date5 = Date.UTC(year, month - 1, day, hour || 0, minute || 0, second || 0, millisec);
17616
17550
  const tz = match[8];
17617
17551
  if (tz && tz !== "Z") {
17618
17552
  let d = parseSexagesimal(tz, false);
17619
17553
  if (Math.abs(d) < 30)
17620
17554
  d *= 60;
17621
- date6 -= 60000 * d;
17555
+ date5 -= 60000 * d;
17622
17556
  }
17623
- return new Date(date6);
17557
+ return new Date(date5);
17624
17558
  },
17625
17559
  stringify: ({ value }) => value?.toISOString().replace(/(T00:00:00)?\.000Z$/, "") ?? ""
17626
17560
  };
@@ -19480,7 +19414,7 @@ var require_composer = __commonJS((exports) => {
19480
19414
  var node_process = __require("process");
19481
19415
  var directives = require_directives();
19482
19416
  var Document = require_Document();
19483
- var errors4 = require_errors();
19417
+ var errors3 = require_errors();
19484
19418
  var identity = require_identity();
19485
19419
  var composeDoc = require_compose_doc();
19486
19420
  var resolveEnd = require_resolve_end();
@@ -19531,9 +19465,9 @@ var require_composer = __commonJS((exports) => {
19531
19465
  this.onError = (source, code, message, warning) => {
19532
19466
  const pos = getErrorPos(source);
19533
19467
  if (warning)
19534
- this.warnings.push(new errors4.YAMLWarning(pos, code, message));
19468
+ this.warnings.push(new errors3.YAMLWarning(pos, code, message));
19535
19469
  else
19536
- this.errors.push(new errors4.YAMLParseError(pos, code, message));
19470
+ this.errors.push(new errors3.YAMLParseError(pos, code, message));
19537
19471
  };
19538
19472
  this.directives = new directives.Directives({ version: options.version || "1.2" });
19539
19473
  this.options = options;
@@ -19619,7 +19553,7 @@ ${cb}` : comment;
19619
19553
  break;
19620
19554
  case "error": {
19621
19555
  const msg = token.source ? `${token.message}: ${JSON.stringify(token.source)}` : token.message;
19622
- const error51 = new errors4.YAMLParseError(getErrorPos(token), "UNEXPECTED_TOKEN", msg);
19556
+ const error51 = new errors3.YAMLParseError(getErrorPos(token), "UNEXPECTED_TOKEN", msg);
19623
19557
  if (this.atDirectives || !this.doc)
19624
19558
  this.errors.push(error51);
19625
19559
  else
@@ -19629,7 +19563,7 @@ ${cb}` : comment;
19629
19563
  case "doc-end": {
19630
19564
  if (!this.doc) {
19631
19565
  const msg = "Unexpected doc-end without preceding document";
19632
- this.errors.push(new errors4.YAMLParseError(getErrorPos(token), "UNEXPECTED_TOKEN", msg));
19566
+ this.errors.push(new errors3.YAMLParseError(getErrorPos(token), "UNEXPECTED_TOKEN", msg));
19633
19567
  break;
19634
19568
  }
19635
19569
  this.doc.directives.docEnd = true;
@@ -19644,7 +19578,7 @@ ${end.comment}` : end.comment;
19644
19578
  break;
19645
19579
  }
19646
19580
  default:
19647
- this.errors.push(new errors4.YAMLParseError(getErrorPos(token), "UNEXPECTED_TOKEN", `Unsupported token ${token.type}`));
19581
+ this.errors.push(new errors3.YAMLParseError(getErrorPos(token), "UNEXPECTED_TOKEN", `Unsupported token ${token.type}`));
19648
19582
  }
19649
19583
  }
19650
19584
  *end(forceDoc = false, endOffset = -1) {
@@ -19670,7 +19604,7 @@ ${end.comment}` : end.comment;
19670
19604
  var require_cst_scalar = __commonJS((exports) => {
19671
19605
  var resolveBlockScalar = require_resolve_block_scalar();
19672
19606
  var resolveFlowScalar = require_resolve_flow_scalar();
19673
- var errors4 = require_errors();
19607
+ var errors3 = require_errors();
19674
19608
  var stringifyString = require_stringifyString();
19675
19609
  function resolveAsScalar(token, strict = true, onError) {
19676
19610
  if (token) {
@@ -19679,7 +19613,7 @@ var require_cst_scalar = __commonJS((exports) => {
19679
19613
  if (onError)
19680
19614
  onError(offset, code, message);
19681
19615
  else
19682
- throw new errors4.YAMLParseError([offset, offset + 1], code, message);
19616
+ throw new errors3.YAMLParseError([offset, offset + 1], code, message);
19683
19617
  };
19684
19618
  switch (token.type) {
19685
19619
  case "scalar":
@@ -21559,7 +21493,7 @@ var require_parser = __commonJS((exports) => {
21559
21493
  var require_public_api = __commonJS((exports) => {
21560
21494
  var composer = require_composer();
21561
21495
  var Document = require_Document();
21562
- var errors4 = require_errors();
21496
+ var errors3 = require_errors();
21563
21497
  var log = require_log();
21564
21498
  var identity = require_identity();
21565
21499
  var lineCounter = require_line_counter();
@@ -21576,8 +21510,8 @@ var require_public_api = __commonJS((exports) => {
21576
21510
  const docs = Array.from(composer$1.compose(parser$1.parse(source)));
21577
21511
  if (prettyErrors && lineCounter2)
21578
21512
  for (const doc2 of docs) {
21579
- doc2.errors.forEach(errors4.prettifyError(source, lineCounter2));
21580
- doc2.warnings.forEach(errors4.prettifyError(source, lineCounter2));
21513
+ doc2.errors.forEach(errors3.prettifyError(source, lineCounter2));
21514
+ doc2.warnings.forEach(errors3.prettifyError(source, lineCounter2));
21581
21515
  }
21582
21516
  if (docs.length > 0)
21583
21517
  return docs;
@@ -21592,13 +21526,13 @@ var require_public_api = __commonJS((exports) => {
21592
21526
  if (!doc2)
21593
21527
  doc2 = _doc;
21594
21528
  else if (doc2.options.logLevel !== "silent") {
21595
- doc2.errors.push(new errors4.YAMLParseError(_doc.range.slice(0, 2), "MULTIPLE_DOCS", "Source contains multiple documents; please use YAML.parseAllDocuments()"));
21529
+ doc2.errors.push(new errors3.YAMLParseError(_doc.range.slice(0, 2), "MULTIPLE_DOCS", "Source contains multiple documents; please use YAML.parseAllDocuments()"));
21596
21530
  break;
21597
21531
  }
21598
21532
  }
21599
21533
  if (prettyErrors && lineCounter2) {
21600
- doc2.errors.forEach(errors4.prettifyError(source, lineCounter2));
21601
- doc2.warnings.forEach(errors4.prettifyError(source, lineCounter2));
21534
+ doc2.errors.forEach(errors3.prettifyError(source, lineCounter2));
21535
+ doc2.warnings.forEach(errors3.prettifyError(source, lineCounter2));
21602
21536
  }
21603
21537
  return doc2;
21604
21538
  }
@@ -21650,12 +21584,12 @@ var require_public_api = __commonJS((exports) => {
21650
21584
  });
21651
21585
 
21652
21586
  // ../../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/index.js
21653
- var composer, Document, Schema, errors4, Alias, identity, Pair, Scalar, YAMLMap, YAMLSeq, cst, lexer, lineCounter, parser, publicApi, visit, $Composer, $Document, $Schema, $YAMLError, $YAMLParseError, $YAMLWarning, $Alias, $isAlias, $isCollection, $isDocument, $isMap, $isNode, $isPair, $isScalar, $isSeq, $Pair, $Scalar, $YAMLMap, $YAMLSeq, $Lexer, $LineCounter, $Parser, $parse, $parseAllDocuments, $parseDocument, $stringify, $visit, $visitAsync;
21654
- var init_dist2 = __esm(() => {
21587
+ var composer, Document, Schema, errors3, Alias, identity, Pair, Scalar, YAMLMap, YAMLSeq, cst, lexer, lineCounter, parser, publicApi, visit, $Composer, $Document, $Schema, $YAMLError, $YAMLParseError, $YAMLWarning, $Alias, $isAlias, $isCollection, $isDocument, $isMap, $isNode, $isPair, $isScalar, $isSeq, $Pair, $Scalar, $YAMLMap, $YAMLSeq, $Lexer, $LineCounter, $Parser, $parse, $parseAllDocuments, $parseDocument, $stringify, $visit, $visitAsync;
21588
+ var init_dist = __esm(() => {
21655
21589
  composer = require_composer();
21656
21590
  Document = require_Document();
21657
21591
  Schema = require_Schema();
21658
- errors4 = require_errors();
21592
+ errors3 = require_errors();
21659
21593
  Alias = require_Alias();
21660
21594
  identity = require_identity();
21661
21595
  Pair = require_Pair();
@@ -21671,9 +21605,9 @@ var init_dist2 = __esm(() => {
21671
21605
  $Composer = composer.Composer;
21672
21606
  $Document = Document.Document;
21673
21607
  $Schema = Schema.Schema;
21674
- $YAMLError = errors4.YAMLError;
21675
- $YAMLParseError = errors4.YAMLParseError;
21676
- $YAMLWarning = errors4.YAMLWarning;
21608
+ $YAMLError = errors3.YAMLError;
21609
+ $YAMLParseError = errors3.YAMLParseError;
21610
+ $YAMLWarning = errors3.YAMLWarning;
21677
21611
  $Alias = Alias.Alias;
21678
21612
  $isAlias = identity.isAlias;
21679
21613
  $isCollection = identity.isCollection;
@@ -21701,7 +21635,7 @@ var init_dist2 = __esm(() => {
21701
21635
  // ../../node_modules/.bun/@gobing-ai+ts-runtime@0.4.39/node_modules/@gobing-ai/ts-runtime/dist/config.js
21702
21636
  var configSchema;
21703
21637
  var init_config = __esm(() => {
21704
- init_dist2();
21638
+ init_dist();
21705
21639
  init_zod();
21706
21640
  configSchema = exports_external.object({
21707
21641
  app: exports_external.object({
@@ -21952,10 +21886,27 @@ function getProcessPid() {
21952
21886
  function uniqueToken() {
21953
21887
  return `${Date.now()}.${crypto.randomUUID()}`;
21954
21888
  }
21889
+ // ../../node_modules/.bun/@gobing-ai+ts-utils@0.4.67/node_modules/@gobing-ai/ts-utils/dist/output.js
21890
+ var defaultStderrTarget;
21891
+ function processStream(name) {
21892
+ const proc = globalThis.process;
21893
+ const stream = proc?.[name];
21894
+ if (stream === undefined) {
21895
+ throw new Error(`No ${name} target available: set one via setDefaultOutputTargets or pass an explicit target`);
21896
+ }
21897
+ return stream;
21898
+ }
21899
+ function writeLine(message, target) {
21900
+ target.write(`${message}
21901
+ `);
21902
+ }
21903
+ function echoError(message, target = defaultStderrTarget ?? processStream("stderr")) {
21904
+ writeLine(message, target);
21905
+ }
21906
+
21955
21907
  // ../../packages/kk-core/src/render-md.ts
21956
21908
  if (false) {}
21957
21909
  // ../../plugins/generations/episode-plan-gen/src/index.ts
21958
- init_dist();
21959
21910
  var SOURCE_BASE = {
21960
21911
  aihot: 30,
21961
21912
  rss: 12,
@@ -21968,6 +21919,7 @@ var SOURCE_BASE = {
21968
21919
  };
21969
21920
  var DEFAULT_SOURCE_BASE = 5;
21970
21921
  var TITLE_SIMILARITY_THRESHOLD = 0.6;
21922
+ var STUB_BODY_FLOOR = 300;
21971
21923
  var FRESHNESS_DAYS = 7;
21972
21924
  var PER_SOURCE_CAP = 5;
21973
21925
  var NON_NEWS_TAGS = new Set(["geopolitics", "military-conflict", "war"]);
@@ -21999,11 +21951,9 @@ var TAG_CATEGORY = {
21999
21951
  war: "non-ai"
22000
21952
  };
22001
21953
  var NON_AI_SOURCES = new Set(["polymarket"]);
21954
+ var AI_DEFAULT_SOURCES = new Set(["aihot"]);
21955
+ var JUNK_KEYWORDS = ["error:", "http error", "unable to download"];
22002
21956
  var CATEGORY_KEYWORDS = [
22003
- {
22004
- category: "non-ai",
22005
- words: ["error:", "http error", "unable to download"]
22006
- },
22007
21957
  {
22008
21958
  category: "ai-technical",
22009
21959
  words: ["api", "tutorial", "benchmark", "architecture", "sdk", "cli", "quantization", "inference", "fine-tun"]
@@ -22021,13 +21971,28 @@ var CATEGORY_KEYWORDS = [
22021
21971
  "\u4E0A\u7EBF",
22022
21972
  "\u63A8\u51FA",
22023
21973
  "\u5F00\u6E90",
21974
+ "ai",
21975
+ "\u4EBA\u5DE5\u667A\u80FD",
21976
+ "\u5927\u6A21\u578B",
22024
21977
  "sora",
22025
21978
  "gpt",
21979
+ "chatgpt",
22026
21980
  "claude",
22027
21981
  "gemini",
22028
21982
  "llama",
22029
21983
  "grok",
22030
- "copilot"
21984
+ "copilot",
21985
+ "openai",
21986
+ "anthropic",
21987
+ "deepseek",
21988
+ "qwen",
21989
+ "vllm",
21990
+ "glm",
21991
+ "mistral",
21992
+ "nvidia",
21993
+ "\u82F1\u4F1F\u8FBE",
21994
+ "huawei",
21995
+ "\u534E\u4E3A"
22031
21996
  ]
22032
21997
  },
22033
21998
  {
@@ -22051,6 +22016,9 @@ var CATEGORY_KEYWORDS = [
22051
22016
  ];
22052
22017
  var IMPORTANCE_BASE = { aihot: 4, rss: 3, hackernews: 3 };
22053
22018
  var DEFAULT_IMPORTANCE = 2;
22019
+ function planAuditOutPath(outputPath) {
22020
+ return outputPath.endsWith(".json") ? `${outputPath.slice(0, -".json".length)}.audit.json` : `${outputPath}.audit.json`;
22021
+ }
22054
22022
  function docTimestamp(doc2) {
22055
22023
  const meta3 = asRecord(doc2.metadata);
22056
22024
  for (const key of ["publishedAt", "discoveredAt"]) {
@@ -22061,9 +22029,9 @@ function docTimestamp(doc2) {
22061
22029
  return t;
22062
22030
  }
22063
22031
  }
22064
- const date6 = meta3.date;
22065
- if (typeof date6 === "string" && /^\d{4}-\d{2}-\d{2}/.test(date6.trim())) {
22066
- return Date.parse(date6.trim().slice(0, 10));
22032
+ const date5 = meta3.date;
22033
+ if (typeof date5 === "string" && /^\d{4}-\d{2}-\d{2}/.test(date5.trim())) {
22034
+ return Date.parse(date5.trim().slice(0, 10));
22067
22035
  }
22068
22036
  return null;
22069
22037
  }
@@ -22154,10 +22122,15 @@ function classifyCategory(doc2) {
22154
22122
  if (hit)
22155
22123
  return hit;
22156
22124
  }
22157
- if (NON_AI_SOURCES.has(typeof meta3.source === "string" ? meta3.source : ""))
22125
+ const source = typeof meta3.source === "string" ? meta3.source : "";
22126
+ if (NON_AI_SOURCES.has(source))
22158
22127
  return "non-ai";
22159
22128
  const title = (doc2.title ?? "").toLowerCase();
22160
22129
  const bodyHead = (doc2.body ?? "").slice(0, 200).toLowerCase();
22130
+ if (JUNK_KEYWORDS.some((w) => matchesKeyword(title, w) || matchesKeyword(bodyHead, w)))
22131
+ return "non-ai";
22132
+ if (AI_DEFAULT_SOURCES.has(source))
22133
+ return "ai-news";
22161
22134
  for (const { category, words } of CATEGORY_KEYWORDS) {
22162
22135
  if (words.some((w) => matchesKeyword(title, w) || matchesKeyword(bodyHead, w)))
22163
22136
  return category;
@@ -22166,8 +22139,9 @@ function classifyCategory(doc2) {
22166
22139
  }
22167
22140
  function scoreDimensions(doc2, planDate) {
22168
22141
  const meta3 = asRecord(doc2.metadata);
22169
- let quality = 1 + Math.min(4, Math.round((doc2.body ?? "").length / 1500));
22170
- if (doc2.sourceUri)
22142
+ const bodyLen = (doc2.body ?? "").length;
22143
+ let quality = bodyLen < STUB_BODY_FLOOR ? 1 : 1 + Math.min(4, Math.round(bodyLen / 1500));
22144
+ if (doc2.sourceUri && bodyLen >= STUB_BODY_FLOOR)
22171
22145
  quality = Math.min(5, quality + 1);
22172
22146
  const source = typeof meta3.source === "string" ? meta3.source : "";
22173
22147
  let importance = IMPORTANCE_BASE[source] ?? DEFAULT_IMPORTANCE;
@@ -22200,6 +22174,7 @@ function planScore(doc2) {
22200
22174
  }
22201
22175
  function planEpisode(docs, options) {
22202
22176
  const planDate = options.date ?? new Date().toISOString().slice(0, 10);
22177
+ const rows = options.audit ? new Map : null;
22203
22178
  const byUrl = new Map;
22204
22179
  const scored = [];
22205
22180
  for (const doc2 of docs) {
@@ -22212,9 +22187,25 @@ function planEpisode(docs, options) {
22212
22187
  scores: scoreDimensions(doc2, planDate)
22213
22188
  }
22214
22189
  };
22190
+ const meta3 = asRecord(cleaned.metadata);
22191
+ rows?.set(cleaned, {
22192
+ id: doc2.id,
22193
+ source: sourceOf(doc2),
22194
+ title: doc2.title ?? "",
22195
+ category: meta3.category,
22196
+ scores: meta3.scores,
22197
+ planScore: null,
22198
+ disposition: "gate"
22199
+ });
22215
22200
  if (!passesGates(cleaned, planDate))
22216
22201
  continue;
22217
- const record2 = { doc: cleaned, score: planScore(cleaned), mergedFrom: [] };
22202
+ const score = planScore(cleaned);
22203
+ const row = rows?.get(cleaned);
22204
+ if (row) {
22205
+ row.planScore = score;
22206
+ row.disposition = "topN";
22207
+ }
22208
+ const record2 = { doc: cleaned, score, mergedFrom: [] };
22218
22209
  const urlKey = normalizeUrl(doc2.sourceUri);
22219
22210
  if (urlKey) {
22220
22211
  const existing = byUrl.get(urlKey);
@@ -22226,6 +22217,9 @@ function planEpisode(docs, options) {
22226
22217
  title: loser.doc.title ?? "",
22227
22218
  url: loser.doc.sourceUri ?? null
22228
22219
  });
22220
+ const loserRow = rows?.get(loser.doc);
22221
+ if (loserRow)
22222
+ loserRow.disposition = "url-merge";
22229
22223
  if (winner !== existing) {
22230
22224
  existing.doc = winner.doc;
22231
22225
  existing.score = winner.score;
@@ -22257,6 +22251,9 @@ function planEpisode(docs, options) {
22257
22251
  title: loser.doc.title ?? "",
22258
22252
  url: loser.doc.sourceUri ?? null
22259
22253
  });
22254
+ const loserRow = rows?.get(loser.doc);
22255
+ if (loserRow)
22256
+ loserRow.disposition = "title-merge";
22260
22257
  absorbed.add(loser);
22261
22258
  }
22262
22259
  }
@@ -22266,13 +22263,22 @@ function planEpisode(docs, options) {
22266
22263
  for (const record2 of candidates) {
22267
22264
  const source = sourceOf(record2.doc);
22268
22265
  const count = perSource.get(source) ?? 0;
22269
- if (count >= PER_SOURCE_CAP)
22266
+ if (count >= PER_SOURCE_CAP) {
22267
+ const row2 = rows?.get(record2.doc);
22268
+ if (row2)
22269
+ row2.disposition = "cap";
22270
22270
  continue;
22271
+ }
22271
22272
  perSource.set(source, count + 1);
22272
22273
  selected.push(record2);
22274
+ const row = rows?.get(record2.doc);
22275
+ if (row)
22276
+ row.disposition = "selected";
22273
22277
  if (selected.length >= Math.max(1, options.maxItems))
22274
22278
  break;
22275
22279
  }
22280
+ if (rows)
22281
+ options.audit?.push(...rows.values());
22276
22282
  return selected.map((r) => {
22277
22283
  const meta3 = asRecord(r.doc.metadata);
22278
22284
  const ascii = asciiRatio(r.doc.title ?? "");
@@ -22295,7 +22301,7 @@ function sourceOf(doc2) {
22295
22301
  const meta3 = asRecord(doc2.metadata);
22296
22302
  return typeof meta3.source === "string" ? meta3.source : "unknown";
22297
22303
  }
22298
- function renderPlanMarkdown(docs, date6) {
22304
+ function renderPlanMarkdown(docs, date5) {
22299
22305
  const items = docs.map((doc2, i) => {
22300
22306
  const meta3 = asRecord(doc2.metadata);
22301
22307
  const parts = [
@@ -22309,25 +22315,25 @@ function renderPlanMarkdown(docs, date6) {
22309
22315
  }).join(`
22310
22316
 
22311
22317
  `);
22312
- return `# \u6BCF\u65E5 AI \u64AD\u5BA2\u9009\u7A3F\u8BA1\u5212 \u2014 ${date6}
22318
+ return `# \u6BCF\u65E5 AI \u64AD\u5BA2\u9009\u7A3F\u8BA1\u5212 \u2014 ${date5}
22313
22319
 
22314
22320
  \u672C\u671F\u5171 ${docs.length} \u6761\uFF08\u8BC4\u5206/\u53BB\u91CD/\u6807\u8BB0\u540E\u7CBE\u9009\uFF09\u3002
22315
22321
 
22316
22322
  ${items}
22317
22323
  `;
22318
22324
  }
22319
- function docsToContent(docs, date6) {
22320
- const planned = planEpisode(docs, { maxItems: maxItemsFromEnv(), date: date6 });
22321
- return planContent(planned, date6);
22325
+ function docsToContent(docs, date5, audit) {
22326
+ const planned = planEpisode(docs, { maxItems: maxItemsFromEnv(), date: date5, audit });
22327
+ return planContent(planned, date5);
22322
22328
  }
22323
- function planContent(docs, date6) {
22329
+ function planContent(docs, date5) {
22324
22330
  return ContentSchema.parse({
22325
- title: `\u6BCF\u65E5 AI \u64AD\u5BA2\u9009\u7A3F\u8BA1\u5212 \u2014 ${date6}`,
22326
- body: renderPlanMarkdown(docs, date6),
22331
+ title: `\u6BCF\u65E5 AI \u64AD\u5BA2\u9009\u7A3F\u8BA1\u5212 \u2014 ${date5}`,
22332
+ body: renderPlanMarkdown(docs, date5),
22327
22333
  format: "markdown",
22328
22334
  metadata: {
22329
22335
  generator: "kk:episode-plan",
22330
- date: date6,
22336
+ date: date5,
22331
22337
  doc_count: docs.length,
22332
22338
  docs
22333
22339
  }
@@ -22347,7 +22353,7 @@ function resolvePlanDate() {
22347
22353
  var MECE_CATEGORIES = ["ai-news", "ai-technical", "ai-research", "ai-industry", "non-ai"];
22348
22354
  var QC_DIMENSIONS = ["quality", "importance", "urgency", "impact"];
22349
22355
  var DEFAULT_FILTER_CONFIG = {
22350
- categories: ["ai-news", "ai-industry"],
22356
+ categories: ["ai-news", "ai-technical", "ai-research", "ai-industry"],
22351
22357
  minQuality: 2,
22352
22358
  minImportance: 3,
22353
22359
  minUrgency: 2,
@@ -22441,8 +22447,10 @@ async function processGeneratorIO(inputPath, outputPath, mode = "plan") {
22441
22447
  }
22442
22448
  async function processPlanIO(inputPath, outputPath) {
22443
22449
  const docs = DocListSchema.parse(await readJsonFile(inputPath));
22444
- const content = docsToContent(docs, resolvePlanDate());
22450
+ const audit = [];
22451
+ const content = docsToContent(docs, resolvePlanDate(), audit);
22445
22452
  await atomicWrite(outputPath, content);
22453
+ await atomicWrite(planAuditOutPath(outputPath), { date: resolvePlanDate(), total: docs.length, rows: audit });
22446
22454
  return content;
22447
22455
  }
22448
22456
  async function processFilterIO(inputPath, outputPath) {
@@ -22492,6 +22500,7 @@ export {
22492
22500
  processGeneratorIO,
22493
22501
  planScore,
22494
22502
  planEpisode,
22503
+ planAuditOutPath,
22495
22504
  normalizeUrl,
22496
22505
  main2 as main,
22497
22506
  filterConfigFromEnv,