@remnic/core 9.50.0 → 9.50.2

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 (367) hide show
  1. package/dist/access-admin-ops-surface.d.ts +10 -10
  2. package/dist/access-admin-ops-surface.js +17 -17
  3. package/dist/access-authorization-probe.d.ts +10 -10
  4. package/dist/access-authorization-probe.js +18 -18
  5. package/dist/access-boundary.d.ts +10 -10
  6. package/dist/access-boundary.js +17 -17
  7. package/dist/access-cli.js +42 -42
  8. package/dist/access-coding-context-resolution.d.ts +1 -1
  9. package/dist/access-extraction-force-flush.d.ts +10 -10
  10. package/dist/access-extraction-force-flush.js +17 -17
  11. package/dist/access-health-types.d.ts +1 -1
  12. package/dist/access-http-lcm-compaction.d.ts +10 -10
  13. package/dist/access-http-lifecycle-flush.d.ts +10 -10
  14. package/dist/access-http-offline-stream.d.ts +10 -10
  15. package/dist/access-http-query.js +17 -17
  16. package/dist/access-http.d.ts +10 -10
  17. package/dist/access-http.js +23 -23
  18. package/dist/access-identity-continuity-surface.d.ts +8 -8
  19. package/dist/access-identity-continuity-surface.js +17 -17
  20. package/dist/access-lcm-surface.d.ts +10 -10
  21. package/dist/access-lcm-surface.js +17 -17
  22. package/dist/access-mcp.d.ts +10 -10
  23. package/dist/access-mcp.js +21 -21
  24. package/dist/access-memory-search-fanout.d.ts +2 -2
  25. package/dist/{access-namespace-preflight-DuDU301-.d.ts → access-namespace-preflight-Dj2QolFE.d.ts} +1 -1
  26. package/dist/access-namespace-preflight.d.ts +3 -3
  27. package/dist/access-namespace-preflight.js +17 -17
  28. package/dist/access-observe-write-surface.d.ts +10 -10
  29. package/dist/access-observe-write-surface.js +17 -17
  30. package/dist/access-offline-manifest.d.ts +8 -8
  31. package/dist/access-operations-batch.js +18 -18
  32. package/dist/access-operations.d.ts +10 -10
  33. package/dist/access-operations.js +20 -20
  34. package/dist/access-recall-concurrency.d.ts +10 -10
  35. package/dist/access-recall-concurrency.js +17 -17
  36. package/dist/access-recall-response.d.ts +10 -10
  37. package/dist/access-recall-response.js +17 -17
  38. package/dist/access-recall-surface.d.ts +10 -10
  39. package/dist/access-recall-surface.js +17 -17
  40. package/dist/{access-service--_3T_v23.d.ts → access-service-DesbnTSa.d.ts} +7 -7
  41. package/dist/access-service-helpers.d.ts +10 -10
  42. package/dist/access-service.d.ts +10 -10
  43. package/dist/access-service.js +17 -17
  44. package/dist/access-surface-catalog.d.ts +10 -10
  45. package/dist/access-wearables-meetings-surface.d.ts +3 -3
  46. package/dist/action-confidence.d.ts +1 -1
  47. package/dist/active-memory-bridge.d.ts +1 -1
  48. package/dist/active-recall.d.ts +1 -1
  49. package/dist/ambient-provenance.d.ts +1 -1
  50. package/dist/artifact-search.d.ts +1 -1
  51. package/dist/behavior-learner.d.ts +1 -1
  52. package/dist/behavior-signals.d.ts +1 -1
  53. package/dist/bootstrap.d.ts +8 -8
  54. package/dist/briefing.d.ts +2 -2
  55. package/dist/briefing.js +6 -6
  56. package/dist/buffer-surprise-report.d.ts +1 -1
  57. package/dist/buffer-turn-helpers.d.ts +1 -1
  58. package/dist/buffer.d.ts +2 -2
  59. package/dist/bulk-import/index.d.ts +3 -3
  60. package/dist/calibration.d.ts +1 -1
  61. package/dist/capabilities.d.ts +1 -1
  62. package/dist/{capsule-merge-KXTRZ23Z.js → capsule-merge-XMFBXVDP.js} +4 -4
  63. package/dist/{catalog-DjUmUIal.d.ts → catalog-D-G7RgXR.d.ts} +1 -1
  64. package/dist/causal-behavior.d.ts +1 -1
  65. package/dist/causal-consolidation.d.ts +1 -1
  66. package/dist/causal-consolidation.js +7 -7
  67. package/dist/causal-trajectory-graph.d.ts +1 -1
  68. package/dist/{chunk-N3CXAYPJ.js → chunk-2HGUDBRJ.js} +2 -2
  69. package/dist/{chunk-FV7YQTN3.js → chunk-2S72LWKX.js} +2 -2
  70. package/dist/{chunk-NKL25FCF.js → chunk-4MBPIL4V.js} +2 -2
  71. package/dist/{chunk-PWIMF7LP.js → chunk-5C2HNJMO.js} +12 -12
  72. package/dist/{chunk-ZN4EYMKJ.js → chunk-67QG75MJ.js} +2 -2
  73. package/dist/{chunk-JI62YGPI.js → chunk-6QPHF6RR.js} +2 -2
  74. package/dist/{chunk-4EABKPZS.js → chunk-75XOWNRS.js} +4 -4
  75. package/dist/{chunk-O76MWTVS.js → chunk-7BAYBYY5.js} +2 -2
  76. package/dist/{chunk-4JWJMRPJ.js → chunk-7PKFPLLZ.js} +2 -2
  77. package/dist/{chunk-24BKGKGO.js → chunk-BOFVT6P3.js} +5 -5
  78. package/dist/{chunk-SHYIMIX5.js → chunk-ESG7Z255.js} +2 -2
  79. package/dist/{chunk-P26YHAQH.js → chunk-EWMTOVMY.js} +51 -27
  80. package/dist/chunk-EWMTOVMY.js.map +1 -0
  81. package/dist/{chunk-WPZX7MEA.js → chunk-FXX6RQYC.js} +3 -3
  82. package/dist/{chunk-S75UQ3T3.js → chunk-GDDGZVFI.js} +2 -2
  83. package/dist/{chunk-S2SJEOTM.js → chunk-GFIKG4FR.js} +2 -2
  84. package/dist/{chunk-7NDM2PNK.js → chunk-GZICBRWK.js} +2 -2
  85. package/dist/{chunk-X4IDNPOS.js → chunk-HAEU3ZW7.js} +2 -2
  86. package/dist/{chunk-RBPH3GZV.js → chunk-IK6X5QPO.js} +26 -29
  87. package/dist/chunk-IK6X5QPO.js.map +1 -0
  88. package/dist/{chunk-GKEYXXKX.js → chunk-IXXABW5A.js} +2 -2
  89. package/dist/{chunk-GGBSF2X7.js → chunk-JB6D7EFB.js} +2 -2
  90. package/dist/{chunk-E633OXMH.js → chunk-JPHEOE6Z.js} +8 -8
  91. package/dist/{chunk-6XGEBQ3R.js → chunk-KDG2KTWW.js} +3 -3
  92. package/dist/{chunk-7BLWBSRL.js → chunk-LEJPSMKM.js} +2 -2
  93. package/dist/{chunk-JDCQK3C5.js → chunk-M4A44LUA.js} +2 -2
  94. package/dist/{chunk-ZDAYWJV6.js → chunk-NO37MR45.js} +3 -3
  95. package/dist/{chunk-PWLB4TRK.js → chunk-OQAL6SIR.js} +2 -2
  96. package/dist/{chunk-QWLW3VQH.js → chunk-PLKFO2HJ.js} +2 -2
  97. package/dist/{chunk-EURCX6PS.js → chunk-PWN32TAG.js} +2 -2
  98. package/dist/{chunk-ELQCS47S.js → chunk-PYKKWQZ2.js} +3 -3
  99. package/dist/{chunk-P4QOYG52.js → chunk-QN7NTKRC.js} +1 -1
  100. package/dist/{chunk-7VWZ4LRW.js → chunk-QW3WFHKU.js} +2 -2
  101. package/dist/{chunk-PNRA7FAD.js → chunk-RZRUV6N2.js} +104 -62
  102. package/dist/chunk-RZRUV6N2.js.map +1 -0
  103. package/dist/{chunk-3LD4N2TF.js → chunk-S3AYIQCU.js} +68 -82
  104. package/dist/chunk-S3AYIQCU.js.map +1 -0
  105. package/dist/{chunk-ZJIFYUJI.js → chunk-SV3PSA7Y.js} +2 -2
  106. package/dist/{chunk-LQKXVQZR.js → chunk-TQFHQPWD.js} +5 -5
  107. package/dist/{chunk-GSEPRIZC.js → chunk-TS4AJ2GI.js} +2 -2
  108. package/dist/{chunk-VFS3MK5F.js → chunk-V5H6OJCR.js} +2 -2
  109. package/dist/{chunk-T35UJI5R.js → chunk-V7X767RT.js} +18 -18
  110. package/dist/{chunk-4S3ECH3U.js → chunk-VJXY5ZCT.js} +2 -2
  111. package/dist/{chunk-PLCHU56K.js → chunk-YQ4IQ2GA.js} +2 -2
  112. package/dist/{chunk-LTOAJXZB.js → chunk-Z3RHPGSY.js} +3 -3
  113. package/dist/{chunk-5XCN4XBU.js → chunk-ZQOCRIGA.js} +3 -3
  114. package/dist/{cli-BLNmNEMT.d.ts → cli-D4vvtxjY.d.ts} +5 -5
  115. package/dist/cli.d.ts +12 -12
  116. package/dist/cli.js +34 -34
  117. package/dist/coding/pre-action-gate.d.ts +1 -1
  118. package/dist/compounding/engine.d.ts +2 -2
  119. package/dist/compounding/engine.js +6 -6
  120. package/dist/compounding/preference-consolidator.d.ts +1 -1
  121. package/dist/compression-optimizer.d.ts +1 -1
  122. package/dist/config.d.ts +1 -1
  123. package/dist/connectors/codex-materialize-runner.d.ts +1 -1
  124. package/dist/connectors/codex-materialize-runner.js +6 -6
  125. package/dist/connectors/codex-materialize.d.ts +1 -1
  126. package/dist/connectors/index.d.ts +2 -1
  127. package/dist/connectors/index.js +7 -7
  128. package/dist/consolidation-provenance-check.d.ts +2 -2
  129. package/dist/consolidation-provenance-check.js +4 -4
  130. package/dist/consolidation-undo.d.ts +2 -2
  131. package/dist/consolidation-undo.js +3 -3
  132. package/dist/contradiction/index.d.ts +2 -2
  133. package/dist/converge-config.d.ts +1 -1
  134. package/dist/convergence-refresh.d.ts +2 -2
  135. package/dist/convergence-refresh.js +8 -8
  136. package/dist/conversation-index/backend.d.ts +1 -1
  137. package/dist/conversation-index/chunker.d.ts +1 -1
  138. package/dist/conversation-index/faiss-adapter.d.ts +1 -1
  139. package/dist/conversation-index/indexer.d.ts +1 -1
  140. package/dist/conversation-index/search.d.ts +1 -1
  141. package/dist/corpus-watermark.d.ts +1 -1
  142. package/dist/corpus-watermark.js +8 -8
  143. package/dist/day-summary.d.ts +1 -1
  144. package/dist/delinearize.d.ts +1 -1
  145. package/dist/dependency-propagation-config.d.ts +1 -1
  146. package/dist/direct-answer-wiring.d.ts +1 -1
  147. package/dist/direct-answer.d.ts +1 -1
  148. package/dist/embedding-fallback.d.ts +1 -1
  149. package/dist/enrichment/index.d.ts +1 -1
  150. package/dist/entity-retrieval.d.ts +2 -2
  151. package/dist/entity-retrieval.js +6 -6
  152. package/dist/entity-schema.d.ts +1 -1
  153. package/dist/explicit-capture.d.ts +8 -8
  154. package/dist/explicit-capture.js +4 -4
  155. package/dist/external-wiki-access.d.ts +10 -10
  156. package/dist/external-wiki-access.js +18 -18
  157. package/dist/external-wiki-collection-registration.d.ts +1 -1
  158. package/dist/external-wiki-collection.d.ts +1 -1
  159. package/dist/external-wiki-mcp-tools.d.ts +10 -10
  160. package/dist/extraction-error-classification.d.ts +1 -1
  161. package/dist/extraction-faithfulness.d.ts +1 -1
  162. package/dist/extraction-judge-telemetry.d.ts +1 -1
  163. package/dist/extraction-judge-training.d.ts +1 -1
  164. package/dist/extraction-judge.d.ts +1 -1
  165. package/dist/extraction-liveness.d.ts +1 -1
  166. package/dist/extraction-normalization.d.ts +1 -1
  167. package/dist/extraction-prompt.d.ts +1 -1
  168. package/dist/extraction-source-grounding-rules.d.ts +1 -1
  169. package/dist/extraction-source-grounding.d.ts +1 -1
  170. package/dist/extraction.d.ts +17 -18
  171. package/dist/extraction.js +10 -10
  172. package/dist/fallback-llm.d.ts +1 -1
  173. package/dist/{forget-GJ42LCBW.js → forget-UJDJHG6R.js} +2 -2
  174. package/dist/graph-dashboard-diff.d.ts +1 -1
  175. package/dist/graph-dashboard-key.d.ts +1 -1
  176. package/dist/graph-dashboard-parser.d.ts +1 -1
  177. package/dist/graph-edge-reinforcement.d.ts +1 -1
  178. package/dist/graph-snapshot.d.ts +1 -1
  179. package/dist/graph.d.ts +1 -1
  180. package/dist/harmonic-retrieval.js +1 -1
  181. package/dist/importance.d.ts +1 -1
  182. package/dist/importers/index.d.ts +1 -1
  183. package/dist/in-flight-reads.d.ts +1 -1
  184. package/dist/index.d.ts +19 -19
  185. package/dist/index.js +42 -42
  186. package/dist/intent.d.ts +1 -1
  187. package/dist/lcm/engine.d.ts +1 -1
  188. package/dist/lcm/index.d.ts +1 -1
  189. package/dist/lcm/tools.d.ts +1 -1
  190. package/dist/lifecycle.d.ts +1 -1
  191. package/dist/live-connectors-runner.d.ts +1 -1
  192. package/dist/local-llm.d.ts +1 -1
  193. package/dist/local-model-endpoint.d.ts +1 -1
  194. package/dist/maintenance/memory-governance.d.ts +1 -1
  195. package/dist/maintenance/memory-governance.js +6 -6
  196. package/dist/maintenance/rebuild-memory-lifecycle-ledger.d.ts +2 -2
  197. package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +6 -6
  198. package/dist/maintenance/rebuild-memory-projection.d.ts +2 -2
  199. package/dist/maintenance/rebuild-memory-projection.js +7 -7
  200. package/dist/{maintenance-DKbKZi3u.d.ts → maintenance-ClmUVpGI.d.ts} +3 -3
  201. package/dist/mcp-memory-inspector-app.d.ts +10 -10
  202. package/dist/memory-action-policy.d.ts +1 -1
  203. package/dist/memory-cache.d.ts +1 -1
  204. package/dist/memory-lifecycle-ledger-utils.d.ts +1 -1
  205. package/dist/memory-projection-store.d.ts +1 -1
  206. package/dist/memory-provenance.d.ts +1 -1
  207. package/dist/memory-snapshot.d.ts +1 -1
  208. package/dist/memory-worth-outcomes.d.ts +2 -2
  209. package/dist/models-json.d.ts +1 -1
  210. package/dist/namespaces/migrate.d.ts +3 -3
  211. package/dist/namespaces/migrate.js +7 -7
  212. package/dist/namespaces/principal.d.ts +1 -1
  213. package/dist/namespaces/search.d.ts +1 -1
  214. package/dist/namespaces/storage.d.ts +3 -3
  215. package/dist/namespaces/storage.js +6 -6
  216. package/dist/native-knowledge.d.ts +1 -1
  217. package/dist/offline-sync-impression-drain.d.ts +1 -1
  218. package/dist/operator-doctor-corpus.d.ts +1 -1
  219. package/dist/operator-doctor-corpus.js +9 -9
  220. package/dist/operator-doctor-replica.d.ts +1 -1
  221. package/dist/operator-toolkit.d.ts +3 -3
  222. package/dist/operator-toolkit.js +14 -14
  223. package/dist/orchestration/compression-guideline-coordinator.d.ts +2 -2
  224. package/dist/orchestration/maintenance.d.ts +4 -4
  225. package/dist/orchestration/maintenance.js +11 -11
  226. package/dist/{orchestrator-BRwD7ceU.d.ts → orchestrator-qJ07zI8H.d.ts} +8 -12
  227. package/dist/orchestrator.d.ts +8 -8
  228. package/dist/orchestrator.js +42 -42
  229. package/dist/page-versioning.js +3 -3
  230. package/dist/patterns-cli.d.ts +1 -1
  231. package/dist/{pipeline-DC-1C9T8.d.ts → pipeline-WFCxhHOn.d.ts} +1 -1
  232. package/dist/policy-runtime.d.ts +1 -1
  233. package/dist/proactive-contention.d.ts +1 -1
  234. package/dist/provenance.d.ts +1 -1
  235. package/dist/{qmd-DdeCEZdb.d.ts → qmd-5tzkQ44y.d.ts} +1 -1
  236. package/dist/qmd-preflight.d.ts +2 -2
  237. package/dist/qmd-recall-cache.d.ts +1 -1
  238. package/dist/qmd.d.ts +2 -2
  239. package/dist/recall-concurrency-config.d.ts +1 -1
  240. package/dist/recall-disclosure-escalation.d.ts +1 -1
  241. package/dist/recall-explain-renderer.d.ts +1 -1
  242. package/dist/recall-memory-map.d.ts +1 -1
  243. package/dist/recall-planner-llm.d.ts +1 -1
  244. package/dist/recall-state.d.ts +1 -1
  245. package/dist/recall-tag-filter.d.ts +1 -1
  246. package/dist/recall-timings.d.ts +1 -1
  247. package/dist/recall-xray-cli.d.ts +1 -1
  248. package/dist/recall-xray-renderer.d.ts +1 -1
  249. package/dist/recall-xray.d.ts +1 -1
  250. package/dist/reconcile/cursor.d.ts +1 -1
  251. package/dist/reconcile/manifest.d.ts +1 -1
  252. package/dist/reconcile/plan.d.ts +1 -1
  253. package/dist/replay/normalizers/chatgpt.d.ts +1 -1
  254. package/dist/replay/normalizers/claude.d.ts +1 -1
  255. package/dist/replay/normalizers/openclaw.d.ts +1 -1
  256. package/dist/replay/normalizers/shared.d.ts +1 -1
  257. package/dist/replay/runner.d.ts +1 -1
  258. package/dist/replay/types.d.ts +1 -1
  259. package/dist/replica-divergence.d.ts +1 -1
  260. package/dist/replica-peers-config.d.ts +1 -1
  261. package/dist/resolve-auth-token.d.ts +1 -1
  262. package/dist/retrieval-agents.d.ts +2 -2
  263. package/dist/retrieval-tiers.d.ts +1 -1
  264. package/dist/routing/engine.d.ts +1 -1
  265. package/dist/routing/store.d.ts +1 -1
  266. package/dist/salvage-envelope.d.ts +1 -1
  267. package/dist/{scope-profiles-BXVq4Jv0.d.ts → scope-profiles--vfXPl3X.d.ts} +1 -1
  268. package/dist/search/embed-helper.d.ts +1 -1
  269. package/dist/search/factory.d.ts +1 -1
  270. package/dist/search/index.d.ts +1 -1
  271. package/dist/search/lancedb-backend.d.ts +1 -1
  272. package/dist/search/meilisearch-backend.d.ts +1 -1
  273. package/dist/search/noop-backend.d.ts +1 -1
  274. package/dist/search/orama-backend.d.ts +1 -1
  275. package/dist/search/port.d.ts +1 -1
  276. package/dist/search/remote-backend.d.ts +1 -1
  277. package/dist/{semantic-consolidation-CGYxfa8F.d.ts → semantic-consolidation-BBDuP9nJ.d.ts} +1 -1
  278. package/dist/semantic-consolidation.d.ts +2 -2
  279. package/dist/semantic-consolidation.js +7 -7
  280. package/dist/semantic-rule-promotion.js +6 -6
  281. package/dist/semantic-rule-verifier.d.ts +1 -1
  282. package/dist/semantic-rule-verifier.js +6 -6
  283. package/dist/{service-CBDBQFCN.d.ts → service-B8DtbpCM.d.ts} +2 -2
  284. package/dist/session-observer-bands.d.ts +1 -1
  285. package/dist/session-observer-state.d.ts +1 -1
  286. package/dist/shared-context/manager.d.ts +1 -1
  287. package/dist/signal.d.ts +1 -1
  288. package/dist/source-agent-qualifier.d.ts +1 -1
  289. package/dist/source-agent-qualifier.js +9 -9
  290. package/dist/{storage-V--MQi7w.d.ts → storage-BkYN1RIy.d.ts} +1 -1
  291. package/dist/storage.d.ts +2 -2
  292. package/dist/storage.js +5 -5
  293. package/dist/summarizer.d.ts +1 -1
  294. package/dist/summary-snapshot.d.ts +1 -1
  295. package/dist/temporal-supersession.d.ts +2 -2
  296. package/dist/temporal-supersession.js +1 -1
  297. package/dist/temporal-timeline-recall.d.ts +1 -1
  298. package/dist/temporal-validity.d.ts +1 -1
  299. package/dist/threading.d.ts +1 -1
  300. package/dist/tier-migration.d.ts +2 -2
  301. package/dist/tier-routing.d.ts +1 -1
  302. package/dist/topics.d.ts +1 -1
  303. package/dist/transcript.d.ts +1 -1
  304. package/dist/transfer/capsule-import.js +4 -4
  305. package/dist/trust-score-stage.d.ts +1 -1
  306. package/dist/trust-score.d.ts +1 -1
  307. package/dist/{types-D_a6Sqjz.d.ts → types-u2s9j1uD.d.ts} +1 -1
  308. package/dist/types.d.ts +1 -1
  309. package/dist/utility-runtime.d.ts +1 -1
  310. package/dist/verified-recall.js +6 -6
  311. package/dist/write-envelope.d.ts +1 -1
  312. package/package.json +2 -2
  313. package/src/connectors/index.ts +40 -112
  314. package/src/dependency-revalidation-routing.test.ts +165 -0
  315. package/src/extraction.ts +46 -31
  316. package/src/orchestration/dependency-propagation.test.ts +89 -8
  317. package/src/orchestration/dependency-propagation.ts +60 -27
  318. package/src/orchestration/dependency-revalidation.test.ts +119 -0
  319. package/src/orchestration/dependency-revalidation.ts +31 -82
  320. package/src/orchestrator.ts +5 -7
  321. package/src/runtime/daemon-health.ts +53 -0
  322. package/src/runtime/http-transport.ts +25 -0
  323. package/src/testing/subjects/dependency-propagation.test.ts +367 -0
  324. package/dist/chunk-3LD4N2TF.js.map +0 -1
  325. package/dist/chunk-P26YHAQH.js.map +0 -1
  326. package/dist/chunk-PNRA7FAD.js.map +0 -1
  327. package/dist/chunk-RBPH3GZV.js.map +0 -1
  328. /package/dist/{capsule-merge-KXTRZ23Z.js.map → capsule-merge-XMFBXVDP.js.map} +0 -0
  329. /package/dist/{chunk-N3CXAYPJ.js.map → chunk-2HGUDBRJ.js.map} +0 -0
  330. /package/dist/{chunk-FV7YQTN3.js.map → chunk-2S72LWKX.js.map} +0 -0
  331. /package/dist/{chunk-NKL25FCF.js.map → chunk-4MBPIL4V.js.map} +0 -0
  332. /package/dist/{chunk-PWIMF7LP.js.map → chunk-5C2HNJMO.js.map} +0 -0
  333. /package/dist/{chunk-ZN4EYMKJ.js.map → chunk-67QG75MJ.js.map} +0 -0
  334. /package/dist/{chunk-JI62YGPI.js.map → chunk-6QPHF6RR.js.map} +0 -0
  335. /package/dist/{chunk-4EABKPZS.js.map → chunk-75XOWNRS.js.map} +0 -0
  336. /package/dist/{chunk-O76MWTVS.js.map → chunk-7BAYBYY5.js.map} +0 -0
  337. /package/dist/{chunk-4JWJMRPJ.js.map → chunk-7PKFPLLZ.js.map} +0 -0
  338. /package/dist/{chunk-24BKGKGO.js.map → chunk-BOFVT6P3.js.map} +0 -0
  339. /package/dist/{chunk-SHYIMIX5.js.map → chunk-ESG7Z255.js.map} +0 -0
  340. /package/dist/{chunk-WPZX7MEA.js.map → chunk-FXX6RQYC.js.map} +0 -0
  341. /package/dist/{chunk-S75UQ3T3.js.map → chunk-GDDGZVFI.js.map} +0 -0
  342. /package/dist/{chunk-S2SJEOTM.js.map → chunk-GFIKG4FR.js.map} +0 -0
  343. /package/dist/{chunk-7NDM2PNK.js.map → chunk-GZICBRWK.js.map} +0 -0
  344. /package/dist/{chunk-X4IDNPOS.js.map → chunk-HAEU3ZW7.js.map} +0 -0
  345. /package/dist/{chunk-GKEYXXKX.js.map → chunk-IXXABW5A.js.map} +0 -0
  346. /package/dist/{chunk-GGBSF2X7.js.map → chunk-JB6D7EFB.js.map} +0 -0
  347. /package/dist/{chunk-E633OXMH.js.map → chunk-JPHEOE6Z.js.map} +0 -0
  348. /package/dist/{chunk-6XGEBQ3R.js.map → chunk-KDG2KTWW.js.map} +0 -0
  349. /package/dist/{chunk-7BLWBSRL.js.map → chunk-LEJPSMKM.js.map} +0 -0
  350. /package/dist/{chunk-JDCQK3C5.js.map → chunk-M4A44LUA.js.map} +0 -0
  351. /package/dist/{chunk-ZDAYWJV6.js.map → chunk-NO37MR45.js.map} +0 -0
  352. /package/dist/{chunk-PWLB4TRK.js.map → chunk-OQAL6SIR.js.map} +0 -0
  353. /package/dist/{chunk-QWLW3VQH.js.map → chunk-PLKFO2HJ.js.map} +0 -0
  354. /package/dist/{chunk-EURCX6PS.js.map → chunk-PWN32TAG.js.map} +0 -0
  355. /package/dist/{chunk-ELQCS47S.js.map → chunk-PYKKWQZ2.js.map} +0 -0
  356. /package/dist/{chunk-P4QOYG52.js.map → chunk-QN7NTKRC.js.map} +0 -0
  357. /package/dist/{chunk-7VWZ4LRW.js.map → chunk-QW3WFHKU.js.map} +0 -0
  358. /package/dist/{chunk-ZJIFYUJI.js.map → chunk-SV3PSA7Y.js.map} +0 -0
  359. /package/dist/{chunk-LQKXVQZR.js.map → chunk-TQFHQPWD.js.map} +0 -0
  360. /package/dist/{chunk-GSEPRIZC.js.map → chunk-TS4AJ2GI.js.map} +0 -0
  361. /package/dist/{chunk-VFS3MK5F.js.map → chunk-V5H6OJCR.js.map} +0 -0
  362. /package/dist/{chunk-T35UJI5R.js.map → chunk-V7X767RT.js.map} +0 -0
  363. /package/dist/{chunk-4S3ECH3U.js.map → chunk-VJXY5ZCT.js.map} +0 -0
  364. /package/dist/{chunk-PLCHU56K.js.map → chunk-YQ4IQ2GA.js.map} +0 -0
  365. /package/dist/{chunk-LTOAJXZB.js.map → chunk-Z3RHPGSY.js.map} +0 -0
  366. /package/dist/{chunk-5XCN4XBU.js.map → chunk-ZQOCRIGA.js.map} +0 -0
  367. /package/dist/{forget-GJ42LCBW.js.map → forget-UJDJHG6R.js.map} +0 -0
@@ -79,7 +79,7 @@ function config(overrides: Record<string, unknown> = {}): PluginConfig {
79
79
 
80
80
  function fixture(
81
81
  initial: MemoryFile[],
82
- verdicts: Verdict[] | Error | ((signal?: AbortSignal) => Promise<never>),
82
+ verdicts: Verdict[] | Error | ((signal?: AbortSignal) => Promise<{ verdicts: Verdict[] }>),
83
83
  ): Fixture {
84
84
  const memories = new Map(initial.map((item) => [item.frontmatter.id, item]));
85
85
  const calls: Fixture["calls"] = { revalidate: [], supersede: [], frontmatter: [] };
@@ -267,13 +267,24 @@ test("disabled propagation is an immediate no-op for boolean and string false",
267
267
  },
268
268
  );
269
269
 
270
- assert.deepEqual(result, {
271
- dependentsFound: 0,
272
- invalidated: 0,
273
- stillValid: 0,
274
- uncertain: 0,
275
- skipped: "disabled",
276
- });
270
+ assert.deepEqual(
271
+ {
272
+ dependentsFound: result.dependentsFound,
273
+ invalidated: result.invalidated,
274
+ stillValid: result.stillValid,
275
+ uncertain: result.uncertain,
276
+ skipped: result.skipped,
277
+ },
278
+ {
279
+ dependentsFound: 0,
280
+ invalidated: 0,
281
+ stillValid: 0,
282
+ uncertain: 0,
283
+ skipped: "disabled",
284
+ },
285
+ );
286
+ assert.equal(result.route, null);
287
+ assert.equal(typeof result.durationMs, "number");
277
288
  assert.equal(fixtureValue.calls.revalidate.length, 0);
278
289
  }
279
290
  });
@@ -295,6 +306,12 @@ test("invalidated verdict supersedes the dependent and persists dependency front
295
306
  );
296
307
 
297
308
  assert.equal(result.invalidated, 1);
309
+ assert.equal(result.dependentsFound, 1);
310
+ assert.equal(result.stillValid, 0);
311
+ assert.equal(result.uncertain, 0);
312
+ assert.equal(result.skipped, null);
313
+ assert.equal(result.route, "fast-completion");
314
+ assert.equal(typeof result.durationMs, "number");
298
315
  assert.deepEqual(fixtureValue.calls.supersede, [
299
316
  {
300
317
  id: "dep",
@@ -387,6 +404,12 @@ test("LLM errors skip the event and perform zero writes", async () => {
387
404
  },
388
405
  );
389
406
 
407
+ assert.equal(result.dependentsFound, 1);
408
+ assert.equal(result.invalidated, 0);
409
+ assert.equal(result.stillValid, 0);
410
+ assert.equal(result.uncertain, 0);
411
+ assert.equal(result.route, "fast-completion");
412
+ assert.equal(typeof result.durationMs, "number");
390
413
  assert.equal(result.skipped, "llm_error");
391
414
  assert.equal(fixtureValue.calls.supersede.length, 0);
392
415
  assert.equal(fixtureValue.calls.frontmatter.length, 0);
@@ -411,11 +434,69 @@ test("LLM timeout aborts the batch and performs zero writes", async () => {
411
434
  },
412
435
  );
413
436
 
437
+ assert.equal(result.dependentsFound, 1);
438
+ assert.equal(result.route, "fast-completion");
439
+ assert.equal(typeof result.durationMs, "number");
414
440
  assert.equal(result.skipped, "timeout");
415
441
  assert.equal(fixtureValue.calls.supersede.length, 0);
416
442
  assert.equal(fixtureValue.calls.frontmatter.length, 0);
417
443
  });
418
444
 
445
+ test("a completion that ignores AbortSignal returns at the shared deadline", async (t) => {
446
+ t.mock.timers.enable({ apis: ["setTimeout", "Date"], now: 0 });
447
+ try {
448
+ const old = memory("old", { links: [{ targetId: "dep", linkType: "supports" }] });
449
+ const fixtureValue = fixture([old, memory("dep")], () => new Promise<never>(() => {}));
450
+ const resultPromise = propagateInvalidation(
451
+ deps(fixtureValue, { dependencyPropagation: { timeoutMs: 20 } }),
452
+ {
453
+ oldMemory: old,
454
+ replacementId: "new",
455
+ replacementContent: "replacement",
456
+ cause: "contradiction",
457
+ namespaceScope: "namespace-a",
458
+ },
459
+ );
460
+
461
+ await Promise.resolve();
462
+ t.mock.timers.tick(20);
463
+ const result = await resultPromise;
464
+
465
+ assert.equal(result.dependentsFound, 1);
466
+ assert.equal(result.invalidated, 0);
467
+ assert.equal(result.stillValid, 0);
468
+ assert.equal(result.uncertain, 0);
469
+ assert.equal(result.skipped, "timeout");
470
+ assert.equal(result.route, "fast-completion");
471
+ assert.equal(result.durationMs, 20);
472
+ assert.equal(fixtureValue.calls.supersede.length, 0);
473
+ assert.equal(fixtureValue.calls.frontmatter.length, 0);
474
+ } finally {
475
+ t.mock.timers.reset();
476
+ }
477
+ });
478
+
479
+ test("a zero timeout disables the deadline", async () => {
480
+ const old = memory("old", { links: [{ targetId: "dep", linkType: "supports" }] });
481
+ const fixtureValue = fixture([old, memory("dep")], () =>
482
+ new Promise((resolve) => setTimeout(() => resolve({
483
+ verdicts: [{ memoryId: "dep", verdict: "invalidated" }],
484
+ }), 5)),
485
+ );
486
+ const result = await propagateInvalidation(
487
+ deps(fixtureValue, { dependencyPropagation: { timeoutMs: 0 } }),
488
+ {
489
+ oldMemory: old,
490
+ replacementId: "new",
491
+ replacementContent: "replacement",
492
+ cause: "contradiction",
493
+ namespaceScope: "namespace-a",
494
+ },
495
+ );
496
+ assert.equal(result.invalidated, 1);
497
+ assert.equal(result.skipped, null);
498
+ });
499
+
419
500
  test("dryRun computes invalidation verdicts without writing", async () => {
420
501
  const old = memory("old", { links: [{ targetId: "dep", linkType: "supports" }] });
421
502
  const fixtureValue = fixture([old, memory("dep")], [{ memoryId: "dep", verdict: "invalidated" }]);
@@ -34,6 +34,8 @@ export interface PropagationResult {
34
34
  stillValid: number;
35
35
  uncertain: number;
36
36
  skipped: "disabled" | "no_dependents" | "llm_error" | "timeout" | null;
37
+ route: "fast-completion" | null;
38
+ durationMs: number;
37
39
  }
38
40
 
39
41
  function propagationConfig(config: PluginConfig): DependencyPropagationConfig {
@@ -96,8 +98,13 @@ export function findDependents(
96
98
  });
97
99
  }
98
100
 
99
- function emptyResult(skipped: PropagationResult["skipped"]): PropagationResult {
100
- return { dependentsFound: 0, invalidated: 0, stillValid: 0, uncertain: 0, skipped };
101
+ function emptyResult(
102
+ skipped: PropagationResult["skipped"],
103
+ durationMs: number,
104
+ route: PropagationResult["route"] = null,
105
+ dependentsFound = 0,
106
+ ): PropagationResult {
107
+ return { dependentsFound, invalidated: 0, stillValid: 0, uncertain: 0, skipped, route, durationMs };
101
108
  }
102
109
 
103
110
  function logResult(event: PropagationEvent, result: PropagationResult): void {
@@ -111,6 +118,8 @@ function logResult(event: PropagationEvent, result: PropagationResult): void {
111
118
  stillValid: result.stillValid,
112
119
  uncertain: result.uncertain,
113
120
  skipped: result.skipped,
121
+ route: result.route,
122
+ durationMs: result.durationMs,
114
123
  })}`,
115
124
  );
116
125
  }
@@ -136,16 +145,17 @@ export async function propagateInvalidation(
136
145
  deps: { storage: StorageManager; extraction: ExtractionEngine; config: PluginConfig },
137
146
  event: PropagationEvent,
138
147
  ): Promise<PropagationResult> {
148
+ const startedAt = Date.now();
139
149
  const config = propagationConfig(deps.config);
140
150
  if (!isEnabled(config.enabled)) {
141
- const result = emptyResult("disabled");
151
+ const result = emptyResult("disabled", Date.now() - startedAt);
142
152
  logResult(event, result);
143
153
  return result;
144
154
  }
145
155
 
146
156
  const maxDependents = config.maxDependents;
147
157
  if (maxDependents <= 0) {
148
- const result = emptyResult("no_dependents");
158
+ const result = emptyResult("no_dependents", Date.now() - startedAt);
149
159
  logResult(event, result);
150
160
  return result;
151
161
  }
@@ -155,7 +165,7 @@ export async function propagateInvalidation(
155
165
  memories = await deps.storage.readAllMemories();
156
166
  } catch (error) {
157
167
  log.warn(`dependency propagation discovery failed for ${event.oldMemory.frontmatter.id}: ${error}`);
158
- const result = emptyResult("llm_error");
168
+ const result = emptyResult("llm_error", Date.now() - startedAt);
159
169
  logResult(event, result);
160
170
  return result;
161
171
  }
@@ -171,46 +181,67 @@ export async function propagateInvalidation(
171
181
  const dependents = discovered.slice(0, Math.max(0, Math.floor(maxDependents)));
172
182
 
173
183
  if (dependents.length === 0) {
174
- const result = emptyResult("no_dependents");
184
+ const result = emptyResult("no_dependents", Date.now() - startedAt);
175
185
  logResult(event, result);
176
186
  return result;
177
187
  }
178
188
 
179
189
  const controller = new AbortController();
180
190
  const timeoutMs = config.timeoutMs;
181
- const timeout = Number.isFinite(timeoutMs) && timeoutMs > 0
182
- ? setTimeout(() => controller.abort(new PropagationTimeoutError()), timeoutMs)
191
+ let timedOut = false;
192
+ let timeout: ReturnType<typeof setTimeout> | undefined;
193
+ const deadline = Number.isFinite(timeoutMs) && timeoutMs > 0
194
+ ? new Promise<never>((_, reject) => {
195
+ timeout = setTimeout(() => {
196
+ timedOut = true;
197
+ const error = new PropagationTimeoutError();
198
+ controller.abort(error);
199
+ reject(error);
200
+ }, timeoutMs);
201
+ })
183
202
  : undefined;
203
+ const revalidation = Promise.resolve().then(() => deps.extraction.revalidateDependents(
204
+ { id: event.oldMemory.frontmatter.id, content: event.oldMemory.content },
205
+ event.replacementId && event.replacementContent !== null
206
+ ? { id: event.replacementId, content: event.replacementContent }
207
+ : null,
208
+ dependents.map((memory) => ({
209
+ id: memory.frontmatter.id,
210
+ category: memory.frontmatter.category,
211
+ content: memory.content,
212
+ })),
213
+ controller.signal,
214
+ ));
184
215
 
185
216
  let verdicts: Array<{ memoryId: string; verdict: "still_valid" | "invalidated" | "uncertain"; reason?: string }>;
186
217
  try {
187
- const response = await deps.extraction.revalidateDependents(
188
- { id: event.oldMemory.frontmatter.id, content: event.oldMemory.content },
189
- event.replacementId && event.replacementContent !== null
190
- ? { id: event.replacementId, content: event.replacementContent }
191
- : null,
192
- dependents.map((memory) => ({
193
- id: memory.frontmatter.id,
194
- category: memory.frontmatter.category,
195
- content: memory.content,
196
- })),
197
- controller.signal,
198
- );
199
- verdicts = response.verdicts;
200
- if (controller.signal.aborted) {
201
- if (timeout !== undefined) clearTimeout(timeout);
202
- const result = emptyResult("timeout");
218
+ const response = deadline
219
+ ? await Promise.race([revalidation, deadline])
220
+ : await revalidation;
221
+ if (timedOut || controller.signal.aborted) {
222
+ const result = emptyResult(
223
+ "timeout",
224
+ Date.now() - startedAt,
225
+ "fast-completion",
226
+ dependents.length,
227
+ );
203
228
  logResult(event, result);
204
229
  return result;
205
230
  }
231
+ verdicts = response.verdicts;
206
232
  } catch (error) {
207
- const result = emptyResult(isTimeoutError(error, controller.signal) ? "timeout" : "llm_error");
233
+ const result = emptyResult(
234
+ timedOut || isTimeoutError(error, controller.signal) ? "timeout" : "llm_error",
235
+ Date.now() - startedAt,
236
+ "fast-completion",
237
+ dependents.length,
238
+ );
208
239
  log.warn(`dependency propagation revalidation failed for ${event.oldMemory.frontmatter.id}: ${error}`);
209
240
  logResult(event, result);
210
- if (timeout !== undefined) clearTimeout(timeout);
211
241
  return result;
242
+ } finally {
243
+ clearTimeout(timeout!);
212
244
  }
213
- if (timeout !== undefined) clearTimeout(timeout);
214
245
 
215
246
  let invalidated = 0;
216
247
  let stillValid = 0;
@@ -257,6 +288,8 @@ export async function propagateInvalidation(
257
288
  stillValid,
258
289
  uncertain,
259
290
  skipped: null,
291
+ route: "fast-completion",
292
+ durationMs: Date.now() - startedAt,
260
293
  };
261
294
  logResult(event, result);
262
295
  return result;
@@ -0,0 +1,119 @@
1
+ import assert from "node:assert/strict";
2
+ import test from "node:test";
3
+
4
+ import {
5
+ revalidateDependentsViaLlm,
6
+ type RevalidationDeps,
7
+ } from "./dependency-revalidation.js";
8
+
9
+ type Dependent = { id: string; category: string; content: string };
10
+ type CompletionOptions = {
11
+ operation?: string;
12
+ priority?: "background" | "recall-critical";
13
+ timeoutMs?: number;
14
+ signal?: AbortSignal;
15
+ temperature?: number;
16
+ maxTokens?: number;
17
+ };
18
+
19
+ type CompletionCall = {
20
+ messages: Array<{ role: string; content: string }>;
21
+ options: CompletionOptions;
22
+ };
23
+
24
+ const superseded = { id: "old", content: "old supporting fact" };
25
+ const replacement = { id: "new", content: "new supporting fact" };
26
+
27
+ function dependents(count: number): Dependent[] {
28
+ return Array.from({ length: count }, (_, index) => ({
29
+ id: `dependent-${String(index + 1).padStart(2, "0")}`,
30
+ category: index % 2 === 0 ? "fact" : "decision",
31
+ content: `dependent claim ${index + 1}`,
32
+ }));
33
+ }
34
+
35
+ function makeDeps(payload: unknown, calls: CompletionCall[]): RevalidationDeps {
36
+ return {
37
+ fastChatCompletion: async (messages, options) => {
38
+ calls.push({ messages, options });
39
+ return { content: JSON.stringify(payload) };
40
+ },
41
+ parseJsonObject: (raw) => JSON.parse(raw ?? "null") as unknown,
42
+ };
43
+ }
44
+
45
+ test("revalidation uses only the injected fast completion seam", async () => {
46
+ const calls: CompletionCall[] = [];
47
+ const signal = new AbortController().signal;
48
+ const requested = dependents(1);
49
+
50
+ await revalidateDependentsViaLlm(
51
+ makeDeps({ verdicts: [{ memoryId: requested[0]!.id, verdict: "still_valid" }] }, calls),
52
+ superseded,
53
+ replacement,
54
+ requested,
55
+ { signal, timeoutMs: 37 },
56
+ );
57
+
58
+ const call = calls[0];
59
+ assert.ok(call);
60
+ assert.equal(call.options.operation, "dependency_revalidation");
61
+ assert.equal(call.options.priority, "background");
62
+ assert.equal(call.options.timeoutMs, 37);
63
+ assert.equal(call.options.signal, signal);
64
+ });
65
+
66
+ test("revalidation normalizes one verdict per dependent for one, five, and ten dependents", async () => {
67
+ for (const count of [1, 5, 10]) {
68
+ const requested = dependents(count);
69
+ const calls: CompletionCall[] = [];
70
+ const result = await revalidateDependentsViaLlm(
71
+ makeDeps(
72
+ {
73
+ verdicts: [
74
+ ...requested.map((dependent) => ({ memoryId: dependent.id, verdict: "invalidated" })),
75
+ { memoryId: "unknown-id", verdict: "invalidated" },
76
+ { memoryId: requested[0]!.id, verdict: "still_valid" },
77
+ ],
78
+ },
79
+ calls,
80
+ ),
81
+ superseded,
82
+ replacement,
83
+ requested,
84
+ { timeoutMs: 37 },
85
+ );
86
+
87
+ assert.equal(result.verdicts.length, count);
88
+ assert.deepEqual(
89
+ result.verdicts.map((verdict) => verdict.memoryId),
90
+ requested.map((dependent) => dependent.id),
91
+ );
92
+ assert.equal(new Set(result.verdicts.map((verdict) => verdict.memoryId)).size, count);
93
+ assert.equal(calls.length, 1);
94
+ }
95
+ });
96
+
97
+ test("revalidation rejects empty completion output", async () => {
98
+ for (const content of [null, "", " "]) {
99
+ const deps: RevalidationDeps = {
100
+ fastChatCompletion: async () => content === null ? null : { content },
101
+ parseJsonObject: (raw) => JSON.parse(raw ?? "null") as unknown,
102
+ };
103
+ await assert.rejects(
104
+ revalidateDependentsViaLlm(deps, superseded, replacement, dependents(1)),
105
+ /no dependency revalidation output/,
106
+ );
107
+ }
108
+ });
109
+
110
+ test("revalidation defaults invalid verdict enums to uncertain", async () => {
111
+ const requested = dependents(1);
112
+ const result = await revalidateDependentsViaLlm(
113
+ makeDeps({ verdicts: [{ memoryId: requested[0]!.id, verdict: "approved" }] }, []),
114
+ superseded,
115
+ replacement,
116
+ requested,
117
+ );
118
+ assert.deepEqual(result.verdicts, [{ memoryId: requested[0]!.id, verdict: "uncertain" }]);
119
+ });
@@ -4,8 +4,6 @@
4
4
  * Extracted from ExtractionEngine to keep extraction.ts under its ratchet
5
5
  * ceiling. The ExtractionEngine.revalidateDependents method delegates here.
6
6
  */
7
- import type { LocalLlmClient } from "../local-llm.js";
8
- import type { FallbackLlmClient, FallbackLlmOptions } from "../fallback-llm.js";
9
7
 
10
8
  export interface RevalidationVerdict {
11
9
  memoryId: string;
@@ -13,18 +11,20 @@ export interface RevalidationVerdict {
13
11
  reason?: string;
14
12
  }
15
13
 
16
- export interface RevalidationDeps {
17
- shouldUseLocalLlm: boolean;
18
- shouldUseDirectClient: boolean;
19
- localLlm: LocalLlmClient;
20
- fallbackLlm: FallbackLlmClient;
21
- client: unknown;
22
- config: { model: string; localLlmFallback?: boolean };
23
- withGatewayAgent: (opts: {
24
- temperature: number;
25
- maxTokens: number;
14
+ export type RevalidationFastChatCompletion = (
15
+ messages: Array<{ role: "system" | "user" | "assistant"; content: string }>,
16
+ options: {
17
+ temperature?: number;
18
+ maxTokens?: number;
19
+ timeoutMs?: number;
20
+ operation?: string;
21
+ priority?: "background" | "recall-critical";
26
22
  signal?: AbortSignal;
27
- }) => FallbackLlmOptions;
23
+ },
24
+ ) => Promise<{ content: string } | null>;
25
+
26
+ export interface RevalidationDeps {
27
+ fastChatCompletion: RevalidationFastChatCompletion;
28
28
  parseJsonObject: (raw: string | null) => unknown;
29
29
  }
30
30
 
@@ -95,78 +95,27 @@ export async function revalidateDependentsViaLlm(
95
95
  superseded: { id: string; content: string },
96
96
  replacement: { id: string; content: string } | null,
97
97
  dependents: Array<{ id: string; category: string; content: string }>,
98
- signal?: AbortSignal,
98
+ options: { signal?: AbortSignal; timeoutMs?: number } = {},
99
99
  ): Promise<{ verdicts: RevalidationVerdict[] }> {
100
100
  const { input, instructionText } = buildPrompt(superseded, replacement, dependents);
101
101
  const maxTokens = Math.max(1024, dependents.length * 256);
102
-
103
- let rawContent: string | null = null;
104
- if (deps.shouldUseLocalLlm) {
105
- try {
106
- const response = await deps.localLlm.chatCompletion(
107
- [
108
- { role: "system", content: instructionText },
109
- { role: "user", content: input },
110
- ],
111
- {
112
- temperature: 0.2,
113
- maxTokens,
114
- operation: "dependency_revalidation",
115
- priority: "background",
116
- signal,
117
- },
118
- );
119
- rawContent = response?.content ?? null;
120
- if (!rawContent && !deps.config.localLlmFallback) {
121
- throw new Error("local LLM returned no dependency revalidation output");
122
- }
123
- } catch (error) {
124
- if (!deps.config.localLlmFallback || signal?.aborted) throw error;
125
- }
126
- }
127
-
128
- if (rawContent === null && !deps.shouldUseDirectClient) {
129
- const response = await deps.fallbackLlm.chatCompletion(
130
- [
131
- { role: "system", content: instructionText },
132
- { role: "user", content: input },
133
- ],
134
- deps.withGatewayAgent({ temperature: 0.2, maxTokens, signal }),
135
- );
136
- rawContent = response?.content ?? null;
137
- if (!rawContent) throw new Error("fallback LLM returned no dependency revalidation output");
138
- }
139
-
140
- if (rawContent === null && deps.shouldUseDirectClient) {
141
- const chatClient = deps.client as unknown as {
142
- chat: {
143
- completions: {
144
- create(
145
- request: {
146
- model: string;
147
- messages: Array<{ role: string; content: string }>;
148
- max_tokens?: number;
149
- },
150
- options?: { signal?: AbortSignal },
151
- ): Promise<{ choices?: Array<{ message?: { content?: string } }> }>;
152
- };
153
- };
154
- };
155
- const response = await chatClient.chat.completions.create(
156
- {
157
- model: deps.config.model,
158
- messages: [
159
- { role: "system", content: instructionText },
160
- { role: "user", content: input },
161
- ],
162
- max_tokens: maxTokens,
163
- },
164
- { signal },
165
- );
166
- rawContent = response.choices?.[0]?.message?.content ?? null;
167
- if (!rawContent?.trim()) {
168
- throw new Error("direct client returned no dependency revalidation output");
169
- }
102
+ const response = await deps.fastChatCompletion(
103
+ [
104
+ { role: "system", content: instructionText },
105
+ { role: "user", content: input },
106
+ ],
107
+ {
108
+ temperature: 0.2,
109
+ maxTokens,
110
+ operation: "dependency_revalidation",
111
+ priority: "background",
112
+ timeoutMs: options.timeoutMs,
113
+ signal: options.signal,
114
+ },
115
+ );
116
+ const rawContent = response?.content ?? null;
117
+ if (!rawContent?.trim()) {
118
+ throw new Error("fast completion returned no dependency revalidation output");
170
119
  }
171
120
 
172
121
  return { verdicts: normalizeVerdicts(deps.parseJsonObject(rawContent), dependents) };
@@ -24,6 +24,7 @@ import { SmartBuffer } from "./buffer.js";
24
24
  import { chunkContent, type ChunkingConfig } from "./chunking.js";
25
25
  import { semanticChunkContent, type SemanticChunkResult } from "./semantic-chunking.js";
26
26
  import { ExtractionEngine } from "./extraction.js";
27
+ import type { RevalidationFastChatCompletion } from "./orchestration/dependency-revalidation.js";
27
28
  import { detectPassiveCorrections } from "./correction/passive-correction-detector.js";
28
29
  import { capturePassiveCorrections, type PassiveCaptureConfig } from "./correction/passive-capture.js";
29
30
  import { createCorrectionService } from "./correction/correction-access-wiring.js";
@@ -1684,6 +1685,7 @@ export class Orchestrator {
1684
1685
  this.localLlm,
1685
1686
  config.gatewayConfig,
1686
1687
  this.modelRegistry,
1688
+ this.fastChatCompletion.bind(this),
1687
1689
  );
1688
1690
  this.lifecyclePolicyCoordinator = new LifecyclePolicyCoordinator({
1689
1691
  config,
@@ -1881,21 +1883,17 @@ export class Orchestrator {
1881
1883
  );
1882
1884
  }
1883
1885
 
1884
- /**
1885
- * Execute a fast-tier LLM chat completion.
1886
- * When gateway model source is active and fastGatewayAgentId is configured,
1887
- * routes through the gateway chain. Otherwise uses the local fast LLM.
1888
- */
1886
+ /** Execute a fast-tier completion through the gateway when configured, otherwise the local fast LLM. */
1889
1887
  private async fastChatCompletion(
1890
1888
  messages: Array<{ role: string; content: string }>,
1891
- options: { temperature?: number; maxTokens?: number; timeoutMs?: number; operation?: string; priority?: "background" | "recall-critical" },
1889
+ options: Parameters<RevalidationFastChatCompletion>[1],
1892
1890
  ): Promise<{ content: string } | null> {
1893
1891
  if (this._fastGatewayLlm && this.config.modelSource === "gateway") {
1894
1892
  const agentId =
1895
1893
  this.config.fastGatewayAgentId || this.config.gatewayAgentId || undefined;
1896
1894
  const result = await this._fastGatewayLlm.chatCompletion(
1897
1895
  messages as Array<{ role: "system" | "user" | "assistant"; content: string }>,
1898
- { temperature: options.temperature, maxTokens: options.maxTokens, timeoutMs: options.timeoutMs, agentId },
1896
+ { ...options, agentId },
1899
1897
  );
1900
1898
  return result ? { content: result.content } : null;
1901
1899
  }
@@ -0,0 +1,53 @@
1
+ import { launchProcessSync } from "./child-process.js";
2
+ import { mergeEnv } from "./env.js";
3
+ import { httpProtocolForHost } from "./http-transport.js";
4
+
5
+ const HEALTH_EXIT_OK = 0;
6
+ const HEALTH_EXIT_UNAUTHORIZED = 2;
7
+
8
+ export function checkDaemonHealth(
9
+ host: string,
10
+ port: number,
11
+ authToken?: string,
12
+ allowInsecureHttp = false,
13
+ ): boolean {
14
+ try {
15
+ const safePort = Math.trunc(Number(port));
16
+ if (!Number.isFinite(safePort) || safePort < 1 || safePort > 65535) return false;
17
+
18
+ const bareHost = host.startsWith("[") && host.endsWith("]") ? host.slice(1, -1) : host;
19
+ const script = [
20
+ "const env = process['env'];",
21
+ "const protocol = env.REMNIC_HEALTH_PROTOCOL;",
22
+ "if (protocol !== 'http' && protocol !== 'https') process.exit(1);",
23
+ "const transport = require(protocol);",
24
+ "const headers = {};",
25
+ "if (env.REMNIC_HEALTH_TOKEN) headers['authorization'] = 'Bearer ' + env.REMNIC_HEALTH_TOKEN;",
26
+ "const req = transport.get({",
27
+ " host: env.REMNIC_HEALTH_HOST,",
28
+ " port: parseInt(env.REMNIC_HEALTH_PORT, 10),",
29
+ " path: '/engram/v1/health', headers, timeout: 3000,",
30
+ "}, (res) => { process.exit(res.statusCode === 200 ? 0 : res.statusCode === 401 ? 2 : 1); });",
31
+ "req.on('error', () => process.exit(1));",
32
+ "req.on('timeout', () => { req.destroy(); process.exit(1); });",
33
+ ].join("\n");
34
+ const env: NodeJS.ProcessEnv = mergeEnv({
35
+ REMNIC_HEALTH_HOST: bareHost,
36
+ REMNIC_HEALTH_PORT: String(safePort),
37
+ REMNIC_HEALTH_PROTOCOL: httpProtocolForHost(host, allowInsecureHttp),
38
+ });
39
+ if (authToken) env.REMNIC_HEALTH_TOKEN = authToken;
40
+
41
+ const launchOptions = { timeout: 4000, env };
42
+ const result = launchProcessSync(process.execPath, ["-e", script], launchOptions);
43
+ if (result.status === HEALTH_EXIT_OK) return true;
44
+ if (result.status !== HEALTH_EXIT_UNAUTHORIZED) return false;
45
+
46
+ console.error("[remnic/connectors] health probe got 401 — retrying after token cache TTL...");
47
+ launchProcessSync(process.execPath, ["-e", "setTimeout(() => {}, 6000)"], { timeout: 7000, env: {} });
48
+ const retry = launchProcessSync(process.execPath, ["-e", script], launchOptions);
49
+ return retry.status === HEALTH_EXIT_OK;
50
+ } catch {
51
+ return false;
52
+ }
53
+ }
@@ -0,0 +1,25 @@
1
+ import { isIP } from "node:net";
2
+
3
+ function normalizedIp(host: string): string {
4
+ const value = host.trim().replace(/^\[/, "").replace(/\]\.?$/, "").replace(/\.$/, "");
5
+ if (isIP(value) === 4) return value;
6
+ if (isIP(value) !== 6) return "";
7
+ return new URL(`http://[${value}]/`).hostname.slice(1, -1);
8
+ }
9
+
10
+ export function isLoopbackHost(host: string): boolean {
11
+ const normalized = host.trim().replace(/^\[/, "").replace(/\]\.?$/, "").replace(/\.$/, "").toLowerCase();
12
+ if (normalized === "localhost" || normalized.endsWith(".localhost")) return true;
13
+
14
+ const ip = normalizedIp(normalized);
15
+ if (ip === "::1") return true;
16
+ if (isIP(ip) === 4) return ip.startsWith("127.");
17
+ if (!ip.startsWith("::ffff:")) return false;
18
+
19
+ const [high, low] = ip.slice("::ffff:".length).split(":");
20
+ return Number.parseInt(high, 16) >>> 8 === 127 || (high === "0" && Number.parseInt(low, 16) >>> 8 === 127);
21
+ }
22
+
23
+ export function httpProtocolForHost(host: string, allowInsecureHttp = false): "http" | "https" {
24
+ return isLoopbackHost(host) || allowInsecureHttp ? "http" : "https";
25
+ }