@graphorin/memory 0.6.1 → 0.7.0

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 (227) hide show
  1. package/CHANGELOG.md +71 -0
  2. package/README.md +1 -1
  3. package/dist/conflict/index.js +0 -1
  4. package/dist/conflict/pipeline.js +0 -1
  5. package/dist/conflict/pipeline.js.map +1 -1
  6. package/dist/conflict/stages/stage3-heuristic-regex.js +0 -1
  7. package/dist/conflict/stages/stage3-heuristic-regex.js.map +1 -1
  8. package/dist/conflict/types.d.ts +1 -1
  9. package/dist/conflict/types.js.map +1 -1
  10. package/dist/consolidator/index.js +2 -0
  11. package/dist/consolidator/index.js.map +1 -1
  12. package/dist/consolidator/lock.js +7 -1
  13. package/dist/consolidator/lock.js.map +1 -1
  14. package/dist/consolidator/phases/deep.js +19 -12
  15. package/dist/consolidator/phases/deep.js.map +1 -1
  16. package/dist/consolidator/phases/induce.d.ts.map +1 -1
  17. package/dist/consolidator/phases/induce.js +2 -3
  18. package/dist/consolidator/phases/induce.js.map +1 -1
  19. package/dist/consolidator/phases/reflect.js +35 -8
  20. package/dist/consolidator/phases/reflect.js.map +1 -1
  21. package/dist/consolidator/phases/standard.js +199 -28
  22. package/dist/consolidator/phases/standard.js.map +1 -1
  23. package/dist/consolidator/reconcile.js +16 -15
  24. package/dist/consolidator/reconcile.js.map +1 -1
  25. package/dist/consolidator/runtime.d.ts.map +1 -1
  26. package/dist/consolidator/runtime.js +129 -47
  27. package/dist/consolidator/runtime.js.map +1 -1
  28. package/dist/consolidator/scheduler.d.ts +17 -3
  29. package/dist/consolidator/scheduler.d.ts.map +1 -1
  30. package/dist/consolidator/scheduler.js.map +1 -1
  31. package/dist/consolidator/types.d.ts +30 -1
  32. package/dist/consolidator/types.d.ts.map +1 -1
  33. package/dist/consolidator/types.js +10 -0
  34. package/dist/consolidator/types.js.map +1 -1
  35. package/dist/context-engine/compaction/clear-tool-results.d.ts +1 -1
  36. package/dist/context-engine/compaction/clear-tool-results.js +1 -1
  37. package/dist/context-engine/compaction/clear-tool-results.js.map +1 -1
  38. package/dist/context-engine/compaction/compactor.d.ts +1 -0
  39. package/dist/context-engine/compaction/compactor.d.ts.map +1 -1
  40. package/dist/context-engine/compaction/compactor.js +32 -8
  41. package/dist/context-engine/compaction/compactor.js.map +1 -1
  42. package/dist/context-engine/compaction/hooks/types.d.ts +1 -1
  43. package/dist/context-engine/compaction/index.d.ts +1 -0
  44. package/dist/context-engine/compaction/templates/marker.d.ts +33 -0
  45. package/dist/context-engine/compaction/templates/marker.d.ts.map +1 -0
  46. package/dist/context-engine/compaction/templates/marker.js +34 -0
  47. package/dist/context-engine/compaction/templates/marker.js.map +1 -0
  48. package/dist/context-engine/compaction/templates/summary-9-section.d.ts +1 -1
  49. package/dist/context-engine/compaction/templates/summary-9-section.d.ts.map +1 -1
  50. package/dist/context-engine/compaction/templates/summary-9-section.js +4 -3
  51. package/dist/context-engine/compaction/templates/summary-9-section.js.map +1 -1
  52. package/dist/context-engine/engine.d.ts +7 -176
  53. package/dist/context-engine/engine.d.ts.map +1 -1
  54. package/dist/context-engine/engine.js +0 -2
  55. package/dist/context-engine/engine.js.map +1 -1
  56. package/dist/context-engine/index.d.ts +8 -49
  57. package/dist/context-engine/io-types.d.ts +144 -0
  58. package/dist/context-engine/io-types.d.ts.map +1 -0
  59. package/dist/context-engine/locale-packs/types.d.ts +1 -1
  60. package/dist/context-engine/locale-packs/types.js.map +1 -1
  61. package/dist/context-engine/privacy-filter.d.ts +1 -2
  62. package/dist/context-engine/privacy-filter.d.ts.map +1 -1
  63. package/dist/context-engine/privacy-filter.js +1 -2
  64. package/dist/context-engine/privacy-filter.js.map +1 -1
  65. package/dist/errors/index.d.ts +2 -2
  66. package/dist/errors/index.js +2 -2
  67. package/dist/errors/index.js.map +1 -1
  68. package/dist/facade.d.ts +43 -52
  69. package/dist/facade.d.ts.map +1 -1
  70. package/dist/facade.js +5 -3
  71. package/dist/facade.js.map +1 -1
  72. package/dist/graph/entity-resolver.js +1 -1
  73. package/dist/graph/entity-resolver.js.map +1 -1
  74. package/dist/index.d.ts +16 -13
  75. package/dist/index.d.ts.map +1 -1
  76. package/dist/index.js +2 -5
  77. package/dist/index.js.map +1 -1
  78. package/dist/internal/envelope.js +57 -0
  79. package/dist/internal/envelope.js.map +1 -0
  80. package/dist/internal/injection-heuristics.js +0 -0
  81. package/dist/internal/injection-heuristics.js.map +1 -1
  82. package/dist/internal/llm-json.js +40 -0
  83. package/dist/internal/llm-json.js.map +1 -0
  84. package/dist/internal/storage-adapter.d.ts +23 -10
  85. package/dist/internal/storage-adapter.d.ts.map +1 -1
  86. package/dist/memory-interface.d.ts +131 -0
  87. package/dist/memory-interface.d.ts.map +1 -0
  88. package/dist/package.js +1 -1
  89. package/dist/package.js.map +1 -1
  90. package/dist/search/iterative.d.ts.map +1 -1
  91. package/dist/search/iterative.js +2 -3
  92. package/dist/search/iterative.js.map +1 -1
  93. package/dist/search/query-transform.d.ts.map +1 -1
  94. package/dist/search/query-transform.js +2 -3
  95. package/dist/search/query-transform.js.map +1 -1
  96. package/dist/tiers/episodic-memory.js +3 -3
  97. package/dist/tiers/episodic-memory.js.map +1 -1
  98. package/dist/tiers/index.d.ts +2 -2
  99. package/dist/tiers/insight-memory.js +1 -1
  100. package/dist/tiers/insight-memory.js.map +1 -1
  101. package/dist/tiers/procedural-memory.d.ts +1 -1
  102. package/dist/tiers/procedural-memory.js +2 -2
  103. package/dist/tiers/procedural-memory.js.map +1 -1
  104. package/dist/tiers/semantic-memory.d.ts +58 -4
  105. package/dist/tiers/semantic-memory.d.ts.map +1 -1
  106. package/dist/tiers/semantic-memory.js +103 -20
  107. package/dist/tiers/semantic-memory.js.map +1 -1
  108. package/dist/tools/block-tools.d.ts +19 -57
  109. package/dist/tools/block-tools.d.ts.map +1 -1
  110. package/dist/tools/block-tools.js.map +1 -1
  111. package/dist/tools/fact-tools.d.ts +53 -214
  112. package/dist/tools/fact-tools.d.ts.map +1 -1
  113. package/dist/tools/fact-tools.js +3 -2
  114. package/dist/tools/fact-tools.js.map +1 -1
  115. package/dist/tools/recall-tools.d.ts +34 -175
  116. package/dist/tools/recall-tools.d.ts.map +1 -1
  117. package/dist/tools/recall-tools.js +5 -4
  118. package/dist/tools/recall-tools.js.map +1 -1
  119. package/dist/tools/runbook-tools.d.ts +15 -58
  120. package/dist/tools/runbook-tools.d.ts.map +1 -1
  121. package/dist/tools/runbook-tools.js.map +1 -1
  122. package/dist/tools/types.d.ts +1 -1
  123. package/package.json +18 -17
  124. package/src/conflict/index.ts +29 -0
  125. package/src/conflict/locale-packs/en.ts +142 -0
  126. package/src/conflict/locale-packs/index.ts +17 -0
  127. package/src/conflict/locale-packs/types.ts +138 -0
  128. package/src/conflict/pipeline.ts +371 -0
  129. package/src/conflict/stages/helpers.ts +65 -0
  130. package/src/conflict/stages/stage1-exact-dedup.ts +40 -0
  131. package/src/conflict/stages/stage2-embedding-three-zone.ts +54 -0
  132. package/src/conflict/stages/stage3-heuristic-regex.ts +51 -0
  133. package/src/conflict/stages/stage4-subject-predicate.ts +46 -0
  134. package/src/conflict/stages/stage5-defer-to-deep.ts +34 -0
  135. package/src/conflict/types.ts +263 -0
  136. package/src/consolidator/budget.ts +312 -0
  137. package/src/consolidator/decay.ts +246 -0
  138. package/src/consolidator/dlq.ts +61 -0
  139. package/src/consolidator/errors.ts +87 -0
  140. package/src/consolidator/idempotency.ts +27 -0
  141. package/src/consolidator/index.ts +269 -0
  142. package/src/consolidator/lock.ts +141 -0
  143. package/src/consolidator/noise-filter.ts +235 -0
  144. package/src/consolidator/phases/deep.ts +308 -0
  145. package/src/consolidator/phases/induce.ts +423 -0
  146. package/src/consolidator/phases/learned-context.ts +233 -0
  147. package/src/consolidator/phases/light.ts +166 -0
  148. package/src/consolidator/phases/reflect.ts +504 -0
  149. package/src/consolidator/phases/standard.ts +1002 -0
  150. package/src/consolidator/reconcile.ts +273 -0
  151. package/src/consolidator/runtime.ts +1049 -0
  152. package/src/consolidator/scheduler.ts +182 -0
  153. package/src/consolidator/triggers.ts +134 -0
  154. package/src/consolidator/types.ts +622 -0
  155. package/src/context-engine/annotations.ts +161 -0
  156. package/src/context-engine/auto-recall.ts +92 -0
  157. package/src/context-engine/compaction/clear-tool-results.ts +232 -0
  158. package/src/context-engine/compaction/compactor.ts +403 -0
  159. package/src/context-engine/compaction/hooks/reanchor-persona-block.ts +55 -0
  160. package/src/context-engine/compaction/hooks/reanchor-pinned-facts.ts +66 -0
  161. package/src/context-engine/compaction/hooks/reanchor-project-rules.ts +57 -0
  162. package/src/context-engine/compaction/hooks/reanchor-recent-results.ts +116 -0
  163. package/src/context-engine/compaction/hooks/types.ts +68 -0
  164. package/src/context-engine/compaction/index.ts +60 -0
  165. package/src/context-engine/compaction/templates/marker.ts +33 -0
  166. package/src/context-engine/compaction/templates/summary-9-section.ts +223 -0
  167. package/src/context-engine/compaction/thresholds.ts +107 -0
  168. package/src/context-engine/compaction/types.ts +255 -0
  169. package/src/context-engine/engine.ts +970 -0
  170. package/src/context-engine/index.ts +118 -0
  171. package/src/context-engine/io-types.ts +162 -0
  172. package/src/context-engine/locale-packs/en.ts +107 -0
  173. package/src/context-engine/locale-packs/index.ts +19 -0
  174. package/src/context-engine/locale-packs/resolver.ts +197 -0
  175. package/src/context-engine/locale-packs/types.ts +177 -0
  176. package/src/context-engine/metadata.ts +114 -0
  177. package/src/context-engine/preambles/inbound-en.ts +19 -0
  178. package/src/context-engine/privacy-filter.ts +190 -0
  179. package/src/context-engine/templates/base-en.ts +19 -0
  180. package/src/context-engine/templates/composer.ts +91 -0
  181. package/src/context-engine/token-budget.ts +319 -0
  182. package/src/context-engine/token-counter.ts +157 -0
  183. package/src/errors/index.ts +273 -0
  184. package/src/facade.ts +750 -0
  185. package/src/graph/entity-resolver.ts +364 -0
  186. package/src/graph/index.ts +24 -0
  187. package/src/index.ts +259 -0
  188. package/src/internal/contextualize.ts +173 -0
  189. package/src/internal/embedder-binding.ts +53 -0
  190. package/src/internal/envelope.ts +70 -0
  191. package/src/internal/id.ts +23 -0
  192. package/src/internal/injection-heuristics.ts +0 -0
  193. package/src/internal/llm-json.ts +38 -0
  194. package/src/internal/spans.ts +35 -0
  195. package/src/internal/storage-adapter.ts +963 -0
  196. package/src/memory-interface.ts +158 -0
  197. package/src/migration/embedder-migration.ts +237 -0
  198. package/src/migration/index.ts +13 -0
  199. package/src/search/explain.ts +123 -0
  200. package/src/search/fit-weights.ts +109 -0
  201. package/src/search/graph-ppr.ts +38 -0
  202. package/src/search/index.ts +55 -0
  203. package/src/search/iterative.ts +658 -0
  204. package/src/search/query-transform.ts +285 -0
  205. package/src/search/rrf.ts +225 -0
  206. package/src/search/trust.ts +55 -0
  207. package/src/search/types.ts +50 -0
  208. package/src/tiers/episodic-memory.ts +463 -0
  209. package/src/tiers/index.ts +50 -0
  210. package/src/tiers/insight-memory.ts +208 -0
  211. package/src/tiers/procedural-memory.ts +482 -0
  212. package/src/tiers/semantic-memory.ts +1729 -0
  213. package/src/tiers/session-memory.ts +271 -0
  214. package/src/tiers/shared-memory.ts +62 -0
  215. package/src/tiers/working-memory.ts +368 -0
  216. package/src/tools/block-tools.ts +172 -0
  217. package/src/tools/fact-tools.ts +473 -0
  218. package/src/tools/index.ts +109 -0
  219. package/src/tools/recall-tools.ts +303 -0
  220. package/src/tools/runbook-tools.ts +107 -0
  221. package/src/tools/taint.ts +39 -0
  222. package/src/tools/types.ts +37 -0
  223. package/dist/conflict/locale-packs/index.js +0 -4
  224. package/dist/context-engine/compaction/index.js +0 -10
  225. package/dist/context-engine/index.d.ts.map +0 -1
  226. package/dist/context-engine/index.js +0 -25
  227. package/dist/context-engine/locale-packs/index.js +0 -4
@@ -0,0 +1,622 @@
1
+ /**
2
+ * Public types for the Phase 10c consolidator runtime.
3
+ *
4
+ * The consolidator is the background pipeline that turns raw
5
+ * conversation turns into long-lived facts and episodes. The runtime
6
+ * has three phases (`light` / `standard` / `deep`), an explicit cost
7
+ * envelope, an idempotent cursor, a wait-then-defer lock, and a
8
+ * dead-letter queue for retry-able failures. The binding architecture
9
+ * references are DEC-133 / DEC-134 / ADR-038.
10
+ *
11
+ * @packageDocumentation
12
+ */
13
+
14
+ import type { Provider, SessionScope, Tracer } from '@graphorin/core';
15
+ import type { ContextualRetrievalMode } from '../internal/contextualize.js';
16
+ import type { MemoryStoreAdapter } from '../internal/storage-adapter.js';
17
+ import type { EpisodicMemory } from '../tiers/episodic-memory.js';
18
+ import type { SemanticMemory } from '../tiers/semantic-memory.js';
19
+ import type { WorkingMemory } from '../tiers/working-memory.js';
20
+ import type { SalienceWeights } from './decay.js';
21
+
22
+ /**
23
+ * Trigger discriminator. The `'turn:N'` and `'idle:Xm'` variants are
24
+ * the production defaults per DEC-133. `'cron:EXPR'`, `'event:NAME'`
25
+ * and `'budget:N'` are opt-in.
26
+ *
27
+ * @stable
28
+ */
29
+ export type ConsolidatorTriggerSpec =
30
+ | `turn:${number}`
31
+ | `idle:${string}`
32
+ | `cron:${string}`
33
+ | `event:${string}`
34
+ | `budget:${number}`;
35
+
36
+ /**
37
+ * Tier preset that selects a consolidator behaviour bundle. The
38
+ * `'free'` preset is the default per DEC-144 / ADR-038 - no LLM call
39
+ * fires until the operator opts in.
40
+ *
41
+ * @stable
42
+ */
43
+ export type ConsolidatorTier = 'free' | 'cheap' | 'standard' | 'full' | 'custom';
44
+
45
+ /**
46
+ * Triggering reason surfaced through `Consolidator.trigger(...)`.
47
+ *
48
+ * @stable
49
+ */
50
+ export interface ConsolidatorTriggerReason {
51
+ readonly kind: 'turn' | 'idle' | 'cron' | 'event' | 'budget' | 'manual';
52
+ readonly value?: string | number;
53
+ }
54
+
55
+ /**
56
+ * Daily cost ceilings, tracked per budget window. How a breach is
57
+ * handled depends on {@link OnBudgetExceed}: `'pause'` / `'throw'`
58
+ * enforce, `'log'` (the shipped standard/full presets) only WARNs and
59
+ * keeps running. The USD leg accumulates only when a `priceUsage`
60
+ * pricer is configured (memory-consolidation-02) - without one every
61
+ * call prices at $0 and `maxCostPerDay` can never trip. The default
62
+ * ceiling shape per tier is captured in
63
+ * {@link CONSOLIDATOR_TIER_DEFAULTS}.
64
+ *
65
+ * @stable
66
+ */
67
+ export interface ConsolidatorCeilings {
68
+ readonly maxTokensPerDay: number;
69
+ readonly maxCostPerDay: number;
70
+ /**
71
+ * ADVISORY (MCON-8): the per-scope lock serializes runs, so effective
72
+ * concurrency is always 1 per scope regardless of this value. The
73
+ * field is retained for forward compatibility; it enforces nothing
74
+ * today.
75
+ */
76
+ readonly maxConcurrentRuns: number;
77
+ readonly maxRunDurationMs: number;
78
+ /**
79
+ * Minimum quiet period between non-manual runs per scope (MCON-8).
80
+ * After each run the runtime persists `nextEligibleAt = now +
81
+ * cooldownMs`; trigger-driven runs (`turn` / `idle` / `cron` /
82
+ * `event` / `budget`) inside that window defer with reason
83
+ * `'cooldown'`. Manual `fireNow(...)` and DLQ replays bypass it.
84
+ */
85
+ readonly cooldownMs: number;
86
+ }
87
+
88
+ /**
89
+ * Behaviour applied by the budget enforcer when a ceiling is hit
90
+ * mid-run. `'pause'` is the conservative default - the consolidator
91
+ * skips subsequent runs until the next budget reset; `'log'` keeps
92
+ * running with a WARN; `'throw'` raises a typed
93
+ * {@link BudgetExceededError}.
94
+ *
95
+ * @stable
96
+ */
97
+ export type OnBudgetExceed = 'pause' | 'log' | 'throw';
98
+
99
+ /**
100
+ * Phase identifier used by the runtime + audit rows.
101
+ *
102
+ * @stable
103
+ */
104
+ export type ConsolidatorPhase = 'light' | 'standard' | 'deep';
105
+
106
+ /**
107
+ * Locked-down configuration accepted by `createConsolidator(...)`.
108
+ *
109
+ * @stable
110
+ */
111
+ export interface ConsolidatorConfig {
112
+ readonly triggers: ReadonlyArray<ConsolidatorTriggerSpec>;
113
+ readonly tier: ConsolidatorTier;
114
+ readonly phases: ReadonlyArray<ConsolidatorPhase>;
115
+ readonly ceilings: ConsolidatorCeilings;
116
+ readonly onExceed: OnBudgetExceed;
117
+ /**
118
+ * Advisory label for the standard phase's model - recorded on spans /
119
+ * run telemetry only (MCON-7). Routing happens via
120
+ * `CreateConsolidatorOptions.cheapProvider`; this string disables
121
+ * nothing.
122
+ */
123
+ readonly cheapModel: string | null;
124
+ /**
125
+ * Advisory label for the deep phase's model - telemetry only
126
+ * (MCON-7). Routing happens via
127
+ * `CreateConsolidatorOptions.deepProvider`.
128
+ */
129
+ readonly deepModel: string | null;
130
+ readonly budgetResetSemantics: 'utc' | 'local' | 'sliding-24h';
131
+ readonly noiseFilters: ReadonlyArray<'default' | 'minimal' | 'none'>;
132
+ readonly lockWaitMs: number;
133
+ readonly decayTauDays: number;
134
+ readonly decayArchiveThreshold: number;
135
+ /**
136
+ * Capacity-bounded eviction target for the light phase (X-1). When set,
137
+ * each light pass archives the lowest-salience live facts in the LRU
138
+ * decay window down to this many - **cost / staleness control, not an
139
+ * accuracy lever**. `null` (the default at every tier) leaves storage
140
+ * unbounded, so behaviour is identical to pre-X-1. Archiving is a soft,
141
+ * recoverable move; nothing is hard-deleted.
142
+ */
143
+ readonly decayCapacity: number | null;
144
+ /**
145
+ * Weights for the multi-signal salience score (X-1) that orders both
146
+ * threshold archiving and capacity eviction. Defaults to
147
+ * `DEFAULT_SALIENCE_WEIGHTS`; with neutral importance, active
148
+ * status, and first-party provenance salience equals plain retention.
149
+ */
150
+ readonly salienceWeights: SalienceWeights;
151
+ readonly maxStandardBatchSize: number;
152
+ /**
153
+ * Input-side transcript budget for the standard phase, in characters
154
+ * (W-081; chars/4 is the package's deterministic token proxy, so the
155
+ * 60k default approximates 15k tokens). `maxStandardBatchSize` bounds
156
+ * only the MESSAGE COUNT of a slice; without a size budget a batch of
157
+ * near-cap messages can render to hundreds of kilobytes, overflow a
158
+ * cheap-tier model context on every retry and wedge the cursor
159
+ * permanently. A transcript over this budget is half-split BEFORE the
160
+ * provider call (same convergent recursion as the
161
+ * `finishReason: 'length'` output handling); a single message that
162
+ * alone exceeds the budget is tail-truncated and recorded on the
163
+ * phase span. Conservative for CJK scripts by design.
164
+ */
165
+ readonly maxTranscriptChars: number;
166
+ readonly maxDeepConflictsPerRun: number;
167
+ readonly dlqMaxRetries: number;
168
+ readonly dlqBaseBackoffMs: number;
169
+ readonly dlqMaxBackoffMs: number;
170
+ /**
171
+ * Auto-form a quarantined episode from each processed standard-phase
172
+ * slice (P1-2). Defaults on at the `standard`+ tiers, off at `free` /
173
+ * `cheap` / `custom`. The episode summary is one budgeted LLM call;
174
+ * when the budget is exhausted (or no episodic tier is wired) the
175
+ * phase degrades to fact-only behaviour.
176
+ */
177
+ readonly formEpisodes: boolean;
178
+ /**
179
+ * Ask the episode-summarization call for an LLM importance score
180
+ * (1-10, normalized to `[0, 1]`) so episodic triple-signal retrieval
181
+ * (recency × relevance × importance) runs on all three signals
182
+ * (P1-2). Importance is always a *soft* signal - it never gates
183
+ * retention. Defaults track {@link formEpisodes}.
184
+ */
185
+ readonly importanceScoring: boolean;
186
+ /**
187
+ * Auto-promotion policy (MCON-2). When `true`, the standard phase admits an
188
+ * injection-clean **extraction** fact as `active` instead of quarantined, so
189
+ * routine distillation surfaces in default recall without a manual
190
+ * `memory review --promote`. Injection-flagged facts always stay quarantined
191
+ * - the security gate is preserved - and episodes / insights / induced
192
+ * procedures are unaffected (they remain quarantined-until-validated).
193
+ * Defaults **off** at every tier: it trades the fail-safe default for
194
+ * convenience and is an explicit operator opt-in.
195
+ */
196
+ readonly autoPromoteExtraction: boolean;
197
+ /**
198
+ * Run the deep-phase reflection pass (P1-1): when accumulated episode
199
+ * importance crosses {@link importanceThreshold}, synthesize
200
+ * higher-order, cited insights over recent memories (Generative
201
+ * Agents). Insights land quarantined + `provenance: 'reflection'` and
202
+ * are ranked below the facts they cite. Defaults **on at the `full`
203
+ * tier only** (off at `free` / `cheap` / `standard` / `custom`) - it
204
+ * is the most LLM-intensive phase. A no-op without an episodic tier
205
+ * or an insight-capable storage adapter.
206
+ */
207
+ readonly reflection: boolean;
208
+ /**
209
+ * Sum of recent episode importance (each in `[0, 1]`) at or above
210
+ * which {@link reflection} fires. Below it the pass makes no LLM
211
+ * call. Defaults to `3`.
212
+ */
213
+ readonly importanceThreshold: number;
214
+ /** Upper bound on salient questions reflection asks per pass. Defaults to `3`. */
215
+ readonly reflectionMaxQuestions: number;
216
+ /**
217
+ * W-082: cap on the unreviewed (quarantined) insight queue. Quarantined
218
+ * insights are exempt from reflection pass-decay - their decay clock
219
+ * starts at validation - and this bound keeps the review queue from
220
+ * growing without limit: beyond it the oldest quarantined insights are
221
+ * pruned. Defaults to `100`.
222
+ */
223
+ readonly reflectionMaxQuarantinedInsights: number;
224
+ /**
225
+ * Contextual retrieval for facts written by the standard phase (P1-3).
226
+ * `'late-chunk'` (default at every tier) relies on the offline
227
+ * situating-context prefix the shared {@link SemanticMemory} computes
228
+ * for every write - no extra LLM call. `'llm'` is the opt-in
229
+ * enrichment: the standard phase spends one budgeted cheap-model call
230
+ * per additive write to author a 1-2 sentence situating prefix, then
231
+ * passes it as the write's index text. `'off'` indexes the bare text.
232
+ * The `'llm'` mode is **consolidator-only** by construction - the hot
233
+ * write path never has a provider for contextualization.
234
+ */
235
+ readonly contextualRetrieval: ContextualRetrievalMode;
236
+ /**
237
+ * Maintain the learned-context digest block (D3): after the deep
238
+ * phase, one budgeted LLM call rewrites the reserved
239
+ * `learned_context` working block from the previous digest + recent
240
+ * episodes / active insights / active procedures, so the system
241
+ * prompt carries a compact standing summary. Defaults **off at every
242
+ * tier** (Wave-D trial) - a no-op without a working tier handle.
243
+ */
244
+ readonly learnedContext: boolean;
245
+ /** Character bound enforced on the learned-context digest. Default `1200`. */
246
+ readonly learnedContextMaxChars: number;
247
+ }
248
+
249
+ /**
250
+ * Per-phase last-run snapshot surfaced inside
251
+ * {@link ConsolidatorStatus.lastRuns}. Each entry carries the
252
+ * timestamp of the most recent **completed** invocation for that
253
+ * phase (`undefined` when the phase has never run).
254
+ *
255
+ * @stable
256
+ */
257
+ export interface ConsolidatorLastRuns {
258
+ readonly light?: string;
259
+ readonly standard?: string;
260
+ readonly deep?: string;
261
+ }
262
+
263
+ /**
264
+ * Budget snapshot block of {@link ConsolidatorStatus}. Surfaces
265
+ * both the absolute usage and the remaining envelope so consumers
266
+ * (CLI, server health endpoint) can render the operator dashboard
267
+ * without doing the math themselves.
268
+ *
269
+ * @stable
270
+ */
271
+ export interface ConsolidatorBudgetSnapshot {
272
+ readonly tokensUsedToday: number;
273
+ readonly costUsedToday: number;
274
+ readonly tokensRemaining: number;
275
+ readonly costRemaining: number;
276
+ readonly resetAt: string;
277
+ }
278
+
279
+ /**
280
+ * Status snapshot returned by {@link Consolidator.status}.
281
+ *
282
+ * Public shape: `{ tier, queueDepth, dlqSize, lastRuns,
283
+ * budgetRemaining, deferredRuns }` - extended with a few additional
284
+ * fields the server health endpoint and the
285
+ * `graphorin consolidator status` CLI consume.
286
+ *
287
+ * `queueDepth` is an alias for {@link pendingConflicts} (the size
288
+ * of the deep-phase queue); both fields are populated for backwards
289
+ * compatibility.
290
+ *
291
+ * @stable
292
+ */
293
+ export interface ConsolidatorStatus {
294
+ readonly tier: ConsolidatorTier;
295
+ readonly triggers: ReadonlyArray<ConsolidatorTriggerSpec>;
296
+ readonly phases: ReadonlyArray<ConsolidatorPhase>;
297
+ readonly running: boolean;
298
+ readonly paused: boolean;
299
+ /** Most recent completed run timestamp (any phase). */
300
+ readonly lastRunAt?: string;
301
+ /** Phase of the most recent completed run. */
302
+ readonly lastPhase?: ConsolidatorPhase;
303
+ /** Per-phase last-completed timestamps surfaced for CLI / dashboard. */
304
+ readonly lastRuns: ConsolidatorLastRuns;
305
+ /** Spec alias for {@link pendingConflicts}. */
306
+ readonly queueDepth: number;
307
+ readonly pendingConflicts: number;
308
+ readonly dlqSize: number;
309
+ readonly deferredRuns: number;
310
+ readonly emptyExtractions: number;
311
+ readonly budget: ConsolidatorBudgetSnapshot;
312
+ /** Spec alias - surfaces remaining-budget figures at the top level. */
313
+ readonly budgetRemaining: {
314
+ readonly tokens: number;
315
+ readonly costUsd: number;
316
+ };
317
+ }
318
+
319
+ /**
320
+ * Outcome surfaced by every phase invocation. Recorded into
321
+ * `consolidator_runs` and emitted on the AISpan.
322
+ *
323
+ * @stable
324
+ */
325
+ export interface PhaseOutcome {
326
+ readonly phase: ConsolidatorPhase;
327
+ readonly status: 'completed' | 'failed' | 'deferred' | 'partial';
328
+ readonly factsCreated: number;
329
+ readonly factsUpdated: number;
330
+ readonly conflictsResolved: number;
331
+ /** Episodes auto-formed from the processed slice (P1-2). */
332
+ readonly episodesFormed: number;
333
+ /** Insights synthesized by the deep-phase reflection pass (P1-1). */
334
+ readonly insightsCreated: number;
335
+ /** True when the learned-context digest block was rewritten (D3). */
336
+ readonly learnedContextUpdated?: boolean;
337
+ readonly noiseFilteredCount: number;
338
+ readonly emptyExtractions: number;
339
+ readonly llmTokensUsed: number;
340
+ readonly llmCostUsd: number | null;
341
+ readonly errorMessage: string | null;
342
+ }
343
+
344
+ /**
345
+ * Listener callback subscribed via
346
+ * {@link Consolidator.onPhaseFinished}. Useful for tests + observers.
347
+ *
348
+ * @stable
349
+ */
350
+ export type PhaseListener = (
351
+ outcome: PhaseOutcome & {
352
+ readonly scope: SessionScope;
353
+ readonly trigger: ConsolidatorTriggerReason;
354
+ },
355
+ ) => void;
356
+
357
+ /**
358
+ * Options accepted by {@link createConsolidator}.
359
+ *
360
+ * @stable
361
+ */
362
+ export interface CreateConsolidatorOptions {
363
+ /**
364
+ * Storage adapter - supplies the consolidator state, runs, DLQ,
365
+ * and per-tier helpers. The default `@graphorin/store-sqlite`
366
+ * adapter exposes everything by construction.
367
+ */
368
+ readonly store: MemoryStoreAdapter;
369
+ /**
370
+ * The {@link SemanticMemory} tier instance from the parent
371
+ * `createMemory(...)` facade. The standard phase routes every
372
+ * extracted fact through `semantic.remember(...)` so the conflict
373
+ * pipeline (Phase 10b) handles dedup / supersede.
374
+ */
375
+ readonly semantic: SemanticMemory;
376
+ /**
377
+ * The {@link EpisodicMemory} tier instance from the parent
378
+ * `createMemory(...)` facade. When supplied (and `formEpisodes` is
379
+ * on) the standard phase auto-forms a quarantined episode per
380
+ * processed slice (P1-2). Omitted ⇒ episode formation is skipped.
381
+ */
382
+ readonly episodic?: EpisodicMemory;
383
+ /**
384
+ * The {@link WorkingMemory} tier instance from the parent
385
+ * `createMemory(...)` facade (D3). Required for the learned-context
386
+ * pass - without it the pass is a silent no-op even when
387
+ * `learnedContext` is enabled.
388
+ */
389
+ readonly working?: WorkingMemory;
390
+ /**
391
+ * Provider used by the standard + deep phases. Required when the
392
+ * tier enables either phase; ignored when the active phases
393
+ * collapse to `['light']`.
394
+ */
395
+ readonly provider?: Provider | null;
396
+ readonly tracer?: Tracer;
397
+ /** Override the wall clock - used by tests. */
398
+ readonly now?: () => number;
399
+ /** Random source for stable run ids - used by tests. */
400
+ readonly randomId?: () => string;
401
+ readonly triggers?: ReadonlyArray<ConsolidatorTriggerSpec>;
402
+ readonly tier?: ConsolidatorTier;
403
+ readonly phases?: ReadonlyArray<ConsolidatorPhase>;
404
+ readonly ceilings?: Partial<ConsolidatorCeilings>;
405
+ readonly onExceed?: OnBudgetExceed;
406
+ /**
407
+ * USD pricer for phase LLM usage (memory-consolidation-02). Wire it
408
+ * to `@graphorin/pricing`'s `calculateCost` (or any per-token rate)
409
+ * so the `maxCostPerDay` ceiling can actually accumulate spend -
410
+ * without it every phase prices its calls at $0 and the USD ceiling
411
+ * never trips at any tier.
412
+ *
413
+ * ```ts
414
+ * priceUsage: ({ promptTokens, completionTokens }) =>
415
+ * (promptTokens * 3 + completionTokens * 15) / 1_000_000
416
+ * ```
417
+ */
418
+ readonly priceUsage?: (usage: { promptTokens: number; completionTokens: number }) => number;
419
+ /**
420
+ * Provider routed to the standard phase (extraction / episode /
421
+ * reconcile / situating-context calls) when set (MCON-7). Falls back
422
+ * to `provider`. Pair with `cheapModel` for the telemetry label.
423
+ */
424
+ readonly cheapProvider?: Provider | null;
425
+ /**
426
+ * Provider routed to the deep phase (conflict judge) and the
427
+ * reflection pass when set (MCON-7). Falls back to `provider`.
428
+ */
429
+ readonly deepProvider?: Provider | null;
430
+ readonly cheapModel?: string | null;
431
+ readonly deepModel?: string | null;
432
+ readonly budgetResetSemantics?: 'utc' | 'local' | 'sliding-24h';
433
+ readonly noiseFilters?: ReadonlyArray<'default' | 'minimal' | 'none'>;
434
+ readonly lockWaitMs?: number;
435
+ readonly decayTauDays?: number;
436
+ readonly decayArchiveThreshold?: number;
437
+ /** Override the {@link ConsolidatorConfig.decayCapacity} default (X-1). */
438
+ readonly decayCapacity?: number | null;
439
+ /** Override the {@link ConsolidatorConfig.salienceWeights} default (X-1). */
440
+ readonly salienceWeights?: SalienceWeights;
441
+ readonly maxStandardBatchSize?: number;
442
+ /** Override the per-tier {@link ConsolidatorConfig.maxTranscriptChars} default (W-081). */
443
+ readonly maxTranscriptChars?: number;
444
+ readonly maxDeepConflictsPerRun?: number;
445
+ readonly dlqMaxRetries?: number;
446
+ readonly dlqBaseBackoffMs?: number;
447
+ readonly dlqMaxBackoffMs?: number;
448
+ /** Override the per-tier {@link ConsolidatorConfig.formEpisodes} default (P1-2). */
449
+ readonly formEpisodes?: boolean;
450
+ /** Override the per-tier {@link ConsolidatorConfig.importanceScoring} default (P1-2). */
451
+ readonly importanceScoring?: boolean;
452
+ /**
453
+ * Opt in to auto-promotion of injection-clean extraction facts (MCON-2).
454
+ * Defaults `false`. See {@link ConsolidatorConfig.autoPromoteExtraction}.
455
+ */
456
+ readonly autoPromoteExtraction?: boolean;
457
+ /** Override the per-tier {@link ConsolidatorConfig.reflection} default (P1-1). */
458
+ readonly reflection?: boolean;
459
+ /** Override the {@link ConsolidatorConfig.importanceThreshold} default (P1-1). */
460
+ readonly importanceThreshold?: number;
461
+ /** Override the {@link ConsolidatorConfig.reflectionMaxQuestions} default (P1-1). */
462
+ readonly reflectionMaxQuestions?: number;
463
+ /** Override the {@link ConsolidatorConfig.reflectionMaxQuarantinedInsights} default (W-082). */
464
+ readonly reflectionMaxQuarantinedInsights?: number;
465
+ /** Override the per-tier {@link ConsolidatorConfig.contextualRetrieval} default (P1-3). */
466
+ readonly contextualRetrieval?: ContextualRetrievalMode;
467
+ /** Override the per-tier {@link ConsolidatorConfig.learnedContext} default (D3). */
468
+ readonly learnedContext?: boolean;
469
+ /** Override the {@link ConsolidatorConfig.learnedContextMaxChars} default (D3). */
470
+ readonly learnedContextMaxChars?: number;
471
+ /** Default scope used by event triggers + the manual `fireNow` path. */
472
+ readonly defaultScope?: SessionScope;
473
+ }
474
+
475
+ /**
476
+ * Tier preset table. The defaults follow ADR-038 §4 - `'free'`
477
+ * disables every LLM phase and pins zero ceilings, the upper tiers
478
+ * widen the budget envelope progressively.
479
+ *
480
+ * @stable
481
+ */
482
+ export const CONSOLIDATOR_TIER_DEFAULTS: Readonly<
483
+ Record<
484
+ ConsolidatorTier,
485
+ {
486
+ readonly ceilings: ConsolidatorCeilings;
487
+ readonly phases: ReadonlyArray<ConsolidatorPhase>;
488
+ readonly cheapModel: string | null;
489
+ readonly deepModel: string | null;
490
+ readonly onExceed: OnBudgetExceed;
491
+ /** W-081: input transcript budget for one standard-phase slice. */
492
+ readonly maxTranscriptChars: number;
493
+ readonly formEpisodes: boolean;
494
+ readonly importanceScoring: boolean;
495
+ readonly reflection: boolean;
496
+ readonly importanceThreshold: number;
497
+ readonly reflectionMaxQuestions: number;
498
+ readonly reflectionMaxQuarantinedInsights: number;
499
+ readonly contextualRetrieval: ContextualRetrievalMode;
500
+ readonly learnedContext: boolean;
501
+ readonly learnedContextMaxChars: number;
502
+ }
503
+ >
504
+ > = Object.freeze({
505
+ free: {
506
+ ceilings: {
507
+ maxTokensPerDay: 0,
508
+ maxCostPerDay: 0,
509
+ maxConcurrentRuns: 1,
510
+ maxRunDurationMs: 5 * 60 * 1000,
511
+ cooldownMs: 60_000,
512
+ },
513
+ phases: ['light'],
514
+ cheapModel: null,
515
+ deepModel: null,
516
+ onExceed: 'pause',
517
+ maxTranscriptChars: 60_000,
518
+ formEpisodes: false,
519
+ importanceScoring: false,
520
+ reflection: false,
521
+ importanceThreshold: 3,
522
+ reflectionMaxQuestions: 3,
523
+ reflectionMaxQuarantinedInsights: 100,
524
+ contextualRetrieval: 'late-chunk',
525
+ learnedContext: false,
526
+ learnedContextMaxChars: 1200,
527
+ },
528
+ cheap: {
529
+ ceilings: {
530
+ maxTokensPerDay: 50_000,
531
+ maxCostPerDay: 0.2,
532
+ maxConcurrentRuns: 1,
533
+ maxRunDurationMs: 5 * 60 * 1000,
534
+ cooldownMs: 60_000,
535
+ },
536
+ phases: ['light', 'standard'],
537
+ cheapModel: null,
538
+ deepModel: null,
539
+ onExceed: 'pause',
540
+ maxTranscriptChars: 60_000,
541
+ formEpisodes: false,
542
+ importanceScoring: false,
543
+ reflection: false,
544
+ importanceThreshold: 3,
545
+ reflectionMaxQuestions: 3,
546
+ reflectionMaxQuarantinedInsights: 100,
547
+ contextualRetrieval: 'late-chunk',
548
+ learnedContext: false,
549
+ learnedContextMaxChars: 1200,
550
+ },
551
+ standard: {
552
+ ceilings: {
553
+ maxTokensPerDay: 200_000,
554
+ maxCostPerDay: 1.0,
555
+ maxConcurrentRuns: 1,
556
+ maxRunDurationMs: 10 * 60 * 1000,
557
+ cooldownMs: 30_000,
558
+ },
559
+ phases: ['light', 'standard', 'deep'],
560
+ cheapModel: null,
561
+ deepModel: null,
562
+ onExceed: 'log',
563
+ maxTranscriptChars: 60_000,
564
+ formEpisodes: true,
565
+ importanceScoring: true,
566
+ reflection: false,
567
+ importanceThreshold: 3,
568
+ reflectionMaxQuestions: 3,
569
+ reflectionMaxQuarantinedInsights: 100,
570
+ contextualRetrieval: 'late-chunk',
571
+ learnedContext: false,
572
+ learnedContextMaxChars: 1200,
573
+ },
574
+ full: {
575
+ ceilings: {
576
+ maxTokensPerDay: 1_000_000,
577
+ maxCostPerDay: 5.0,
578
+ maxConcurrentRuns: 2,
579
+ maxRunDurationMs: 15 * 60 * 1000,
580
+ cooldownMs: 10_000,
581
+ },
582
+ phases: ['light', 'standard', 'deep'],
583
+ cheapModel: null,
584
+ deepModel: null,
585
+ onExceed: 'log',
586
+ // Full-tier models carry wider contexts - a larger input budget
587
+ // keeps slices coarse (fewer calls) without risking overflow.
588
+ maxTranscriptChars: 120_000,
589
+ formEpisodes: true,
590
+ importanceScoring: true,
591
+ reflection: true,
592
+ importanceThreshold: 3,
593
+ reflectionMaxQuestions: 3,
594
+ reflectionMaxQuarantinedInsights: 100,
595
+ contextualRetrieval: 'late-chunk',
596
+ learnedContext: false,
597
+ learnedContextMaxChars: 1200,
598
+ },
599
+ custom: {
600
+ ceilings: {
601
+ maxTokensPerDay: 0,
602
+ maxCostPerDay: 0,
603
+ maxConcurrentRuns: 1,
604
+ maxRunDurationMs: 5 * 60 * 1000,
605
+ cooldownMs: 60_000,
606
+ },
607
+ phases: ['light'],
608
+ cheapModel: null,
609
+ deepModel: null,
610
+ onExceed: 'pause',
611
+ maxTranscriptChars: 60_000,
612
+ formEpisodes: false,
613
+ importanceScoring: false,
614
+ reflection: false,
615
+ importanceThreshold: 3,
616
+ reflectionMaxQuestions: 3,
617
+ reflectionMaxQuarantinedInsights: 100,
618
+ contextualRetrieval: 'late-chunk',
619
+ learnedContext: false,
620
+ learnedContextMaxChars: 1200,
621
+ },
622
+ });