@fgv/ts-agent-memory 5.1.0-49 → 5.1.0-50

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 (164) hide show
  1. package/dist/packlets/index/memoryIndex.js +23 -16
  2. package/dist/packlets/index/memoryIndex.js.map +1 -1
  3. package/dist/packlets/ingest/orchestrator.js +13 -1
  4. package/dist/packlets/ingest/orchestrator.js.map +1 -1
  5. package/dist/packlets/retrieve/linkTraversalRetriever.js +12 -26
  6. package/dist/packlets/retrieve/linkTraversalRetriever.js.map +1 -1
  7. package/dist/packlets/retrieve/recencyRetriever.js +7 -7
  8. package/dist/packlets/retrieve/recencyRetriever.js.map +1 -1
  9. package/dist/packlets/retrieve/retriever.js +91 -10
  10. package/dist/packlets/retrieve/retriever.js.map +1 -1
  11. package/dist/packlets/retrieve/semanticRetriever.js +16 -16
  12. package/dist/packlets/retrieve/semanticRetriever.js.map +1 -1
  13. package/dist/packlets/retrieve/structuredFilterRetriever.js +7 -7
  14. package/dist/packlets/retrieve/structuredFilterRetriever.js.map +1 -1
  15. package/dist/packlets/retrieve/tagRetriever.js +7 -7
  16. package/dist/packlets/retrieve/tagRetriever.js.map +1 -1
  17. package/dist/packlets/retrieve/temporalRetrievers.js +23 -20
  18. package/dist/packlets/retrieve/temporalRetrievers.js.map +1 -1
  19. package/dist/packlets/store/coverage.js +6 -0
  20. package/dist/packlets/store/coverage.js.map +1 -0
  21. package/dist/packlets/store/fileTreeMemoryStore.js +221 -79
  22. package/dist/packlets/store/fileTreeMemoryStore.js.map +1 -1
  23. package/dist/packlets/store/index.js +4 -0
  24. package/dist/packlets/store/index.js.map +1 -1
  25. package/dist/packlets/store/listSelection.js +36 -0
  26. package/dist/packlets/store/listSelection.js.map +1 -0
  27. package/dist/packlets/store/memoryStore.js +6 -0
  28. package/dist/packlets/store/memoryStore.js.map +1 -0
  29. package/dist/packlets/store/reconcile.js +6 -0
  30. package/dist/packlets/store/reconcile.js.map +1 -0
  31. package/dist/packlets/store/storeCoverage.js +102 -0
  32. package/dist/packlets/store/storeCoverage.js.map +1 -0
  33. package/dist/packlets/store/storeReconcile.js +122 -0
  34. package/dist/packlets/store/storeReconcile.js.map +1 -0
  35. package/dist/packlets/store/vectorMaintenance.js +116 -8
  36. package/dist/packlets/store/vectorMaintenance.js.map +1 -1
  37. package/dist/packlets/store/vectorRecordSource.js +44 -0
  38. package/dist/packlets/store/vectorRecordSource.js.map +1 -0
  39. package/dist/packlets/tools/memoryTools.js +25 -2
  40. package/dist/packlets/tools/memoryTools.js.map +1 -1
  41. package/dist/packlets/types/envelope.js +25 -0
  42. package/dist/packlets/types/envelope.js.map +1 -1
  43. package/dist/packlets/types/index.js +1 -0
  44. package/dist/packlets/types/index.js.map +1 -1
  45. package/dist/packlets/types/recordResolver.js +6 -0
  46. package/dist/packlets/types/recordResolver.js.map +1 -0
  47. package/dist/packlets/types/temporal.js.map +1 -1
  48. package/dist/packlets/vector/inMemoryCosineIndex.js +39 -18
  49. package/dist/packlets/vector/inMemoryCosineIndex.js.map +1 -1
  50. package/dist/packlets/vector/inMemoryFragmentCosineIndex.js +67 -12
  51. package/dist/packlets/vector/inMemoryFragmentCosineIndex.js.map +1 -1
  52. package/dist/packlets/vector/rebuildHelpers.js +38 -0
  53. package/dist/packlets/vector/rebuildHelpers.js.map +1 -0
  54. package/dist/packlets/vector/vectorIndex.js.map +1 -1
  55. package/dist/ts-agent-memory.d.ts +1035 -106
  56. package/lib/packlets/index/memoryIndex.d.ts +118 -27
  57. package/lib/packlets/index/memoryIndex.d.ts.map +1 -1
  58. package/lib/packlets/index/memoryIndex.js +23 -16
  59. package/lib/packlets/index/memoryIndex.js.map +1 -1
  60. package/lib/packlets/ingest/orchestrator.d.ts.map +1 -1
  61. package/lib/packlets/ingest/orchestrator.js +13 -1
  62. package/lib/packlets/ingest/orchestrator.js.map +1 -1
  63. package/lib/packlets/retrieve/linkTraversalRetriever.d.ts +3 -10
  64. package/lib/packlets/retrieve/linkTraversalRetriever.d.ts.map +1 -1
  65. package/lib/packlets/retrieve/linkTraversalRetriever.js +11 -25
  66. package/lib/packlets/retrieve/linkTraversalRetriever.js.map +1 -1
  67. package/lib/packlets/retrieve/recencyRetriever.d.ts +3 -3
  68. package/lib/packlets/retrieve/recencyRetriever.d.ts.map +1 -1
  69. package/lib/packlets/retrieve/recencyRetriever.js +6 -6
  70. package/lib/packlets/retrieve/recencyRetriever.js.map +1 -1
  71. package/lib/packlets/retrieve/retriever.d.ts +88 -7
  72. package/lib/packlets/retrieve/retriever.d.ts.map +1 -1
  73. package/lib/packlets/retrieve/retriever.js +94 -9
  74. package/lib/packlets/retrieve/retriever.js.map +1 -1
  75. package/lib/packlets/retrieve/semanticRetriever.d.ts +3 -5
  76. package/lib/packlets/retrieve/semanticRetriever.d.ts.map +1 -1
  77. package/lib/packlets/retrieve/semanticRetriever.js +15 -15
  78. package/lib/packlets/retrieve/semanticRetriever.js.map +1 -1
  79. package/lib/packlets/retrieve/structuredFilterRetriever.d.ts +3 -3
  80. package/lib/packlets/retrieve/structuredFilterRetriever.d.ts.map +1 -1
  81. package/lib/packlets/retrieve/structuredFilterRetriever.js +6 -6
  82. package/lib/packlets/retrieve/structuredFilterRetriever.js.map +1 -1
  83. package/lib/packlets/retrieve/tagRetriever.d.ts +3 -3
  84. package/lib/packlets/retrieve/tagRetriever.d.ts.map +1 -1
  85. package/lib/packlets/retrieve/tagRetriever.js +6 -6
  86. package/lib/packlets/retrieve/tagRetriever.js.map +1 -1
  87. package/lib/packlets/retrieve/temporalRetrievers.d.ts +7 -5
  88. package/lib/packlets/retrieve/temporalRetrievers.d.ts.map +1 -1
  89. package/lib/packlets/retrieve/temporalRetrievers.js +22 -19
  90. package/lib/packlets/retrieve/temporalRetrievers.js.map +1 -1
  91. package/lib/packlets/store/coverage.d.ts +102 -0
  92. package/lib/packlets/store/coverage.d.ts.map +1 -0
  93. package/lib/packlets/store/coverage.js +7 -0
  94. package/lib/packlets/store/coverage.js.map +1 -0
  95. package/lib/packlets/store/fileTreeMemoryStore.d.ts +53 -166
  96. package/lib/packlets/store/fileTreeMemoryStore.d.ts.map +1 -1
  97. package/lib/packlets/store/fileTreeMemoryStore.js +221 -79
  98. package/lib/packlets/store/fileTreeMemoryStore.js.map +1 -1
  99. package/lib/packlets/store/index.d.ts +4 -0
  100. package/lib/packlets/store/index.d.ts.map +1 -1
  101. package/lib/packlets/store/index.js +4 -0
  102. package/lib/packlets/store/index.js.map +1 -1
  103. package/lib/packlets/store/listSelection.d.ts +101 -0
  104. package/lib/packlets/store/listSelection.d.ts.map +1 -0
  105. package/lib/packlets/store/listSelection.js +40 -0
  106. package/lib/packlets/store/listSelection.js.map +1 -0
  107. package/lib/packlets/store/memoryStore.d.ts +237 -0
  108. package/lib/packlets/store/memoryStore.d.ts.map +1 -0
  109. package/lib/packlets/store/memoryStore.js +7 -0
  110. package/lib/packlets/store/memoryStore.js.map +1 -0
  111. package/lib/packlets/store/reconcile.d.ts +82 -0
  112. package/lib/packlets/store/reconcile.d.ts.map +1 -0
  113. package/lib/packlets/store/reconcile.js +7 -0
  114. package/lib/packlets/store/reconcile.js.map +1 -0
  115. package/lib/packlets/store/storeCoverage.d.ts +45 -0
  116. package/lib/packlets/store/storeCoverage.d.ts.map +1 -0
  117. package/lib/packlets/store/storeCoverage.js +105 -0
  118. package/lib/packlets/store/storeCoverage.js.map +1 -0
  119. package/lib/packlets/store/storeReconcile.d.ts +41 -0
  120. package/lib/packlets/store/storeReconcile.d.ts.map +1 -0
  121. package/lib/packlets/store/storeReconcile.js +125 -0
  122. package/lib/packlets/store/storeReconcile.js.map +1 -0
  123. package/lib/packlets/store/vectorMaintenance.d.ts +74 -0
  124. package/lib/packlets/store/vectorMaintenance.d.ts.map +1 -1
  125. package/lib/packlets/store/vectorMaintenance.js +117 -8
  126. package/lib/packlets/store/vectorMaintenance.js.map +1 -1
  127. package/lib/packlets/store/vectorRecordSource.d.ts +36 -0
  128. package/lib/packlets/store/vectorRecordSource.d.ts.map +1 -0
  129. package/lib/packlets/store/vectorRecordSource.js +47 -0
  130. package/lib/packlets/store/vectorRecordSource.js.map +1 -0
  131. package/lib/packlets/tools/memoryTools.d.ts.map +1 -1
  132. package/lib/packlets/tools/memoryTools.js +25 -2
  133. package/lib/packlets/tools/memoryTools.js.map +1 -1
  134. package/lib/packlets/types/envelope.d.ts +24 -2
  135. package/lib/packlets/types/envelope.d.ts.map +1 -1
  136. package/lib/packlets/types/envelope.js +26 -0
  137. package/lib/packlets/types/envelope.js.map +1 -1
  138. package/lib/packlets/types/index.d.ts +1 -0
  139. package/lib/packlets/types/index.d.ts.map +1 -1
  140. package/lib/packlets/types/index.js +1 -0
  141. package/lib/packlets/types/index.js.map +1 -1
  142. package/lib/packlets/types/recordResolver.d.ts +39 -0
  143. package/lib/packlets/types/recordResolver.d.ts.map +1 -0
  144. package/lib/packlets/types/recordResolver.js +7 -0
  145. package/lib/packlets/types/recordResolver.js.map +1 -0
  146. package/lib/packlets/types/temporal.d.ts +26 -6
  147. package/lib/packlets/types/temporal.d.ts.map +1 -1
  148. package/lib/packlets/types/temporal.js.map +1 -1
  149. package/lib/packlets/vector/inMemoryCosineIndex.d.ts +9 -2
  150. package/lib/packlets/vector/inMemoryCosineIndex.d.ts.map +1 -1
  151. package/lib/packlets/vector/inMemoryCosineIndex.js +40 -19
  152. package/lib/packlets/vector/inMemoryCosineIndex.js.map +1 -1
  153. package/lib/packlets/vector/inMemoryFragmentCosineIndex.d.ts +6 -3
  154. package/lib/packlets/vector/inMemoryFragmentCosineIndex.d.ts.map +1 -1
  155. package/lib/packlets/vector/inMemoryFragmentCosineIndex.js +66 -11
  156. package/lib/packlets/vector/inMemoryFragmentCosineIndex.js.map +1 -1
  157. package/lib/packlets/vector/rebuildHelpers.d.ts +30 -0
  158. package/lib/packlets/vector/rebuildHelpers.d.ts.map +1 -0
  159. package/lib/packlets/vector/rebuildHelpers.js +42 -0
  160. package/lib/packlets/vector/rebuildHelpers.js.map +1 -0
  161. package/lib/packlets/vector/vectorIndex.d.ts +270 -15
  162. package/lib/packlets/vector/vectorIndex.d.ts.map +1 -1
  163. package/lib/packlets/vector/vectorIndex.js.map +1 -1
  164. package/package.json +7 -7
@@ -1,3 +1,7 @@
1
+ export * from './coverage';
2
+ export * from './reconcile';
3
+ export * from './listSelection';
4
+ export * from './memoryStore';
1
5
  export * from './fileTreeMemoryStore';
2
6
  export * from './scopeEncoding';
3
7
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/packlets/store/index.ts"],"names":[],"mappings":"AAKA,cAAc,uBAAuB,CAAC;AACtC,cAAc,iBAAiB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/packlets/store/index.ts"],"names":[],"mappings":"AAKA,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,iBAAiB,CAAC;AAChC,cAAc,eAAe,CAAC;AAC9B,cAAc,uBAAuB,CAAC;AACtC,cAAc,iBAAiB,CAAC"}
@@ -18,6 +18,10 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
18
18
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
19
19
  };
20
20
  Object.defineProperty(exports, "__esModule", { value: true });
21
+ __exportStar(require("./coverage"), exports);
22
+ __exportStar(require("./reconcile"), exports);
23
+ __exportStar(require("./listSelection"), exports);
24
+ __exportStar(require("./memoryStore"), exports);
21
25
  __exportStar(require("./fileTreeMemoryStore"), exports);
22
26
  __exportStar(require("./scopeEncoding"), exports);
23
27
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/packlets/store/index.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;;;;;;;;;;;;;;AAEH,wDAAsC;AACtC,kDAAgC","sourcesContent":["/*\n * Copyright (c) 2026 Erik Fortune\n * SPDX-License-Identifier: MIT\n */\n\nexport * from './fileTreeMemoryStore';\nexport * from './scopeEncoding';\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/packlets/store/index.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;;;;;;;;;;;;;;AAEH,6CAA2B;AAC3B,8CAA4B;AAC5B,kDAAgC;AAChC,gDAA8B;AAC9B,wDAAsC;AACtC,kDAAgC","sourcesContent":["/*\n * Copyright (c) 2026 Erik Fortune\n * SPDX-License-Identifier: MIT\n */\n\nexport * from './coverage';\nexport * from './reconcile';\nexport * from './listSelection';\nexport * from './memoryStore';\nexport * from './fileTreeMemoryStore';\nexport * from './scopeEncoding';\n"]}
@@ -0,0 +1,101 @@
1
+ import { Kind, MemoryScopeKey, Tag } from '../types';
2
+ /**
3
+ * Filter for {@link IMemoryStore.list}. All present fields are ANDed together.
4
+ *
5
+ * @remarks
6
+ * **At least one of `scope` / `kind` / `tag` must be present.** `asOf` is a
7
+ * temporal *projection*, not a narrowing — it collapses versions rather than
8
+ * excluding entities — so it does not satisfy the requirement on its own. A
9
+ * selection that narrows nothing fails with a message naming
10
+ * {@link scanEveryRecord}.
11
+ * @public
12
+ */
13
+ export interface IMemoryStoreListFilter {
14
+ /**
15
+ * Never present on a narrowing filter.
16
+ *
17
+ * @remarks
18
+ * Exclusivity marker, paired with the `never`s on {@link IWholeVaultScan}.
19
+ * Without it `{ scanEveryRecord: true, kind }` type-checks — TypeScript's
20
+ * excess-property check on a union admits any property declared by *any*
21
+ * member — and `list` then takes the scan branch and silently discards the
22
+ * narrowing. Since the whole point of requiring a selection is that a
23
+ * whole-vault read must be deliberate, a call that reads the whole vault while
24
+ * *looking* narrowed is the one outcome this surface must not permit.
25
+ */
26
+ readonly scanEveryRecord?: never;
27
+ /** Restrict to records in this scope. */
28
+ readonly scope?: MemoryScopeKey;
29
+ /** Restrict to records of this kind. */
30
+ readonly kind?: Kind;
31
+ /** Restrict to records carrying this tag (exact match). */
32
+ readonly tag?: Tag;
33
+ /**
34
+ * For temporal (versioned) kinds: collapse each entity to the single version
35
+ * valid at this epoch ms. Non-temporal records are timeless and pass through
36
+ * unchanged. Absent = no temporal projection (every version is returned).
37
+ */
38
+ readonly asOf?: number;
39
+ }
40
+ /**
41
+ * The named, deliberately uncomfortable opt-out from
42
+ * {@link IMemoryStore.list}'s narrowing requirement — build one with
43
+ * {@link scanEveryRecord}.
44
+ * @public
45
+ */
46
+ export interface IWholeVaultScan {
47
+ /** Discriminator. Always `true`; produced only by {@link scanEveryRecord}. */
48
+ readonly scanEveryRecord: true;
49
+ /**
50
+ * Never present on a whole-vault scan — see
51
+ * {@link IMemoryStoreListFilter.scanEveryRecord} for why these markers exist.
52
+ * A scan that also carried a narrowing axis would have that axis dropped.
53
+ */
54
+ readonly scope?: never;
55
+ /** Never present on a whole-vault scan. See {@link IWholeVaultScan.scope}. */
56
+ readonly kind?: never;
57
+ /** Never present on a whole-vault scan. See {@link IWholeVaultScan.scope}. */
58
+ readonly tag?: never;
59
+ /**
60
+ * Optional temporal projection, exactly as on {@link IMemoryStoreListFilter}.
61
+ * NOT excluded, because `asOf` projects rather than narrows and composes with
62
+ * a whole-vault read exactly as it does with a filtered one.
63
+ */
64
+ readonly asOf?: number;
65
+ }
66
+ /**
67
+ * What {@link IMemoryStore.list} accepts: a narrowing filter, or the explicit
68
+ * whole-vault scan.
69
+ * @public
70
+ */
71
+ export type MemoryListSelection = IMemoryStoreListFilter | IWholeVaultScan;
72
+ /**
73
+ * Ask {@link IMemoryStore.list} for **every record in the vault**, bodies
74
+ * included.
75
+ *
76
+ * @remarks
77
+ * `list` requires a selection and rejects one that narrows nothing, so this is
78
+ * the only way to get the whole vault — and that is the point. Since the index
79
+ * holds envelopes only, `list` materializes every survivor from storage, so an
80
+ * unnarrowed call reads one file per record. Making it impossible to write by
81
+ * accident is worth more than making it fast.
82
+ *
83
+ * It is named for what it costs rather than for what it returns, and it is
84
+ * greppable: `scanEveryRecord` enumerates every whole-vault read in a codebase in
85
+ * one search. This mirrors `@fgv/ts-extras`' `safer-fetch`, where `addressGuard`
86
+ * is required with no default and `allowAnyAddress()` is the named opt-out.
87
+ *
88
+ * **If you only need to select, you do not need this.** Use
89
+ * {@link IMemoryStore.listEntries}, which returns every entry's scope and
90
+ * envelope, reads no files, and needs no selection.
91
+ * @public
92
+ */
93
+ export declare function scanEveryRecord(options?: {
94
+ readonly asOf?: number;
95
+ }): IWholeVaultScan;
96
+ /**
97
+ * Whether a selection is the explicit whole-vault opt-out.
98
+ * @public
99
+ */
100
+ export declare function isWholeVaultScan(selection: MemoryListSelection): selection is IWholeVaultScan;
101
+ //# sourceMappingURL=listSelection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"listSelection.d.ts","sourceRoot":"","sources":["../../../src/packlets/store/listSelection.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,IAAI,EAAE,cAAc,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAErD;;;;;;;;;;GAUG;AACH,MAAM,WAAW,sBAAsB;IACrC;;;;;;;;;;;OAWG;IACH,QAAQ,CAAC,eAAe,CAAC,EAAE,KAAK,CAAC;IACjC,yCAAyC;IACzC,QAAQ,CAAC,KAAK,CAAC,EAAE,cAAc,CAAC;IAChC,wCAAwC;IACxC,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC;IACrB,2DAA2D;IAC3D,QAAQ,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC;IACnB;;;;OAIG;IACH,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;;;;GAKG;AACH,MAAM,WAAW,eAAe;IAC9B,8EAA8E;IAC9E,QAAQ,CAAC,eAAe,EAAE,IAAI,CAAC;IAC/B;;;;OAIG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC;IACvB,8EAA8E;IAC9E,QAAQ,CAAC,IAAI,CAAC,EAAE,KAAK,CAAC;IACtB,8EAA8E;IAC9E,QAAQ,CAAC,GAAG,CAAC,EAAE,KAAK,CAAC;IACrB;;;;OAIG;IACH,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;;;GAIG;AACH,MAAM,MAAM,mBAAmB,GAAG,sBAAsB,GAAG,eAAe,CAAC;AAE3E;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,eAAe,CAAC,OAAO,CAAC,EAAE;IAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,eAAe,CAKrF;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,mBAAmB,GAAG,SAAS,IAAI,eAAe,CAE7F"}
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+ /*
3
+ * Copyright (c) 2026 Erik Fortune
4
+ * SPDX-License-Identifier: MIT
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.scanEveryRecord = scanEveryRecord;
8
+ exports.isWholeVaultScan = isWholeVaultScan;
9
+ /**
10
+ * Ask {@link IMemoryStore.list} for **every record in the vault**, bodies
11
+ * included.
12
+ *
13
+ * @remarks
14
+ * `list` requires a selection and rejects one that narrows nothing, so this is
15
+ * the only way to get the whole vault — and that is the point. Since the index
16
+ * holds envelopes only, `list` materializes every survivor from storage, so an
17
+ * unnarrowed call reads one file per record. Making it impossible to write by
18
+ * accident is worth more than making it fast.
19
+ *
20
+ * It is named for what it costs rather than for what it returns, and it is
21
+ * greppable: `scanEveryRecord` enumerates every whole-vault read in a codebase in
22
+ * one search. This mirrors `@fgv/ts-extras`' `safer-fetch`, where `addressGuard`
23
+ * is required with no default and `allowAnyAddress()` is the named opt-out.
24
+ *
25
+ * **If you only need to select, you do not need this.** Use
26
+ * {@link IMemoryStore.listEntries}, which returns every entry's scope and
27
+ * envelope, reads no files, and needs no selection.
28
+ * @public
29
+ */
30
+ function scanEveryRecord(options) {
31
+ return Object.assign({ scanEveryRecord: true }, ((options === null || options === void 0 ? void 0 : options.asOf) !== undefined ? { asOf: options.asOf } : {}));
32
+ }
33
+ /**
34
+ * Whether a selection is the explicit whole-vault opt-out.
35
+ * @public
36
+ */
37
+ function isWholeVaultScan(selection) {
38
+ return selection.scanEveryRecord === true;
39
+ }
40
+ //# sourceMappingURL=listSelection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"listSelection.js","sourceRoot":"","sources":["../../../src/packlets/store/listSelection.ts"],"names":[],"mappings":";AAAA;;;GAGG;;AAkGH,0CAKC;AAMD,4CAEC;AAlCD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,SAAgB,eAAe,CAAC,OAAoC;IAClE,uBACE,eAAe,EAAE,IAAI,IAClB,CAAC,CAAA,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,IAAI,MAAK,SAAS,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAC9D;AACJ,CAAC;AAED;;;GAGG;AACH,SAAgB,gBAAgB,CAAC,SAA8B;IAC7D,OAAQ,SAA6B,CAAC,eAAe,KAAK,IAAI,CAAC;AACjE,CAAC","sourcesContent":["/*\n * Copyright (c) 2026 Erik Fortune\n * SPDX-License-Identifier: MIT\n */\n\nimport { Kind, MemoryScopeKey, Tag } from '../types';\n\n/**\n * Filter for {@link IMemoryStore.list}. All present fields are ANDed together.\n *\n * @remarks\n * **At least one of `scope` / `kind` / `tag` must be present.** `asOf` is a\n * temporal *projection*, not a narrowing — it collapses versions rather than\n * excluding entities — so it does not satisfy the requirement on its own. A\n * selection that narrows nothing fails with a message naming\n * {@link scanEveryRecord}.\n * @public\n */\nexport interface IMemoryStoreListFilter {\n /**\n * Never present on a narrowing filter.\n *\n * @remarks\n * Exclusivity marker, paired with the `never`s on {@link IWholeVaultScan}.\n * Without it `{ scanEveryRecord: true, kind }` type-checks — TypeScript's\n * excess-property check on a union admits any property declared by *any*\n * member — and `list` then takes the scan branch and silently discards the\n * narrowing. Since the whole point of requiring a selection is that a\n * whole-vault read must be deliberate, a call that reads the whole vault while\n * *looking* narrowed is the one outcome this surface must not permit.\n */\n readonly scanEveryRecord?: never;\n /** Restrict to records in this scope. */\n readonly scope?: MemoryScopeKey;\n /** Restrict to records of this kind. */\n readonly kind?: Kind;\n /** Restrict to records carrying this tag (exact match). */\n readonly tag?: Tag;\n /**\n * For temporal (versioned) kinds: collapse each entity to the single version\n * valid at this epoch ms. Non-temporal records are timeless and pass through\n * unchanged. Absent = no temporal projection (every version is returned).\n */\n readonly asOf?: number;\n}\n\n/**\n * The named, deliberately uncomfortable opt-out from\n * {@link IMemoryStore.list}'s narrowing requirement — build one with\n * {@link scanEveryRecord}.\n * @public\n */\nexport interface IWholeVaultScan {\n /** Discriminator. Always `true`; produced only by {@link scanEveryRecord}. */\n readonly scanEveryRecord: true;\n /**\n * Never present on a whole-vault scan — see\n * {@link IMemoryStoreListFilter.scanEveryRecord} for why these markers exist.\n * A scan that also carried a narrowing axis would have that axis dropped.\n */\n readonly scope?: never;\n /** Never present on a whole-vault scan. See {@link IWholeVaultScan.scope}. */\n readonly kind?: never;\n /** Never present on a whole-vault scan. See {@link IWholeVaultScan.scope}. */\n readonly tag?: never;\n /**\n * Optional temporal projection, exactly as on {@link IMemoryStoreListFilter}.\n * NOT excluded, because `asOf` projects rather than narrows and composes with\n * a whole-vault read exactly as it does with a filtered one.\n */\n readonly asOf?: number;\n}\n\n/**\n * What {@link IMemoryStore.list} accepts: a narrowing filter, or the explicit\n * whole-vault scan.\n * @public\n */\nexport type MemoryListSelection = IMemoryStoreListFilter | IWholeVaultScan;\n\n/**\n * Ask {@link IMemoryStore.list} for **every record in the vault**, bodies\n * included.\n *\n * @remarks\n * `list` requires a selection and rejects one that narrows nothing, so this is\n * the only way to get the whole vault — and that is the point. Since the index\n * holds envelopes only, `list` materializes every survivor from storage, so an\n * unnarrowed call reads one file per record. Making it impossible to write by\n * accident is worth more than making it fast.\n *\n * It is named for what it costs rather than for what it returns, and it is\n * greppable: `scanEveryRecord` enumerates every whole-vault read in a codebase in\n * one search. This mirrors `@fgv/ts-extras`' `safer-fetch`, where `addressGuard`\n * is required with no default and `allowAnyAddress()` is the named opt-out.\n *\n * **If you only need to select, you do not need this.** Use\n * {@link IMemoryStore.listEntries}, which returns every entry's scope and\n * envelope, reads no files, and needs no selection.\n * @public\n */\nexport function scanEveryRecord(options?: { readonly asOf?: number }): IWholeVaultScan {\n return {\n scanEveryRecord: true,\n ...(options?.asOf !== undefined ? { asOf: options.asOf } : {})\n };\n}\n\n/**\n * Whether a selection is the explicit whole-vault opt-out.\n * @public\n */\nexport function isWholeVaultScan(selection: MemoryListSelection): selection is IWholeVaultScan {\n return (selection as IWholeVaultScan).scanEveryRecord === true;\n}\n"]}
@@ -0,0 +1,237 @@
1
+ import { Result } from '@fgv/ts-utils';
2
+ import { DedupScope, EntityId, IMemoryRecord, IMemoryRecordResolver, Kind, MemoryId, MemoryScopeKey } from '../types';
3
+ import { IIndexedMemoryEntry } from '../index';
4
+ import { IMemoryRecordSource, IScopedMemoryRecord } from '../vector';
5
+ import { MemoryListSelection } from './listSelection';
6
+ import { IDerivedStateCoverage } from './coverage';
7
+ import { DerivedArtifact, ReconcileReport } from './reconcile';
8
+ /**
9
+ * The writable, FileTree-backed, content-hash-deduped memory store.
10
+ *
11
+ * @remarks
12
+ * Extends {@link IMemoryRecordResolver} because the retrievers take a resolver
13
+ * and a store is the obvious one to hand them — `{ index, resolver: store }` is
14
+ * the documented wiring, and it has to type-check for the `IMemoryStore` handle
15
+ * a consumer actually holds, not only for the concrete `FileTreeMemoryStore`.
16
+ * @public
17
+ */
18
+ export interface IMemoryStore extends IMemoryRecordResolver {
19
+ /**
20
+ * Keyed read by entity id. Resolves `entityId` to a storage address via the
21
+ * registered {@link IIdentityCodec} for `kind`. Returns `undefined` when no
22
+ * record exists. For a versioned (temporal) kind the current version is
23
+ * *selected* from the derived in-memory index — the version history is walked
24
+ * over envelopes, never bodies — and then that one version is read from
25
+ * storage. So the selection costs no file reads and the result costs exactly
26
+ * one, rather than one per version.
27
+ */
28
+ get(kind: Kind, entityId: EntityId): Promise<Result<IMemoryRecord<unknown> | undefined>>;
29
+ /**
30
+ * Direct read by `(scope, MemoryId)`. Returns `undefined` when not found.
31
+ */
32
+ getById(scope: MemoryScopeKey, id: MemoryId): Promise<Result<IMemoryRecord<unknown> | undefined>>;
33
+ /**
34
+ * List records: select over the derived index, then materialize the survivors.
35
+ *
36
+ * @remarks
37
+ * **The selection is required and must narrow.** Since the index holds
38
+ * envelopes only, every returned record is read from storage — so a call that
39
+ * narrows nothing reads the whole vault, and that has to be a decision rather
40
+ * than a default. Omitting the argument is a compile error; passing one with no
41
+ * `scope` / `kind` / `tag` fails with a message naming {@link scanEveryRecord},
42
+ * which is how a caller says it meant it.
43
+ *
44
+ * The requirement buys **explicitness, not a cost bound** — `{ kind }` on a
45
+ * vault dominated by that kind still materializes most of it. What it prevents
46
+ * is the whole-vault read nobody chose.
47
+ *
48
+ * If you only need to select, use {@link IMemoryStore.listEntries} instead: no
49
+ * selection, no file reads.
50
+ */
51
+ list(selection: MemoryListSelection): Promise<Result<ReadonlyArray<IMemoryRecord<unknown>>>>;
52
+ /**
53
+ * How much of the store's **derived state** exists, resolved by {@link Kind}.
54
+ *
55
+ * @remarks
56
+ * Answers *"is my derived state consistent with my records, and if not by how
57
+ * much?"* for every artifact the store derives — `rank`, record vectors, and
58
+ * fragment vectors — in one call.
59
+ *
60
+ * **Cheap and total, by contract rather than by implementation.** Every input is
61
+ * an envelope field or an index-side count: it reads **no record bodies** and
62
+ * calls **no embedder**, and the walk over the vault's own state touches the
63
+ * filesystem not at all. That is why it takes no selection, unlike
64
+ * {@link IMemoryStore.list} — the guard there exists because an unnarrowed list
65
+ * reads the vault, and putting one here would decorate a free operation and make
66
+ * that guard mean less.
67
+ *
68
+ * **The index-side counts are the one exception, and it is the caller's own
69
+ * index that spends it.** A persistent index answers `size` / `recordCount` /
70
+ * `fragmentCount` with a query — `SqliteVecVectorIndex` runs a prepared `COUNT`
71
+ * — so on a durable backend this call does I/O and can **fail**. It is bounded
72
+ * (one count per wired index, never per record) and it is why the return is a
73
+ * `Result` rather than a bare value.
74
+ *
75
+ * *If a future addition to the report would require reading a record body, it
76
+ * does not belong on this report.*
77
+ *
78
+ * The counterpart is {@link IMemoryStore.reconcile}: coverage says **how big**
79
+ * the gap is, cheaply; reconcile says **what it was** and closes what it can, at
80
+ * the cost of re-running the embedder. Neither substitutes for the other.
81
+ *
82
+ * **A lane is reported here whenever its *index* is wired**, which is weaker
83
+ * than what reconcile requires (index **and** embedder). That is intended: an
84
+ * index without an embedder still holds vectors and still answers queries, so
85
+ * its coverage is a real number worth reporting. The consequence to expect is a
86
+ * half-wired store that reports a gap `reconcile` will refuse to close, naming
87
+ * the missing embedder.
88
+ */
89
+ coverage(): Promise<Result<IDerivedStateCoverage>>;
90
+ /**
91
+ * Every entry in the vault — scope and envelope, **no bodies**. Reads no files
92
+ * and requires no selection, because there is nothing to be careful about: it
93
+ * returns what the index already holds.
94
+ *
95
+ * @remarks
96
+ * This is the whole-vault read most callers actually want. Selection, grouping,
97
+ * counting, "which kinds are in here", "what links at this" — all of it is
98
+ * envelope work. Reach for {@link IMemoryStore.list} with
99
+ * {@link scanEveryRecord} only when you genuinely need every body.
100
+ *
101
+ * Synchronous in spirit but `Promise`-returning for consistency with the rest
102
+ * of the store surface.
103
+ */
104
+ listEntries(): Promise<Result<ReadonlyArray<IIndexedMemoryEntry>>>;
105
+ /**
106
+ * List EVERY record in the vault, each paired with its scope-qualified
107
+ * `(scope, id)` address — the projection {@link IMemoryRecordSource} requires.
108
+ * Unlike {@link IMemoryStore.list | list}, it takes no filter (whole-vault) and
109
+ * returns {@link IScopedMemoryRecord}s so a re-index keys each entry on the same
110
+ * scoped target the incremental embed-on-write path uses. Two records that share
111
+ * a filename stem across scopes appear as distinct entries.
112
+ */
113
+ listScoped(): Promise<Result<ReadonlyArray<IScopedMemoryRecord>>>;
114
+ /**
115
+ * Adapt this store to the {@link IMemoryRecordSource} seam so it can drive
116
+ * {@link IVectorIndex} rebuilds (e.g. `InMemoryCosineIndex.rebuild`). The
117
+ * returned source's `list()` delegates to {@link IMemoryStore.listScoped},
118
+ * **filtered to the kinds {@link IMemoryStore.embedsKind | embedsKind} reports** —
119
+ * this source exists to feed the record vector index, so a kind excluded from
120
+ * that index is excluded here too, and a reopen does not re-embed records the
121
+ * index will never return. With no
122
+ * {@link IFileTreeMemoryStoreCreateParams.embedKinds | embedKinds} declaration
123
+ * every kind participates and the filter is the identity. `listScoped` itself is
124
+ * **not** filtered and remains the whole-vault surface.
125
+ *
126
+ * The filter also **counts what it drops**, onto
127
+ * {@link IMemoryRecordListing.excluded} — this is the layer where the exclusion
128
+ * decision is made and so the only one that can. The count is always present
129
+ * (empty when nothing was excluded).
130
+ *
131
+ * The store cannot implement {@link IMemoryRecordSource} directly because its
132
+ * `list(filter?)` returns bare records (the ergonomic query surface) while the
133
+ * seam's `list()` returns scope-qualified records.
134
+ */
135
+ asRecordSource(): IMemoryRecordSource;
136
+ /**
137
+ * The EFFECTIVE {@link DedupScope} for `kind` — the granularity at which a
138
+ * write for this kind deduplicates against the existing vault.
139
+ *
140
+ * @remarks
141
+ * This is a **read accessor over the store's already-injected write policies**,
142
+ * and it is the single place any caller — the store's own write path included —
143
+ * asks what a kind's dedup granularity is. It resolves the full chain the store
144
+ * applies on write: the kind's registered {@link IWritePolicy}, falling back to
145
+ * the store's default policy, then that policy's
146
+ * {@link IWritePolicy.dedupScope | dedupScope}, falling back to
147
+ * {@link DEFAULT_DEDUP_SCOPE}. Note the store's default policy is a
148
+ * {@link KnowledgeLwwPolicy}, which declares `'content'` — so a kind with NO
149
+ * registered policy resolves to `'content'`, not to `DEFAULT_DEDUP_SCOPE`.
150
+ *
151
+ * It exists so a caller that must agree with the store about dedup granularity
152
+ * — notably the ingest orchestrator's stage-4 layer-1 exact match — can read the
153
+ * declaration through this seam instead of being handed a second copy of the
154
+ * policy map. A second declaration site is precisely the defect this accessor
155
+ * was added to remove.
156
+ *
157
+ * Deliberately synchronous, total, and NOT `Result`-returning: it reads
158
+ * constructor-injected configuration, touches no I/O, and cannot fail (every
159
+ * link in the fallback chain has a total default). It exposes only the scope,
160
+ * never the {@link IWritePolicy} itself, so it can never become a back door for
161
+ * invoking admission or merge logic out of band.
162
+ */
163
+ dedupScopeFor(kind: Kind): DedupScope;
164
+ /**
165
+ * Whether records of `kind` participate in the **record-granular** vector index.
166
+ *
167
+ * @remarks
168
+ * A read accessor over the store's injected {@link IFileTreeMemoryStoreCreateParams.embedKinds | embedKinds}
169
+ * declaration, in the same spirit as {@link IMemoryStore.dedupScopeFor} — one
170
+ * place to ask, so the store's write path and any caller reasoning about index
171
+ * coverage cannot disagree. `true` for every kind when no declaration was made.
172
+ *
173
+ * **This is distinct from a {@link MemoryEmbedder} decline, and the difference is
174
+ * cost.** An embedder that returns `undefined` has already been called: the
175
+ * round trip is paid, and on a locally-hosted model that round trip is the
176
+ * expense. A kind excluded here is never handed to the embedder at all. The
177
+ * decline makes the intent *expressible*; this makes it *free*.
178
+ *
179
+ * Deliberately synchronous, total, and NOT `Result`-returning: it reads
180
+ * constructor-injected configuration, touches no I/O, and cannot fail.
181
+ */
182
+ embedsKind(kind: Kind): boolean;
183
+ /**
184
+ * Write a record. Validates the body, computes a content hash, deduplicates
185
+ * (scope-wide, before policy), applies the kind's {@link IWritePolicy}, stamps
186
+ * transaction-time metadata (`created` / `updated` / `seq` / `contentHash`),
187
+ * writes the file, and patches the index. Returns the written record — or the
188
+ * existing record unchanged on a dedup no-op.
189
+ */
190
+ put(record: IMemoryRecord<unknown>): Promise<Result<IMemoryRecord<unknown>>>;
191
+ /**
192
+ * Repair one derived artifact for one {@link Kind} — **targeted and
193
+ * non-destructive**, unlike `IVectorIndex.rebuild`, which resets the index and
194
+ * re-embeds everything.
195
+ *
196
+ * @remarks
197
+ * The counterpart to {@link IMemoryStore.coverage}: coverage says **how big**
198
+ * the gap is and costs nothing; reconcile says **what it was** and closes what
199
+ * it can, at the cost of reading bodies and re-running the embedder. Neither
200
+ * substitutes for the other — in particular, only reconcile can distinguish a
201
+ * *declined* record from a *failed* one, because learning that requires calling
202
+ * the embedder again.
203
+ *
204
+ * **It only touches what is missing.** For the vector lanes it asks
205
+ * `has(target)` per record and skips the ones already held, so a repair after a
206
+ * brief outage costs a handful of embedder calls rather than a whole vault.
207
+ * That check is also the only way to see a record whose vector the index holds
208
+ * but whose envelope lost its `embeddingRef` — which needs a restamp and no
209
+ * embedder call at all, and which an `embeddingRef`-only repair cannot detect.
210
+ *
211
+ * **`artifact` is required and names one lane.** See {@link DerivedArtifact}
212
+ * for why an operation repairing "everything wired" would be the wrong shape.
213
+ *
214
+ * **A vector lane must be wired on BOTH halves — index *and* embedder — or this
215
+ * fails, and it is deliberately stricter than {@link IMemoryStore.coverage}.**
216
+ * The two ask different questions of the same wiring. Coverage asks *what does
217
+ * the index hold*, which an index alone can answer: an index wired without an
218
+ * embedder is a legal store (queries work; writes simply do not embed), so
219
+ * coverage reports that lane rather than pretending it is absent. Reconcile
220
+ * asks to *produce* vectors, which needs the embedder. So a half-wired store
221
+ * legitimately reports a coverage gap it cannot repair, and reconcile names the
222
+ * missing half rather than returning a cheerful success with every record in
223
+ * `failed`.
224
+ *
225
+ * Runs under the store's write lock, like any other mutation.
226
+ */
227
+ reconcile(kind: Kind, artifact: DerivedArtifact): Promise<Result<ReconcileReport>>;
228
+ /**
229
+ * Delete a record by `(kind, entityId)`. Non-temporal kinds physically delete
230
+ * the file and return the deleted record's {@link MemoryId}. Temporal
231
+ * (versioned) kinds SOFT-delete: the current version is invalidated
232
+ * (`invalid_at` set), history is retained, and the invalidated version's
233
+ * {@link MemoryId} is returned.
234
+ */
235
+ delete(kind: Kind, entityId: EntityId): Promise<Result<MemoryId>>;
236
+ }
237
+ //# sourceMappingURL=memoryStore.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memoryStore.d.ts","sourceRoot":"","sources":["../../../src/packlets/store/memoryStore.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AACvC,OAAO,EACL,UAAU,EACV,QAAQ,EACR,aAAa,EACb,qBAAqB,EACrB,IAAI,EACJ,QAAQ,EACR,cAAc,EACf,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AAC/C,OAAO,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAC;AACrE,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAE/D;;;;;;;;;GASG;AACH,MAAM,WAAW,YAAa,SAAQ,qBAAqB;IACzD;;;;;;;;OAQG;IACH,GAAG,CAAC,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,aAAa,CAAC,OAAO,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC;IAEzF;;OAEG;IACH,OAAO,CAAC,KAAK,EAAE,cAAc,EAAE,EAAE,EAAE,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,aAAa,CAAC,OAAO,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC;IAElG;;;;;;;;;;;;;;;;;OAiBG;IACH,IAAI,CAAC,SAAS,EAAE,mBAAmB,GAAG,OAAO,CAAC,MAAM,CAAC,aAAa,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;IAE7F;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAoCG;IACH,QAAQ,IAAI,OAAO,CAAC,MAAM,CAAC,qBAAqB,CAAC,CAAC,CAAC;IAEnD;;;;;;;;;;;;;OAaG;IACH,WAAW,IAAI,OAAO,CAAC,MAAM,CAAC,aAAa,CAAC,mBAAmB,CAAC,CAAC,CAAC,CAAC;IAEnE;;;;;;;OAOG;IACH,UAAU,IAAI,OAAO,CAAC,MAAM,CAAC,aAAa,CAAC,mBAAmB,CAAC,CAAC,CAAC,CAAC;IAElE;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,cAAc,IAAI,mBAAmB,CAAC;IAEtC;;;;;;;;;;;;;;;;;;;;;;;;;;OA0BG;IACH,aAAa,CAAC,IAAI,EAAE,IAAI,GAAG,UAAU,CAAC;IAEtC;;;;;;;;;;;;;;;;;OAiBG;IACH,UAAU,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC;IAEhC;;;;;;OAMG;IACH,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IAE7E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAmCG;IACH,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC,CAAC;IAEnF;;;;;;OAMG;IACH,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC;CACnE"}
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ /*
3
+ * Copyright (c) 2026 Erik Fortune
4
+ * SPDX-License-Identifier: MIT
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ //# sourceMappingURL=memoryStore.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memoryStore.js","sourceRoot":"","sources":["../../../src/packlets/store/memoryStore.ts"],"names":[],"mappings":";AAAA;;;GAGG","sourcesContent":["/*\n * Copyright (c) 2026 Erik Fortune\n * SPDX-License-Identifier: MIT\n */\n\nimport { Result } from '@fgv/ts-utils';\nimport {\n DedupScope,\n EntityId,\n IMemoryRecord,\n IMemoryRecordResolver,\n Kind,\n MemoryId,\n MemoryScopeKey\n} from '../types';\nimport { IIndexedMemoryEntry } from '../index';\nimport { IMemoryRecordSource, IScopedMemoryRecord } from '../vector';\nimport { MemoryListSelection } from './listSelection';\nimport { IDerivedStateCoverage } from './coverage';\nimport { DerivedArtifact, ReconcileReport } from './reconcile';\n\n/**\n * The writable, FileTree-backed, content-hash-deduped memory store.\n *\n * @remarks\n * Extends {@link IMemoryRecordResolver} because the retrievers take a resolver\n * and a store is the obvious one to hand them — `{ index, resolver: store }` is\n * the documented wiring, and it has to type-check for the `IMemoryStore` handle\n * a consumer actually holds, not only for the concrete `FileTreeMemoryStore`.\n * @public\n */\nexport interface IMemoryStore extends IMemoryRecordResolver {\n /**\n * Keyed read by entity id. Resolves `entityId` to a storage address via the\n * registered {@link IIdentityCodec} for `kind`. Returns `undefined` when no\n * record exists. For a versioned (temporal) kind the current version is\n * *selected* from the derived in-memory index — the version history is walked\n * over envelopes, never bodies — and then that one version is read from\n * storage. So the selection costs no file reads and the result costs exactly\n * one, rather than one per version.\n */\n get(kind: Kind, entityId: EntityId): Promise<Result<IMemoryRecord<unknown> | undefined>>;\n\n /**\n * Direct read by `(scope, MemoryId)`. Returns `undefined` when not found.\n */\n getById(scope: MemoryScopeKey, id: MemoryId): Promise<Result<IMemoryRecord<unknown> | undefined>>;\n\n /**\n * List records: select over the derived index, then materialize the survivors.\n *\n * @remarks\n * **The selection is required and must narrow.** Since the index holds\n * envelopes only, every returned record is read from storage — so a call that\n * narrows nothing reads the whole vault, and that has to be a decision rather\n * than a default. Omitting the argument is a compile error; passing one with no\n * `scope` / `kind` / `tag` fails with a message naming {@link scanEveryRecord},\n * which is how a caller says it meant it.\n *\n * The requirement buys **explicitness, not a cost bound** — `{ kind }` on a\n * vault dominated by that kind still materializes most of it. What it prevents\n * is the whole-vault read nobody chose.\n *\n * If you only need to select, use {@link IMemoryStore.listEntries} instead: no\n * selection, no file reads.\n */\n list(selection: MemoryListSelection): Promise<Result<ReadonlyArray<IMemoryRecord<unknown>>>>;\n\n /**\n * How much of the store's **derived state** exists, resolved by {@link Kind}.\n *\n * @remarks\n * Answers *\"is my derived state consistent with my records, and if not by how\n * much?\"* for every artifact the store derives — `rank`, record vectors, and\n * fragment vectors — in one call.\n *\n * **Cheap and total, by contract rather than by implementation.** Every input is\n * an envelope field or an index-side count: it reads **no record bodies** and\n * calls **no embedder**, and the walk over the vault's own state touches the\n * filesystem not at all. That is why it takes no selection, unlike\n * {@link IMemoryStore.list} — the guard there exists because an unnarrowed list\n * reads the vault, and putting one here would decorate a free operation and make\n * that guard mean less.\n *\n * **The index-side counts are the one exception, and it is the caller's own\n * index that spends it.** A persistent index answers `size` / `recordCount` /\n * `fragmentCount` with a query — `SqliteVecVectorIndex` runs a prepared `COUNT`\n * — so on a durable backend this call does I/O and can **fail**. It is bounded\n * (one count per wired index, never per record) and it is why the return is a\n * `Result` rather than a bare value.\n *\n * *If a future addition to the report would require reading a record body, it\n * does not belong on this report.*\n *\n * The counterpart is {@link IMemoryStore.reconcile}: coverage says **how big**\n * the gap is, cheaply; reconcile says **what it was** and closes what it can, at\n * the cost of re-running the embedder. Neither substitutes for the other.\n *\n * **A lane is reported here whenever its *index* is wired**, which is weaker\n * than what reconcile requires (index **and** embedder). That is intended: an\n * index without an embedder still holds vectors and still answers queries, so\n * its coverage is a real number worth reporting. The consequence to expect is a\n * half-wired store that reports a gap `reconcile` will refuse to close, naming\n * the missing embedder.\n */\n coverage(): Promise<Result<IDerivedStateCoverage>>;\n\n /**\n * Every entry in the vault — scope and envelope, **no bodies**. Reads no files\n * and requires no selection, because there is nothing to be careful about: it\n * returns what the index already holds.\n *\n * @remarks\n * This is the whole-vault read most callers actually want. Selection, grouping,\n * counting, \"which kinds are in here\", \"what links at this\" — all of it is\n * envelope work. Reach for {@link IMemoryStore.list} with\n * {@link scanEveryRecord} only when you genuinely need every body.\n *\n * Synchronous in spirit but `Promise`-returning for consistency with the rest\n * of the store surface.\n */\n listEntries(): Promise<Result<ReadonlyArray<IIndexedMemoryEntry>>>;\n\n /**\n * List EVERY record in the vault, each paired with its scope-qualified\n * `(scope, id)` address — the projection {@link IMemoryRecordSource} requires.\n * Unlike {@link IMemoryStore.list | list}, it takes no filter (whole-vault) and\n * returns {@link IScopedMemoryRecord}s so a re-index keys each entry on the same\n * scoped target the incremental embed-on-write path uses. Two records that share\n * a filename stem across scopes appear as distinct entries.\n */\n listScoped(): Promise<Result<ReadonlyArray<IScopedMemoryRecord>>>;\n\n /**\n * Adapt this store to the {@link IMemoryRecordSource} seam so it can drive\n * {@link IVectorIndex} rebuilds (e.g. `InMemoryCosineIndex.rebuild`). The\n * returned source's `list()` delegates to {@link IMemoryStore.listScoped},\n * **filtered to the kinds {@link IMemoryStore.embedsKind | embedsKind} reports** —\n * this source exists to feed the record vector index, so a kind excluded from\n * that index is excluded here too, and a reopen does not re-embed records the\n * index will never return. With no\n * {@link IFileTreeMemoryStoreCreateParams.embedKinds | embedKinds} declaration\n * every kind participates and the filter is the identity. `listScoped` itself is\n * **not** filtered and remains the whole-vault surface.\n *\n * The filter also **counts what it drops**, onto\n * {@link IMemoryRecordListing.excluded} — this is the layer where the exclusion\n * decision is made and so the only one that can. The count is always present\n * (empty when nothing was excluded).\n *\n * The store cannot implement {@link IMemoryRecordSource} directly because its\n * `list(filter?)` returns bare records (the ergonomic query surface) while the\n * seam's `list()` returns scope-qualified records.\n */\n asRecordSource(): IMemoryRecordSource;\n\n /**\n * The EFFECTIVE {@link DedupScope} for `kind` — the granularity at which a\n * write for this kind deduplicates against the existing vault.\n *\n * @remarks\n * This is a **read accessor over the store's already-injected write policies**,\n * and it is the single place any caller — the store's own write path included —\n * asks what a kind's dedup granularity is. It resolves the full chain the store\n * applies on write: the kind's registered {@link IWritePolicy}, falling back to\n * the store's default policy, then that policy's\n * {@link IWritePolicy.dedupScope | dedupScope}, falling back to\n * {@link DEFAULT_DEDUP_SCOPE}. Note the store's default policy is a\n * {@link KnowledgeLwwPolicy}, which declares `'content'` — so a kind with NO\n * registered policy resolves to `'content'`, not to `DEFAULT_DEDUP_SCOPE`.\n *\n * It exists so a caller that must agree with the store about dedup granularity\n * — notably the ingest orchestrator's stage-4 layer-1 exact match — can read the\n * declaration through this seam instead of being handed a second copy of the\n * policy map. A second declaration site is precisely the defect this accessor\n * was added to remove.\n *\n * Deliberately synchronous, total, and NOT `Result`-returning: it reads\n * constructor-injected configuration, touches no I/O, and cannot fail (every\n * link in the fallback chain has a total default). It exposes only the scope,\n * never the {@link IWritePolicy} itself, so it can never become a back door for\n * invoking admission or merge logic out of band.\n */\n dedupScopeFor(kind: Kind): DedupScope;\n\n /**\n * Whether records of `kind` participate in the **record-granular** vector index.\n *\n * @remarks\n * A read accessor over the store's injected {@link IFileTreeMemoryStoreCreateParams.embedKinds | embedKinds}\n * declaration, in the same spirit as {@link IMemoryStore.dedupScopeFor} — one\n * place to ask, so the store's write path and any caller reasoning about index\n * coverage cannot disagree. `true` for every kind when no declaration was made.\n *\n * **This is distinct from a {@link MemoryEmbedder} decline, and the difference is\n * cost.** An embedder that returns `undefined` has already been called: the\n * round trip is paid, and on a locally-hosted model that round trip is the\n * expense. A kind excluded here is never handed to the embedder at all. The\n * decline makes the intent *expressible*; this makes it *free*.\n *\n * Deliberately synchronous, total, and NOT `Result`-returning: it reads\n * constructor-injected configuration, touches no I/O, and cannot fail.\n */\n embedsKind(kind: Kind): boolean;\n\n /**\n * Write a record. Validates the body, computes a content hash, deduplicates\n * (scope-wide, before policy), applies the kind's {@link IWritePolicy}, stamps\n * transaction-time metadata (`created` / `updated` / `seq` / `contentHash`),\n * writes the file, and patches the index. Returns the written record — or the\n * existing record unchanged on a dedup no-op.\n */\n put(record: IMemoryRecord<unknown>): Promise<Result<IMemoryRecord<unknown>>>;\n\n /**\n * Repair one derived artifact for one {@link Kind} — **targeted and\n * non-destructive**, unlike `IVectorIndex.rebuild`, which resets the index and\n * re-embeds everything.\n *\n * @remarks\n * The counterpart to {@link IMemoryStore.coverage}: coverage says **how big**\n * the gap is and costs nothing; reconcile says **what it was** and closes what\n * it can, at the cost of reading bodies and re-running the embedder. Neither\n * substitutes for the other — in particular, only reconcile can distinguish a\n * *declined* record from a *failed* one, because learning that requires calling\n * the embedder again.\n *\n * **It only touches what is missing.** For the vector lanes it asks\n * `has(target)` per record and skips the ones already held, so a repair after a\n * brief outage costs a handful of embedder calls rather than a whole vault.\n * That check is also the only way to see a record whose vector the index holds\n * but whose envelope lost its `embeddingRef` — which needs a restamp and no\n * embedder call at all, and which an `embeddingRef`-only repair cannot detect.\n *\n * **`artifact` is required and names one lane.** See {@link DerivedArtifact}\n * for why an operation repairing \"everything wired\" would be the wrong shape.\n *\n * **A vector lane must be wired on BOTH halves — index *and* embedder — or this\n * fails, and it is deliberately stricter than {@link IMemoryStore.coverage}.**\n * The two ask different questions of the same wiring. Coverage asks *what does\n * the index hold*, which an index alone can answer: an index wired without an\n * embedder is a legal store (queries work; writes simply do not embed), so\n * coverage reports that lane rather than pretending it is absent. Reconcile\n * asks to *produce* vectors, which needs the embedder. So a half-wired store\n * legitimately reports a coverage gap it cannot repair, and reconcile names the\n * missing half rather than returning a cheerful success with every record in\n * `failed`.\n *\n * Runs under the store's write lock, like any other mutation.\n */\n reconcile(kind: Kind, artifact: DerivedArtifact): Promise<Result<ReconcileReport>>;\n\n /**\n * Delete a record by `(kind, entityId)`. Non-temporal kinds physically delete\n * the file and return the deleted record's {@link MemoryId}. Temporal\n * (versioned) kinds SOFT-delete: the current version is invalidated\n * (`invalid_at` set), history is retained, and the invalidated version's\n * {@link MemoryId} is returned.\n */\n delete(kind: Kind, entityId: EntityId): Promise<Result<MemoryId>>;\n}\n"]}
@@ -0,0 +1,82 @@
1
+ import { Kind } from '../types';
2
+ import { ISkippedVectorRecord } from '../vector';
3
+ /**
4
+ * Which derived artifact a {@link IMemoryStore.reconcile} call repairs.
5
+ *
6
+ * @remarks
7
+ * **The operation names its artifact rather than repairing everything wired**,
8
+ * and the reasons are structural rather than stylistic: the record and fragment
9
+ * lanes are independently wirable (so an unnamed repair on a fragment-only store
10
+ * would have to no-op or guess), their units are incommensurable (one vector per
11
+ * record vs. N), and their costs differ by orders of magnitude — a measured case
12
+ * put 68 fragments behind a single 56 KB record. An operation whose cost varies
13
+ * that much along a dimension it does not name is the accidental-expense shape
14
+ * `IMemoryStore.list`'s required selection exists to prevent.
15
+ * @public
16
+ */
17
+ export type DerivedArtifact = 'rank' | 'record-vector' | 'fragment-vector';
18
+ /** What every reconcile reports, whatever the artifact. @public */
19
+ export interface IReconcileReportBase {
20
+ /** The kind reconciled — named by the caller, so every count below is scalar. */
21
+ readonly kind: Kind;
22
+ /** Records of this kind considered. The denominator for everything else. */
23
+ readonly examined: number;
24
+ /** Records whose derived artifact was (re)produced by this call. */
25
+ readonly repaired: number;
26
+ /** Records that failed, with the error. A fault, never a decline. */
27
+ readonly failed: ReadonlyArray<ISkippedVectorRecord>;
28
+ }
29
+ /** A `rank` reconcile: re-run the projector and restamp what changed. @public */
30
+ export interface IRankReconcileReport extends IReconcileReportBase {
31
+ readonly artifact: 'rank';
32
+ }
33
+ /**
34
+ * A record-vector reconcile.
35
+ * @public
36
+ */
37
+ export interface IVectorReconcileReport extends IReconcileReportBase {
38
+ readonly artifact: 'record-vector';
39
+ /**
40
+ * Records the index already held and which needed **no embedder call** — the
41
+ * whole point of a targeted repair, and the number that shows what it saved
42
+ * against a `rebuild`.
43
+ */
44
+ readonly alreadyIndexed: number;
45
+ /**
46
+ * Records whose vector the index held but whose envelope had **lost its
47
+ * `embeddingRef`** — repaired by restamping the reference, with no embedder
48
+ * call.
49
+ *
50
+ * @remarks
51
+ * This case is invisible to an `embeddingRef`-only check, which is one of the
52
+ * two reasons `IVectorIndex.has` is on the contract: a reference-absent record
53
+ * looks identical to a never-embedded one until you ask the index.
54
+ */
55
+ readonly restamped: number;
56
+ /** Records the embedder intentionally declined. Not a failure, not a gap. */
57
+ readonly declined: number;
58
+ }
59
+ /**
60
+ * A fragment-vector reconcile.
61
+ *
62
+ * @remarks
63
+ * Note there is no `restamped`: the fragment lane has **no envelope marker**, so
64
+ * there is no reference that can go missing and nothing to restamp. The
65
+ * asymmetry with {@link IVectorReconcileReport} is real rather than an oversight.
66
+ * @public
67
+ */
68
+ export interface IFragmentReconcileReport extends IReconcileReportBase {
69
+ readonly artifact: 'fragment-vector';
70
+ /** Records already represented, needing no embedder call. */
71
+ readonly alreadyIndexed: number;
72
+ /** Records whose embedder produced no fragments — this lane's decline. */
73
+ readonly declined: number;
74
+ /** Fragments written by this call — the fan-out `repaired` cannot express. */
75
+ readonly fragments: number;
76
+ }
77
+ /**
78
+ * What a {@link IMemoryStore.reconcile} established, discriminated by artifact.
79
+ * @public
80
+ */
81
+ export type ReconcileReport = IRankReconcileReport | IVectorReconcileReport | IFragmentReconcileReport;
82
+ //# sourceMappingURL=reconcile.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reconcile.d.ts","sourceRoot":"","sources":["../../../src/packlets/store/reconcile.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAChC,OAAO,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAC;AAEjD;;;;;;;;;;;;;GAaG;AACH,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,eAAe,GAAG,iBAAiB,CAAC;AAE3E,mEAAmE;AACnE,MAAM,WAAW,oBAAoB;IACnC,iFAAiF;IACjF,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC;IACpB,4EAA4E;IAC5E,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,oEAAoE;IACpE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,qEAAqE;IACrE,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC,oBAAoB,CAAC,CAAC;CACtD;AAED,iFAAiF;AACjF,MAAM,WAAW,oBAAqB,SAAQ,oBAAoB;IAChE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B;AAED;;;GAGG;AACH,MAAM,WAAW,sBAAuB,SAAQ,oBAAoB;IAClE,QAAQ,CAAC,QAAQ,EAAE,eAAe,CAAC;IACnC;;;;OAIG;IACH,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC;;;;;;;;;OASG;IACH,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,6EAA6E;IAC7E,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,wBAAyB,SAAQ,oBAAoB;IACpE,QAAQ,CAAC,QAAQ,EAAE,iBAAiB,CAAC;IACrC,6DAA6D;IAC7D,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,0EAA0E;IAC1E,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,8EAA8E;IAC9E,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAED;;;GAGG;AACH,MAAM,MAAM,eAAe,GAAG,oBAAoB,GAAG,sBAAsB,GAAG,wBAAwB,CAAC"}
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ /*
3
+ * Copyright (c) 2026 Erik Fortune
4
+ * SPDX-License-Identifier: MIT
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ //# sourceMappingURL=reconcile.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reconcile.js","sourceRoot":"","sources":["../../../src/packlets/store/reconcile.ts"],"names":[],"mappings":";AAAA;;;GAGG","sourcesContent":["/*\n * Copyright (c) 2026 Erik Fortune\n * SPDX-License-Identifier: MIT\n */\n\nimport { Kind } from '../types';\nimport { ISkippedVectorRecord } from '../vector';\n\n/**\n * Which derived artifact a {@link IMemoryStore.reconcile} call repairs.\n *\n * @remarks\n * **The operation names its artifact rather than repairing everything wired**,\n * and the reasons are structural rather than stylistic: the record and fragment\n * lanes are independently wirable (so an unnamed repair on a fragment-only store\n * would have to no-op or guess), their units are incommensurable (one vector per\n * record vs. N), and their costs differ by orders of magnitude — a measured case\n * put 68 fragments behind a single 56 KB record. An operation whose cost varies\n * that much along a dimension it does not name is the accidental-expense shape\n * `IMemoryStore.list`'s required selection exists to prevent.\n * @public\n */\nexport type DerivedArtifact = 'rank' | 'record-vector' | 'fragment-vector';\n\n/** What every reconcile reports, whatever the artifact. @public */\nexport interface IReconcileReportBase {\n /** The kind reconciled — named by the caller, so every count below is scalar. */\n readonly kind: Kind;\n /** Records of this kind considered. The denominator for everything else. */\n readonly examined: number;\n /** Records whose derived artifact was (re)produced by this call. */\n readonly repaired: number;\n /** Records that failed, with the error. A fault, never a decline. */\n readonly failed: ReadonlyArray<ISkippedVectorRecord>;\n}\n\n/** A `rank` reconcile: re-run the projector and restamp what changed. @public */\nexport interface IRankReconcileReport extends IReconcileReportBase {\n readonly artifact: 'rank';\n}\n\n/**\n * A record-vector reconcile.\n * @public\n */\nexport interface IVectorReconcileReport extends IReconcileReportBase {\n readonly artifact: 'record-vector';\n /**\n * Records the index already held and which needed **no embedder call** — the\n * whole point of a targeted repair, and the number that shows what it saved\n * against a `rebuild`.\n */\n readonly alreadyIndexed: number;\n /**\n * Records whose vector the index held but whose envelope had **lost its\n * `embeddingRef`** — repaired by restamping the reference, with no embedder\n * call.\n *\n * @remarks\n * This case is invisible to an `embeddingRef`-only check, which is one of the\n * two reasons `IVectorIndex.has` is on the contract: a reference-absent record\n * looks identical to a never-embedded one until you ask the index.\n */\n readonly restamped: number;\n /** Records the embedder intentionally declined. Not a failure, not a gap. */\n readonly declined: number;\n}\n\n/**\n * A fragment-vector reconcile.\n *\n * @remarks\n * Note there is no `restamped`: the fragment lane has **no envelope marker**, so\n * there is no reference that can go missing and nothing to restamp. The\n * asymmetry with {@link IVectorReconcileReport} is real rather than an oversight.\n * @public\n */\nexport interface IFragmentReconcileReport extends IReconcileReportBase {\n readonly artifact: 'fragment-vector';\n /** Records already represented, needing no embedder call. */\n readonly alreadyIndexed: number;\n /** Records whose embedder produced no fragments — this lane's decline. */\n readonly declined: number;\n /** Fragments written by this call — the fan-out `repaired` cannot express. */\n readonly fragments: number;\n}\n\n/**\n * What a {@link IMemoryStore.reconcile} established, discriminated by artifact.\n * @public\n */\nexport type ReconcileReport = IRankReconcileReport | IVectorReconcileReport | IFragmentReconcileReport;\n"]}
@@ -0,0 +1,45 @@
1
+ import { Result } from '@fgv/ts-utils';
2
+ import { Kind } from '../types';
3
+ import { IIndexedMemoryEntry } from '../index';
4
+ import { IFragmentVectorIndex, IVectorIndex } from '../vector';
5
+ import { IDerivedStateCoverage } from './coverage';
6
+ /**
7
+ * Everything {@link computeCoverage} needs, supplied by the store.
8
+ *
9
+ * @remarks
10
+ * Taken as inputs rather than reading a store, so this module has no dependency
11
+ * on `FileTreeMemoryStore` and the walk is testable on its own. Package-internal:
12
+ * `IMemoryStore.coverage` is the published surface.
13
+ */
14
+ export interface IComputeCoverageParams {
15
+ /** The projected index entries — envelopes only, already free of file reads. */
16
+ readonly entries: ReadonlyArray<IIndexedMemoryEntry>;
17
+ /** Whether `kind` has a registered rank projector. */
18
+ readonly hasRankProjector: (kind: Kind) => boolean;
19
+ /** Whether ANY kind has one — distinguishes an unwired lane from an empty one. */
20
+ readonly anyRankProjector: boolean;
21
+ /** Whether `kind` participates in the record-granular vector index. */
22
+ readonly embedsKind: (kind: Kind) => boolean;
23
+ /** The wired record-vector index, or `undefined` when the lane is unwired. */
24
+ readonly vectorIndex: IVectorIndex | undefined;
25
+ /** The wired fragment index, or `undefined` when the lane is unwired. */
26
+ readonly fragmentIndex: IFragmentVectorIndex | undefined;
27
+ }
28
+ /**
29
+ * One walk over the projected entries, producing every derived-state count.
30
+ *
31
+ * @remarks
32
+ * **Reads no record bodies and calls no embedder**, and the walk itself touches
33
+ * no filesystem. That is the contract `IMemoryStore.coverage` makes, and this
34
+ * function is where it is kept: every number below comes from an envelope field
35
+ * or an index-side count. The index-side counts are the one place that leaves
36
+ * envelope territory — on a durable backend they run a query, which is why they
37
+ * are captured (see the comment at the `captureResult` below) and why the walk's
38
+ * "no filesystem" claim is scoped to the walk rather than the whole call. A
39
+ * future addition that needs a body does not belong here.
40
+ *
41
+ * Extracted from `fileTreeMemoryStore.ts` because inlining it took that file past
42
+ * the 2000-line `max-lines` cap — the same reason `vectorRecordSource.ts` exists.
43
+ */
44
+ export declare function computeCoverage(params: IComputeCoverageParams): Result<IDerivedStateCoverage>;
45
+ //# sourceMappingURL=storeCoverage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storeCoverage.d.ts","sourceRoot":"","sources":["../../../src/packlets/store/storeCoverage.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,MAAM,EAA0B,MAAM,eAAe,CAAC;AAC/D,OAAO,EAAE,IAAI,EAAkB,MAAM,UAAU,CAAC;AAChD,OAAO,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AAC/C,OAAO,EAAE,oBAAoB,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAC/D,OAAO,EAAqB,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAEtE;;;;;;;GAOG;AACH,MAAM,WAAW,sBAAsB;IACrC,gFAAgF;IAChF,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC,mBAAmB,CAAC,CAAC;IACrD,sDAAsD;IACtD,QAAQ,CAAC,gBAAgB,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC;IACnD,kFAAkF;IAClF,QAAQ,CAAC,gBAAgB,EAAE,OAAO,CAAC;IACnC,uEAAuE;IACvE,QAAQ,CAAC,UAAU,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC;IAC7C,8EAA8E;IAC9E,QAAQ,CAAC,WAAW,EAAE,YAAY,GAAG,SAAS,CAAC;IAC/C,yEAAyE;IACzE,QAAQ,CAAC,aAAa,EAAE,oBAAoB,GAAG,SAAS,CAAC;CAC1D;AAkBD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,sBAAsB,GAAG,MAAM,CAAC,qBAAqB,CAAC,CAkF7F"}