akm-cli 0.9.0-beta.2 → 0.9.0-beta.27

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 (120) hide show
  1. package/CHANGELOG.md +660 -0
  2. package/dist/assets/prompts/consolidate-system.md +23 -0
  3. package/dist/assets/prompts/contradiction-judge.md +33 -0
  4. package/dist/assets/prompts/distill-knowledge-system.md +22 -0
  5. package/dist/assets/prompts/distill-lesson-system.md +36 -0
  6. package/dist/assets/prompts/extract-session.md +5 -1
  7. package/dist/assets/prompts/graph-extract-system.md +1 -0
  8. package/dist/assets/prompts/memory-infer-system.md +1 -0
  9. package/dist/assets/prompts/memory-infer-user.md +5 -0
  10. package/dist/assets/prompts/metadata-enhance-system.md +1 -0
  11. package/dist/assets/prompts/procedural-system.md +44 -0
  12. package/dist/assets/prompts/recombine-system.md +40 -0
  13. package/dist/assets/prompts/staleness-detect-system.md +6 -0
  14. package/dist/assets/prompts/validate-summary-judge.md +1 -0
  15. package/dist/assets/templates/html/default.html +78 -0
  16. package/dist/assets/templates/html/health.html +730 -0
  17. package/dist/assets/templates/html/vendor/echarts.min.js +45 -0
  18. package/dist/cli/shared.js +21 -5
  19. package/dist/cli.js +47 -5
  20. package/dist/commands/agent/contribute-cli.js +16 -3
  21. package/dist/commands/feedback-cli.js +15 -6
  22. package/dist/commands/graph/graph.js +75 -71
  23. package/dist/commands/health/checks.js +48 -0
  24. package/dist/commands/health/html-report.js +790 -0
  25. package/dist/commands/health.js +478 -15
  26. package/dist/commands/improve/calibration.js +161 -0
  27. package/dist/commands/improve/consolidate.js +634 -111
  28. package/dist/commands/improve/dedup.js +482 -0
  29. package/dist/commands/improve/distill.js +145 -69
  30. package/dist/commands/improve/encoding-salience.js +205 -0
  31. package/dist/commands/improve/extract-cli.js +115 -1
  32. package/dist/commands/improve/extract-prompt.js +33 -2
  33. package/dist/commands/improve/extract-watch.js +140 -0
  34. package/dist/commands/improve/extract.js +280 -35
  35. package/dist/commands/improve/feedback-valence.js +54 -0
  36. package/dist/commands/improve/homeostatic.js +467 -0
  37. package/dist/commands/improve/improve-auto-accept.js +139 -6
  38. package/dist/commands/improve/improve-profiles.js +12 -0
  39. package/dist/commands/improve/improve.js +2079 -608
  40. package/dist/commands/improve/memory/memory-contradiction-detect.js +23 -28
  41. package/dist/commands/improve/outcome-loop.js +256 -0
  42. package/dist/commands/improve/proactive-maintenance.js +87 -0
  43. package/dist/commands/improve/procedural.js +409 -0
  44. package/dist/commands/improve/recombine.js +488 -0
  45. package/dist/commands/improve/reflect-noise.js +0 -0
  46. package/dist/commands/improve/reflect.js +51 -1
  47. package/dist/commands/improve/related-sessions.js +120 -0
  48. package/dist/commands/improve/salience.js +386 -0
  49. package/dist/commands/improve/triage.js +95 -0
  50. package/dist/commands/lint/agent-linter.js +19 -24
  51. package/dist/commands/lint/base-linter.js +173 -60
  52. package/dist/commands/lint/command-linter.js +19 -24
  53. package/dist/commands/lint/env-key-rules.js +34 -1
  54. package/dist/commands/lint/fact-linter.js +39 -0
  55. package/dist/commands/lint/index.js +31 -13
  56. package/dist/commands/lint/memory-linter.js +1 -1
  57. package/dist/commands/lint/registry.js +7 -2
  58. package/dist/commands/lint/task-linter.js +3 -3
  59. package/dist/commands/lint/workflow-linter.js +26 -1
  60. package/dist/commands/proposal/drain.js +73 -6
  61. package/dist/commands/proposal/proposal-cli.js +22 -10
  62. package/dist/commands/proposal/proposal.js +17 -1
  63. package/dist/commands/proposal/validators/proposals.js +369 -329
  64. package/dist/commands/read/curate.js +344 -80
  65. package/dist/commands/read/search-cli.js +7 -0
  66. package/dist/commands/read/search.js +1 -0
  67. package/dist/commands/read/show.js +67 -2
  68. package/dist/commands/remember.js +6 -2
  69. package/dist/commands/sources/installed-stashes.js +5 -1
  70. package/dist/commands/sources/stash-cli.js +10 -2
  71. package/dist/core/asset/asset-registry.js +2 -0
  72. package/dist/core/asset/asset-spec.js +14 -0
  73. package/dist/core/asset/frontmatter.js +166 -167
  74. package/dist/core/asset/markdown.js +8 -0
  75. package/dist/core/config/config-schema.js +255 -2
  76. package/dist/core/config/config.js +2 -2
  77. package/dist/core/logs-db.js +305 -0
  78. package/dist/core/paths.js +3 -0
  79. package/dist/core/state-db.js +706 -42
  80. package/dist/indexer/db/db.js +364 -38
  81. package/dist/indexer/db/graph-db.js +129 -86
  82. package/dist/indexer/ensure-index.js +152 -17
  83. package/dist/indexer/graph/graph-boost.js +51 -41
  84. package/dist/indexer/graph/graph-extraction.js +203 -3
  85. package/dist/indexer/index-writer-lock.js +99 -0
  86. package/dist/indexer/indexer.js +114 -111
  87. package/dist/indexer/passes/memory-inference.js +71 -25
  88. package/dist/indexer/passes/staleness-detect.js +2 -5
  89. package/dist/indexer/search/db-search.js +15 -4
  90. package/dist/indexer/search/ranking-contributors.js +22 -0
  91. package/dist/indexer/search/ranking.js +4 -0
  92. package/dist/indexer/walk/matchers.js +9 -0
  93. package/dist/integrations/agent/prompts.js +1 -0
  94. package/dist/integrations/harnesses/claude/session-log.js +27 -5
  95. package/dist/integrations/harnesses/opencode/session-log.js +9 -0
  96. package/dist/integrations/session-logs/index.js +16 -0
  97. package/dist/llm/client.js +38 -4
  98. package/dist/llm/embedder.js +27 -3
  99. package/dist/llm/embedders/local.js +66 -2
  100. package/dist/llm/graph-extract.js +2 -1
  101. package/dist/llm/memory-infer.js +4 -8
  102. package/dist/llm/metadata-enhance.js +9 -1
  103. package/dist/llm/usage-persist.js +77 -0
  104. package/dist/llm/usage-telemetry.js +103 -0
  105. package/dist/output/context.js +3 -2
  106. package/dist/output/html-render.js +73 -0
  107. package/dist/output/renderers.js +73 -1
  108. package/dist/output/shapes/curate.js +14 -2
  109. package/dist/output/shapes/helpers.js +17 -1
  110. package/dist/output/text/helpers.js +78 -1
  111. package/dist/runtime.js +25 -1
  112. package/dist/scripts/migrate-storage.js +1262 -591
  113. package/dist/scripts/migrations/import-fs-improve-runs-to-db.js +485 -270
  114. package/dist/sources/providers/tar-utils.js +16 -8
  115. package/dist/storage/sqlite-pragmas.js +146 -0
  116. package/dist/tasks/runner.js +99 -16
  117. package/dist/workflows/db.js +5 -2
  118. package/dist/workflows/validate-summary.js +2 -7
  119. package/docs/data-and-telemetry.md +1 -0
  120. package/package.json +9 -6
@@ -34,9 +34,35 @@ var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports,
34
34
  var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
35
35
  var __require = import.meta.require;
36
36
 
37
+ // src/core/warn.ts
38
+ import fs from "fs";
39
+ function appendToLogFile(level, args) {
40
+ if (!logFilePath)
41
+ return;
42
+ const ts = new Date().toISOString();
43
+ const msg = args.map((a) => typeof a === "string" ? a : JSON.stringify(a)).join(" ");
44
+ try {
45
+ fs.appendFileSync(logFilePath, `[${ts}] [${level}] ${msg}
46
+ `);
47
+ } catch (e) {
48
+ process.stderr.write(`[akm:warn] log-file write failed (${logFilePath}): ${e}
49
+ `);
50
+ process.stderr.write(`[${ts}] [${level}] ${msg}
51
+ `);
52
+ }
53
+ }
54
+ function warn(...args) {
55
+ appendToLogFile("WARN", args);
56
+ if (!quiet) {
57
+ console.warn(...args);
58
+ }
59
+ }
60
+ var quiet = false, logFilePath;
61
+ var init_warn = () => {};
62
+
37
63
  // node_modules/dotenv/lib/main.js
38
64
  var require_main = __commonJS((exports, module) => {
39
- var fs = __require("fs");
65
+ var fs2 = __require("fs");
40
66
  var path = __require("path");
41
67
  var os = __require("os");
42
68
  var crypto = __require("crypto");
@@ -170,7 +196,7 @@ var require_main = __commonJS((exports, module) => {
170
196
  if (options && options.path && options.path.length > 0) {
171
197
  if (Array.isArray(options.path)) {
172
198
  for (const filepath of options.path) {
173
- if (fs.existsSync(filepath)) {
199
+ if (fs2.existsSync(filepath)) {
174
200
  possibleVaultPath = filepath.endsWith(".vault") ? filepath : `${filepath}.vault`;
175
201
  }
176
202
  }
@@ -180,7 +206,7 @@ var require_main = __commonJS((exports, module) => {
180
206
  } else {
181
207
  possibleVaultPath = path.resolve(process.cwd(), ".env.vault");
182
208
  }
183
- if (fs.existsSync(possibleVaultPath)) {
209
+ if (fs2.existsSync(possibleVaultPath)) {
184
210
  return possibleVaultPath;
185
211
  }
186
212
  return null;
@@ -190,8 +216,8 @@ var require_main = __commonJS((exports, module) => {
190
216
  }
191
217
  function _configVault(options) {
192
218
  const debug = parseBoolean(process.env.DOTENV_CONFIG_DEBUG || options && options.debug);
193
- const quiet = parseBoolean(process.env.DOTENV_CONFIG_QUIET || options && options.quiet);
194
- if (debug || !quiet) {
219
+ const quiet2 = parseBoolean(process.env.DOTENV_CONFIG_QUIET || options && options.quiet);
220
+ if (debug || !quiet2) {
195
221
  _log("loading env from encrypted .env.vault");
196
222
  }
197
223
  const parsed = DotenvModule._parseVault(options);
@@ -210,7 +236,7 @@ var require_main = __commonJS((exports, module) => {
210
236
  processEnv = options.processEnv;
211
237
  }
212
238
  let debug = parseBoolean(processEnv.DOTENV_CONFIG_DEBUG || options && options.debug);
213
- let quiet = parseBoolean(processEnv.DOTENV_CONFIG_QUIET || options && options.quiet);
239
+ let quiet2 = parseBoolean(processEnv.DOTENV_CONFIG_QUIET || options && options.quiet);
214
240
  if (options && options.encoding) {
215
241
  encoding = options.encoding;
216
242
  } else {
@@ -233,7 +259,7 @@ var require_main = __commonJS((exports, module) => {
233
259
  const parsedAll = {};
234
260
  for (const path2 of optionPaths) {
235
261
  try {
236
- const parsed = DotenvModule.parse(fs.readFileSync(path2, { encoding }));
262
+ const parsed = DotenvModule.parse(fs2.readFileSync(path2, { encoding }));
237
263
  DotenvModule.populate(parsedAll, parsed, options);
238
264
  } catch (e) {
239
265
  if (debug) {
@@ -244,8 +270,8 @@ var require_main = __commonJS((exports, module) => {
244
270
  }
245
271
  const populated = DotenvModule.populate(processEnv, parsedAll, options);
246
272
  debug = parseBoolean(processEnv.DOTENV_CONFIG_DEBUG || debug);
247
- quiet = parseBoolean(processEnv.DOTENV_CONFIG_QUIET || quiet);
248
- if (debug || !quiet) {
273
+ quiet2 = parseBoolean(processEnv.DOTENV_CONFIG_QUIET || quiet2);
274
+ if (debug || !quiet2) {
249
275
  const keysCount = Object.keys(populated).length;
250
276
  const shortPaths = [];
251
277
  for (const filePath of optionPaths) {
@@ -412,7 +438,7 @@ var init_errors = __esm(() => {
412
438
  });
413
439
 
414
440
  // src/commands/env/env.ts
415
- import fs from "fs";
441
+ import fs2 from "fs";
416
442
  function scanKeys(text) {
417
443
  const keys = [];
418
444
  const seen = new Set;
@@ -439,9 +465,9 @@ function scanComments(text) {
439
465
  return comments;
440
466
  }
441
467
  function listKeys(envPath) {
442
- if (!fs.existsSync(envPath))
468
+ if (!fs2.existsSync(envPath))
443
469
  return { keys: [], comments: [] };
444
- const text = fs.readFileSync(envPath, "utf8");
470
+ const text = fs2.readFileSync(envPath, "utf8");
445
471
  return { keys: scanKeys(text), comments: scanComments(text) };
446
472
  }
447
473
  var import_dotenv, ASSIGN_RE;
@@ -452,251 +478,6 @@ var init_env = __esm(() => {
452
478
  ASSIGN_RE = /^\s*(?:export\s+)?([A-Za-z_][A-Za-z0-9_]*)\s*=/;
453
479
  });
454
480
 
455
- // src/core/asset/frontmatter.ts
456
- function parseFrontmatter(raw) {
457
- const parsedBlock = parseFrontmatterBlock(raw);
458
- if (!parsedBlock) {
459
- return { data: {}, content: raw, frontmatter: null, bodyStartLine: 1 };
460
- }
461
- const data = {};
462
- let currentKey = null;
463
- let mode = "scalar";
464
- let nested = null;
465
- let currentList = null;
466
- let blockLines = null;
467
- let blockChomping = "clip";
468
- const flushPending = () => {
469
- if (mode === "pending" && currentKey !== null) {
470
- data[currentKey] = "";
471
- }
472
- };
473
- const flushBlock = () => {
474
- if (mode !== "block" || currentKey === null || blockLines === null)
475
- return;
476
- const deindented = blockLines.map((l) => l.startsWith(" ") ? l.slice(2) : l);
477
- if (blockChomping === "keep") {
478
- data[currentKey] = deindented.join(`
479
- `);
480
- } else if (blockChomping === "strip") {
481
- data[currentKey] = deindented.join(`
482
- `).replace(/\n+$/, "");
483
- } else {
484
- data[currentKey] = `${deindented.join(`
485
- `).replace(/\n+$/, "")}
486
- `;
487
- }
488
- };
489
- for (const line of parsedBlock.frontmatter.split(/\r?\n/)) {
490
- if (mode === "block") {
491
- if (line.startsWith(" ") || line === "") {
492
- blockLines.push(line);
493
- continue;
494
- }
495
- flushBlock();
496
- mode = "scalar";
497
- blockLines = null;
498
- }
499
- const seqItem = line.match(/^(?: {2})?- (.*)$/);
500
- if (seqItem && currentKey !== null && (mode === "list" || mode === "pending")) {
501
- if (mode === "pending") {
502
- currentList = [];
503
- data[currentKey] = currentList;
504
- mode = "list";
505
- }
506
- currentList.push(parseYamlScalar(seqItem[1].trim()));
507
- continue;
508
- }
509
- if (mode === "scalar" && currentKey !== null && /^ {2}\S/.test(line)) {
510
- data[currentKey] = `${String(data[currentKey])} ${line.trim()}`;
511
- continue;
512
- }
513
- const indented = line.match(/^ {2}(\w[\w-]*):\s*(.+)$/);
514
- if (indented && currentKey !== null && (mode === "object" || mode === "pending")) {
515
- if (mode === "pending") {
516
- nested = {};
517
- data[currentKey] = nested;
518
- mode = "object";
519
- }
520
- nested[indented[1]] = parseYamlScalar(indented[2].trim());
521
- continue;
522
- }
523
- const top = line.match(/^(\w[\w-]*):\s*(.*)$/);
524
- if (!top) {
525
- continue;
526
- }
527
- flushPending();
528
- currentKey = top[1];
529
- const value = top[2].trim();
530
- if (value === "|" || value === "|-" || value === "|+") {
531
- mode = "block";
532
- blockLines = [];
533
- blockChomping = value === "|-" ? "strip" : value === "|+" ? "keep" : "clip";
534
- nested = null;
535
- currentList = null;
536
- } else if (value === "") {
537
- mode = "pending";
538
- nested = null;
539
- currentList = null;
540
- } else if (value.startsWith("[") && value.endsWith("]")) {
541
- mode = "list";
542
- nested = null;
543
- currentList = null;
544
- currentList = parseFlowArray(value);
545
- data[currentKey] = currentList;
546
- } else {
547
- mode = "scalar";
548
- nested = null;
549
- currentList = null;
550
- data[currentKey] = parseYamlScalar(value);
551
- }
552
- }
553
- if (mode === "block") {
554
- flushBlock();
555
- }
556
- flushPending();
557
- return {
558
- data,
559
- content: parsedBlock.content,
560
- frontmatter: parsedBlock.frontmatter,
561
- bodyStartLine: parsedBlock.bodyStartLine
562
- };
563
- }
564
- function parseFlowArray(value) {
565
- const inner = value.slice(1, -1).trim();
566
- if (!inner)
567
- return [];
568
- return inner.split(",").map((item) => parseYamlScalar(item.trim()));
569
- }
570
- function parseFrontmatterBlock(raw) {
571
- const match = raw.match(/^---\r?\n([\s\S]*?)\r?\n---(?:\r\n|\r|\n|$)([\s\S]*)$/);
572
- if (!match)
573
- return null;
574
- const frontmatter = match[1].replace(/\r/g, "");
575
- const content = match[2];
576
- return {
577
- frontmatter,
578
- content,
579
- bodyStartLine: countLines(raw.slice(0, match[0].length - match[2].length)) + 1
580
- };
581
- }
582
- function countLines(text) {
583
- if (text.length === 0)
584
- return 0;
585
- return text.split(/\r?\n/).length - 1;
586
- }
587
- function parseYamlScalar(value) {
588
- if (value === "")
589
- return "";
590
- if (value === "true")
591
- return true;
592
- if (value === "false")
593
- return false;
594
- const asNumber = Number(value);
595
- if (!Number.isNaN(asNumber))
596
- return asNumber;
597
- if (value.startsWith('"') && value.endsWith('"') || value.startsWith("'") && value.endsWith("'")) {
598
- return value.slice(1, -1);
599
- }
600
- return value;
601
- }
602
-
603
- // src/core/asset/markdown.ts
604
- function parseMarkdownToc(content) {
605
- const lines = content.split(/\r?\n/);
606
- const headings = [];
607
- const parsed = parseFrontmatter(content);
608
- const start = parsed.frontmatter ? parsed.bodyStartLine - 1 : 0;
609
- for (let i = start;i < lines.length; i++) {
610
- const match = lines[i].match(/^(#{1,6})\s+(.+)$/);
611
- if (match) {
612
- headings.push({
613
- level: match[1].length,
614
- text: match[2].replace(/\s+#+\s*$/, "").trim(),
615
- line: i + 1
616
- });
617
- }
618
- }
619
- return { headings, totalLines: lines.length };
620
- }
621
- var init_markdown = () => {};
622
-
623
- // src/core/warn.ts
624
- var init_warn = () => {};
625
-
626
- // src/indexer/walk/file-context.ts
627
- var renderers;
628
- var init_file_context = __esm(() => {
629
- init_common();
630
- renderers = new Map;
631
- });
632
-
633
- // src/indexer/passes/metadata-contributors.ts
634
- function registerMetadataContributor(contributor) {
635
- contributors.push(contributor);
636
- }
637
- var contributors;
638
- var init_metadata_contributors = __esm(() => {
639
- contributors = [];
640
- });
641
-
642
- // src/indexer/passes/metadata.ts
643
- import fs2 from "fs";
644
- function extractDescriptionFromComments(filePath) {
645
- let content;
646
- try {
647
- content = fs2.readFileSync(filePath, "utf8");
648
- } catch {
649
- return null;
650
- }
651
- const lines = content.split(/\r?\n/).slice(0, 50);
652
- const blockStart = lines.findIndex((l) => /^\s*\/\*\*/.test(l));
653
- if (blockStart >= 0) {
654
- const desc = [];
655
- for (let i = blockStart;i < lines.length; i++) {
656
- const line = lines[i];
657
- if (i > blockStart && /\*\//.test(line))
658
- break;
659
- const cleaned = line.replace(/^\s*\/?\*\*?\s?/, "").replace(/\*\/\s*$/, "").trim();
660
- if (cleaned)
661
- desc.push(cleaned);
662
- }
663
- if (desc.length > 0)
664
- return desc.join(" ");
665
- }
666
- let start = 0;
667
- if (lines[0]?.startsWith("#!"))
668
- start = 1;
669
- const hashLines = [];
670
- for (let i = start;i < lines.length; i++) {
671
- const line = lines[i].trim();
672
- if (line.startsWith("#") && !line.startsWith("#!")) {
673
- hashLines.push(line.replace(/^#+\s*/, "").trim());
674
- } else if (line === "") {} else {
675
- break;
676
- }
677
- }
678
- if (hashLines.length > 0)
679
- return hashLines.join(" ");
680
- return null;
681
- }
682
- var KNOWN_QUALITY_VALUES, warnedUnknownQualityValues, WIKI_INFRA_FILES;
683
- var init_metadata = __esm(() => {
684
- init_asset_spec();
685
- init_common();
686
- init_warn();
687
- init_file_context();
688
- init_metadata_contributors();
689
- KNOWN_QUALITY_VALUES = new Set(["generated", "curated", "enriched", "proposed"]);
690
- warnedUnknownQualityValues = new Set;
691
- WIKI_INFRA_FILES = new Set(["schema.md", "index.md", "log.md"]);
692
- });
693
-
694
- // src/core/asset/asset-ref.ts
695
- var init_asset_ref = __esm(() => {
696
- init_common();
697
- init_errors();
698
- });
699
-
700
481
  // node_modules/yaml/dist/nodes/identity.js
701
482
  var require_identity = __commonJS((exports) => {
702
483
  var ALIAS = Symbol.for("yaml.alias");
@@ -7667,6 +7448,199 @@ var init_dist = __esm(() => {
7667
7448
  $visitAsync = visit.visitAsync;
7668
7449
  });
7669
7450
 
7451
+ // src/core/asset/frontmatter.ts
7452
+ function parseFrontmatter(raw) {
7453
+ const parsedBlock = parseFrontmatterBlock(raw);
7454
+ if (!parsedBlock) {
7455
+ return { data: {}, content: raw, frontmatter: null, bodyStartLine: 1 };
7456
+ }
7457
+ let data = {};
7458
+ if (parsedBlock.frontmatter.trim()) {
7459
+ try {
7460
+ const parsed = $parse(parsedBlock.frontmatter);
7461
+ if (parsed !== null && typeof parsed === "object" && !Array.isArray(parsed)) {
7462
+ data = normalizeYamlValues(parsed);
7463
+ }
7464
+ } catch {
7465
+ data = parseFrontmatterLenient(parsedBlock.frontmatter);
7466
+ }
7467
+ }
7468
+ return {
7469
+ data,
7470
+ content: parsedBlock.content,
7471
+ frontmatter: parsedBlock.frontmatter,
7472
+ bodyStartLine: parsedBlock.bodyStartLine
7473
+ };
7474
+ }
7475
+ function normalizeYamlValues(value) {
7476
+ if (value instanceof Date) {
7477
+ const y = value.getUTCFullYear();
7478
+ const m = String(value.getUTCMonth() + 1).padStart(2, "0");
7479
+ const d = String(value.getUTCDate()).padStart(2, "0");
7480
+ return `${y}-${m}-${d}`;
7481
+ }
7482
+ if (value === null)
7483
+ return "";
7484
+ if (Array.isArray(value))
7485
+ return value.map(normalizeYamlValues);
7486
+ if (typeof value === "object") {
7487
+ return Object.fromEntries(Object.entries(value).map(([k, v]) => [k, normalizeYamlValues(v)]));
7488
+ }
7489
+ return value;
7490
+ }
7491
+ function parseFrontmatterLenient(frontmatter) {
7492
+ const data = {};
7493
+ for (const line of frontmatter.split(/\r?\n/)) {
7494
+ const m = line.match(/^([\w][\w-]*):\s*(.*)$/);
7495
+ if (!m)
7496
+ continue;
7497
+ const key = m[1];
7498
+ const rawValue = (m[2] ?? "").trim();
7499
+ try {
7500
+ const singleEntry = $parse(`k: ${rawValue}`);
7501
+ if (singleEntry !== null && typeof singleEntry === "object" && !Array.isArray(singleEntry)) {
7502
+ const v = singleEntry.k;
7503
+ data[key] = v === null || v === undefined ? "" : v;
7504
+ } else {
7505
+ data[key] = rawValue;
7506
+ }
7507
+ } catch {
7508
+ data[key] = rawValue;
7509
+ }
7510
+ }
7511
+ return data;
7512
+ }
7513
+ function parseFrontmatterBlock(raw) {
7514
+ const match = raw.match(/^---\r?\n([\s\S]*?)\r?\n---(?:\r\n|\r|\n|$)([\s\S]*)$/);
7515
+ if (match) {
7516
+ const frontmatter = match[1].replace(/\r/g, "");
7517
+ const content = match[2];
7518
+ return {
7519
+ frontmatter,
7520
+ content,
7521
+ bodyStartLine: countLines(raw.slice(0, match[0].length - match[2].length)) + 1
7522
+ };
7523
+ }
7524
+ const emptyMatch = raw.match(/^---\r?\n---(?:\r\n|\r|\n)([\s\S]*)$/);
7525
+ if (emptyMatch) {
7526
+ return { frontmatter: "", content: emptyMatch[1], bodyStartLine: 3 };
7527
+ }
7528
+ return null;
7529
+ }
7530
+ function countLines(text) {
7531
+ if (text.length === 0)
7532
+ return 0;
7533
+ return text.split(/\r?\n/).length - 1;
7534
+ }
7535
+ var init_frontmatter = __esm(() => {
7536
+ init_dist();
7537
+ });
7538
+
7539
+ // src/core/asset/markdown.ts
7540
+ function parseMarkdownToc(content) {
7541
+ const lines = content.split(/\r?\n/);
7542
+ const headings = [];
7543
+ const parsed = parseFrontmatter(content);
7544
+ const start = parsed.frontmatter ? parsed.bodyStartLine - 1 : 0;
7545
+ let inFence = false;
7546
+ for (let i = start;i < lines.length; i++) {
7547
+ if (/^\s*(`{3,}|~{3,})/.test(lines[i])) {
7548
+ inFence = !inFence;
7549
+ continue;
7550
+ }
7551
+ if (inFence)
7552
+ continue;
7553
+ const match = lines[i].match(/^(#{1,6})\s+(.+)$/);
7554
+ if (match) {
7555
+ headings.push({
7556
+ level: match[1].length,
7557
+ text: match[2].replace(/\s+#+\s*$/, "").trim(),
7558
+ line: i + 1
7559
+ });
7560
+ }
7561
+ }
7562
+ return { headings, totalLines: lines.length };
7563
+ }
7564
+ var init_markdown = __esm(() => {
7565
+ init_frontmatter();
7566
+ });
7567
+
7568
+ // src/indexer/walk/file-context.ts
7569
+ var renderers;
7570
+ var init_file_context = __esm(() => {
7571
+ init_frontmatter();
7572
+ init_common();
7573
+ renderers = new Map;
7574
+ });
7575
+
7576
+ // src/indexer/passes/metadata-contributors.ts
7577
+ function registerMetadataContributor(contributor) {
7578
+ contributors.push(contributor);
7579
+ }
7580
+ var contributors;
7581
+ var init_metadata_contributors = __esm(() => {
7582
+ contributors = [];
7583
+ });
7584
+
7585
+ // src/indexer/passes/metadata.ts
7586
+ import fs3 from "fs";
7587
+ function extractDescriptionFromComments(filePath) {
7588
+ let content;
7589
+ try {
7590
+ content = fs3.readFileSync(filePath, "utf8");
7591
+ } catch {
7592
+ return null;
7593
+ }
7594
+ const lines = content.split(/\r?\n/).slice(0, 50);
7595
+ const blockStart = lines.findIndex((l) => /^\s*\/\*\*/.test(l));
7596
+ if (blockStart >= 0) {
7597
+ const desc = [];
7598
+ for (let i = blockStart;i < lines.length; i++) {
7599
+ const line = lines[i];
7600
+ if (i > blockStart && /\*\//.test(line))
7601
+ break;
7602
+ const cleaned = line.replace(/^\s*\/?\*\*?\s?/, "").replace(/\*\/\s*$/, "").trim();
7603
+ if (cleaned)
7604
+ desc.push(cleaned);
7605
+ }
7606
+ if (desc.length > 0)
7607
+ return desc.join(" ");
7608
+ }
7609
+ let start = 0;
7610
+ if (lines[0]?.startsWith("#!"))
7611
+ start = 1;
7612
+ const hashLines = [];
7613
+ for (let i = start;i < lines.length; i++) {
7614
+ const line = lines[i].trim();
7615
+ if (line.startsWith("#") && !line.startsWith("#!")) {
7616
+ hashLines.push(line.replace(/^#+\s*/, "").trim());
7617
+ } else if (line === "") {} else {
7618
+ break;
7619
+ }
7620
+ }
7621
+ if (hashLines.length > 0)
7622
+ return hashLines.join(" ");
7623
+ return null;
7624
+ }
7625
+ var KNOWN_QUALITY_VALUES, warnedUnknownQualityValues, WIKI_INFRA_FILES;
7626
+ var init_metadata = __esm(() => {
7627
+ init_asset_spec();
7628
+ init_frontmatter();
7629
+ init_common();
7630
+ init_warn();
7631
+ init_file_context();
7632
+ init_metadata_contributors();
7633
+ KNOWN_QUALITY_VALUES = new Set(["generated", "curated", "enriched", "proposed"]);
7634
+ warnedUnknownQualityValues = new Set;
7635
+ WIKI_INFRA_FILES = new Set(["schema.md", "index.md", "log.md"]);
7636
+ });
7637
+
7638
+ // src/core/asset/asset-ref.ts
7639
+ var init_asset_ref = __esm(() => {
7640
+ init_common();
7641
+ init_errors();
7642
+ });
7643
+
7670
7644
  // src/workflows/schema.ts
7671
7645
  var WORKFLOW_SCHEMA_VERSION = 1;
7672
7646
 
@@ -8061,6 +8035,7 @@ function sortErrors(errors2) {
8061
8035
  var WORKFLOW_TITLE_PREFIX = "Workflow:", STEP_PREFIX = "Step:", STEP_ID_LINE, BULLET_LINE, SUBSECTION_INSTRUCTIONS = "Instructions", SUBSECTION_COMPLETION_CRITERIA = "Completion Criteria";
8062
8036
  var init_parser = __esm(() => {
8063
8037
  init_dist();
8038
+ init_frontmatter();
8064
8039
  init_markdown();
8065
8040
  init_validator();
8066
8041
  STEP_ID_LINE = /^Step ID:\s+(.+?)\s*$/;
@@ -8151,6 +8126,25 @@ function applyTocMetadata(entry, ctx) {
8151
8126
  entry.toc = toc.headings;
8152
8127
  } catch {}
8153
8128
  }
8129
+ function applyFactMetadata(entry, ctx) {
8130
+ try {
8131
+ const fm = applyFrontmatterDescriptionAndTags(entry, ctx);
8132
+ const tags = new Set([...entry.tags ?? [], "fact"]);
8133
+ const hints = new Set(entry.searchHints ?? []);
8134
+ const category = asNonEmptyString(fm.category);
8135
+ if (category) {
8136
+ tags.add(category);
8137
+ hints.add(`category:${category}`);
8138
+ }
8139
+ if (fm.pinned === true) {
8140
+ tags.add("pinned");
8141
+ hints.add("pinned");
8142
+ }
8143
+ entry.tags = Array.from(tags).filter(Boolean);
8144
+ if (hints.size > 0)
8145
+ entry.searchHints = Array.from(hints).filter(Boolean);
8146
+ } catch {}
8147
+ }
8154
8148
  function applyFrontmatterDescriptionAndTags(entry, ctx) {
8155
8149
  const parsed = parseFrontmatter(ctx.content());
8156
8150
  const fm = parsed.data;
@@ -8250,6 +8244,7 @@ function applyTaskMetadata(entry, ctx) {
8250
8244
  }
8251
8245
  var init_renderers = __esm(() => {
8252
8246
  init_env();
8247
+ init_frontmatter();
8253
8248
  init_markdown();
8254
8249
  init_common();
8255
8250
  init_metadata();
@@ -8296,6 +8291,11 @@ var init_renderers = __esm(() => {
8296
8291
  appliesTo: ({ rendererName }) => rendererName === "session-md",
8297
8292
  contribute: (entry, ctx) => applySessionMetadata(entry, ctx.renderContext)
8298
8293
  });
8294
+ registerMetadataContributor({
8295
+ name: "fact-md-metadata",
8296
+ appliesTo: ({ rendererName }) => rendererName === "fact-md",
8297
+ contribute: (entry, ctx) => applyFactMetadata(entry, ctx.renderContext)
8298
+ });
8299
8299
  });
8300
8300
 
8301
8301
  // src/core/asset/asset-registry.ts
@@ -8430,6 +8430,12 @@ var init_asset_spec = __esm(() => {
8430
8430
  ...markdownSpec,
8431
8431
  rendererName: "session-md",
8432
8432
  actionBuilder: (ref) => `akm show ${ref} -> read the session summary; follow the \`access\` frontmatter to open the raw log at \`log_path\``
8433
+ },
8434
+ fact: {
8435
+ stashDir: "facts",
8436
+ ...markdownSpec,
8437
+ rendererName: "fact-md",
8438
+ actionBuilder: (ref) => `akm show ${ref} -> read the stash fact and apply it as durable context`
8433
8439
  }
8434
8440
  };
8435
8441
  TYPE_DIRS = Object.fromEntries(Object.entries(ASSET_SPECS_INTERNAL).map(([type, spec]) => [type, spec.stashDir]));
@@ -8498,11 +8504,11 @@ var init_paths = __esm(() => {
8498
8504
  });
8499
8505
 
8500
8506
  // scripts/migrations/import-fs-improve-runs-to-db.ts
8501
- import fs4 from "fs";
8507
+ import fs5 from "fs";
8502
8508
  import path4 from "path";
8503
8509
 
8504
8510
  // src/core/state-db.ts
8505
- import fs3 from "fs";
8511
+ import fs4 from "fs";
8506
8512
  import path3 from "path";
8507
8513
 
8508
8514
  // src/storage/database.ts
@@ -8578,6 +8584,94 @@ function runMigrations(db, migrations, opts) {
8578
8584
  }
8579
8585
  }
8580
8586
 
8587
+ // src/storage/sqlite-pragmas.ts
8588
+ init_warn();
8589
+
8590
+ // src/runtime.ts
8591
+ import { createWriteStream, statfsSync } from "fs";
8592
+ import { createRequire as createRequire2 } from "module";
8593
+ var isBun2 = !!process.versions?.bun;
8594
+ var nodeRequire2 = createRequire2(import.meta.url);
8595
+ function statfsType(path) {
8596
+ try {
8597
+ return statfsSync(path).type;
8598
+ } catch {
8599
+ return;
8600
+ }
8601
+ }
8602
+ var mainPath = isBun2 ? bunGlobal().main : process.argv[1];
8603
+ function bunGlobal() {
8604
+ return globalThis.Bun;
8605
+ }
8606
+
8607
+ // src/storage/sqlite-pragmas.ts
8608
+ var VALID_MODES = new Set(["WAL", "DELETE", "TRUNCATE"]);
8609
+ var warnedInvalid = false;
8610
+ var warnedNetworkFallback = false;
8611
+ function resolveJournalMode(raw) {
8612
+ if (raw === undefined)
8613
+ return "WAL";
8614
+ const normalized = raw.trim().toUpperCase();
8615
+ if (normalized === "")
8616
+ return "WAL";
8617
+ if (VALID_MODES.has(normalized)) {
8618
+ return normalized;
8619
+ }
8620
+ warnInvalidJournalModeOnce(raw);
8621
+ return "WAL";
8622
+ }
8623
+ function resolveConfiguredJournalMode() {
8624
+ return resolveJournalMode(process.env.AKM_SQLITE_JOURNAL_MODE);
8625
+ }
8626
+ function warnInvalidJournalModeOnce(raw) {
8627
+ if (warnedInvalid)
8628
+ return;
8629
+ warnedInvalid = true;
8630
+ warn(`[akm] invalid AKM_SQLITE_JOURNAL_MODE=${JSON.stringify(raw)} \u2014 using WAL (valid: WAL, DELETE, TRUNCATE)`);
8631
+ }
8632
+ var FS_MAGIC_NFS = 26985;
8633
+ var FS_MAGIC_SMB = 20859;
8634
+ var FS_MAGIC_CIFS = 4283649346;
8635
+ var FS_MAGIC_SMB2 = 4266872130;
8636
+ var FS_MAGIC_FUSE = 1702057286;
8637
+ var NETWORK_FS_MAGICS = new Set([
8638
+ FS_MAGIC_NFS,
8639
+ FS_MAGIC_SMB,
8640
+ FS_MAGIC_CIFS,
8641
+ FS_MAGIC_SMB2,
8642
+ FS_MAGIC_FUSE
8643
+ ]);
8644
+ function isNetworkFilesystem(fsType) {
8645
+ if (fsType === undefined)
8646
+ return false;
8647
+ return NETWORK_FS_MAGICS.has(fsType);
8648
+ }
8649
+ function applyStandardPragmas(db, opts = {}) {
8650
+ let mode = resolveConfiguredJournalMode();
8651
+ if (mode === "WAL" && opts.dataDir) {
8652
+ const probe = opts.fsTypeProbe ?? statfsType;
8653
+ if (isNetworkFilesystem(probe(opts.dataDir))) {
8654
+ mode = "DELETE";
8655
+ warnNetworkFallbackOnce(opts.dataDir);
8656
+ }
8657
+ }
8658
+ db.exec("PRAGMA busy_timeout = 30000");
8659
+ db.exec(`PRAGMA journal_mode = ${mode}`);
8660
+ if (opts.foreignKeys !== false) {
8661
+ db.exec("PRAGMA foreign_keys = ON");
8662
+ }
8663
+ if (mode !== "WAL") {
8664
+ db.exec("PRAGMA synchronous = FULL");
8665
+ }
8666
+ return mode;
8667
+ }
8668
+ function warnNetworkFallbackOnce(dataDir) {
8669
+ if (warnedNetworkFallback)
8670
+ return;
8671
+ warnedNetworkFallback = true;
8672
+ warn(`[akm] network filesystem detected at ${dataDir} \u2014 WAL unsupported, using DELETE journal mode`);
8673
+ }
8674
+
8581
8675
  // src/core/assert.ts
8582
8676
  function assertNever(x, context) {
8583
8677
  let serialized;
@@ -8625,13 +8719,11 @@ function getStateDbPath() {
8625
8719
  function openStateDatabase(dbPath) {
8626
8720
  const resolvedPath = dbPath ?? getStateDbPath();
8627
8721
  const dir = path3.dirname(resolvedPath);
8628
- if (!fs3.existsSync(dir)) {
8629
- fs3.mkdirSync(dir, { recursive: true });
8722
+ if (!fs4.existsSync(dir)) {
8723
+ fs4.mkdirSync(dir, { recursive: true });
8630
8724
  }
8631
8725
  const db = openDatabase(resolvedPath);
8632
- db.exec("PRAGMA journal_mode = WAL");
8633
- db.exec("PRAGMA foreign_keys = ON");
8634
- db.exec("PRAGMA busy_timeout = 5000");
8726
+ applyStandardPragmas(db, { dataDir: dir });
8635
8727
  runMigrations2(db);
8636
8728
  return db;
8637
8729
  }
@@ -8706,7 +8798,9 @@ var MIGRATIONS = [
8706
8798
  --
8707
8799
  -- Extensible (metadata_json) columns:
8708
8800
  -- metadata_json TEXT \u2014 JSON object for future proposal fields.
8709
- -- Current fields stored here: sourceRun, review.
8801
+ -- Current fields stored here: sourceRun,
8802
+ -- review, confidence, gateDecision (#577),
8803
+ -- backupContent, eligibilitySource.
8710
8804
  --
8711
8805
  -- ADD COLUMN extension points (future migrations):
8712
8806
  -- ALTER TABLE proposals ADD COLUMN source_run TEXT DEFAULT NULL;
@@ -8893,6 +8987,127 @@ var MIGRATIONS = [
8893
8987
  CREATE INDEX IF NOT EXISTS idx_extract_sessions_processed
8894
8988
  ON extract_sessions_seen(processed_at);
8895
8989
  `
8990
+ },
8991
+ {
8992
+ id: "005-proposal-fs-imports",
8993
+ up: `
8994
+ CREATE TABLE IF NOT EXISTS proposal_fs_imports (
8995
+ stash_dir TEXT PRIMARY KEY,
8996
+ imported_at TEXT NOT NULL,
8997
+ imported_count INTEGER NOT NULL DEFAULT 0
8998
+ );
8999
+ `
9000
+ },
9001
+ {
9002
+ id: "006-proposals-pending-ref-source",
9003
+ up: `
9004
+ CREATE INDEX IF NOT EXISTS idx_proposals_stash_status_ref_source
9005
+ ON proposals(stash_dir, status, ref, source);
9006
+ `
9007
+ },
9008
+ {
9009
+ id: "007-consolidation-judged",
9010
+ up: `
9011
+ CREATE TABLE IF NOT EXISTS consolidation_judged (
9012
+ entry_key TEXT PRIMARY KEY,
9013
+ content_hash TEXT NOT NULL,
9014
+ judged_at TEXT NOT NULL,
9015
+ outcome TEXT NOT NULL
9016
+ );
9017
+ `
9018
+ },
9019
+ {
9020
+ id: "008-body-embeddings",
9021
+ up: `
9022
+ CREATE TABLE IF NOT EXISTS body_embeddings (
9023
+ content_hash TEXT PRIMARY KEY,
9024
+ embedding BLOB NOT NULL,
9025
+ model_id TEXT NOT NULL,
9026
+ created_at INTEGER NOT NULL
9027
+ );
9028
+ `
9029
+ },
9030
+ {
9031
+ id: "009-asset-salience",
9032
+ up: `
9033
+ CREATE TABLE IF NOT EXISTS asset_salience (
9034
+ asset_ref TEXT PRIMARY KEY,
9035
+ encoding_salience REAL NOT NULL DEFAULT 0.5,
9036
+ outcome_salience REAL NOT NULL DEFAULT 0.0,
9037
+ retrieval_salience REAL NOT NULL DEFAULT 0.0,
9038
+ rank_score REAL NOT NULL DEFAULT 0.0,
9039
+ consecutive_no_ops INTEGER NOT NULL DEFAULT 0,
9040
+ updated_at INTEGER NOT NULL DEFAULT 0
9041
+ );
9042
+
9043
+ -- Hot path: sort / filter by rank_score for selector queries.
9044
+ CREATE INDEX IF NOT EXISTS idx_asset_salience_rank
9045
+ ON asset_salience(rank_score DESC);
9046
+ `
9047
+ },
9048
+ {
9049
+ id: "010-asset-outcome",
9050
+ up: `
9051
+ CREATE TABLE IF NOT EXISTS asset_outcome (
9052
+ asset_ref TEXT PRIMARY KEY,
9053
+ last_retrieved_at INTEGER NOT NULL DEFAULT 0,
9054
+ retrieval_count INTEGER NOT NULL DEFAULT 0,
9055
+ expected_retrieval_rate REAL NOT NULL DEFAULT 0.0,
9056
+ negative_feedback_count INTEGER NOT NULL DEFAULT 0,
9057
+ accepted_change_count INTEGER NOT NULL DEFAULT 0,
9058
+ review_pressure INTEGER NOT NULL DEFAULT 0,
9059
+ outcome_score REAL NOT NULL DEFAULT 0.0,
9060
+ updated_at INTEGER NOT NULL DEFAULT 0
9061
+ );
9062
+
9063
+ -- Hot path: sort assets by review_pressure DESC for #613 admission.
9064
+ CREATE INDEX IF NOT EXISTS idx_asset_outcome_review_pressure
9065
+ ON asset_outcome(review_pressure DESC);
9066
+
9067
+ -- Secondary: sort by outcome_score DESC for outcomeSalience reads.
9068
+ CREATE INDEX IF NOT EXISTS idx_asset_outcome_score
9069
+ ON asset_outcome(outcome_score DESC);
9070
+ `
9071
+ },
9072
+ {
9073
+ id: "011-asset-salience-homeostatic-demoted-at",
9074
+ up: `
9075
+ ALTER TABLE asset_salience ADD COLUMN homeostatic_demoted_at INTEGER DEFAULT NULL;
9076
+ `
9077
+ },
9078
+ {
9079
+ id: "012-improve-gate-thresholds",
9080
+ up: `
9081
+ CREATE TABLE IF NOT EXISTS improve_gate_thresholds (
9082
+ phase TEXT NOT NULL PRIMARY KEY,
9083
+ threshold INTEGER NOT NULL,
9084
+ updated_at INTEGER NOT NULL
9085
+ );
9086
+ `
9087
+ },
9088
+ {
9089
+ id: "013-extract-sessions-content-hash",
9090
+ up: `
9091
+ ALTER TABLE extract_sessions_seen ADD COLUMN content_hash TEXT DEFAULT NULL;
9092
+ `
9093
+ },
9094
+ {
9095
+ id: "014-recombine-hypotheses",
9096
+ up: `
9097
+ CREATE TABLE IF NOT EXISTS recombine_hypotheses (
9098
+ hypothesis_ref TEXT PRIMARY KEY,
9099
+ signature TEXT NOT NULL,
9100
+ member_key TEXT NOT NULL,
9101
+ consecutive_count INTEGER NOT NULL DEFAULT 0,
9102
+ first_seen_at TEXT NOT NULL,
9103
+ last_seen_at TEXT NOT NULL,
9104
+ last_run TEXT,
9105
+ promoted_at TEXT,
9106
+ metadata_json TEXT NOT NULL DEFAULT '{}'
9107
+ );
9108
+ CREATE INDEX IF NOT EXISTS idx_recombine_hypotheses_last_seen
9109
+ ON recombine_hypotheses(last_seen_at);
9110
+ `
8896
9111
  }
8897
9112
  ];
8898
9113
  function runMigrations2(db) {
@@ -9001,11 +9216,11 @@ function inferScope(envelope) {
9001
9216
  async function main() {
9002
9217
  const args = parseArgs(process.argv.slice(2));
9003
9218
  const runsRoot = path4.join(args.stashDir, ".akm", "runs");
9004
- if (!fs4.existsSync(runsRoot)) {
9219
+ if (!fs5.existsSync(runsRoot)) {
9005
9220
  console.log(`[import] no legacy runs directory at ${runsRoot}; nothing to do`);
9006
9221
  return;
9007
9222
  }
9008
- const entries = fs4.readdirSync(runsRoot, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => e.name).sort();
9223
+ const entries = fs5.readdirSync(runsRoot, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => e.name).sort();
9009
9224
  if (entries.length === 0) {
9010
9225
  console.log(`[import] ${runsRoot} is empty; nothing to do`);
9011
9226
  return;
@@ -9020,7 +9235,7 @@ async function main() {
9020
9235
  let skippedNoTimestamp = 0;
9021
9236
  for (const id of entries) {
9022
9237
  const resultPath = path4.join(runsRoot, id, "improve-result.json");
9023
- if (!fs4.existsSync(resultPath)) {
9238
+ if (!fs5.existsSync(resultPath)) {
9024
9239
  skippedNoResult++;
9025
9240
  continue;
9026
9241
  }
@@ -9030,7 +9245,7 @@ async function main() {
9030
9245
  }
9031
9246
  let envelope;
9032
9247
  try {
9033
- envelope = JSON.parse(fs4.readFileSync(resultPath, "utf8"));
9248
+ envelope = JSON.parse(fs5.readFileSync(resultPath, "utf8"));
9034
9249
  } catch (err) {
9035
9250
  console.warn(`[import] skipping ${id}: parse failed (${err instanceof Error ? err.message : String(err)})`);
9036
9251
  skippedParseFailed++;
@@ -9096,7 +9311,7 @@ async function main() {
9096
9311
  }
9097
9312
  const ts = new Date().toISOString().replace(/[:.]/g, "-");
9098
9313
  const archiveTarget = path4.join(args.stashDir, ".akm", `runs.archived-${ts}`);
9099
- fs4.renameSync(runsRoot, archiveTarget);
9314
+ fs5.renameSync(runsRoot, archiveTarget);
9100
9315
  console.log(`[import] archived ${runsRoot} \u2192 ${archiveTarget}`);
9101
9316
  }
9102
9317
  main().catch((err) => {