@fgv/ts-agent-memory 5.1.0-37 → 5.1.0-39

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 (197) hide show
  1. package/.rush/temp/{6dfc331ddf74dc2db0d4483d0c96ea971f351c83.tar.log → b82cf6bdece20481260e6bab946179eeec9d7b46.tar.log} +116 -2
  2. package/.rush/temp/chunked-rush-logs/ts-agent-memory.build.chunks.jsonl +4 -4
  3. package/.rush/temp/operation/build/all.log +4 -4
  4. package/.rush/temp/operation/build/log-chunks.jsonl +4 -4
  5. package/.rush/temp/operation/build/state.json +1 -1
  6. package/.rush/temp/shrinkwrap-deps.json +222 -221
  7. package/config/jest.config.json +1 -1
  8. package/dist/index.js +2 -0
  9. package/dist/index.js.map +1 -1
  10. package/dist/packlets/ingest/cycleGuard.js +111 -0
  11. package/dist/packlets/ingest/cycleGuard.js.map +1 -0
  12. package/dist/packlets/ingest/hostStages.js +6 -0
  13. package/dist/packlets/ingest/hostStages.js.map +1 -0
  14. package/dist/packlets/ingest/index.js +9 -0
  15. package/dist/packlets/ingest/index.js.map +1 -0
  16. package/dist/packlets/ingest/model.js +6 -0
  17. package/dist/packlets/ingest/model.js.map +1 -0
  18. package/dist/packlets/ingest/orchestrator.js +438 -0
  19. package/dist/packlets/ingest/orchestrator.js.map +1 -0
  20. package/dist/packlets/retrieve/index.js +1 -0
  21. package/dist/packlets/retrieve/index.js.map +1 -1
  22. package/dist/packlets/retrieve/temporalRetrievers.js +172 -0
  23. package/dist/packlets/retrieve/temporalRetrievers.js.map +1 -0
  24. package/dist/packlets/store/fileTreeMemoryStore.js +323 -41
  25. package/dist/packlets/store/fileTreeMemoryStore.js.map +1 -1
  26. package/dist/packlets/tools/index.js +6 -0
  27. package/dist/packlets/tools/index.js.map +1 -0
  28. package/dist/packlets/tools/memoryTools.js +337 -0
  29. package/dist/packlets/tools/memoryTools.js.map +1 -0
  30. package/dist/packlets/types/identityCodec.js +115 -0
  31. package/dist/packlets/types/identityCodec.js.map +1 -1
  32. package/dist/packlets/types/index.js +1 -0
  33. package/dist/packlets/types/index.js.map +1 -1
  34. package/dist/packlets/types/temporal.js +85 -0
  35. package/dist/packlets/types/temporal.js.map +1 -0
  36. package/dist/packlets/types/writePolicy.js +96 -0
  37. package/dist/packlets/types/writePolicy.js.map +1 -1
  38. package/dist/test/unit/converters/antagonistRoundTrip.test.js +95 -0
  39. package/dist/test/unit/converters/antagonistRoundTrip.test.js.map +1 -0
  40. package/dist/test/unit/ingest/antagonistCycleAndParity.test.js +273 -0
  41. package/dist/test/unit/ingest/antagonistCycleAndParity.test.js.map +1 -0
  42. package/dist/test/unit/ingest/cycleGuard.test.js +54 -0
  43. package/dist/test/unit/ingest/cycleGuard.test.js.map +1 -0
  44. package/dist/test/unit/ingest/orchestrator.test.js +913 -0
  45. package/dist/test/unit/ingest/orchestrator.test.js.map +1 -0
  46. package/dist/test/unit/retrieve/temporalRetrievers.test.js +182 -0
  47. package/dist/test/unit/retrieve/temporalRetrievers.test.js.map +1 -0
  48. package/dist/test/unit/store/antagonistTemporalBoundary.test.js +120 -0
  49. package/dist/test/unit/store/antagonistTemporalBoundary.test.js.map +1 -0
  50. package/dist/test/unit/store/fileTreeMemoryStore.test.js +74 -7
  51. package/dist/test/unit/store/fileTreeMemoryStore.test.js.map +1 -1
  52. package/dist/test/unit/store/temporalStore.test.js +398 -0
  53. package/dist/test/unit/store/temporalStore.test.js.map +1 -0
  54. package/dist/test/unit/tools/memoryTools.test.js +572 -0
  55. package/dist/test/unit/tools/memoryTools.test.js.map +1 -0
  56. package/dist/test/unit/types/temporalCodec.test.js +203 -0
  57. package/dist/test/unit/types/temporalCodec.test.js.map +1 -0
  58. package/dist/test/unit/types/temporalPolicy.test.js +62 -0
  59. package/dist/test/unit/types/temporalPolicy.test.js.map +1 -0
  60. package/dist/ts-agent-memory.d.ts +1042 -10
  61. package/dist/tsdoc-metadata.json +1 -1
  62. package/etc/ts-agent-memory.api.md +284 -0
  63. package/lib/index.d.ts +2 -0
  64. package/lib/index.d.ts.map +1 -1
  65. package/lib/index.js +2 -0
  66. package/lib/index.js.map +1 -1
  67. package/lib/packlets/ingest/cycleGuard.d.ts +41 -0
  68. package/lib/packlets/ingest/cycleGuard.d.ts.map +1 -0
  69. package/lib/packlets/ingest/cycleGuard.js +115 -0
  70. package/lib/packlets/ingest/cycleGuard.js.map +1 -0
  71. package/lib/packlets/ingest/hostStages.d.ts +88 -0
  72. package/lib/packlets/ingest/hostStages.d.ts.map +1 -0
  73. package/lib/packlets/ingest/hostStages.js +7 -0
  74. package/lib/packlets/ingest/hostStages.js.map +1 -0
  75. package/lib/packlets/ingest/index.d.ts +5 -0
  76. package/lib/packlets/ingest/index.d.ts.map +1 -0
  77. package/lib/packlets/ingest/index.js +25 -0
  78. package/lib/packlets/ingest/index.js.map +1 -0
  79. package/lib/packlets/ingest/model.d.ts +177 -0
  80. package/lib/packlets/ingest/model.d.ts.map +1 -0
  81. package/lib/packlets/ingest/model.js +7 -0
  82. package/lib/packlets/ingest/model.js.map +1 -0
  83. package/lib/packlets/ingest/orchestrator.d.ts +206 -0
  84. package/lib/packlets/ingest/orchestrator.d.ts.map +1 -0
  85. package/lib/packlets/ingest/orchestrator.js +442 -0
  86. package/lib/packlets/ingest/orchestrator.js.map +1 -0
  87. package/lib/packlets/retrieve/index.d.ts +1 -0
  88. package/lib/packlets/retrieve/index.d.ts.map +1 -1
  89. package/lib/packlets/retrieve/index.js +1 -0
  90. package/lib/packlets/retrieve/index.js.map +1 -1
  91. package/lib/packlets/retrieve/temporalRetrievers.d.ts +78 -0
  92. package/lib/packlets/retrieve/temporalRetrievers.d.ts.map +1 -0
  93. package/lib/packlets/retrieve/temporalRetrievers.js +178 -0
  94. package/lib/packlets/retrieve/temporalRetrievers.js.map +1 -0
  95. package/lib/packlets/store/fileTreeMemoryStore.d.ts +118 -9
  96. package/lib/packlets/store/fileTreeMemoryStore.d.ts.map +1 -1
  97. package/lib/packlets/store/fileTreeMemoryStore.js +322 -40
  98. package/lib/packlets/store/fileTreeMemoryStore.js.map +1 -1
  99. package/lib/packlets/tools/index.d.ts +2 -0
  100. package/lib/packlets/tools/index.d.ts.map +1 -0
  101. package/lib/packlets/tools/index.js +22 -0
  102. package/lib/packlets/tools/index.js.map +1 -0
  103. package/lib/packlets/tools/memoryTools.d.ts +139 -0
  104. package/lib/packlets/tools/memoryTools.d.ts.map +1 -0
  105. package/lib/packlets/tools/memoryTools.js +341 -0
  106. package/lib/packlets/tools/memoryTools.js.map +1 -0
  107. package/lib/packlets/types/identityCodec.d.ts +86 -0
  108. package/lib/packlets/types/identityCodec.d.ts.map +1 -1
  109. package/lib/packlets/types/identityCodec.js +118 -1
  110. package/lib/packlets/types/identityCodec.js.map +1 -1
  111. package/lib/packlets/types/index.d.ts +1 -0
  112. package/lib/packlets/types/index.d.ts.map +1 -1
  113. package/lib/packlets/types/index.js +1 -0
  114. package/lib/packlets/types/index.js.map +1 -1
  115. package/lib/packlets/types/temporal.d.ts +40 -0
  116. package/lib/packlets/types/temporal.d.ts.map +1 -0
  117. package/lib/packlets/types/temporal.js +92 -0
  118. package/lib/packlets/types/temporal.js.map +1 -0
  119. package/lib/packlets/types/writePolicy.d.ts +49 -0
  120. package/lib/packlets/types/writePolicy.d.ts.map +1 -1
  121. package/lib/packlets/types/writePolicy.js +98 -1
  122. package/lib/packlets/types/writePolicy.js.map +1 -1
  123. package/lib/test/unit/converters/antagonistRoundTrip.test.d.ts +10 -0
  124. package/lib/test/unit/converters/antagonistRoundTrip.test.d.ts.map +1 -0
  125. package/lib/test/unit/converters/antagonistRoundTrip.test.js +97 -0
  126. package/lib/test/unit/converters/antagonistRoundTrip.test.js.map +1 -0
  127. package/lib/test/unit/ingest/antagonistCycleAndParity.test.d.ts +9 -0
  128. package/lib/test/unit/ingest/antagonistCycleAndParity.test.d.ts.map +1 -0
  129. package/lib/test/unit/ingest/antagonistCycleAndParity.test.js +275 -0
  130. package/lib/test/unit/ingest/antagonistCycleAndParity.test.js.map +1 -0
  131. package/lib/test/unit/ingest/cycleGuard.test.d.ts +2 -0
  132. package/lib/test/unit/ingest/cycleGuard.test.d.ts.map +1 -0
  133. package/lib/test/unit/ingest/cycleGuard.test.js +56 -0
  134. package/lib/test/unit/ingest/cycleGuard.test.js.map +1 -0
  135. package/lib/test/unit/ingest/orchestrator.test.d.ts +2 -0
  136. package/lib/test/unit/ingest/orchestrator.test.d.ts.map +1 -0
  137. package/lib/test/unit/ingest/orchestrator.test.js +915 -0
  138. package/lib/test/unit/ingest/orchestrator.test.js.map +1 -0
  139. package/lib/test/unit/retrieve/temporalRetrievers.test.d.ts +2 -0
  140. package/lib/test/unit/retrieve/temporalRetrievers.test.d.ts.map +1 -0
  141. package/lib/test/unit/retrieve/temporalRetrievers.test.js +184 -0
  142. package/lib/test/unit/retrieve/temporalRetrievers.test.js.map +1 -0
  143. package/lib/test/unit/store/antagonistTemporalBoundary.test.d.ts +9 -0
  144. package/lib/test/unit/store/antagonistTemporalBoundary.test.d.ts.map +1 -0
  145. package/lib/test/unit/store/antagonistTemporalBoundary.test.js +122 -0
  146. package/lib/test/unit/store/antagonistTemporalBoundary.test.js.map +1 -0
  147. package/lib/test/unit/store/fileTreeMemoryStore.test.js +74 -7
  148. package/lib/test/unit/store/fileTreeMemoryStore.test.js.map +1 -1
  149. package/lib/test/unit/store/temporalStore.test.d.ts +2 -0
  150. package/lib/test/unit/store/temporalStore.test.d.ts.map +1 -0
  151. package/lib/test/unit/store/temporalStore.test.js +400 -0
  152. package/lib/test/unit/store/temporalStore.test.js.map +1 -0
  153. package/lib/test/unit/tools/memoryTools.test.d.ts +2 -0
  154. package/lib/test/unit/tools/memoryTools.test.d.ts.map +1 -0
  155. package/lib/test/unit/tools/memoryTools.test.js +574 -0
  156. package/lib/test/unit/tools/memoryTools.test.js.map +1 -0
  157. package/lib/test/unit/types/temporalCodec.test.d.ts +2 -0
  158. package/lib/test/unit/types/temporalCodec.test.d.ts.map +1 -0
  159. package/lib/test/unit/types/temporalCodec.test.js +205 -0
  160. package/lib/test/unit/types/temporalCodec.test.js.map +1 -0
  161. package/lib/test/unit/types/temporalPolicy.test.d.ts +2 -0
  162. package/lib/test/unit/types/temporalPolicy.test.d.ts.map +1 -0
  163. package/lib/test/unit/types/temporalPolicy.test.js +64 -0
  164. package/lib/test/unit/types/temporalPolicy.test.js.map +1 -0
  165. package/package.json +7 -7
  166. package/rush-logs/ts-agent-memory.build.cache.log +1 -1
  167. package/rush-logs/ts-agent-memory.build.log +4 -4
  168. package/src/index.ts +2 -0
  169. package/src/packlets/ingest/cycleGuard.ts +142 -0
  170. package/src/packlets/ingest/hostStages.ts +111 -0
  171. package/src/packlets/ingest/index.ts +9 -0
  172. package/src/packlets/ingest/model.ts +184 -0
  173. package/src/packlets/ingest/orchestrator.ts +797 -0
  174. package/src/packlets/retrieve/index.ts +1 -0
  175. package/src/packlets/retrieve/temporalRetrievers.ts +210 -0
  176. package/src/packlets/store/fileTreeMemoryStore.ts +460 -66
  177. package/src/packlets/tools/index.ts +6 -0
  178. package/src/packlets/tools/memoryTools.ts +579 -0
  179. package/src/packlets/types/identityCodec.ts +184 -0
  180. package/src/packlets/types/index.ts +1 -0
  181. package/src/packlets/types/temporal.ts +96 -0
  182. package/src/packlets/types/writePolicy.ts +127 -0
  183. package/src/test/unit/converters/antagonistRoundTrip.test.ts +110 -0
  184. package/src/test/unit/ingest/antagonistCycleAndParity.test.ts +362 -0
  185. package/src/test/unit/ingest/cycleGuard.test.ts +68 -0
  186. package/src/test/unit/ingest/orchestrator.test.ts +1158 -0
  187. package/src/test/unit/retrieve/temporalRetrievers.test.ts +226 -0
  188. package/src/test/unit/store/antagonistTemporalBoundary.test.ts +158 -0
  189. package/src/test/unit/store/fileTreeMemoryStore.test.ts +98 -7
  190. package/src/test/unit/store/temporalStore.test.ts +469 -0
  191. package/src/test/unit/tools/memoryTools.test.ts +771 -0
  192. package/src/test/unit/types/temporalCodec.test.ts +259 -0
  193. package/src/test/unit/types/temporalPolicy.test.ts +96 -0
  194. package/temp/build/lint/_eslint-5eVG3S6w.json +85 -9
  195. package/temp/build/typescript/ts_8nwakTlr.json +1 -1
  196. package/temp/ts-agent-memory.api.json +11984 -6314
  197. package/temp/ts-agent-memory.api.md +284 -0
@@ -0,0 +1,88 @@
1
+ import { Result } from '@fgv/ts-utils';
2
+ import { MemoryId } from '../types';
3
+ import { ICandidateEdge, ICandidateRecord, IEntityResolutionCandidate, IIngestItem, IMemoryClassification, ResolutionVerdict } from './model';
4
+ /**
5
+ * Stage 2 — the host's classifier. Decides what {@link IIngestItem} maps to
6
+ * which memory {@link Kind} (and optional tags / confidence). LOCKED as a
7
+ * separate staged interface (OQ-10): the host plugs its existing classifier
8
+ * machinery in here rather than surrendering to an opaque ingestor.
9
+ * @public
10
+ */
11
+ export interface IMemoryClassifier {
12
+ /**
13
+ * Classify one item. A `fail` aborts the item's ingest loudly (fgv never
14
+ * guesses a kind).
15
+ */
16
+ classify(item: IIngestItem): Promise<Result<IMemoryClassification>>;
17
+ }
18
+ /**
19
+ * Stage 3 — the host's fact extractor. Turns a classified item into zero or more
20
+ * {@link ICandidateRecord}s. Each candidate's body is validated against the
21
+ * kind's registered Converter by fgv before it can reach the store (the typed
22
+ * validation boundary — no unchecked host data is persisted).
23
+ * @public
24
+ */
25
+ export interface IFactExtractor {
26
+ /**
27
+ * Extract candidate records from a classified item. An empty array is a valid
28
+ * result (the item yielded nothing memorable).
29
+ */
30
+ extract(item: IIngestItem, classification: IMemoryClassification): Promise<Result<ReadonlyArray<ICandidateRecord>>>;
31
+ }
32
+ /**
33
+ * Stage 4 (optional) — the host's entity resolver (OQ-13, LOCKED OPTIONAL). When
34
+ * supplied, fgv surfaces near-duplicate {@link IEntityResolutionCandidate}s (from
35
+ * layer-2 similarity search) and the resolver returns a
36
+ * {@link ResolutionVerdict}. When ABSENT, stage-4 dedup falls back to
37
+ * exact-`{ kind, body }`-hash only — the deterministic-identity host path.
38
+ * @public
39
+ */
40
+ export interface IEntityResolver {
41
+ /**
42
+ * Decide whether `candidate` is new, a duplicate of / supersedes / merges into
43
+ * one of the surfaced `similar` records. `similar` is non-empty and ordered by
44
+ * descending score when the resolver is invoked (fgv only calls it when
45
+ * layer-2 surfaces at least one over-threshold neighbor).
46
+ */
47
+ resolve(candidate: ICandidateRecord, similar: ReadonlyArray<IEntityResolutionCandidate>): Promise<Result<ResolutionVerdict>>;
48
+ }
49
+ /**
50
+ * The context fgv hands the host's relation extractor (stage 5): the source item
51
+ * plus the candidates fgv is about to write, each paired with its resolved
52
+ * reference id (the codec `idStem`). The extractor proposes attributed edges over
53
+ * these ids and existing store records.
54
+ * @public
55
+ */
56
+ export interface IRelationContext {
57
+ /** The item being ingested. */
58
+ readonly item: IIngestItem;
59
+ /** The candidates fgv is about to write, each with its resolved reference id. */
60
+ readonly candidates: ReadonlyArray<IRelationCandidate>;
61
+ }
62
+ /**
63
+ * A candidate paired with its resolved reference id, handed to the relation
64
+ * extractor so it can source edges from it.
65
+ * @public
66
+ */
67
+ export interface IRelationCandidate {
68
+ /** The candidate about to be written. */
69
+ readonly candidate: ICandidateRecord;
70
+ /** Its resolved reference id (codec `idStem` — the stable entity reference). */
71
+ readonly id: MemoryId;
72
+ }
73
+ /**
74
+ * Stage 5 — the host's relation extractor. Proposes attributed edges among the
75
+ * candidates and existing records. fgv owns the validation, the write-time cycle
76
+ * guard, and the actual persistence of the edges (the host brings only the
77
+ * relationship judgment).
78
+ * @public
79
+ */
80
+ export interface IRelationExtractor {
81
+ /**
82
+ * Propose the edges to attach for this ingest. An empty array is valid (no
83
+ * relations). Every proposed {@link ICandidateEdge.source | source} must be one
84
+ * of the context's candidate reference ids.
85
+ */
86
+ relate(context: IRelationContext): Promise<Result<ReadonlyArray<ICandidateEdge>>>;
87
+ }
88
+ //# sourceMappingURL=hostStages.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hostStages.d.ts","sourceRoot":"","sources":["../../../src/packlets/ingest/hostStages.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AACvC,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AACpC,OAAO,EACL,cAAc,EACd,gBAAgB,EAChB,0BAA0B,EAC1B,WAAW,EACX,qBAAqB,EACrB,iBAAiB,EAClB,MAAM,SAAS,CAAC;AAEjB;;;;;;GAMG;AACH,MAAM,WAAW,iBAAiB;IAChC;;;OAGG;IACH,QAAQ,CAAC,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,qBAAqB,CAAC,CAAC,CAAC;CACrE;AAED;;;;;;GAMG;AACH,MAAM,WAAW,cAAc;IAC7B;;;OAGG;IACH,OAAO,CACL,IAAI,EAAE,WAAW,EACjB,cAAc,EAAE,qBAAqB,GACpC,OAAO,CAAC,MAAM,CAAC,aAAa,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC;CACrD;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,eAAe;IAC9B;;;;;OAKG;IACH,OAAO,CACL,SAAS,EAAE,gBAAgB,EAC3B,OAAO,EAAE,aAAa,CAAC,0BAA0B,CAAC,GACjD,OAAO,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC,CAAC;CACvC;AAED;;;;;;GAMG;AACH,MAAM,WAAW,gBAAgB;IAC/B,+BAA+B;IAC/B,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAC3B,iFAAiF;IACjF,QAAQ,CAAC,UAAU,EAAE,aAAa,CAAC,kBAAkB,CAAC,CAAC;CACxD;AAED;;;;GAIG;AACH,MAAM,WAAW,kBAAkB;IACjC,yCAAyC;IACzC,QAAQ,CAAC,SAAS,EAAE,gBAAgB,CAAC;IACrC,gFAAgF;IAChF,QAAQ,CAAC,EAAE,EAAE,QAAQ,CAAC;CACvB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,kBAAkB;IACjC;;;;OAIG;IACH,MAAM,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,MAAM,CAAC,aAAa,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC;CACnF"}
@@ -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=hostStages.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hostStages.js","sourceRoot":"","sources":["../../../src/packlets/ingest/hostStages.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 { MemoryId } from '../types';\nimport {\n ICandidateEdge,\n ICandidateRecord,\n IEntityResolutionCandidate,\n IIngestItem,\n IMemoryClassification,\n ResolutionVerdict\n} from './model';\n\n/**\n * Stage 2 — the host's classifier. Decides what {@link IIngestItem} maps to\n * which memory {@link Kind} (and optional tags / confidence). LOCKED as a\n * separate staged interface (OQ-10): the host plugs its existing classifier\n * machinery in here rather than surrendering to an opaque ingestor.\n * @public\n */\nexport interface IMemoryClassifier {\n /**\n * Classify one item. A `fail` aborts the item's ingest loudly (fgv never\n * guesses a kind).\n */\n classify(item: IIngestItem): Promise<Result<IMemoryClassification>>;\n}\n\n/**\n * Stage 3 — the host's fact extractor. Turns a classified item into zero or more\n * {@link ICandidateRecord}s. Each candidate's body is validated against the\n * kind's registered Converter by fgv before it can reach the store (the typed\n * validation boundary — no unchecked host data is persisted).\n * @public\n */\nexport interface IFactExtractor {\n /**\n * Extract candidate records from a classified item. An empty array is a valid\n * result (the item yielded nothing memorable).\n */\n extract(\n item: IIngestItem,\n classification: IMemoryClassification\n ): Promise<Result<ReadonlyArray<ICandidateRecord>>>;\n}\n\n/**\n * Stage 4 (optional) — the host's entity resolver (OQ-13, LOCKED OPTIONAL). When\n * supplied, fgv surfaces near-duplicate {@link IEntityResolutionCandidate}s (from\n * layer-2 similarity search) and the resolver returns a\n * {@link ResolutionVerdict}. When ABSENT, stage-4 dedup falls back to\n * exact-`{ kind, body }`-hash only — the deterministic-identity host path.\n * @public\n */\nexport interface IEntityResolver {\n /**\n * Decide whether `candidate` is new, a duplicate of / supersedes / merges into\n * one of the surfaced `similar` records. `similar` is non-empty and ordered by\n * descending score when the resolver is invoked (fgv only calls it when\n * layer-2 surfaces at least one over-threshold neighbor).\n */\n resolve(\n candidate: ICandidateRecord,\n similar: ReadonlyArray<IEntityResolutionCandidate>\n ): Promise<Result<ResolutionVerdict>>;\n}\n\n/**\n * The context fgv hands the host's relation extractor (stage 5): the source item\n * plus the candidates fgv is about to write, each paired with its resolved\n * reference id (the codec `idStem`). The extractor proposes attributed edges over\n * these ids and existing store records.\n * @public\n */\nexport interface IRelationContext {\n /** The item being ingested. */\n readonly item: IIngestItem;\n /** The candidates fgv is about to write, each with its resolved reference id. */\n readonly candidates: ReadonlyArray<IRelationCandidate>;\n}\n\n/**\n * A candidate paired with its resolved reference id, handed to the relation\n * extractor so it can source edges from it.\n * @public\n */\nexport interface IRelationCandidate {\n /** The candidate about to be written. */\n readonly candidate: ICandidateRecord;\n /** Its resolved reference id (codec `idStem` — the stable entity reference). */\n readonly id: MemoryId;\n}\n\n/**\n * Stage 5 — the host's relation extractor. Proposes attributed edges among the\n * candidates and existing records. fgv owns the validation, the write-time cycle\n * guard, and the actual persistence of the edges (the host brings only the\n * relationship judgment).\n * @public\n */\nexport interface IRelationExtractor {\n /**\n * Propose the edges to attach for this ingest. An empty array is valid (no\n * relations). Every proposed {@link ICandidateEdge.source | source} must be one\n * of the context's candidate reference ids.\n */\n relate(context: IRelationContext): Promise<Result<ReadonlyArray<ICandidateEdge>>>;\n}\n"]}
@@ -0,0 +1,5 @@
1
+ export * from './model';
2
+ export * from './hostStages';
3
+ export * from './cycleGuard';
4
+ export * from './orchestrator';
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/packlets/ingest/index.ts"],"names":[],"mappings":"AAKA,cAAc,SAAS,CAAC;AACxB,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC;AAC7B,cAAc,gBAAgB,CAAC"}
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ /*
3
+ * Copyright (c) 2026 Erik Fortune
4
+ * SPDX-License-Identifier: MIT
5
+ */
6
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
7
+ if (k2 === undefined) k2 = k;
8
+ var desc = Object.getOwnPropertyDescriptor(m, k);
9
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
10
+ desc = { enumerable: true, get: function() { return m[k]; } };
11
+ }
12
+ Object.defineProperty(o, k2, desc);
13
+ }) : (function(o, m, k, k2) {
14
+ if (k2 === undefined) k2 = k;
15
+ o[k2] = m[k];
16
+ }));
17
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
18
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
19
+ };
20
+ Object.defineProperty(exports, "__esModule", { value: true });
21
+ __exportStar(require("./model"), exports);
22
+ __exportStar(require("./hostStages"), exports);
23
+ __exportStar(require("./cycleGuard"), exports);
24
+ __exportStar(require("./orchestrator"), exports);
25
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/packlets/ingest/index.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;;;;;;;;;;;;;;AAEH,0CAAwB;AACxB,+CAA6B;AAC7B,+CAA6B;AAC7B,iDAA+B","sourcesContent":["/*\n * Copyright (c) 2026 Erik Fortune\n * SPDX-License-Identifier: MIT\n */\n\nexport * from './model';\nexport * from './hostStages';\nexport * from './cycleGuard';\nexport * from './orchestrator';\n"]}
@@ -0,0 +1,177 @@
1
+ import { IEdge, IMemoryEnvelope, IMemoryRecord, Kind, MemoryId, Tag } from '../types';
2
+ /**
3
+ * A single unit of raw source material handed to the ingest pipeline. The host
4
+ * owns the shape of {@link IIngestItem.content | content} — fgv never interprets
5
+ * it; it flows opaquely into the host's classifier and extractor (stages 2-3).
6
+ *
7
+ * Single-item ingest is FIRST-CLASS: the orchestrator's primary entry point
8
+ * takes one `IIngestItem` (per-turn streaming), and the batch entry point is a
9
+ * convenience loop over it.
10
+ * @public
11
+ */
12
+ export interface IIngestItem {
13
+ /**
14
+ * Host-owned identity for this source item. Opaque to fgv; used only in
15
+ * diagnostics and echoed back on the {@link IIngestItemResult}.
16
+ */
17
+ readonly id: string;
18
+ /**
19
+ * The opaque source payload the host's classifier / extractor understand
20
+ * (e.g. a raw turn, a document, a tool-call transcript). Never interpreted by
21
+ * fgv.
22
+ */
23
+ readonly content: unknown;
24
+ /**
25
+ * Optional back-link to the memory record this item was derived from (e.g. the
26
+ * MTM turn an extracted fact came from). When present, fgv stamps it as
27
+ * {@link IProvenance.derivedFrom | provenance.derivedFrom} on every record
28
+ * ingested from this item (stage 6) — the cross-kind provenance spine.
29
+ */
30
+ readonly sourceId?: MemoryId;
31
+ /** Optional opaque metadata carried alongside the item; never interpreted by fgv. */
32
+ readonly metadata?: Record<string, unknown>;
33
+ }
34
+ /**
35
+ * The host classifier's verdict for an {@link IIngestItem} (stage 2). Guides the
36
+ * host's own extractor (stage 3) and supplies the default `kind` / `tags` /
37
+ * `confidence` fgv stamps when the extractor does not override them.
38
+ *
39
+ * Extensible: the `[key: string]: unknown` arm lets the host attach an opaque
40
+ * classification payload without changing this interface.
41
+ * @public
42
+ */
43
+ export interface IMemoryClassification {
44
+ /** The record kind the item classifies as. */
45
+ readonly kind: Kind;
46
+ /** Optional tags the classifier assigns. */
47
+ readonly tags?: ReadonlyArray<Tag>;
48
+ /** Optional classifier confidence in `[0, 1]`; flows to `provenance.confidence`. */
49
+ readonly confidence?: number;
50
+ /** Opaque, host-owned extension payload — never interpreted by fgv. */
51
+ readonly [key: string]: unknown;
52
+ }
53
+ /**
54
+ * The store-owned envelope fields fgv derives or stamps: `id` (from the codec),
55
+ * and the transaction-time metadata (`seq` / `contentHash` / `created` /
56
+ * `updated`). A {@link ICandidateRecord} supplies everything EXCEPT these.
57
+ * @public
58
+ */
59
+ export type StoreStampedEnvelopeField = 'id' | 'seq' | 'contentHash' | 'created' | 'updated';
60
+ /**
61
+ * A host-extracted candidate record (stage 3 output). The host supplies the
62
+ * full envelope MINUS the {@link StoreStampedEnvelopeField | store-stamped
63
+ * fields} (fgv derives `id` from the codec; the store stamps the rest) plus the
64
+ * typed body. Every candidate body is validated against the kind's registered
65
+ * Converter before it can reach the store (the typed validation boundary).
66
+ * @public
67
+ */
68
+ export interface ICandidateRecord {
69
+ /** The host-supplied envelope, minus the store-stamped fields. */
70
+ readonly envelope: Omit<IMemoryEnvelope, StoreStampedEnvelopeField>;
71
+ /** The per-kind body (a markdown string in v1), validated on ingest. */
72
+ readonly body: unknown;
73
+ }
74
+ /**
75
+ * A near-duplicate candidate surfaced to the {@link IEntityResolver} by stage-4
76
+ * layer-2 similarity search: an existing record whose embedding is within the
77
+ * similarity threshold of the incoming candidate.
78
+ * @public
79
+ */
80
+ export interface IEntityResolutionCandidate {
81
+ /** The existing record's id. */
82
+ readonly id: MemoryId;
83
+ /** The existing record. */
84
+ readonly record: IMemoryRecord<unknown>;
85
+ /** The backend similarity score (higher = more similar). */
86
+ readonly score: number;
87
+ }
88
+ /**
89
+ * The four dedup verdicts a {@link IEntityResolver} (or fgv's exact-match layer)
90
+ * returns for a candidate. See the design note §3 for the verdict → write
91
+ * disposition mapping.
92
+ * @public
93
+ */
94
+ export type ResolutionVerdict = {
95
+ readonly verdict: 'new';
96
+ } | {
97
+ readonly verdict: 'duplicate-of';
98
+ readonly target: MemoryId;
99
+ } | {
100
+ readonly verdict: 'supersede';
101
+ readonly target: MemoryId;
102
+ } | {
103
+ readonly verdict: 'merge-into';
104
+ readonly target: MemoryId;
105
+ };
106
+ /**
107
+ * How a candidate was ultimately written (or not) after resolution.
108
+ *
109
+ * - `written` — persisted as a fresh record (verdict `new`), or as a superseding
110
+ * record (verdict `supersede`).
111
+ * - `deduped` — not written; an existing record satisfied it (verdict
112
+ * `duplicate-of`, incl. every layer-1 exact `{ kind, body }` match).
113
+ * - `merged` — merged into an existing target entity (verdict `merge-into`).
114
+ * @public
115
+ */
116
+ export type IngestDisposition = 'written' | 'deduped' | 'merged';
117
+ /**
118
+ * A stage-5 attributed edge proposal: the {@link ICandidateEdge.edge | edge} to
119
+ * add, sourced from {@link ICandidateEdge.source | source}. The source MUST be a
120
+ * candidate being written in this ingest (edges land on the source record's
121
+ * `envelope.links`); the edge's `target` must resolve to a sibling candidate or
122
+ * an existing store record.
123
+ * @public
124
+ */
125
+ export interface ICandidateEdge {
126
+ /** The reference id (codec `idStem`) of the candidate the edge originates from. */
127
+ readonly source: MemoryId;
128
+ /** The attributed edge (type / target / optional confidence / provenance). */
129
+ readonly edge: IEdge;
130
+ }
131
+ /**
132
+ * Per-candidate outcome of an ingest run.
133
+ * @public
134
+ */
135
+ export interface IIngestedRecordResult {
136
+ /** The candidate the outcome is for. */
137
+ readonly candidate: ICandidateRecord;
138
+ /** The resolution verdict fgv reached (or the resolver returned). */
139
+ readonly resolution: ResolutionVerdict;
140
+ /** What the write ultimately did. */
141
+ readonly disposition: IngestDisposition;
142
+ /**
143
+ * The stored record's id: the newly-written id (`written` / `merged`), or the
144
+ * existing target's id (`deduped`).
145
+ */
146
+ readonly id: MemoryId;
147
+ /** The persisted record, when a write happened (`written` / `merged`). */
148
+ readonly record?: IMemoryRecord<unknown>;
149
+ /** The stage-5 edges attached to this candidate before the write. */
150
+ readonly edges: ReadonlyArray<ICandidateEdge>;
151
+ /**
152
+ * Informational diagnostic, set to `'temporal-versioned'` when the
153
+ * contradicts→temporal interlock is recognized: a `contradicts` edge was
154
+ * attached to a candidate of a temporal kind.
155
+ *
156
+ * @remarks
157
+ * A temporal kind ALWAYS writes through the store's versioned put path (that is
158
+ * the codec's `isVersioned` behavior — the prior version is invalidated and a
159
+ * new version written on every write, contradicts edge or not). This flag does
160
+ * NOT cause that routing; it is a diagnostic marker that the contradicts-driven
161
+ * scenario occurred, so callers can distinguish a contradiction-superseding
162
+ * version from an ordinary revision.
163
+ */
164
+ readonly interlock?: 'temporal-versioned';
165
+ }
166
+ /**
167
+ * The result of ingesting a single {@link IIngestItem}: the item plus the
168
+ * per-candidate outcomes (one item can yield zero or many candidate records).
169
+ * @public
170
+ */
171
+ export interface IIngestItemResult {
172
+ /** The item that was ingested. */
173
+ readonly item: IIngestItem;
174
+ /** The per-candidate outcomes, in extraction order. */
175
+ readonly records: ReadonlyArray<IIngestedRecordResult>;
176
+ }
177
+ //# sourceMappingURL=model.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../../../src/packlets/ingest/model.ts"],"names":[],"mappings":"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"}
@@ -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=model.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model.js","sourceRoot":"","sources":["../../../src/packlets/ingest/model.ts"],"names":[],"mappings":";AAAA;;;GAGG","sourcesContent":["/*\n * Copyright (c) 2026 Erik Fortune\n * SPDX-License-Identifier: MIT\n */\n\nimport { IEdge, IMemoryEnvelope, IMemoryRecord, Kind, MemoryId, Tag } from '../types';\n\n/**\n * A single unit of raw source material handed to the ingest pipeline. The host\n * owns the shape of {@link IIngestItem.content | content} — fgv never interprets\n * it; it flows opaquely into the host's classifier and extractor (stages 2-3).\n *\n * Single-item ingest is FIRST-CLASS: the orchestrator's primary entry point\n * takes one `IIngestItem` (per-turn streaming), and the batch entry point is a\n * convenience loop over it.\n * @public\n */\nexport interface IIngestItem {\n /**\n * Host-owned identity for this source item. Opaque to fgv; used only in\n * diagnostics and echoed back on the {@link IIngestItemResult}.\n */\n readonly id: string;\n /**\n * The opaque source payload the host's classifier / extractor understand\n * (e.g. a raw turn, a document, a tool-call transcript). Never interpreted by\n * fgv.\n */\n readonly content: unknown;\n /**\n * Optional back-link to the memory record this item was derived from (e.g. the\n * MTM turn an extracted fact came from). When present, fgv stamps it as\n * {@link IProvenance.derivedFrom | provenance.derivedFrom} on every record\n * ingested from this item (stage 6) — the cross-kind provenance spine.\n */\n readonly sourceId?: MemoryId;\n /** Optional opaque metadata carried alongside the item; never interpreted by fgv. */\n readonly metadata?: Record<string, unknown>;\n}\n\n/**\n * The host classifier's verdict for an {@link IIngestItem} (stage 2). Guides the\n * host's own extractor (stage 3) and supplies the default `kind` / `tags` /\n * `confidence` fgv stamps when the extractor does not override them.\n *\n * Extensible: the `[key: string]: unknown` arm lets the host attach an opaque\n * classification payload without changing this interface.\n * @public\n */\nexport interface IMemoryClassification {\n /** The record kind the item classifies as. */\n readonly kind: Kind;\n /** Optional tags the classifier assigns. */\n readonly tags?: ReadonlyArray<Tag>;\n /** Optional classifier confidence in `[0, 1]`; flows to `provenance.confidence`. */\n readonly confidence?: number;\n /** Opaque, host-owned extension payload — never interpreted by fgv. */\n readonly [key: string]: unknown;\n}\n\n/**\n * The store-owned envelope fields fgv derives or stamps: `id` (from the codec),\n * and the transaction-time metadata (`seq` / `contentHash` / `created` /\n * `updated`). A {@link ICandidateRecord} supplies everything EXCEPT these.\n * @public\n */\nexport type StoreStampedEnvelopeField = 'id' | 'seq' | 'contentHash' | 'created' | 'updated';\n\n/**\n * A host-extracted candidate record (stage 3 output). The host supplies the\n * full envelope MINUS the {@link StoreStampedEnvelopeField | store-stamped\n * fields} (fgv derives `id` from the codec; the store stamps the rest) plus the\n * typed body. Every candidate body is validated against the kind's registered\n * Converter before it can reach the store (the typed validation boundary).\n * @public\n */\nexport interface ICandidateRecord {\n /** The host-supplied envelope, minus the store-stamped fields. */\n readonly envelope: Omit<IMemoryEnvelope, StoreStampedEnvelopeField>;\n /** The per-kind body (a markdown string in v1), validated on ingest. */\n readonly body: unknown;\n}\n\n/**\n * A near-duplicate candidate surfaced to the {@link IEntityResolver} by stage-4\n * layer-2 similarity search: an existing record whose embedding is within the\n * similarity threshold of the incoming candidate.\n * @public\n */\nexport interface IEntityResolutionCandidate {\n /** The existing record's id. */\n readonly id: MemoryId;\n /** The existing record. */\n readonly record: IMemoryRecord<unknown>;\n /** The backend similarity score (higher = more similar). */\n readonly score: number;\n}\n\n/**\n * The four dedup verdicts a {@link IEntityResolver} (or fgv's exact-match layer)\n * returns for a candidate. See the design note §3 for the verdict → write\n * disposition mapping.\n * @public\n */\nexport type ResolutionVerdict =\n | { readonly verdict: 'new' }\n | { readonly verdict: 'duplicate-of'; readonly target: MemoryId }\n | { readonly verdict: 'supersede'; readonly target: MemoryId }\n | { readonly verdict: 'merge-into'; readonly target: MemoryId };\n\n/**\n * How a candidate was ultimately written (or not) after resolution.\n *\n * - `written` — persisted as a fresh record (verdict `new`), or as a superseding\n * record (verdict `supersede`).\n * - `deduped` — not written; an existing record satisfied it (verdict\n * `duplicate-of`, incl. every layer-1 exact `{ kind, body }` match).\n * - `merged` — merged into an existing target entity (verdict `merge-into`).\n * @public\n */\nexport type IngestDisposition = 'written' | 'deduped' | 'merged';\n\n/**\n * A stage-5 attributed edge proposal: the {@link ICandidateEdge.edge | edge} to\n * add, sourced from {@link ICandidateEdge.source | source}. The source MUST be a\n * candidate being written in this ingest (edges land on the source record's\n * `envelope.links`); the edge's `target` must resolve to a sibling candidate or\n * an existing store record.\n * @public\n */\nexport interface ICandidateEdge {\n /** The reference id (codec `idStem`) of the candidate the edge originates from. */\n readonly source: MemoryId;\n /** The attributed edge (type / target / optional confidence / provenance). */\n readonly edge: IEdge;\n}\n\n/**\n * Per-candidate outcome of an ingest run.\n * @public\n */\nexport interface IIngestedRecordResult {\n /** The candidate the outcome is for. */\n readonly candidate: ICandidateRecord;\n /** The resolution verdict fgv reached (or the resolver returned). */\n readonly resolution: ResolutionVerdict;\n /** What the write ultimately did. */\n readonly disposition: IngestDisposition;\n /**\n * The stored record's id: the newly-written id (`written` / `merged`), or the\n * existing target's id (`deduped`).\n */\n readonly id: MemoryId;\n /** The persisted record, when a write happened (`written` / `merged`). */\n readonly record?: IMemoryRecord<unknown>;\n /** The stage-5 edges attached to this candidate before the write. */\n readonly edges: ReadonlyArray<ICandidateEdge>;\n /**\n * Informational diagnostic, set to `'temporal-versioned'` when the\n * contradicts→temporal interlock is recognized: a `contradicts` edge was\n * attached to a candidate of a temporal kind.\n *\n * @remarks\n * A temporal kind ALWAYS writes through the store's versioned put path (that is\n * the codec's `isVersioned` behavior — the prior version is invalidated and a\n * new version written on every write, contradicts edge or not). This flag does\n * NOT cause that routing; it is a diagnostic marker that the contradicts-driven\n * scenario occurred, so callers can distinguish a contradiction-superseding\n * version from an ordinary revision.\n */\n readonly interlock?: 'temporal-versioned';\n}\n\n/**\n * The result of ingesting a single {@link IIngestItem}: the item plus the\n * per-candidate outcomes (one item can yield zero or many candidate records).\n * @public\n */\nexport interface IIngestItemResult {\n /** The item that was ingested. */\n readonly item: IIngestItem;\n /** The per-candidate outcomes, in extraction order. */\n readonly records: ReadonlyArray<IIngestedRecordResult>;\n}\n"]}
@@ -0,0 +1,206 @@
1
+ import { Logging, Result } from '@fgv/ts-utils';
2
+ import { IIdentityCodec, Kind, LinkType } from '../types';
3
+ import { IBodyConverterRegistry } from '../converters';
4
+ import { IMemoryStore } from '../store';
5
+ import { IVectorIndex, MemoryEmbedder } from '../vector';
6
+ import { IEntityResolver, IFactExtractor, IMemoryClassifier, IRelationExtractor } from './hostStages';
7
+ import { IIngestItem, IIngestItemResult } from './model';
8
+ /**
9
+ * The provenance source stamped on every record the ingest pipeline writes.
10
+ * @public
11
+ */
12
+ export declare const HOST_INGEST_PROVENANCE_SOURCE: string;
13
+ /**
14
+ * The link type whose presence on a temporal-kind candidate fires the
15
+ * contradicts→temporal-versioned interlock.
16
+ * @public
17
+ */
18
+ export declare const CONTRADICTS_LINK_TYPE: LinkType;
19
+ /**
20
+ * The default stage-4 layer-2 cosine similarity threshold (design note §2). A
21
+ * near-duplicate candidate is surfaced to the {@link IEntityResolver} only when
22
+ * its nearest neighbor scores `>= 0.85`.
23
+ * @public
24
+ */
25
+ export declare const DEFAULT_SIMILARITY_THRESHOLD: number;
26
+ /**
27
+ * The default top-K for stage-4 layer-2 similarity candidate generation.
28
+ * @public
29
+ */
30
+ export declare const DEFAULT_SIMILARITY_TOP_K: number;
31
+ /**
32
+ * How the write-time cycle guard behaves: `'reject'` (default — a cycle-inducing
33
+ * edge fails the ingest) or `'off'` (no acyclicity constraint, for deployments
34
+ * whose link graphs are legitimately cyclic — e.g. mutual associative links).
35
+ * @public
36
+ */
37
+ export type CycleGuardMode = 'reject' | 'off';
38
+ /**
39
+ * The fgv-owned six-stage ingest orchestrator. Composes the host's staged
40
+ * classify / extract / (optional) resolve / relate machinery around fgv's owned
41
+ * validation boundary, dedup, edge + cycle safety, provenance stamping, and the
42
+ * contradicts→temporal interlock.
43
+ * @public
44
+ */
45
+ export interface IMemoryIngestOrchestrator {
46
+ /**
47
+ * Ingest a SINGLE item end-to-end (the first-class per-turn streaming path).
48
+ */
49
+ ingestItem(item: IIngestItem): Promise<Result<IIngestItemResult>>;
50
+ /**
51
+ * Ingest a batch of items. A convenience loop over {@link
52
+ * IMemoryIngestOrchestrator.ingestItem | ingestItem} — items are processed in
53
+ * order and the first failure aborts the batch.
54
+ */
55
+ ingestBatch(items: ReadonlyArray<IIngestItem>): Promise<Result<ReadonlyArray<IIngestItemResult>>>;
56
+ }
57
+ /**
58
+ * Parameters for {@link MemoryIngestOrchestrator.create}.
59
+ * @public
60
+ */
61
+ export interface IMemoryIngestOrchestratorCreateParams {
62
+ /** The store every write bottoms out in (stage 6). */
63
+ readonly store: IMemoryStore;
64
+ /** Per-kind body converter registry — the stage-3 typed validation boundary. */
65
+ readonly registry: IBodyConverterRegistry;
66
+ /** Per-kind identity codecs (maps a candidate `entityId` to its storage address). */
67
+ readonly codecs?: ReadonlyMap<Kind, IIdentityCodec>;
68
+ /** Default identity codec for kinds without an explicit entry. */
69
+ readonly defaultCodec?: IIdentityCodec;
70
+ /** Stage 2 — the host's classifier. */
71
+ readonly classifier: IMemoryClassifier;
72
+ /** Stage 3 — the host's fact extractor. */
73
+ readonly extractor: IFactExtractor;
74
+ /** Stage 5 — the host's relation extractor. */
75
+ readonly relationExtractor: IRelationExtractor;
76
+ /**
77
+ * Stage 4 (optional, OQ-13) — the host's entity resolver. Absent → stage-4
78
+ * dedup is exact-`{ kind, body }`-hash only (the deterministic-identity path).
79
+ */
80
+ readonly entityResolver?: IEntityResolver;
81
+ /**
82
+ * Optional vector index for stage-4 layer-2 similarity candidate-gen. Wired
83
+ * together with {@link IMemoryIngestOrchestratorCreateParams.embed | embed} AND
84
+ * {@link IMemoryIngestOrchestratorCreateParams.entityResolver | entityResolver};
85
+ * absent (or either co-requisite absent) → layer-2 is skipped and dedup is
86
+ * exact-only.
87
+ */
88
+ readonly vectorIndex?: IVectorIndex;
89
+ /** Optional embedder used to embed a candidate for layer-2 similarity search. */
90
+ readonly embed?: MemoryEmbedder;
91
+ /**
92
+ * Stage-4 layer-2 cosine threshold. Defaults to {@link
93
+ * DEFAULT_SIMILARITY_THRESHOLD} (`0.85`).
94
+ */
95
+ readonly similarityThreshold?: number;
96
+ /**
97
+ * Stage-4 layer-2 top-K. Defaults to {@link DEFAULT_SIMILARITY_TOP_K} (`5`).
98
+ */
99
+ readonly similarityTopK?: number;
100
+ /** Write-time cycle guard mode. Defaults to `'reject'`. */
101
+ readonly cycleGuard?: CycleGuardMode;
102
+ /** Diagnostic logger (defaults to a no-op). */
103
+ readonly logger?: Logging.ILogger;
104
+ }
105
+ /**
106
+ * Default {@link IMemoryIngestOrchestrator}.
107
+ * @public
108
+ */
109
+ export declare class MemoryIngestOrchestrator implements IMemoryIngestOrchestrator {
110
+ private readonly _store;
111
+ private readonly _registry;
112
+ private readonly _codecs;
113
+ private readonly _defaultCodec;
114
+ private readonly _classifier;
115
+ private readonly _extractor;
116
+ private readonly _relationExtractor;
117
+ private readonly _similarity;
118
+ private readonly _similarityThreshold;
119
+ private readonly _similarityTopK;
120
+ private readonly _cycleGuard;
121
+ private readonly _logger;
122
+ private readonly _hasher;
123
+ private constructor();
124
+ /** Family-convention factory. */
125
+ static create(params: IMemoryIngestOrchestratorCreateParams): Result<MemoryIngestOrchestrator>;
126
+ /** {@inheritDoc IMemoryIngestOrchestrator.ingestItem} */
127
+ ingestItem(item: IIngestItem): Promise<Result<IIngestItemResult>>;
128
+ /** {@inheritDoc IMemoryIngestOrchestrator.ingestBatch} */
129
+ ingestBatch(items: ReadonlyArray<IIngestItem>): Promise<Result<ReadonlyArray<IIngestItemResult>>>;
130
+ /** Stage 2 — classify (host), normalizing a rejected promise into a Failure. */
131
+ private _classify;
132
+ /** Stage 3 — extract (host), normalizing a rejected promise into a Failure. */
133
+ private _extract;
134
+ /**
135
+ * Stages 3b-6 over the extracted candidates: validate bodies, resolve/dedup
136
+ * (stage 4), relate + cycle guard (stage 5), and load-with-provenance (stage 6).
137
+ */
138
+ private _processCandidates;
139
+ /** Stage 3b + 4 for one candidate: validate body, resolve address, resolve verdict. */
140
+ private _planCandidate;
141
+ /**
142
+ * Turn a resolved verdict into a candidate plan. A `new` verdict writes under the
143
+ * candidate's own address. Every TARGET-bearing verdict
144
+ * (`duplicate-of` / `supersede` / `merge-into`) is validated uniformly: the
145
+ * target must be a real store record (fgv owns validation — a non-compliant host
146
+ * resolver never smuggles a bogus id through) AND its kind must equal the
147
+ * candidate's kind (a cross-kind target would write to the wrong scope). Only
148
+ * `merge-into` re-addresses the write to the target's entity.
149
+ */
150
+ private _planFromVerdict;
151
+ /**
152
+ * Stage 4 — resolve a dedup verdict. Layer 1: an exact `{ kind, body }` match in
153
+ * the candidate's scope is a `duplicate-of` (design note §1). Layer 2 (only when
154
+ * a resolver + vector index + embedder are all wired): embed the candidate,
155
+ * surface over-threshold neighbors, and dispatch to the {@link IEntityResolver}.
156
+ * Otherwise the verdict is `new` (the exact-only fall-back path).
157
+ */
158
+ private _resolveVerdict;
159
+ /** Layer-2 similarity candidate-gen + resolver dispatch. */
160
+ private _resolveViaSimilarity;
161
+ /** Layer-2 continuation once the candidate has a provisional record to embed. */
162
+ private _resolveViaSimilarityEmbedded;
163
+ /**
164
+ * Find an existing record in `scope` whose `{ kind, body }` hash matches the
165
+ * candidate's (layer-1 exact dedup). Invalidated temporal versions are excluded
166
+ * — only a live (non-temporal or current) record deduplicates a candidate.
167
+ */
168
+ private _findExactMatch;
169
+ /**
170
+ * The body of a persisted record, required to be a string (the store persists
171
+ * only string bodies). Fails loudly rather than blind-casting an `unknown` body
172
+ * into the exact-dedup hash — a non-string existing body is a store-integrity
173
+ * fault, surfaced with context, not a silent miscompute.
174
+ */
175
+ private static _recordBodyString;
176
+ /** The stage-4 exact-dedup key over `{ kind, body }` (design note §1). */
177
+ private _exactKey;
178
+ /** Stage 5 — relate (host), validate edges, and run the write-time cycle guard. */
179
+ private _relate;
180
+ /**
181
+ * Validate stage-5 edges: each `source` must be a candidate being written; each
182
+ * `target` must resolve to a sibling candidate or an existing store record.
183
+ */
184
+ private _validateEdges;
185
+ /** Stage 6 — stamp provenance + edges, admit through the store, record the outcome. */
186
+ private _loadCandidate;
187
+ /** Build the fully-stamped record to persist (provenance + edges + placeholder txn fields). */
188
+ private _buildRecord;
189
+ /** Union two tag lists, de-duplicated, preserving first-occurrence order. */
190
+ private static _unionTags;
191
+ /** De-duplicate a link list by canonical edge hash, preserving first-occurrence order. */
192
+ private _dedupEdges;
193
+ /** Resolve a `(kind, entityId)` to its storage address via the registered codec. */
194
+ private _resolveAddress;
195
+ /** Run a host hook, normalizing a thrown/rejected hook into a Failure (never throws across the seam). */
196
+ private _capture;
197
+ /** Index a record snapshot by id (last write wins on an id collision across scopes). */
198
+ private static _indexById;
199
+ /** Every existing outbound edge in the snapshot, as cycle-guard edges. */
200
+ private static _existingEdges;
201
+ /** A provisional record for embedding a candidate (placeholder txn-time fields). */
202
+ private static _provisionalRecord;
203
+ /** Require a candidate body to be a string (the store persists only string bodies). */
204
+ private static _asStringBody;
205
+ }
206
+ //# sourceMappingURL=orchestrator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"orchestrator.d.ts","sourceRoot":"","sources":["../../../src/packlets/ingest/orchestrator.ts"],"names":[],"mappings":"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"}