akm-cli 0.9.0-beta.11 → 0.9.0-beta.26

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 (88) hide show
  1. package/CHANGELOG.md +163 -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/health.html +25 -27
  16. package/dist/cli.js +2 -2
  17. package/dist/commands/agent/contribute-cli.js +16 -3
  18. package/dist/commands/feedback-cli.js +48 -44
  19. package/dist/commands/health/html-report.js +140 -16
  20. package/dist/commands/health.js +277 -1
  21. package/dist/commands/improve/calibration.js +161 -0
  22. package/dist/commands/improve/consolidate.js +595 -105
  23. package/dist/commands/improve/dedup.js +482 -0
  24. package/dist/commands/improve/distill.js +119 -64
  25. package/dist/commands/improve/encoding-salience.js +205 -0
  26. package/dist/commands/improve/extract-cli.js +115 -1
  27. package/dist/commands/improve/extract-prompt.js +32 -1
  28. package/dist/commands/improve/extract-watch.js +140 -0
  29. package/dist/commands/improve/extract.js +210 -30
  30. package/dist/commands/improve/feedback-valence.js +54 -0
  31. package/dist/commands/improve/homeostatic.js +467 -0
  32. package/dist/commands/improve/improve-auto-accept.js +80 -7
  33. package/dist/commands/improve/improve-profiles.js +8 -0
  34. package/dist/commands/improve/improve.js +991 -61
  35. package/dist/commands/improve/memory/memory-contradiction-detect.js +23 -28
  36. package/dist/commands/improve/outcome-loop.js +256 -0
  37. package/dist/commands/improve/proactive-maintenance.js +9 -35
  38. package/dist/commands/improve/procedural.js +409 -0
  39. package/dist/commands/improve/recombine.js +488 -0
  40. package/dist/commands/improve/reflect.js +20 -1
  41. package/dist/commands/improve/related-sessions.js +120 -0
  42. package/dist/commands/improve/salience.js +386 -0
  43. package/dist/commands/improve/triage.js +95 -0
  44. package/dist/commands/lint/agent-linter.js +19 -24
  45. package/dist/commands/lint/base-linter.js +173 -60
  46. package/dist/commands/lint/command-linter.js +19 -24
  47. package/dist/commands/lint/env-key-rules.js +34 -1
  48. package/dist/commands/lint/index.js +30 -13
  49. package/dist/commands/lint/memory-linter.js +1 -1
  50. package/dist/commands/lint/registry.js +5 -2
  51. package/dist/commands/lint/task-linter.js +3 -3
  52. package/dist/commands/lint/workflow-linter.js +26 -1
  53. package/dist/commands/proposal/validators/proposals.js +4 -0
  54. package/dist/commands/read/curate.js +284 -86
  55. package/dist/commands/read/search-cli.js +7 -0
  56. package/dist/commands/read/search.js +1 -0
  57. package/dist/commands/sources/installed-stashes.js +5 -1
  58. package/dist/core/asset/frontmatter.js +166 -167
  59. package/dist/core/asset/markdown.js +8 -0
  60. package/dist/core/config/config-schema.js +211 -3
  61. package/dist/core/config/config.js +2 -2
  62. package/dist/core/logs-db.js +4 -3
  63. package/dist/core/state-db.js +555 -29
  64. package/dist/indexer/db/db.js +250 -27
  65. package/dist/indexer/db/graph-db.js +81 -86
  66. package/dist/indexer/graph/graph-boost.js +51 -41
  67. package/dist/indexer/passes/memory-inference.js +10 -3
  68. package/dist/indexer/passes/staleness-detect.js +2 -5
  69. package/dist/indexer/search/db-search.js +15 -4
  70. package/dist/indexer/search/ranking.js +4 -0
  71. package/dist/integrations/harnesses/claude/session-log.js +10 -0
  72. package/dist/integrations/harnesses/opencode/session-log.js +9 -0
  73. package/dist/integrations/session-logs/index.js +16 -0
  74. package/dist/llm/embedder.js +27 -3
  75. package/dist/llm/embedders/local.js +66 -2
  76. package/dist/llm/graph-extract.js +2 -1
  77. package/dist/llm/memory-infer.js +4 -8
  78. package/dist/llm/metadata-enhance.js +9 -1
  79. package/dist/output/shapes/curate.js +14 -2
  80. package/dist/output/text/helpers.js +9 -0
  81. package/dist/runtime.js +25 -1
  82. package/dist/scripts/migrate-storage.js +1025 -567
  83. package/dist/scripts/migrations/import-fs-improve-runs-to-db.js +435 -269
  84. package/dist/storage/sqlite-pragmas.js +146 -0
  85. package/dist/workflows/db.js +3 -4
  86. package/dist/workflows/validate-summary.js +2 -7
  87. package/docs/data-and-telemetry.md +1 -0
  88. package/package.json +5 -4
@@ -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*$/;
@@ -8250,6 +8225,7 @@ function applyTaskMetadata(entry, ctx) {
8250
8225
  }
8251
8226
  var init_renderers = __esm(() => {
8252
8227
  init_env();
8228
+ init_frontmatter();
8253
8229
  init_markdown();
8254
8230
  init_common();
8255
8231
  init_metadata();
@@ -8498,11 +8474,11 @@ var init_paths = __esm(() => {
8498
8474
  });
8499
8475
 
8500
8476
  // scripts/migrations/import-fs-improve-runs-to-db.ts
8501
- import fs4 from "fs";
8477
+ import fs5 from "fs";
8502
8478
  import path4 from "path";
8503
8479
 
8504
8480
  // src/core/state-db.ts
8505
- import fs3 from "fs";
8481
+ import fs4 from "fs";
8506
8482
  import path3 from "path";
8507
8483
 
8508
8484
  // src/storage/database.ts
@@ -8578,6 +8554,94 @@ function runMigrations(db, migrations, opts) {
8578
8554
  }
8579
8555
  }
8580
8556
 
8557
+ // src/storage/sqlite-pragmas.ts
8558
+ init_warn();
8559
+
8560
+ // src/runtime.ts
8561
+ import { createWriteStream, statfsSync } from "fs";
8562
+ import { createRequire as createRequire2 } from "module";
8563
+ var isBun2 = !!process.versions?.bun;
8564
+ var nodeRequire2 = createRequire2(import.meta.url);
8565
+ function statfsType(path) {
8566
+ try {
8567
+ return statfsSync(path).type;
8568
+ } catch {
8569
+ return;
8570
+ }
8571
+ }
8572
+ var mainPath = isBun2 ? bunGlobal().main : process.argv[1];
8573
+ function bunGlobal() {
8574
+ return globalThis.Bun;
8575
+ }
8576
+
8577
+ // src/storage/sqlite-pragmas.ts
8578
+ var VALID_MODES = new Set(["WAL", "DELETE", "TRUNCATE"]);
8579
+ var warnedInvalid = false;
8580
+ var warnedNetworkFallback = false;
8581
+ function resolveJournalMode(raw) {
8582
+ if (raw === undefined)
8583
+ return "WAL";
8584
+ const normalized = raw.trim().toUpperCase();
8585
+ if (normalized === "")
8586
+ return "WAL";
8587
+ if (VALID_MODES.has(normalized)) {
8588
+ return normalized;
8589
+ }
8590
+ warnInvalidJournalModeOnce(raw);
8591
+ return "WAL";
8592
+ }
8593
+ function resolveConfiguredJournalMode() {
8594
+ return resolveJournalMode(process.env.AKM_SQLITE_JOURNAL_MODE);
8595
+ }
8596
+ function warnInvalidJournalModeOnce(raw) {
8597
+ if (warnedInvalid)
8598
+ return;
8599
+ warnedInvalid = true;
8600
+ warn(`[akm] invalid AKM_SQLITE_JOURNAL_MODE=${JSON.stringify(raw)} \u2014 using WAL (valid: WAL, DELETE, TRUNCATE)`);
8601
+ }
8602
+ var FS_MAGIC_NFS = 26985;
8603
+ var FS_MAGIC_SMB = 20859;
8604
+ var FS_MAGIC_CIFS = 4283649346;
8605
+ var FS_MAGIC_SMB2 = 4266872130;
8606
+ var FS_MAGIC_FUSE = 1702057286;
8607
+ var NETWORK_FS_MAGICS = new Set([
8608
+ FS_MAGIC_NFS,
8609
+ FS_MAGIC_SMB,
8610
+ FS_MAGIC_CIFS,
8611
+ FS_MAGIC_SMB2,
8612
+ FS_MAGIC_FUSE
8613
+ ]);
8614
+ function isNetworkFilesystem(fsType) {
8615
+ if (fsType === undefined)
8616
+ return false;
8617
+ return NETWORK_FS_MAGICS.has(fsType);
8618
+ }
8619
+ function applyStandardPragmas(db, opts = {}) {
8620
+ let mode = resolveConfiguredJournalMode();
8621
+ if (mode === "WAL" && opts.dataDir) {
8622
+ const probe = opts.fsTypeProbe ?? statfsType;
8623
+ if (isNetworkFilesystem(probe(opts.dataDir))) {
8624
+ mode = "DELETE";
8625
+ warnNetworkFallbackOnce(opts.dataDir);
8626
+ }
8627
+ }
8628
+ db.exec("PRAGMA busy_timeout = 30000");
8629
+ db.exec(`PRAGMA journal_mode = ${mode}`);
8630
+ if (opts.foreignKeys !== false) {
8631
+ db.exec("PRAGMA foreign_keys = ON");
8632
+ }
8633
+ if (mode !== "WAL") {
8634
+ db.exec("PRAGMA synchronous = FULL");
8635
+ }
8636
+ return mode;
8637
+ }
8638
+ function warnNetworkFallbackOnce(dataDir) {
8639
+ if (warnedNetworkFallback)
8640
+ return;
8641
+ warnedNetworkFallback = true;
8642
+ warn(`[akm] network filesystem detected at ${dataDir} \u2014 WAL unsupported, using DELETE journal mode`);
8643
+ }
8644
+
8581
8645
  // src/core/assert.ts
8582
8646
  function assertNever(x, context) {
8583
8647
  let serialized;
@@ -8625,13 +8689,11 @@ function getStateDbPath() {
8625
8689
  function openStateDatabase(dbPath) {
8626
8690
  const resolvedPath = dbPath ?? getStateDbPath();
8627
8691
  const dir = path3.dirname(resolvedPath);
8628
- if (!fs3.existsSync(dir)) {
8629
- fs3.mkdirSync(dir, { recursive: true });
8692
+ if (!fs4.existsSync(dir)) {
8693
+ fs4.mkdirSync(dir, { recursive: true });
8630
8694
  }
8631
8695
  const db = openDatabase(resolvedPath);
8632
- db.exec("PRAGMA journal_mode = WAL");
8633
- db.exec("PRAGMA foreign_keys = ON");
8634
- db.exec("PRAGMA busy_timeout = 30000");
8696
+ applyStandardPragmas(db, { dataDir: dir });
8635
8697
  runMigrations2(db);
8636
8698
  return db;
8637
8699
  }
@@ -8912,6 +8974,110 @@ var MIGRATIONS = [
8912
8974
  CREATE INDEX IF NOT EXISTS idx_proposals_stash_status_ref_source
8913
8975
  ON proposals(stash_dir, status, ref, source);
8914
8976
  `
8977
+ },
8978
+ {
8979
+ id: "007-consolidation-judged",
8980
+ up: `
8981
+ CREATE TABLE IF NOT EXISTS consolidation_judged (
8982
+ entry_key TEXT PRIMARY KEY,
8983
+ content_hash TEXT NOT NULL,
8984
+ judged_at TEXT NOT NULL,
8985
+ outcome TEXT NOT NULL
8986
+ );
8987
+ `
8988
+ },
8989
+ {
8990
+ id: "008-body-embeddings",
8991
+ up: `
8992
+ CREATE TABLE IF NOT EXISTS body_embeddings (
8993
+ content_hash TEXT PRIMARY KEY,
8994
+ embedding BLOB NOT NULL,
8995
+ model_id TEXT NOT NULL,
8996
+ created_at INTEGER NOT NULL
8997
+ );
8998
+ `
8999
+ },
9000
+ {
9001
+ id: "009-asset-salience",
9002
+ up: `
9003
+ CREATE TABLE IF NOT EXISTS asset_salience (
9004
+ asset_ref TEXT PRIMARY KEY,
9005
+ encoding_salience REAL NOT NULL DEFAULT 0.5,
9006
+ outcome_salience REAL NOT NULL DEFAULT 0.0,
9007
+ retrieval_salience REAL NOT NULL DEFAULT 0.0,
9008
+ rank_score REAL NOT NULL DEFAULT 0.0,
9009
+ consecutive_no_ops INTEGER NOT NULL DEFAULT 0,
9010
+ updated_at INTEGER NOT NULL DEFAULT 0
9011
+ );
9012
+
9013
+ -- Hot path: sort / filter by rank_score for selector queries.
9014
+ CREATE INDEX IF NOT EXISTS idx_asset_salience_rank
9015
+ ON asset_salience(rank_score DESC);
9016
+ `
9017
+ },
9018
+ {
9019
+ id: "010-asset-outcome",
9020
+ up: `
9021
+ CREATE TABLE IF NOT EXISTS asset_outcome (
9022
+ asset_ref TEXT PRIMARY KEY,
9023
+ last_retrieved_at INTEGER NOT NULL DEFAULT 0,
9024
+ retrieval_count INTEGER NOT NULL DEFAULT 0,
9025
+ expected_retrieval_rate REAL NOT NULL DEFAULT 0.0,
9026
+ negative_feedback_count INTEGER NOT NULL DEFAULT 0,
9027
+ accepted_change_count INTEGER NOT NULL DEFAULT 0,
9028
+ review_pressure INTEGER NOT NULL DEFAULT 0,
9029
+ outcome_score REAL NOT NULL DEFAULT 0.0,
9030
+ updated_at INTEGER NOT NULL DEFAULT 0
9031
+ );
9032
+
9033
+ -- Hot path: sort assets by review_pressure DESC for #613 admission.
9034
+ CREATE INDEX IF NOT EXISTS idx_asset_outcome_review_pressure
9035
+ ON asset_outcome(review_pressure DESC);
9036
+
9037
+ -- Secondary: sort by outcome_score DESC for outcomeSalience reads.
9038
+ CREATE INDEX IF NOT EXISTS idx_asset_outcome_score
9039
+ ON asset_outcome(outcome_score DESC);
9040
+ `
9041
+ },
9042
+ {
9043
+ id: "011-asset-salience-homeostatic-demoted-at",
9044
+ up: `
9045
+ ALTER TABLE asset_salience ADD COLUMN homeostatic_demoted_at INTEGER DEFAULT NULL;
9046
+ `
9047
+ },
9048
+ {
9049
+ id: "012-improve-gate-thresholds",
9050
+ up: `
9051
+ CREATE TABLE IF NOT EXISTS improve_gate_thresholds (
9052
+ phase TEXT NOT NULL PRIMARY KEY,
9053
+ threshold INTEGER NOT NULL,
9054
+ updated_at INTEGER NOT NULL
9055
+ );
9056
+ `
9057
+ },
9058
+ {
9059
+ id: "013-extract-sessions-content-hash",
9060
+ up: `
9061
+ ALTER TABLE extract_sessions_seen ADD COLUMN content_hash TEXT DEFAULT NULL;
9062
+ `
9063
+ },
9064
+ {
9065
+ id: "014-recombine-hypotheses",
9066
+ up: `
9067
+ CREATE TABLE IF NOT EXISTS recombine_hypotheses (
9068
+ hypothesis_ref TEXT PRIMARY KEY,
9069
+ signature TEXT NOT NULL,
9070
+ member_key TEXT NOT NULL,
9071
+ consecutive_count INTEGER NOT NULL DEFAULT 0,
9072
+ first_seen_at TEXT NOT NULL,
9073
+ last_seen_at TEXT NOT NULL,
9074
+ last_run TEXT,
9075
+ promoted_at TEXT,
9076
+ metadata_json TEXT NOT NULL DEFAULT '{}'
9077
+ );
9078
+ CREATE INDEX IF NOT EXISTS idx_recombine_hypotheses_last_seen
9079
+ ON recombine_hypotheses(last_seen_at);
9080
+ `
8915
9081
  }
8916
9082
  ];
8917
9083
  function runMigrations2(db) {
@@ -9020,11 +9186,11 @@ function inferScope(envelope) {
9020
9186
  async function main() {
9021
9187
  const args = parseArgs(process.argv.slice(2));
9022
9188
  const runsRoot = path4.join(args.stashDir, ".akm", "runs");
9023
- if (!fs4.existsSync(runsRoot)) {
9189
+ if (!fs5.existsSync(runsRoot)) {
9024
9190
  console.log(`[import] no legacy runs directory at ${runsRoot}; nothing to do`);
9025
9191
  return;
9026
9192
  }
9027
- const entries = fs4.readdirSync(runsRoot, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => e.name).sort();
9193
+ const entries = fs5.readdirSync(runsRoot, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => e.name).sort();
9028
9194
  if (entries.length === 0) {
9029
9195
  console.log(`[import] ${runsRoot} is empty; nothing to do`);
9030
9196
  return;
@@ -9039,7 +9205,7 @@ async function main() {
9039
9205
  let skippedNoTimestamp = 0;
9040
9206
  for (const id of entries) {
9041
9207
  const resultPath = path4.join(runsRoot, id, "improve-result.json");
9042
- if (!fs4.existsSync(resultPath)) {
9208
+ if (!fs5.existsSync(resultPath)) {
9043
9209
  skippedNoResult++;
9044
9210
  continue;
9045
9211
  }
@@ -9049,7 +9215,7 @@ async function main() {
9049
9215
  }
9050
9216
  let envelope;
9051
9217
  try {
9052
- envelope = JSON.parse(fs4.readFileSync(resultPath, "utf8"));
9218
+ envelope = JSON.parse(fs5.readFileSync(resultPath, "utf8"));
9053
9219
  } catch (err) {
9054
9220
  console.warn(`[import] skipping ${id}: parse failed (${err instanceof Error ? err.message : String(err)})`);
9055
9221
  skippedParseFailed++;
@@ -9115,7 +9281,7 @@ async function main() {
9115
9281
  }
9116
9282
  const ts = new Date().toISOString().replace(/[:.]/g, "-");
9117
9283
  const archiveTarget = path4.join(args.stashDir, ".akm", `runs.archived-${ts}`);
9118
- fs4.renameSync(runsRoot, archiveTarget);
9284
+ fs5.renameSync(runsRoot, archiveTarget);
9119
9285
  console.log(`[import] archived ${runsRoot} \u2192 ${archiveTarget}`);
9120
9286
  }
9121
9287
  main().catch((err) => {