@graphorin/memory 0.5.0 → 0.6.1

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 (236) hide show
  1. package/CHANGELOG.md +102 -1
  2. package/README.md +54 -37
  3. package/dist/conflict/index.d.ts +3 -1
  4. package/dist/conflict/index.js +1 -1
  5. package/dist/conflict/locale-packs/en.d.ts +13 -0
  6. package/dist/conflict/locale-packs/en.d.ts.map +1 -0
  7. package/dist/conflict/locale-packs/en.js +1 -1
  8. package/dist/conflict/locale-packs/en.js.map +1 -1
  9. package/dist/conflict/pipeline.d.ts +2 -2
  10. package/dist/conflict/pipeline.js +3 -3
  11. package/dist/conflict/pipeline.js.map +1 -1
  12. package/dist/conflict/stages/helpers.js +1 -1
  13. package/dist/conflict/stages/helpers.js.map +1 -1
  14. package/dist/conflict/stages/stage1-exact-dedup.js.map +1 -1
  15. package/dist/conflict/stages/stage2-embedding-three-zone.js.map +1 -1
  16. package/dist/conflict/stages/stage3-heuristic-regex.js +1 -1
  17. package/dist/conflict/stages/stage3-heuristic-regex.js.map +1 -1
  18. package/dist/conflict/stages/stage4-subject-predicate.js.map +1 -1
  19. package/dist/conflict/stages/stage5-defer-to-deep.js.map +1 -1
  20. package/dist/conflict/types.d.ts +7 -7
  21. package/dist/conflict/types.js +1 -1
  22. package/dist/conflict/types.js.map +1 -1
  23. package/dist/consolidator/budget.js +16 -3
  24. package/dist/consolidator/budget.js.map +1 -1
  25. package/dist/consolidator/decay.d.ts +13 -2
  26. package/dist/consolidator/decay.js +17 -5
  27. package/dist/consolidator/decay.js.map +1 -1
  28. package/dist/consolidator/dlq.js +1 -1
  29. package/dist/consolidator/dlq.js.map +1 -1
  30. package/dist/consolidator/errors.js +2 -2
  31. package/dist/consolidator/errors.js.map +1 -1
  32. package/dist/consolidator/index.js +8 -6
  33. package/dist/consolidator/index.js.map +1 -1
  34. package/dist/consolidator/lock.js +1 -1
  35. package/dist/consolidator/lock.js.map +1 -1
  36. package/dist/consolidator/noise-filter.js.map +1 -1
  37. package/dist/consolidator/phases/deep.js +6 -2
  38. package/dist/consolidator/phases/deep.js.map +1 -1
  39. package/dist/consolidator/phases/induce.d.ts +10 -10
  40. package/dist/consolidator/phases/induce.js +6 -6
  41. package/dist/consolidator/phases/induce.js.map +1 -1
  42. package/dist/consolidator/phases/learned-context.js +129 -0
  43. package/dist/consolidator/phases/learned-context.js.map +1 -0
  44. package/dist/consolidator/phases/light.js +2 -1
  45. package/dist/consolidator/phases/light.js.map +1 -1
  46. package/dist/consolidator/phases/reflect.js +5 -4
  47. package/dist/consolidator/phases/reflect.js.map +1 -1
  48. package/dist/consolidator/phases/standard.js +37 -8
  49. package/dist/consolidator/phases/standard.js.map +1 -1
  50. package/dist/consolidator/reconcile.js +1 -1
  51. package/dist/consolidator/reconcile.js.map +1 -1
  52. package/dist/consolidator/runtime.d.ts +4 -4
  53. package/dist/consolidator/runtime.d.ts.map +1 -1
  54. package/dist/consolidator/runtime.js +73 -16
  55. package/dist/consolidator/runtime.js.map +1 -1
  56. package/dist/consolidator/scheduler.d.ts +5 -5
  57. package/dist/consolidator/scheduler.js +1 -1
  58. package/dist/consolidator/scheduler.js.map +1 -1
  59. package/dist/consolidator/triggers.js +7 -7
  60. package/dist/consolidator/triggers.js.map +1 -1
  61. package/dist/consolidator/types.d.ts +68 -20
  62. package/dist/consolidator/types.d.ts.map +1 -1
  63. package/dist/consolidator/types.js +16 -6
  64. package/dist/consolidator/types.js.map +1 -1
  65. package/dist/context-engine/annotations.d.ts +9 -9
  66. package/dist/context-engine/annotations.js +3 -3
  67. package/dist/context-engine/annotations.js.map +1 -1
  68. package/dist/context-engine/auto-recall.js.map +1 -1
  69. package/dist/context-engine/compaction/clear-tool-results.d.ts +18 -3
  70. package/dist/context-engine/compaction/clear-tool-results.d.ts.map +1 -1
  71. package/dist/context-engine/compaction/clear-tool-results.js +26 -5
  72. package/dist/context-engine/compaction/clear-tool-results.js.map +1 -1
  73. package/dist/context-engine/compaction/compactor.js +19 -6
  74. package/dist/context-engine/compaction/compactor.js.map +1 -1
  75. package/dist/context-engine/compaction/hooks/reanchor-persona-block.js +4 -0
  76. package/dist/context-engine/compaction/hooks/reanchor-persona-block.js.map +1 -1
  77. package/dist/context-engine/compaction/hooks/reanchor-pinned-facts.js +1 -0
  78. package/dist/context-engine/compaction/hooks/reanchor-pinned-facts.js.map +1 -1
  79. package/dist/context-engine/compaction/hooks/reanchor-project-rules.js +2 -1
  80. package/dist/context-engine/compaction/hooks/reanchor-project-rules.js.map +1 -1
  81. package/dist/context-engine/compaction/hooks/reanchor-recent-results.d.ts +28 -0
  82. package/dist/context-engine/compaction/hooks/reanchor-recent-results.d.ts.map +1 -0
  83. package/dist/context-engine/compaction/hooks/reanchor-recent-results.js +71 -0
  84. package/dist/context-engine/compaction/hooks/reanchor-recent-results.js.map +1 -0
  85. package/dist/context-engine/compaction/hooks/types.d.ts +15 -3
  86. package/dist/context-engine/compaction/hooks/types.d.ts.map +1 -1
  87. package/dist/context-engine/compaction/index.d.ts +1 -0
  88. package/dist/context-engine/compaction/index.js +2 -1
  89. package/dist/context-engine/compaction/templates/summary-9-section.d.ts +10 -3
  90. package/dist/context-engine/compaction/templates/summary-9-section.d.ts.map +1 -1
  91. package/dist/context-engine/compaction/templates/summary-9-section.js +42 -5
  92. package/dist/context-engine/compaction/templates/summary-9-section.js.map +1 -1
  93. package/dist/context-engine/compaction/thresholds.js.map +1 -1
  94. package/dist/context-engine/compaction/types.d.ts +47 -7
  95. package/dist/context-engine/compaction/types.d.ts.map +1 -1
  96. package/dist/context-engine/engine.d.ts +23 -4
  97. package/dist/context-engine/engine.d.ts.map +1 -1
  98. package/dist/context-engine/engine.js +69 -15
  99. package/dist/context-engine/engine.js.map +1 -1
  100. package/dist/context-engine/index.d.ts +1 -0
  101. package/dist/context-engine/index.d.ts.map +1 -1
  102. package/dist/context-engine/index.js +2 -1
  103. package/dist/context-engine/locale-packs/en.js +14 -13
  104. package/dist/context-engine/locale-packs/en.js.map +1 -1
  105. package/dist/context-engine/locale-packs/types.d.ts +10 -10
  106. package/dist/context-engine/locale-packs/types.d.ts.map +1 -1
  107. package/dist/context-engine/locale-packs/types.js.map +1 -1
  108. package/dist/context-engine/metadata.d.ts +1 -1
  109. package/dist/context-engine/metadata.js +2 -2
  110. package/dist/context-engine/metadata.js.map +1 -1
  111. package/dist/context-engine/preambles/inbound-en.d.ts +1 -1
  112. package/dist/context-engine/preambles/inbound-en.js +1 -1
  113. package/dist/context-engine/preambles/inbound-en.js.map +1 -1
  114. package/dist/context-engine/privacy-filter.d.ts +2 -2
  115. package/dist/context-engine/privacy-filter.js +1 -1
  116. package/dist/context-engine/privacy-filter.js.map +1 -1
  117. package/dist/context-engine/templates/base-en.d.ts +1 -1
  118. package/dist/context-engine/templates/base-en.js +1 -1
  119. package/dist/context-engine/templates/base-en.js.map +1 -1
  120. package/dist/context-engine/templates/composer.d.ts +1 -1
  121. package/dist/context-engine/templates/composer.js.map +1 -1
  122. package/dist/context-engine/token-budget.d.ts +1 -1
  123. package/dist/context-engine/token-budget.js +1 -1
  124. package/dist/context-engine/token-budget.js.map +1 -1
  125. package/dist/context-engine/token-counter.d.ts +16 -7
  126. package/dist/context-engine/token-counter.d.ts.map +1 -1
  127. package/dist/context-engine/token-counter.js +31 -9
  128. package/dist/context-engine/token-counter.js.map +1 -1
  129. package/dist/errors/index.d.ts +2 -2
  130. package/dist/errors/index.js +4 -4
  131. package/dist/errors/index.js.map +1 -1
  132. package/dist/facade.d.ts +44 -15
  133. package/dist/facade.d.ts.map +1 -1
  134. package/dist/facade.js +16 -8
  135. package/dist/facade.js.map +1 -1
  136. package/dist/graph/entity-resolver.d.ts +2 -2
  137. package/dist/graph/entity-resolver.js +2 -2
  138. package/dist/graph/entity-resolver.js.map +1 -1
  139. package/dist/index.d.ts +9 -6
  140. package/dist/index.d.ts.map +1 -1
  141. package/dist/index.js +11 -5
  142. package/dist/index.js.map +1 -1
  143. package/dist/internal/contextualize.js +2 -2
  144. package/dist/internal/contextualize.js.map +1 -1
  145. package/dist/internal/embedder-binding.js +1 -1
  146. package/dist/internal/embedder-binding.js.map +1 -1
  147. package/dist/internal/id.js +1 -1
  148. package/dist/internal/id.js.map +1 -1
  149. package/dist/internal/injection-heuristics.js +25 -2
  150. package/dist/internal/injection-heuristics.js.map +1 -1
  151. package/dist/internal/spans.js +1 -1
  152. package/dist/internal/spans.js.map +1 -1
  153. package/dist/internal/storage-adapter.d.ts +71 -22
  154. package/dist/internal/storage-adapter.d.ts.map +1 -1
  155. package/dist/migration/embedder-migration.d.ts +7 -7
  156. package/dist/migration/embedder-migration.js.map +1 -1
  157. package/dist/package.js +6 -0
  158. package/dist/package.js.map +1 -0
  159. package/dist/search/explain.d.ts +7 -4
  160. package/dist/search/explain.d.ts.map +1 -1
  161. package/dist/search/explain.js +1 -1
  162. package/dist/search/explain.js.map +1 -1
  163. package/dist/search/fit-weights.d.ts +48 -0
  164. package/dist/search/fit-weights.d.ts.map +1 -0
  165. package/dist/search/fit-weights.js +70 -0
  166. package/dist/search/fit-weights.js.map +1 -0
  167. package/dist/search/graph-ppr.d.ts +36 -0
  168. package/dist/search/graph-ppr.d.ts.map +1 -0
  169. package/dist/search/graph-ppr.js +38 -0
  170. package/dist/search/graph-ppr.js.map +1 -0
  171. package/dist/search/index.d.ts +4 -1
  172. package/dist/search/index.js +4 -1
  173. package/dist/search/iterative.d.ts +15 -8
  174. package/dist/search/iterative.d.ts.map +1 -1
  175. package/dist/search/iterative.js +10 -9
  176. package/dist/search/iterative.js.map +1 -1
  177. package/dist/search/query-transform.d.ts +6 -6
  178. package/dist/search/query-transform.js +6 -6
  179. package/dist/search/query-transform.js.map +1 -1
  180. package/dist/search/rrf.d.ts +4 -4
  181. package/dist/search/rrf.js +4 -4
  182. package/dist/search/rrf.js.map +1 -1
  183. package/dist/search/trust.d.ts +30 -0
  184. package/dist/search/trust.d.ts.map +1 -0
  185. package/dist/search/trust.js +50 -0
  186. package/dist/search/trust.js.map +1 -0
  187. package/dist/search/types.d.ts +1 -1
  188. package/dist/tiers/episodic-memory.d.ts +6 -4
  189. package/dist/tiers/episodic-memory.d.ts.map +1 -1
  190. package/dist/tiers/episodic-memory.js +3 -2
  191. package/dist/tiers/episodic-memory.js.map +1 -1
  192. package/dist/tiers/index.d.ts +1 -1
  193. package/dist/tiers/index.js +1 -1
  194. package/dist/tiers/insight-memory.d.ts +4 -4
  195. package/dist/tiers/insight-memory.js +3 -3
  196. package/dist/tiers/insight-memory.js.map +1 -1
  197. package/dist/tiers/procedural-memory.d.ts +29 -7
  198. package/dist/tiers/procedural-memory.d.ts.map +1 -1
  199. package/dist/tiers/procedural-memory.js +66 -6
  200. package/dist/tiers/procedural-memory.js.map +1 -1
  201. package/dist/tiers/semantic-memory.d.ts +111 -30
  202. package/dist/tiers/semantic-memory.d.ts.map +1 -1
  203. package/dist/tiers/semantic-memory.js +120 -27
  204. package/dist/tiers/semantic-memory.js.map +1 -1
  205. package/dist/tiers/session-memory.d.ts +7 -7
  206. package/dist/tiers/session-memory.js +7 -7
  207. package/dist/tiers/session-memory.js.map +1 -1
  208. package/dist/tiers/shared-memory.d.ts +1 -1
  209. package/dist/tiers/shared-memory.js +1 -1
  210. package/dist/tiers/shared-memory.js.map +1 -1
  211. package/dist/tiers/working-memory.d.ts +3 -3
  212. package/dist/tiers/working-memory.js +2 -2
  213. package/dist/tiers/working-memory.js.map +1 -1
  214. package/dist/tools/block-tools.d.ts +3 -3
  215. package/dist/tools/block-tools.js +3 -3
  216. package/dist/tools/block-tools.js.map +1 -1
  217. package/dist/tools/fact-tools.d.ts +48 -31
  218. package/dist/tools/fact-tools.d.ts.map +1 -1
  219. package/dist/tools/fact-tools.js +30 -18
  220. package/dist/tools/fact-tools.js.map +1 -1
  221. package/dist/tools/index.d.ts +9 -2
  222. package/dist/tools/index.d.ts.map +1 -1
  223. package/dist/tools/index.js +4 -2
  224. package/dist/tools/index.js.map +1 -1
  225. package/dist/tools/recall-tools.d.ts +40 -20
  226. package/dist/tools/recall-tools.d.ts.map +1 -1
  227. package/dist/tools/recall-tools.js +29 -10
  228. package/dist/tools/recall-tools.js.map +1 -1
  229. package/dist/tools/runbook-tools.d.ts +76 -0
  230. package/dist/tools/runbook-tools.d.ts.map +1 -0
  231. package/dist/tools/runbook-tools.js +53 -0
  232. package/dist/tools/runbook-tools.js.map +1 -0
  233. package/dist/tools/taint.js +33 -0
  234. package/dist/tools/taint.js.map +1 -0
  235. package/dist/tools/types.d.ts +1 -1
  236. package/package.json +8 -8
@@ -1 +1 @@
1
- {"version":3,"file":"fact-tools.js","names":[],"sources":["../../src/tools/fact-tools.ts"],"sourcesContent":["import type { Tool } from '@graphorin/core';\nimport { tool } from '@graphorin/tools';\nimport { z } from 'zod';\nimport type { MemoryToolDeps } from './types.js';\n\nconst sensitivityEnum = z.enum(['public', 'internal', 'secret']);\nconst provenanceEnum = z.enum([\n 'user',\n 'tool',\n 'extraction',\n 'reflection',\n 'induction',\n 'imported',\n]);\n\nconst factRememberInputSchema = z.object({\n text: z.string().min(1).max(8192),\n tags: z.array(z.string().min(1).max(64)).max(32).optional(),\n confidence: z.number().min(0).max(1).optional(),\n sensitivity: sensitivityEnum.optional(),\n validFrom: z.string().datetime().optional(),\n validTo: z.string().datetime().optional(),\n});\nconst factRememberOutputSchema = z.object({\n factId: z.string(),\n /**\n * MRET-3: `true` when the write landed in quarantine (hidden from\n * default recall until validated). A synthesized consolidator write or\n * a candidate that tripped the injection heuristics quarantines.\n */\n quarantined: z.boolean(),\n /** Why it was quarantined, when it was. */\n quarantineReason: z.enum(['injection', 'synthesized']).optional(),\n});\n\ntype FactRememberInput = z.infer<typeof factRememberInputSchema>;\ntype FactRememberOutput = z.infer<typeof factRememberOutputSchema>;\n\nconst factSearchInputSchema = z.object({\n query: z.string().min(1).max(1024),\n topK: z.number().int().positive().max(50).optional(),\n tags: z.array(z.string().min(1)).max(16).optional(),\n asOf: z.string().datetime().optional(),\n});\nconst factSearchOutputSchema = z.object({\n hits: z.array(\n z.object({\n factId: z.string(),\n text: z.string(),\n score: z.number(),\n sensitivity: sensitivityEnum,\n provenance: provenanceEnum.optional(),\n }),\n ),\n});\n\ntype FactSearchInput = z.infer<typeof factSearchInputSchema>;\ntype FactSearchOutput = z.infer<typeof factSearchOutputSchema>;\n\nconst factSupersedeInputSchema = z.object({\n oldId: z.string().min(1),\n newText: z.string().min(1).max(8192),\n reason: z.string().max(512).optional(),\n});\nconst factSupersedeOutputSchema = z.object({\n oldId: z.string(),\n newId: z.string(),\n});\n\ntype FactSupersedeInput = z.infer<typeof factSupersedeInputSchema>;\ntype FactSupersedeOutput = z.infer<typeof factSupersedeOutputSchema>;\n\nconst factForgetInputSchema = z.object({\n factId: z.string().min(1),\n reason: z.string().max(512).optional(),\n});\nconst factForgetOutputSchema = z.object({\n factId: z.string(),\n forgotten: z.boolean(),\n});\n\ntype FactForgetInput = z.infer<typeof factForgetInputSchema>;\ntype FactForgetOutput = z.infer<typeof factForgetOutputSchema>;\n\nconst factHistoryInputSchema = z.object({\n factId: z.string().min(1),\n});\nconst factHistoryOutputSchema = z.object({\n chain: z.array(\n z.object({\n factId: z.string(),\n text: z.string(),\n validFrom: z.string().optional(),\n validTo: z.string().optional(),\n supersedes: z.string().optional(),\n supersededBy: z.string().optional(),\n sensitivity: sensitivityEnum,\n }),\n ),\n});\n\ntype FactHistoryInput = z.infer<typeof factHistoryInputSchema>;\ntype FactHistoryOutput = z.infer<typeof factHistoryOutputSchema>;\n\nconst factValidateInputSchema = z.object({\n factId: z.string().min(1),\n reason: z.string().max(512).optional(),\n});\nconst factValidateOutputSchema = z.object({\n factId: z.string(),\n validated: z.boolean(),\n});\n\ntype FactValidateInput = z.infer<typeof factValidateInputSchema>;\ntype FactValidateOutput = z.infer<typeof factValidateOutputSchema>;\n\n/**\n * `fact_remember` — persist a single semantic fact. The minimum-viable\n * pipeline writes the fact straight through with MD5 deduplication;\n * Phase 10b extends the body with the multi-stage conflict resolution.\n *\n * @stable\n */\nexport function createFactRememberTool(\n deps: MemoryToolDeps,\n): Tool<FactRememberInput, FactRememberOutput> {\n return tool<FactRememberInput, FactRememberOutput>({\n name: 'fact_remember',\n description:\n 'Persist an atomic factual statement about the user, the world, or the current session. Prefer one fact per call; the system applies dedup + conflict resolution downstream. Pass `validFrom` / `validTo` for bi-temporal facts and `sensitivity` to control redaction.',\n inputSchema: factRememberInputSchema,\n outputSchema: factRememberOutputSchema,\n sideEffectClass: 'side-effecting',\n sandboxPolicy: 'none',\n sensitivity: 'internal',\n memoryGuardTier: 'memory-aware',\n tags: ['memory', 'semantic'],\n async execute(input, ctx) {\n const scope = await deps.resolveScope(ctx);\n const outcome = await deps.semantic.rememberWithDecision(scope, {\n text: input.text,\n ...(input.tags !== undefined ? { tags: input.tags } : {}),\n ...(input.confidence !== undefined ? { confidence: input.confidence } : {}),\n ...(input.sensitivity !== undefined ? { sensitivity: input.sensitivity } : {}),\n ...(input.validFrom !== undefined ? { validFrom: input.validFrom } : {}),\n ...(input.validTo !== undefined ? { validTo: input.validTo } : {}),\n });\n // MRET-3: tell the caller when the write was quarantined so a\n // poisoned fact cannot masquerade as a normally-stored one.\n return {\n factId: outcome.fact.id,\n quarantined: outcome.fact.status === 'quarantined',\n ...(outcome.quarantineReason !== undefined\n ? { quarantineReason: outcome.quarantineReason }\n : {}),\n };\n },\n });\n}\n\n/**\n * `fact_search` — hybrid (vector + FTS5) search over the user's\n * semantic memory. Results merged through the configured reranker.\n *\n * @stable\n */\nexport function createFactSearchTool(\n deps: MemoryToolDeps,\n): Tool<FactSearchInput, FactSearchOutput> {\n return tool<FactSearchInput, FactSearchOutput>({\n name: 'fact_search',\n description:\n \"Search the user's long-term factual memory by natural-language query. Returns up to `topK` matched facts with their score and sensitivity. Use this BEFORE asking the user a question they may have answered earlier. Pass `asOf` (ISO-8601) to read memory as it was at a past instant — point-in-time / 'what was true on date X' — instead of the current state.\",\n inputSchema: factSearchInputSchema,\n outputSchema: factSearchOutputSchema,\n sideEffectClass: 'read-only',\n sandboxPolicy: 'none',\n sensitivity: 'internal',\n memoryGuardTier: 'pure',\n tags: ['memory', 'semantic'],\n async execute(input, ctx) {\n const scope = await deps.resolveScope(ctx);\n const hits = await deps.semantic.search(scope, input.query, {\n ...(input.topK !== undefined ? { topK: input.topK } : {}),\n // MRET-4: forward the tags filter — it was accepted by the\n // schema and silently dropped here.\n ...(input.tags !== undefined && input.tags.length > 0 ? { tags: input.tags } : {}),\n ...(input.asOf !== undefined ? { asOf: input.asOf } : {}),\n signal: ctx.signal,\n });\n return {\n hits: hits.map((hit) => ({\n factId: hit.record.id,\n text: hit.record.text,\n score: hit.score,\n sensitivity: hit.record.sensitivity,\n ...(hit.record.provenance !== undefined ? { provenance: hit.record.provenance } : {}),\n })),\n };\n },\n });\n}\n\n/**\n * `fact_supersede` — soft-supersede an old fact by storing a new one\n * that replaces it. The old fact is kept for replay but ranked below\n * the new one.\n *\n * @stable\n */\nexport function createFactSupersedeTool(\n deps: MemoryToolDeps,\n): Tool<FactSupersedeInput, FactSupersedeOutput> {\n return tool<FactSupersedeInput, FactSupersedeOutput>({\n name: 'fact_supersede',\n description:\n \"Mark an old fact superseded by a new one. Use this when the user's situation changed (moved cities, updated a goal, switched a preference) — the old fact is preserved for replay but no longer surfaced as current.\",\n inputSchema: factSupersedeInputSchema,\n outputSchema: factSupersedeOutputSchema,\n sideEffectClass: 'side-effecting',\n sandboxPolicy: 'none',\n sensitivity: 'internal',\n memoryGuardTier: 'memory-aware',\n tags: ['memory', 'semantic'],\n async execute(input, ctx) {\n const scope = await deps.resolveScope(ctx);\n const result = await deps.semantic.supersede(\n scope,\n input.oldId,\n { text: input.newText },\n input.reason,\n );\n return { oldId: result.old, newId: result.new.id };\n },\n });\n}\n\n/**\n * `fact_forget` — soft-delete a fact (kept for replay; never hard-\n * deleted at this layer).\n *\n * @stable\n */\nexport function createFactForgetTool(\n deps: MemoryToolDeps,\n): Tool<FactForgetInput, FactForgetOutput> {\n return tool<FactForgetInput, FactForgetOutput>({\n name: 'fact_forget',\n description:\n 'Soft-delete a fact. The record is preserved for replay but no longer surfaced by fact_search. Use only for explicit user-driven removal (privacy / user request).',\n inputSchema: factForgetInputSchema,\n outputSchema: factForgetOutputSchema,\n sideEffectClass: 'side-effecting',\n sandboxPolicy: 'none',\n sensitivity: 'internal',\n memoryGuardTier: 'memory-aware',\n tags: ['memory', 'semantic'],\n async execute(input, ctx) {\n const scope = await deps.resolveScope(ctx);\n await deps.semantic.forget(scope, input.factId, input.reason);\n return { factId: input.factId, forgotten: true };\n },\n });\n}\n\n/**\n * `fact_history` — trace how a fact changed over time. Returns the\n * full bi-temporal supersede chain the given fact belongs to, oldest →\n * newest, including superseded entries, so the agent can answer \"what\n * did the user say before\" / \"how did this change\". Read-only. P0-2.\n *\n * @stable\n */\nexport function createFactHistoryTool(\n deps: MemoryToolDeps,\n): Tool<FactHistoryInput, FactHistoryOutput> {\n return tool<FactHistoryInput, FactHistoryOutput>({\n name: 'fact_history',\n description:\n \"Trace how a fact changed over time. Given a factId, returns its full bi-temporal supersede chain (oldest → newest), including superseded entries, with each entry's validFrom/validTo. Use this to answer 'how did this change' or 'what was the previous value'.\",\n inputSchema: factHistoryInputSchema,\n outputSchema: factHistoryOutputSchema,\n sideEffectClass: 'read-only',\n sandboxPolicy: 'none',\n sensitivity: 'internal',\n memoryGuardTier: 'pure',\n tags: ['memory', 'semantic', 'temporal'],\n async execute(input, ctx) {\n const scope = await deps.resolveScope(ctx);\n const chain = await deps.semantic.history(scope, input.factId);\n return {\n chain: chain.map((f) => ({\n factId: f.id,\n text: f.text,\n ...(f.validFrom !== undefined ? { validFrom: f.validFrom } : {}),\n ...(f.validTo !== undefined ? { validTo: f.validTo } : {}),\n ...(f.supersedes !== undefined ? { supersedes: f.supersedes } : {}),\n ...(f.supersededBy !== undefined ? { supersededBy: f.supersededBy } : {}),\n sensitivity: f.sensitivity,\n })),\n };\n },\n });\n}\n\n/**\n * `fact_validate` — promote a quarantined fact to active (P1-4). The\n * validation path that admits a synthesized (consolidator / reflection)\n * memory into action-driving recall once it has been reviewed; the\n * promotion is audited in `memory_history`.\n *\n * MRET-3 / MST-1 — two gates close the one-turn memory-poisoning chain\n * (`fact_remember(poison)` → `fact_validate(id)` → active recall):\n *\n * 1. `needsApproval: true` — the run suspends for a human decision\n * before this tool ever executes, so the agent cannot silently\n * promote any quarantined fact.\n * 2. The underlying `SemanticMemory.validate(...)` re-checks the fact's\n * text against the injection heuristics and **refuses** (no `force`\n * is passed here) — an injection-flagged memory cannot be promoted by\n * the agent at all. Only an operator, via the programmatic API with\n * `{ force: true }`, can override after review.\n *\n * Synthesized-but-clean consolidator writes promote normally once\n * approved.\n *\n * @stable\n */\nexport function createFactValidateTool(\n deps: MemoryToolDeps,\n): Tool<FactValidateInput, FactValidateOutput> {\n return tool<FactValidateInput, FactValidateOutput>({\n name: 'fact_validate',\n description:\n 'Promote a quarantined fact to active so it becomes eligible for normal recall. Quarantined facts are memories the system synthesized or flagged as risky; validating one is a deliberate, human-approved admission and never a routine step. This action requires approval, and facts flagged as prompt-injection cannot be promoted here — they are an operator-only decision.',\n inputSchema: factValidateInputSchema,\n outputSchema: factValidateOutputSchema,\n // MRET-3: the only real gate on a model-callable tool — suspend the\n // run for a human decision before promoting anything out of quarantine.\n needsApproval: true,\n sideEffectClass: 'side-effecting',\n sandboxPolicy: 'none',\n sensitivity: 'internal',\n memoryGuardTier: 'memory-aware',\n tags: ['memory', 'semantic', 'safety'],\n async execute(input, ctx) {\n const scope = await deps.resolveScope(ctx);\n // No `force`: the agent path can never promote an injection-flagged\n // fact (validate throws QuarantinePromotionRefusedError for those).\n await deps.semantic.validate(scope, input.factId, input.reason);\n return { factId: input.factId, validated: true };\n },\n });\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"fact-tools.js","names":[],"sources":["../../src/tools/fact-tools.ts"],"sourcesContent":["import type { Tool } from '@graphorin/core';\nimport { tool } from '@graphorin/tools';\nimport { z } from 'zod';\nimport { recallTaint } from './taint.js';\nimport type { MemoryToolDeps } from './types.js';\n\nconst sensitivityEnum = z.enum(['public', 'internal', 'secret']);\nconst provenanceEnum = z.enum([\n 'user',\n 'tool',\n 'extraction',\n 'reflection',\n 'induction',\n 'imported',\n]);\n\nconst factRememberInputSchema = z.object({\n text: z.string().min(1).max(8192),\n tags: z.array(z.string().min(1).max(64)).max(32).optional(),\n confidence: z.number().min(0).max(1).optional(),\n sensitivity: sensitivityEnum.optional(),\n validFrom: z.string().datetime().optional(),\n validTo: z.string().datetime().optional(),\n});\nconst factRememberOutputSchema = z.object({\n factId: z.string(),\n /**\n * MRET-3: `true` when the write landed in quarantine (hidden from\n * default recall until validated). A synthesized consolidator write or\n * a candidate that tripped the injection heuristics quarantines.\n */\n quarantined: z.boolean(),\n /** Why it was quarantined, when it was. */\n quarantineReason: z.enum(['injection', 'synthesized']).optional(),\n});\n\ntype FactRememberInput = z.infer<typeof factRememberInputSchema>;\ntype FactRememberOutput = z.infer<typeof factRememberOutputSchema>;\n\nconst factSearchInputSchema = z.object({\n query: z.string().min(1).max(1024),\n topK: z.number().int().positive().max(50).optional(),\n tags: z.array(z.string().min(1)).max(16).optional(),\n asOf: z.string().datetime().optional(),\n});\nconst factSearchOutputSchema = z.object({\n hits: z.array(\n z.object({\n factId: z.string(),\n text: z.string(),\n score: z.number(),\n sensitivity: sensitivityEnum,\n provenance: provenanceEnum.optional(),\n /**\n * Set when the fact's validity interval was closed (superseded /\n * expired). Only present on `asOf` reads - default reads exclude\n * such facts entirely (memory-retrieval-01).\n */\n validTo: z.string().optional(),\n /** Id of the fact that superseded this one, when any. */\n supersededBy: z.string().optional(),\n }),\n ),\n});\n\ntype FactSearchInput = z.infer<typeof factSearchInputSchema>;\ntype FactSearchOutput = z.infer<typeof factSearchOutputSchema>;\n\nconst factSupersedeInputSchema = z.object({\n oldId: z.string().min(1),\n newText: z.string().min(1).max(8192),\n reason: z.string().max(512).optional(),\n});\nconst factSupersedeOutputSchema = z.object({\n oldId: z.string(),\n newId: z.string(),\n});\n\ntype FactSupersedeInput = z.infer<typeof factSupersedeInputSchema>;\ntype FactSupersedeOutput = z.infer<typeof factSupersedeOutputSchema>;\n\nconst factForgetInputSchema = z.object({\n factId: z.string().min(1),\n reason: z.string().max(512).optional(),\n});\nconst factForgetOutputSchema = z.object({\n factId: z.string(),\n forgotten: z.boolean(),\n});\n\ntype FactForgetInput = z.infer<typeof factForgetInputSchema>;\ntype FactForgetOutput = z.infer<typeof factForgetOutputSchema>;\n\nconst factHistoryInputSchema = z.object({\n factId: z.string().min(1),\n});\nconst factHistoryOutputSchema = z.object({\n chain: z.array(\n z.object({\n factId: z.string(),\n text: z.string(),\n validFrom: z.string().optional(),\n validTo: z.string().optional(),\n supersedes: z.string().optional(),\n supersededBy: z.string().optional(),\n sensitivity: sensitivityEnum,\n }),\n ),\n});\n\ntype FactHistoryInput = z.infer<typeof factHistoryInputSchema>;\ntype FactHistoryOutput = z.infer<typeof factHistoryOutputSchema>;\n\nconst factValidateInputSchema = z.object({\n factId: z.string().min(1),\n reason: z.string().max(512).optional(),\n});\nconst factValidateOutputSchema = z.object({\n factId: z.string(),\n validated: z.boolean(),\n});\n\ntype FactValidateInput = z.infer<typeof factValidateInputSchema>;\ntype FactValidateOutput = z.infer<typeof factValidateOutputSchema>;\n\n/**\n * `fact_remember` - persist a single semantic fact. The minimum-viable\n * pipeline writes the fact straight through with MD5 deduplication;\n * Phase 10b extends the body with the multi-stage conflict resolution.\n *\n * @stable\n */\nexport function createFactRememberTool(\n deps: MemoryToolDeps,\n): Tool<FactRememberInput, FactRememberOutput> {\n return tool<FactRememberInput, FactRememberOutput>({\n name: 'fact_remember',\n description:\n 'Persist an atomic factual statement about the user, the world, or the current session. Prefer one fact per call; the system applies dedup + conflict resolution downstream. Pass `validFrom` / `validTo` for bi-temporal facts and `sensitivity` to control redaction.',\n inputSchema: factRememberInputSchema,\n outputSchema: factRememberOutputSchema,\n sideEffectClass: 'side-effecting',\n sandboxPolicy: 'none',\n sensitivity: 'internal',\n memoryGuardTier: 'memory-aware',\n tags: ['memory', 'semantic'],\n async execute(input, ctx) {\n const scope = await deps.resolveScope(ctx);\n const outcome = await deps.semantic.rememberWithDecision(scope, {\n text: input.text,\n ...(input.tags !== undefined ? { tags: input.tags } : {}),\n ...(input.confidence !== undefined ? { confidence: input.confidence } : {}),\n ...(input.sensitivity !== undefined ? { sensitivity: input.sensitivity } : {}),\n ...(input.validFrom !== undefined ? { validFrom: input.validFrom } : {}),\n ...(input.validTo !== undefined ? { validTo: input.validTo } : {}),\n });\n // MRET-3: tell the caller when the write was quarantined so a\n // poisoned fact cannot masquerade as a normally-stored one.\n return {\n factId: outcome.fact.id,\n quarantined: outcome.fact.status === 'quarantined',\n ...(outcome.quarantineReason !== undefined\n ? { quarantineReason: outcome.quarantineReason }\n : {}),\n };\n },\n });\n}\n\n/**\n * `fact_search` - hybrid (vector + FTS5) search over the user's\n * semantic memory. Results merged through the configured reranker.\n *\n * @stable\n */\nexport function createFactSearchTool(\n deps: MemoryToolDeps,\n): Tool<FactSearchInput, FactSearchOutput> {\n return tool<FactSearchInput, FactSearchOutput>({\n name: 'fact_search',\n description:\n \"Search the user's long-term factual memory by natural-language query. Returns up to `topK` matched facts with their score and sensitivity. Use this BEFORE asking the user a question they may have answered earlier. Pass `asOf` (ISO-8601) to read memory as it was at a past instant - point-in-time / 'what was true on date X' - instead of the current state.\",\n inputSchema: factSearchInputSchema,\n outputSchema: factSearchOutputSchema,\n sideEffectClass: 'read-only',\n sandboxPolicy: 'none',\n sensitivity: 'internal',\n memoryGuardTier: 'pure',\n tags: ['memory', 'semantic'],\n async execute(input, ctx) {\n const scope = await deps.resolveScope(ctx);\n const hits = await deps.semantic.search(scope, input.query, {\n ...(input.topK !== undefined ? { topK: input.topK } : {}),\n // MRET-4: forward the tags filter - it was accepted by the\n // schema and silently dropped here.\n ...(input.tags !== undefined && input.tags.length > 0 ? { tags: input.tags } : {}),\n ...(input.asOf !== undefined ? { asOf: input.asOf } : {}),\n signal: ctx.signal,\n });\n const output = {\n hits: hits.map((hit) => ({\n factId: hit.record.id,\n text: hit.record.text,\n score: hit.score,\n sensitivity: hit.record.sensitivity,\n ...(hit.record.provenance !== undefined ? { provenance: hit.record.provenance } : {}),\n // memory-retrieval-01: surface validity metadata so the model\n // can tell a historical (asOf) hit from a current one.\n ...(hit.record.validTo !== undefined ? { validTo: hit.record.validTo } : {}),\n ...(hit.record.supersededBy !== undefined\n ? { supersededBy: hit.record.supersededBy }\n : {}),\n })),\n };\n // C6: recalled quarantined / foreign-provenance content re-arms the\n // taint ledger - the cross-session poisoning leg.\n const taint = recallTaint(hits.map((h) => h.record));\n return taint === undefined ? output : { output, taint };\n },\n });\n}\n\n/**\n * `fact_supersede` - soft-supersede an old fact by storing a new one\n * that replaces it. The old fact is kept for replay but no longer\n * surfaced by default reads (they evaluate validity at NOW); it stays\n * reachable via `asOf` / inspector paths.\n *\n * @stable\n */\nexport function createFactSupersedeTool(\n deps: MemoryToolDeps,\n): Tool<FactSupersedeInput, FactSupersedeOutput> {\n return tool<FactSupersedeInput, FactSupersedeOutput>({\n name: 'fact_supersede',\n description:\n \"Mark an old fact superseded by a new one. Use this when the user's situation changed (moved cities, updated a goal, switched a preference) - the old fact is preserved for replay but no longer surfaced as current.\",\n inputSchema: factSupersedeInputSchema,\n outputSchema: factSupersedeOutputSchema,\n sideEffectClass: 'side-effecting',\n sandboxPolicy: 'none',\n sensitivity: 'internal',\n memoryGuardTier: 'memory-aware',\n tags: ['memory', 'semantic'],\n async execute(input, ctx) {\n const scope = await deps.resolveScope(ctx);\n const result = await deps.semantic.supersede(\n scope,\n input.oldId,\n { text: input.newText },\n input.reason,\n );\n return { oldId: result.old, newId: result.new.id };\n },\n });\n}\n\n/**\n * `fact_forget` - soft-delete a fact (kept for replay; never hard-\n * deleted at this layer).\n *\n * @stable\n */\nexport function createFactForgetTool(\n deps: MemoryToolDeps,\n): Tool<FactForgetInput, FactForgetOutput> {\n return tool<FactForgetInput, FactForgetOutput>({\n name: 'fact_forget',\n description:\n 'Soft-delete a fact. The record is preserved for replay but no longer surfaced by fact_search. Use only for explicit user-driven removal (privacy / user request).',\n inputSchema: factForgetInputSchema,\n outputSchema: factForgetOutputSchema,\n sideEffectClass: 'side-effecting',\n sandboxPolicy: 'none',\n sensitivity: 'internal',\n memoryGuardTier: 'memory-aware',\n tags: ['memory', 'semantic'],\n async execute(input, ctx) {\n const scope = await deps.resolveScope(ctx);\n await deps.semantic.forget(scope, input.factId, input.reason);\n return { factId: input.factId, forgotten: true };\n },\n });\n}\n\n/**\n * `fact_history` - trace how a fact changed over time. Returns the\n * full bi-temporal supersede chain the given fact belongs to, oldest →\n * newest, including superseded entries, so the agent can answer \"what\n * did the user say before\" / \"how did this change\". Read-only. P0-2.\n *\n * @stable\n */\nexport function createFactHistoryTool(\n deps: MemoryToolDeps,\n): Tool<FactHistoryInput, FactHistoryOutput> {\n return tool<FactHistoryInput, FactHistoryOutput>({\n name: 'fact_history',\n description:\n \"Trace how a fact changed over time. Given a factId, returns its full bi-temporal supersede chain (oldest → newest), including superseded entries, with each entry's validFrom/validTo. Use this to answer 'how did this change' or 'what was the previous value'.\",\n inputSchema: factHistoryInputSchema,\n outputSchema: factHistoryOutputSchema,\n sideEffectClass: 'read-only',\n sandboxPolicy: 'none',\n sensitivity: 'internal',\n memoryGuardTier: 'pure',\n tags: ['memory', 'semantic', 'temporal'],\n async execute(input, ctx) {\n const scope = await deps.resolveScope(ctx);\n const chain = await deps.semantic.history(scope, input.factId);\n return {\n chain: chain.map((f) => ({\n factId: f.id,\n text: f.text,\n ...(f.validFrom !== undefined ? { validFrom: f.validFrom } : {}),\n ...(f.validTo !== undefined ? { validTo: f.validTo } : {}),\n ...(f.supersedes !== undefined ? { supersedes: f.supersedes } : {}),\n ...(f.supersededBy !== undefined ? { supersededBy: f.supersededBy } : {}),\n sensitivity: f.sensitivity,\n })),\n };\n },\n });\n}\n\n/**\n * `fact_validate` - promote a quarantined fact to active (P1-4). The\n * validation path that admits a synthesized (consolidator / reflection)\n * memory into action-driving recall once it has been reviewed; the\n * promotion is audited in `memory_history`.\n *\n * MRET-3 / MST-1 - two gates close the one-turn memory-poisoning chain\n * (`fact_remember(poison)` → `fact_validate(id)` → active recall):\n *\n * 1. `needsApproval: true` - the run suspends for a human decision\n * before this tool ever executes, so the agent cannot silently\n * promote any quarantined fact.\n * 2. The underlying `SemanticMemory.validate(...)` re-checks the fact's\n * text against the injection heuristics and **refuses** (no `force`\n * is passed here) - an injection-flagged memory cannot be promoted by\n * the agent at all. Only an operator, via the programmatic API with\n * `{ force: true }`, can override after review.\n *\n * Synthesized-but-clean consolidator writes promote normally once\n * approved.\n *\n * @stable\n */\nexport function createFactValidateTool(\n deps: MemoryToolDeps,\n): Tool<FactValidateInput, FactValidateOutput> {\n return tool<FactValidateInput, FactValidateOutput>({\n name: 'fact_validate',\n description:\n 'Promote a quarantined fact to active so it becomes eligible for normal recall. Quarantined facts are memories the system synthesized or flagged as risky; validating one is a deliberate, human-approved admission and never a routine step. This action requires approval, and facts flagged as prompt-injection cannot be promoted here - they are an operator-only decision.',\n inputSchema: factValidateInputSchema,\n outputSchema: factValidateOutputSchema,\n // MRET-3: the only real gate on a model-callable tool - suspend the\n // run for a human decision before promoting anything out of quarantine.\n needsApproval: true,\n sideEffectClass: 'side-effecting',\n sandboxPolicy: 'none',\n sensitivity: 'internal',\n memoryGuardTier: 'memory-aware',\n tags: ['memory', 'semantic', 'safety'],\n async execute(input, ctx) {\n const scope = await deps.resolveScope(ctx);\n // No `force`: the agent path can never promote an injection-flagged\n // fact (validate throws QuarantinePromotionRefusedError for those).\n await deps.semantic.validate(scope, input.factId, input.reason);\n return { factId: input.factId, validated: true };\n },\n });\n}\n"],"mappings":";;;;;AAMA,MAAM,kBAAkB,EAAE,KAAK;CAAC;CAAU;CAAY;CAAS,CAAC;AAChE,MAAM,iBAAiB,EAAE,KAAK;CAC5B;CACA;CACA;CACA;CACA;CACA;CACD,CAAC;AAEF,MAAM,0BAA0B,EAAE,OAAO;CACvC,MAAM,EAAE,QAAQ,CAAC,IAAI,EAAE,CAAC,IAAI,KAAK;CACjC,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,IAAI,EAAE,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,GAAG,CAAC,UAAU;CAC3D,YAAY,EAAE,QAAQ,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC,UAAU;CAC/C,aAAa,gBAAgB,UAAU;CACvC,WAAW,EAAE,QAAQ,CAAC,UAAU,CAAC,UAAU;CAC3C,SAAS,EAAE,QAAQ,CAAC,UAAU,CAAC,UAAU;CAC1C,CAAC;AACF,MAAM,2BAA2B,EAAE,OAAO;CACxC,QAAQ,EAAE,QAAQ;CAMlB,aAAa,EAAE,SAAS;CAExB,kBAAkB,EAAE,KAAK,CAAC,aAAa,cAAc,CAAC,CAAC,UAAU;CAClE,CAAC;AAKF,MAAM,wBAAwB,EAAE,OAAO;CACrC,OAAO,EAAE,QAAQ,CAAC,IAAI,EAAE,CAAC,IAAI,KAAK;CAClC,MAAM,EAAE,QAAQ,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,GAAG,CAAC,UAAU;CACpD,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,GAAG,CAAC,UAAU;CACnD,MAAM,EAAE,QAAQ,CAAC,UAAU,CAAC,UAAU;CACvC,CAAC;AACF,MAAM,yBAAyB,EAAE,OAAO,EACtC,MAAM,EAAE,MACN,EAAE,OAAO;CACP,QAAQ,EAAE,QAAQ;CAClB,MAAM,EAAE,QAAQ;CAChB,OAAO,EAAE,QAAQ;CACjB,aAAa;CACb,YAAY,eAAe,UAAU;CAMrC,SAAS,EAAE,QAAQ,CAAC,UAAU;CAE9B,cAAc,EAAE,QAAQ,CAAC,UAAU;CACpC,CAAC,CACH,EACF,CAAC;AAKF,MAAM,2BAA2B,EAAE,OAAO;CACxC,OAAO,EAAE,QAAQ,CAAC,IAAI,EAAE;CACxB,SAAS,EAAE,QAAQ,CAAC,IAAI,EAAE,CAAC,IAAI,KAAK;CACpC,QAAQ,EAAE,QAAQ,CAAC,IAAI,IAAI,CAAC,UAAU;CACvC,CAAC;AACF,MAAM,4BAA4B,EAAE,OAAO;CACzC,OAAO,EAAE,QAAQ;CACjB,OAAO,EAAE,QAAQ;CAClB,CAAC;AAKF,MAAM,wBAAwB,EAAE,OAAO;CACrC,QAAQ,EAAE,QAAQ,CAAC,IAAI,EAAE;CACzB,QAAQ,EAAE,QAAQ,CAAC,IAAI,IAAI,CAAC,UAAU;CACvC,CAAC;AACF,MAAM,yBAAyB,EAAE,OAAO;CACtC,QAAQ,EAAE,QAAQ;CAClB,WAAW,EAAE,SAAS;CACvB,CAAC;AAKF,MAAM,yBAAyB,EAAE,OAAO,EACtC,QAAQ,EAAE,QAAQ,CAAC,IAAI,EAAE,EAC1B,CAAC;AACF,MAAM,0BAA0B,EAAE,OAAO,EACvC,OAAO,EAAE,MACP,EAAE,OAAO;CACP,QAAQ,EAAE,QAAQ;CAClB,MAAM,EAAE,QAAQ;CAChB,WAAW,EAAE,QAAQ,CAAC,UAAU;CAChC,SAAS,EAAE,QAAQ,CAAC,UAAU;CAC9B,YAAY,EAAE,QAAQ,CAAC,UAAU;CACjC,cAAc,EAAE,QAAQ,CAAC,UAAU;CACnC,aAAa;CACd,CAAC,CACH,EACF,CAAC;AAKF,MAAM,0BAA0B,EAAE,OAAO;CACvC,QAAQ,EAAE,QAAQ,CAAC,IAAI,EAAE;CACzB,QAAQ,EAAE,QAAQ,CAAC,IAAI,IAAI,CAAC,UAAU;CACvC,CAAC;AACF,MAAM,2BAA2B,EAAE,OAAO;CACxC,QAAQ,EAAE,QAAQ;CAClB,WAAW,EAAE,SAAS;CACvB,CAAC;;;;;;;;AAYF,SAAgB,uBACd,MAC6C;AAC7C,QAAO,KAA4C;EACjD,MAAM;EACN,aACE;EACF,aAAa;EACb,cAAc;EACd,iBAAiB;EACjB,eAAe;EACf,aAAa;EACb,iBAAiB;EACjB,MAAM,CAAC,UAAU,WAAW;EAC5B,MAAM,QAAQ,OAAO,KAAK;GACxB,MAAM,QAAQ,MAAM,KAAK,aAAa,IAAI;GAC1C,MAAM,UAAU,MAAM,KAAK,SAAS,qBAAqB,OAAO;IAC9D,MAAM,MAAM;IACZ,GAAI,MAAM,SAAS,SAAY,EAAE,MAAM,MAAM,MAAM,GAAG,EAAE;IACxD,GAAI,MAAM,eAAe,SAAY,EAAE,YAAY,MAAM,YAAY,GAAG,EAAE;IAC1E,GAAI,MAAM,gBAAgB,SAAY,EAAE,aAAa,MAAM,aAAa,GAAG,EAAE;IAC7E,GAAI,MAAM,cAAc,SAAY,EAAE,WAAW,MAAM,WAAW,GAAG,EAAE;IACvE,GAAI,MAAM,YAAY,SAAY,EAAE,SAAS,MAAM,SAAS,GAAG,EAAE;IAClE,CAAC;AAGF,UAAO;IACL,QAAQ,QAAQ,KAAK;IACrB,aAAa,QAAQ,KAAK,WAAW;IACrC,GAAI,QAAQ,qBAAqB,SAC7B,EAAE,kBAAkB,QAAQ,kBAAkB,GAC9C,EAAE;IACP;;EAEJ,CAAC;;;;;;;;AASJ,SAAgB,qBACd,MACyC;AACzC,QAAO,KAAwC;EAC7C,MAAM;EACN,aACE;EACF,aAAa;EACb,cAAc;EACd,iBAAiB;EACjB,eAAe;EACf,aAAa;EACb,iBAAiB;EACjB,MAAM,CAAC,UAAU,WAAW;EAC5B,MAAM,QAAQ,OAAO,KAAK;GACxB,MAAM,QAAQ,MAAM,KAAK,aAAa,IAAI;GAC1C,MAAM,OAAO,MAAM,KAAK,SAAS,OAAO,OAAO,MAAM,OAAO;IAC1D,GAAI,MAAM,SAAS,SAAY,EAAE,MAAM,MAAM,MAAM,GAAG,EAAE;IAGxD,GAAI,MAAM,SAAS,UAAa,MAAM,KAAK,SAAS,IAAI,EAAE,MAAM,MAAM,MAAM,GAAG,EAAE;IACjF,GAAI,MAAM,SAAS,SAAY,EAAE,MAAM,MAAM,MAAM,GAAG,EAAE;IACxD,QAAQ,IAAI;IACb,CAAC;GACF,MAAM,SAAS,EACb,MAAM,KAAK,KAAK,SAAS;IACvB,QAAQ,IAAI,OAAO;IACnB,MAAM,IAAI,OAAO;IACjB,OAAO,IAAI;IACX,aAAa,IAAI,OAAO;IACxB,GAAI,IAAI,OAAO,eAAe,SAAY,EAAE,YAAY,IAAI,OAAO,YAAY,GAAG,EAAE;IAGpF,GAAI,IAAI,OAAO,YAAY,SAAY,EAAE,SAAS,IAAI,OAAO,SAAS,GAAG,EAAE;IAC3E,GAAI,IAAI,OAAO,iBAAiB,SAC5B,EAAE,cAAc,IAAI,OAAO,cAAc,GACzC,EAAE;IACP,EAAE,EACJ;GAGD,MAAM,QAAQ,YAAY,KAAK,KAAK,MAAM,EAAE,OAAO,CAAC;AACpD,UAAO,UAAU,SAAY,SAAS;IAAE;IAAQ;IAAO;;EAE1D,CAAC;;;;;;;;;;AAWJ,SAAgB,wBACd,MAC+C;AAC/C,QAAO,KAA8C;EACnD,MAAM;EACN,aACE;EACF,aAAa;EACb,cAAc;EACd,iBAAiB;EACjB,eAAe;EACf,aAAa;EACb,iBAAiB;EACjB,MAAM,CAAC,UAAU,WAAW;EAC5B,MAAM,QAAQ,OAAO,KAAK;GACxB,MAAM,QAAQ,MAAM,KAAK,aAAa,IAAI;GAC1C,MAAM,SAAS,MAAM,KAAK,SAAS,UACjC,OACA,MAAM,OACN,EAAE,MAAM,MAAM,SAAS,EACvB,MAAM,OACP;AACD,UAAO;IAAE,OAAO,OAAO;IAAK,OAAO,OAAO,IAAI;IAAI;;EAErD,CAAC;;;;;;;;AASJ,SAAgB,qBACd,MACyC;AACzC,QAAO,KAAwC;EAC7C,MAAM;EACN,aACE;EACF,aAAa;EACb,cAAc;EACd,iBAAiB;EACjB,eAAe;EACf,aAAa;EACb,iBAAiB;EACjB,MAAM,CAAC,UAAU,WAAW;EAC5B,MAAM,QAAQ,OAAO,KAAK;GACxB,MAAM,QAAQ,MAAM,KAAK,aAAa,IAAI;AAC1C,SAAM,KAAK,SAAS,OAAO,OAAO,MAAM,QAAQ,MAAM,OAAO;AAC7D,UAAO;IAAE,QAAQ,MAAM;IAAQ,WAAW;IAAM;;EAEnD,CAAC;;;;;;;;;;AAWJ,SAAgB,sBACd,MAC2C;AAC3C,QAAO,KAA0C;EAC/C,MAAM;EACN,aACE;EACF,aAAa;EACb,cAAc;EACd,iBAAiB;EACjB,eAAe;EACf,aAAa;EACb,iBAAiB;EACjB,MAAM;GAAC;GAAU;GAAY;GAAW;EACxC,MAAM,QAAQ,OAAO,KAAK;GACxB,MAAM,QAAQ,MAAM,KAAK,aAAa,IAAI;AAE1C,UAAO,EACL,QAFY,MAAM,KAAK,SAAS,QAAQ,OAAO,MAAM,OAAO,EAE/C,KAAK,OAAO;IACvB,QAAQ,EAAE;IACV,MAAM,EAAE;IACR,GAAI,EAAE,cAAc,SAAY,EAAE,WAAW,EAAE,WAAW,GAAG,EAAE;IAC/D,GAAI,EAAE,YAAY,SAAY,EAAE,SAAS,EAAE,SAAS,GAAG,EAAE;IACzD,GAAI,EAAE,eAAe,SAAY,EAAE,YAAY,EAAE,YAAY,GAAG,EAAE;IAClE,GAAI,EAAE,iBAAiB,SAAY,EAAE,cAAc,EAAE,cAAc,GAAG,EAAE;IACxE,aAAa,EAAE;IAChB,EAAE,EACJ;;EAEJ,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;AA0BJ,SAAgB,uBACd,MAC6C;AAC7C,QAAO,KAA4C;EACjD,MAAM;EACN,aACE;EACF,aAAa;EACb,cAAc;EAGd,eAAe;EACf,iBAAiB;EACjB,eAAe;EACf,aAAa;EACb,iBAAiB;EACjB,MAAM;GAAC;GAAU;GAAY;GAAS;EACtC,MAAM,QAAQ,OAAO,KAAK;GACxB,MAAM,QAAQ,MAAM,KAAK,aAAa,IAAI;AAG1C,SAAM,KAAK,SAAS,SAAS,OAAO,MAAM,QAAQ,MAAM,OAAO;AAC/D,UAAO;IAAE,QAAQ,MAAM;IAAQ,WAAW;IAAM;;EAEnD,CAAC"}
@@ -2,6 +2,7 @@ import { MemoryToolDeps, ScopeResolver } from "./types.js";
2
2
  import { createBlockAppendTool, createBlockReplaceTool, createBlockRethinkTool } from "./block-tools.js";
3
3
  import { createFactForgetTool, createFactHistoryTool, createFactRememberTool, createFactSearchTool, createFactSupersedeTool, createFactValidateTool } from "./fact-tools.js";
4
4
  import { createConversationSearchTool, createDeepRecallTool, createRecallEpisodesTool } from "./recall-tools.js";
5
+ import { createRunbookSearchTool } from "./runbook-tools.js";
5
6
  import { Tool } from "@graphorin/core";
6
7
 
7
8
  //#region src/tools/index.d.ts
@@ -18,9 +19,15 @@ interface BuildMemoryToolsOptions {
18
19
  * default tool surface stays at the canonical eleven. Default `false`.
19
20
  */
20
21
  readonly includeDeepRecall?: boolean;
22
+ /**
23
+ * Append the gated `runbook_search` tool (D3). The facade sets this
24
+ * only when `createMemory({ runbookSearch: true })` opts in, so the
25
+ * default tool surface is unchanged. Default `false`.
26
+ */
27
+ readonly includeRunbookSearch?: boolean;
21
28
  }
22
29
  /**
23
- * Build the canonical eleven-memory-tool array. Order is stable
30
+ * Build the canonical eleven-memory-tool array. Order is stable -
24
31
  * consumers can rely on the indices for snapshot tests. `fact_history`
25
32
  * (P0-2) and `fact_validate` (P1-4) are appended last so the original
26
33
  * nine indices are unchanged. With `{ includeDeepRecall: true }` the
@@ -31,5 +38,5 @@ interface BuildMemoryToolsOptions {
31
38
  */
32
39
  declare function buildMemoryTools(deps: MemoryToolDeps, options?: BuildMemoryToolsOptions): ReadonlyArray<Tool>;
33
40
  //#endregion
34
- export { BuildMemoryToolsOptions, type MemoryToolDeps, type ScopeResolver, buildMemoryTools, createBlockAppendTool, createBlockReplaceTool, createBlockRethinkTool, createConversationSearchTool, createDeepRecallTool, createFactForgetTool, createFactHistoryTool, createFactRememberTool, createFactSearchTool, createFactSupersedeTool, createFactValidateTool, createRecallEpisodesTool };
41
+ export { BuildMemoryToolsOptions, type MemoryToolDeps, type ScopeResolver, buildMemoryTools, createBlockAppendTool, createBlockReplaceTool, createBlockRethinkTool, createConversationSearchTool, createDeepRecallTool, createFactForgetTool, createFactHistoryTool, createFactRememberTool, createFactSearchTool, createFactSupersedeTool, createFactValidateTool, createRecallEpisodesTool, createRunbookSearchTool };
35
42
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../../src/tools/index.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;;;;UAyDiB,uBAAA;;;;;;;;;;;;;;;;;;iBAmBD,gBAAA,OACR,0BACG,0BACR,cAAc"}
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../../src/tools/index.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;;;;;UA2DiB,uBAAA;;;;;;;;;;;;;;;;;;;;;;;;iBAyBD,gBAAA,OACR,0BACG,0BACR,cAAc"}
@@ -1,10 +1,11 @@
1
1
  import { createBlockAppendTool, createBlockReplaceTool, createBlockRethinkTool } from "./block-tools.js";
2
2
  import { createFactForgetTool, createFactHistoryTool, createFactRememberTool, createFactSearchTool, createFactSupersedeTool, createFactValidateTool } from "./fact-tools.js";
3
3
  import { createConversationSearchTool, createDeepRecallTool, createRecallEpisodesTool } from "./recall-tools.js";
4
+ import { createRunbookSearchTool } from "./runbook-tools.js";
4
5
 
5
6
  //#region src/tools/index.ts
6
7
  /**
7
- * Build the canonical eleven-memory-tool array. Order is stable
8
+ * Build the canonical eleven-memory-tool array. Order is stable -
8
9
  * consumers can rely on the indices for snapshot tests. `fact_history`
9
10
  * (P0-2) and `fact_validate` (P1-4) are appended last so the original
10
11
  * nine indices are unchanged. With `{ includeDeepRecall: true }` the
@@ -28,9 +29,10 @@ function buildMemoryTools(deps, options = {}) {
28
29
  createFactValidateTool(deps)
29
30
  ];
30
31
  if (options.includeDeepRecall === true) tools.push(createDeepRecallTool(deps));
32
+ if (options.includeRunbookSearch === true) tools.push(createRunbookSearchTool(deps));
31
33
  return Object.freeze(tools);
32
34
  }
33
35
 
34
36
  //#endregion
35
- export { buildMemoryTools, createBlockAppendTool, createBlockReplaceTool, createBlockRethinkTool, createConversationSearchTool, createDeepRecallTool, createFactForgetTool, createFactHistoryTool, createFactRememberTool, createFactSearchTool, createFactSupersedeTool, createFactValidateTool, createRecallEpisodesTool };
37
+ export { buildMemoryTools, createBlockAppendTool, createBlockReplaceTool, createBlockRethinkTool, createConversationSearchTool, createDeepRecallTool, createFactForgetTool, createFactHistoryTool, createFactRememberTool, createFactSearchTool, createFactSupersedeTool, createFactValidateTool, createRecallEpisodesTool, createRunbookSearchTool };
36
38
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["tools: Tool[]"],"sources":["../../src/tools/index.ts"],"sourcesContent":["/**\n * Eleven memory tools registered with `@graphorin/tools` by the\n * `createMemory()` facade plus an opt-in twelfth, `deep_recall` (P2-4),\n * appended only when iterative retrieval is configured. Each factory\n * takes a {@link MemoryToolDeps} bundle so consumers can scope the tool\n * surface (per-tier ACL, scope resolver, etc.) without rebuilding the\n * underlying memory facade.\n *\n * @packageDocumentation\n */\n\nimport type { Tool } from '@graphorin/core';\nimport {\n createBlockAppendTool,\n createBlockReplaceTool,\n createBlockRethinkTool,\n} from './block-tools.js';\nimport {\n createFactForgetTool,\n createFactHistoryTool,\n createFactRememberTool,\n createFactSearchTool,\n createFactSupersedeTool,\n createFactValidateTool,\n} from './fact-tools.js';\nimport {\n createConversationSearchTool,\n createDeepRecallTool,\n createRecallEpisodesTool,\n} from './recall-tools.js';\nimport type { MemoryToolDeps } from './types.js';\n\nexport {\n createBlockAppendTool,\n createBlockReplaceTool,\n createBlockRethinkTool,\n} from './block-tools.js';\nexport {\n createFactForgetTool,\n createFactHistoryTool,\n createFactRememberTool,\n createFactSearchTool,\n createFactSupersedeTool,\n createFactValidateTool,\n} from './fact-tools.js';\nexport {\n createConversationSearchTool,\n createDeepRecallTool,\n createRecallEpisodesTool,\n} from './recall-tools.js';\nexport type { MemoryToolDeps, ScopeResolver } from './types.js';\n\n/**\n * Options for {@link buildMemoryTools}.\n *\n * @stable\n */\nexport interface BuildMemoryToolsOptions {\n /**\n * Append the gated `deep_recall` tool (P2-4) as a twelfth tool. The\n * facade sets this only when `iterativeRetrieval` is configured, so the\n * default tool surface stays at the canonical eleven. Default `false`.\n */\n readonly includeDeepRecall?: boolean;\n}\n\n/**\n * Build the canonical eleven-memory-tool array. Order is stable —\n * consumers can rely on the indices for snapshot tests. `fact_history`\n * (P0-2) and `fact_validate` (P1-4) are appended last so the original\n * nine indices are unchanged. With `{ includeDeepRecall: true }` the\n * gated `deep_recall` tool (P2-4) is appended as a twelfth, after the\n * stable eleven.\n *\n * @stable\n */\nexport function buildMemoryTools(\n deps: MemoryToolDeps,\n options: BuildMemoryToolsOptions = {},\n): ReadonlyArray<Tool> {\n const tools: Tool[] = [\n createBlockAppendTool(deps) as Tool,\n createBlockReplaceTool(deps) as Tool,\n createBlockRethinkTool(deps) as Tool,\n createFactRememberTool(deps) as Tool,\n createFactSearchTool(deps) as Tool,\n createFactSupersedeTool(deps) as Tool,\n createFactForgetTool(deps) as Tool,\n createRecallEpisodesTool(deps) as Tool,\n createConversationSearchTool(deps) as Tool,\n createFactHistoryTool(deps) as Tool,\n createFactValidateTool(deps) as Tool,\n ];\n if (options.includeDeepRecall === true) {\n tools.push(createDeepRecallTool(deps) as Tool);\n }\n return Object.freeze(tools);\n}\n"],"mappings":";;;;;;;;;;;;;;;AA4EA,SAAgB,iBACd,MACA,UAAmC,EAAE,EAChB;CACrB,MAAMA,QAAgB;EACpB,sBAAsB,KAAK;EAC3B,uBAAuB,KAAK;EAC5B,uBAAuB,KAAK;EAC5B,uBAAuB,KAAK;EAC5B,qBAAqB,KAAK;EAC1B,wBAAwB,KAAK;EAC7B,qBAAqB,KAAK;EAC1B,yBAAyB,KAAK;EAC9B,6BAA6B,KAAK;EAClC,sBAAsB,KAAK;EAC3B,uBAAuB,KAAK;EAC7B;AACD,KAAI,QAAQ,sBAAsB,KAChC,OAAM,KAAK,qBAAqB,KAAK,CAAS;AAEhD,QAAO,OAAO,OAAO,MAAM"}
1
+ {"version":3,"file":"index.js","names":["tools: Tool[]"],"sources":["../../src/tools/index.ts"],"sourcesContent":["/**\n * Eleven memory tools registered with `@graphorin/tools` by the\n * `createMemory()` facade - plus an opt-in twelfth, `deep_recall` (P2-4),\n * appended only when iterative retrieval is configured. Each factory\n * takes a {@link MemoryToolDeps} bundle so consumers can scope the tool\n * surface (per-tier ACL, scope resolver, etc.) without rebuilding the\n * underlying memory facade.\n *\n * @packageDocumentation\n */\n\nimport type { Tool } from '@graphorin/core';\nimport {\n createBlockAppendTool,\n createBlockReplaceTool,\n createBlockRethinkTool,\n} from './block-tools.js';\nimport {\n createFactForgetTool,\n createFactHistoryTool,\n createFactRememberTool,\n createFactSearchTool,\n createFactSupersedeTool,\n createFactValidateTool,\n} from './fact-tools.js';\nimport {\n createConversationSearchTool,\n createDeepRecallTool,\n createRecallEpisodesTool,\n} from './recall-tools.js';\nimport { createRunbookSearchTool } from './runbook-tools.js';\nimport type { MemoryToolDeps } from './types.js';\n\nexport {\n createBlockAppendTool,\n createBlockReplaceTool,\n createBlockRethinkTool,\n} from './block-tools.js';\nexport {\n createFactForgetTool,\n createFactHistoryTool,\n createFactRememberTool,\n createFactSearchTool,\n createFactSupersedeTool,\n createFactValidateTool,\n} from './fact-tools.js';\nexport {\n createConversationSearchTool,\n createDeepRecallTool,\n createRecallEpisodesTool,\n} from './recall-tools.js';\nexport { createRunbookSearchTool } from './runbook-tools.js';\nexport type { MemoryToolDeps, ScopeResolver } from './types.js';\n\n/**\n * Options for {@link buildMemoryTools}.\n *\n * @stable\n */\nexport interface BuildMemoryToolsOptions {\n /**\n * Append the gated `deep_recall` tool (P2-4) as a twelfth tool. The\n * facade sets this only when `iterativeRetrieval` is configured, so the\n * default tool surface stays at the canonical eleven. Default `false`.\n */\n readonly includeDeepRecall?: boolean;\n /**\n * Append the gated `runbook_search` tool (D3). The facade sets this\n * only when `createMemory({ runbookSearch: true })` opts in, so the\n * default tool surface is unchanged. Default `false`.\n */\n readonly includeRunbookSearch?: boolean;\n}\n\n/**\n * Build the canonical eleven-memory-tool array. Order is stable -\n * consumers can rely on the indices for snapshot tests. `fact_history`\n * (P0-2) and `fact_validate` (P1-4) are appended last so the original\n * nine indices are unchanged. With `{ includeDeepRecall: true }` the\n * gated `deep_recall` tool (P2-4) is appended as a twelfth, after the\n * stable eleven.\n *\n * @stable\n */\nexport function buildMemoryTools(\n deps: MemoryToolDeps,\n options: BuildMemoryToolsOptions = {},\n): ReadonlyArray<Tool> {\n const tools: Tool[] = [\n createBlockAppendTool(deps) as Tool,\n createBlockReplaceTool(deps) as Tool,\n createBlockRethinkTool(deps) as Tool,\n createFactRememberTool(deps) as Tool,\n createFactSearchTool(deps) as Tool,\n createFactSupersedeTool(deps) as Tool,\n createFactForgetTool(deps) as Tool,\n createRecallEpisodesTool(deps) as Tool,\n createConversationSearchTool(deps) as Tool,\n createFactHistoryTool(deps) as Tool,\n createFactValidateTool(deps) as Tool,\n ];\n if (options.includeDeepRecall === true) {\n tools.push(createDeepRecallTool(deps) as Tool);\n }\n if (options.includeRunbookSearch === true) {\n tools.push(createRunbookSearchTool(deps) as Tool);\n }\n return Object.freeze(tools);\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAoFA,SAAgB,iBACd,MACA,UAAmC,EAAE,EAChB;CACrB,MAAMA,QAAgB;EACpB,sBAAsB,KAAK;EAC3B,uBAAuB,KAAK;EAC5B,uBAAuB,KAAK;EAC5B,uBAAuB,KAAK;EAC5B,qBAAqB,KAAK;EAC1B,wBAAwB,KAAK;EAC7B,qBAAqB,KAAK;EAC1B,yBAAyB,KAAK;EAC9B,6BAA6B,KAAK;EAClC,sBAAsB,KAAK;EAC3B,uBAAuB,KAAK;EAC7B;AACD,KAAI,QAAQ,sBAAsB,KAChC,OAAM,KAAK,qBAAqB,KAAK,CAAS;AAEhD,KAAI,QAAQ,yBAAyB,KACnC,OAAM,KAAK,wBAAwB,KAAK,CAAS;AAEnD,QAAO,OAAO,OAAO,MAAM"}
@@ -38,37 +38,37 @@ declare const recallEpisodesOutputSchema: z.ZodObject<{
38
38
  score: z.ZodNumber;
39
39
  startedAt: z.ZodString;
40
40
  endedAt: z.ZodString;
41
- /** Trust-provenance tag (MST-10) synthesized episodes say so. */
41
+ /** Trust-provenance tag (MST-10) - synthesized episodes say so. */
42
42
  provenance: z.ZodOptional<z.ZodString>;
43
43
  }, "strip", z.ZodTypeAny, {
44
+ score: number;
44
45
  episodeId: string;
45
46
  summary: string;
46
- score: number;
47
47
  startedAt: string;
48
48
  endedAt: string;
49
49
  provenance?: string | undefined;
50
50
  }, {
51
+ score: number;
51
52
  episodeId: string;
52
53
  summary: string;
53
- score: number;
54
54
  startedAt: string;
55
55
  endedAt: string;
56
56
  provenance?: string | undefined;
57
57
  }>, "many">;
58
58
  }, "strip", z.ZodTypeAny, {
59
59
  episodes: {
60
+ score: number;
60
61
  episodeId: string;
61
62
  summary: string;
62
- score: number;
63
63
  startedAt: string;
64
64
  endedAt: string;
65
65
  provenance?: string | undefined;
66
66
  }[];
67
67
  }, {
68
68
  episodes: {
69
+ score: number;
69
70
  episodeId: string;
70
71
  summary: string;
71
- score: number;
72
72
  startedAt: string;
73
73
  endedAt: string;
74
74
  provenance?: string | undefined;
@@ -118,13 +118,13 @@ declare const deepRecallInputSchema: z.ZodObject<{
118
118
  }, "strip", z.ZodTypeAny, {
119
119
  query: string;
120
120
  topK?: number | undefined;
121
- maxIterations?: number | undefined;
122
121
  asOf?: string | undefined;
122
+ maxIterations?: number | undefined;
123
123
  }, {
124
124
  query: string;
125
125
  topK?: number | undefined;
126
- maxIterations?: number | undefined;
127
126
  asOf?: string | undefined;
127
+ maxIterations?: number | undefined;
128
128
  }>;
129
129
  declare const deepRecallOutputSchema: z.ZodObject<{
130
130
  hits: z.ZodArray<z.ZodObject<{
@@ -132,71 +132,91 @@ declare const deepRecallOutputSchema: z.ZodObject<{
132
132
  text: z.ZodString;
133
133
  score: z.ZodNumber;
134
134
  sensitivity: z.ZodEnum<["public", "internal", "secret"]>;
135
- /** Trust-provenance tag (MST-10) synthesized facts say so. */
135
+ /** Trust-provenance tag (MST-10) - synthesized facts say so. */
136
136
  provenance: z.ZodOptional<z.ZodString>;
137
+ /** Closed validity end (only surfaces on `asOf` reads). */
138
+ validTo: z.ZodOptional<z.ZodString>;
139
+ /** Id of the fact that superseded this one, when any. */
140
+ supersededBy: z.ZodOptional<z.ZodString>;
137
141
  }, "strip", z.ZodTypeAny, {
138
- score: number;
139
- factId: string;
140
142
  text: string;
143
+ score: number;
141
144
  sensitivity: "public" | "internal" | "secret";
145
+ factId: string;
146
+ validTo?: string | undefined;
142
147
  provenance?: string | undefined;
148
+ supersededBy?: string | undefined;
143
149
  }, {
144
- score: number;
145
- factId: string;
146
150
  text: string;
151
+ score: number;
147
152
  sensitivity: "public" | "internal" | "secret";
153
+ factId: string;
154
+ validTo?: string | undefined;
148
155
  provenance?: string | undefined;
156
+ supersededBy?: string | undefined;
149
157
  }>, "many">;
150
158
  sufficient: z.ZodBoolean;
151
159
  abstained: z.ZodBoolean;
160
+ /**
161
+ * Whether the grader actually judged sufficiency
162
+ * (memory-retrieval-02). When `false`, `sufficient: true` is a
163
+ * default, not a verdict.
164
+ */
165
+ graded: z.ZodBoolean;
152
166
  iterations: z.ZodNumber;
153
167
  }, "strip", z.ZodTypeAny, {
154
168
  hits: {
155
- score: number;
156
- factId: string;
157
169
  text: string;
170
+ score: number;
158
171
  sensitivity: "public" | "internal" | "secret";
172
+ factId: string;
173
+ validTo?: string | undefined;
159
174
  provenance?: string | undefined;
175
+ supersededBy?: string | undefined;
160
176
  }[];
161
177
  sufficient: boolean;
162
178
  abstained: boolean;
179
+ graded: boolean;
163
180
  iterations: number;
164
181
  }, {
165
182
  hits: {
166
- score: number;
167
- factId: string;
168
183
  text: string;
184
+ score: number;
169
185
  sensitivity: "public" | "internal" | "secret";
186
+ factId: string;
187
+ validTo?: string | undefined;
170
188
  provenance?: string | undefined;
189
+ supersededBy?: string | undefined;
171
190
  }[];
172
191
  sufficient: boolean;
173
192
  abstained: boolean;
193
+ graded: boolean;
174
194
  iterations: number;
175
195
  }>;
176
196
  type DeepRecallInput = z.infer<typeof deepRecallInputSchema>;
177
197
  type DeepRecallOutput = z.infer<typeof deepRecallOutputSchema>;
178
198
  /**
179
- * `recall_episodes` triple-signal episode retrieval (recency ×
199
+ * `recall_episodes` - triple-signal episode retrieval (recency ×
180
200
  * relevance × importance).
181
201
  *
182
202
  * @stable
183
203
  */
184
204
  declare function createRecallEpisodesTool(deps: MemoryToolDeps): Tool<RecallEpisodesInput, RecallEpisodesOutput>;
185
205
  /**
186
- * `conversation_search` FTS5 search over the active session
206
+ * `conversation_search` - FTS5 search over the active session
187
207
  * messages.
188
208
  *
189
209
  * @stable
190
210
  */
191
211
  declare function createConversationSearchTool(deps: MemoryToolDeps): Tool<ConversationSearchInput, ConversationSearchOutput>;
192
212
  /**
193
- * `deep_recall` gated, multi-pass ("deep") recall over the user's
213
+ * `deep_recall` - gated, multi-pass ("deep") recall over the user's
194
214
  * factual memory for HARD questions (P2-4). A local difficulty gate keeps
195
215
  * simple lookups single-shot; only queries judged hard trigger a
196
216
  * grade-and-reformulate loop (bounded by `maxIterations`, hard-capped at
197
217
  * 5), widening to one-hop graph expansion on reformulation passes. The
198
218
  * output reports `abstained: true` when memory was insufficient even
199
- * after reformulating the agent should then say it lacks the
219
+ * after reformulating - the agent should then say it lacks the
200
220
  * information rather than guess. Registered only when the facade is
201
221
  * created with `iterativeRetrieval`; otherwise it degrades to a single
202
222
  * pass, so prefer the cheaper `fact_search` for ordinary lookups.
@@ -1 +1 @@
1
- {"version":3,"file":"recall-tools.d.ts","names":[],"sources":["../../src/tools/recall-tools.ts"],"sourcesContent":[],"mappings":";;;;;cAKM,2BAAyB,CAAA,CAAA;;EAAzB,IAAA,eAAA,YASJ,CAAA;;;;;;;;;;;;EAT6B,KAAA,EAAA,MAAA;EAAA,IAAA,CAAA,EAAA,MAAA,GAAA,SAAA;EAUzB,SAAA,CAAA,EAAA;;;;;;;;;;;;cAAA,0BAA0B,EAAA,CAAA,CAAA,SAAA,CAAA;EAAA,QAAA,YAAA,YAAA,CAAA;IAc3B,SAAA,aAAmB;IACnB,OAAA,aAAoB;IAEnB,KAAA,aAAA;;;;;EAA6B,CAAA,EAAA,OAAA,cAAA,EAAA;IAAA,SAAA,EAAA,MAAA;IAI7B,OAAA,EAAA,MAAA;;;;;;;IAA8B,OAAA,EAAA,MAAA;IAAA,KAAA,EAAA,MAAA;IAS/B,SAAA,EAAA,MAAA;IACA,OAAA,EAAA,MAAA;IAGC,UAAA,CAAA,EAAA,MAAA,GAKJ,SAAA;;;;;;;;;IALyB,UAAA,CAAA,EAAA,MAAA,GAAA,SAAA;EAAA,CAAA,EAAA;AAAA,CAAA,EAAA;;;;;;;;;;KApBtB,mBAAA,GAAsB,CAAA,CAAE,aAAa;KACrC,oBAAA,GAAuB,CAAA,CAAE,aAAa;cAErC,+BAA6B,CAAA,CAAA;;EAuBP,IAAA,eAAA,YAAA,CAAA;CAAA,EAAA,OAAA,cAAA,EAAA;EAgBvB,KAAA,EAAA,MAAA;EACA,IAAA,CAAA,EAAA,MAAA,GAAA,SAAgB;AAQrB,CAAA,EAAA;EACQ,KAAA,EAAA,MAAA;EACA,IAAA,CAAA,EAAA,MAAA,GAAA,SAAA;CAAqB,CAAA;cA9CvB,8BA8CH,EA9CiC,CAAA,CAAA,SA8CjC,CAAA;EAAI,OAAA,YAAA,YAAA,CAAA;IAiDS,SAAA,aAAA;IACR,KAAA,aAAA;EACA,CAAA,EAAA,OAAA,cAAA,EAAA;IAAyB,KAAA,EAAA,MAAA;IAA9B,SAAA,EAAA,MAAA;EAAI,CAAA,EAAA;IA0CS,KAAA,EAAA,MAAA;IACR,SAAA,EAAA,MAAA;EACA,CAAA,CAAA,EAAA,MAAA,CAAA;CAAiB,EAAA,OAAA,cAAA,EAAA;EAAtB,OAAA,EAAA;IAAI,KAAA,EAAA,MAAA;;;;;;;;;KApIF,uBAAA,GAA0B,CAAA,CAAE,aAAa;KACzC,wBAAA,GAA2B,CAAA,CAAE,aAAa;cAGzC,uBAAqB,CAAA,CAAA;;;;;;;;;;;;;;;;cAMrB,wBAAsB,CAAA,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAgBvB,eAAA,GAAkB,CAAA,CAAE,aAAa;KACjC,gBAAA,GAAmB,CAAA,CAAE,aAAa;;;;;;;iBAQvB,wBAAA,OACR,iBACL,KAAK,qBAAqB;;;;;;;iBAiDb,4BAAA,OACR,iBACL,KAAK,yBAAyB;;;;;;;;;;;;;;;iBA0CjB,oBAAA,OACR,iBACL,KAAK,iBAAiB"}
1
+ {"version":3,"file":"recall-tools.d.ts","names":[],"sources":["../../src/tools/recall-tools.ts"],"sourcesContent":[],"mappings":";;;;;cAMM,2BAAyB,CAAA,CAAA;;EAAzB,IAAA,eAAA,YASJ,CAAA;;;;;;;;;;;;EAT6B,KAAA,EAAA,MAAA;EAAA,IAAA,CAAA,EAAA,MAAA,GAAA,SAAA;EAUzB,SAAA,CAAA,EAAA;;;;;;;;;;;;cAAA,0BAA0B,EAAA,CAAA,CAAA,SAAA,CAAA;EAAA,QAAA,YAAA,YAAA,CAAA;IAc3B,SAAA,aAAmB;IACnB,OAAA,aAAoB;IAEnB,KAAA,aAAA;;;;;EAA6B,CAAA,EAAA,OAAA,cAAA,EAAA;IAAA,KAAA,EAAA,MAAA;IAI7B,SAAA,EAAA,MAAA;;;;;;;IAA8B,SAAA,EAAA,MAAA;IAAA,OAAA,EAAA,MAAA;IAS/B,SAAA,EAAA,MAAA;IACA,OAAA,EAAA,MAAA;IAGC,UAAA,CAAA,EAAA,MAAA,GAKJ,SAAA;;;;;;;;;IALyB,UAAA,CAAA,EAAA,MAAA,GAAA,SAAA;EAAA,CAAA,EAAA;AAAA,CAAA,EAAA;;;;;;;;;;KApBtB,mBAAA,GAAsB,CAAA,CAAE,aAAa;KACrC,oBAAA,GAAuB,CAAA,CAAE,aAAa;cAErC,+BAA6B,CAAA,CAAA;;;;;;;EAuBP,KAAA,EAAA,MAAA;EAAA,IAAA,CAAA,EAAA,MAAA,GAAA,SAAA;AAAA,CAAA,CAAA;AA0BE,cA7CxB,8BA8CiC,EA9CH,CAAA,CAAA,SA8CG,CAAA;EAQvB,OAAA,YAAA,YAAwB,CAAA;IAChC,SAAA,aAAA;IACA,KAAA,aAAA;EAAqB,CAAA,EAAA,OAAA,cAAA,EAAA;IAA1B,KAAA,EAAA,MAAA;IAAI,SAAA,EAAA,MAAA;EAqDS,CAAA,EAAA;IACR,KAAA,EAAA,MAAA;IACA,SAAA,EAAA,MAAA;EAAyB,CAAA,CAAA,EAAA,MAAA,CAAA;CAA9B,EAAA,OAAA,cAAA,EAAA;EAAI,OAAA,EAAA;IA0CS,KAAA,EAAA,MAAA;IACR,SAAA,EAAA,MAAA;EACA,CAAA,EAAA;CAAiB,EAAA;EAAtB,OAAA,EAAA;IAAI,KAAA,EAAA,MAAA;;;;KAlJF,uBAAA,GAA0B,CAAA,CAAE,aAAa;KACzC,wBAAA,GAA2B,CAAA,CAAE,aAAa;cAGzC,uBAAqB,CAAA,CAAA;;;;;;;;;;;;;;;;cAMrB,wBAAsB,CAAA,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KA0BvB,eAAA,GAAkB,CAAA,CAAE,aAAa;KACjC,gBAAA,GAAmB,CAAA,CAAE,aAAa;;;;;;;iBAQvB,wBAAA,OACR,iBACL,KAAK,qBAAqB;;;;;;;iBAqDb,4BAAA,OACR,iBACL,KAAK,yBAAyB;;;;;;;;;;;;;;;iBA0CjB,oBAAA,OACR,iBACL,KAAK,iBAAiB"}
@@ -1,3 +1,4 @@
1
+ import { recallTaint } from "./taint.js";
1
2
  import { tool } from "@graphorin/tools";
2
3
  import { z } from "zod";
3
4
 
@@ -43,14 +44,17 @@ const deepRecallOutputSchema = z.object({
43
44
  text: z.string(),
44
45
  score: z.number(),
45
46
  sensitivity: deepRecallSensitivityEnum,
46
- provenance: z.string().optional()
47
+ provenance: z.string().optional(),
48
+ validTo: z.string().optional(),
49
+ supersededBy: z.string().optional()
47
50
  })),
48
51
  sufficient: z.boolean(),
49
52
  abstained: z.boolean(),
53
+ graded: z.boolean(),
50
54
  iterations: z.number().int()
51
55
  });
52
56
  /**
53
- * `recall_episodes` triple-signal episode retrieval (recency ×
57
+ * `recall_episodes` - triple-signal episode retrieval (recency ×
54
58
  * relevance × importance).
55
59
  *
56
60
  * @stable
@@ -72,11 +76,12 @@ function createRecallEpisodesTool(deps) {
72
76
  ...input.dateRange.from !== void 0 ? { from: input.dateRange.from } : {},
73
77
  ...input.dateRange.to !== void 0 ? { to: input.dateRange.to } : {}
74
78
  } : void 0;
75
- return { episodes: (await deps.episodic.search(scope, input.query, {
79
+ const hits = await deps.episodic.search(scope, input.query, {
76
80
  ...input.topK !== void 0 ? { topK: input.topK } : {},
77
81
  ...dateRange !== void 0 ? { dateRange } : {},
78
82
  signal: ctx.signal
79
- })).map((hit) => ({
83
+ });
84
+ const output = { episodes: hits.map((hit) => ({
80
85
  episodeId: hit.record.id,
81
86
  summary: hit.record.summary,
82
87
  score: hit.score,
@@ -84,11 +89,16 @@ function createRecallEpisodesTool(deps) {
84
89
  endedAt: hit.record.endedAt,
85
90
  ...hit.record.provenance !== void 0 ? { provenance: hit.record.provenance } : {}
86
91
  })) };
92
+ const taint = recallTaint(hits.map((h) => h.record));
93
+ return taint === void 0 ? output : {
94
+ output,
95
+ taint
96
+ };
87
97
  }
88
98
  });
89
99
  }
90
100
  /**
91
- * `conversation_search` FTS5 search over the active session
101
+ * `conversation_search` - FTS5 search over the active session
92
102
  * messages.
93
103
  *
94
104
  * @stable
@@ -117,13 +127,13 @@ function createConversationSearchTool(deps) {
117
127
  });
118
128
  }
119
129
  /**
120
- * `deep_recall` gated, multi-pass ("deep") recall over the user's
130
+ * `deep_recall` - gated, multi-pass ("deep") recall over the user's
121
131
  * factual memory for HARD questions (P2-4). A local difficulty gate keeps
122
132
  * simple lookups single-shot; only queries judged hard trigger a
123
133
  * grade-and-reformulate loop (bounded by `maxIterations`, hard-capped at
124
134
  * 5), widening to one-hop graph expansion on reformulation passes. The
125
135
  * output reports `abstained: true` when memory was insufficient even
126
- * after reformulating the agent should then say it lacks the
136
+ * after reformulating - the agent should then say it lacks the
127
137
  * information rather than guess. Registered only when the facade is
128
138
  * created with `iterativeRetrieval`; otherwise it degrades to a single
129
139
  * pass, so prefer the cheaper `fact_search` for ordinary lookups.
@@ -133,7 +143,7 @@ function createConversationSearchTool(deps) {
133
143
  function createDeepRecallTool(deps) {
134
144
  return tool({
135
145
  name: "deep_recall",
136
- description: "Multi-pass ('deep') recall over the user's long-term factual memory for HARD multi-hop or temporal questions one search can't answer (e.g. 'who recommended the book the person I met in Tbilisi mentioned?'). A difficulty gate keeps simple lookups single-shot; hard questions trigger a bounded grade-and-reformulate loop. If `abstained` is true the memory was insufficient even after reformulating tell the user you don't have enough stored to answer and DO NOT guess. Prefer the cheaper fact_search for ordinary lookups.",
146
+ description: "Multi-pass ('deep') recall over the user's long-term factual memory for HARD multi-hop or temporal questions one search can't answer (e.g. 'who recommended the book the person I met in Tbilisi mentioned?'). A difficulty gate keeps simple lookups single-shot; hard questions trigger a bounded grade-and-reformulate loop. If `abstained` is true the memory was insufficient even after reformulating - tell the user you don't have enough stored to answer and DO NOT guess. Prefer the cheaper fact_search for ordinary lookups.",
137
147
  inputSchema: deepRecallInputSchema,
138
148
  outputSchema: deepRecallOutputSchema,
139
149
  sideEffectClass: "read-only",
@@ -147,20 +157,29 @@ function createDeepRecallTool(deps) {
147
157
  ...input.topK !== void 0 ? { topK: input.topK } : {},
148
158
  ...input.maxIterations !== void 0 ? { maxIterations: input.maxIterations } : {},
149
159
  ...input.asOf !== void 0 ? { asOf: input.asOf } : {},
160
+ forceHard: true,
150
161
  signal: ctx.signal
151
162
  });
152
- return {
163
+ const output = {
153
164
  hits: result.hits.map((hit) => ({
154
165
  factId: hit.record.id,
155
166
  text: hit.record.text,
156
167
  score: hit.score,
157
168
  sensitivity: hit.record.sensitivity,
158
- ...hit.record.provenance !== void 0 ? { provenance: hit.record.provenance } : {}
169
+ ...hit.record.provenance !== void 0 ? { provenance: hit.record.provenance } : {},
170
+ ...hit.record.validTo !== void 0 ? { validTo: hit.record.validTo } : {},
171
+ ...hit.record.supersededBy !== void 0 ? { supersededBy: hit.record.supersededBy } : {}
159
172
  })),
160
173
  sufficient: result.sufficient,
161
174
  abstained: result.abstained,
175
+ graded: result.graded,
162
176
  iterations: result.iterations
163
177
  };
178
+ const taint = recallTaint(result.hits.map((h) => h.record));
179
+ return taint === void 0 ? output : {
180
+ output,
181
+ taint
182
+ };
164
183
  }
165
184
  });
166
185
  }
@@ -1 +1 @@
1
- {"version":3,"file":"recall-tools.js","names":[],"sources":["../../src/tools/recall-tools.ts"],"sourcesContent":["import type { Tool } from '@graphorin/core';\nimport { tool } from '@graphorin/tools';\nimport { z } from 'zod';\nimport type { MemoryToolDeps } from './types.js';\n\nconst recallEpisodesInputSchema = z.object({\n query: z.string().min(1).max(1024),\n topK: z.number().int().positive().max(20).optional(),\n dateRange: z\n .object({\n from: z.string().datetime().optional(),\n to: z.string().datetime().optional(),\n })\n .optional(),\n});\nconst recallEpisodesOutputSchema = z.object({\n episodes: z.array(\n z.object({\n episodeId: z.string(),\n summary: z.string(),\n score: z.number(),\n startedAt: z.string(),\n endedAt: z.string(),\n /** Trust-provenance tag (MST-10) — synthesized episodes say so. */\n provenance: z.string().optional(),\n }),\n ),\n});\n\ntype RecallEpisodesInput = z.infer<typeof recallEpisodesInputSchema>;\ntype RecallEpisodesOutput = z.infer<typeof recallEpisodesOutputSchema>;\n\nconst conversationSearchInputSchema = z.object({\n query: z.string().min(1).max(1024),\n topK: z.number().int().positive().max(20).optional(),\n});\nconst conversationSearchOutputSchema = z.object({\n matches: z.array(\n z.object({\n messageId: z.string(),\n score: z.number(),\n }),\n ),\n});\n\ntype ConversationSearchInput = z.infer<typeof conversationSearchInputSchema>;\ntype ConversationSearchOutput = z.infer<typeof conversationSearchOutputSchema>;\n\nconst deepRecallSensitivityEnum = z.enum(['public', 'internal', 'secret']);\nconst deepRecallInputSchema = z.object({\n query: z.string().min(1).max(1024),\n topK: z.number().int().positive().max(50).optional(),\n maxIterations: z.number().int().min(1).max(5).optional(),\n asOf: z.string().datetime().optional(),\n});\nconst deepRecallOutputSchema = z.object({\n hits: z.array(\n z.object({\n factId: z.string(),\n text: z.string(),\n score: z.number(),\n sensitivity: deepRecallSensitivityEnum,\n /** Trust-provenance tag (MST-10) — synthesized facts say so. */\n provenance: z.string().optional(),\n }),\n ),\n sufficient: z.boolean(),\n abstained: z.boolean(),\n iterations: z.number().int(),\n});\n\ntype DeepRecallInput = z.infer<typeof deepRecallInputSchema>;\ntype DeepRecallOutput = z.infer<typeof deepRecallOutputSchema>;\n\n/**\n * `recall_episodes` — triple-signal episode retrieval (recency ×\n * relevance × importance).\n *\n * @stable\n */\nexport function createRecallEpisodesTool(\n deps: MemoryToolDeps,\n): Tool<RecallEpisodesInput, RecallEpisodesOutput> {\n return tool<RecallEpisodesInput, RecallEpisodesOutput>({\n name: 'recall_episodes',\n description:\n \"Recall summarized episodes (multi-message stretches of past activity) matching a natural-language query. Combines vector relevance, time-decay recency, and the per-episode importance score. Use for long-horizon recall ('the last time we discussed X').\",\n inputSchema: recallEpisodesInputSchema,\n outputSchema: recallEpisodesOutputSchema,\n sideEffectClass: 'read-only',\n sandboxPolicy: 'none',\n sensitivity: 'internal',\n memoryGuardTier: 'pure',\n tags: ['memory', 'episodic'],\n async execute(input, ctx) {\n const scope = await deps.resolveScope(ctx);\n const dateRange =\n input.dateRange !== undefined\n ? {\n ...(input.dateRange.from !== undefined ? { from: input.dateRange.from } : {}),\n ...(input.dateRange.to !== undefined ? { to: input.dateRange.to } : {}),\n }\n : undefined;\n const hits = await deps.episodic.search(scope, input.query, {\n ...(input.topK !== undefined ? { topK: input.topK } : {}),\n ...(dateRange !== undefined ? { dateRange } : {}),\n signal: ctx.signal,\n });\n return {\n episodes: hits.map((hit) => ({\n episodeId: hit.record.id,\n summary: hit.record.summary,\n score: hit.score,\n startedAt: hit.record.startedAt,\n endedAt: hit.record.endedAt,\n // MST-10: surface origin so a consumer can tell a synthesized\n // (consolidator-extracted) episode from a first-party record —\n // recalled text re-enters the model as trusted tool output.\n ...(hit.record.provenance !== undefined ? { provenance: hit.record.provenance } : {}),\n })),\n };\n },\n });\n}\n\n/**\n * `conversation_search` — FTS5 search over the active session\n * messages.\n *\n * @stable\n */\nexport function createConversationSearchTool(\n deps: MemoryToolDeps,\n): Tool<ConversationSearchInput, ConversationSearchOutput> {\n return tool<ConversationSearchInput, ConversationSearchOutput>({\n name: 'conversation_search',\n description:\n 'Search the active session message log by natural-language query. Returns up to `topK` matched messages with their stable id and BM25 score.',\n inputSchema: conversationSearchInputSchema,\n outputSchema: conversationSearchOutputSchema,\n sideEffectClass: 'read-only',\n sandboxPolicy: 'none',\n sensitivity: 'internal',\n memoryGuardTier: 'pure',\n tags: ['memory', 'session'],\n async execute(input, ctx) {\n const scope = await deps.resolveScope(ctx);\n const hits = await deps.session.search(scope, input.query, {\n ...(input.topK !== undefined ? { topK: input.topK } : {}),\n signal: ctx.signal,\n });\n return {\n matches: hits.map((hit) => ({\n messageId: hit.record.id,\n score: hit.score,\n })),\n };\n },\n });\n}\n\n/**\n * `deep_recall` — gated, multi-pass (\"deep\") recall over the user's\n * factual memory for HARD questions (P2-4). A local difficulty gate keeps\n * simple lookups single-shot; only queries judged hard trigger a\n * grade-and-reformulate loop (bounded by `maxIterations`, hard-capped at\n * 5), widening to one-hop graph expansion on reformulation passes. The\n * output reports `abstained: true` when memory was insufficient even\n * after reformulating — the agent should then say it lacks the\n * information rather than guess. Registered only when the facade is\n * created with `iterativeRetrieval`; otherwise it degrades to a single\n * pass, so prefer the cheaper `fact_search` for ordinary lookups.\n *\n * @stable\n */\nexport function createDeepRecallTool(\n deps: MemoryToolDeps,\n): Tool<DeepRecallInput, DeepRecallOutput> {\n return tool<DeepRecallInput, DeepRecallOutput>({\n name: 'deep_recall',\n description:\n \"Multi-pass ('deep') recall over the user's long-term factual memory for HARD multi-hop or temporal questions one search can't answer (e.g. 'who recommended the book the person I met in Tbilisi mentioned?'). A difficulty gate keeps simple lookups single-shot; hard questions trigger a bounded grade-and-reformulate loop. If `abstained` is true the memory was insufficient even after reformulating — tell the user you don't have enough stored to answer and DO NOT guess. Prefer the cheaper fact_search for ordinary lookups.\",\n inputSchema: deepRecallInputSchema,\n outputSchema: deepRecallOutputSchema,\n sideEffectClass: 'read-only',\n sandboxPolicy: 'none',\n sensitivity: 'internal',\n memoryGuardTier: 'pure',\n tags: ['memory', 'semantic'],\n async execute(input, ctx) {\n const scope = await deps.resolveScope(ctx);\n const result = await deps.semantic.searchIterative(scope, input.query, {\n ...(input.topK !== undefined ? { topK: input.topK } : {}),\n ...(input.maxIterations !== undefined ? { maxIterations: input.maxIterations } : {}),\n ...(input.asOf !== undefined ? { asOf: input.asOf } : {}),\n signal: ctx.signal,\n });\n return {\n hits: result.hits.map((hit) => ({\n factId: hit.record.id,\n text: hit.record.text,\n score: hit.score,\n sensitivity: hit.record.sensitivity,\n // MST-10: origin annotation, mirroring fact_search.\n ...(hit.record.provenance !== undefined ? { provenance: hit.record.provenance } : {}),\n })),\n sufficient: result.sufficient,\n abstained: result.abstained,\n iterations: result.iterations,\n };\n },\n });\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"recall-tools.js","names":[],"sources":["../../src/tools/recall-tools.ts"],"sourcesContent":["import type { Tool } from '@graphorin/core';\nimport { tool } from '@graphorin/tools';\nimport { z } from 'zod';\nimport { recallTaint } from './taint.js';\nimport type { MemoryToolDeps } from './types.js';\n\nconst recallEpisodesInputSchema = z.object({\n query: z.string().min(1).max(1024),\n topK: z.number().int().positive().max(20).optional(),\n dateRange: z\n .object({\n from: z.string().datetime().optional(),\n to: z.string().datetime().optional(),\n })\n .optional(),\n});\nconst recallEpisodesOutputSchema = z.object({\n episodes: z.array(\n z.object({\n episodeId: z.string(),\n summary: z.string(),\n score: z.number(),\n startedAt: z.string(),\n endedAt: z.string(),\n /** Trust-provenance tag (MST-10) - synthesized episodes say so. */\n provenance: z.string().optional(),\n }),\n ),\n});\n\ntype RecallEpisodesInput = z.infer<typeof recallEpisodesInputSchema>;\ntype RecallEpisodesOutput = z.infer<typeof recallEpisodesOutputSchema>;\n\nconst conversationSearchInputSchema = z.object({\n query: z.string().min(1).max(1024),\n topK: z.number().int().positive().max(20).optional(),\n});\nconst conversationSearchOutputSchema = z.object({\n matches: z.array(\n z.object({\n messageId: z.string(),\n score: z.number(),\n }),\n ),\n});\n\ntype ConversationSearchInput = z.infer<typeof conversationSearchInputSchema>;\ntype ConversationSearchOutput = z.infer<typeof conversationSearchOutputSchema>;\n\nconst deepRecallSensitivityEnum = z.enum(['public', 'internal', 'secret']);\nconst deepRecallInputSchema = z.object({\n query: z.string().min(1).max(1024),\n topK: z.number().int().positive().max(50).optional(),\n maxIterations: z.number().int().min(1).max(5).optional(),\n asOf: z.string().datetime().optional(),\n});\nconst deepRecallOutputSchema = z.object({\n hits: z.array(\n z.object({\n factId: z.string(),\n text: z.string(),\n score: z.number(),\n sensitivity: deepRecallSensitivityEnum,\n /** Trust-provenance tag (MST-10) - synthesized facts say so. */\n provenance: z.string().optional(),\n /** Closed validity end (only surfaces on `asOf` reads). */\n validTo: z.string().optional(),\n /** Id of the fact that superseded this one, when any. */\n supersededBy: z.string().optional(),\n }),\n ),\n sufficient: z.boolean(),\n abstained: z.boolean(),\n /**\n * Whether the grader actually judged sufficiency\n * (memory-retrieval-02). When `false`, `sufficient: true` is a\n * default, not a verdict.\n */\n graded: z.boolean(),\n iterations: z.number().int(),\n});\n\ntype DeepRecallInput = z.infer<typeof deepRecallInputSchema>;\ntype DeepRecallOutput = z.infer<typeof deepRecallOutputSchema>;\n\n/**\n * `recall_episodes` - triple-signal episode retrieval (recency ×\n * relevance × importance).\n *\n * @stable\n */\nexport function createRecallEpisodesTool(\n deps: MemoryToolDeps,\n): Tool<RecallEpisodesInput, RecallEpisodesOutput> {\n return tool<RecallEpisodesInput, RecallEpisodesOutput>({\n name: 'recall_episodes',\n description:\n \"Recall summarized episodes (multi-message stretches of past activity) matching a natural-language query. Combines vector relevance, time-decay recency, and the per-episode importance score. Use for long-horizon recall ('the last time we discussed X').\",\n inputSchema: recallEpisodesInputSchema,\n outputSchema: recallEpisodesOutputSchema,\n sideEffectClass: 'read-only',\n sandboxPolicy: 'none',\n sensitivity: 'internal',\n memoryGuardTier: 'pure',\n tags: ['memory', 'episodic'],\n async execute(input, ctx) {\n const scope = await deps.resolveScope(ctx);\n const dateRange =\n input.dateRange !== undefined\n ? {\n ...(input.dateRange.from !== undefined ? { from: input.dateRange.from } : {}),\n ...(input.dateRange.to !== undefined ? { to: input.dateRange.to } : {}),\n }\n : undefined;\n const hits = await deps.episodic.search(scope, input.query, {\n ...(input.topK !== undefined ? { topK: input.topK } : {}),\n ...(dateRange !== undefined ? { dateRange } : {}),\n signal: ctx.signal,\n });\n const output = {\n episodes: hits.map((hit) => ({\n episodeId: hit.record.id,\n summary: hit.record.summary,\n score: hit.score,\n startedAt: hit.record.startedAt,\n endedAt: hit.record.endedAt,\n // MST-10: surface origin so a consumer can tell a synthesized\n // (consolidator-extracted) episode from a first-party record -\n // recalled text re-enters the model as trusted tool output.\n ...(hit.record.provenance !== undefined ? { provenance: hit.record.provenance } : {}),\n })),\n };\n // C6: recalled foreign-provenance / quarantined episodes re-arm the\n // taint ledger (the cross-session poisoning leg).\n const taint = recallTaint(hits.map((h) => h.record));\n return taint === undefined ? output : { output, taint };\n },\n });\n}\n\n/**\n * `conversation_search` - FTS5 search over the active session\n * messages.\n *\n * @stable\n */\nexport function createConversationSearchTool(\n deps: MemoryToolDeps,\n): Tool<ConversationSearchInput, ConversationSearchOutput> {\n return tool<ConversationSearchInput, ConversationSearchOutput>({\n name: 'conversation_search',\n description:\n 'Search the active session message log by natural-language query. Returns up to `topK` matched messages with their stable id and BM25 score.',\n inputSchema: conversationSearchInputSchema,\n outputSchema: conversationSearchOutputSchema,\n sideEffectClass: 'read-only',\n sandboxPolicy: 'none',\n sensitivity: 'internal',\n memoryGuardTier: 'pure',\n tags: ['memory', 'session'],\n async execute(input, ctx) {\n const scope = await deps.resolveScope(ctx);\n const hits = await deps.session.search(scope, input.query, {\n ...(input.topK !== undefined ? { topK: input.topK } : {}),\n signal: ctx.signal,\n });\n return {\n matches: hits.map((hit) => ({\n messageId: hit.record.id,\n score: hit.score,\n })),\n };\n },\n });\n}\n\n/**\n * `deep_recall` - gated, multi-pass (\"deep\") recall over the user's\n * factual memory for HARD questions (P2-4). A local difficulty gate keeps\n * simple lookups single-shot; only queries judged hard trigger a\n * grade-and-reformulate loop (bounded by `maxIterations`, hard-capped at\n * 5), widening to one-hop graph expansion on reformulation passes. The\n * output reports `abstained: true` when memory was insufficient even\n * after reformulating - the agent should then say it lacks the\n * information rather than guess. Registered only when the facade is\n * created with `iterativeRetrieval`; otherwise it degrades to a single\n * pass, so prefer the cheaper `fact_search` for ordinary lookups.\n *\n * @stable\n */\nexport function createDeepRecallTool(\n deps: MemoryToolDeps,\n): Tool<DeepRecallInput, DeepRecallOutput> {\n return tool<DeepRecallInput, DeepRecallOutput>({\n name: 'deep_recall',\n description:\n \"Multi-pass ('deep') recall over the user's long-term factual memory for HARD multi-hop or temporal questions one search can't answer (e.g. 'who recommended the book the person I met in Tbilisi mentioned?'). A difficulty gate keeps simple lookups single-shot; hard questions trigger a bounded grade-and-reformulate loop. If `abstained` is true the memory was insufficient even after reformulating - tell the user you don't have enough stored to answer and DO NOT guess. Prefer the cheaper fact_search for ordinary lookups.\",\n inputSchema: deepRecallInputSchema,\n outputSchema: deepRecallOutputSchema,\n sideEffectClass: 'read-only',\n sandboxPolicy: 'none',\n sensitivity: 'internal',\n memoryGuardTier: 'pure',\n tags: ['memory', 'semantic'],\n async execute(input, ctx) {\n const scope = await deps.resolveScope(ctx);\n const result = await deps.semantic.searchIterative(scope, input.query, {\n ...(input.topK !== undefined ? { topK: input.topK } : {}),\n ...(input.maxIterations !== undefined ? { maxIterations: input.maxIterations } : {}),\n ...(input.asOf !== undefined ? { asOf: input.asOf } : {}),\n // memory-retrieval-02: the model choosing deep_recall over\n // fact_search IS the hardness signal - the local heuristic gate\n // rejected the tool's own documented multi-hop examples\n // (W_MULTI_HOP 0.4 < threshold 0.5) and is English-only. The\n // cap + grader stop conditions still bound cost.\n forceHard: true,\n signal: ctx.signal,\n });\n const output = {\n hits: result.hits.map((hit) => ({\n factId: hit.record.id,\n text: hit.record.text,\n score: hit.score,\n sensitivity: hit.record.sensitivity,\n // MST-10: origin annotation, mirroring fact_search.\n ...(hit.record.provenance !== undefined ? { provenance: hit.record.provenance } : {}),\n ...(hit.record.validTo !== undefined ? { validTo: hit.record.validTo } : {}),\n ...(hit.record.supersededBy !== undefined\n ? { supersededBy: hit.record.supersededBy }\n : {}),\n })),\n sufficient: result.sufficient,\n abstained: result.abstained,\n graded: result.graded,\n iterations: result.iterations,\n };\n // C6: mirror fact_search - recalled poisoned content re-arms the ledger.\n const taint = recallTaint(result.hits.map((h) => h.record));\n return taint === undefined ? output : { output, taint };\n },\n });\n}\n"],"mappings":"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"}
@@ -0,0 +1,76 @@
1
+ import { MemoryToolDeps } from "./types.js";
2
+ import { Tool } from "@graphorin/core";
3
+ import { z } from "zod";
4
+
5
+ //#region src/tools/runbook-tools.d.ts
6
+
7
+ declare const runbookSearchInputSchema: z.ZodObject<{
8
+ query: z.ZodString;
9
+ topK: z.ZodOptional<z.ZodNumber>;
10
+ }, "strip", z.ZodTypeAny, {
11
+ query: string;
12
+ topK?: number | undefined;
13
+ }, {
14
+ query: string;
15
+ topK?: number | undefined;
16
+ }>;
17
+ declare const runbookSearchOutputSchema: z.ZodObject<{
18
+ procedures: z.ZodArray<z.ZodObject<{
19
+ id: z.ZodString;
20
+ text: z.ZodString;
21
+ steps: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
22
+ variables: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
23
+ successCriteria: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
24
+ priority: z.ZodNumber;
25
+ score: z.ZodNumber;
26
+ }, "strip", z.ZodTypeAny, {
27
+ id: string;
28
+ text: string;
29
+ priority: number;
30
+ score: number;
31
+ steps?: string[] | undefined;
32
+ variables?: string[] | undefined;
33
+ successCriteria?: string[] | undefined;
34
+ }, {
35
+ id: string;
36
+ text: string;
37
+ priority: number;
38
+ score: number;
39
+ steps?: string[] | undefined;
40
+ variables?: string[] | undefined;
41
+ successCriteria?: string[] | undefined;
42
+ }>, "many">;
43
+ }, "strip", z.ZodTypeAny, {
44
+ procedures: {
45
+ id: string;
46
+ text: string;
47
+ priority: number;
48
+ score: number;
49
+ steps?: string[] | undefined;
50
+ variables?: string[] | undefined;
51
+ successCriteria?: string[] | undefined;
52
+ }[];
53
+ }, {
54
+ procedures: {
55
+ id: string;
56
+ text: string;
57
+ priority: number;
58
+ score: number;
59
+ steps?: string[] | undefined;
60
+ variables?: string[] | undefined;
61
+ successCriteria?: string[] | undefined;
62
+ }[];
63
+ }>;
64
+ type RunbookSearchInput = z.infer<typeof runbookSearchInputSchema>;
65
+ type RunbookSearchOutput = z.infer<typeof runbookSearchOutputSchema>;
66
+ /**
67
+ * `runbook_search` - find validated procedures matching a task
68
+ * description. Quarantined (unvalidated induced) procedures never
69
+ * surface here: they must not drive actions until validated.
70
+ *
71
+ * @stable
72
+ */
73
+ declare function createRunbookSearchTool(deps: MemoryToolDeps): Tool<RunbookSearchInput, RunbookSearchOutput>;
74
+ //#endregion
75
+ export { createRunbookSearchTool };
76
+ //# sourceMappingURL=runbook-tools.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runbook-tools.d.ts","names":[],"sources":["../../src/tools/runbook-tools.ts"],"sourcesContent":[],"mappings":";;;;;;cAiBM,0BAAwB,CAAA,CAAA;;;;;;;;;;cAIxB,2BAAyB,CAAA,CAAA;;;;;;IAAA,eAAA,eAAA,WAAA,YAAA,EAAA,MAAA,CAAA,CAAA;IAAA,QAAA,aAAA;IAc1B,KAAA,aAAkB;EAClB,CAAA,EAAA,OAAA,cAAmB,EAAA;IASR,EAAA,EAAA,MAAA;IACR,IAAA,EAAA,MAAA;IACA,QAAA,EAAA,MAAA;IAAoB,KAAA,EAAA,MAAA;IAAzB,KAAA,CAAA,EAAA,MAAA,EAAA,GAAA,SAAA;IAAI,SAAA,CAAA,EAAA,MAAA,EAAA,GAAA,SAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAZF,kBAAA,GAAqB,CAAA,CAAE,aAAa;KACpC,mBAAA,GAAsB,CAAA,CAAE,aAAa;;;;;;;;iBAS1B,uBAAA,OACR,iBACL,KAAK,oBAAoB"}