@graphorin/memory 0.6.0 → 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 +83 -0
  2. package/README.md +24 -7
  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 +17 -15
  75. package/dist/index.d.ts.map +1 -1
  76. package/dist/index.js +5 -7
  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 +6 -0
  89. package/dist/package.js.map +1 -0
  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
@@ -1 +1 @@
1
- {"version":3,"file":"engine.js","names":["DEFAULT_LAYER_CAPS: Readonly<\n Record<keyof Required<NonNullable<ContextEngineConfig['layers']>>, number | undefined>\n>","LAYER_EMIT_ORDER: Readonly<Record<LayerAllocation['id'], number>>","localePack: ContextLocalePack","layersEnabled: Record<string, boolean>","layerCaps: Record<string, number | undefined>","tokenCounter: ContextTokenCounter","defaultSensitivity: Sensitivity","providerTrust: LocalProviderTrust","compactionStrategy: CompactionStrategy","compactionHooks: ReadonlyArray<NamedPostCompactionHook>","resolvedConfig: ResolvedContextEngineConfig","blocksKept: Array<(typeof blocks)[number]>","privacyCounters: Record<PrivacyDecisionReason, number>","privacyDecide","rulesKept: Array<(typeof rules)[number]>","autoRecall: AutoRecallTriggerResult","facts: Fact[]","allocateLayers","finalParts: string[]","annotations: AnnotatedPart[]","lastCompactionAfterTokens: number | null","compactionInputCall: ExecuteCompactionInput","result: CompactionResult","hookFailures: Array<{ readonly hookName: string; readonly reason: string }>","extraContent: MessageContent[]","enrichedResult: CompactionResult"],"sources":["../../src/context-engine/engine.ts"],"sourcesContent":["/**\n * `ContextEngine` - the layered six-layer system prompt assembler.\n *\n * Combines:\n *\n * - Layer 1 (`graphorin_memory_base`) educational template\n * - Layer 2 user-defined `agent_instructions`\n * - Layer 3 working-memory blocks (filtered through D2 privacy)\n * - Layer 4 procedural rules + skill metadata cards\n * - Layer 5 memory-metadata counters\n * - Layer 6 opt-in auto-recall\n *\n * Cross-cuts:\n *\n * - D2 privacy filter (sensitivity-tier drop)\n * - D3 cooperation contract (`ContentOrigin` annotation)\n * - D4 inbound preamble injection (post cache-breakpoint)\n * - RB-44 per-step tool-catalogue cardinality allocator (separate axis)\n * - RB-46 in-flight session message-history compaction (separate axis)\n *\n * @packageDocumentation\n */\n\nimport type {\n Fact,\n LocalProviderTrust,\n Message,\n MessageContent,\n Sensitivity,\n SessionScope,\n TokenCounter,\n} from '@graphorin/core';\nimport type { Memory } from '../facade.js';\nimport { annotate, type ContentAnnotation, shouldFireInboundPreamble } from './annotations.js';\nimport {\n type AutoRecallStrategy,\n type AutoRecallTriggerResult,\n defaultLocaleHeuristicStrategy,\n} from './auto-recall.js';\nimport {\n DEFAULT_PRESERVE_RECENT_TURNS,\n type ExecuteCompactionInput,\n executeCompaction,\n} from './compaction/compactor.js';\nimport type { NamedPostCompactionHook } from './compaction/hooks/types.js';\nimport {\n reanchorPersonaBlock,\n reanchorPinnedFacts,\n reanchorProjectRules,\n} from './compaction/index.js';\nimport { resolveAutoCompactionDefault, resolveTriggerThreshold } from './compaction/thresholds.js';\nimport type {\n CompactionConfig,\n CompactionResult,\n CompactionSource,\n CompactionStrategy,\n CompactionSummarizer,\n PostCompactionHook,\n} from './compaction/types.js';\nimport {\n type ContextLocalePack,\n enLocalePack,\n type PartialContextLocalePack,\n} from './locale-packs/index.js';\nimport { resolveLocalePack } from './locale-packs/resolver.js';\nimport { renderMetadataBlock } from './metadata.js';\nimport { type PrivacyDecisionReason, decide as privacyDecide } from './privacy-filter.js';\nimport {\n composeInboundPreamble,\n composeLayer1,\n composeLayer2,\n composeLayer4Skills,\n type MemoryBaseMode,\n type SkillMetadataCard,\n} from './templates/composer.js';\nimport {\n type AllocationResult,\n allocate as allocateLayers,\n type LayerAllocation,\n type LayerCandidate,\n} from './token-budget.js';\nimport {\n adaptTokenCounter,\n type ContextTokenCounter,\n countMessageTokens,\n HEURISTIC_TOKEN_COUNTER,\n} from './token-counter.js';\n\n/**\n * Per-layer cap configuration. Mirrors the documented\n * `ContextEngineConfig.layers.*` fields.\n *\n * @stable\n */\nexport interface LayerConfig {\n readonly enabled?: boolean;\n readonly cap?: number;\n}\n\n/**\n * Auto-recall config knob. `false` disables; `{ topK }` enables\n * the heuristic with a bounded top-K.\n *\n * @stable\n */\nexport type AutoRecallConfig =\n | false\n | {\n readonly topK?: number;\n /**\n * Minimum fused score a hit must reach to be injected. **Default `0`**\n * (CE-4) - `topK` already bounds the volume. The scale is\n * reranker-dependent: the default RRF reranker fuses the FTS + vector\n * candidate lists as `1/(60 + rank)` per list, so scores top out near\n * `2/(60 + 1) ≈ 0.033` - any positive default would silently drop every\n * hit. Set this only when calibrating against a known reranker's scale.\n */\n readonly threshold?: number;\n readonly strategy?: AutoRecallStrategy;\n };\n\n/**\n * Privacy block of the engine config.\n *\n * @stable\n */\nexport interface PrivacyConfig {\n readonly cloudUploadConsent?: boolean;\n readonly defaultSensitivity?: Sensitivity;\n readonly providerAcceptsSensitivity?: ReadonlyArray<Sensitivity>;\n readonly providerTrust?: LocalProviderTrust;\n}\n\n/**\n * Configuration accepted by {@link createContextEngine}.\n *\n * @stable\n */\nexport interface ContextEngineConfig {\n /**\n * Layer 1 base-template mode. `'full'` (default) ships the\n * verbose ~250-350 token narrative aimed at general LLMs;\n * `'minimal'` opts top-tier models into the ~80-120 token\n * compact form.\n */\n readonly memoryBaseMode?: MemoryBaseMode;\n /** Default `'en'`. Pluggable via `defineContextLocalePack`. */\n readonly locale?: string | ContextLocalePack | PartialContextLocalePack;\n /** Per-layer enable / cap overrides. */\n readonly layers?: {\n readonly identity?: LayerConfig;\n readonly memoryMetadata?: LayerConfig;\n readonly activeRules?: LayerConfig;\n readonly activeSkills?: LayerConfig;\n readonly workingBlocks?: LayerConfig;\n readonly autoRecall?: LayerConfig & { readonly topK?: number; readonly threshold?: number };\n };\n /** Auto-recall trigger configuration. Default `false`. */\n readonly factsAutoRecall?: AutoRecallConfig;\n /** Privacy-filter configuration. */\n readonly privacy?: PrivacyConfig;\n /** Hard token budget. Default `Number.POSITIVE_INFINITY` (no global cap). */\n readonly maxContextTokens?: number;\n /** Tokens reserved for the model's response. Default `4096`. */\n readonly reservedForResponse?: number;\n /** Tokens reserved for the compaction summarizer call. Default `8192`. */\n readonly reservedForCompaction?: number;\n /** Pluggable token counter. Default heuristic (chars/4). */\n readonly tokenCounter?: TokenCounter | ContextTokenCounter;\n /** Auto-compaction configuration (RB-46). */\n readonly compaction?: false | CompactionConfig;\n /** Active provider's context window; required when compaction is enabled. */\n readonly providerContextWindow?: number;\n /** Default summarizer adapter the auto-trigger uses. */\n readonly summarizer?: CompactionSummarizer;\n /** Wall clock for tests + deterministic compaction. */\n readonly now?: () => number;\n}\n\n/**\n * Per-call runtime context handed to {@link ContextEngine.assemble}.\n *\n * @stable\n */\nexport interface AssembleInput {\n readonly scope: SessionScope;\n readonly agentId: string;\n readonly sessionId: string;\n readonly runId: string;\n readonly agentInstructions?: string;\n readonly skills?: ReadonlyArray<SkillMetadataCard>;\n readonly proceduralActivation?: {\n readonly topic?: string;\n readonly tags?: ReadonlyArray<string>;\n };\n readonly lastUserMessage?: string;\n readonly autoRecallStrategyOverride?: AutoRecallStrategy;\n /**\n * Optional inbound-trust annotations carried by upstream\n * messages (`session_messages` rows tagged by Phase 12 / Phase\n * 07 / Phase 09). When at least one part has `inboundTrust !==\n * 'trusted' && inboundTrust !== 'n/a'`, the per-step preamble\n * fires (see RB-43 / DEC-159).\n */\n readonly upstreamAnnotations?: ReadonlyArray<ContentAnnotation>;\n}\n\n/**\n * Single annotated `MessageContent` part assembled by the engine.\n *\n * @stable\n */\nexport interface AnnotatedPart {\n readonly content: MessageContent;\n readonly annotation: ContentAnnotation;\n}\n\n/**\n * Output of {@link ContextEngine.assemble}.\n *\n * @stable\n */\nexport interface AssembledPrompt {\n /** Single system message ready for `provider.stream(...)`. */\n readonly systemMessage: { readonly role: 'system'; readonly content: string };\n /**\n * Per-part annotations, in the same order as the assembled\n * system content. Span-only - never serialized to the wire payload.\n */\n readonly annotations: ReadonlyArray<AnnotatedPart>;\n /**\n * Per-layer allocation snapshot. Surfaced for tests + diagnostics.\n */\n readonly layerAllocation: AllocationResult;\n /** Whether the per-step inbound preamble fragment fired this assembly. */\n readonly inboundPreambleFired: boolean;\n /** Privacy-filter counters surfaced to the metadata block. */\n readonly privacyCounters: Readonly<Record<PrivacyDecisionReason, number>>;\n /** Resolved locale id (`'en'` for the default; custom otherwise). */\n readonly localeId: string;\n /** Resolved memory base mode. */\n readonly memoryBaseMode: MemoryBaseMode;\n /** Whether auto-recall was triggered this assembly. */\n readonly autoRecall: AutoRecallTriggerResult;\n}\n\n/**\n * Public surface of the {@link ContextEngine} instance returned by\n * {@link createContextEngine}.\n *\n * @stable\n */\nexport interface ContextEngine {\n /** Assemble the layered system prompt for a single step. */\n assemble(memory: Memory, input: AssembleInput): Promise<AssembledPrompt>;\n /**\n * Trigger evaluation primitive used by Phase 12 (agent runtime)\n * at the top of every step. Returns `true` when the in-flight\n * buffer's token count crosses the per-provider trigger\n * threshold. Pass `precomputedTokens` to amortize the count\n * via the per-message cache surfaced by\n * `SessionMemoryStoreExt.totalCachedTokens(scope)` (DEC-131) -\n * the production hot path is an O(1) comparison when the cache\n * is warm.\n */\n shouldCompact(\n messages: ReadonlyArray<Message>,\n options?: {\n readonly precomputedTokens?: number;\n /**\n * Index of the first COMPACTABLE message (context-engine-04): the\n * caller's pinned, never-compacted system prefix ends here. The\n * SOTA-4 reclaim floor counts only `messages.slice(from)` older\n * turns as reclaimable - without it a large system prompt is\n * counted as reclaimable and the floor fires the summarizer for\n * near-zero real reclaim. Default `0` (everything compactable).\n */\n readonly compactableFromIndex?: number;\n },\n ): Promise<boolean>;\n /**\n * Run a compaction call. Phase 12 calls this when the trigger\n * fires (`source: 'auto-trigger'`) or the operator invokes\n * `agent.compact(...)` (`source: 'manual'`).\n */\n compactNow(input: {\n readonly scope: SessionScope;\n readonly runId: string;\n readonly sessionId: string;\n readonly agentId: string;\n readonly source: CompactionSource;\n readonly messages: ReadonlyArray<Message>;\n readonly memory: Memory;\n readonly summarizer?: CompactionSummarizer;\n /** Per-call override of the strategy's preserve-recent count (CE-3). */\n readonly preserveRecentTurns?: number;\n /** Topic/tags narrowing for the procedural-rules re-anchor hook (CE-6). */\n readonly procedural?: { readonly topic?: string; readonly tags?: ReadonlyArray<string> };\n /**\n * The caller's pinned system prefix - the messages EXCLUDED from\n * `messages` before this call (context-engine-04). Used only for\n * accounting: the anti-thrash guard and the \"still above threshold\"\n * warning must compare against the FULL post-splice context\n * (prefix + summary + preserved + essentials), or a real system\n * prompt defeats the guard and a summarizer call fires every step\n * at the context edge. Never compacted, never returned.\n */\n readonly prefixMessages?: ReadonlyArray<Message>;\n readonly signal?: AbortSignal;\n }): Promise<{\n readonly result: CompactionResult;\n readonly extraContent: ReadonlyArray<MessageContent>;\n readonly hookFailures: ReadonlyArray<{ readonly hookName: string; readonly reason: string }>;\n }>;\n /** Resolved configuration snapshot. */\n config(): ResolvedContextEngineConfig;\n}\n\n/**\n * Resolved configuration snapshot returned by\n * {@link ContextEngine.config}.\n *\n * @stable\n */\nexport interface ResolvedContextEngineConfig {\n readonly memoryBaseMode: MemoryBaseMode;\n readonly localeId: string;\n readonly maxContextTokens: number;\n readonly reservedForResponse: number;\n readonly reservedForCompaction: number;\n readonly compactionEnabled: boolean;\n /**\n * Whether compaction can actually fire (CE-12): `compactionEnabled` **and** a\n * `providerContextWindow` was supplied. `compactionEnabled: true` with\n * `compactionEffective: false` is the honest signal that compaction is\n * configured-on but a no-op for want of a context window.\n */\n readonly compactionEffective: boolean;\n readonly compactionThresholdTokens: number;\n readonly providerContextWindow: number | null;\n readonly providerTrust: LocalProviderTrust;\n readonly cloudUploadConsent: boolean;\n readonly defaultSensitivity: Sensitivity;\n}\n\nconst DEFAULT_LAYER_CAPS: Readonly<\n Record<keyof Required<NonNullable<ContextEngineConfig['layers']>>, number | undefined>\n> = {\n identity: undefined,\n memoryMetadata: undefined,\n activeRules: undefined,\n activeSkills: undefined,\n workingBlocks: undefined,\n autoRecall: undefined,\n};\n\nlet compactionIneffectiveWarned = false;\nlet heuristicCounterWarned = false;\n\n/** Emit the \"compaction enabled but ineffective\" warning at most once (CE-12). */\nfunction warnCompactionIneffective(message: string): void {\n if (compactionIneffectiveWarned) return;\n compactionIneffectiveWarned = true;\n process.stderr.write(`[graphorin/memory] ${message}\\n`);\n}\n\n/**\n * Test-only - reset the one-time CE-12 compaction warning so a test can assert\n * it fires.\n *\n * @internal\n */\nexport function _resetCompactionWarningForTesting(): void {\n compactionIneffectiveWarned = false;\n}\n\n/** @internal - test seam for the one-time heuristic-counter warning (CE-13). */\nexport function _resetHeuristicCounterWarningForTesting(): void {\n heuristicCounterWarned = false;\n}\n\n/**\n * Emission order for the assembled layers - deliberately **distinct from the\n * truncation priority ladder** (CE-9). Allocation still trims by\n * `DEFAULT_LAYER_PRIORITY` (lowest priority first), but layers are *emitted* in\n * this order so the volatile blocks that change every turn (`memoryMetadata`'s\n * counts, `autoRecall`'s injected facts) sit **after** the stable Layer 1-4\n * prefix (identity / rules / blocks / skills). That keeps the provider's - and a\n * local llama.cpp / vLLM server's - KV-cache breakpoint real: the prefix stays\n * byte-identical across turns even as the message count and recalled facts move.\n */\nconst LAYER_EMIT_ORDER: Readonly<Record<LayerAllocation['id'], number>> = Object.freeze({\n identity: 0,\n activeRules: 1,\n workingBlocks: 2,\n activeSkills: 3,\n // --- KV-cache breakpoint: everything below changes per turn ---\n memoryMetadata: 4,\n autoRecall: 5,\n});\n\n/**\n * Build a ContextEngine instance from the supplied configuration.\n *\n * @stable\n */\nexport function createContextEngine(config: ContextEngineConfig = {}): ContextEngine {\n const memoryBaseMode = config.memoryBaseMode ?? 'full';\n const localeInput = config.locale;\n const localePack: ContextLocalePack = resolvePackInput(localeInput);\n const localeId = localePack.id;\n const layerCfg = config.layers ?? {};\n const layersEnabled: Record<string, boolean> = {\n identity: layerCfg.identity?.enabled ?? true,\n memoryMetadata: layerCfg.memoryMetadata?.enabled ?? true,\n activeRules: layerCfg.activeRules?.enabled ?? true,\n activeSkills: layerCfg.activeSkills?.enabled ?? true,\n workingBlocks: layerCfg.workingBlocks?.enabled ?? true,\n autoRecall: layerCfg.autoRecall?.enabled ?? true,\n };\n const layerCaps: Record<string, number | undefined> = {\n identity: layerCfg.identity?.cap ?? DEFAULT_LAYER_CAPS.identity,\n memoryMetadata: layerCfg.memoryMetadata?.cap ?? DEFAULT_LAYER_CAPS.memoryMetadata,\n activeRules: layerCfg.activeRules?.cap ?? DEFAULT_LAYER_CAPS.activeRules,\n activeSkills: layerCfg.activeSkills?.cap ?? DEFAULT_LAYER_CAPS.activeSkills,\n workingBlocks: layerCfg.workingBlocks?.cap ?? DEFAULT_LAYER_CAPS.workingBlocks,\n autoRecall: layerCfg.autoRecall?.cap ?? DEFAULT_LAYER_CAPS.autoRecall,\n };\n const factsAutoRecall = config.factsAutoRecall ?? false;\n const reservedForResponse = config.reservedForResponse ?? 4096;\n const reservedForCompaction = config.reservedForCompaction ?? 8192;\n const maxContextTokens = config.maxContextTokens ?? Number.POSITIVE_INFINITY;\n\n const tokenCounter: ContextTokenCounter = config.tokenCounter\n ? 'count' in config.tokenCounter\n ? adaptTokenCounter(config.tokenCounter)\n : (config.tokenCounter as ContextTokenCounter)\n : HEURISTIC_TOKEN_COUNTER;\n // CE-13: budgeting against a real provider window with the heuristic\n // counter is approximate - say so once instead of failing silently\n // late (the heuristic's failure mode is a provider context-length\n // error before compaction fires).\n if (\n config.tokenCounter === undefined &&\n typeof config.providerContextWindow === 'number' &&\n !heuristicCounterWarned\n ) {\n heuristicCounterWarned = true;\n process.stderr.write(\n '[graphorin/memory] context-engine token counts use the built-in heuristic (chars/4 + dense-script). For production budgeting against a real provider window, pass `contextEngine.tokenCounter` (e.g. the provider package JsTiktokenCounter).\\n',\n );\n }\n\n const privacy = config.privacy ?? {};\n const defaultSensitivity: Sensitivity = privacy.defaultSensitivity ?? 'internal';\n const providerTrust: LocalProviderTrust = privacy.providerTrust ?? 'public-tls';\n const cloudUploadConsent = privacy.cloudUploadConsent ?? false;\n const heuristicStrategy = defaultLocaleHeuristicStrategy(localePack);\n\n // Compaction config resolution.\n const compactionInput = config.compaction;\n const compactionAutoDefault = resolveAutoCompactionDefault(providerTrust);\n const compactionEnabled =\n compactionInput === false\n ? false\n : compactionInput === undefined\n ? compactionAutoDefault === 'enabled'\n : compactionInput.trigger !== 'never';\n const providerContextWindow = config.providerContextWindow ?? null;\n const triggerSpec =\n compactionInput === false || compactionInput === undefined\n ? undefined\n : compactionInput.trigger;\n const compactionThresholdTokens =\n compactionEnabled && providerContextWindow !== null\n ? resolveTriggerThreshold({\n contextWindow: providerContextWindow,\n ...(triggerSpec !== undefined ? { trigger: triggerSpec } : {}),\n reservedForResponse,\n reservedForCompaction,\n })\n : Number.POSITIVE_INFINITY;\n // CE-12: compaction enabled without a `providerContextWindow` leaves the\n // threshold at Infinity, so `shouldCompact` returns false forever - a\n // silently-dead default-on protection. Surface it: throw if the operator\n // explicitly configured compaction, warn (once) if it is on by the default\n // trust policy. Auto-detecting the window from the provider is not\n // implemented.\n const compactionEffective = compactionEnabled && providerContextWindow !== null;\n if (compactionEnabled && providerContextWindow === null) {\n const message =\n 'context-engine compaction is enabled but `providerContextWindow` is not set, so the ' +\n 'trigger threshold is Infinity and compaction will never fire. Pass `providerContextWindow` ' +\n \"(your model's context window, in tokens) - auto-detection from the provider is not implemented.\";\n if (compactionInput !== undefined && compactionInput !== false) {\n throw new Error(`[graphorin/memory] ${message}`);\n }\n warnCompactionIneffective(message);\n }\n const compactionStrategy: CompactionStrategy =\n compactionInput === false ||\n compactionInput === undefined ||\n compactionInput.strategy === undefined\n ? {\n kind: 'summarize-old-preserve-recent',\n preserveRecentTurns: 6,\n templateName: 'summary-sections',\n }\n : compactionInput.strategy;\n // SOTA-4 reclaim-floor: defer a compaction whose older (compactable) portion\n // is below this floor (read from the trigger config; 0 = off, byte-identical).\n const compactionMinReclaimTokens =\n triggerSpec !== undefined && triggerSpec !== 'never'\n ? Math.max(0, triggerSpec.minReclaimTokens ?? 0)\n : 0;\n // How many recent turns the active strategy preserves (the reclaimable portion\n // is everything before them).\n const reclaimPreserveTurns =\n compactionStrategy.kind === 'summarize-old-preserve-recent'\n ? (compactionStrategy.preserveRecentTurns ?? DEFAULT_PRESERVE_RECENT_TURNS)\n : compactionStrategy.kind === 'clear-old-tool-results' &&\n typeof compactionStrategy.summarizeFallback === 'object'\n ? (compactionStrategy.summarizeFallback.preserveRecentTurns ??\n DEFAULT_PRESERVE_RECENT_TURNS)\n : DEFAULT_PRESERVE_RECENT_TURNS;\n const compactionHooks: ReadonlyArray<NamedPostCompactionHook> = resolveDefaultHooks(\n compactionInput === false || compactionInput === undefined\n ? undefined\n : compactionInput.postCompactionHooks,\n );\n const summarizer = config.summarizer;\n const now = config.now ?? Date.now;\n\n const resolvedConfig: ResolvedContextEngineConfig = Object.freeze({\n memoryBaseMode,\n localeId,\n maxContextTokens,\n reservedForResponse,\n reservedForCompaction,\n compactionEnabled,\n compactionEffective,\n compactionThresholdTokens,\n providerContextWindow,\n providerTrust,\n cloudUploadConsent,\n defaultSensitivity,\n });\n\n async function assemble(memory: Memory, input: AssembleInput): Promise<AssembledPrompt> {\n // Layer 1 - base template.\n const layer1Text = layersEnabled.identity ? composeLayer1(localePack, memoryBaseMode) : '';\n // Layer 2 - agent instructions.\n const layer2Text = composeLayer2(input.agentInstructions);\n\n // Layer 3 - working blocks (filter D2).\n const blocks = await memory.working.list(input.scope);\n const blocksKept: Array<(typeof blocks)[number]> = [];\n const privacyCounters: Record<PrivacyDecisionReason, number> = {\n allowed: 0,\n 'no-cloud-upload-consent': 0,\n 'provider-rejects-internal': 0,\n 'provider-rejects-secret': 0,\n };\n for (const block of blocks) {\n const decision = privacyDecide(block.sensitivity, {\n ...(privacy.providerAcceptsSensitivity !== undefined\n ? { providerAcceptsSensitivity: privacy.providerAcceptsSensitivity }\n : {}),\n providerTrust,\n cloudUploadConsent,\n defaultSensitivity,\n });\n privacyCounters[decision.reason] += 1;\n if (decision.decision === 'pass') blocksKept.push(block);\n }\n const layer3Text = layersEnabled.workingBlocks ? renderWorkingBlocks(blocksKept) : '';\n\n // Layer 4 - procedural rules + skills (filter D2 on rules).\n const rules = await memory.procedural.activate(input.scope, input.proceduralActivation ?? {});\n const rulesKept: Array<(typeof rules)[number]> = [];\n for (const rule of rules) {\n const decision = privacyDecide(rule.sensitivity, {\n ...(privacy.providerAcceptsSensitivity !== undefined\n ? { providerAcceptsSensitivity: privacy.providerAcceptsSensitivity }\n : {}),\n providerTrust,\n cloudUploadConsent,\n defaultSensitivity,\n });\n privacyCounters[decision.reason] += 1;\n if (decision.decision === 'pass') rulesKept.push(rule);\n }\n const layer4RulesText = layersEnabled.activeRules ? renderProceduralRules(rulesKept) : '';\n const layer4SkillsText = layersEnabled.activeSkills\n ? composeLayer4Skills(input.skills ?? [])\n : '';\n\n // Layer 5 - memory metadata.\n const meta = await memory.metadata(input.scope);\n const layer5Text = layersEnabled.memoryMetadata\n ? renderMetadataBlock(enrichMetadataTags(meta, localeId, memory.embedderId()))\n : '';\n\n // Layer 6 - auto-recall.\n let autoRecall: AutoRecallTriggerResult = { factsTriggered: false };\n let layer6Text = '';\n if (factsAutoRecall !== false && layersEnabled.autoRecall) {\n const strategy =\n input.autoRecallStrategyOverride ?? factsAutoRecall.strategy ?? heuristicStrategy;\n autoRecall = strategy({\n locale: localeId,\n lastUserMessage: input.lastUserMessage ?? '',\n });\n if (autoRecall.factsTriggered) {\n const topK = factsAutoRecall.topK ?? layerCfg.autoRecall?.topK ?? 5;\n // CE-4: default 0 - rank-based `topK` already bounds the injected\n // volume, and the threshold's scale is reranker-dependent (the default\n // RRF reranker fuses 2 candidate lists, so scores top out near\n // `2/(60+1) ≈ 0.033` and any positive default would silently drop\n // everything). Operators tuning against a known reranker scale can pass\n // an explicit `threshold`.\n const threshold = factsAutoRecall.threshold ?? layerCfg.autoRecall?.threshold ?? 0;\n const hits = await memory.semantic\n .search(input.scope, input.lastUserMessage ?? '', { topK })\n .catch(() => []);\n const facts: Fact[] = [];\n for (const hit of hits) {\n if (hit.score < threshold) continue;\n const decision = privacyDecide(hit.record.sensitivity, {\n ...(privacy.providerAcceptsSensitivity !== undefined\n ? { providerAcceptsSensitivity: privacy.providerAcceptsSensitivity }\n : {}),\n providerTrust,\n cloudUploadConsent,\n defaultSensitivity,\n });\n privacyCounters[decision.reason] += 1;\n if (decision.decision === 'pass') facts.push(hit.record);\n }\n layer6Text = renderAutoRecalledFacts(facts);\n }\n }\n\n // Token-budget allocation. Layer 1 (`graphorin_memory_base`) and\n // Layer 2 (`agent_instructions`) are concatenated into the\n // single `identity` candidate so they share a priority slot;\n // they are joined with a blank line so the assembled prompt is\n // readable.\n const identityText =\n layer1Text.length > 0 && layer2Text.length > 0\n ? `${layer1Text}\\n\\n${layer2Text}`\n : layer1Text + layer2Text;\n const candidates: LayerCandidate[] = [\n buildCandidate('identity', identityText, layerCaps.identity),\n buildCandidate('memoryMetadata', layer5Text, layerCaps.memoryMetadata),\n buildCandidate('activeRules', layer4RulesText, layerCaps.activeRules),\n buildCandidate('workingBlocks', layer3Text, layerCaps.workingBlocks),\n buildCandidate('activeSkills', layer4SkillsText, layerCaps.activeSkills),\n buildCandidate('autoRecall', layer6Text, layerCaps.autoRecall),\n ].filter((c) => c.text.length > 0);\n\n const allocation = await allocateLayers(candidates, maxContextTokens, tokenCounter);\n\n // D4 inbound preamble - fires on steps containing untrusted upstream parts.\n const preambleFired = shouldFireInboundPreamble(input.upstreamAnnotations ?? []);\n const preambleText = preambleFired ? composeInboundPreamble(localePack) : '';\n\n // CE-9: emit in stability order (Layer 1-4 prefix, then the cache\n // breakpoint, then the volatile metadata / auto-recall), NOT in the\n // truncation-priority order `allocation.layers` arrives in.\n const assembledLayers = allocation.layers\n .filter((l) => l.text.length > 0)\n .sort((a, b) => LAYER_EMIT_ORDER[a.id] - LAYER_EMIT_ORDER[b.id]);\n const finalParts: string[] = assembledLayers.map((l) => l.text);\n if (preambleText.length > 0) finalParts.push(preambleText);\n const systemContent = finalParts.join('\\n\\n');\n\n // Annotations - one per assembled fragment, in the same order\n // as `finalParts` so observers can correlate.\n const annotations: AnnotatedPart[] = assembledLayers.map((layer) => ({\n content: { type: 'text', text: layer.text } as MessageContent,\n annotation: annotationForLayer(layer),\n }));\n if (preambleText.length > 0) {\n annotations.push({\n content: { type: 'text', text: preambleText } as MessageContent,\n annotation: annotate('system:framework', 'n/a'),\n });\n }\n\n return Object.freeze({\n systemMessage: Object.freeze({ role: 'system' as const, content: systemContent }),\n annotations: Object.freeze(annotations),\n layerAllocation: allocation,\n inboundPreambleFired: preambleFired,\n privacyCounters: Object.freeze(privacyCounters),\n localeId,\n memoryBaseMode,\n autoRecall,\n });\n }\n\n // CE-7 anti-thrash: after a compaction whose afterTokens still sits at\n // or above the trigger threshold (e.g. huge tool results among the\n // preserved turns), an immediate re-trigger would summarize the\n // previous summary - spend with no reclaim. Track the last outcome and\n // require the buffer to have GROWN past it before firing again.\n let lastCompactionAfterTokens: number | null = null;\n const REARM_GROWTH_TOKENS = 256;\n\n // C4 (context-engine-06/07 hardening): a persistently-failing summarizer\n // previously re-fired an LLM call at the top of EVERY step (the\n // anti-thrash guard arms only on success). Count consecutive failures -\n // including \"successful\" passes that did not actually shrink the buffer\n // - retry each pass once with a short backoff, and after\n // MAX_CONSECUTIVE_COMPACTION_FAILURES disable the AUTO trigger until a\n // later compactNow (e.g. a manual compact with a fixed summarizer)\n // succeeds and re-arms it.\n let consecutiveCompactionFailures = 0;\n let autoCompactionDisabledByFailures = false;\n const MAX_CONSECUTIVE_COMPACTION_FAILURES = 3;\n const COMPACTION_RETRY_BACKOFF_MS = 250;\n\n function recordCompactionFailure(reason: string): void {\n consecutiveCompactionFailures += 1;\n if (\n consecutiveCompactionFailures >= MAX_CONSECUTIVE_COMPACTION_FAILURES &&\n !autoCompactionDisabledByFailures\n ) {\n autoCompactionDisabledByFailures = true;\n process.stderr.write(\n `[graphorin/memory] auto-compaction disabled after ${consecutiveCompactionFailures} consecutive failed passes (last: ${reason}). Manual compactNow() still runs and re-enables the trigger on success.\\n`,\n );\n }\n }\n\n async function shouldCompact(\n messages: ReadonlyArray<Message>,\n options: {\n readonly precomputedTokens?: number;\n readonly compactableFromIndex?: number;\n } = {},\n ): Promise<boolean> {\n if (!compactionEnabled) return false;\n if (autoCompactionDisabledByFailures) return false;\n if (compactionThresholdTokens === Number.POSITIVE_INFINITY) return false;\n const total = options.precomputedTokens ?? (await countMessageTokens(messages, tokenCounter));\n if (total < compactionThresholdTokens) return false;\n if (\n lastCompactionAfterTokens !== null &&\n total <= lastCompactionAfterTokens + REARM_GROWTH_TOKENS\n ) {\n return false;\n }\n // SOTA-4 reclaim-floor: skip when the older (compactable) portion is too\n // small to be worth a summarizer call - avoids compact-thrash at the\n // threshold. Counts only the older slice; cheap relative to the avoided\n // call. context-engine-04: the caller's pinned system prefix\n // (`compactableFromIndex`) is NOT reclaimable and must not be counted -\n // a 10k-token prefix would otherwise satisfy any floor while the body\n // holds near-zero reclaimable tokens.\n if (compactionMinReclaimTokens > 0) {\n const from = Math.max(0, Math.min(options.compactableFromIndex ?? 0, messages.length));\n const olderCount = Math.max(from, messages.length - reclaimPreserveTurns);\n if (olderCount <= from) return false;\n const olderTokens = await countMessageTokens(messages.slice(from, olderCount), tokenCounter);\n if (olderTokens < compactionMinReclaimTokens) return false;\n }\n return true;\n }\n\n async function compactNow(callInput: {\n readonly scope: SessionScope;\n readonly runId: string;\n readonly sessionId: string;\n readonly agentId: string;\n readonly source: CompactionSource;\n readonly messages: ReadonlyArray<Message>;\n readonly memory: Memory;\n readonly summarizer?: CompactionSummarizer;\n /** Per-call override of the strategy's preserve-recent count (CE-3). */\n readonly preserveRecentTurns?: number;\n /** Topic/tags narrowing for the procedural-rules re-anchor hook (CE-6). */\n readonly procedural?: { readonly topic?: string; readonly tags?: ReadonlyArray<string> };\n /** The caller's pinned system prefix - accounting only (context-engine-04). */\n readonly prefixMessages?: ReadonlyArray<Message>;\n readonly signal?: AbortSignal;\n }): Promise<{\n readonly result: CompactionResult;\n readonly extraContent: ReadonlyArray<MessageContent>;\n readonly hookFailures: ReadonlyArray<{ readonly hookName: string; readonly reason: string }>;\n }> {\n const activeSummarizer = callInput.summarizer ?? summarizer;\n if (activeSummarizer === undefined) {\n throw new TypeError(\n '[graphorin/memory] ContextEngine.compactNow: no summarizer configured. ' +\n 'Pass `summarizer` to createContextEngine({...}) or to compactNow({...}).',\n );\n }\n const compactionInputCall: ExecuteCompactionInput = {\n messages: callInput.messages,\n source: callInput.source,\n strategy:\n callInput.preserveRecentTurns !== undefined &&\n compactionStrategy.kind === 'summarize-old-preserve-recent'\n ? { ...compactionStrategy, preserveRecentTurns: callInput.preserveRecentTurns }\n : compactionStrategy,\n localePack,\n summarizer: activeSummarizer,\n tokenCounter,\n thresholdTokens: compactionThresholdTokens,\n runId: callInput.runId,\n sessionId: callInput.sessionId,\n agentId: callInput.agentId,\n scope: callInput.scope,\n providerTrust,\n now,\n ...(callInput.signal !== undefined ? { signal: callInput.signal } : {}),\n };\n // C4: one retry with a short backoff on summarizer failure, then a\n // strictly-smaller-than-input assert - a pass that dropped messages\n // yet did not shrink the buffer is a failure (a looping/echoing\n // summarizer), not a success to arm the anti-thrash guard with.\n let result: CompactionResult;\n try {\n result = await executeCompaction(compactionInputCall);\n } catch (firstError) {\n if (callInput.signal?.aborted === true) throw firstError;\n await new Promise<void>((resolve) => setTimeout(resolve, COMPACTION_RETRY_BACKOFF_MS));\n try {\n result = await executeCompaction(compactionInputCall);\n } catch (secondError) {\n recordCompactionFailure(\n secondError instanceof Error ? secondError.message : String(secondError),\n );\n throw secondError;\n }\n }\n if (result.droppedMessageIndices.length > 0 && result.afterTokens >= result.beforeTokens) {\n const reason = `compaction did not shrink the buffer (${result.beforeTokens} -> ${result.afterTokens} tokens)`;\n if (callInput.source === 'auto-trigger') {\n // The auto loop must never keep paying for passes that grow the\n // buffer (the Gemini-CLI compression-loop class) - fail the pass.\n recordCompactionFailure(reason);\n throw new Error(`[graphorin/memory] ${reason}`);\n }\n // An operator-requested compaction of a small window can\n // legitimately cost more than it reclaims (the summary skeleton\n // has a floor) - warn, hand back the result, count nothing.\n process.stderr.write(`[graphorin/memory] ${reason} (source: ${callInput.source}).\\n`);\n } else if (result.droppedMessageIndices.length > 0) {\n // A pass that actually reclaimed space re-arms the auto trigger.\n consecutiveCompactionFailures = 0;\n if (autoCompactionDisabledByFailures) {\n autoCompactionDisabledByFailures = false;\n process.stderr.write(\n '[graphorin/memory] auto-compaction re-enabled after a successful pass.\\n',\n );\n }\n }\n // C4: hand hooks the DROPPED message content (not just indices) so\n // re-anchoring hooks like reanchorRecentResults can recover the\n // result handles that just left the window. Reference-diff against\n // trimmedMessages (both strategies carry surviving originals by\n // reference; the per-strategy index spaces differ, so indices are\n // not usable here).\n const survivors = new Set(result.trimmedMessages);\n const droppedMessages = callInput.messages.filter((m) => !survivors.has(m));\n const ctx = {\n result,\n scope: callInput.scope,\n runId: callInput.runId,\n sessionId: callInput.sessionId,\n agentId: callInput.agentId,\n source: callInput.source,\n droppedMessages,\n };\n const hookFailures: Array<{ readonly hookName: string; readonly reason: string }> = [];\n const extraContent: MessageContent[] = [];\n let hooksFired = 0;\n // context-engine-02: the same D2 privacy decision `assemble()` applies\n // to blocks / rules / facts, handed to the hooks - their output is\n // spliced into the buffer and shipped to the provider, so it must obey\n // the same filter or secret-tier content leaks on the first compaction.\n const allowSensitivity = (sensitivity: Sensitivity | undefined): boolean =>\n privacyDecide(sensitivity, {\n ...(privacy.providerAcceptsSensitivity !== undefined\n ? { providerAcceptsSensitivity: privacy.providerAcceptsSensitivity }\n : {}),\n providerTrust,\n cloudUploadConsent,\n defaultSensitivity,\n }).decision === 'pass';\n for (const hook of compactionHooks) {\n try {\n // CE-6: hooks receive the REAL compaction context - the old code\n // built `ctx` and then `void ctx;`-discarded it while the\n // function-form wrapper fabricated a zeroed result.\n const parts = await hook.resolveContent(\n {\n memory: callInput.memory,\n scope: callInput.scope,\n ...(callInput.procedural !== undefined ? { procedural: callInput.procedural } : {}),\n allowSensitivity,\n },\n ctx,\n );\n extraContent.push(...parts);\n hooksFired += 1;\n } catch (err) {\n hookFailures.push({\n hookName: hook.id,\n reason: err instanceof Error ? err.name : 'UnknownError',\n });\n }\n }\n const enrichedResult: CompactionResult = Object.freeze({\n ...result,\n hooksFiredCount: hooksFired,\n });\n // CE-7: arm the anti-thrash guard and surface the failure mode where\n // compaction could not get under the trigger threshold.\n //\n // context-engine-04: `shouldCompact` compares the FULL buffer total\n // (pinned prefix included) against this baseline, so the baseline must\n // be full-basis too: body afterTokens + the caller's pinned prefix +\n // the Context-Essentials message the caller splices in. Arming with\n // the body-only number let any real system prompt (> 256 tokens)\n // defeat the guard, re-firing a summarizer LLM call at the top of\n // EVERY step whenever compaction could not get under the threshold.\n const prefixTokens =\n callInput.prefixMessages !== undefined && callInput.prefixMessages.length > 0\n ? await countMessageTokens(callInput.prefixMessages, tokenCounter)\n : 0;\n let essentialsTokens = 0;\n for (const part of extraContent) {\n if (part.type === 'text') essentialsTokens += await tokenCounter.countText(part.text);\n }\n const fullAfterTokens = enrichedResult.afterTokens + prefixTokens + essentialsTokens;\n lastCompactionAfterTokens = fullAfterTokens;\n if (\n compactionThresholdTokens !== Number.POSITIVE_INFINITY &&\n fullAfterTokens >= compactionThresholdTokens\n ) {\n process.stderr.write(\n `[graphorin/memory] compaction finished at ${fullAfterTokens} tokens (body ${enrichedResult.afterTokens} + pinned prefix ${prefixTokens} + essentials ${essentialsTokens}) - still at/above the ${compactionThresholdTokens}-token trigger (oversized preserved turns?). The immediate re-trigger is suppressed until the buffer grows.\\n`,\n );\n }\n return Object.freeze({\n result: enrichedResult,\n extraContent: Object.freeze(extraContent),\n hookFailures: Object.freeze(hookFailures),\n });\n }\n\n return Object.freeze({\n assemble,\n shouldCompact,\n compactNow,\n config(): ResolvedContextEngineConfig {\n return resolvedConfig;\n },\n });\n}\n\nfunction buildCandidate(\n id: LayerCandidate['id'],\n text: string,\n cap: number | undefined,\n): LayerCandidate {\n if (cap !== undefined) return { id, text, cap };\n return { id, text };\n}\n\nfunction annotationForLayer(layer: LayerAllocation): ContentAnnotation {\n switch (layer.id) {\n case 'identity':\n // Identity merges the framework base (Layer 1) + the user-defined\n // agent_instructions (Layer 2) into one trusted fragment, tagged\n // `system:framework` so D3 skips re-scanning it under\n // `scanScope: 'untrusted'`. (Both halves are first-party prompt text, so\n // the merged layer carries a single framework trust tag - `LayerAllocation`\n // does not surface which halves were present.)\n return annotate('system:framework', 'n/a');\n case 'memoryMetadata':\n case 'activeRules':\n case 'workingBlocks':\n case 'activeSkills':\n case 'autoRecall':\n return annotate('memory:tier-filtered', 'n/a');\n default:\n return annotate('system:framework', 'n/a');\n }\n}\n\nfunction renderWorkingBlocks(\n blocks: ReadonlyArray<{\n readonly label: string;\n readonly value: string;\n readonly description?: string;\n }>,\n): string {\n if (blocks.length === 0) return '';\n const lines = ['<memory_blocks>'];\n for (const block of blocks) {\n const description =\n block.description !== undefined ? ` description=\"${escapeXmlAttr(block.description)}\"` : '';\n lines.push(` <block label=\"${escapeXmlAttr(block.label)}\"${description}>`);\n lines.push(` ${escapeXmlText(block.value)}`);\n lines.push(' </block>');\n }\n lines.push('</memory_blocks>');\n return lines.join('\\n');\n}\n\nfunction renderProceduralRules(\n rules: ReadonlyArray<{ readonly text: string; readonly priority: number }>,\n): string {\n if (rules.length === 0) return '';\n const lines = ['<memory_rules>'];\n for (const rule of rules) {\n lines.push(` <rule priority=\"${rule.priority}\">${escapeXmlText(rule.text)}</rule>`);\n }\n lines.push('</memory_rules>');\n return lines.join('\\n');\n}\n\nfunction renderAutoRecalledFacts(facts: ReadonlyArray<Fact>): string {\n if (facts.length === 0) return '';\n const lines = ['<auto_recalled_facts>'];\n for (const fact of facts) {\n const tagsAttr =\n fact.tags !== undefined ? ` tags=\"${escapeXmlAttr((fact.tags ?? []).join(','))}\"` : '';\n lines.push(\n ` <fact id=\"${escapeXmlAttr(fact.id)}\"${tagsAttr}>${escapeXmlText(fact.text)}</fact>`,\n );\n }\n lines.push('</auto_recalled_facts>');\n return lines.join('\\n');\n}\n\nfunction escapeXmlAttr(value: string): string {\n return value\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;');\n}\n\nfunction escapeXmlText(value: string): string {\n return value.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');\n}\n\nfunction resolvePackInput(input: ContextEngineConfig['locale']): ContextLocalePack {\n if (input === undefined) return enLocalePack;\n if (typeof input === 'string') {\n if (input === enLocalePack.id) return enLocalePack;\n return resolveLocalePack({ id: input });\n }\n return resolveLocalePack(input);\n}\n\nfunction resolveDefaultHooks(\n input: ReadonlyArray<PostCompactionHook> | ReadonlyArray<NamedPostCompactionHook> | undefined,\n): ReadonlyArray<NamedPostCompactionHook> {\n if (input === undefined) {\n return Object.freeze([\n reanchorProjectRules(),\n reanchorPersonaBlock(),\n reanchorPinnedFacts({ pinnedFactIds: [] }),\n ]);\n }\n return Object.freeze(\n input.map((hook, idx): NamedPostCompactionHook => {\n if (typeof hook === 'function') {\n const id = `customHook_${idx}`;\n return {\n id,\n async resolveContent(_deps, ctx) {\n // CE-6: the operator's hook sees the genuine compaction\n // context. `ctx` is always supplied by compactNow; the\n // throw guards a direct caller that forgot it rather than\n // silently fabricating zeros (the old behaviour).\n if (ctx === undefined) {\n throw new TypeError(\n '[graphorin/memory] post-compaction hooks require the compaction context - call through ContextEngine.compactNow(...).',\n );\n }\n const result = await hook(ctx);\n return result;\n },\n };\n }\n return hook;\n }),\n );\n}\n\n/**\n * Augment a {@link MemoryMetadata} snapshot with the active locale +\n * embedder tags so the rendered metadata block carries the\n * additional context the model uses for reasoning. Pure: the\n * original `meta` reference is not mutated.\n */\nfunction enrichMetadataTags(\n meta: import('@graphorin/core').MemoryMetadata,\n localeId: string,\n embedderId: string | null,\n): import('@graphorin/core').MemoryMetadata {\n const baseTags = meta.tags !== undefined ? [...meta.tags] : [];\n if (!baseTags.some((tag) => tag.startsWith('locale:'))) {\n baseTags.push(`locale:${localeId}`);\n }\n if (embedderId !== null && !baseTags.some((tag) => tag.startsWith('embedder:'))) {\n baseTags.push(`embedder:${embedderId}`);\n }\n return { ...meta, tags: Object.freeze(baseTags) };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"engine.js","names":["DEFAULT_LAYER_CAPS: Readonly<\n Record<keyof Required<NonNullable<ContextEngineConfig['layers']>>, number | undefined>\n>","LAYER_EMIT_ORDER: Readonly<Record<LayerAllocation['id'], number>>","localePack: ContextLocalePack","layersEnabled: Record<string, boolean>","layerCaps: Record<string, number | undefined>","tokenCounter: ContextTokenCounter","defaultSensitivity: Sensitivity","providerTrust: LocalProviderTrust","compactionStrategy: CompactionStrategy","compactionHooks: ReadonlyArray<NamedPostCompactionHook>","resolvedConfig: ResolvedContextEngineConfig","blocksKept: Array<(typeof blocks)[number]>","privacyCounters: Record<PrivacyDecisionReason, number>","privacyDecide","rulesKept: Array<(typeof rules)[number]>","autoRecall: AutoRecallTriggerResult","facts: Fact[]","allocateLayers","finalParts: string[]","annotations: AnnotatedPart[]","lastCompactionAfterTokens: number | null","compactionInputCall: ExecuteCompactionInput","result: CompactionResult","hookFailures: Array<{ readonly hookName: string; readonly reason: string }>","extraContent: MessageContent[]","enrichedResult: CompactionResult"],"sources":["../../src/context-engine/engine.ts"],"sourcesContent":["/**\n * `ContextEngine` - the layered six-layer system prompt assembler.\n *\n * Combines:\n *\n * - Layer 1 (`graphorin_memory_base`) educational template\n * - Layer 2 user-defined `agent_instructions`\n * - Layer 3 working-memory blocks (filtered through D2 privacy)\n * - Layer 4 procedural rules + skill metadata cards\n * - Layer 5 memory-metadata counters\n * - Layer 6 opt-in auto-recall\n *\n * Cross-cuts:\n *\n * - D2 privacy filter (sensitivity-tier drop)\n * - D3 cooperation contract (`ContentOrigin` annotation)\n * - D4 inbound preamble injection (post cache-breakpoint)\n * - RB-44 per-step tool-catalogue cardinality allocator (separate axis)\n * - RB-46 in-flight session message-history compaction (separate axis)\n *\n * @packageDocumentation\n */\n\nimport type {\n Fact,\n LocalProviderTrust,\n Message,\n MessageContent,\n Sensitivity,\n SessionScope,\n TokenCounter,\n} from '@graphorin/core';\nimport type { ContextEngine, Memory } from '../memory-interface.js';\nimport { annotate, type ContentAnnotation, shouldFireInboundPreamble } from './annotations.js';\nimport {\n type AutoRecallStrategy,\n type AutoRecallTriggerResult,\n defaultLocaleHeuristicStrategy,\n} from './auto-recall.js';\nimport {\n DEFAULT_PRESERVE_RECENT_TURNS,\n type ExecuteCompactionInput,\n executeCompaction,\n} from './compaction/compactor.js';\nimport type { NamedPostCompactionHook } from './compaction/hooks/types.js';\nimport {\n reanchorPersonaBlock,\n reanchorPinnedFacts,\n reanchorProjectRules,\n} from './compaction/index.js';\nimport { resolveAutoCompactionDefault, resolveTriggerThreshold } from './compaction/thresholds.js';\nimport type {\n CompactionConfig,\n CompactionResult,\n CompactionSource,\n CompactionStrategy,\n CompactionSummarizer,\n PostCompactionHook,\n} from './compaction/types.js';\nimport type {\n AnnotatedPart,\n AssembledPrompt,\n AssembleInput,\n ResolvedContextEngineConfig,\n} from './io-types.js';\nimport {\n type ContextLocalePack,\n enLocalePack,\n type PartialContextLocalePack,\n} from './locale-packs/index.js';\nimport { resolveLocalePack } from './locale-packs/resolver.js';\nimport { renderMetadataBlock } from './metadata.js';\nimport { type PrivacyDecisionReason, decide as privacyDecide } from './privacy-filter.js';\nimport {\n composeInboundPreamble,\n composeLayer1,\n composeLayer2,\n composeLayer4Skills,\n type MemoryBaseMode,\n} from './templates/composer.js';\nimport {\n allocate as allocateLayers,\n type LayerAllocation,\n type LayerCandidate,\n} from './token-budget.js';\nimport {\n adaptTokenCounter,\n type ContextTokenCounter,\n countMessageTokens,\n HEURISTIC_TOKEN_COUNTER,\n} from './token-counter.js';\n\n/**\n * Per-layer cap configuration. Mirrors the documented\n * `ContextEngineConfig.layers.*` fields.\n *\n * @stable\n */\nexport interface LayerConfig {\n readonly enabled?: boolean;\n readonly cap?: number;\n}\n\n/**\n * Auto-recall config knob. `false` disables; `{ topK }` enables\n * the heuristic with a bounded top-K.\n *\n * @stable\n */\nexport type AutoRecallConfig =\n | false\n | {\n readonly topK?: number;\n /**\n * Minimum fused score a hit must reach to be injected. **Default `0`**\n * (CE-4) - `topK` already bounds the volume. The scale is\n * reranker-dependent: the default RRF reranker fuses the FTS + vector\n * candidate lists as `1/(60 + rank)` per list, so scores top out near\n * `2/(60 + 1) ≈ 0.033` - any positive default would silently drop every\n * hit. Set this only when calibrating against a known reranker's scale.\n */\n readonly threshold?: number;\n readonly strategy?: AutoRecallStrategy;\n };\n\n/**\n * Privacy block of the engine config.\n *\n * @stable\n */\nexport interface PrivacyConfig {\n readonly cloudUploadConsent?: boolean;\n readonly defaultSensitivity?: Sensitivity;\n readonly providerAcceptsSensitivity?: ReadonlyArray<Sensitivity>;\n readonly providerTrust?: LocalProviderTrust;\n}\n\n/**\n * Configuration accepted by {@link createContextEngine}.\n *\n * @stable\n */\nexport interface ContextEngineConfig {\n /**\n * Layer 1 base-template mode. `'full'` (default) ships the\n * verbose ~250-350 token narrative aimed at general LLMs;\n * `'minimal'` opts top-tier models into the ~80-120 token\n * compact form.\n */\n readonly memoryBaseMode?: MemoryBaseMode;\n /** Default `'en'`. Pluggable via `defineContextLocalePack`. */\n readonly locale?: string | ContextLocalePack | PartialContextLocalePack;\n /** Per-layer enable / cap overrides. */\n readonly layers?: {\n readonly identity?: LayerConfig;\n readonly memoryMetadata?: LayerConfig;\n readonly activeRules?: LayerConfig;\n readonly activeSkills?: LayerConfig;\n readonly workingBlocks?: LayerConfig;\n readonly autoRecall?: LayerConfig & { readonly topK?: number; readonly threshold?: number };\n };\n /** Auto-recall trigger configuration. Default `false`. */\n readonly factsAutoRecall?: AutoRecallConfig;\n /** Privacy-filter configuration. */\n readonly privacy?: PrivacyConfig;\n /** Hard token budget. Default `Number.POSITIVE_INFINITY` (no global cap). */\n readonly maxContextTokens?: number;\n /** Tokens reserved for the model's response. Default `4096`. */\n readonly reservedForResponse?: number;\n /** Tokens reserved for the compaction summarizer call. Default `8192`. */\n readonly reservedForCompaction?: number;\n /** Pluggable token counter. Default heuristic (chars/4). */\n readonly tokenCounter?: TokenCounter | ContextTokenCounter;\n /** Auto-compaction configuration (RB-46). */\n readonly compaction?: false | CompactionConfig;\n /** Active provider's context window; required when compaction is enabled. */\n readonly providerContextWindow?: number;\n /** Default summarizer adapter the auto-trigger uses. */\n readonly summarizer?: CompactionSummarizer;\n /** Wall clock for tests + deterministic compaction. */\n readonly now?: () => number;\n}\n\n// The IO shapes (AssembleInput / AnnotatedPart / AssembledPrompt /\n// ResolvedContextEngineConfig) live in the io-types leaf and the\n// ContextEngine interface itself is co-located with `Memory` in\n// memory-interface.ts (issue #22 - the pair is mutually recursive).\n// Both are re-exported here so every existing import path keeps\n// working unchanged.\nexport type { ContextEngine } from '../memory-interface.js';\nexport type {\n AnnotatedPart,\n AssembledPrompt,\n AssembleInput,\n ResolvedContextEngineConfig,\n} from './io-types.js';\n\nconst DEFAULT_LAYER_CAPS: Readonly<\n Record<keyof Required<NonNullable<ContextEngineConfig['layers']>>, number | undefined>\n> = {\n identity: undefined,\n memoryMetadata: undefined,\n activeRules: undefined,\n activeSkills: undefined,\n workingBlocks: undefined,\n autoRecall: undefined,\n};\n\nlet compactionIneffectiveWarned = false;\nlet heuristicCounterWarned = false;\n\n/** Emit the \"compaction enabled but ineffective\" warning at most once (CE-12). */\nfunction warnCompactionIneffective(message: string): void {\n if (compactionIneffectiveWarned) return;\n compactionIneffectiveWarned = true;\n process.stderr.write(`[graphorin/memory] ${message}\\n`);\n}\n\n/**\n * Test-only - reset the one-time CE-12 compaction warning so a test can assert\n * it fires.\n *\n * @internal\n */\nexport function _resetCompactionWarningForTesting(): void {\n compactionIneffectiveWarned = false;\n}\n\n/** @internal - test seam for the one-time heuristic-counter warning (CE-13). */\nexport function _resetHeuristicCounterWarningForTesting(): void {\n heuristicCounterWarned = false;\n}\n\n/**\n * Emission order for the assembled layers - deliberately **distinct from the\n * truncation priority ladder** (CE-9). Allocation still trims by\n * `DEFAULT_LAYER_PRIORITY` (lowest priority first), but layers are *emitted* in\n * this order so the volatile blocks that change every turn (`memoryMetadata`'s\n * counts, `autoRecall`'s injected facts) sit **after** the stable Layer 1-4\n * prefix (identity / rules / blocks / skills). That keeps the provider's - and a\n * local llama.cpp / vLLM server's - KV-cache breakpoint real: the prefix stays\n * byte-identical across turns even as the message count and recalled facts move.\n */\nconst LAYER_EMIT_ORDER: Readonly<Record<LayerAllocation['id'], number>> = Object.freeze({\n identity: 0,\n activeRules: 1,\n workingBlocks: 2,\n activeSkills: 3,\n // --- KV-cache breakpoint: everything below changes per turn ---\n memoryMetadata: 4,\n autoRecall: 5,\n});\n\n/**\n * Build a ContextEngine instance from the supplied configuration.\n *\n * @stable\n */\nexport function createContextEngine(config: ContextEngineConfig = {}): ContextEngine {\n const memoryBaseMode = config.memoryBaseMode ?? 'full';\n const localeInput = config.locale;\n const localePack: ContextLocalePack = resolvePackInput(localeInput);\n const localeId = localePack.id;\n const layerCfg = config.layers ?? {};\n const layersEnabled: Record<string, boolean> = {\n identity: layerCfg.identity?.enabled ?? true,\n memoryMetadata: layerCfg.memoryMetadata?.enabled ?? true,\n activeRules: layerCfg.activeRules?.enabled ?? true,\n activeSkills: layerCfg.activeSkills?.enabled ?? true,\n workingBlocks: layerCfg.workingBlocks?.enabled ?? true,\n autoRecall: layerCfg.autoRecall?.enabled ?? true,\n };\n const layerCaps: Record<string, number | undefined> = {\n identity: layerCfg.identity?.cap ?? DEFAULT_LAYER_CAPS.identity,\n memoryMetadata: layerCfg.memoryMetadata?.cap ?? DEFAULT_LAYER_CAPS.memoryMetadata,\n activeRules: layerCfg.activeRules?.cap ?? DEFAULT_LAYER_CAPS.activeRules,\n activeSkills: layerCfg.activeSkills?.cap ?? DEFAULT_LAYER_CAPS.activeSkills,\n workingBlocks: layerCfg.workingBlocks?.cap ?? DEFAULT_LAYER_CAPS.workingBlocks,\n autoRecall: layerCfg.autoRecall?.cap ?? DEFAULT_LAYER_CAPS.autoRecall,\n };\n const factsAutoRecall = config.factsAutoRecall ?? false;\n const reservedForResponse = config.reservedForResponse ?? 4096;\n const reservedForCompaction = config.reservedForCompaction ?? 8192;\n const maxContextTokens = config.maxContextTokens ?? Number.POSITIVE_INFINITY;\n\n const tokenCounter: ContextTokenCounter = config.tokenCounter\n ? 'count' in config.tokenCounter\n ? adaptTokenCounter(config.tokenCounter)\n : (config.tokenCounter as ContextTokenCounter)\n : HEURISTIC_TOKEN_COUNTER;\n // CE-13: budgeting against a real provider window with the heuristic\n // counter is approximate - say so once instead of failing silently\n // late (the heuristic's failure mode is a provider context-length\n // error before compaction fires).\n if (\n config.tokenCounter === undefined &&\n typeof config.providerContextWindow === 'number' &&\n !heuristicCounterWarned\n ) {\n heuristicCounterWarned = true;\n process.stderr.write(\n '[graphorin/memory] context-engine token counts use the built-in heuristic (chars/4 + dense-script). For production budgeting against a real provider window, pass `contextEngine.tokenCounter` (e.g. the provider package JsTiktokenCounter).\\n',\n );\n }\n\n const privacy = config.privacy ?? {};\n const defaultSensitivity: Sensitivity = privacy.defaultSensitivity ?? 'internal';\n const providerTrust: LocalProviderTrust = privacy.providerTrust ?? 'public-tls';\n const cloudUploadConsent = privacy.cloudUploadConsent ?? false;\n const heuristicStrategy = defaultLocaleHeuristicStrategy(localePack);\n\n // Compaction config resolution.\n const compactionInput = config.compaction;\n const compactionAutoDefault = resolveAutoCompactionDefault(providerTrust);\n const compactionEnabled =\n compactionInput === false\n ? false\n : compactionInput === undefined\n ? compactionAutoDefault === 'enabled'\n : compactionInput.trigger !== 'never';\n const providerContextWindow = config.providerContextWindow ?? null;\n const triggerSpec =\n compactionInput === false || compactionInput === undefined\n ? undefined\n : compactionInput.trigger;\n const compactionThresholdTokens =\n compactionEnabled && providerContextWindow !== null\n ? resolveTriggerThreshold({\n contextWindow: providerContextWindow,\n ...(triggerSpec !== undefined ? { trigger: triggerSpec } : {}),\n reservedForResponse,\n reservedForCompaction,\n })\n : Number.POSITIVE_INFINITY;\n // CE-12: compaction enabled without a `providerContextWindow` leaves the\n // threshold at Infinity, so `shouldCompact` returns false forever - a\n // silently-dead default-on protection. Surface it: throw if the operator\n // explicitly configured compaction, warn (once) if it is on by the default\n // trust policy. Auto-detecting the window from the provider is not\n // implemented.\n const compactionEffective = compactionEnabled && providerContextWindow !== null;\n if (compactionEnabled && providerContextWindow === null) {\n const message =\n 'context-engine compaction is enabled but `providerContextWindow` is not set, so the ' +\n 'trigger threshold is Infinity and compaction will never fire. Pass `providerContextWindow` ' +\n \"(your model's context window, in tokens) - auto-detection from the provider is not implemented.\";\n if (compactionInput !== undefined && compactionInput !== false) {\n throw new Error(`[graphorin/memory] ${message}`);\n }\n warnCompactionIneffective(message);\n }\n const compactionStrategy: CompactionStrategy =\n compactionInput === false ||\n compactionInput === undefined ||\n compactionInput.strategy === undefined\n ? {\n kind: 'summarize-old-preserve-recent',\n preserveRecentTurns: 6,\n templateName: 'summary-sections',\n }\n : compactionInput.strategy;\n // SOTA-4 reclaim-floor: defer a compaction whose older (compactable) portion\n // is below this floor (read from the trigger config; 0 = off, byte-identical).\n const compactionMinReclaimTokens =\n triggerSpec !== undefined && triggerSpec !== 'never'\n ? Math.max(0, triggerSpec.minReclaimTokens ?? 0)\n : 0;\n // How many recent turns the active strategy preserves (the reclaimable portion\n // is everything before them).\n const reclaimPreserveTurns =\n compactionStrategy.kind === 'summarize-old-preserve-recent'\n ? (compactionStrategy.preserveRecentTurns ?? DEFAULT_PRESERVE_RECENT_TURNS)\n : compactionStrategy.kind === 'clear-old-tool-results' &&\n typeof compactionStrategy.summarizeFallback === 'object'\n ? (compactionStrategy.summarizeFallback.preserveRecentTurns ??\n DEFAULT_PRESERVE_RECENT_TURNS)\n : DEFAULT_PRESERVE_RECENT_TURNS;\n const compactionHooks: ReadonlyArray<NamedPostCompactionHook> = resolveDefaultHooks(\n compactionInput === false || compactionInput === undefined\n ? undefined\n : compactionInput.postCompactionHooks,\n );\n const summarizer = config.summarizer;\n const now = config.now ?? Date.now;\n\n const resolvedConfig: ResolvedContextEngineConfig = Object.freeze({\n memoryBaseMode,\n localeId,\n maxContextTokens,\n reservedForResponse,\n reservedForCompaction,\n compactionEnabled,\n compactionEffective,\n compactionThresholdTokens,\n providerContextWindow,\n providerTrust,\n cloudUploadConsent,\n defaultSensitivity,\n });\n\n async function assemble(memory: Memory, input: AssembleInput): Promise<AssembledPrompt> {\n // Layer 1 - base template.\n const layer1Text = layersEnabled.identity ? composeLayer1(localePack, memoryBaseMode) : '';\n // Layer 2 - agent instructions.\n const layer2Text = composeLayer2(input.agentInstructions);\n\n // Layer 3 - working blocks (filter D2).\n const blocks = await memory.working.list(input.scope);\n const blocksKept: Array<(typeof blocks)[number]> = [];\n const privacyCounters: Record<PrivacyDecisionReason, number> = {\n allowed: 0,\n 'no-cloud-upload-consent': 0,\n 'provider-rejects-internal': 0,\n 'provider-rejects-secret': 0,\n };\n for (const block of blocks) {\n const decision = privacyDecide(block.sensitivity, {\n ...(privacy.providerAcceptsSensitivity !== undefined\n ? { providerAcceptsSensitivity: privacy.providerAcceptsSensitivity }\n : {}),\n providerTrust,\n cloudUploadConsent,\n defaultSensitivity,\n });\n privacyCounters[decision.reason] += 1;\n if (decision.decision === 'pass') blocksKept.push(block);\n }\n const layer3Text = layersEnabled.workingBlocks ? renderWorkingBlocks(blocksKept) : '';\n\n // Layer 4 - procedural rules + skills (filter D2 on rules).\n const rules = await memory.procedural.activate(input.scope, input.proceduralActivation ?? {});\n const rulesKept: Array<(typeof rules)[number]> = [];\n for (const rule of rules) {\n const decision = privacyDecide(rule.sensitivity, {\n ...(privacy.providerAcceptsSensitivity !== undefined\n ? { providerAcceptsSensitivity: privacy.providerAcceptsSensitivity }\n : {}),\n providerTrust,\n cloudUploadConsent,\n defaultSensitivity,\n });\n privacyCounters[decision.reason] += 1;\n if (decision.decision === 'pass') rulesKept.push(rule);\n }\n const layer4RulesText = layersEnabled.activeRules ? renderProceduralRules(rulesKept) : '';\n const layer4SkillsText = layersEnabled.activeSkills\n ? composeLayer4Skills(input.skills ?? [])\n : '';\n\n // Layer 5 - memory metadata.\n const meta = await memory.metadata(input.scope);\n const layer5Text = layersEnabled.memoryMetadata\n ? renderMetadataBlock(enrichMetadataTags(meta, localeId, memory.embedderId()))\n : '';\n\n // Layer 6 - auto-recall.\n let autoRecall: AutoRecallTriggerResult = { factsTriggered: false };\n let layer6Text = '';\n if (factsAutoRecall !== false && layersEnabled.autoRecall) {\n const strategy =\n input.autoRecallStrategyOverride ?? factsAutoRecall.strategy ?? heuristicStrategy;\n autoRecall = strategy({\n locale: localeId,\n lastUserMessage: input.lastUserMessage ?? '',\n });\n if (autoRecall.factsTriggered) {\n const topK = factsAutoRecall.topK ?? layerCfg.autoRecall?.topK ?? 5;\n // CE-4: default 0 - rank-based `topK` already bounds the injected\n // volume, and the threshold's scale is reranker-dependent (the default\n // RRF reranker fuses 2 candidate lists, so scores top out near\n // `2/(60+1) ≈ 0.033` and any positive default would silently drop\n // everything). Operators tuning against a known reranker scale can pass\n // an explicit `threshold`.\n const threshold = factsAutoRecall.threshold ?? layerCfg.autoRecall?.threshold ?? 0;\n const hits = await memory.semantic\n .search(input.scope, input.lastUserMessage ?? '', { topK })\n .catch(() => []);\n const facts: Fact[] = [];\n for (const hit of hits) {\n if (hit.score < threshold) continue;\n const decision = privacyDecide(hit.record.sensitivity, {\n ...(privacy.providerAcceptsSensitivity !== undefined\n ? { providerAcceptsSensitivity: privacy.providerAcceptsSensitivity }\n : {}),\n providerTrust,\n cloudUploadConsent,\n defaultSensitivity,\n });\n privacyCounters[decision.reason] += 1;\n if (decision.decision === 'pass') facts.push(hit.record);\n }\n layer6Text = renderAutoRecalledFacts(facts);\n }\n }\n\n // Token-budget allocation. Layer 1 (`graphorin_memory_base`) and\n // Layer 2 (`agent_instructions`) are concatenated into the\n // single `identity` candidate so they share a priority slot;\n // they are joined with a blank line so the assembled prompt is\n // readable.\n const identityText =\n layer1Text.length > 0 && layer2Text.length > 0\n ? `${layer1Text}\\n\\n${layer2Text}`\n : layer1Text + layer2Text;\n const candidates: LayerCandidate[] = [\n buildCandidate('identity', identityText, layerCaps.identity),\n buildCandidate('memoryMetadata', layer5Text, layerCaps.memoryMetadata),\n buildCandidate('activeRules', layer4RulesText, layerCaps.activeRules),\n buildCandidate('workingBlocks', layer3Text, layerCaps.workingBlocks),\n buildCandidate('activeSkills', layer4SkillsText, layerCaps.activeSkills),\n buildCandidate('autoRecall', layer6Text, layerCaps.autoRecall),\n ].filter((c) => c.text.length > 0);\n\n const allocation = await allocateLayers(candidates, maxContextTokens, tokenCounter);\n\n // D4 inbound preamble - fires on steps containing untrusted upstream parts.\n const preambleFired = shouldFireInboundPreamble(input.upstreamAnnotations ?? []);\n const preambleText = preambleFired ? composeInboundPreamble(localePack) : '';\n\n // CE-9: emit in stability order (Layer 1-4 prefix, then the cache\n // breakpoint, then the volatile metadata / auto-recall), NOT in the\n // truncation-priority order `allocation.layers` arrives in.\n const assembledLayers = allocation.layers\n .filter((l) => l.text.length > 0)\n .sort((a, b) => LAYER_EMIT_ORDER[a.id] - LAYER_EMIT_ORDER[b.id]);\n const finalParts: string[] = assembledLayers.map((l) => l.text);\n if (preambleText.length > 0) finalParts.push(preambleText);\n const systemContent = finalParts.join('\\n\\n');\n\n // Annotations - one per assembled fragment, in the same order\n // as `finalParts` so observers can correlate.\n const annotations: AnnotatedPart[] = assembledLayers.map((layer) => ({\n content: { type: 'text', text: layer.text } as MessageContent,\n annotation: annotationForLayer(layer),\n }));\n if (preambleText.length > 0) {\n annotations.push({\n content: { type: 'text', text: preambleText } as MessageContent,\n annotation: annotate('system:framework', 'n/a'),\n });\n }\n\n return Object.freeze({\n systemMessage: Object.freeze({ role: 'system' as const, content: systemContent }),\n annotations: Object.freeze(annotations),\n layerAllocation: allocation,\n inboundPreambleFired: preambleFired,\n privacyCounters: Object.freeze(privacyCounters),\n localeId,\n memoryBaseMode,\n autoRecall,\n });\n }\n\n // CE-7 anti-thrash: after a compaction whose afterTokens still sits at\n // or above the trigger threshold (e.g. huge tool results among the\n // preserved turns), an immediate re-trigger would summarize the\n // previous summary - spend with no reclaim. Track the last outcome and\n // require the buffer to have GROWN past it before firing again.\n let lastCompactionAfterTokens: number | null = null;\n const REARM_GROWTH_TOKENS = 256;\n\n // C4 (context-engine-06/07 hardening): a persistently-failing summarizer\n // previously re-fired an LLM call at the top of EVERY step (the\n // anti-thrash guard arms only on success). Count consecutive failures -\n // including \"successful\" passes that did not actually shrink the buffer\n // - retry each pass once with a short backoff, and after\n // MAX_CONSECUTIVE_COMPACTION_FAILURES disable the AUTO trigger until a\n // later compactNow (e.g. a manual compact with a fixed summarizer)\n // succeeds and re-arms it.\n let consecutiveCompactionFailures = 0;\n let autoCompactionDisabledByFailures = false;\n const MAX_CONSECUTIVE_COMPACTION_FAILURES = 3;\n const COMPACTION_RETRY_BACKOFF_MS = 250;\n\n function recordCompactionFailure(reason: string): void {\n consecutiveCompactionFailures += 1;\n if (\n consecutiveCompactionFailures >= MAX_CONSECUTIVE_COMPACTION_FAILURES &&\n !autoCompactionDisabledByFailures\n ) {\n autoCompactionDisabledByFailures = true;\n process.stderr.write(\n `[graphorin/memory] auto-compaction disabled after ${consecutiveCompactionFailures} consecutive failed passes (last: ${reason}). Manual compactNow() still runs and re-enables the trigger on success.\\n`,\n );\n }\n }\n\n async function shouldCompact(\n messages: ReadonlyArray<Message>,\n options: {\n readonly precomputedTokens?: number;\n readonly compactableFromIndex?: number;\n } = {},\n ): Promise<boolean> {\n if (!compactionEnabled) return false;\n if (autoCompactionDisabledByFailures) return false;\n if (compactionThresholdTokens === Number.POSITIVE_INFINITY) return false;\n const total = options.precomputedTokens ?? (await countMessageTokens(messages, tokenCounter));\n if (total < compactionThresholdTokens) return false;\n if (\n lastCompactionAfterTokens !== null &&\n total <= lastCompactionAfterTokens + REARM_GROWTH_TOKENS\n ) {\n return false;\n }\n // SOTA-4 reclaim-floor: skip when the older (compactable) portion is too\n // small to be worth a summarizer call - avoids compact-thrash at the\n // threshold. Counts only the older slice; cheap relative to the avoided\n // call. context-engine-04: the caller's pinned system prefix\n // (`compactableFromIndex`) is NOT reclaimable and must not be counted -\n // a 10k-token prefix would otherwise satisfy any floor while the body\n // holds near-zero reclaimable tokens.\n if (compactionMinReclaimTokens > 0) {\n const from = Math.max(0, Math.min(options.compactableFromIndex ?? 0, messages.length));\n const olderCount = Math.max(from, messages.length - reclaimPreserveTurns);\n if (olderCount <= from) return false;\n const olderTokens = await countMessageTokens(messages.slice(from, olderCount), tokenCounter);\n if (olderTokens < compactionMinReclaimTokens) return false;\n }\n return true;\n }\n\n async function compactNow(callInput: {\n readonly scope: SessionScope;\n readonly runId: string;\n readonly sessionId: string;\n readonly agentId: string;\n readonly source: CompactionSource;\n readonly messages: ReadonlyArray<Message>;\n readonly memory: Memory;\n readonly summarizer?: CompactionSummarizer;\n /** Per-call override of the strategy's preserve-recent count (CE-3). */\n readonly preserveRecentTurns?: number;\n /** Topic/tags narrowing for the procedural-rules re-anchor hook (CE-6). */\n readonly procedural?: { readonly topic?: string; readonly tags?: ReadonlyArray<string> };\n /** The caller's pinned system prefix - accounting only (context-engine-04). */\n readonly prefixMessages?: ReadonlyArray<Message>;\n readonly signal?: AbortSignal;\n }): Promise<{\n readonly result: CompactionResult;\n readonly extraContent: ReadonlyArray<MessageContent>;\n readonly hookFailures: ReadonlyArray<{ readonly hookName: string; readonly reason: string }>;\n }> {\n const activeSummarizer = callInput.summarizer ?? summarizer;\n if (activeSummarizer === undefined) {\n throw new TypeError(\n '[graphorin/memory] ContextEngine.compactNow: no summarizer configured. ' +\n 'Pass `summarizer` to createContextEngine({...}) or to compactNow({...}).',\n );\n }\n const compactionInputCall: ExecuteCompactionInput = {\n messages: callInput.messages,\n source: callInput.source,\n strategy:\n callInput.preserveRecentTurns !== undefined &&\n compactionStrategy.kind === 'summarize-old-preserve-recent'\n ? { ...compactionStrategy, preserveRecentTurns: callInput.preserveRecentTurns }\n : compactionStrategy,\n localePack,\n summarizer: activeSummarizer,\n tokenCounter,\n thresholdTokens: compactionThresholdTokens,\n runId: callInput.runId,\n sessionId: callInput.sessionId,\n agentId: callInput.agentId,\n scope: callInput.scope,\n providerTrust,\n now,\n ...(callInput.signal !== undefined ? { signal: callInput.signal } : {}),\n };\n // C4: one retry with a short backoff on summarizer failure, then a\n // strictly-smaller-than-input assert - a pass that dropped messages\n // yet did not shrink the buffer is a failure (a looping/echoing\n // summarizer), not a success to arm the anti-thrash guard with.\n let result: CompactionResult;\n try {\n result = await executeCompaction(compactionInputCall);\n } catch (firstError) {\n if (callInput.signal?.aborted === true) throw firstError;\n await new Promise<void>((resolve) => setTimeout(resolve, COMPACTION_RETRY_BACKOFF_MS));\n try {\n result = await executeCompaction(compactionInputCall);\n } catch (secondError) {\n recordCompactionFailure(\n secondError instanceof Error ? secondError.message : String(secondError),\n );\n throw secondError;\n }\n }\n if (result.droppedMessageIndices.length > 0 && result.afterTokens >= result.beforeTokens) {\n const reason = `compaction did not shrink the buffer (${result.beforeTokens} -> ${result.afterTokens} tokens)`;\n if (callInput.source === 'auto-trigger') {\n // The auto loop must never keep paying for passes that grow the\n // buffer (the Gemini-CLI compression-loop class) - fail the pass.\n recordCompactionFailure(reason);\n throw new Error(`[graphorin/memory] ${reason}`);\n }\n // An operator-requested compaction of a small window can\n // legitimately cost more than it reclaims (the summary skeleton\n // has a floor) - warn, hand back the result, count nothing.\n process.stderr.write(`[graphorin/memory] ${reason} (source: ${callInput.source}).\\n`);\n } else if (result.droppedMessageIndices.length > 0) {\n // A pass that actually reclaimed space re-arms the auto trigger.\n consecutiveCompactionFailures = 0;\n if (autoCompactionDisabledByFailures) {\n autoCompactionDisabledByFailures = false;\n process.stderr.write(\n '[graphorin/memory] auto-compaction re-enabled after a successful pass.\\n',\n );\n }\n }\n // C4: hand hooks the DROPPED message content (not just indices) so\n // re-anchoring hooks like reanchorRecentResults can recover the\n // result handles that just left the window. Reference-diff against\n // trimmedMessages (both strategies carry surviving originals by\n // reference; the per-strategy index spaces differ, so indices are\n // not usable here).\n const survivors = new Set(result.trimmedMessages);\n const droppedMessages = callInput.messages.filter((m) => !survivors.has(m));\n const ctx = {\n result,\n scope: callInput.scope,\n runId: callInput.runId,\n sessionId: callInput.sessionId,\n agentId: callInput.agentId,\n source: callInput.source,\n droppedMessages,\n };\n const hookFailures: Array<{ readonly hookName: string; readonly reason: string }> = [];\n const extraContent: MessageContent[] = [];\n let hooksFired = 0;\n // context-engine-02: the same D2 privacy decision `assemble()` applies\n // to blocks / rules / facts, handed to the hooks - their output is\n // spliced into the buffer and shipped to the provider, so it must obey\n // the same filter or secret-tier content leaks on the first compaction.\n const allowSensitivity = (sensitivity: Sensitivity | undefined): boolean =>\n privacyDecide(sensitivity, {\n ...(privacy.providerAcceptsSensitivity !== undefined\n ? { providerAcceptsSensitivity: privacy.providerAcceptsSensitivity }\n : {}),\n providerTrust,\n cloudUploadConsent,\n defaultSensitivity,\n }).decision === 'pass';\n for (const hook of compactionHooks) {\n try {\n // CE-6: hooks receive the REAL compaction context - the old code\n // built `ctx` and then `void ctx;`-discarded it while the\n // function-form wrapper fabricated a zeroed result.\n const parts = await hook.resolveContent(\n {\n memory: callInput.memory,\n scope: callInput.scope,\n ...(callInput.procedural !== undefined ? { procedural: callInput.procedural } : {}),\n allowSensitivity,\n },\n ctx,\n );\n extraContent.push(...parts);\n hooksFired += 1;\n } catch (err) {\n hookFailures.push({\n hookName: hook.id,\n reason: err instanceof Error ? err.name : 'UnknownError',\n });\n }\n }\n const enrichedResult: CompactionResult = Object.freeze({\n ...result,\n hooksFiredCount: hooksFired,\n });\n // CE-7: arm the anti-thrash guard and surface the failure mode where\n // compaction could not get under the trigger threshold.\n //\n // context-engine-04: `shouldCompact` compares the FULL buffer total\n // (pinned prefix included) against this baseline, so the baseline must\n // be full-basis too: body afterTokens + the caller's pinned prefix +\n // the Context-Essentials message the caller splices in. Arming with\n // the body-only number let any real system prompt (> 256 tokens)\n // defeat the guard, re-firing a summarizer LLM call at the top of\n // EVERY step whenever compaction could not get under the threshold.\n const prefixTokens =\n callInput.prefixMessages !== undefined && callInput.prefixMessages.length > 0\n ? await countMessageTokens(callInput.prefixMessages, tokenCounter)\n : 0;\n let essentialsTokens = 0;\n for (const part of extraContent) {\n if (part.type === 'text') essentialsTokens += await tokenCounter.countText(part.text);\n }\n const fullAfterTokens = enrichedResult.afterTokens + prefixTokens + essentialsTokens;\n lastCompactionAfterTokens = fullAfterTokens;\n if (\n compactionThresholdTokens !== Number.POSITIVE_INFINITY &&\n fullAfterTokens >= compactionThresholdTokens\n ) {\n process.stderr.write(\n `[graphorin/memory] compaction finished at ${fullAfterTokens} tokens (body ${enrichedResult.afterTokens} + pinned prefix ${prefixTokens} + essentials ${essentialsTokens}) - still at/above the ${compactionThresholdTokens}-token trigger (oversized preserved turns?). The immediate re-trigger is suppressed until the buffer grows.\\n`,\n );\n }\n return Object.freeze({\n result: enrichedResult,\n extraContent: Object.freeze(extraContent),\n hookFailures: Object.freeze(hookFailures),\n });\n }\n\n return Object.freeze({\n assemble,\n shouldCompact,\n compactNow,\n config(): ResolvedContextEngineConfig {\n return resolvedConfig;\n },\n });\n}\n\nfunction buildCandidate(\n id: LayerCandidate['id'],\n text: string,\n cap: number | undefined,\n): LayerCandidate {\n if (cap !== undefined) return { id, text, cap };\n return { id, text };\n}\n\nfunction annotationForLayer(layer: LayerAllocation): ContentAnnotation {\n switch (layer.id) {\n case 'identity':\n // Identity merges the framework base (Layer 1) + the user-defined\n // agent_instructions (Layer 2) into one trusted fragment, tagged\n // `system:framework` so D3 skips re-scanning it under\n // `scanScope: 'untrusted'`. (Both halves are first-party prompt text, so\n // the merged layer carries a single framework trust tag - `LayerAllocation`\n // does not surface which halves were present.)\n return annotate('system:framework', 'n/a');\n case 'memoryMetadata':\n case 'activeRules':\n case 'workingBlocks':\n case 'activeSkills':\n case 'autoRecall':\n return annotate('memory:tier-filtered', 'n/a');\n default:\n return annotate('system:framework', 'n/a');\n }\n}\n\nfunction renderWorkingBlocks(\n blocks: ReadonlyArray<{\n readonly label: string;\n readonly value: string;\n readonly description?: string;\n }>,\n): string {\n if (blocks.length === 0) return '';\n const lines = ['<memory_blocks>'];\n for (const block of blocks) {\n const description =\n block.description !== undefined ? ` description=\"${escapeXmlAttr(block.description)}\"` : '';\n lines.push(` <block label=\"${escapeXmlAttr(block.label)}\"${description}>`);\n lines.push(` ${escapeXmlText(block.value)}`);\n lines.push(' </block>');\n }\n lines.push('</memory_blocks>');\n return lines.join('\\n');\n}\n\nfunction renderProceduralRules(\n rules: ReadonlyArray<{ readonly text: string; readonly priority: number }>,\n): string {\n if (rules.length === 0) return '';\n const lines = ['<memory_rules>'];\n for (const rule of rules) {\n lines.push(` <rule priority=\"${rule.priority}\">${escapeXmlText(rule.text)}</rule>`);\n }\n lines.push('</memory_rules>');\n return lines.join('\\n');\n}\n\nfunction renderAutoRecalledFacts(facts: ReadonlyArray<Fact>): string {\n if (facts.length === 0) return '';\n const lines = ['<auto_recalled_facts>'];\n for (const fact of facts) {\n const tagsAttr =\n fact.tags !== undefined ? ` tags=\"${escapeXmlAttr((fact.tags ?? []).join(','))}\"` : '';\n lines.push(\n ` <fact id=\"${escapeXmlAttr(fact.id)}\"${tagsAttr}>${escapeXmlText(fact.text)}</fact>`,\n );\n }\n lines.push('</auto_recalled_facts>');\n return lines.join('\\n');\n}\n\nfunction escapeXmlAttr(value: string): string {\n return value\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;');\n}\n\nfunction escapeXmlText(value: string): string {\n return value.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');\n}\n\nfunction resolvePackInput(input: ContextEngineConfig['locale']): ContextLocalePack {\n if (input === undefined) return enLocalePack;\n if (typeof input === 'string') {\n if (input === enLocalePack.id) return enLocalePack;\n return resolveLocalePack({ id: input });\n }\n return resolveLocalePack(input);\n}\n\nfunction resolveDefaultHooks(\n input: ReadonlyArray<PostCompactionHook> | ReadonlyArray<NamedPostCompactionHook> | undefined,\n): ReadonlyArray<NamedPostCompactionHook> {\n if (input === undefined) {\n return Object.freeze([\n reanchorProjectRules(),\n reanchorPersonaBlock(),\n reanchorPinnedFacts({ pinnedFactIds: [] }),\n ]);\n }\n return Object.freeze(\n input.map((hook, idx): NamedPostCompactionHook => {\n if (typeof hook === 'function') {\n const id = `customHook_${idx}`;\n return {\n id,\n async resolveContent(_deps, ctx) {\n // CE-6: the operator's hook sees the genuine compaction\n // context. `ctx` is always supplied by compactNow; the\n // throw guards a direct caller that forgot it rather than\n // silently fabricating zeros (the old behaviour).\n if (ctx === undefined) {\n throw new TypeError(\n '[graphorin/memory] post-compaction hooks require the compaction context - call through ContextEngine.compactNow(...).',\n );\n }\n const result = await hook(ctx);\n return result;\n },\n };\n }\n return hook;\n }),\n );\n}\n\n/**\n * Augment a {@link MemoryMetadata} snapshot with the active locale +\n * embedder tags so the rendered metadata block carries the\n * additional context the model uses for reasoning. Pure: the\n * original `meta` reference is not mutated.\n */\nfunction enrichMetadataTags(\n meta: import('@graphorin/core').MemoryMetadata,\n localeId: string,\n embedderId: string | null,\n): import('@graphorin/core').MemoryMetadata {\n const baseTags = meta.tags !== undefined ? [...meta.tags] : [];\n if (!baseTags.some((tag) => tag.startsWith('locale:'))) {\n baseTags.push(`locale:${localeId}`);\n }\n if (embedderId !== null && !baseTags.some((tag) => tag.startsWith('embedder:'))) {\n baseTags.push(`embedder:${embedderId}`);\n }\n return { ...meta, tags: Object.freeze(baseTags) };\n}\n"],"mappings":"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"}
@@ -6,64 +6,23 @@ import { ContextTokenCounter, HEURISTIC_TOKEN_COUNTER, adaptTokenCounter, countM
6
6
  import { CLEARED_TOOL_RESULT_MARKER, ClearToolResultsOptions, ClearToolResultsOutcome, clearOldToolResults } from "./compaction/clear-tool-results.js";
7
7
  import { CompactionConfig, CompactionContext, CompactionResult, CompactionSource, CompactionStrategy, CompactionSummarizer, CompactionTriggerConfig, PostCompactionHook, PostCompactionHookContext } from "./compaction/types.js";
8
8
  import { DEFAULT_PRESERVE_RECENT_TURNS, ExecuteCompactionInput, executeCompaction } from "./compaction/compactor.js";
9
+ import { PartitionResult, PrivacyDecision, PrivacyDecisionReason, PrivacyFilterContext, decide, effectiveAcceptsSensitivity, partition } from "./privacy-filter.js";
10
+ import { MemoryBaseMode, SkillMetadataCard, composeInboundPreamble, composeLayer1, composeLayer2, composeLayer4Skills } from "./templates/composer.js";
11
+ import { AllocationResult, DEFAULT_LAYER_PRIORITY, LayerAllocation, LayerCandidate, LayerId, OverflowMode, allocate, truncateToTokens } from "./token-budget.js";
12
+ import { AnnotatedPart, AssembleInput, AssembledPrompt, CompileOptions, CompileScope, MemoryContextBlocks, ResolvedContextEngineConfig } from "./io-types.js";
13
+ import { ContextEngine } from "../memory-interface.js";
9
14
  import { HookDeps, NamedPostCompactionHook } from "./compaction/hooks/types.js";
10
15
  import { reanchorPersonaBlock } from "./compaction/hooks/reanchor-persona-block.js";
11
16
  import { reanchorPinnedFacts } from "./compaction/hooks/reanchor-pinned-facts.js";
12
17
  import { reanchorProjectRules } from "./compaction/hooks/reanchor-project-rules.js";
13
18
  import { ReanchorRecentResultsOptions, reanchorRecentResults } from "./compaction/hooks/reanchor-recent-results.js";
19
+ import { COMPACTION_SUMMARY_CLOSE, COMPACTION_SUMMARY_MARKER, COMPACTION_SUMMARY_OPEN, COMPACTION_SUMMARY_TAG } from "./compaction/templates/marker.js";
14
20
  import { CompactionMetadataPayload, RenderedTemplate, SUMMARY_TEMPLATE_NAME, SUMMARY_TEMPLATE_VERSION, buildSummarizerPrompt, renderFinalSummary } from "./compaction/templates/summary-9-section.js";
15
21
  import { AutoCompactionDefault, DEFAULT_RESERVED_FOR_COMPACTION, DEFAULT_RESERVED_FOR_RESPONSE, DEFAULT_THRESHOLD_RATIO, resolveAutoCompactionDefault, resolveTriggerThreshold } from "./compaction/thresholds.js";
16
22
  import "./compaction/index.js";
17
- import { PartitionResult, PrivacyDecision, PrivacyDecisionReason, PrivacyFilterContext, decide, effectiveAcceptsSensitivity, partition } from "./privacy-filter.js";
18
- import { MemoryBaseMode, SkillMetadataCard, composeInboundPreamble, composeLayer1, composeLayer2, composeLayer4Skills } from "./templates/composer.js";
19
- import { AllocationResult, DEFAULT_LAYER_PRIORITY, LayerAllocation, LayerCandidate, LayerId, OverflowMode, allocate, truncateToTokens } from "./token-budget.js";
20
- import { AnnotatedPart, AssembleInput, AssembledPrompt, AutoRecallConfig, ContextEngine, ContextEngineConfig, LayerConfig, PrivacyConfig, ResolvedContextEngineConfig, createContextEngine } from "./engine.js";
23
+ import { AutoRecallConfig, ContextEngineConfig, LayerConfig, PrivacyConfig, createContextEngine } from "./engine.js";
21
24
  import { LocaleResolverLogger, _getLocaleFallbackWarningsForTesting, _resetLocaleFallbackWarningsForTesting, resolveLocalePack } from "./locale-packs/resolver.js";
22
25
  import { MemoryMetadataDeps, gatherMemoryMetadata, renderMetadataBlock } from "./metadata.js";
23
26
  import { INBOUND_SANITIZATION_PREAMBLE_EN } from "./preambles/inbound-en.js";
24
27
  import { BASE_TEMPLATE_EN_FULL, BASE_TEMPLATE_EN_MINIMAL } from "./templates/base-en.js";
25
- import * as _graphorin_core0 from "@graphorin/core";
26
-
27
- //#region src/context-engine/index.d.ts
28
-
29
- /**
30
- * Compile result. Layered into the system prompt by the agent
31
- * runtime. Preserved as a stable surface from Phase 10a so
32
- * existing consumers (`memory.compile(scope)`) keep working
33
- * unchanged after Phase 10d.
34
- *
35
- * @stable
36
- */
37
- interface MemoryContextBlocks {
38
- /** XML-rendered working memory blocks, when any. */
39
- readonly workingBlocks?: string;
40
- /** Active procedural rules block. */
41
- readonly rules?: string;
42
- /** Static narrative base (English by default; locale-aware). */
43
- readonly base?: string;
44
- /** Bucketed memory metadata block. */
45
- readonly metadata?: string;
46
- /** Optional auto-recalled memory hints. */
47
- readonly autoRecalled?: string;
48
- /** Optional `cache_control` hints for prompt-cache aware providers. */
49
- readonly cacheHints?: ReadonlyArray<string>;
50
- }
51
- /**
52
- * Per-call options accepted by `memory.compile(...)`.
53
- *
54
- * @stable
55
- */
56
- interface CompileOptions {
57
- readonly maxBlocks?: number;
58
- readonly includeMetadata?: boolean;
59
- readonly providerAcceptsSensitivity?: ReadonlyArray<'public' | 'internal' | 'secret'>;
60
- }
61
- /**
62
- * Author-time scope passed through to the context engine.
63
- *
64
- * @stable
65
- */
66
- type CompileScope = _graphorin_core0.SessionScope;
67
- //#endregion
68
- export { CompileOptions, CompileScope, MemoryContextBlocks };
69
- //# sourceMappingURL=index.d.ts.map
28
+ import "@graphorin/core";
@@ -0,0 +1,144 @@
1
+ import { ContentAnnotation } from "./annotations.js";
2
+ import { AutoRecallStrategy, AutoRecallTriggerResult } from "./auto-recall.js";
3
+ import { PrivacyDecisionReason } from "./privacy-filter.js";
4
+ import { MemoryBaseMode, SkillMetadataCard } from "./templates/composer.js";
5
+ import { AllocationResult } from "./token-budget.js";
6
+ import * as _graphorin_core0 from "@graphorin/core";
7
+ import { LocalProviderTrust, MessageContent, Sensitivity, SessionScope } from "@graphorin/core";
8
+
9
+ //#region src/context-engine/io-types.d.ts
10
+
11
+ /**
12
+ * Input to {@link ContextEngine.assemble}.
13
+ *
14
+ * @stable
15
+ */
16
+ interface AssembleInput {
17
+ readonly scope: SessionScope;
18
+ readonly agentId: string;
19
+ readonly sessionId: string;
20
+ readonly runId: string;
21
+ readonly agentInstructions?: string;
22
+ readonly skills?: ReadonlyArray<SkillMetadataCard>;
23
+ readonly proceduralActivation?: {
24
+ readonly topic?: string;
25
+ readonly tags?: ReadonlyArray<string>;
26
+ };
27
+ readonly lastUserMessage?: string;
28
+ readonly autoRecallStrategyOverride?: AutoRecallStrategy;
29
+ /**
30
+ * Optional inbound-trust annotations carried by upstream
31
+ * messages (`session_messages` rows tagged by Phase 12 / Phase
32
+ * 07 / Phase 09). When at least one part has `inboundTrust !==
33
+ * 'trusted' && inboundTrust !== 'n/a'`, the per-step preamble
34
+ * fires (see RB-43 / DEC-159).
35
+ */
36
+ readonly upstreamAnnotations?: ReadonlyArray<ContentAnnotation>;
37
+ }
38
+ /**
39
+ * Single annotated `MessageContent` part assembled by the engine.
40
+ *
41
+ * @stable
42
+ */
43
+ interface AnnotatedPart {
44
+ readonly content: MessageContent;
45
+ readonly annotation: ContentAnnotation;
46
+ }
47
+ /**
48
+ * Output of {@link ContextEngine.assemble}.
49
+ *
50
+ * @stable
51
+ */
52
+ interface AssembledPrompt {
53
+ /** Single system message ready for `provider.stream(...)`. */
54
+ readonly systemMessage: {
55
+ readonly role: 'system';
56
+ readonly content: string;
57
+ };
58
+ /**
59
+ * Per-part annotations, in the same order as the assembled
60
+ * system content. Span-only - never serialized to the wire payload.
61
+ */
62
+ readonly annotations: ReadonlyArray<AnnotatedPart>;
63
+ /**
64
+ * Per-layer allocation snapshot. Surfaced for tests + diagnostics.
65
+ */
66
+ readonly layerAllocation: AllocationResult;
67
+ /** Whether the per-step inbound preamble fragment fired this assembly. */
68
+ readonly inboundPreambleFired: boolean;
69
+ /** Privacy-filter counters surfaced to the metadata block. */
70
+ readonly privacyCounters: Readonly<Record<PrivacyDecisionReason, number>>;
71
+ /** Resolved locale id (`'en'` for the default; custom otherwise). */
72
+ readonly localeId: string;
73
+ /** Resolved memory base mode. */
74
+ readonly memoryBaseMode: MemoryBaseMode;
75
+ /** Whether auto-recall was triggered this assembly. */
76
+ readonly autoRecall: AutoRecallTriggerResult;
77
+ }
78
+ /**
79
+ * Resolved configuration snapshot returned by
80
+ * {@link ContextEngine.config}.
81
+ *
82
+ * @stable
83
+ */
84
+ interface ResolvedContextEngineConfig {
85
+ readonly memoryBaseMode: MemoryBaseMode;
86
+ readonly localeId: string;
87
+ readonly maxContextTokens: number;
88
+ readonly reservedForResponse: number;
89
+ readonly reservedForCompaction: number;
90
+ readonly compactionEnabled: boolean;
91
+ /**
92
+ * Whether compaction can actually fire (CE-12): `compactionEnabled` **and** a
93
+ * `providerContextWindow` was supplied. `compactionEnabled: true` with
94
+ * `compactionEffective: false` is the honest signal that compaction is
95
+ * configured-on but a no-op for want of a context window.
96
+ */
97
+ readonly compactionEffective: boolean;
98
+ readonly compactionThresholdTokens: number;
99
+ readonly providerContextWindow: number | null;
100
+ readonly providerTrust: LocalProviderTrust;
101
+ readonly cloudUploadConsent: boolean;
102
+ readonly defaultSensitivity: Sensitivity;
103
+ }
104
+ /**
105
+ * Compile result. Layered into the system prompt by the agent
106
+ * runtime. Preserved as a stable surface from Phase 10a so
107
+ * existing consumers (`memory.compile(scope)`) keep working
108
+ * unchanged after Phase 10d.
109
+ *
110
+ * @stable
111
+ */
112
+ interface MemoryContextBlocks {
113
+ /** XML-rendered working memory blocks, when any. */
114
+ readonly workingBlocks?: string;
115
+ /** Active procedural rules block. */
116
+ readonly rules?: string;
117
+ /** Static narrative base (English by default; locale-aware). */
118
+ readonly base?: string;
119
+ /** Bucketed memory metadata block. */
120
+ readonly metadata?: string;
121
+ /** Optional auto-recalled memory hints. */
122
+ readonly autoRecalled?: string;
123
+ /** Optional `cache_control` hints for prompt-cache aware providers. */
124
+ readonly cacheHints?: ReadonlyArray<string>;
125
+ }
126
+ /**
127
+ * Per-call options accepted by `memory.compile(...)`.
128
+ *
129
+ * @stable
130
+ */
131
+ interface CompileOptions {
132
+ readonly maxBlocks?: number;
133
+ readonly includeMetadata?: boolean;
134
+ readonly providerAcceptsSensitivity?: ReadonlyArray<'public' | 'internal' | 'secret'>;
135
+ }
136
+ /**
137
+ * Author-time scope passed through to the context engine.
138
+ *
139
+ * @stable
140
+ */
141
+ type CompileScope = _graphorin_core0.SessionScope;
142
+ //#endregion
143
+ export { AnnotatedPart, AssembleInput, AssembledPrompt, CompileOptions, CompileScope, MemoryContextBlocks, ResolvedContextEngineConfig };
144
+ //# sourceMappingURL=io-types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"io-types.d.ts","names":[],"sources":["../../src/context-engine/io-types.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;;;;;;AA0F2B,UAzDV,aAAA,CAyDU;EAEJ,SAAA,KAAA,EA1DL,YA0DK;EAAuB,SAAA,OAAA,EAAA,MAAA;EAS7B,SAAA,SAAA,EAAA,MAAA;EACU,SAAA,KAAA,EAAA,MAAA;EAeD,SAAA,iBAAA,CAAA,EAAA,MAAA;EAEK,SAAA,MAAA,CAAA,EAhFX,aAgFW,CAhFG,iBAgFH,CAAA;EAAW,SAAA,oBAAA,CAAA,EAAA;IAWzB,SAAA,KAAA,CAAA,EAAA,MAAmB;IAoBnB,SAAA,IAAc,CAAA,EA5GX,aA+GoB,CAAA,MAAA,CAAA;EAQ5B,CAAA;;wCApH4B;;;;;;;;iCAQP,cAAc;;;;;;;UAQ9B,aAAA;oBACG;uBACG;;;;;;;UAQN,eAAA;;;;;;;;;;wBAOO,cAAc;;;;4BAIV;;;;4BAIA,SAAS,OAAO;;;;2BAIjB;;uBAEJ;;;;;;;;UASN,2BAAA;2BACU;;;;;;;;;;;;;;;0BAeD;;+BAEK;;;;;;;;;;UAWd,mBAAA;;;;;;;;;;;;wBAYO;;;;;;;UAQP,cAAA;;;wCAGuB;;;;;;;KAQ5B,YAAA,GAAY,gBAAA,CAA6B,YAAA"}
@@ -28,7 +28,7 @@ interface AutoRecallTriggers {
28
28
  readonly factTriggers: ReadonlyArray<RegExp>;
29
29
  }
30
30
  /**
31
- * Layer 1 template fragments. The {@link composeTemplate} function
31
+ * Layer 1 template fragments. The `composeTemplate` function
32
32
  * picks the right fragment based on `memoryBaseMode`.
33
33
  *
34
34
  * @stable
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","names":[],"sources":["../../../src/context-engine/locale-packs/types.ts"],"sourcesContent":["/**\n * Public types for the per-locale assets the\n * {@link ContextEngine} consumes when assembling the layered system\n * prompt. The framework ships an English default ({@link enLocalePack});\n * additional locales are supplied by application code via\n * {@link defineContextLocalePack}.\n *\n * The framework is locale-agnostic - no language is privileged in\n * core. Every consumer-facing string is reachable through this\n * surface so consumers can swap them without forking the framework.\n *\n * @packageDocumentation\n */\n\n/**\n * Trigger mode used by the auto-recall heuristic. The framework ships\n * regex patterns for the bundled locale; consumers may extend or\n * replace them via {@link defineContextLocalePack}.\n *\n * @stable\n */\nexport interface AutoRecallTriggers {\n /**\n * Case-insensitive regex set evaluated against the last user\n * message. A match indicates the model would benefit from the\n * top-K facts being injected into Layer 6.\n */\n readonly factTriggers: ReadonlyArray<RegExp>;\n}\n\n/**\n * Layer 1 template fragments. The {@link composeTemplate} function\n * picks the right fragment based on `memoryBaseMode`.\n *\n * @stable\n */\nexport interface BaseTemplateFragments {\n /** Full educational template (~250-350 tokens). */\n readonly full: string;\n /** Minimal template for high-end models (~80-120 tokens). */\n readonly minimal: string;\n}\n\n/**\n * D4 inbound-sanitization preamble fragment. Injected after the\n * cache breakpoint (Layer 5/6 territory) on steps containing\n * untrusted tool output.\n *\n * @stable\n */\nexport interface InboundSanitizationPreamble {\n /** Verbatim text appended to the system message when fired. */\n readonly text: string;\n}\n\n/**\n * Structured section-template fragments used by the auto-compaction\n * summarizer (RB-46). Section order is fixed; only the per-section\n * header / preamble text is locale-extensible.\n *\n * Each entry is the human-readable header for the corresponding\n * section. Section indices are 1-based to match the documented\n * layout in the architecture doc.\n *\n * @stable\n */\nexport interface CompactionSummaryTemplate {\n /** Preamble injected at the top of the summarizer prompt. */\n readonly preamble: string;\n /** 12 section headers. The last two are filled by the harness. */\n readonly sections: readonly [\n string, // 1: Session goal and current task\n string, // 2: Decisions made and rationale\n string, // 3: Constraints and non-negotiables (C4)\n string, // 4: Key facts established\n string, // 5: Open questions and ambiguities\n string, // 6: Tools used and their outcomes\n string, // 7: Files / artifacts referenced\n string, // 8: Persona / preferences / project rules surfaced\n string, // 9: Errors encountered and resolutions (SOTA-6)\n string, // 10: Next steps (SOTA-6)\n string, // 11: Recent turns preserved verbatim (harness-filled)\n string, // 12: Compaction metadata (harness-filled)\n ];\n}\n\n/**\n * A `LocalePack` collects every consumer-facing string the\n * ContextEngine renders. Consumers register additional locales via\n * {@link defineContextLocalePack}. The framework is locale-agnostic\n * - no language is privileged in core.\n *\n * @stable\n */\nexport interface ContextLocalePack {\n /** Stable lowercase identifier (`'en'`, `'de'`, `'fr'`, …). */\n readonly id: string;\n /** Layer 1 base template fragments. */\n readonly baseTemplate: BaseTemplateFragments;\n /** Auto-recall trigger regex set. */\n readonly autoRecallTriggers: AutoRecallTriggers;\n /** Inbound-sanitization preamble (D4 - RB-43). */\n readonly inboundSanitizationPreamble: InboundSanitizationPreamble;\n /** Structured compaction summary template (RB-46). */\n readonly compactionSummaryTemplate: CompactionSummaryTemplate;\n}\n\n/**\n * Builder used by application code that wants to ship a custom\n * locale pack. The builder freezes every input so the pack can be\n * safely reused across multiple `Memory` instances without\n * accidental mutation.\n *\n * Partial packs are accepted: any field omitted falls back to the\n * English default at compose time, with a one-time WARN per locale\n * per missing surface (the safety guarantee is preserved even when\n * an operator installs a partial locale pack).\n *\n * @stable\n */\nexport interface PartialContextLocalePack {\n readonly id: string;\n readonly baseTemplate?: Partial<BaseTemplateFragments>;\n readonly autoRecallTriggers?: Partial<AutoRecallTriggers>;\n readonly inboundSanitizationPreamble?: Partial<InboundSanitizationPreamble>;\n readonly compactionSummaryTemplate?: Partial<CompactionSummaryTemplate>;\n}\n\n/**\n * Build a {@link ContextLocalePack} from a partial input. Missing\n * fields fall back to the English default at compose time.\n *\n * @stable\n */\nexport function defineContextLocalePack(input: PartialContextLocalePack): PartialContextLocalePack {\n if (typeof input.id !== 'string' || input.id.length === 0) {\n throw new TypeError(\n '[graphorin/memory] defineContextLocalePack: `id` must be a non-empty lowercase string.',\n );\n }\n return Object.freeze({\n id: input.id,\n ...(input.baseTemplate !== undefined\n ? { baseTemplate: Object.freeze({ ...input.baseTemplate }) }\n : {}),\n ...(input.autoRecallTriggers !== undefined\n ? {\n autoRecallTriggers: Object.freeze({\n ...(input.autoRecallTriggers.factTriggers !== undefined\n ? { factTriggers: Object.freeze([...input.autoRecallTriggers.factTriggers]) }\n : {}),\n }) as Partial<AutoRecallTriggers>,\n }\n : {}),\n ...(input.inboundSanitizationPreamble !== undefined\n ? {\n inboundSanitizationPreamble: Object.freeze({ ...input.inboundSanitizationPreamble }),\n }\n : {}),\n ...(input.compactionSummaryTemplate !== undefined\n ? {\n compactionSummaryTemplate: Object.freeze({\n ...(input.compactionSummaryTemplate.preamble !== undefined\n ? { preamble: input.compactionSummaryTemplate.preamble }\n : {}),\n ...(input.compactionSummaryTemplate.sections !== undefined\n ? {\n sections: Object.freeze([\n ...input.compactionSummaryTemplate.sections,\n ]) as CompactionSummaryTemplate['sections'],\n }\n : {}),\n }) as Partial<CompactionSummaryTemplate>,\n }\n : {}),\n });\n}\n"],"mappings":";;;;;;;AAsIA,SAAgB,wBAAwB,OAA2D;AACjG,KAAI,OAAO,MAAM,OAAO,YAAY,MAAM,GAAG,WAAW,EACtD,OAAM,IAAI,UACR,yFACD;AAEH,QAAO,OAAO,OAAO;EACnB,IAAI,MAAM;EACV,GAAI,MAAM,iBAAiB,SACvB,EAAE,cAAc,OAAO,OAAO,EAAE,GAAG,MAAM,cAAc,CAAC,EAAE,GAC1D,EAAE;EACN,GAAI,MAAM,uBAAuB,SAC7B,EACE,oBAAoB,OAAO,OAAO,EAChC,GAAI,MAAM,mBAAmB,iBAAiB,SAC1C,EAAE,cAAc,OAAO,OAAO,CAAC,GAAG,MAAM,mBAAmB,aAAa,CAAC,EAAE,GAC3E,EAAE,EACP,CAAC,EACH,GACD,EAAE;EACN,GAAI,MAAM,gCAAgC,SACtC,EACE,6BAA6B,OAAO,OAAO,EAAE,GAAG,MAAM,6BAA6B,CAAC,EACrF,GACD,EAAE;EACN,GAAI,MAAM,8BAA8B,SACpC,EACE,2BAA2B,OAAO,OAAO;GACvC,GAAI,MAAM,0BAA0B,aAAa,SAC7C,EAAE,UAAU,MAAM,0BAA0B,UAAU,GACtD,EAAE;GACN,GAAI,MAAM,0BAA0B,aAAa,SAC7C,EACE,UAAU,OAAO,OAAO,CACtB,GAAG,MAAM,0BAA0B,SACpC,CAAC,EACH,GACD,EAAE;GACP,CAAC,EACH,GACD,EAAE;EACP,CAAC"}
1
+ {"version":3,"file":"types.js","names":[],"sources":["../../../src/context-engine/locale-packs/types.ts"],"sourcesContent":["/**\n * Public types for the per-locale assets the\n * {@link ContextEngine} consumes when assembling the layered system\n * prompt. The framework ships an English default ({@link enLocalePack});\n * additional locales are supplied by application code via\n * {@link defineContextLocalePack}.\n *\n * The framework is locale-agnostic - no language is privileged in\n * core. Every consumer-facing string is reachable through this\n * surface so consumers can swap them without forking the framework.\n *\n * @packageDocumentation\n */\n\n/**\n * Trigger mode used by the auto-recall heuristic. The framework ships\n * regex patterns for the bundled locale; consumers may extend or\n * replace them via {@link defineContextLocalePack}.\n *\n * @stable\n */\nexport interface AutoRecallTriggers {\n /**\n * Case-insensitive regex set evaluated against the last user\n * message. A match indicates the model would benefit from the\n * top-K facts being injected into Layer 6.\n */\n readonly factTriggers: ReadonlyArray<RegExp>;\n}\n\n/**\n * Layer 1 template fragments. The `composeTemplate` function\n * picks the right fragment based on `memoryBaseMode`.\n *\n * @stable\n */\nexport interface BaseTemplateFragments {\n /** Full educational template (~250-350 tokens). */\n readonly full: string;\n /** Minimal template for high-end models (~80-120 tokens). */\n readonly minimal: string;\n}\n\n/**\n * D4 inbound-sanitization preamble fragment. Injected after the\n * cache breakpoint (Layer 5/6 territory) on steps containing\n * untrusted tool output.\n *\n * @stable\n */\nexport interface InboundSanitizationPreamble {\n /** Verbatim text appended to the system message when fired. */\n readonly text: string;\n}\n\n/**\n * Structured section-template fragments used by the auto-compaction\n * summarizer (RB-46). Section order is fixed; only the per-section\n * header / preamble text is locale-extensible.\n *\n * Each entry is the human-readable header for the corresponding\n * section. Section indices are 1-based to match the documented\n * layout in the architecture doc.\n *\n * @stable\n */\nexport interface CompactionSummaryTemplate {\n /** Preamble injected at the top of the summarizer prompt. */\n readonly preamble: string;\n /** 12 section headers. The last two are filled by the harness. */\n readonly sections: readonly [\n string, // 1: Session goal and current task\n string, // 2: Decisions made and rationale\n string, // 3: Constraints and non-negotiables (C4)\n string, // 4: Key facts established\n string, // 5: Open questions and ambiguities\n string, // 6: Tools used and their outcomes\n string, // 7: Files / artifacts referenced\n string, // 8: Persona / preferences / project rules surfaced\n string, // 9: Errors encountered and resolutions (SOTA-6)\n string, // 10: Next steps (SOTA-6)\n string, // 11: Recent turns preserved verbatim (harness-filled)\n string, // 12: Compaction metadata (harness-filled)\n ];\n}\n\n/**\n * A `LocalePack` collects every consumer-facing string the\n * ContextEngine renders. Consumers register additional locales via\n * {@link defineContextLocalePack}. The framework is locale-agnostic\n * - no language is privileged in core.\n *\n * @stable\n */\nexport interface ContextLocalePack {\n /** Stable lowercase identifier (`'en'`, `'de'`, `'fr'`, …). */\n readonly id: string;\n /** Layer 1 base template fragments. */\n readonly baseTemplate: BaseTemplateFragments;\n /** Auto-recall trigger regex set. */\n readonly autoRecallTriggers: AutoRecallTriggers;\n /** Inbound-sanitization preamble (D4 - RB-43). */\n readonly inboundSanitizationPreamble: InboundSanitizationPreamble;\n /** Structured compaction summary template (RB-46). */\n readonly compactionSummaryTemplate: CompactionSummaryTemplate;\n}\n\n/**\n * Builder used by application code that wants to ship a custom\n * locale pack. The builder freezes every input so the pack can be\n * safely reused across multiple `Memory` instances without\n * accidental mutation.\n *\n * Partial packs are accepted: any field omitted falls back to the\n * English default at compose time, with a one-time WARN per locale\n * per missing surface (the safety guarantee is preserved even when\n * an operator installs a partial locale pack).\n *\n * @stable\n */\nexport interface PartialContextLocalePack {\n readonly id: string;\n readonly baseTemplate?: Partial<BaseTemplateFragments>;\n readonly autoRecallTriggers?: Partial<AutoRecallTriggers>;\n readonly inboundSanitizationPreamble?: Partial<InboundSanitizationPreamble>;\n readonly compactionSummaryTemplate?: Partial<CompactionSummaryTemplate>;\n}\n\n/**\n * Build a {@link ContextLocalePack} from a partial input. Missing\n * fields fall back to the English default at compose time.\n *\n * @stable\n */\nexport function defineContextLocalePack(input: PartialContextLocalePack): PartialContextLocalePack {\n if (typeof input.id !== 'string' || input.id.length === 0) {\n throw new TypeError(\n '[graphorin/memory] defineContextLocalePack: `id` must be a non-empty lowercase string.',\n );\n }\n return Object.freeze({\n id: input.id,\n ...(input.baseTemplate !== undefined\n ? { baseTemplate: Object.freeze({ ...input.baseTemplate }) }\n : {}),\n ...(input.autoRecallTriggers !== undefined\n ? {\n autoRecallTriggers: Object.freeze({\n ...(input.autoRecallTriggers.factTriggers !== undefined\n ? { factTriggers: Object.freeze([...input.autoRecallTriggers.factTriggers]) }\n : {}),\n }) as Partial<AutoRecallTriggers>,\n }\n : {}),\n ...(input.inboundSanitizationPreamble !== undefined\n ? {\n inboundSanitizationPreamble: Object.freeze({ ...input.inboundSanitizationPreamble }),\n }\n : {}),\n ...(input.compactionSummaryTemplate !== undefined\n ? {\n compactionSummaryTemplate: Object.freeze({\n ...(input.compactionSummaryTemplate.preamble !== undefined\n ? { preamble: input.compactionSummaryTemplate.preamble }\n : {}),\n ...(input.compactionSummaryTemplate.sections !== undefined\n ? {\n sections: Object.freeze([\n ...input.compactionSummaryTemplate.sections,\n ]) as CompactionSummaryTemplate['sections'],\n }\n : {}),\n }) as Partial<CompactionSummaryTemplate>,\n }\n : {}),\n });\n}\n"],"mappings":";;;;;;;AAsIA,SAAgB,wBAAwB,OAA2D;AACjG,KAAI,OAAO,MAAM,OAAO,YAAY,MAAM,GAAG,WAAW,EACtD,OAAM,IAAI,UACR,yFACD;AAEH,QAAO,OAAO,OAAO;EACnB,IAAI,MAAM;EACV,GAAI,MAAM,iBAAiB,SACvB,EAAE,cAAc,OAAO,OAAO,EAAE,GAAG,MAAM,cAAc,CAAC,EAAE,GAC1D,EAAE;EACN,GAAI,MAAM,uBAAuB,SAC7B,EACE,oBAAoB,OAAO,OAAO,EAChC,GAAI,MAAM,mBAAmB,iBAAiB,SAC1C,EAAE,cAAc,OAAO,OAAO,CAAC,GAAG,MAAM,mBAAmB,aAAa,CAAC,EAAE,GAC3E,EAAE,EACP,CAAC,EACH,GACD,EAAE;EACN,GAAI,MAAM,gCAAgC,SACtC,EACE,6BAA6B,OAAO,OAAO,EAAE,GAAG,MAAM,6BAA6B,CAAC,EACrF,GACD,EAAE;EACN,GAAI,MAAM,8BAA8B,SACpC,EACE,2BAA2B,OAAO,OAAO;GACvC,GAAI,MAAM,0BAA0B,aAAa,SAC7C,EAAE,UAAU,MAAM,0BAA0B,UAAU,GACtD,EAAE;GACN,GAAI,MAAM,0BAA0B,aAAa,SAC7C,EACE,UAAU,OAAO,OAAO,CACtB,GAAG,MAAM,0BAA0B,SACpC,CAAC,EACH,GACD,EAAE;GACP,CAAC,EACH,GACD,EAAE;EACP,CAAC"}
@@ -54,8 +54,7 @@ type PrivacyDecisionReason = 'provider-rejects-secret' | 'provider-rejects-inter
54
54
  *
55
55
  * - `'loopback'` → `['public', 'internal', 'secret']`.
56
56
  * - `'private'` → `['public', 'internal']`.
57
- * - `'public-tls'` / `'public-mtls'` → `['public']`.
58
- * - `'public-cleartext'` → `['public']`.
57
+ * - `'public-tls'` / `'public-cleartext'` → `['public']`.
59
58
  *
60
59
  * Per-provider overrides always win over the defaults - pass
61
60
  * `providerAcceptsSensitivity` explicitly to override.
@@ -1 +1 @@
1
- {"version":3,"file":"privacy-filter.d.ts","names":[],"sources":["../../src/context-engine/privacy-filter.ts"],"sourcesContent":[],"mappings":";;;;;;;AAkHA;;;AAGwB,UAhGP,oBAAA,CAgGO;EAAkC;;AAiC1D;;EACiB,SAAA,0BAAA,CAAA,EA7HuB,aA6HvB,CA7HqC,WA6HrC,CAAA;EAEI;;;;;EAGA,SAAA,aAAA,CAAA,EA5HM,kBA4HN;EAAQ;AAQ7B;;;;EAEW,SAAA,kBAAA,CAAA,EAAA,OAAA;EACQ;;;;gCA5Ha;;;;;;;KAQpB,eAAA;;;;;;;KAQA,qBAAA;;;;;;;;;;;;;;;;;;iBAuBI,2BAAA,UACL,uBACR,cAAc;;;;;;;;;;;;;;iBA8BD,MAAA,oBACK,kCACV;qBACa;mBAAkC;;;;;;;;;UAiCzC;iBACA,cAAc;oBACX;qBACC;qBACA;;qBAEA,SAAS,OAAO;;;;;;;iBAQrB;yBAAmD;YACxD,cAAc,mBACd,uBACR,gBAAgB"}
1
+ {"version":3,"file":"privacy-filter.d.ts","names":[],"sources":["../../src/context-engine/privacy-filter.ts"],"sourcesContent":[],"mappings":";;;;;;;AAiHA;;;AAGwB,UA/FP,oBAAA,CA+FO;EAAkC;;AAiC1D;;EACiB,SAAA,0BAAA,CAAA,EA5HuB,aA4HvB,CA5HqC,WA4HrC,CAAA;EAEI;;;;;EAGA,SAAA,aAAA,CAAA,EA3HM,kBA2HN;EAAQ;AAQ7B;;;;EAEW,SAAA,kBAAA,CAAA,EAAA,OAAA;EACQ;;;;gCA3Ha;;;;;;;KAQpB,eAAA;;;;;;;KAQA,qBAAA;;;;;;;;;;;;;;;;;iBAsBI,2BAAA,UACL,uBACR,cAAc;;;;;;;;;;;;;;iBA8BD,MAAA,oBACK,kCACV;qBACa;mBAAkC;;;;;;;;;UAiCzC;iBACA,cAAc;oBACX;qBACC;qBACA;;qBAEA,SAAS,OAAO;;;;;;;iBAQrB;yBAAmD;YACxD,cAAc,mBACd,uBACR,gBAAgB"}
@@ -8,8 +8,7 @@
8
8
  *
9
9
  * - `'loopback'` → `['public', 'internal', 'secret']`.
10
10
  * - `'private'` → `['public', 'internal']`.
11
- * - `'public-tls'` / `'public-mtls'` → `['public']`.
12
- * - `'public-cleartext'` → `['public']`.
11
+ * - `'public-tls'` / `'public-cleartext'` → `['public']`.
13
12
  *
14
13
  * Per-provider overrides always win over the defaults - pass
15
14
  * `providerAcceptsSensitivity` explicitly to override.