@remnic/core 9.69.52 → 9.69.53

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 (128) hide show
  1. package/dist/access-admin-ops-surface.d.ts +1 -1
  2. package/dist/access-admin-ops-surface.js +4 -4
  3. package/dist/access-authorization-probe.d.ts +1 -1
  4. package/dist/access-authorization-probe.js +5 -5
  5. package/dist/access-boundary.d.ts +1 -1
  6. package/dist/access-boundary.js +4 -4
  7. package/dist/access-cli.js +20 -20
  8. package/dist/access-extraction-force-flush.d.ts +1 -1
  9. package/dist/access-extraction-force-flush.js +4 -4
  10. package/dist/access-http-briefing.d.ts +1 -1
  11. package/dist/access-http-briefing.js +5 -5
  12. package/dist/access-http-lcm-compaction.d.ts +1 -1
  13. package/dist/access-http-lifecycle-flush.d.ts +1 -1
  14. package/dist/access-http-offline-stream.d.ts +1 -1
  15. package/dist/access-http-query.js +4 -4
  16. package/dist/access-http.d.ts +2 -2
  17. package/dist/access-http.js +16 -16
  18. package/dist/access-identity-continuity-surface.js +4 -4
  19. package/dist/access-lcm-surface.d.ts +1 -1
  20. package/dist/access-lcm-surface.js +4 -4
  21. package/dist/access-mcp-shared-context-tools.d.ts +1 -1
  22. package/dist/access-mcp.d.ts +1 -1
  23. package/dist/access-mcp.js +11 -11
  24. package/dist/access-namespace-preflight.js +4 -4
  25. package/dist/access-observe-write-surface.d.ts +1 -1
  26. package/dist/access-observe-write-surface.js +4 -4
  27. package/dist/access-operations-batch.js +5 -5
  28. package/dist/access-operations.d.ts +1 -1
  29. package/dist/access-operations.js +10 -10
  30. package/dist/access-recall-concurrency.d.ts +1 -1
  31. package/dist/access-recall-concurrency.js +4 -4
  32. package/dist/access-recall-response.d.ts +1 -1
  33. package/dist/access-recall-response.js +4 -4
  34. package/dist/access-recall-surface.d.ts +1 -1
  35. package/dist/access-recall-surface.js +4 -4
  36. package/dist/access-schema.d.ts +113 -113
  37. package/dist/{access-service-CUNM5RfA.d.ts → access-service-H-qEdnSs.d.ts} +64 -64
  38. package/dist/access-service-helpers.d.ts +1 -1
  39. package/dist/access-service.d.ts +1 -1
  40. package/dist/access-service.js +4 -4
  41. package/dist/access-surface-catalog.d.ts +1 -1
  42. package/dist/access-surface-catalog.js +6 -6
  43. package/dist/{chunk-TEQQQTQS.js → chunk-2HJKAVAS.js} +2 -2
  44. package/dist/{chunk-HWT6KRGS.js → chunk-6UEM5EOB.js} +2 -2
  45. package/dist/{chunk-UCY4EHAG.js → chunk-A4TQFNRX.js} +3 -3
  46. package/dist/{chunk-72N2P44O.js → chunk-ARRKSBQU.js} +2 -2
  47. package/dist/{chunk-WBW34YCJ.js → chunk-BCXZ4BDS.js} +2 -2
  48. package/dist/{chunk-V5BU5PVE.js → chunk-CO7KBRPF.js} +2 -2
  49. package/dist/{chunk-HG42J2EX.js → chunk-EQNZC3BH.js} +2 -2
  50. package/dist/{chunk-35EH6KW4.js → chunk-EYK3UHAP.js} +2 -2
  51. package/dist/{chunk-DCRK7I5E.js → chunk-HUQMVI3A.js} +93 -4
  52. package/dist/chunk-HUQMVI3A.js.map +1 -0
  53. package/dist/{chunk-MSTKJI5T.js → chunk-K7FXR75S.js} +442 -318
  54. package/dist/chunk-K7FXR75S.js.map +1 -0
  55. package/dist/{chunk-U6CMLAP4.js → chunk-M7HFDWOS.js} +2 -2
  56. package/dist/{chunk-2UDAABV6.js → chunk-MTJUIIM4.js} +2 -2
  57. package/dist/{chunk-GRX6YH4E.js → chunk-MXTCV3B5.js} +2 -2
  58. package/dist/{chunk-6KCQNFDQ.js → chunk-SOOWBRMH.js} +8 -8
  59. package/dist/{chunk-SOFATSHJ.js → chunk-TS66MUUJ.js} +5 -5
  60. package/dist/{chunk-72AV2H3R.js → chunk-U3NBO4IX.js} +39 -3
  61. package/dist/chunk-U3NBO4IX.js.map +1 -0
  62. package/dist/{chunk-EW3Y73MN.js → chunk-UJBIWY5M.js} +2 -2
  63. package/dist/{chunk-SVUUOLKM.js → chunk-VMKAA5SU.js} +2 -2
  64. package/dist/{chunk-UQTXER7M.js → chunk-ZADYEZY4.js} +2 -2
  65. package/dist/{chunk-2INZSV27.js → chunk-ZANEMAEV.js} +2 -2
  66. package/dist/{cli-CCc34xV7.d.ts → cli-VGDSn2zY.d.ts} +1 -1
  67. package/dist/cli.d.ts +2 -2
  68. package/dist/cli.js +17 -17
  69. package/dist/deep-recall-http-glue.d.ts +1 -1
  70. package/dist/deep-recall-mcp-tools.d.ts +1 -1
  71. package/dist/directory-sidecars.d.ts +30 -7
  72. package/dist/directory-sidecars.js +5 -1
  73. package/dist/external-wiki-access.d.ts +1 -1
  74. package/dist/external-wiki-access.js +5 -5
  75. package/dist/external-wiki-mcp-tools.d.ts +1 -1
  76. package/dist/index.d.ts +680 -680
  77. package/dist/index.js +20 -20
  78. package/dist/mcp-memory-inspector-app.d.ts +1 -1
  79. package/dist/memory-browse-http-glue.d.ts +1 -1
  80. package/dist/memory-browse-mcp-tools.d.ts +1 -1
  81. package/dist/memory-browse-operations.js +5 -5
  82. package/dist/memory-browse.js +3 -3
  83. package/dist/memory-subject-cli.d.ts +1 -1
  84. package/dist/memory-subject.d.ts +1 -1
  85. package/dist/orchestrator.js +20 -20
  86. package/dist/{public-http-UWVcqMcb.d.ts → public-http-P0cnHzYB.d.ts} +1 -1
  87. package/dist/recall-navigation-http-glue.d.ts +1 -1
  88. package/dist/recall-navigation-mcp-tools.d.ts +1 -1
  89. package/dist/recall-navigation-operations.js +5 -5
  90. package/dist/recall-navigation.js +4 -4
  91. package/dist/recall-state-view-admission.js +3 -3
  92. package/dist/schemas.d.ts +160 -160
  93. package/dist/shared-context/manager.d.ts +8 -8
  94. package/dist/support-passport/index.d.ts +4 -4
  95. package/dist/support-passport/index.js +7 -7
  96. package/dist/transfer/types.d.ts +78 -78
  97. package/dist/who-knows-cli.d.ts +1 -1
  98. package/dist/who-knows.d.ts +1 -1
  99. package/package.json +2 -2
  100. package/src/directory-sidecars.test.ts +113 -0
  101. package/src/directory-sidecars.ts +70 -8
  102. package/src/experience/session-experience-mining.test.ts +186 -0
  103. package/src/experience/session-experience-mining.ts +90 -0
  104. package/src/orchestration/persistence-index.ts +50 -0
  105. package/src/orchestration/recall-recognition-index.test.ts +249 -0
  106. package/src/orchestration/recall-recognition-index.ts +169 -0
  107. package/src/procedural/procedure-miner.ts +8 -6
  108. package/src/testing/subjects/recall-recognition-index.test.ts +97 -0
  109. package/dist/chunk-72AV2H3R.js.map +0 -1
  110. package/dist/chunk-DCRK7I5E.js.map +0 -1
  111. package/dist/chunk-MSTKJI5T.js.map +0 -1
  112. /package/dist/{chunk-TEQQQTQS.js.map → chunk-2HJKAVAS.js.map} +0 -0
  113. /package/dist/{chunk-HWT6KRGS.js.map → chunk-6UEM5EOB.js.map} +0 -0
  114. /package/dist/{chunk-UCY4EHAG.js.map → chunk-A4TQFNRX.js.map} +0 -0
  115. /package/dist/{chunk-72N2P44O.js.map → chunk-ARRKSBQU.js.map} +0 -0
  116. /package/dist/{chunk-WBW34YCJ.js.map → chunk-BCXZ4BDS.js.map} +0 -0
  117. /package/dist/{chunk-V5BU5PVE.js.map → chunk-CO7KBRPF.js.map} +0 -0
  118. /package/dist/{chunk-HG42J2EX.js.map → chunk-EQNZC3BH.js.map} +0 -0
  119. /package/dist/{chunk-35EH6KW4.js.map → chunk-EYK3UHAP.js.map} +0 -0
  120. /package/dist/{chunk-U6CMLAP4.js.map → chunk-M7HFDWOS.js.map} +0 -0
  121. /package/dist/{chunk-2UDAABV6.js.map → chunk-MTJUIIM4.js.map} +0 -0
  122. /package/dist/{chunk-GRX6YH4E.js.map → chunk-MXTCV3B5.js.map} +0 -0
  123. /package/dist/{chunk-6KCQNFDQ.js.map → chunk-SOOWBRMH.js.map} +0 -0
  124. /package/dist/{chunk-SOFATSHJ.js.map → chunk-TS66MUUJ.js.map} +0 -0
  125. /package/dist/{chunk-EW3Y73MN.js.map → chunk-UJBIWY5M.js.map} +0 -0
  126. /package/dist/{chunk-SVUUOLKM.js.map → chunk-VMKAA5SU.js.map} +0 -0
  127. /package/dist/{chunk-UQTXER7M.js.map → chunk-ZADYEZY4.js.map} +0 -0
  128. /package/dist/{chunk-2INZSV27.js.map → chunk-ZANEMAEV.js.map} +0 -0
@@ -111,7 +111,7 @@ import {
111
111
  import {
112
112
  indexStateViewAnnotatedResults,
113
113
  resolveRecallStateViewActive
114
- } from "./chunk-72N2P44O.js";
114
+ } from "./chunk-ARRKSBQU.js";
115
115
  import {
116
116
  applyRecallStateViews
117
117
  } from "./chunk-DBB5JPSL.js";
@@ -231,7 +231,7 @@ import {
231
231
  runTimelinePublishCli,
232
232
  screenCandidateFact,
233
233
  summarizeVaultPublish
234
- } from "./chunk-SOFATSHJ.js";
234
+ } from "./chunk-TS66MUUJ.js";
235
235
  import {
236
236
  normalizeReplaySessionKey
237
237
  } from "./chunk-AJVLDJU6.js";
@@ -344,9 +344,12 @@ import {
344
344
  resolveVaultNotePath
345
345
  } from "./chunk-3KJTSCSX.js";
346
346
  import {
347
+ buildRecognitionIndex,
347
348
  decideRecognitionTier,
348
349
  loadRecognitionIndex,
349
- runRecognitionTier
350
+ recognitionIndexPath,
351
+ runRecognitionTier,
352
+ saveRecognitionIndex
350
353
  } from "./chunk-4KQIWY4A.js";
351
354
  import {
352
355
  AMBIENT_CAPTURE_PROMPT_RULE,
@@ -354,7 +357,7 @@ import {
354
357
  } from "./chunk-QW27DOHG.js";
355
358
  import {
356
359
  MeetingsInputError
357
- } from "./chunk-6KCQNFDQ.js";
360
+ } from "./chunk-SOOWBRMH.js";
358
361
  import {
359
362
  WearablesInputError,
360
363
  describeErrorForOperator
@@ -378,8 +381,10 @@ import {
378
381
  SessionContextCoordinator,
379
382
  capturePassiveCorrections,
380
383
  clusterByKey,
381
- detectPassiveCorrections
382
- } from "./chunk-DCRK7I5E.js";
384
+ detectPassiveCorrections,
385
+ renderSessionExperiencePreview,
386
+ scoreSessionExperienceForPrompt
387
+ } from "./chunk-HUQMVI3A.js";
383
388
  import {
384
389
  importCapsule
385
390
  } from "./chunk-VVX5PZFS.js";
@@ -419,7 +424,7 @@ import {
419
424
  isTopLevelArchivePath,
420
425
  journalPath,
421
426
  writeJournalFile
422
- } from "./chunk-TEQQQTQS.js";
427
+ } from "./chunk-2HJKAVAS.js";
423
428
  import {
424
429
  searchHarmonicRetrieval
425
430
  } from "./chunk-TQT4AOPO.js";
@@ -850,7 +855,7 @@ import {
850
855
  } from "./chunk-3WCASNQZ.js";
851
856
 
852
857
  // src/orchestrator.ts
853
- import path22 from "path";
858
+ import path23 from "path";
854
859
  import { createHash as createHash9 } from "crypto";
855
860
 
856
861
  // src/orchestration/tier-migration-coordinator.ts
@@ -2408,7 +2413,7 @@ var RecallRerankCoordinator = class _RecallRerankCoordinator {
2408
2413
  namespaces,
2409
2414
  {
2410
2415
  readNamespaceMemories: async (ns) => (await this.getStorage(ns)).readAllMemories(),
2411
- readMemoryFrontmatter: async (path41, preferredNamespace) => {
2416
+ readMemoryFrontmatter: async (path42, preferredNamespace) => {
2412
2417
  if (!fallbackReader) {
2413
2418
  for (const ns of namespaces) {
2414
2419
  try {
@@ -2420,7 +2425,7 @@ var RecallRerankCoordinator = class _RecallRerankCoordinator {
2420
2425
  }
2421
2426
  if (!fallbackReader) return null;
2422
2427
  const memory = await this.readQmdResultMemory(
2423
- path41,
2428
+ path42,
2424
2429
  fallbackReader,
2425
2430
  namespaces,
2426
2431
  preferredNamespace
@@ -9897,44 +9902,8 @@ var GraphRecallCoordinator = class {
9897
9902
  }
9898
9903
  };
9899
9904
 
9900
- // src/experience/session-experience-recall.ts
9901
- function tokenOverlapScore(prompt, memoryText) {
9902
- const norm = (s) => s.toLowerCase().split(/[^a-z0-9]+/).filter((t) => t.length > 2);
9903
- const promptTokens = new Set(norm(prompt));
9904
- const memTokens = new Set(norm(memoryText));
9905
- if (promptTokens.size === 0 || memTokens.size === 0) return 0;
9906
- let inter = 0;
9907
- for (const t of promptTokens) {
9908
- if (memTokens.has(t)) inter++;
9909
- }
9910
- const union = /* @__PURE__ */ new Set([...promptTokens, ...memTokens]);
9911
- return inter / Math.max(1, union.size);
9912
- }
9913
- function isSessionExperienceMemory(memory) {
9914
- const hash = memory.frontmatter.structuredAttributes?.experience_session_hash;
9915
- return typeof hash === "string" && hash.length > 0;
9916
- }
9917
- function scoreSessionExperienceForPrompt(memory, prompt) {
9918
- if (!isSessionExperienceMemory(memory)) return null;
9919
- const situation = memory.frontmatter.structuredAttributes?.experience_situation ?? "";
9920
- const situationScore = tokenOverlapScore(prompt, situation);
9921
- const bodyScore = tokenOverlapScore(prompt, memory.content);
9922
- return Math.min(1, situationScore * 0.75 + bodyScore * 0.25);
9923
- }
9924
- function renderSessionExperiencePreview(memory) {
9925
- if (!isSessionExperienceMemory(memory)) return null;
9926
- const attrs = memory.frontmatter.structuredAttributes ?? {};
9927
- const situation = (attrs.experience_situation ?? "").trim();
9928
- const approach = (attrs.experience_approach ?? "").trim();
9929
- const reflection = (attrs.experience_reflection ?? "").trim();
9930
- if (situation.length === 0 && approach.length === 0 && reflection.length === 0) {
9931
- return `Experience. ${memory.content.replace(/\s+/g, " ").trim()}`;
9932
- }
9933
- return `Experience. Situation: ${situation} Approach: ${approach} Reflection: ${reflection}`.replace(/\s+/g, " ").trim();
9934
- }
9935
-
9936
9905
  // src/procedural/procedure-recall.ts
9937
- function tokenOverlapScore2(prompt, memoryText) {
9906
+ function tokenOverlapScore(prompt, memoryText) {
9938
9907
  const norm = (s) => s.toLowerCase().split(/[^a-z0-9]+/).filter((t) => t.length > 2);
9939
9908
  const promptTokens = new Set(norm(prompt));
9940
9909
  const memTokens = new Set(norm(memoryText));
@@ -9949,7 +9918,7 @@ function tokenOverlapScore2(prompt, memoryText) {
9949
9918
  function scoreProcedureForPrompt(m, prompt, queryIntent, experienceEnabled) {
9950
9919
  const memText = `${m.content}
9951
9920
  ${(m.frontmatter.tags ?? []).join(" ")}`;
9952
- const jaccard = tokenOverlapScore2(prompt, memText);
9921
+ const jaccard = tokenOverlapScore(prompt, memText);
9953
9922
  const memIntent = inferIntentFromText(m.content.slice(0, 2e3));
9954
9923
  const intentScore = intentCompatibilityScore(queryIntent, memIntent);
9955
9924
  const base = jaccard * 0.55 + intentScore * 0.45;
@@ -17655,7 +17624,121 @@ var OrchestratorInitCoordinator = class {
17655
17624
  };
17656
17625
 
17657
17626
  // src/orchestration/persistence-index.ts
17627
+ import path19 from "path";
17628
+
17629
+ // src/orchestration/recall-recognition-index.ts
17630
+ import { promises as fsp } from "fs";
17658
17631
  import path18 from "path";
17632
+ import { setTimeout as delay } from "timers/promises";
17633
+ var writeChains = /* @__PURE__ */ new Map();
17634
+ var LOCK_POLL_MS = 10;
17635
+ var LOCK_ATTEMPTS = 50;
17636
+ var LOCK_STALE_MS = 6e4;
17637
+ function recognitionDescriptionFromContent(content) {
17638
+ const trimmed = content.trim();
17639
+ if (trimmed.length === 0) return "";
17640
+ const newline = trimmed.indexOf("\n");
17641
+ return newline === -1 ? trimmed : trimmed.slice(0, newline).trimEnd();
17642
+ }
17643
+ function withIndexChain(indexPath, op) {
17644
+ const previous = writeChains.get(indexPath) ?? Promise.resolve();
17645
+ const run = previous.then(op, op);
17646
+ const tail = run.then(() => void 0, () => void 0);
17647
+ writeChains.set(indexPath, tail);
17648
+ void tail.then(() => {
17649
+ if (writeChains.get(indexPath) === tail) writeChains.delete(indexPath);
17650
+ });
17651
+ return run;
17652
+ }
17653
+ async function removeAbandonedRecognitionLock(lockDir) {
17654
+ try {
17655
+ const info = await fsp.lstat(lockDir);
17656
+ if (info.isSymbolicLink()) return "blocked";
17657
+ if (!info.isDirectory()) {
17658
+ await fsp.rm(lockDir, { force: true });
17659
+ return "removed";
17660
+ }
17661
+ if (Date.now() - info.mtimeMs < LOCK_STALE_MS) return "wait";
17662
+ await fsp.rm(lockDir, { recursive: true, force: true });
17663
+ return "removed";
17664
+ } catch (error) {
17665
+ if (error?.code === "ENOENT") return "removed";
17666
+ return "blocked";
17667
+ }
17668
+ }
17669
+ async function withRecognitionIndexLock(memoryDir, op) {
17670
+ const lockDir = `${recognitionIndexPath(memoryDir)}.lock.d`;
17671
+ for (let attempt = 0; attempt < LOCK_ATTEMPTS; attempt++) {
17672
+ try {
17673
+ await fsp.mkdir(lockDir);
17674
+ try {
17675
+ return await op();
17676
+ } finally {
17677
+ await fsp.rm(lockDir, { recursive: true, force: true }).catch(() => void 0);
17678
+ }
17679
+ } catch (error) {
17680
+ const code = error?.code;
17681
+ if (code === "ENOENT") {
17682
+ await fsp.mkdir(path18.dirname(lockDir), { recursive: true }).catch(() => void 0);
17683
+ continue;
17684
+ }
17685
+ if (code !== "EEXIST") throw error;
17686
+ const cleanup = await removeAbandonedRecognitionLock(lockDir);
17687
+ if (cleanup === "blocked") {
17688
+ throw new Error(`recognition index lock blocked at ${lockDir}`);
17689
+ }
17690
+ if (cleanup === "removed") continue;
17691
+ await delay(LOCK_POLL_MS);
17692
+ }
17693
+ }
17694
+ throw new Error(`recognition index lock timed out at ${lockDir}`);
17695
+ }
17696
+ function applyChanges(entries, changes) {
17697
+ const next = entries.map((entry) => ({ id: entry.id, description: entry.description }));
17698
+ const byId = new Map(next.map((entry, index) => [entry.id, index]));
17699
+ for (const change of changes) {
17700
+ const id = change.id.trim();
17701
+ if (id.length === 0) continue;
17702
+ if (change.action === "remove") {
17703
+ const index = byId.get(id);
17704
+ if (index === void 0) continue;
17705
+ next.splice(index, 1);
17706
+ byId.delete(id);
17707
+ for (const [key, value] of byId) {
17708
+ if (value > index) byId.set(key, value - 1);
17709
+ }
17710
+ continue;
17711
+ }
17712
+ const description = recognitionDescriptionFromContent(change.content);
17713
+ const existing = byId.get(id);
17714
+ if (existing !== void 0) {
17715
+ next[existing] = { id, description };
17716
+ } else {
17717
+ byId.set(id, next.length);
17718
+ next.push({ id, description });
17719
+ }
17720
+ }
17721
+ return next;
17722
+ }
17723
+ function meaningfulChanges(changes) {
17724
+ return changes.filter((change) => change.id.trim().length > 0);
17725
+ }
17726
+ async function maintainRecognitionIndexAfterWrite(args) {
17727
+ if (args.enabled !== true) return;
17728
+ const changes = meaningfulChanges(args.changes);
17729
+ if (changes.length === 0) return;
17730
+ const indexPath = recognitionIndexPath(args.memoryDir);
17731
+ await withIndexChain(
17732
+ indexPath,
17733
+ () => withRecognitionIndexLock(args.memoryDir, async () => {
17734
+ const loaded = await loadRecognitionIndex(args.memoryDir);
17735
+ const entries = applyChanges(loaded?.entries ?? [], changes);
17736
+ await saveRecognitionIndex(args.memoryDir, buildRecognitionIndex(entries));
17737
+ })
17738
+ );
17739
+ }
17740
+
17741
+ // src/orchestration/persistence-index.ts
17659
17742
  var PersistenceIndexCoordinator = class {
17660
17743
  constructor(deps) {
17661
17744
  this.deps = deps;
@@ -17847,7 +17930,7 @@ var PersistenceIndexCoordinator = class {
17847
17930
  const allMems = allMemsForGraph ?? [];
17848
17931
  for (const m of allMems) {
17849
17932
  if (m.frontmatter.entityRef === entityRef) {
17850
- const rel = path18.relative(storage.dir, m.path);
17933
+ const rel = path19.relative(storage.dir, m.path);
17851
17934
  if (rel !== memoryRelPath) entitySiblings.push(rel);
17852
17935
  }
17853
17936
  }
@@ -17898,6 +17981,7 @@ var PersistenceIndexCoordinator = class {
17898
17981
  * Fail-open: any error is logged but does not abort extraction.
17899
17982
  */
17900
17983
  async updateTemporalTagIndexes(storage, persistedIds) {
17984
+ await this.maintainRecognitionIndex(storage, persistedIds);
17901
17985
  const caps = resolveCapabilities(this.deps.config);
17902
17986
  if (!resolveIndexingCapabilities(this.deps.config).queryAwareIndexing && !caps.parallelRetrieval && !resolveRecallEnhancementCapabilities(this.deps.config).eventOrderRecall)
17903
17987
  return;
@@ -17998,11 +18082,51 @@ var PersistenceIndexCoordinator = class {
17998
18082
  );
17999
18083
  return enriched;
18000
18084
  }
18085
+ /**
18086
+ * Upsert persisted memories into the namespace recognition index.
18087
+ * `recallRecognitionTier !== true` returns before any index I/O.
18088
+ * A missing index is bootstrapped from the active corpus so the first
18089
+ * post-enable write cannot publish a partial index that recall would
18090
+ * treat as the full working set.
18091
+ */
18092
+ async maintainRecognitionIndex(storage, persistedIds) {
18093
+ try {
18094
+ if (this.deps.config.recallRecognitionTier !== true) return;
18095
+ const indexMissing = await loadRecognitionIndex(storage.dir) === null;
18096
+ if (!indexMissing && persistedIds.length === 0) return;
18097
+ const changes = [];
18098
+ const pushUpsert = (memory) => {
18099
+ if (!isActiveMemoryStatus(memory.frontmatter.status)) return;
18100
+ const memoryId = memory.frontmatter.id;
18101
+ if (typeof memoryId !== "string" || memoryId.trim().length === 0) return;
18102
+ changes.push({ action: "upsert", id: memoryId, content: memory.content ?? "" });
18103
+ };
18104
+ if (indexMissing) {
18105
+ const corpus = await storage.readAllMemories().catch(() => []);
18106
+ for (const memory of corpus) pushUpsert(memory);
18107
+ }
18108
+ for (const id of persistedIds) {
18109
+ let memory = await storage.getMemoryById(id);
18110
+ if (!memory) {
18111
+ const cold = await storage.getMemoryByIdIncludingArchived(id).catch(() => null);
18112
+ if (cold && isActiveMemoryStatus(cold.frontmatter.status)) memory = cold;
18113
+ }
18114
+ if (memory) pushUpsert(memory);
18115
+ }
18116
+ await maintainRecognitionIndexAfterWrite({
18117
+ memoryDir: storage.dir,
18118
+ enabled: true,
18119
+ changes
18120
+ });
18121
+ } catch (err) {
18122
+ log.debug(`recognition-index update error (non-fatal): ${err}`);
18123
+ }
18124
+ }
18001
18125
  };
18002
18126
 
18003
18127
  // src/orchestration/workspace-ops.ts
18004
18128
  import { lstat as lstat2, mkdir as mkdir6, readFile as readFile8, readdir as readdir3, realpath as realpath2, writeFile as writeFile6 } from "fs/promises";
18005
- import path19 from "path";
18129
+ import path20 from "path";
18006
18130
 
18007
18131
  // src/maintenance/pattern-reinforcement.ts
18008
18132
  function patternReinforcementKey(content) {
@@ -19906,8 +20030,8 @@ var MeetingsService = class {
19906
20030
  // src/orchestration/workspace-ops.ts
19907
20031
  var MEETINGS_BUILD_DEBOUNCE_MS = 5e3;
19908
20032
  function matchesMemoryPath(candidatePath, requestedPath, memoryDir) {
19909
- const normalizedCandidate = path19.resolve(candidatePath);
19910
- return normalizedCandidate === path19.resolve(requestedPath) || normalizedCandidate === path19.resolve(memoryDir, requestedPath);
20033
+ const normalizedCandidate = path20.resolve(candidatePath);
20034
+ return normalizedCandidate === path20.resolve(requestedPath) || normalizedCandidate === path20.resolve(memoryDir, requestedPath);
19911
20035
  }
19912
20036
  function accessTrackingPathCandidates(storageDir, memoryPath) {
19913
20037
  const candidates = qmdResultPathCandidates(storageDir, memoryPath);
@@ -19915,12 +20039,12 @@ function accessTrackingPathCandidates(storageDir, memoryPath) {
19915
20039
  if (!parts) return candidates;
19916
20040
  candidates.push(
19917
20041
  ...qmdResultPathCandidates(storageDir, parts.relativePath),
19918
- ...qmdResultPathCandidates(path19.join(storageDir, "cold"), parts.relativePath)
20042
+ ...qmdResultPathCandidates(path20.join(storageDir, "cold"), parts.relativePath)
19919
20043
  );
19920
20044
  return [...new Set(candidates)];
19921
20045
  }
19922
20046
  function canonicalMemoryPath(memoryPath, memoryDir) {
19923
- return path19.resolve(path19.isAbsolute(memoryPath) ? memoryPath : path19.resolve(memoryDir, memoryPath));
20047
+ return path20.resolve(path20.isAbsolute(memoryPath) ? memoryPath : path20.resolve(memoryDir, memoryPath));
19924
20048
  }
19925
20049
  var WorkspaceOpsCoordinator = class {
19926
20050
  constructor(deps) {
@@ -20002,15 +20126,15 @@ var WorkspaceOpsCoordinator = class {
20002
20126
  this.deps.lastFileHygieneRunAtMs = now;
20003
20127
  if (hygiene.rotateEnabled) {
20004
20128
  for (const rel of hygiene.rotatePaths) {
20005
- const abs = path19.isAbsolute(rel) ? rel : path19.join(this.deps.config.workspaceDir, rel);
20129
+ const abs = path20.isAbsolute(rel) ? rel : path20.join(this.deps.config.workspaceDir, rel);
20006
20130
  try {
20007
20131
  const raw = await readFile8(abs, "utf-8");
20008
20132
  if (raw.length > hygiene.rotateMaxBytes) {
20009
- const archiveDir = path19.join(
20133
+ const archiveDir = path20.join(
20010
20134
  this.deps.config.workspaceDir,
20011
20135
  hygiene.archiveDir
20012
20136
  );
20013
- const base = path19.basename(abs);
20137
+ const base = path20.basename(abs);
20014
20138
  const prefix = base.toUpperCase().replace(/\.MD$/i, "").replace(/[^A-Z0-9]+/g, "-") || "FILE";
20015
20139
  const { newContent } = await rotateMarkdownFileToArchive({
20016
20140
  filePath: abs,
@@ -20035,8 +20159,8 @@ var WorkspaceOpsCoordinator = class {
20035
20159
  log.warn(w.message);
20036
20160
  }
20037
20161
  if (hygiene.warningsLogEnabled && warnings.length > 0) {
20038
- const fp = path19.join(this.deps.config.memoryDir, hygiene.warningsLogPath);
20039
- await mkdir6(path19.dirname(fp), { recursive: true });
20162
+ const fp = path20.join(this.deps.config.memoryDir, hygiene.warningsLogPath);
20163
+ await mkdir6(path20.dirname(fp), { recursive: true });
20040
20164
  const stamp = (/* @__PURE__ */ new Date()).toISOString();
20041
20165
  const block = `
20042
20166
 
@@ -20076,7 +20200,7 @@ var WorkspaceOpsCoordinator = class {
20076
20200
  for (const categoryDir of RECALL_FALLBACK_DIRS) {
20077
20201
  if (memoryRootReal === null) break;
20078
20202
  for (const date of datesToScan) {
20079
- const dateDir = path19.join(storage.dir, categoryDir, date);
20203
+ const dateDir = path20.join(storage.dir, categoryDir, date);
20080
20204
  try {
20081
20205
  const dirStat = await lstat2(dateDir);
20082
20206
  if (dirStat.isSymbolicLink() || !dirStat.isDirectory()) continue;
@@ -20085,7 +20209,7 @@ var WorkspaceOpsCoordinator = class {
20085
20209
  for (const entry of entries) {
20086
20210
  if (entry.isSymbolicLink()) continue;
20087
20211
  if (!entry.name.endsWith(".md")) continue;
20088
- const fullPath = path19.join(dateDir, entry.name);
20212
+ const fullPath = path20.join(dateDir, entry.name);
20089
20213
  try {
20090
20214
  assertPathInsideRoot(memoryRootReal, await realpath2(fullPath), fullPath);
20091
20215
  const memory = await storage.readMemoryByPath(fullPath);
@@ -20107,13 +20231,13 @@ var WorkspaceOpsCoordinator = class {
20107
20231
  return a.frontmatter.created < b.frontmatter.created ? -1 : 1;
20108
20232
  });
20109
20233
  const hourlySummaries = [];
20110
- const hourlyBaseDir = path19.join(storage.dir, "summaries", "hourly");
20234
+ const hourlyBaseDir = path20.join(storage.dir, "summaries", "hourly");
20111
20235
  try {
20112
20236
  const sessionKeys = await readdir3(hourlyBaseDir, { withFileTypes: true });
20113
20237
  for (const sk of sessionKeys) {
20114
20238
  if (!sk.isDirectory()) continue;
20115
20239
  for (const date of datesToScan) {
20116
- const summaryFile = path19.join(hourlyBaseDir, sk.name, `${date}.md`);
20240
+ const summaryFile = path20.join(hourlyBaseDir, sk.name, `${date}.md`);
20117
20241
  try {
20118
20242
  const raw = await readFile8(summaryFile, "utf-8");
20119
20243
  const filtered = filterHourlySummaryMarkdownForLocalDay(
@@ -20590,18 +20714,18 @@ ${reflectionsContent.trim()}
20590
20714
  // src/orchestration/namespace-read-fanout.ts
20591
20715
  import { existsSync, readFileSync } from "fs";
20592
20716
  import { stat as stat3 } from "fs/promises";
20593
- import path21 from "path";
20717
+ import path22 from "path";
20594
20718
 
20595
20719
  // src/orchestration/orchestrator-namespace-scope.ts
20596
- import path20 from "path";
20720
+ import path21 from "path";
20597
20721
  function computeSemanticDedupScope(targetStorage, config) {
20598
20722
  if (!resolveNamespaceCapabilities(config).namespaces) return {};
20599
- const memoryDir = path20.resolve(config.memoryDir);
20600
- const storageDir = path20.resolve(targetStorage.dir);
20723
+ const memoryDir = path21.resolve(config.memoryDir);
20724
+ const storageDir = path21.resolve(targetStorage.dir);
20601
20725
  if (storageDir === memoryDir) {
20602
20726
  return { pathExcludePrefixes: ["namespaces/"] };
20603
20727
  }
20604
- let rel = path20.relative(memoryDir, storageDir);
20728
+ let rel = path21.relative(memoryDir, storageDir);
20605
20729
  if (!rel || rel.startsWith("..")) {
20606
20730
  log.debug(
20607
20731
  `semantic dedup: target storage dir ${storageDir} is outside memoryDir ${memoryDir}; scoping lookup to absolute path prefix`
@@ -20654,7 +20778,7 @@ var NamespaceReadFanoutCoordinator = class {
20654
20778
  loadNamespaceStorageDirHintsFromCatalog() {
20655
20779
  if (this.deps.namespaceStorageDirHintsLoaded || !this.deps.namespaceCatalog.enabled) return;
20656
20780
  this.deps.namespaceStorageDirHintsLoaded = true;
20657
- const catalogPath = path21.join(this.deps.config.memoryDir, "state", "namespaces.jsonl");
20781
+ const catalogPath = path22.join(this.deps.config.memoryDir, "state", "namespaces.jsonl");
20658
20782
  if (!existsSync(catalogPath)) return;
20659
20783
  let body;
20660
20784
  try {
@@ -20691,7 +20815,7 @@ var NamespaceReadFanoutCoordinator = class {
20691
20815
  if (!this.deps.storageDirMatchesNamespaceHint(record.namespace, record.storageDir)) {
20692
20816
  continue;
20693
20817
  }
20694
- const resolvedStorageDir = path21.resolve(record.storageDir);
20818
+ const resolvedStorageDir = path22.resolve(record.storageDir);
20695
20819
  const current = preferredByStorageDir.get(resolvedStorageDir);
20696
20820
  preferredByStorageDir.set(
20697
20821
  resolvedStorageDir,
@@ -20876,12 +21000,12 @@ var NamespaceReadFanoutCoordinator = class {
20876
21000
  }
20877
21001
  async resolveStateDirForNamespace(namespace) {
20878
21002
  if (!resolveNamespaceCapabilities(this.deps.config).namespaces) {
20879
- return path21.join(this.deps.config.memoryDir, "state");
21003
+ return path22.join(this.deps.config.memoryDir, "state");
20880
21004
  }
20881
21005
  if (namespace !== this.deps.config.defaultNamespace) {
20882
- return path21.join(this.deps.config.memoryDir, "namespaces", namespace, "state");
21006
+ return path22.join(this.deps.config.memoryDir, "namespaces", namespace, "state");
20883
21007
  }
20884
- const candidate = path21.join(
21008
+ const candidate = path22.join(
20885
21009
  this.deps.config.memoryDir,
20886
21010
  "namespaces",
20887
21011
  this.deps.config.defaultNamespace
@@ -20889,11 +21013,11 @@ var NamespaceReadFanoutCoordinator = class {
20889
21013
  try {
20890
21014
  const candidateStat = await stat3(candidate);
20891
21015
  if (candidateStat.isDirectory()) {
20892
- return path21.join(candidate, "state");
21016
+ return path22.join(candidate, "state");
20893
21017
  }
20894
21018
  } catch {
20895
21019
  }
20896
- return path21.join(this.deps.config.memoryDir, "state");
21020
+ return path22.join(this.deps.config.memoryDir, "state");
20897
21021
  }
20898
21022
  namespaceFromPath(p) {
20899
21023
  if (!resolveNamespaceCapabilities(this.deps.config).namespaces) return this.deps.config.defaultNamespace;
@@ -21348,7 +21472,7 @@ var Orchestrator = class {
21348
21472
  if (this.destroyed) throw new Error("orchestrator has been destroyed");
21349
21473
  if (!this._dependencyPropagationDelivery) {
21350
21474
  this._dependencyPropagationDelivery = new DependencyPropagationDelivery({
21351
- queueRoot: path22.join(this.config.memoryDir, "state", "dependency-propagation"),
21475
+ queueRoot: path23.join(this.config.memoryDir, "state", "dependency-propagation"),
21352
21476
  config: this.config,
21353
21477
  extraction: this.extraction,
21354
21478
  getStorage: (namespace) => this.getStorage(namespace),
@@ -21703,7 +21827,7 @@ var Orchestrator = class {
21703
21827
  const defaultNs = normalizeNamespaceIdentity(this.config.defaultNamespace);
21704
21828
  if (ns !== defaultNs && !isSafeRouteNamespace(ns)) return;
21705
21829
  if (!this.storageDirMatchesNamespaceHint(ns, storageDir)) return;
21706
- const resolvedStorageDir = path22.resolve(storageDir);
21830
+ const resolvedStorageDir = path23.resolve(storageDir);
21707
21831
  let hints = this.namespaceStorageDirHints.get(resolvedStorageDir);
21708
21832
  if (!hints) {
21709
21833
  hints = /* @__PURE__ */ new Set();
@@ -21714,21 +21838,21 @@ var Orchestrator = class {
21714
21838
  storageDirMatchesNamespaceHint(namespace, storageDir) {
21715
21839
  const ns = normalizeNamespaceIdentity(namespace);
21716
21840
  if (!ns) return false;
21717
- const resolvedStorageDir = path22.resolve(storageDir);
21718
- const resolvedMemoryDir = path22.resolve(this.config.memoryDir);
21841
+ const resolvedStorageDir = path23.resolve(storageDir);
21842
+ const resolvedMemoryDir = path23.resolve(this.config.memoryDir);
21719
21843
  const defaultNs = normalizeNamespaceIdentity(this.config.defaultNamespace);
21720
21844
  if (resolvedStorageDir === resolvedMemoryDir) return ns === defaultNs;
21721
- const resolvedNamespacesDir = path22.join(resolvedMemoryDir, "namespaces");
21845
+ const resolvedNamespacesDir = path23.join(resolvedMemoryDir, "namespaces");
21722
21846
  if (!isPathInsideStorageRoot(resolvedNamespacesDir, resolvedStorageDir)) return false;
21723
- const rawRoot = path22.resolve(resolvedNamespacesDir, ns);
21724
- const tokenRoot = path22.resolve(resolvedNamespacesDir, namespaceIdentityToken(ns));
21847
+ const rawRoot = path23.resolve(resolvedNamespacesDir, ns);
21848
+ const tokenRoot = path23.resolve(resolvedNamespacesDir, namespaceIdentityToken(ns));
21725
21849
  return resolvedStorageDir === rawRoot || resolvedStorageDir === tokenRoot;
21726
21850
  }
21727
21851
  namespaceStorageDirHintOwnershipRank(record, resolvedStorageDir, configured) {
21728
- if (resolvedStorageDir === path22.resolve(this.config.memoryDir)) {
21852
+ if (resolvedStorageDir === path23.resolve(this.config.memoryDir)) {
21729
21853
  return record.namespace === normalizeNamespaceIdentity(this.config.defaultNamespace) ? 0 : 3;
21730
21854
  }
21731
- const leaf = path22.basename(resolvedStorageDir);
21855
+ const leaf = path23.basename(resolvedStorageDir);
21732
21856
  const tokenOwnsRoot = namespaceIdentityToken(record.namespace) === leaf;
21733
21857
  if (tokenOwnsRoot && configured.has(record.namespace)) return 0;
21734
21858
  if (record.namespace === leaf) return 1;
@@ -21869,7 +21993,7 @@ var Orchestrator = class {
21869
21993
  StorageManager.setOkfConformanceDefault(config.memoryDir, config.okf?.conformanceEnabled);
21870
21994
  this.profiler = new ProfilingCollector({
21871
21995
  enabled: resolvePipelineProcessingCapabilities(this.config).profiling,
21872
- storageDir: config.profilingStorageDir || path22.join(config.memoryDir, "profiling"),
21996
+ storageDir: config.profilingStorageDir || path23.join(config.memoryDir, "profiling"),
21873
21997
  maxTraces: config.profilingMaxTraces
21874
21998
  });
21875
21999
  this.namespaceCatalog = new NamespaceCatalog(config);
@@ -21956,7 +22080,7 @@ var Orchestrator = class {
21956
22080
  this.compounding = resolveConsolidationCapabilities(config).compounding ? new CompoundingEngine(config, this.storage) : void 0;
21957
22081
  this.buffer = new SmartBuffer(config, this.storage);
21958
22082
  this.transcript = new TranscriptManager(config);
21959
- this.conversationIndexDir = path22.join(
22083
+ this.conversationIndexDir = path23.join(
21960
22084
  config.memoryDir,
21961
22085
  "conversation-index",
21962
22086
  "chunks"
@@ -22107,7 +22231,7 @@ var Orchestrator = class {
22107
22231
  getHandleHistory: () => this.handleHistory
22108
22232
  });
22109
22233
  this.threading = new ThreadingManager(
22110
- path22.join(config.memoryDir, "threads"),
22234
+ path23.join(config.memoryDir, "threads"),
22111
22235
  config.threadingGapMinutes
22112
22236
  );
22113
22237
  const lifecycleCaps = resolveMemoryLifecycleCapabilities(config);
@@ -24200,9 +24324,9 @@ function readStructuralSymbol(entry) {
24200
24324
  const rec = entry;
24201
24325
  const symbol = typeof rec.symbol === "string" ? rec.symbol.trim() : "";
24202
24326
  if (!symbol) return null;
24203
- const path41 = typeof rec.path === "string" && rec.path.length > 0 ? rec.path : void 0;
24327
+ const path42 = typeof rec.path === "string" && rec.path.length > 0 ? rec.path : void 0;
24204
24328
  const kind = typeof rec.kind === "string" && rec.kind.length > 0 ? rec.kind : void 0;
24205
- const item = path41 !== void 0 && kind !== void 0 ? { symbol, path: path41, kind } : path41 !== void 0 ? { symbol, path: path41 } : kind !== void 0 ? { symbol, kind } : { symbol };
24329
+ const item = path42 !== void 0 && kind !== void 0 ? { symbol, path: path42, kind } : path42 !== void 0 ? { symbol, path: path42 } : kind !== void 0 ? { symbol, kind } : { symbol };
24206
24330
  return item;
24207
24331
  }
24208
24332
  function classifySpawnError(err) {
@@ -24275,8 +24399,8 @@ var DEFAULT_MAX_BINARY_SIZE_BYTES = 50 * 1024 * 1024;
24275
24399
  var DEFAULT_GRACE_PERIOD_DAYS = 7;
24276
24400
 
24277
24401
  // src/binary-lifecycle/backend.ts
24278
- import fsp from "fs/promises";
24279
- import path23 from "path";
24402
+ import fsp2 from "fs/promises";
24403
+ import path24 from "path";
24280
24404
  var FilesystemBackend = class {
24281
24405
  type = "filesystem";
24282
24406
  basePath;
@@ -24284,30 +24408,30 @@ var FilesystemBackend = class {
24284
24408
  if (!basePath || basePath.trim().length === 0) {
24285
24409
  throw new Error("FilesystemBackend requires a non-empty basePath");
24286
24410
  }
24287
- this.basePath = path23.resolve(basePath);
24411
+ this.basePath = path24.resolve(basePath);
24288
24412
  }
24289
24413
  resolveRemotePath(remotePath) {
24290
- const resolved = path23.isAbsolute(remotePath) ? path23.resolve(remotePath) : path23.resolve(this.basePath, remotePath);
24291
- const relative = path23.relative(this.basePath, resolved);
24292
- if (relative === ".." || relative.startsWith(`..${path23.sep}`) || path23.isAbsolute(relative)) {
24414
+ const resolved = path24.isAbsolute(remotePath) ? path24.resolve(remotePath) : path24.resolve(this.basePath, remotePath);
24415
+ const relative = path24.relative(this.basePath, resolved);
24416
+ if (relative === ".." || relative.startsWith(`..${path24.sep}`) || path24.isAbsolute(relative)) {
24293
24417
  throw new Error(`FilesystemBackend remotePath escapes basePath: ${JSON.stringify(remotePath)}`);
24294
24418
  }
24295
24419
  return resolved;
24296
24420
  }
24297
24421
  isInsideBase(candidate, realBase) {
24298
- const relative = path23.relative(realBase, candidate);
24299
- return relative === "" || relative !== ".." && !relative.startsWith(`..${path23.sep}`) && !path23.isAbsolute(relative);
24422
+ const relative = path24.relative(realBase, candidate);
24423
+ return relative === "" || relative !== ".." && !relative.startsWith(`..${path24.sep}`) && !path24.isAbsolute(relative);
24300
24424
  }
24301
24425
  async realBasePathIfExists() {
24302
24426
  try {
24303
- const stat5 = await fsp.lstat(this.basePath);
24427
+ const stat5 = await fsp2.lstat(this.basePath);
24304
24428
  if (stat5.isSymbolicLink()) {
24305
24429
  throw new Error(`FilesystemBackend basePath must not be a symlink: ${this.basePath}`);
24306
24430
  }
24307
24431
  if (!stat5.isDirectory()) {
24308
24432
  throw new Error(`FilesystemBackend basePath must be a directory: ${this.basePath}`);
24309
24433
  }
24310
- return await fsp.realpath(this.basePath);
24434
+ return await fsp2.realpath(this.basePath);
24311
24435
  } catch (err) {
24312
24436
  if (err.code === "ENOENT") {
24313
24437
  return null;
@@ -24316,7 +24440,7 @@ var FilesystemBackend = class {
24316
24440
  }
24317
24441
  }
24318
24442
  async ensureBaseDirectory() {
24319
- await fsp.mkdir(this.basePath, { recursive: true });
24443
+ await fsp2.mkdir(this.basePath, { recursive: true });
24320
24444
  const realBase = await this.realBasePathIfExists();
24321
24445
  if (realBase === null) {
24322
24446
  throw new Error(`FilesystemBackend failed to create basePath: ${this.basePath}`);
@@ -24325,15 +24449,15 @@ var FilesystemBackend = class {
24325
24449
  }
24326
24450
  async ensureSafeParentDirectory(dest) {
24327
24451
  const realBase = await this.ensureBaseDirectory();
24328
- const destDir = path23.dirname(dest);
24329
- const relativeDir = path23.relative(this.basePath, destDir);
24330
- const segments = relativeDir === "" ? [] : relativeDir.split(path23.sep);
24452
+ const destDir = path24.dirname(dest);
24453
+ const relativeDir = path24.relative(this.basePath, destDir);
24454
+ const segments = relativeDir === "" ? [] : relativeDir.split(path24.sep);
24331
24455
  let current = this.basePath;
24332
24456
  for (const segment of segments) {
24333
24457
  if (segment === "." || segment === "") continue;
24334
- current = path23.join(current, segment);
24458
+ current = path24.join(current, segment);
24335
24459
  try {
24336
- const stat5 = await fsp.lstat(current);
24460
+ const stat5 = await fsp2.lstat(current);
24337
24461
  if (stat5.isSymbolicLink()) {
24338
24462
  throw new Error(`FilesystemBackend remotePath traverses symlink: ${current}`);
24339
24463
  }
@@ -24344,10 +24468,10 @@ var FilesystemBackend = class {
24344
24468
  if (err.code !== "ENOENT") {
24345
24469
  throw err;
24346
24470
  }
24347
- await fsp.mkdir(current);
24471
+ await fsp2.mkdir(current);
24348
24472
  }
24349
24473
  }
24350
- const realParent = await fsp.realpath(destDir);
24474
+ const realParent = await fsp2.realpath(destDir);
24351
24475
  if (!this.isInsideBase(realParent, realBase)) {
24352
24476
  throw new Error(`FilesystemBackend remotePath parent escapes basePath: ${dest}`);
24353
24477
  }
@@ -24359,16 +24483,16 @@ var FilesystemBackend = class {
24359
24483
  if (realBase === null) {
24360
24484
  return null;
24361
24485
  }
24362
- const destDir = path23.dirname(dest);
24363
- const relativeDir = path23.relative(this.basePath, destDir);
24364
- const segments = relativeDir === "" ? [] : relativeDir.split(path23.sep);
24486
+ const destDir = path24.dirname(dest);
24487
+ const relativeDir = path24.relative(this.basePath, destDir);
24488
+ const segments = relativeDir === "" ? [] : relativeDir.split(path24.sep);
24365
24489
  let current = this.basePath;
24366
24490
  for (const segment of segments) {
24367
24491
  if (segment === "." || segment === "") continue;
24368
- current = path23.join(current, segment);
24492
+ current = path24.join(current, segment);
24369
24493
  let stat5;
24370
24494
  try {
24371
- stat5 = await fsp.lstat(current);
24495
+ stat5 = await fsp2.lstat(current);
24372
24496
  } catch (err) {
24373
24497
  if (err.code === "ENOENT") {
24374
24498
  return null;
@@ -24382,7 +24506,7 @@ var FilesystemBackend = class {
24382
24506
  return null;
24383
24507
  }
24384
24508
  }
24385
- const realParent = await fsp.realpath(destDir).catch((err) => {
24509
+ const realParent = await fsp2.realpath(destDir).catch((err) => {
24386
24510
  if (isErrnoCode(err, "ENOENT")) return null;
24387
24511
  throw err;
24388
24512
  });
@@ -24393,7 +24517,7 @@ var FilesystemBackend = class {
24393
24517
  throw new Error(`FilesystemBackend remotePath parent escapes basePath: ${JSON.stringify(remotePath)}`);
24394
24518
  }
24395
24519
  try {
24396
- const stat5 = await fsp.lstat(dest);
24520
+ const stat5 = await fsp2.lstat(dest);
24397
24521
  if (stat5.isSymbolicLink()) {
24398
24522
  throw new Error(`FilesystemBackend remotePath points to symlink: ${dest}`);
24399
24523
  }
@@ -24406,20 +24530,20 @@ var FilesystemBackend = class {
24406
24530
  }
24407
24531
  throw err;
24408
24532
  }
24409
- const realDest = await fsp.realpath(dest);
24533
+ const realDest = await fsp2.realpath(dest);
24410
24534
  if (!this.isInsideBase(realDest, realBase)) {
24411
24535
  throw new Error(`FilesystemBackend remotePath escapes basePath: ${JSON.stringify(remotePath)}`);
24412
24536
  }
24413
24537
  return dest;
24414
24538
  }
24415
24539
  async upload(localPath, remotePath) {
24416
- if (path23.isAbsolute(remotePath)) {
24540
+ if (path24.isAbsolute(remotePath)) {
24417
24541
  throw new Error(`FilesystemBackend upload remotePath must be relative: ${JSON.stringify(remotePath)}`);
24418
24542
  }
24419
24543
  const dest = this.resolveRemotePath(remotePath);
24420
24544
  const realBase = await this.ensureSafeParentDirectory(dest);
24421
24545
  try {
24422
- const stat5 = await fsp.lstat(dest);
24546
+ const stat5 = await fsp2.lstat(dest);
24423
24547
  if (stat5.isSymbolicLink()) {
24424
24548
  throw new Error(`FilesystemBackend remotePath points to symlink: ${dest}`);
24425
24549
  }
@@ -24428,8 +24552,8 @@ var FilesystemBackend = class {
24428
24552
  throw err;
24429
24553
  }
24430
24554
  }
24431
- await fsp.copyFile(localPath, dest);
24432
- const realDest = await fsp.realpath(dest);
24555
+ await fsp2.copyFile(localPath, dest);
24556
+ const realDest = await fsp2.realpath(dest);
24433
24557
  if (!this.isInsideBase(realDest, realBase)) {
24434
24558
  throw new Error(`FilesystemBackend remotePath escapes basePath: ${JSON.stringify(remotePath)}`);
24435
24559
  }
@@ -24445,7 +24569,7 @@ var FilesystemBackend = class {
24445
24569
  return;
24446
24570
  }
24447
24571
  try {
24448
- await fsp.unlink(dest);
24572
+ await fsp2.unlink(dest);
24449
24573
  } catch (err) {
24450
24574
  if (err.code !== "ENOENT") throw err;
24451
24575
  }
@@ -24485,8 +24609,8 @@ function createBackend(cfg) {
24485
24609
  }
24486
24610
 
24487
24611
  // src/binary-lifecycle/scanner.ts
24488
- import fsp2 from "fs/promises";
24489
- import path24 from "path";
24612
+ import fsp3 from "fs/promises";
24613
+ import path25 from "path";
24490
24614
  import crypto from "crypto";
24491
24615
  function matchesPatterns(filename, patterns) {
24492
24616
  const lower = filename.toLowerCase();
@@ -24506,13 +24630,13 @@ async function scanForBinaries(memoryDir, config, manifest) {
24506
24630
  async function walk(dir) {
24507
24631
  let entries;
24508
24632
  try {
24509
- entries = await fsp2.readdir(dir, { withFileTypes: true });
24633
+ entries = await fsp3.readdir(dir, { withFileTypes: true });
24510
24634
  } catch {
24511
24635
  return;
24512
24636
  }
24513
24637
  for (const entry of entries) {
24514
- const fullPath = path24.join(dir, entry.name);
24515
- const relativePath = path24.relative(memoryDir, fullPath).split(path24.sep).join("/");
24638
+ const fullPath = path25.join(dir, entry.name);
24639
+ const relativePath = path25.relative(memoryDir, fullPath).split(path25.sep).join("/");
24516
24640
  if (entry.isDirectory()) {
24517
24641
  if (entry.name === ".binary-lifecycle") continue;
24518
24642
  await walk(fullPath);
@@ -24521,7 +24645,7 @@ async function scanForBinaries(memoryDir, config, manifest) {
24521
24645
  if (!entry.isFile()) continue;
24522
24646
  if (!matchesPatterns(entry.name, config.scanPatterns)) continue;
24523
24647
  try {
24524
- const stat5 = await fsp2.stat(fullPath);
24648
+ const stat5 = await fsp3.stat(fullPath);
24525
24649
  if (stat5.size > config.maxBinarySizeBytes) continue;
24526
24650
  if (stat5.size === 0) continue;
24527
24651
  const existing = tracked.get(relativePath);
@@ -24546,27 +24670,27 @@ async function scanForBinaries(memoryDir, config, manifest) {
24546
24670
  return results;
24547
24671
  }
24548
24672
  async function hashFile(filePath) {
24549
- const content = await fsp2.readFile(filePath);
24673
+ const content = await fsp3.readFile(filePath);
24550
24674
  return crypto.createHash("sha256").update(content).digest("hex");
24551
24675
  }
24552
24676
 
24553
24677
  // src/binary-lifecycle/manifest.ts
24554
- import fsp3 from "fs/promises";
24555
- import path25 from "path";
24678
+ import fsp4 from "fs/promises";
24679
+ import path26 from "path";
24556
24680
  import crypto2 from "crypto";
24557
24681
  var MANIFEST_DIR = ".binary-lifecycle";
24558
24682
  var MANIFEST_FILE = "manifest.json";
24559
24683
  function manifestDir(memoryDir) {
24560
- return path25.join(memoryDir, MANIFEST_DIR);
24684
+ return path26.join(memoryDir, MANIFEST_DIR);
24561
24685
  }
24562
24686
  function manifestPath(memoryDir) {
24563
- return path25.join(memoryDir, MANIFEST_DIR, MANIFEST_FILE);
24687
+ return path26.join(memoryDir, MANIFEST_DIR, MANIFEST_FILE);
24564
24688
  }
24565
24689
  async function readManifest(memoryDir) {
24566
24690
  const filePath = manifestPath(memoryDir);
24567
24691
  let raw;
24568
24692
  try {
24569
- raw = await fsp3.readFile(filePath, "utf-8");
24693
+ raw = await fsp4.readFile(filePath, "utf-8");
24570
24694
  } catch (err) {
24571
24695
  if (err.code === "ENOENT") {
24572
24696
  return emptyManifest();
@@ -24590,17 +24714,17 @@ async function readManifest(memoryDir) {
24590
24714
  }
24591
24715
  async function writeManifest(memoryDir, manifest) {
24592
24716
  const dir = manifestDir(memoryDir);
24593
- await fsp3.mkdir(dir, { recursive: true });
24717
+ await fsp4.mkdir(dir, { recursive: true });
24594
24718
  const dest = manifestPath(memoryDir);
24595
24719
  const tmpSuffix = crypto2.randomBytes(8).toString("hex");
24596
24720
  const tmpPath = `${dest}.${tmpSuffix}.tmp`;
24597
24721
  const content = JSON.stringify(manifest, null, 2) + "\n";
24598
- await fsp3.writeFile(tmpPath, content, "utf-8");
24722
+ await fsp4.writeFile(tmpPath, content, "utf-8");
24599
24723
  try {
24600
- await fsp3.rename(tmpPath, dest);
24724
+ await fsp4.rename(tmpPath, dest);
24601
24725
  } catch (renameErr) {
24602
24726
  try {
24603
- await fsp3.unlink(tmpPath);
24727
+ await fsp4.unlink(tmpPath);
24604
24728
  } catch {
24605
24729
  }
24606
24730
  throw renameErr;
@@ -24611,18 +24735,18 @@ function emptyManifest() {
24611
24735
  }
24612
24736
 
24613
24737
  // src/binary-lifecycle/pipeline.ts
24614
- import fsp4 from "fs/promises";
24615
- import path26 from "path";
24738
+ import fsp5 from "fs/promises";
24739
+ import path27 from "path";
24616
24740
  import crypto3 from "crypto";
24617
24741
  var historicalIdCache = new HistoricalEntityCanonicalIdCache();
24618
24742
  function isRecallCorpusMarkdown(mdPath, memoryDir) {
24619
- const rel = path26.relative(memoryDir, mdPath);
24620
- if (rel.startsWith("..") || path26.isAbsolute(rel)) return false;
24621
- const top = rel.split(path26.sep)[0];
24743
+ const rel = path27.relative(memoryDir, mdPath);
24744
+ if (rel.startsWith("..") || path27.isAbsolute(rel)) return false;
24745
+ const top = rel.split(path27.sep)[0];
24622
24746
  return RECALL_FALLBACK_DIRS.includes(top);
24623
24747
  }
24624
24748
  async function hashFile2(filePath) {
24625
- const content = await fsp4.readFile(filePath);
24749
+ const content = await fsp5.readFile(filePath);
24626
24750
  return crypto3.createHash("sha256").update(content).digest("hex");
24627
24751
  }
24628
24752
  function guessMimeType(ext) {
@@ -24642,13 +24766,13 @@ function escapeRegex(s) {
24642
24766
  return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
24643
24767
  }
24644
24768
  function resolveManifestAssetPath(memoryDir, originalPath) {
24645
- if (originalPath.length === 0 || originalPath.includes("\0") || originalPath.includes("\\") || path26.isAbsolute(originalPath) || path26.win32.isAbsolute(originalPath)) {
24769
+ if (originalPath.length === 0 || originalPath.includes("\0") || originalPath.includes("\\") || path27.isAbsolute(originalPath) || path27.win32.isAbsolute(originalPath)) {
24646
24770
  return null;
24647
24771
  }
24648
- const memoryRoot = path26.resolve(memoryDir);
24649
- const fullPath = path26.resolve(memoryRoot, originalPath);
24650
- const relative = path26.relative(memoryRoot, fullPath);
24651
- if (relative === "" || relative === ".." || relative.startsWith(`..${path26.sep}`) || path26.isAbsolute(relative)) {
24772
+ const memoryRoot = path27.resolve(memoryDir);
24773
+ const fullPath = path27.resolve(memoryRoot, originalPath);
24774
+ const relative = path27.relative(memoryRoot, fullPath);
24775
+ if (relative === "" || relative === ".." || relative.startsWith(`..${path27.sep}`) || path27.isAbsolute(relative)) {
24652
24776
  return null;
24653
24777
  }
24654
24778
  return fullPath;
@@ -24659,7 +24783,7 @@ function validateBinaryLifecycleConfig(config) {
24659
24783
  }
24660
24784
  }
24661
24785
  function remotePathForAsset(backend, relPath) {
24662
- const normalized = relPath.split(path26.sep).join("/");
24786
+ const normalized = relPath.split(path27.sep).join("/");
24663
24787
  if (backend.type === "filesystem") {
24664
24788
  return `.binary-lifecycle/mirrors/${normalized}`;
24665
24789
  }
@@ -24672,11 +24796,11 @@ async function stageMirror(memoryDir, newPaths, backend, assets, log2, dryRun) {
24672
24796
  let mirrored = 0;
24673
24797
  const errors = [];
24674
24798
  for (const relPath of newPaths) {
24675
- const fullPath = path26.join(memoryDir, relPath);
24799
+ const fullPath = path27.join(memoryDir, relPath);
24676
24800
  try {
24677
- const stat5 = await fsp4.stat(fullPath);
24801
+ const stat5 = await fsp5.stat(fullPath);
24678
24802
  const contentHash = await hashFile2(fullPath);
24679
- const ext = path26.extname(relPath);
24803
+ const ext = path27.extname(relPath);
24680
24804
  const mimeType = guessMimeType(ext);
24681
24805
  const remotePath = remotePathForAsset(backend, relPath);
24682
24806
  let backendLocation = remotePath;
@@ -24827,7 +24951,7 @@ async function stageRedirect(memoryDir, assets, log2, dryRun, readMarkdownFile,
24827
24951
  for (const update of updates) {
24828
24952
  try {
24829
24953
  await withRawEntityPageMutation(memoryDir, update.mdPath, async () => {
24830
- const stateDir = path26.join(memoryDir, "state");
24954
+ const stateDir = path27.join(memoryDir, "state");
24831
24955
  const kind = classifyEntityRefWritePath(memoryDir, update.mdPath);
24832
24956
  if (kind === "memory") {
24833
24957
  const idsAtWrite = historicalIdCache.get(stateDir);
@@ -24920,10 +25044,10 @@ async function countRemainingLocalReferences(memoryDir, asset, assetAbsolute, md
24920
25044
  return { remaining, errors };
24921
25045
  }
24922
25046
  function markdownReferencePattern(asset, assetAbsolute, mdPath) {
24923
- const mdDir = path26.dirname(mdPath);
25047
+ const mdDir = path27.dirname(mdPath);
24924
25048
  const candidates = /* @__PURE__ */ new Set();
24925
25049
  const addCandidate = (candidate) => {
24926
- const normalized = candidate.split(path26.sep).join("/");
25050
+ const normalized = candidate.split(path27.sep).join("/");
24927
25051
  if (normalized.length === 0) return;
24928
25052
  candidates.add(normalized);
24929
25053
  const isParentTraversal = normalized === ".." || normalized.startsWith("../");
@@ -24931,10 +25055,10 @@ function markdownReferencePattern(asset, assetAbsolute, mdPath) {
24931
25055
  candidates.add(`./${normalized}`);
24932
25056
  }
24933
25057
  };
24934
- addCandidate(path26.relative(mdDir, assetAbsolute));
24935
- const originalPath = asset.originalPath.split(path26.sep).join("/");
24936
- const originalAsFileRelative = path26.resolve(mdDir, ...originalPath.split("/"));
24937
- if (path26.resolve(originalAsFileRelative) === path26.resolve(assetAbsolute)) {
25058
+ addCandidate(path27.relative(mdDir, assetAbsolute));
25059
+ const originalPath = asset.originalPath.split(path27.sep).join("/");
25060
+ const originalAsFileRelative = path27.resolve(mdDir, ...originalPath.split("/"));
25061
+ if (path27.resolve(originalAsFileRelative) === path27.resolve(assetAbsolute)) {
24938
25062
  addCandidate(originalPath);
24939
25063
  }
24940
25064
  addCandidate(`/${originalPath}`);
@@ -24998,7 +25122,7 @@ async function stageClean(memoryDir, assets, backend, gracePeriodDays, log2, dry
24998
25122
  continue;
24999
25123
  }
25000
25124
  if (!dryRun) {
25001
- await fsp4.unlink(fullPath);
25125
+ await fsp5.unlink(fullPath);
25002
25126
  asset.status = "cleaned";
25003
25127
  asset.cleanedAt = (/* @__PURE__ */ new Date()).toISOString();
25004
25128
  }
@@ -25025,12 +25149,12 @@ async function findMarkdownFiles(dir) {
25025
25149
  async function walk(current) {
25026
25150
  let entries;
25027
25151
  try {
25028
- entries = await fsp4.readdir(current, { withFileTypes: true });
25152
+ entries = await fsp5.readdir(current, { withFileTypes: true });
25029
25153
  } catch {
25030
25154
  return;
25031
25155
  }
25032
25156
  for (const entry of entries) {
25033
- const full = path26.join(current, entry.name);
25157
+ const full = path27.join(current, entry.name);
25034
25158
  if (entry.isDirectory()) {
25035
25159
  if (entry.name === ".binary-lifecycle") continue;
25036
25160
  await walk(full);
@@ -25072,8 +25196,8 @@ async function runBinaryLifecyclePipeline(memoryDir, config, backend, log2, opts
25072
25196
  manifest.assets,
25073
25197
  log2,
25074
25198
  dryRun,
25075
- opts?.readMarkdownFile ?? ((filePath) => fsp4.readFile(filePath, "utf-8")),
25076
- opts?.writeMarkdownFile ?? ((filePath, content) => fsp4.writeFile(filePath, content, "utf-8"))
25199
+ opts?.readMarkdownFile ?? ((filePath) => fsp5.readFile(filePath, "utf-8")),
25200
+ opts?.writeMarkdownFile ?? ((filePath, content) => fsp5.writeFile(filePath, content, "utf-8"))
25077
25201
  );
25078
25202
  const cleanResult = await stageClean(
25079
25203
  memoryDir,
@@ -25105,7 +25229,7 @@ async function runBinaryLifecyclePipeline(memoryDir, config, backend, log2, opts
25105
25229
 
25106
25230
  // src/projection/index.ts
25107
25231
  import fs from "fs";
25108
- import path27 from "path";
25232
+ import path28 from "path";
25109
25233
  var VALID_PROJECTION_CATEGORIES = new Set(ALL_CATEGORY_KEYS);
25110
25234
  async function generateContextTree(options) {
25111
25235
  const startTime = Date.now();
@@ -25120,8 +25244,8 @@ async function generateContextTree(options) {
25120
25244
  let nodesGenerated = 0;
25121
25245
  let nodesSkipped = 0;
25122
25246
  const categoryCounts = {};
25123
- const resolvedMemoryDir = path27.resolve(memoryDir);
25124
- const resolvedOutputDir = path27.resolve(outputDir);
25247
+ const resolvedMemoryDir = path28.resolve(memoryDir);
25248
+ const resolvedOutputDir = path28.resolve(outputDir);
25125
25249
  const requestedCategories = validateProjectionCategories(filterCategories);
25126
25250
  const realMemoryDir = assertSafeMemoryRoot(resolvedMemoryDir);
25127
25251
  assertNotSymlink(resolvedOutputDir, "context tree outputDir");
@@ -25159,7 +25283,7 @@ async function generateContextTree(options) {
25159
25283
  }
25160
25284
  }
25161
25285
  if (includeEntities) {
25162
- const entitiesDir = path27.join(memoryDir, "entities");
25286
+ const entitiesDir = path28.join(memoryDir, "entities");
25163
25287
  if (fs.existsSync(entitiesDir)) {
25164
25288
  assertSafeInputRoot(realMemoryDir, entitiesDir, "entities root");
25165
25289
  categoryCounts["entity"] = 0;
@@ -25171,7 +25295,7 @@ async function generateContextTree(options) {
25171
25295
  continue;
25172
25296
  }
25173
25297
  const content = fs.readFileSync(filePath, "utf8");
25174
- const fileName = path27.basename(filePath, ".md");
25298
+ const fileName = path28.basename(filePath, ".md");
25175
25299
  const node = projectEntityNode(fileName, content);
25176
25300
  const outputPath = resolveContainedOutputPath(realOutputDir, "entities", `${fileName}.md`);
25177
25301
  writeProjectedContent(realOutputDir, outputPath, node.content);
@@ -25183,7 +25307,7 @@ async function generateContextTree(options) {
25183
25307
  }
25184
25308
  const shouldIncludeQuestions = includeQuestions && (requestedCategories === void 0 || requestedCategories.includes("question"));
25185
25309
  if (shouldIncludeQuestions) {
25186
- const questionsDir = path27.join(memoryDir, "questions");
25310
+ const questionsDir = path28.join(memoryDir, "questions");
25187
25311
  if (fs.existsSync(questionsDir)) {
25188
25312
  assertSafeInputRoot(realMemoryDir, questionsDir, "questions root");
25189
25313
  categoryCounts["question"] = 0;
@@ -25224,8 +25348,8 @@ async function generateContextTree(options) {
25224
25348
  };
25225
25349
  }
25226
25350
  function isPathInside(root, candidate) {
25227
- const relative = path27.relative(root, candidate);
25228
- return relative === "" || !relative.startsWith("..") && !path27.isAbsolute(relative);
25351
+ const relative = path28.relative(root, candidate);
25352
+ return relative === "" || !relative.startsWith("..") && !path28.isAbsolute(relative);
25229
25353
  }
25230
25354
  function assertNotSymlink(targetPath, label) {
25231
25355
  try {
@@ -25262,12 +25386,12 @@ function assertSafeInputRoot(realMemoryDir, targetPath, label) {
25262
25386
  }
25263
25387
  function assertSafeOutputTarget(realOutputDir, outputPath) {
25264
25388
  let current = realOutputDir;
25265
- const relative = path27.relative(realOutputDir, outputPath);
25266
- if (relative.startsWith("..") || path27.isAbsolute(relative)) {
25389
+ const relative = path28.relative(realOutputDir, outputPath);
25390
+ if (relative.startsWith("..") || path28.isAbsolute(relative)) {
25267
25391
  throw new Error(`context tree output path escapes outputDir: ${outputPath}`);
25268
25392
  }
25269
- for (const segment of relative.split(path27.sep).filter(Boolean)) {
25270
- current = path27.join(current, segment);
25393
+ for (const segment of relative.split(path28.sep).filter(Boolean)) {
25394
+ current = path28.join(current, segment);
25271
25395
  try {
25272
25396
  const stat5 = fs.lstatSync(current);
25273
25397
  if (stat5.isSymbolicLink()) {
@@ -25297,17 +25421,17 @@ function validateProjectionCategories(categories) {
25297
25421
  return validated;
25298
25422
  }
25299
25423
  function resolveContainedOutputPath(outputRoot, ...segments) {
25300
- const resolved = path27.resolve(outputRoot, ...segments);
25301
- const relative = path27.relative(outputRoot, resolved);
25302
- if (relative === "" || !relative.startsWith("..") && !path27.isAbsolute(relative)) {
25424
+ const resolved = path28.resolve(outputRoot, ...segments);
25425
+ const relative = path28.relative(outputRoot, resolved);
25426
+ if (relative === "" || !relative.startsWith("..") && !path28.isAbsolute(relative)) {
25303
25427
  return resolved;
25304
25428
  }
25305
25429
  throw new Error(`context tree output path escapes outputDir: ${segments.join("/")}`);
25306
25430
  }
25307
25431
  function writeProjectedContent(realOutputDir, outputPath, generatedContent) {
25308
25432
  assertSafeOutputTarget(realOutputDir, outputPath);
25309
- fs.mkdirSync(path27.dirname(outputPath), { recursive: true });
25310
- const realParent = fs.realpathSync(path27.dirname(outputPath));
25433
+ fs.mkdirSync(path28.dirname(outputPath), { recursive: true });
25434
+ const realParent = fs.realpathSync(path28.dirname(outputPath));
25311
25435
  if (!isPathInside(realOutputDir, realParent)) {
25312
25436
  throw new Error(`context tree output path escapes outputDir: ${outputPath}`);
25313
25437
  }
@@ -25346,7 +25470,7 @@ function walkR(dir, realMemoryDir) {
25346
25470
  const results = [];
25347
25471
  function walk(directory) {
25348
25472
  for (const entry of fs.readdirSync(directory, { withFileTypes: true })) {
25349
- const fullPath = path27.join(directory, entry.name);
25473
+ const fullPath = path28.join(directory, entry.name);
25350
25474
  if (entry.isSymbolicLink()) {
25351
25475
  throw new Error(`context tree input path contains symlink: ${fullPath}`);
25352
25476
  }
@@ -25399,13 +25523,13 @@ function extractBody(content) {
25399
25523
  }
25400
25524
  function projectNode(filePath, category, fm, rawContent) {
25401
25525
  const body = extractBody(rawContent);
25402
- const fileName = path27.basename(filePath, ".md");
25403
- const dateDir = path27.basename(path27.dirname(filePath));
25526
+ const fileName = path28.basename(filePath, ".md");
25527
+ const dateDir = path28.basename(path28.dirname(filePath));
25404
25528
  let relPath;
25405
25529
  if (/^\d{4}-\d{2}-\d{2}$/.test(dateDir)) {
25406
- relPath = path27.join(category, dateDir, `${fileName}.md`);
25530
+ relPath = path28.join(category, dateDir, `${fileName}.md`);
25407
25531
  } else {
25408
- relPath = path27.join(category, `${fileName}.md`);
25532
+ relPath = path28.join(category, `${fileName}.md`);
25409
25533
  }
25410
25534
  const generatedAt = (/* @__PURE__ */ new Date()).toISOString();
25411
25535
  const md = `# ${fm.id}
@@ -25451,7 +25575,7 @@ function projectEntityNode(fileName, content) {
25451
25575
  ${content}
25452
25576
  `;
25453
25577
  return {
25454
- path: path27.join("entities", `${fileName}.md`),
25578
+ path: path28.join("entities", `${fileName}.md`),
25455
25579
  category: "entity",
25456
25580
  title: fileName,
25457
25581
  content: md,
@@ -25504,7 +25628,7 @@ function generateIndex(categoryCounts, outputDir) {
25504
25628
 
25505
25629
  // src/onboarding/index.ts
25506
25630
  import fs2 from "fs";
25507
- import path28 from "path";
25631
+ import path29 from "path";
25508
25632
  var LANGUAGE_RULES = [
25509
25633
  {
25510
25634
  language: "TypeScript",
@@ -25606,7 +25730,7 @@ function onboard(options) {
25606
25730
  maxDepth = 6,
25607
25731
  excludeDirs = []
25608
25732
  } = options;
25609
- const directory = path28.resolve(options.directory ?? process.cwd());
25733
+ const directory = path29.resolve(options.directory ?? process.cwd());
25610
25734
  let rootStat;
25611
25735
  try {
25612
25736
  rootStat = fs2.statSync(directory);
@@ -25648,7 +25772,7 @@ function walkDir(root, exclude, maxDepth) {
25648
25772
  }
25649
25773
  for (const entry of entries) {
25650
25774
  if (exclude.has(entry.name)) continue;
25651
- const fullPath = path28.join(dir, entry.name);
25775
+ const fullPath = path29.join(dir, entry.name);
25652
25776
  if (entry.isDirectory()) {
25653
25777
  walk(fullPath, depth + 1);
25654
25778
  } else if (entry.isFile()) {
@@ -25663,11 +25787,11 @@ function detectLanguages(files, root) {
25663
25787
  const results = [];
25664
25788
  const extCounts = /* @__PURE__ */ new Map();
25665
25789
  for (const f of files) {
25666
- const ext = path28.extname(f).toLowerCase();
25790
+ const ext = path29.extname(f).toLowerCase();
25667
25791
  if (ext) extCounts.set(ext, (extCounts.get(ext) ?? 0) + 1);
25668
25792
  }
25669
25793
  const rootFiles = new Set(
25670
- files.filter((f) => path28.dirname(f) === root).map((f) => path28.basename(f))
25794
+ files.filter((f) => path29.dirname(f) === root).map((f) => path29.basename(f))
25671
25795
  );
25672
25796
  for (const rule of LANGUAGE_RULES) {
25673
25797
  const evidence = [];
@@ -25711,7 +25835,7 @@ function detectLanguages(files, root) {
25711
25835
  }
25712
25836
  function detectShape(files, root) {
25713
25837
  const rootFiles = new Set(
25714
- files.filter((f) => path28.dirname(f) === root).map((f) => path28.basename(f))
25838
+ files.filter((f) => path29.dirname(f) === root).map((f) => path29.basename(f))
25715
25839
  );
25716
25840
  const rootDirs = /* @__PURE__ */ new Set();
25717
25841
  try {
@@ -25722,7 +25846,7 @@ function detectShape(files, root) {
25722
25846
  }
25723
25847
  const evidence = [];
25724
25848
  if (rootFiles.has("package.json")) {
25725
- const pkg = readJsonSafe(path28.join(root, "package.json"));
25849
+ const pkg = readJsonSafe(path29.join(root, "package.json"));
25726
25850
  if (pkg?.workspaces) {
25727
25851
  evidence.push("package.json has workspaces");
25728
25852
  return { shape: "monorepo", evidence };
@@ -25736,13 +25860,13 @@ function detectShape(files, root) {
25736
25860
  evidence.push("workspace manifest found");
25737
25861
  return { shape: "workspace", evidence };
25738
25862
  }
25739
- const cargoToml = readTomlWorkspace(path28.join(root, "Cargo.toml"));
25863
+ const cargoToml = readTomlWorkspace(path29.join(root, "Cargo.toml"));
25740
25864
  if (cargoToml) {
25741
25865
  evidence.push("Cargo.toml has workspace");
25742
25866
  return { shape: "workspace", evidence };
25743
25867
  }
25744
25868
  if (rootFiles.has("package.json")) {
25745
- const pkg = readJsonSafe(path28.join(root, "package.json"));
25869
+ const pkg = readJsonSafe(path29.join(root, "package.json"));
25746
25870
  if (pkg?.exports || pkg?.main) {
25747
25871
  if (pkg?.bin) {
25748
25872
  evidence.push("package.json has bin");
@@ -25776,8 +25900,8 @@ function discoverDocs(files, root) {
25776
25900
  { pattern: /^\.editorconfig$/i, kind: "config" }
25777
25901
  ];
25778
25902
  for (const filePath of files) {
25779
- const basename = path28.basename(filePath).toLowerCase();
25780
- const relPath = path28.relative(root, filePath);
25903
+ const basename = path29.basename(filePath).toLowerCase();
25904
+ const relPath = path29.relative(root, filePath);
25781
25905
  let kind;
25782
25906
  for (const { pattern, kind: k } of docPatterns) {
25783
25907
  if (pattern.test(basename)) {
@@ -25789,7 +25913,7 @@ function discoverDocs(files, root) {
25789
25913
  kind = "docs";
25790
25914
  }
25791
25915
  if (!kind && (basename.endsWith(".md") || basename.endsWith(".mdx"))) {
25792
- if (path28.dirname(relPath) === "." || isUnderDocsDir(relPath)) {
25916
+ if (path29.dirname(relPath) === "." || isUnderDocsDir(relPath)) {
25793
25917
  kind = "docs";
25794
25918
  }
25795
25919
  }
@@ -25810,7 +25934,7 @@ function discoverDocs(files, root) {
25810
25934
  return docs;
25811
25935
  }
25812
25936
  function isUnderDocsDir(relPath) {
25813
- const parts = relPath.split(path28.sep);
25937
+ const parts = relPath.split(path29.sep);
25814
25938
  return parts[0] === "docs" || parts[0] === "doc" || parts[0] === "documentation";
25815
25939
  }
25816
25940
  function buildPlan(languages, shape, docs, _root) {
@@ -25854,7 +25978,7 @@ function readTomlWorkspace(filePath) {
25854
25978
 
25855
25979
  // src/curation/index.ts
25856
25980
  import fs3 from "fs";
25857
- import path29 from "path";
25981
+ import path30 from "path";
25858
25982
  import crypto4 from "crypto";
25859
25983
  async function curate(options) {
25860
25984
  const startTime = Date.now();
@@ -25945,12 +26069,12 @@ function resolveTargets(targetPath) {
25945
26069
  const extensions = /* @__PURE__ */ new Set([".md", ".txt", ".mdx", ".rst"]);
25946
26070
  function walk(dir) {
25947
26071
  for (const entry of fs3.readdirSync(dir, { withFileTypes: true })) {
25948
- const fullPath = path29.join(dir, entry.name);
26072
+ const fullPath = path30.join(dir, entry.name);
25949
26073
  if (entry.isDirectory()) {
25950
26074
  if (entry.name !== "node_modules" && entry.name !== ".git") {
25951
26075
  walk(fullPath);
25952
26076
  }
25953
- } else if (extensions.has(path29.extname(entry.name).toLowerCase())) {
26077
+ } else if (extensions.has(path30.extname(entry.name).toLowerCase())) {
25954
26078
  results.push(fullPath);
25955
26079
  }
25956
26080
  }
@@ -25959,12 +26083,12 @@ function resolveTargets(targetPath) {
25959
26083
  return results;
25960
26084
  }
25961
26085
  function resolveProvenanceRoot(targetPath) {
25962
- const resolvedTarget = path29.resolve(targetPath);
26086
+ const resolvedTarget = path30.resolve(targetPath);
25963
26087
  const stat5 = fs3.statSync(resolvedTarget);
25964
- return stat5.isFile() ? path29.dirname(resolvedTarget) : resolvedTarget;
26088
+ return stat5.isFile() ? path30.dirname(resolvedTarget) : resolvedTarget;
25965
26089
  }
25966
26090
  function extractStatements(content, filePath, projectRoot, source, sourceFileHash, categoryOverride, confidence, entityRef, tags) {
25967
- const relativePath = path29.relative(projectRoot, path29.resolve(filePath)) || path29.basename(filePath);
26091
+ const relativePath = path30.relative(projectRoot, path30.resolve(filePath)) || path30.basename(filePath);
25968
26092
  const statements = [];
25969
26093
  const now = (/* @__PURE__ */ new Date()).toISOString();
25970
26094
  const paragraphs = content.split(/\n{2,}/).map((p) => p.trim()).filter((p) => p.length > 20 && p.length < 2e3);
@@ -26058,7 +26182,7 @@ function loadExistingMemories(memoryDir) {
26058
26182
  if (!fs3.existsSync(memoryDir)) return result;
26059
26183
  const dirs = ALL_CATEGORY_DIRS;
26060
26184
  for (const dir of dirs) {
26061
- const fullDir = path29.join(memoryDir, dir);
26185
+ const fullDir = path30.join(memoryDir, dir);
26062
26186
  if (!fs3.existsSync(fullDir)) continue;
26063
26187
  walkFiles(fullDir, (filePath) => {
26064
26188
  const content = readFileSafe(filePath);
@@ -26081,11 +26205,11 @@ function writeStatement(stmt, memoryDir) {
26081
26205
  const now = /* @__PURE__ */ new Date();
26082
26206
  const dateDir = now.toISOString().split("T")[0];
26083
26207
  const categoryDir = getCategoryDir(memoryDir, stmt.category);
26084
- const dir = path29.join(categoryDir, dateDir);
26208
+ const dir = path30.join(categoryDir, dateDir);
26085
26209
  fs3.mkdirSync(dir, { recursive: true });
26086
26210
  const fileName = `${stmt.category}-${Date.now()}-${stmt.id.slice(0, 8)}.md`;
26087
- const filePath = path29.join(dir, fileName);
26088
- const historicalIds = historicalIdCache2.get(path29.join(memoryDir, "state"));
26211
+ const filePath = path30.join(dir, fileName);
26212
+ const historicalIds = historicalIdCache2.get(path30.join(memoryDir, "state"));
26089
26213
  const rawBody = `${[
26090
26214
  "---",
26091
26215
  `id: ${stmt.id}`,
@@ -26108,7 +26232,7 @@ ${stmt.content}
26108
26232
  fs3.writeFileSync(filePath, body);
26109
26233
  try {
26110
26234
  repairContentAfterJournalMoveSync({
26111
- stateDir: path29.join(memoryDir, "state"),
26235
+ stateDir: path30.join(memoryDir, "state"),
26112
26236
  cache: historicalIdCache2,
26113
26237
  idsAtWrite: historicalIds,
26114
26238
  rawContent: rawBody,
@@ -26169,7 +26293,7 @@ function extractBody2(content) {
26169
26293
  }
26170
26294
  function walkFiles(dir, callback) {
26171
26295
  for (const entry of fs3.readdirSync(dir, { withFileTypes: true })) {
26172
- const fullPath = path29.join(dir, entry.name);
26296
+ const fullPath = path30.join(dir, entry.name);
26173
26297
  if (entry.isDirectory()) {
26174
26298
  walkFiles(fullPath, callback);
26175
26299
  } else if (entry.name.endsWith(".md")) {
@@ -26181,7 +26305,7 @@ function walkFiles(dir, callback) {
26181
26305
  // src/dedup/index.ts
26182
26306
  import crypto5 from "crypto";
26183
26307
  import fs4 from "fs";
26184
- import path30 from "path";
26308
+ import path31 from "path";
26185
26309
  var DEFAULT_DEDUP_THRESHOLD = 0.85;
26186
26310
  var DEFAULT_MAX_LOAD = 1e4;
26187
26311
  function normalizeThreshold(value, defaultValue) {
@@ -26388,7 +26512,7 @@ function loadMemories(memoryDir, categories, maxLoad = 1e4) {
26388
26512
  const memoryRootReal = fs4.realpathSync(memoryDir);
26389
26513
  for (const category of allCategories) {
26390
26514
  if (result.length >= maxLoad) break;
26391
- const dir = path30.join(memoryDir, category);
26515
+ const dir = path31.join(memoryDir, category);
26392
26516
  if (!fs4.existsSync(dir)) continue;
26393
26517
  const categoryStat = fs4.lstatSync(dir);
26394
26518
  if (categoryStat.isSymbolicLink()) {
@@ -26449,15 +26573,15 @@ function extractBody3(content) {
26449
26573
  return match ? match[1].trim() : content.trim();
26450
26574
  }
26451
26575
  function assertPathInsideRoot2(rootReal, targetReal, sourcePath) {
26452
- const rel = path30.relative(rootReal, targetReal);
26453
- if (rel === "" || !rel.startsWith("..") && !path30.isAbsolute(rel)) {
26576
+ const rel = path31.relative(rootReal, targetReal);
26577
+ if (rel === "" || !rel.startsWith("..") && !path31.isAbsolute(rel)) {
26454
26578
  return;
26455
26579
  }
26456
26580
  throw new Error(`Refusing to scan memory path outside root: ${sourcePath}`);
26457
26581
  }
26458
26582
  function walkMdFiles(dir, memoryRootReal, categoryRootReal, callback) {
26459
26583
  for (const entry of fs4.readdirSync(dir, { withFileTypes: true })) {
26460
- const fullPath = path30.join(dir, entry.name);
26584
+ const fullPath = path31.join(dir, entry.name);
26461
26585
  const entryStat = fs4.lstatSync(fullPath);
26462
26586
  if (entryStat.isSymbolicLink()) {
26463
26587
  throw new Error(`Refusing to scan symlinked memory path: ${fullPath}`);
@@ -26475,7 +26599,7 @@ function walkMdFiles(dir, memoryRootReal, categoryRootReal, callback) {
26475
26599
 
26476
26600
  // src/sync/index.ts
26477
26601
  import fs5 from "fs";
26478
- import path31 from "path";
26602
+ import path32 from "path";
26479
26603
  import crypto6 from "crypto";
26480
26604
  var DEFAULT_EXTENSIONS = /* @__PURE__ */ new Set([".md", ".txt", ".mdx", ".rst"]);
26481
26605
  var DEFAULT_EXCLUDE2 = /* @__PURE__ */ new Set([
@@ -26497,7 +26621,7 @@ function syncChanges(options) {
26497
26621
  } = options;
26498
26622
  const extSet = new Set(extensions);
26499
26623
  const excludeSet = /* @__PURE__ */ new Set([...DEFAULT_EXCLUDE2, ...excludeDirs]);
26500
- const stateFilePath = options.stateFile ?? path31.join(memoryDir, ".sync-state.json");
26624
+ const stateFilePath = options.stateFile ?? path32.join(memoryDir, ".sync-state.json");
26501
26625
  const prevState = loadState(stateFilePath);
26502
26626
  const currentFiles = scanFiles(sourceDir, extSet, excludeSet);
26503
26627
  const changes = computeDiff(currentFiles, prevState.fileHashes, sourceDir);
@@ -26513,7 +26637,7 @@ function syncChanges(options) {
26513
26637
  for (const [relPath, hash] of Object.entries(currentFiles)) {
26514
26638
  newState.fileHashes[relPath] = hash;
26515
26639
  }
26516
- fs5.mkdirSync(path31.dirname(stateFilePath), { recursive: true });
26640
+ fs5.mkdirSync(path32.dirname(stateFilePath), { recursive: true });
26517
26641
  fs5.writeFileSync(stateFilePath, JSON.stringify(newState, null, 2));
26518
26642
  }
26519
26643
  return {
@@ -26579,13 +26703,13 @@ function scanFiles(root, extensions, exclude) {
26579
26703
  }
26580
26704
  for (const entry of entries) {
26581
26705
  if (exclude.has(entry.name)) continue;
26582
- const fullPath = path31.join(dir, entry.name);
26706
+ const fullPath = path32.join(dir, entry.name);
26583
26707
  if (entry.isDirectory()) {
26584
26708
  walk(fullPath);
26585
26709
  } else if (entry.isFile()) {
26586
- const ext = path31.extname(entry.name).toLowerCase();
26710
+ const ext = path32.extname(entry.name).toLowerCase();
26587
26711
  if (!extensions.has(ext)) continue;
26588
- const relPath = path31.relative(root, fullPath);
26712
+ const relPath = path32.relative(root, fullPath);
26589
26713
  try {
26590
26714
  const content = fs5.readFileSync(fullPath, "utf8");
26591
26715
  result[relPath] = hashContent3(content);
@@ -26600,7 +26724,7 @@ function scanFiles(root, extensions, exclude) {
26600
26724
  function computeDiff(current, previous, sourceDir) {
26601
26725
  const changes = [];
26602
26726
  for (const [relPath, hash] of Object.entries(current)) {
26603
- const fullPath = path31.join(sourceDir, relPath);
26727
+ const fullPath = path32.join(sourceDir, relPath);
26604
26728
  if (!(relPath in previous)) {
26605
26729
  let size = 0;
26606
26730
  try {
@@ -26633,7 +26757,7 @@ function computeDiff(current, previous, sourceDir) {
26633
26757
  for (const relPath of Object.keys(previous)) {
26634
26758
  if (!(relPath in current)) {
26635
26759
  changes.push({
26636
- filePath: path31.join(sourceDir, relPath),
26760
+ filePath: path32.join(sourceDir, relPath),
26637
26761
  relativePath: relPath,
26638
26762
  type: "deleted",
26639
26763
  currentHash: "",
@@ -26663,21 +26787,21 @@ function hashContent3(content) {
26663
26787
  import { spawnSync } from "child_process";
26664
26788
  import crypto7 from "crypto";
26665
26789
  import fs6 from "fs";
26666
- import path32 from "path";
26790
+ import path33 from "path";
26667
26791
  var historicalIdCache3 = new HistoricalEntityCanonicalIdCache();
26668
26792
  var MANIFEST_VERSION = 1;
26669
26793
  var MANIFEST_LOCK_STALE_MS = 3e4;
26670
26794
  var MANIFEST_LOCK_TIMEOUT_MS = MANIFEST_LOCK_STALE_MS + 1e4;
26671
26795
  var MANIFEST_LOCK_SLEEP_MS = 20;
26672
26796
  function normalizeSpaceMemoryDir(memoryDir) {
26673
- return path32.resolve(memoryDir);
26797
+ return path33.resolve(memoryDir);
26674
26798
  }
26675
26799
  function getSpacesDir(baseDir) {
26676
26800
  const homeDir = baseDir ?? resolveHomeDir();
26677
- return path32.join(homeDir, ".config", "engram", "spaces");
26801
+ return path33.join(homeDir, ".config", "engram", "spaces");
26678
26802
  }
26679
26803
  function getManifestPath(baseDir) {
26680
- return path32.join(getSpacesDir(baseDir), "manifest.json");
26804
+ return path33.join(getSpacesDir(baseDir), "manifest.json");
26681
26805
  }
26682
26806
  function loadManifest(baseDir, memoryDirOverride) {
26683
26807
  if (fs6.existsSync(getManifestPath(baseDir))) {
@@ -26724,9 +26848,9 @@ function readManifestUnlocked(baseDir, memoryDirOverride, options = {}) {
26724
26848
  }
26725
26849
  function saveManifestUnlocked(manifest, baseDir) {
26726
26850
  const manifestPath2 = getManifestPath(baseDir);
26727
- const manifestDir2 = path32.dirname(manifestPath2);
26851
+ const manifestDir2 = path33.dirname(manifestPath2);
26728
26852
  fs6.mkdirSync(manifestDir2, { recursive: true });
26729
- const tempPath = path32.join(manifestDir2, `.manifest.${process.pid}.${Date.now()}.${crypto7.randomUUID()}.tmp`);
26853
+ const tempPath = path33.join(manifestDir2, `.manifest.${process.pid}.${Date.now()}.${crypto7.randomUUID()}.tmp`);
26730
26854
  try {
26731
26855
  fs6.writeFileSync(tempPath, `${JSON.stringify(manifest, null, 2)}
26732
26856
  `, { flag: "wx" });
@@ -26741,7 +26865,7 @@ function saveManifestUnlocked(manifest, baseDir) {
26741
26865
  }
26742
26866
  function withManifestLock(baseDir, operation) {
26743
26867
  const lockDir = `${getManifestPath(baseDir)}.lock`;
26744
- fs6.mkdirSync(path32.dirname(lockDir), { recursive: true });
26868
+ fs6.mkdirSync(path33.dirname(lockDir), { recursive: true });
26745
26869
  const lockOwner = acquireManifestLock(lockDir);
26746
26870
  try {
26747
26871
  return operation();
@@ -26767,7 +26891,7 @@ function acquireManifestLock(lockDir) {
26767
26891
  try {
26768
26892
  fs6.mkdirSync(lockDir, { recursive: false });
26769
26893
  try {
26770
- fs6.writeFileSync(path32.join(lockDir, "owner"), `${owner}
26894
+ fs6.writeFileSync(path33.join(lockDir, "owner"), `${owner}
26771
26895
  `, { flag: "wx" });
26772
26896
  } catch (error) {
26773
26897
  fs6.rmSync(lockDir, { recursive: true, force: true });
@@ -26797,7 +26921,7 @@ function acquireManifestLock(lockDir) {
26797
26921
  }
26798
26922
  function releaseManifestLock(lockDir, owner) {
26799
26923
  try {
26800
- const ownerPath = path32.join(lockDir, "owner");
26924
+ const ownerPath = path33.join(lockDir, "owner");
26801
26925
  if (fs6.readFileSync(ownerPath, "utf8").trim() === owner) {
26802
26926
  fs6.rmSync(lockDir, { recursive: true, force: true });
26803
26927
  }
@@ -26813,7 +26937,7 @@ function removeStaleManifestLock(lockDir) {
26813
26937
  try {
26814
26938
  fs6.mkdirSync(reclaimDir, { recursive: false });
26815
26939
  try {
26816
- fs6.writeFileSync(path32.join(reclaimDir, "owner"), `${reclaimOwner}
26940
+ fs6.writeFileSync(path33.join(reclaimDir, "owner"), `${reclaimOwner}
26817
26941
  `, { flag: "wx" });
26818
26942
  } catch (error) {
26819
26943
  fs6.rmSync(reclaimDir, { recursive: true, force: true });
@@ -26888,7 +27012,7 @@ function readManifestLockSnapshot(lockDir) {
26888
27012
  throw error;
26889
27013
  }
26890
27014
  try {
26891
- const owner = fs6.readFileSync(path32.join(lockDir, "owner"), "utf8").trim();
27015
+ const owner = fs6.readFileSync(path33.join(lockDir, "owner"), "utf8").trim();
26892
27016
  return { mtimeMs: stat5.mtimeMs, owner };
26893
27017
  } catch (error) {
26894
27018
  if (error.code === "ENOENT") {
@@ -26960,8 +27084,8 @@ function sleepSync(ms) {
26960
27084
  }
26961
27085
  function createPersonalSpace(baseDir, memoryDirOverride) {
26962
27086
  const homeDir = baseDir ?? resolveHomeDir();
26963
- const standalonePath = path32.join(homeDir, ".engram", "memory");
26964
- const openclawPath = path32.join(homeDir, ".openclaw", "workspace", "memory", "local");
27087
+ const standalonePath = path33.join(homeDir, ".engram", "memory");
27088
+ const openclawPath = path33.join(homeDir, ".openclaw", "workspace", "memory", "local");
26965
27089
  const memoryDir = memoryDirOverride ?? readEnvVar("REMNIC_MEMORY_DIR") ?? readEnvVar("ENGRAM_MEMORY_DIR") ?? (fs6.existsSync(standalonePath) ? standalonePath : fs6.existsSync(openclawPath) ? openclawPath : standalonePath);
26966
27090
  const normalizedMemoryDir = normalizeSpaceMemoryDir(memoryDir);
26967
27091
  const now = (/* @__PURE__ */ new Date()).toISOString();
@@ -26990,7 +27114,7 @@ function createSpace(options) {
26990
27114
  const id = options.name.toLowerCase().replace(/[^a-z0-9-]/g, "-").replace(/-+/g, "-");
26991
27115
  const now = (/* @__PURE__ */ new Date()).toISOString();
26992
27116
  const memoryDir = normalizeSpaceMemoryDir(
26993
- options.memoryDir ?? path32.join(getSpacesDir(options.baseDir), id, "memory")
27117
+ options.memoryDir ?? path33.join(getSpacesDir(options.baseDir), id, "memory")
26994
27118
  );
26995
27119
  const space = updateManifest(options.baseDir, (manifest) => {
26996
27120
  if (manifest.spaces.some((s) => s.id === id)) {
@@ -27236,14 +27360,14 @@ async function mergeSpaces(sourceSpaceId, targetSpaceId, options) {
27236
27360
  };
27237
27361
  }
27238
27362
  function getAuditLog(baseDir) {
27239
- const auditPath = path32.join(getSpacesDir(baseDir), "audit.jsonl");
27363
+ const auditPath = path33.join(getSpacesDir(baseDir), "audit.jsonl");
27240
27364
  if (!fs6.existsSync(auditPath)) return [];
27241
27365
  const lines = fs6.readFileSync(auditPath, "utf8").trim().split("\n");
27242
27366
  return lines.filter((l) => l.trim()).map((l) => JSON.parse(l));
27243
27367
  }
27244
27368
  function appendAudit(entry, baseDir) {
27245
- const auditPath = path32.join(getSpacesDir(baseDir), "audit.jsonl");
27246
- fs6.mkdirSync(path32.dirname(auditPath), { recursive: true });
27369
+ const auditPath = path33.join(getSpacesDir(baseDir), "audit.jsonl");
27370
+ fs6.mkdirSync(path33.dirname(auditPath), { recursive: true });
27247
27371
  const full = {
27248
27372
  id: crypto7.randomUUID(),
27249
27373
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
@@ -27264,11 +27388,11 @@ async function copyMemories(sourceDir, targetDir, options) {
27264
27388
  sourceFiles.filter((p) => {
27265
27389
  const rp = safeRealpath(p);
27266
27390
  if (!rp || !isPathInsideRoot(rp, sourceRoot)) return false;
27267
- const rel = path32.relative(sourceRoot, rp);
27268
- const mapped = path32.resolve(targetRoot, rel);
27391
+ const rel = path33.relative(sourceRoot, rp);
27392
+ const mapped = path33.resolve(targetRoot, rel);
27269
27393
  if (!isPathInsideRoot(mapped, targetRoot)) return false;
27270
27394
  return classifyEntityRefWritePath(targetRoot, mapped) === "entity";
27271
- }).map((p) => path32.basename(p, ".md"))
27395
+ }).map((p) => path33.basename(p, ".md"))
27272
27396
  );
27273
27397
  const firstEntityId = sourceEntityIds.values().next().value;
27274
27398
  if (firstEntityId === void 0) {
@@ -27276,7 +27400,7 @@ async function copyMemories(sourceDir, targetDir, options) {
27276
27400
  }
27277
27401
  return withRawEntityPageMutation(
27278
27402
  targetRoot,
27279
- path32.join(targetRoot, "entities", `${firstEntityId}.md`),
27403
+ path33.join(targetRoot, "entities", `${firstEntityId}.md`),
27280
27404
  async () => copyPreparedMemories(
27281
27405
  sourceFiles,
27282
27406
  sourceRoot,
@@ -27303,14 +27427,14 @@ function copyPreparedMemories(sourceFiles, sourceRoot, targetRoot, sourceEntityI
27303
27427
  continue;
27304
27428
  }
27305
27429
  const content = fs6.readFileSync(sourcePath, "utf8");
27306
- const relativePath = path32.relative(sourceRoot, sourceRealPath);
27307
- const targetPath = path32.resolve(targetRoot, relativePath);
27430
+ const relativePath = path33.relative(sourceRoot, sourceRealPath);
27431
+ const targetPath = path33.resolve(targetRoot, relativePath);
27308
27432
  if (!isPathInsideRoot(targetPath, targetRoot)) {
27309
27433
  skipped++;
27310
27434
  continue;
27311
27435
  }
27312
27436
  const targetKind = classifyEntityRefWritePath(targetRoot, targetPath);
27313
- const idsAtCompare = historicalIdCache3.get(path32.join(targetRoot, "state"));
27437
+ const idsAtCompare = historicalIdCache3.get(path33.join(targetRoot, "state"));
27314
27438
  const sourceRef = targetKind === "memory" ? readEntityRefFromFrontmatter(content) : null;
27315
27439
  const refHasSourceClaimant = sourceRef !== null && sourceEntityIds.has(sourceRef);
27316
27440
  const canonicalContent = targetKind === "memory" && !refHasSourceClaimant ? canonicalizeEntityRefFrontmatter(content, idsAtCompare) : content;
@@ -27337,7 +27461,7 @@ function copyPreparedMemories(sourceFiles, sourceRoot, targetRoot, sourceEntityI
27337
27461
  if (fs6.existsSync(targetPath) && !options?.force) {
27338
27462
  const targetContent = fs6.readFileSync(targetPath, "utf8");
27339
27463
  const targetHash = hashContent4(targetContent);
27340
- if (hashContent4(canonicalContent) === targetHash && historicalIdCache3.get(path32.join(targetRoot, "state")) === idsAtCompare) {
27464
+ if (hashContent4(canonicalContent) === targetHash && historicalIdCache3.get(path33.join(targetRoot, "state")) === idsAtCompare) {
27341
27465
  skipped++;
27342
27466
  continue;
27343
27467
  }
@@ -27353,13 +27477,13 @@ function copyPreparedMemories(sourceFiles, sourceRoot, targetRoot, sourceEntityI
27353
27477
  continue;
27354
27478
  }
27355
27479
  }
27356
- fs6.mkdirSync(path32.dirname(targetPath), { recursive: true });
27357
- const targetParentRealPath = safeRealpath(path32.dirname(targetPath));
27480
+ fs6.mkdirSync(path33.dirname(targetPath), { recursive: true });
27481
+ const targetParentRealPath = safeRealpath(path33.dirname(targetPath));
27358
27482
  if (!targetParentRealPath || !isPathInsideRoot(targetParentRealPath, targetRoot)) {
27359
27483
  skipped++;
27360
27484
  continue;
27361
27485
  }
27362
- const stateDir = path32.join(targetRoot, "state");
27486
+ const stateDir = path33.join(targetRoot, "state");
27363
27487
  if (targetKind === "memory" && !refHasSourceClaimant) {
27364
27488
  const idsAtWrite = historicalIdCache3.get(stateDir);
27365
27489
  const written = canonicalizeEntityRefFrontmatter(content, idsAtWrite);
@@ -27403,7 +27527,7 @@ function copyPreparedMemories(sourceFiles, sourceRoot, targetRoot, sourceEntityI
27403
27527
  bumpMemoryCorpusVersionForDir(targetRoot);
27404
27528
  }
27405
27529
  if (reconcileNeeded) {
27406
- requestEntityCanonicalIdReconcileSync(path32.join(targetRoot, "state"));
27530
+ requestEntityCanonicalIdReconcileSync(path33.join(targetRoot, "state"));
27407
27531
  }
27408
27532
  return { merged, conflicts, skipped };
27409
27533
  }
@@ -27414,7 +27538,7 @@ function walkMd(dir) {
27414
27538
  const results = [];
27415
27539
  function walk(d) {
27416
27540
  for (const entry of fs6.readdirSync(d, { withFileTypes: true })) {
27417
- const fullPath = path32.join(d, entry.name);
27541
+ const fullPath = path33.join(d, entry.name);
27418
27542
  if (entry.isSymbolicLink()) {
27419
27543
  continue;
27420
27544
  }
@@ -27443,8 +27567,8 @@ function safeRealpath(filePath) {
27443
27567
  }
27444
27568
  }
27445
27569
  function isPathInsideRoot(candidatePath, rootPath) {
27446
- const relative = path32.relative(rootPath, candidatePath);
27447
- return relative === "" || !relative.startsWith("..") && !path32.isAbsolute(relative);
27570
+ const relative = path33.relative(rootPath, candidatePath);
27571
+ return relative === "" || !relative.startsWith("..") && !path33.isAbsolute(relative);
27448
27572
  }
27449
27573
  function parseSimpleFrontmatter(content) {
27450
27574
  const match = content.match(/^---\n([\s\S]*?)\n---/);
@@ -27565,7 +27689,7 @@ var REMNIC_RECALL_DECISION_RULES = `## When to Use Recall vs Direct Read
27565
27689
  // src/memory-extension/codex-publisher.ts
27566
27690
  import fs7 from "fs";
27567
27691
  import os from "os";
27568
- import path33 from "path";
27692
+ import path34 from "path";
27569
27693
  var REMNIC_EXTENSION_DIR_NAME = "remnic";
27570
27694
  function resolveEnvHome(env) {
27571
27695
  if (env === void 0) return resolveHomeDir();
@@ -27574,12 +27698,12 @@ function resolveEnvHome(env) {
27574
27698
  function expandTildeWithHome(input, homeDir) {
27575
27699
  if (input === "~") return homeDir;
27576
27700
  if (input.startsWith("~/") || input.startsWith("~\\")) {
27577
- return path33.join(homeDir, input.slice(2));
27701
+ return path34.join(homeDir, input.slice(2));
27578
27702
  }
27579
27703
  return input;
27580
27704
  }
27581
27705
  function normalizeHostRoot(input, homeDir) {
27582
- return path33.resolve(expandTildeWithHome(input.trim(), homeDir));
27706
+ return path34.resolve(expandTildeWithHome(input.trim(), homeDir));
27583
27707
  }
27584
27708
  var CodexMemoryExtensionPublisher = class {
27585
27709
  hostId = "codex";
@@ -27593,12 +27717,12 @@ var CodexMemoryExtensionPublisher = class {
27593
27717
  async resolveExtensionRoot(env) {
27594
27718
  const homeDir = resolveEnvHome(env);
27595
27719
  const codexHomeInput = env === void 0 ? readEnvVar("CODEX_HOME")?.trim() : env.CODEX_HOME?.trim();
27596
- const codexHome = codexHomeInput ? normalizeHostRoot(codexHomeInput, homeDir) : path33.resolve(homeDir, ".codex");
27597
- return path33.join(codexHome, "memories_extensions", REMNIC_EXTENSION_DIR_NAME);
27720
+ const codexHome = codexHomeInput ? normalizeHostRoot(codexHomeInput, homeDir) : path34.resolve(homeDir, ".codex");
27721
+ return path34.join(codexHome, "memories_extensions", REMNIC_EXTENSION_DIR_NAME);
27598
27722
  }
27599
27723
  async isHostAvailable() {
27600
27724
  try {
27601
- const home = readEnvVar("CODEX_HOME")?.trim() || path33.join(resolveHomeDir(), ".codex");
27725
+ const home = readEnvVar("CODEX_HOME")?.trim() || path34.join(resolveHomeDir(), ".codex");
27602
27726
  return fs7.existsSync(home);
27603
27727
  } catch {
27604
27728
  return false;
@@ -27649,7 +27773,7 @@ When running inside the Codex phase-2 consolidation sandbox:
27649
27773
  }
27650
27774
  async publish(ctx) {
27651
27775
  const extensionRoot = await this.resolveExtensionRoot();
27652
- const instructionsPath = path33.join(extensionRoot, "instructions.md");
27776
+ const instructionsPath = path34.join(extensionRoot, "instructions.md");
27653
27777
  const filesWritten = [];
27654
27778
  const skipped = [];
27655
27779
  ctx.log.info(`Publishing Codex memory extension to ${extensionRoot}`);
@@ -28281,9 +28405,9 @@ function buildWeeklyActivitySummary(cards, options) {
28281
28405
  // src/activity/timeline/weekly-persist.ts
28282
28406
  import { randomBytes as randomBytes3 } from "crypto";
28283
28407
  import { mkdirSync, readFileSync as readFileSync2, renameSync, unlinkSync, writeFileSync } from "fs";
28284
- import path34 from "path";
28408
+ import path35 from "path";
28285
28409
  var WEEKLY_SNAPSHOT_FORMAT_VERSION = 1;
28286
- var WEEKLY_SNAPSHOT_DIR = path34.join("activity", "weekly");
28410
+ var WEEKLY_SNAPSHOT_DIR = path35.join("activity", "weekly");
28287
28411
  function requireToken(value, name) {
28288
28412
  if (typeof value !== "string" || value.trim().length === 0) {
28289
28413
  throw new TypeError(`${name} must be a non-empty string`);
@@ -28306,8 +28430,8 @@ function weeklySnapshotPath(input) {
28306
28430
  const identity = hashActivityBody(
28307
28431
  `${input.summary.weekStartUtc}\0${input.summary.weekEndUtc}\0${sourceRevision}\0${configHash}`
28308
28432
  );
28309
- return path34.join(
28310
- path34.resolve(memoryDir),
28433
+ return path35.join(
28434
+ path35.resolve(memoryDir),
28311
28435
  WEEKLY_SNAPSHOT_DIR,
28312
28436
  namespaceIdentityToken(namespace),
28313
28437
  `${weekDate}--${identity}.json`
@@ -28337,7 +28461,7 @@ function persistWeeklySnapshot(input) {
28337
28461
  throw error;
28338
28462
  }
28339
28463
  }
28340
- mkdirSync(path34.dirname(filePath), { recursive: true, mode: 448 });
28464
+ mkdirSync(path35.dirname(filePath), { recursive: true, mode: 448 });
28341
28465
  const tmpPath = `${filePath}.${process.pid}.${randomBytes3(8).toString("hex")}.tmp`;
28342
28466
  writeFileSync(tmpPath, text, { encoding: "utf8", mode: 384 });
28343
28467
  try {
@@ -28842,7 +28966,7 @@ function selectRecapForDay(input) {
28842
28966
 
28843
28967
  // src/activity/journal-read.ts
28844
28968
  import { closeSync, constants as fsConstants, fstatSync, lstatSync, openSync, readFileSync as readFileSync3, realpathSync, statSync as statSync2 } from "fs";
28845
- import path35 from "path";
28969
+ import path36 from "path";
28846
28970
 
28847
28971
  // src/activity/journal-section.ts
28848
28972
  function parseAtxHeading(line) {
@@ -29033,8 +29157,8 @@ function readJournalForDate(input) {
29033
29157
  const relative = resolveVaultNotePath(input.vault.dailyNotePath, input.date, {
29034
29158
  timezone: input.timezone
29035
29159
  });
29036
- const root = path35.resolve(expandTildePath(input.vault.vaultPath));
29037
- const filePath = path35.join(root, relative);
29160
+ const root = path36.resolve(expandTildePath(input.vault.vaultPath));
29161
+ const filePath = path36.join(root, relative);
29038
29162
  try {
29039
29163
  const rootStat = lstatSync(root);
29040
29164
  if (rootStat.isSymbolicLink() || !rootStat.isDirectory()) {
@@ -29043,8 +29167,8 @@ function readJournalForDate(input) {
29043
29167
  } catch {
29044
29168
  return { ok: true, exists: false, reason: "missing_file", filePath };
29045
29169
  }
29046
- const lexical = path35.relative(root, filePath);
29047
- if (lexical.length === 0 || lexical === ".." || lexical.startsWith(`..${path35.sep}`) || path35.isAbsolute(lexical)) {
29170
+ const lexical = path36.relative(root, filePath);
29171
+ if (lexical.length === 0 || lexical === ".." || lexical.startsWith(`..${path36.sep}`) || path36.isAbsolute(lexical)) {
29048
29172
  return { ok: false, reason: "path_escape", filePath };
29049
29173
  }
29050
29174
  if (!containedBySymlinks(root, filePath)) {
@@ -29077,11 +29201,11 @@ function containedBySymlinks(root, dest) {
29077
29201
  try {
29078
29202
  if (statSync2(probe).isFile() || statSync2(probe).isDirectory()) {
29079
29203
  const real = realpathSync(probe);
29080
- return real === realRoot || real.startsWith(`${realRoot}${path35.sep}`);
29204
+ return real === realRoot || real.startsWith(`${realRoot}${path36.sep}`);
29081
29205
  }
29082
29206
  } catch {
29083
29207
  }
29084
- const parent = path35.dirname(probe);
29208
+ const parent = path36.dirname(probe);
29085
29209
  if (parent === probe) return false;
29086
29210
  probe = parent;
29087
29211
  }
@@ -29092,15 +29216,15 @@ function symlinkRejected() {
29092
29216
  return err;
29093
29217
  }
29094
29218
  function readVerifiedDailyNote(root, filePath) {
29095
- const relative = path35.relative(root, filePath);
29096
- const parts = relative.split(path35.sep).filter((part) => part.length > 0 && part !== ".");
29219
+ const relative = path36.relative(root, filePath);
29220
+ const parts = relative.split(path36.sep).filter((part) => part.length > 0 && part !== ".");
29097
29221
  let cursor = root;
29098
29222
  for (const part of parts) {
29099
- cursor = path35.join(cursor, part);
29223
+ cursor = path36.join(cursor, part);
29100
29224
  const st = lstatSync(cursor);
29101
29225
  if (st.isSymbolicLink()) throw symlinkRejected();
29102
29226
  }
29103
- const parent = path35.dirname(filePath);
29227
+ const parent = path36.dirname(filePath);
29104
29228
  const parentLstat = lstatSync(parent);
29105
29229
  if (parentLstat.isSymbolicLink() || !parentLstat.isDirectory()) throw symlinkRejected();
29106
29230
  const nofollow = fsConstants.O_NOFOLLOW ?? 0;
@@ -29124,7 +29248,7 @@ function readVerifiedDailyNote(root, filePath) {
29124
29248
  try {
29125
29249
  const fdPath = realpathSync(`/proc/self/fd/${fd}`);
29126
29250
  const realRoot = realpathSync(root);
29127
- if (fdPath !== realRoot && !fdPath.startsWith(`${realRoot}${path35.sep}`)) {
29251
+ if (fdPath !== realRoot && !fdPath.startsWith(`${realRoot}${path36.sep}`)) {
29128
29252
  throw symlinkRejected();
29129
29253
  }
29130
29254
  } catch (err) {
@@ -29139,11 +29263,11 @@ function readVerifiedDailyNote(root, filePath) {
29139
29263
  // src/activity/journal-state.ts
29140
29264
  import { createHash as createHash10, randomBytes as randomBytes4 } from "crypto";
29141
29265
  import { mkdirSync as mkdirSync2, readFileSync as readFileSync4, renameSync as renameSync2, writeFileSync as writeFileSync2 } from "fs";
29142
- import path36 from "path";
29266
+ import path37 from "path";
29143
29267
  var STATE_DIR_NAME = "state";
29144
29268
  var STATE_FILE_NAME = "timeline.json";
29145
29269
  function timelineStatePath(memoryDir) {
29146
- return path36.join(memoryDir, STATE_DIR_NAME, STATE_FILE_NAME);
29270
+ return path37.join(memoryDir, STATE_DIR_NAME, STATE_FILE_NAME);
29147
29271
  }
29148
29272
  function hashJournalText(text) {
29149
29273
  return createHash10("sha256").update(text, "utf8").digest("hex");
@@ -29169,14 +29293,14 @@ function readTimelineState(memoryDir) {
29169
29293
  }
29170
29294
  function writeTimelineState(memoryDir, state) {
29171
29295
  const filePath = timelineStatePath(memoryDir);
29172
- mkdirSync2(path36.dirname(filePath), { recursive: true });
29296
+ mkdirSync2(path37.dirname(filePath), { recursive: true });
29173
29297
  const tempPath = `${filePath}.${process.pid}.${randomBytes4(8).toString("hex")}.tmp`;
29174
29298
  writeFileSync2(tempPath, `${JSON.stringify(state, null, 2)}
29175
29299
  `);
29176
29300
  renameSync2(tempPath, filePath);
29177
29301
  }
29178
29302
  function journalDateLockPath(memoryDir, date) {
29179
- return path36.join(memoryDir, STATE_DIR_NAME, `journal-extract-${date}.lock`);
29303
+ return path37.join(memoryDir, STATE_DIR_NAME, `journal-extract-${date}.lock`);
29180
29304
  }
29181
29305
  function timelineStateLockPath(memoryDir) {
29182
29306
  return `${timelineStatePath(memoryDir)}.lock`;
@@ -29868,7 +29992,7 @@ function filterPrivacyWindow(items, options) {
29868
29992
  }
29869
29993
 
29870
29994
  // src/activity/vault-wikilink.ts
29871
- import path37 from "path";
29995
+ import path38 from "path";
29872
29996
  function formatVaultWikilink(notePath) {
29873
29997
  if (typeof notePath !== "string" || notePath.trim().length === 0) {
29874
29998
  throw new RangeError("Vault wikilink path must be a non-empty relative path.");
@@ -29876,7 +30000,7 @@ function formatVaultWikilink(notePath) {
29876
30000
  if (notePath.includes("\n") || notePath.includes("\r")) {
29877
30001
  throw new RangeError("Vault wikilink path must not contain newlines.");
29878
30002
  }
29879
- if (path37.posix.isAbsolute(notePath) || path37.win32.isAbsolute(notePath)) {
30003
+ if (path38.posix.isAbsolute(notePath) || path38.win32.isAbsolute(notePath)) {
29880
30004
  throw new RangeError("Vault wikilink path must be relative; absolute paths are rejected.");
29881
30005
  }
29882
30006
  if (notePath.split(/[\\/]/).some((segment) => segment === "..")) {
@@ -29898,7 +30022,7 @@ function stripVaultMdSuffix(notePath) {
29898
30022
  }
29899
30023
 
29900
30024
  // src/activity/vault-join.ts
29901
- import path38 from "path";
30025
+ import path39 from "path";
29902
30026
  function joinVaultSegments(parts) {
29903
30027
  if (parts.length === 0) {
29904
30028
  throw new RangeError("Vault path parts must be a non-empty list.");
@@ -29913,7 +30037,7 @@ function joinVaultSegments(parts) {
29913
30037
  if (part.includes("\n") || part.includes("\r")) {
29914
30038
  throw new RangeError("Vault path part must not contain a newline.");
29915
30039
  }
29916
- if (path38.posix.isAbsolute(part) || path38.win32.isAbsolute(part)) {
30040
+ if (path39.posix.isAbsolute(part) || path39.win32.isAbsolute(part)) {
29917
30041
  throw new RangeError("Vault path part must be relative.");
29918
30042
  }
29919
30043
  if (part.split("/").includes("..")) {
@@ -29968,7 +30092,7 @@ function planVaultDryRun(inputs) {
29968
30092
  // src/session-summaries/index.ts
29969
30093
  import { createHash as createHash11 } from "crypto";
29970
30094
  import { lstat as lstat3, mkdir as mkdir7, readFile as readFile9, readdir as readdir4, rename, rm, stat as stat4, writeFile as writeFile7 } from "fs/promises";
29971
- import path39 from "path";
30095
+ import path40 from "path";
29972
30096
 
29973
30097
  // src/session-summaries/adapters.ts
29974
30098
  var VALID_ROLES = /* @__PURE__ */ new Set(["user", "assistant", "tool", "system", "other"]);
@@ -30473,7 +30597,7 @@ function shortHash(value, length = 16) {
30473
30597
  async function listTranscriptFiles(root, maxFiles) {
30474
30598
  const out = [];
30475
30599
  let truncated = false;
30476
- const entrySortKey = (entryName, isDirectory) => isDirectory ? `${entryName}${path39.sep}` : entryName;
30600
+ const entrySortKey = (entryName, isDirectory) => isDirectory ? `${entryName}${path40.sep}` : entryName;
30477
30601
  async function visit(dir) {
30478
30602
  if (truncated) return;
30479
30603
  const entries = (await readdir4(dir, { withFileTypes: true })).sort(
@@ -30483,13 +30607,13 @@ async function listTranscriptFiles(root, maxFiles) {
30483
30607
  if (truncated) return;
30484
30608
  if (entry.name.startsWith(".")) continue;
30485
30609
  if (entry.isSymbolicLink()) continue;
30486
- const fullPath = path39.join(dir, entry.name);
30610
+ const fullPath = path40.join(dir, entry.name);
30487
30611
  if (entry.isDirectory()) {
30488
30612
  await visit(fullPath);
30489
30613
  continue;
30490
30614
  }
30491
30615
  if (!entry.isFile()) continue;
30492
- const ext = path39.extname(entry.name).toLowerCase();
30616
+ const ext = path40.extname(entry.name).toLowerCase();
30493
30617
  if (!SUPPORTED_EXTENSIONS.has(ext)) continue;
30494
30618
  out.push(fullPath);
30495
30619
  if (out.length > maxFiles) {
@@ -30516,7 +30640,7 @@ function normalizeInputDir(inputDir) {
30516
30640
  if (typeof inputDir !== "string" || inputDir.trim().length === 0) {
30517
30641
  throw new Error("inputDir must be a non-empty string");
30518
30642
  }
30519
- return path39.resolve(expandTildePath(inputDir.trim()));
30643
+ return path40.resolve(expandTildePath(inputDir.trim()));
30520
30644
  }
30521
30645
  function initRoleCounts() {
30522
30646
  return {
@@ -30673,11 +30797,11 @@ async function collectLocalSessionSummaries(options) {
30673
30797
  continue;
30674
30798
  }
30675
30799
  seenFileHashes.add(fileHash);
30676
- const fileExtension = path39.extname(filePath).toLowerCase();
30800
+ const fileExtension = path40.extname(filePath).toLowerCase();
30677
30801
  const parsed = await adapter.parseFile(
30678
30802
  {
30679
30803
  content,
30680
- fileName: path39.basename(filePath),
30804
+ fileName: path40.basename(filePath),
30681
30805
  fileExtension,
30682
30806
  fileRef: fileHash
30683
30807
  },
@@ -30733,7 +30857,7 @@ async function collectLocalSessionSummaries(options) {
30733
30857
  }
30734
30858
  async function readRedactionConfig(pathLike) {
30735
30859
  if (!pathLike) return void 0;
30736
- const raw = await readFile9(path39.resolve(expandTildePath(pathLike)), "utf-8");
30860
+ const raw = await readFile9(path40.resolve(expandTildePath(pathLike)), "utf-8");
30737
30861
  const parsed = JSON.parse(raw);
30738
30862
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
30739
30863
  throw new Error("redaction config must be a JSON object");
@@ -30746,15 +30870,15 @@ function toJsonl(drafts) {
30746
30870
  }
30747
30871
  function defaultDraftOutputPath(memoryDir, generatedAt) {
30748
30872
  const stamp = generatedAt.replace(/[:.]/g, "-");
30749
- return path39.join(
30750
- path39.resolve(expandTildePath(memoryDir)),
30873
+ return path40.join(
30874
+ path40.resolve(expandTildePath(memoryDir)),
30751
30875
  "state",
30752
30876
  "session-summary-drafts",
30753
30877
  `session-summaries-${stamp}.jsonl`
30754
30878
  );
30755
30879
  }
30756
30880
  async function writeDrafts(filePath, drafts) {
30757
- await mkdir7(path39.dirname(filePath), { recursive: true });
30881
+ await mkdir7(path40.dirname(filePath), { recursive: true });
30758
30882
  const tempPath = `${filePath}.${process.pid}.${Date.now()}.tmp`;
30759
30883
  try {
30760
30884
  await writeFile7(tempPath, toJsonl(drafts), "utf-8");
@@ -30772,7 +30896,7 @@ async function runLocalSessionSummaryCliCommand(options) {
30772
30896
  });
30773
30897
  const wroteFiles = [];
30774
30898
  if (options.output) {
30775
- const outputPath = path39.resolve(expandTildePath(options.output));
30899
+ const outputPath = path40.resolve(expandTildePath(options.output));
30776
30900
  await writeDrafts(outputPath, report.drafts);
30777
30901
  wroteFiles.push(outputPath);
30778
30902
  }
@@ -30807,19 +30931,19 @@ async function runLocalSessionSummaryCliCommand(options) {
30807
30931
 
30808
30932
  // src/transfer/capsule-fork.ts
30809
30933
  import { lstat as lstat4, mkdir as mkdir8, readFile as readFile10, realpath as realpath3, writeFile as writeFile8 } from "fs/promises";
30810
- import path40 from "path";
30934
+ import path41 from "path";
30811
30935
  async function forkCapsule(opts) {
30812
30936
  validateForkId(opts.forkId);
30813
- const rootAbs = path40.resolve(opts.targetRoot);
30937
+ const rootAbs = path41.resolve(opts.targetRoot);
30814
30938
  await assertIsDirectoryNotSymlink(rootAbs, "forkCapsule", "targetRoot");
30815
- const forkDirAbs = path40.join(rootAbs, "forks", opts.forkId);
30939
+ const forkDirAbs = path41.join(rootAbs, "forks", opts.forkId);
30816
30940
  const forkEntryExists = await pathEntryExists(forkDirAbs);
30817
30941
  if (forkEntryExists) {
30818
30942
  throw new Error(
30819
30943
  `forkCapsule: fork path already exists \u2014 forkId "${opts.forkId}" is already in use at: ${forkDirAbs}`
30820
30944
  );
30821
30945
  }
30822
- const archiveAbs = path40.resolve(opts.sourceArchive);
30946
+ const archiveAbs = path41.resolve(opts.sourceArchive);
30823
30947
  const importResult = await importCapsule({
30824
30948
  archivePath: archiveAbs,
30825
30949
  root: rootAbs,
@@ -30841,10 +30965,10 @@ async function forkCapsule(opts) {
30841
30965
  importedRecords: importResult.imported.length,
30842
30966
  skippedRecords: importResult.skipped.length
30843
30967
  };
30844
- const lineagePath = path40.join(forkDirAbs, "lineage.json");
30968
+ const lineagePath = path41.join(forkDirAbs, "lineage.json");
30845
30969
  const rootReal = await realpath3(rootAbs);
30846
30970
  await assertRealpathInsideRoot(rootReal, lineagePath, `forks/${opts.forkId}/lineage.json`, "forkCapsule");
30847
- await mkdir8(path40.dirname(lineagePath), { recursive: true });
30971
+ await mkdir8(path41.dirname(lineagePath), { recursive: true });
30848
30972
  await writeFile8(lineagePath, JSON.stringify(lineage, null, 2) + "\n", "utf-8");
30849
30973
  return {
30850
30974
  archivePath: archiveAbs,
@@ -30858,11 +30982,11 @@ async function readForkLineage(targetRoot, forkId) {
30858
30982
  if (typeof forkId !== "string" || forkId.length === 0 || forkId.length > 64 || !CAPSULE_ID_PATTERN.test(forkId)) {
30859
30983
  return null;
30860
30984
  }
30861
- const rootAbs = path40.resolve(targetRoot);
30985
+ const rootAbs = path41.resolve(targetRoot);
30862
30986
  const rootReal = await realpath3(rootAbs).catch(() => rootAbs);
30863
- const lineagePath = path40.join(rootReal, "forks", forkId, "lineage.json");
30864
- const rel = path40.relative(rootReal, lineagePath);
30865
- if (rel.startsWith("..") || path40.isAbsolute(rel)) {
30987
+ const lineagePath = path41.join(rootReal, "forks", forkId, "lineage.json");
30988
+ const rel = path41.relative(rootReal, lineagePath);
30989
+ if (rel.startsWith("..") || path41.isAbsolute(rel)) {
30866
30990
  return null;
30867
30991
  }
30868
30992
  if (!await isLineagePathContained(rootReal, lineagePath)) {
@@ -30903,19 +31027,19 @@ async function pathEntryExists(absPath) {
30903
31027
  async function isLineagePathContained(rootReal, lineagePath) {
30904
31028
  let existing = lineagePath;
30905
31029
  const suffix = [];
30906
- while (existing !== path40.dirname(existing)) {
31030
+ while (existing !== path41.dirname(existing)) {
30907
31031
  const st = await lstat4(existing).catch(() => null);
30908
31032
  if (st !== null) break;
30909
- suffix.unshift(path40.basename(existing));
30910
- existing = path40.dirname(existing);
31033
+ suffix.unshift(path41.basename(existing));
31034
+ existing = path41.dirname(existing);
30911
31035
  }
30912
31036
  const existingReal = await realpath3(existing).catch(() => existing);
30913
- const targetReal = suffix.length > 0 ? path40.join(existingReal, ...suffix) : existingReal;
30914
- const rel = path40.relative(rootReal, targetReal);
31037
+ const targetReal = suffix.length > 0 ? path41.join(existingReal, ...suffix) : existingReal;
31038
+ const rel = path41.relative(rootReal, targetReal);
30915
31039
  if (rel === "") return true;
30916
31040
  if (rel === "..") return false;
30917
- if (rel.startsWith(`..${path40.sep}`)) return false;
30918
- if (path40.isAbsolute(rel)) return false;
31041
+ if (rel.startsWith(`..${path41.sep}`)) return false;
31042
+ if (path41.isAbsolute(rel)) return false;
30919
31043
  return true;
30920
31044
  }
30921
31045
 
@@ -31104,4 +31228,4 @@ export {
31104
31228
  qmdStartupCollectionChecksWithTimeout,
31105
31229
  Orchestrator
31106
31230
  };
31107
- //# sourceMappingURL=chunk-MSTKJI5T.js.map
31231
+ //# sourceMappingURL=chunk-K7FXR75S.js.map