@remnic/core 9.69.16 → 9.69.17

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 (280) hide show
  1. package/dist/access-admin-ops-surface.d.ts +1 -1
  2. package/dist/access-admin-ops-surface.js +43 -39
  3. package/dist/access-authorization-probe.d.ts +1 -1
  4. package/dist/access-authorization-probe.js +44 -40
  5. package/dist/access-boundary.d.ts +1 -1
  6. package/dist/access-boundary.js +43 -39
  7. package/dist/access-cli.js +103 -102
  8. package/dist/access-cli.js.map +1 -1
  9. package/dist/access-extraction-force-flush.d.ts +1 -1
  10. package/dist/access-extraction-force-flush.js +43 -39
  11. package/dist/access-http-lcm-compaction.d.ts +1 -1
  12. package/dist/access-http-lifecycle-flush.d.ts +1 -1
  13. package/dist/access-http-offline-stream.d.ts +1 -1
  14. package/dist/access-http-query.js +45 -41
  15. package/dist/access-http.d.ts +2 -2
  16. package/dist/access-http.js +63 -59
  17. package/dist/access-identity-continuity-surface.js +43 -39
  18. package/dist/access-lcm-surface.d.ts +1 -1
  19. package/dist/access-lcm-surface.js +43 -39
  20. package/dist/access-mcp-output-schemas.js +1 -1
  21. package/dist/access-mcp.d.ts +1 -1
  22. package/dist/access-mcp.js +54 -50
  23. package/dist/access-namespace-preflight.js +43 -39
  24. package/dist/access-observe-transcript.d.ts +147 -0
  25. package/dist/access-observe-transcript.js +16 -0
  26. package/dist/access-observe-write-surface.d.ts +2 -1
  27. package/dist/access-observe-write-surface.js +43 -39
  28. package/dist/access-offline-manifest.js +3 -3
  29. package/dist/access-operations-batch.js +46 -42
  30. package/dist/access-operations.d.ts +2 -2
  31. package/dist/access-operations.js +51 -47
  32. package/dist/access-recall-concurrency.d.ts +1 -1
  33. package/dist/access-recall-concurrency.js +43 -39
  34. package/dist/access-recall-response.d.ts +1 -1
  35. package/dist/access-recall-response.js +43 -39
  36. package/dist/access-recall-surface.d.ts +1 -1
  37. package/dist/access-recall-surface.js +43 -39
  38. package/dist/access-schema.d.ts +4 -4
  39. package/dist/access-schema.js +5 -5
  40. package/dist/{access-service-tcC_jK6C.d.ts → access-service-DmDS8Y5P.d.ts} +9 -0
  41. package/dist/access-service-helpers.d.ts +1 -1
  42. package/dist/access-service.d.ts +1 -1
  43. package/dist/access-service.js +43 -39
  44. package/dist/access-surface-catalog.d.ts +1 -1
  45. package/dist/access-surface-catalog.js +45 -41
  46. package/dist/access-surface-catalog.js.map +1 -1
  47. package/dist/active-recall.js +6 -6
  48. package/dist/adapters/index.js +4 -4
  49. package/dist/adapters/registry.js +2 -2
  50. package/dist/{auto-sync-Q6Q2FVSC.js → auto-sync-GRUJFD2F.js} +3 -3
  51. package/dist/briefing.js +13 -13
  52. package/dist/causal-behavior.js +2 -2
  53. package/dist/causal-chain.js +2 -2
  54. package/dist/causal-consolidation.js +15 -15
  55. package/dist/causal-retrieval.js +2 -2
  56. package/dist/causal-trajectory-graph.js +2 -2
  57. package/dist/causal-trajectory.js +1 -1
  58. package/dist/{chunk-LEPOP46W.js → chunk-227UFSEQ.js} +4 -4
  59. package/dist/{chunk-AU7Q3LSC.js → chunk-2QSZNTDO.js} +4 -4
  60. package/dist/{chunk-P6GKRT2H.js → chunk-2Z3DG5CQ.js} +1 -1
  61. package/dist/{chunk-MSDIETFC.js → chunk-376CEAYL.js} +53 -44
  62. package/dist/chunk-376CEAYL.js.map +1 -0
  63. package/dist/{chunk-XMIAU4CO.js → chunk-3ZAZ77WB.js} +2 -2
  64. package/dist/{chunk-3TSU662L.js → chunk-46QMN7I7.js} +5 -5
  65. package/dist/{chunk-LF6SHWVV.js → chunk-5CX3NSR7.js} +2 -2
  66. package/dist/{chunk-QRDSXR3V.js → chunk-5DRBG5U6.js} +2 -2
  67. package/dist/{chunk-I4QAH4SY.js → chunk-5J36BYRI.js} +3 -3
  68. package/dist/{chunk-7JV4JST3.js → chunk-5Z6JYMK4.js} +44 -44
  69. package/dist/{chunk-JGXMA6HL.js → chunk-6FUMA6AA.js} +2 -2
  70. package/dist/{chunk-K2IJH4D3.js → chunk-7RRUHJPG.js} +7 -7
  71. package/dist/{chunk-NNBZS3DY.js → chunk-AG46P24C.js} +4 -4
  72. package/dist/{chunk-QUVWFZOU.js → chunk-AYHPGLG6.js} +2 -2
  73. package/dist/{chunk-S35IIP5P.js → chunk-B67W7CBL.js} +2 -2
  74. package/dist/{chunk-OLBZ2WGG.js → chunk-C2JCVZWX.js} +2 -2
  75. package/dist/{chunk-S5G2LAL7.js → chunk-CHWUICVY.js} +4 -4
  76. package/dist/{chunk-XQGFIAG7.js → chunk-CM3JBYD4.js} +2 -2
  77. package/dist/{chunk-F2ERDKY2.js → chunk-CWPVXVIT.js} +16 -16
  78. package/dist/{chunk-BE4Y6GK6.js → chunk-D35XLYQ7.js} +11 -11
  79. package/dist/{chunk-P7LVYPIX.js → chunk-DBLVQROL.js} +3 -3
  80. package/dist/{chunk-5H2G5X4R.js → chunk-DGKQVGLC.js} +3 -3
  81. package/dist/{chunk-M7DGN6JZ.js → chunk-EQEP23JK.js} +2 -2
  82. package/dist/{chunk-I6DUKBUI.js → chunk-EYKDBZB3.js} +2 -2
  83. package/dist/{chunk-LUDXSSTW.js → chunk-FCL6ENLF.js} +2 -2
  84. package/dist/{chunk-LJAP4KSW.js → chunk-FK2SJX27.js} +2 -2
  85. package/dist/{chunk-4WIKMOE3.js → chunk-GF7QLY6E.js} +1 -1
  86. package/dist/{chunk-B64IVEOH.js → chunk-GI726D4G.js} +2 -2
  87. package/dist/{chunk-NHLEFBE2.js → chunk-I4Y6TBD7.js} +3 -3
  88. package/dist/{chunk-BO4PWIJY.js → chunk-I672YBXY.js} +3 -3
  89. package/dist/{chunk-HODFGQGT.js → chunk-IDZU6I4H.js} +2 -2
  90. package/dist/{chunk-OAKATRAN.js → chunk-IO4OJ73B.js} +10 -10
  91. package/dist/{chunk-CTCGHNWN.js → chunk-J2R275FN.js} +4 -4
  92. package/dist/{chunk-C25N5HWX.js → chunk-J6HRJ37H.js} +2 -2
  93. package/dist/{chunk-XJJYSX6F.js → chunk-JCUG7AXZ.js} +4 -4
  94. package/dist/{chunk-BX6GW4KC.js → chunk-JMAG7WZ7.js} +2 -2
  95. package/dist/{chunk-7LCGFUMB.js → chunk-KQAFEZQX.js} +4 -4
  96. package/dist/{chunk-BEXFNGQ3.js → chunk-LE7B5ETE.js} +3 -3
  97. package/dist/chunk-LVE64P5Y.js +80 -0
  98. package/dist/chunk-LVE64P5Y.js.map +1 -0
  99. package/dist/{chunk-VAMZYOOV.js → chunk-MAIBNEB6.js} +2 -2
  100. package/dist/{chunk-VYD63IFH.js → chunk-N3DSSCOR.js} +2 -2
  101. package/dist/{chunk-IEZ6CGTW.js → chunk-N3SS45OW.js} +115 -55
  102. package/dist/chunk-N3SS45OW.js.map +1 -0
  103. package/dist/{chunk-SXHBZXHK.js → chunk-NAOAZASM.js} +5 -5
  104. package/dist/{chunk-3BS2OGDT.js → chunk-NCUODVUI.js} +5 -5
  105. package/dist/{chunk-63I7LMLG.js → chunk-NISCAOSR.js} +2 -2
  106. package/dist/{chunk-YWN3GYI2.js → chunk-NYFWBYY4.js} +2 -2
  107. package/dist/{chunk-BIJAWZYW.js → chunk-OLT3YTDH.js} +4 -4
  108. package/dist/{chunk-BFDOBESV.js → chunk-QFMFZILG.js} +2 -2
  109. package/dist/{chunk-G7VEQEMG.js → chunk-QVSRE355.js} +65 -39
  110. package/dist/chunk-QVSRE355.js.map +1 -0
  111. package/dist/{chunk-N37X5RU7.js → chunk-RACZB5HT.js} +4 -4
  112. package/dist/{chunk-5JQV4T5Q.js → chunk-ROHBPMWD.js} +2 -2
  113. package/dist/{chunk-ZKZCJRRO.js → chunk-S6ZZOFVJ.js} +2 -2
  114. package/dist/{chunk-KLSPKMIO.js → chunk-SJ5JGIBT.js} +2 -2
  115. package/dist/{chunk-JHTF22NQ.js → chunk-TA7UZZMW.js} +2 -2
  116. package/dist/{chunk-2XJDAEAM.js → chunk-V5RWV5DK.js} +5 -5
  117. package/dist/{chunk-2EHDPHMD.js → chunk-W7M7NKR7.js} +2 -2
  118. package/dist/{chunk-4UVDLNHQ.js → chunk-WHO6ITU7.js} +2 -2
  119. package/dist/{chunk-7ZMU4XQT.js → chunk-WMZ6F7GY.js} +2 -2
  120. package/dist/{chunk-W6GEMUZM.js → chunk-WOEKJPJG.js} +13 -13
  121. package/dist/{chunk-5YQ7RFSO.js → chunk-WP37SBRE.js} +2 -2
  122. package/dist/{chunk-RJ57OOCD.js → chunk-X66BHMAU.js} +2 -2
  123. package/dist/{chunk-W272SWN7.js → chunk-X73YCO3E.js} +6 -6
  124. package/dist/{chunk-PAWIY5OQ.js → chunk-XAJWPB2V.js} +6 -6
  125. package/dist/{chunk-QVI63XSO.js → chunk-XR6LLNLU.js} +48 -48
  126. package/dist/{chunk-GIC6BASP.js → chunk-XZBXINXZ.js} +4 -4
  127. package/dist/{chunk-APZXA4WI.js → chunk-Y7E5SUZ6.js} +2 -2
  128. package/dist/{chunk-LDOQE34V.js → chunk-YCJASQMN.js} +2 -2
  129. package/dist/{chunk-H5IIBGDM.js → chunk-YYE5MKRX.js} +2 -2
  130. package/dist/{chunk-TRLCMLX7.js → chunk-YYP5GM6J.js} +2 -2
  131. package/dist/{chunk-OUKBMQ2O.js → chunk-Z3SQEEB6.js} +2 -2
  132. package/dist/{chunk-NN5CQTAJ.js → chunk-ZEBRENA6.js} +2 -2
  133. package/dist/{cli-BI9YYpKx.d.ts → cli-CYQIKncA.d.ts} +1 -1
  134. package/dist/cli.d.ts +2 -2
  135. package/dist/cli.js +85 -81
  136. package/dist/coding/export-okf-codegraph.js +12 -12
  137. package/dist/coding/pre-action-gate.js +2 -2
  138. package/dist/compounding/engine.js +12 -12
  139. package/dist/config.js +6 -6
  140. package/dist/connectors/codex-materialize-runner.js +12 -12
  141. package/dist/connectors/index.js +12 -12
  142. package/dist/convergence-refresh.js +14 -14
  143. package/dist/conversation-index/backend.js +2 -2
  144. package/dist/corpus-watermark.js +14 -14
  145. package/dist/deep-recall-http-glue.d.ts +1 -1
  146. package/dist/deep-recall-http-glue.js +6 -6
  147. package/dist/deep-recall-mcp-tools.d.ts +1 -1
  148. package/dist/deep-recall.js +2 -2
  149. package/dist/entity-retrieval.js +12 -12
  150. package/dist/external-wiki-access.d.ts +1 -1
  151. package/dist/external-wiki-access.js +44 -40
  152. package/dist/external-wiki-mcp-tools.d.ts +1 -1
  153. package/dist/extraction.js +15 -15
  154. package/dist/{graph-edge-decay-FXGELBFA.js → graph-edge-decay-DGTBFALQ.js} +4 -4
  155. package/dist/graph-edge-decay-DGTBFALQ.js.map +1 -0
  156. package/dist/graph-snapshot.js +3 -3
  157. package/dist/graph.js +2 -2
  158. package/dist/harmonic-retrieval.js +1 -1
  159. package/dist/index.d.ts +4 -4
  160. package/dist/index.js +119 -118
  161. package/dist/location/index.js +14 -14
  162. package/dist/maintenance/memory-governance.js +12 -12
  163. package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +12 -12
  164. package/dist/maintenance/rebuild-memory-projection.js +13 -13
  165. package/dist/mcp-memory-inspector-app.d.ts +1 -1
  166. package/dist/memory-subject-cli.d.ts +1 -1
  167. package/dist/memory-subject.d.ts +1 -1
  168. package/dist/namespaces/migrate.js +13 -13
  169. package/dist/namespaces/search.js +9 -9
  170. package/dist/namespaces/storage.js +12 -12
  171. package/dist/offline-sync.js +2 -2
  172. package/dist/operator-doctor-corpus.js +15 -15
  173. package/dist/operator-toolkit.js +28 -28
  174. package/dist/orchestration/maintenance.js +20 -20
  175. package/dist/orchestrator.js +103 -102
  176. package/dist/{public-http-Bocro5ZU.d.ts → public-http-C_hWt6I8.d.ts} +1 -1
  177. package/dist/resume-bundles.js +7 -7
  178. package/dist/search/factory.js +8 -8
  179. package/dist/search/index.js +13 -13
  180. package/dist/search/lancedb-backend.js +2 -2
  181. package/dist/search/meilisearch-backend.js +2 -2
  182. package/dist/search/orama-backend.js +2 -2
  183. package/dist/semantic-consolidation.js +13 -13
  184. package/dist/semantic-rule-promotion.js +12 -12
  185. package/dist/semantic-rule-verifier.js +12 -12
  186. package/dist/source-agent-qualifier.js +12 -12
  187. package/dist/standup/build.js +12 -12
  188. package/dist/storage.js +11 -11
  189. package/dist/summarizer.d.ts +29 -3
  190. package/dist/summarizer.js +6 -4
  191. package/dist/support-passport/index.d.ts +4 -4
  192. package/dist/support-passport/index.js +46 -42
  193. package/dist/transfer/capsule-export.js +2 -2
  194. package/dist/transfer/capsule-import.js +2 -2
  195. package/dist/transfer/export-okf.js +13 -13
  196. package/dist/verified-recall.js +12 -12
  197. package/dist/who-knows-cli.d.ts +1 -1
  198. package/dist/who-knows-cli.js +13 -13
  199. package/dist/who-knows.d.ts +1 -1
  200. package/dist/who-knows.js +12 -12
  201. package/package.json +2 -2
  202. package/src/access-mcp-output-schemas.ts +60 -34
  203. package/src/access-observe-transcript-persistence.test.ts +252 -0
  204. package/src/access-observe-transcript.ts +153 -0
  205. package/src/access-observe-write-surface.ts +234 -224
  206. package/src/access-service.ts +33 -28
  207. package/src/summarizer.ts +217 -111
  208. package/src/summary-snapshot.test.ts +8 -6
  209. package/dist/chunk-G7VEQEMG.js.map +0 -1
  210. package/dist/chunk-IEZ6CGTW.js.map +0 -1
  211. package/dist/chunk-MSDIETFC.js.map +0 -1
  212. /package/dist/{graph-edge-decay-FXGELBFA.js.map → access-observe-transcript.js.map} +0 -0
  213. /package/dist/{auto-sync-Q6Q2FVSC.js.map → auto-sync-GRUJFD2F.js.map} +0 -0
  214. /package/dist/{chunk-LEPOP46W.js.map → chunk-227UFSEQ.js.map} +0 -0
  215. /package/dist/{chunk-AU7Q3LSC.js.map → chunk-2QSZNTDO.js.map} +0 -0
  216. /package/dist/{chunk-P6GKRT2H.js.map → chunk-2Z3DG5CQ.js.map} +0 -0
  217. /package/dist/{chunk-XMIAU4CO.js.map → chunk-3ZAZ77WB.js.map} +0 -0
  218. /package/dist/{chunk-3TSU662L.js.map → chunk-46QMN7I7.js.map} +0 -0
  219. /package/dist/{chunk-LF6SHWVV.js.map → chunk-5CX3NSR7.js.map} +0 -0
  220. /package/dist/{chunk-QRDSXR3V.js.map → chunk-5DRBG5U6.js.map} +0 -0
  221. /package/dist/{chunk-I4QAH4SY.js.map → chunk-5J36BYRI.js.map} +0 -0
  222. /package/dist/{chunk-7JV4JST3.js.map → chunk-5Z6JYMK4.js.map} +0 -0
  223. /package/dist/{chunk-JGXMA6HL.js.map → chunk-6FUMA6AA.js.map} +0 -0
  224. /package/dist/{chunk-K2IJH4D3.js.map → chunk-7RRUHJPG.js.map} +0 -0
  225. /package/dist/{chunk-NNBZS3DY.js.map → chunk-AG46P24C.js.map} +0 -0
  226. /package/dist/{chunk-QUVWFZOU.js.map → chunk-AYHPGLG6.js.map} +0 -0
  227. /package/dist/{chunk-S35IIP5P.js.map → chunk-B67W7CBL.js.map} +0 -0
  228. /package/dist/{chunk-OLBZ2WGG.js.map → chunk-C2JCVZWX.js.map} +0 -0
  229. /package/dist/{chunk-S5G2LAL7.js.map → chunk-CHWUICVY.js.map} +0 -0
  230. /package/dist/{chunk-XQGFIAG7.js.map → chunk-CM3JBYD4.js.map} +0 -0
  231. /package/dist/{chunk-F2ERDKY2.js.map → chunk-CWPVXVIT.js.map} +0 -0
  232. /package/dist/{chunk-BE4Y6GK6.js.map → chunk-D35XLYQ7.js.map} +0 -0
  233. /package/dist/{chunk-P7LVYPIX.js.map → chunk-DBLVQROL.js.map} +0 -0
  234. /package/dist/{chunk-5H2G5X4R.js.map → chunk-DGKQVGLC.js.map} +0 -0
  235. /package/dist/{chunk-M7DGN6JZ.js.map → chunk-EQEP23JK.js.map} +0 -0
  236. /package/dist/{chunk-I6DUKBUI.js.map → chunk-EYKDBZB3.js.map} +0 -0
  237. /package/dist/{chunk-LUDXSSTW.js.map → chunk-FCL6ENLF.js.map} +0 -0
  238. /package/dist/{chunk-LJAP4KSW.js.map → chunk-FK2SJX27.js.map} +0 -0
  239. /package/dist/{chunk-4WIKMOE3.js.map → chunk-GF7QLY6E.js.map} +0 -0
  240. /package/dist/{chunk-B64IVEOH.js.map → chunk-GI726D4G.js.map} +0 -0
  241. /package/dist/{chunk-NHLEFBE2.js.map → chunk-I4Y6TBD7.js.map} +0 -0
  242. /package/dist/{chunk-BO4PWIJY.js.map → chunk-I672YBXY.js.map} +0 -0
  243. /package/dist/{chunk-HODFGQGT.js.map → chunk-IDZU6I4H.js.map} +0 -0
  244. /package/dist/{chunk-OAKATRAN.js.map → chunk-IO4OJ73B.js.map} +0 -0
  245. /package/dist/{chunk-CTCGHNWN.js.map → chunk-J2R275FN.js.map} +0 -0
  246. /package/dist/{chunk-C25N5HWX.js.map → chunk-J6HRJ37H.js.map} +0 -0
  247. /package/dist/{chunk-XJJYSX6F.js.map → chunk-JCUG7AXZ.js.map} +0 -0
  248. /package/dist/{chunk-BX6GW4KC.js.map → chunk-JMAG7WZ7.js.map} +0 -0
  249. /package/dist/{chunk-7LCGFUMB.js.map → chunk-KQAFEZQX.js.map} +0 -0
  250. /package/dist/{chunk-BEXFNGQ3.js.map → chunk-LE7B5ETE.js.map} +0 -0
  251. /package/dist/{chunk-VAMZYOOV.js.map → chunk-MAIBNEB6.js.map} +0 -0
  252. /package/dist/{chunk-VYD63IFH.js.map → chunk-N3DSSCOR.js.map} +0 -0
  253. /package/dist/{chunk-SXHBZXHK.js.map → chunk-NAOAZASM.js.map} +0 -0
  254. /package/dist/{chunk-3BS2OGDT.js.map → chunk-NCUODVUI.js.map} +0 -0
  255. /package/dist/{chunk-63I7LMLG.js.map → chunk-NISCAOSR.js.map} +0 -0
  256. /package/dist/{chunk-YWN3GYI2.js.map → chunk-NYFWBYY4.js.map} +0 -0
  257. /package/dist/{chunk-BIJAWZYW.js.map → chunk-OLT3YTDH.js.map} +0 -0
  258. /package/dist/{chunk-BFDOBESV.js.map → chunk-QFMFZILG.js.map} +0 -0
  259. /package/dist/{chunk-N37X5RU7.js.map → chunk-RACZB5HT.js.map} +0 -0
  260. /package/dist/{chunk-5JQV4T5Q.js.map → chunk-ROHBPMWD.js.map} +0 -0
  261. /package/dist/{chunk-ZKZCJRRO.js.map → chunk-S6ZZOFVJ.js.map} +0 -0
  262. /package/dist/{chunk-KLSPKMIO.js.map → chunk-SJ5JGIBT.js.map} +0 -0
  263. /package/dist/{chunk-JHTF22NQ.js.map → chunk-TA7UZZMW.js.map} +0 -0
  264. /package/dist/{chunk-2XJDAEAM.js.map → chunk-V5RWV5DK.js.map} +0 -0
  265. /package/dist/{chunk-2EHDPHMD.js.map → chunk-W7M7NKR7.js.map} +0 -0
  266. /package/dist/{chunk-4UVDLNHQ.js.map → chunk-WHO6ITU7.js.map} +0 -0
  267. /package/dist/{chunk-7ZMU4XQT.js.map → chunk-WMZ6F7GY.js.map} +0 -0
  268. /package/dist/{chunk-W6GEMUZM.js.map → chunk-WOEKJPJG.js.map} +0 -0
  269. /package/dist/{chunk-5YQ7RFSO.js.map → chunk-WP37SBRE.js.map} +0 -0
  270. /package/dist/{chunk-RJ57OOCD.js.map → chunk-X66BHMAU.js.map} +0 -0
  271. /package/dist/{chunk-W272SWN7.js.map → chunk-X73YCO3E.js.map} +0 -0
  272. /package/dist/{chunk-PAWIY5OQ.js.map → chunk-XAJWPB2V.js.map} +0 -0
  273. /package/dist/{chunk-QVI63XSO.js.map → chunk-XR6LLNLU.js.map} +0 -0
  274. /package/dist/{chunk-GIC6BASP.js.map → chunk-XZBXINXZ.js.map} +0 -0
  275. /package/dist/{chunk-APZXA4WI.js.map → chunk-Y7E5SUZ6.js.map} +0 -0
  276. /package/dist/{chunk-LDOQE34V.js.map → chunk-YCJASQMN.js.map} +0 -0
  277. /package/dist/{chunk-H5IIBGDM.js.map → chunk-YYE5MKRX.js.map} +0 -0
  278. /package/dist/{chunk-TRLCMLX7.js.map → chunk-YYP5GM6J.js.map} +0 -0
  279. /package/dist/{chunk-OUKBMQ2O.js.map → chunk-Z3SQEEB6.js.map} +0 -0
  280. /package/dist/{chunk-NN5CQTAJ.js.map → chunk-ZEBRENA6.js.map} +0 -0
package/src/summarizer.ts CHANGED
@@ -9,20 +9,14 @@ import { extractJsonCandidates } from "./json-extract.js";
9
9
  import type { HourlySummary, TranscriptEntry, PluginConfig, GatewayConfig } from "./types.js";
10
10
  import type { TranscriptManager } from "./transcript.js";
11
11
  import { readSummarySnapshot, upsertSummarySnapshot, writeSummarySnapshot } from "./summary-snapshot.js";
12
- import {
13
- encodeStoragePathSegment,
14
- resolveSafeStoragePath,
15
- } from "./storage-paths.js";
12
+ import { encodeStoragePathSegment, resolveSafeStoragePath } from "./storage-paths.js";
16
13
  import { sessionStoragePaths } from "./session-identity.js";
17
14
  import { resolveLocalLlmCapabilities } from "./capabilities.js";
18
15
  import { resolvePipelineProcessingCapabilities } from "./capabilities.js";
19
16
 
20
17
  // Schema for LLM summary output
21
18
  const HourlySummarySchema = z.object({
22
- bullets: z
23
- .array(z.string().trim().min(1))
24
- .min(1)
25
- .describe("3-5 bullet points summarizing the hour's activity"),
19
+ bullets: z.array(z.string().trim().min(1)).min(1).describe("3-5 bullet points summarizing the hour's activity"),
26
20
  });
27
21
 
28
22
  type HourlySummaryResult = z.infer<typeof HourlySummarySchema>;
@@ -47,6 +41,68 @@ function escapeRegExp(value: string): string {
47
41
  return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
48
42
  }
49
43
 
44
+ /**
45
+ * Outcome stats of one `runHourly` pass (issue #2783). The summarizer must
46
+ * not report success on empty work: an empty or stale transcript store is
47
+ * the delegate-mode starvation signature, and callers surface these counts
48
+ * and the staleness flag as a distinct warning instead of a bare ok.
49
+ */
50
+ export interface HourlySummarizerRunStats {
51
+ sessionsConsidered: number;
52
+ sessionsWithEntries: number;
53
+ summariesWritten: number;
54
+ /** True when the newest transcript entry across the store is older than STALE_STORE_MS. */
55
+ staleStore: boolean;
56
+ /** ISO timestamp of the newest transcript entry seen by the scan, when any exist. */
57
+ newestEntryTimestamp: string | null;
58
+ /** True when the transcript scan itself FAILED (unreadable store) — distinct from an empty store. */
59
+ scanFailed: boolean;
60
+ }
61
+
62
+ /** A store whose newest entry is older than this is considered stale (starvation signal, issue #2783). */
63
+ const STALE_STORE_MS = 2 * 60 * 60 * 1000;
64
+
65
+ /**
66
+ * Interpret one {@link HourlySummarizerRunStats} into the operator-facing
67
+ * message/warning (issue #2783). Every degraded shape — failed scan, empty
68
+ * store, backend-down, stale store — is DISTINCT from success; monitoring
69
+ * alerts on `warning`, never on `ok` (ok only means "the run completed").
70
+ */
71
+ export function summarizeHourlyStatus(stats: HourlySummarizerRunStats): {
72
+ message: string;
73
+ warning?: string;
74
+ } {
75
+ if (stats.scanFailed) {
76
+ return {
77
+ message:
78
+ "Hourly summarization completed, but the transcript store scan FAILED (unreadable directory or I/O error). Investigate the daemon's memoryDir.",
79
+ warning: "transcript store scan failed",
80
+ };
81
+ }
82
+ if (stats.sessionsConsidered === 0) {
83
+ return {
84
+ message:
85
+ "Hourly summarization completed, but the transcript store is empty — no sessions found. If turns are ingested via observe, transcript persistence may be disabled or failing.",
86
+ warning: "transcript store is empty",
87
+ };
88
+ }
89
+ if (stats.sessionsWithEntries > 0 && stats.summariesWritten === 0) {
90
+ return {
91
+ message: `Hourly summarization found ${stats.sessionsWithEntries} session(s) with transcript entries but wrote no summaries — the summarizer backend may be down.`,
92
+ warning: "sessions with entries produced no summaries",
93
+ };
94
+ }
95
+ if (stats.sessionsWithEntries === 0 && stats.staleStore) {
96
+ return {
97
+ message: `Hourly summarization completed with no transcript entries for the target hour, and the store looks stale (newest entry ${stats.newestEntryTimestamp ?? "unknown"}).`,
98
+ warning: "no transcript entries for the target hour and no new entries recently",
99
+ };
100
+ }
101
+ return {
102
+ message: `Hourly summarization completed: ${stats.summariesWritten} summar${stats.summariesWritten === 1 ? "y" : "ies"} written across ${stats.sessionsWithEntries} session${stats.sessionsWithEntries === 1 ? "" : "s"} with transcript entries.`,
103
+ };
104
+ }
105
+
50
106
  export class HourlySummarizer {
51
107
  private summariesDir: string;
52
108
  private config: PluginConfig;
@@ -55,7 +111,12 @@ export class HourlySummarizer {
55
111
  private modelRegistry: ModelRegistry;
56
112
  private transcript?: TranscriptManager;
57
113
 
58
- constructor(config: PluginConfig, gatewayConfig?: GatewayConfig, modelRegistry?: ModelRegistry, transcript?: TranscriptManager) {
114
+ constructor(
115
+ config: PluginConfig,
116
+ gatewayConfig?: GatewayConfig,
117
+ modelRegistry?: ModelRegistry,
118
+ transcript?: TranscriptManager
119
+ ) {
59
120
  this.config = config;
60
121
  this.summariesDir = path.join(config.memoryDir, "summaries", "hourly");
61
122
  this.modelRegistry = modelRegistry ?? new ModelRegistry(config.memoryDir);
@@ -65,12 +126,13 @@ export class HourlySummarizer {
65
126
  this.localLlm = new LocalLlmClient(config, this.modelRegistry);
66
127
 
67
128
  // Initialize fallback client with gateway config
68
- this.fallbackLlm = new FallbackLlmClient(
69
- gatewayConfig,
70
- fallbackLlmRuntimeContextFromConfig(config),
71
- );
129
+ this.fallbackLlm = new FallbackLlmClient(gatewayConfig, fallbackLlmRuntimeContextFromConfig(config));
72
130
 
73
- if (!gatewayConfig?.agents?.defaults?.model?.primary && !resolveLocalLlmCapabilities(config).localLlm && config.modelSource !== "gateway") {
131
+ if (
132
+ !gatewayConfig?.agents?.defaults?.model?.primary &&
133
+ !resolveLocalLlmCapabilities(config).localLlm &&
134
+ config.modelSource !== "gateway"
135
+ ) {
74
136
  log.warn("no gateway default AI and local LLM disabled — hourly summarization disabled");
75
137
  }
76
138
  }
@@ -83,7 +145,9 @@ export class HourlySummarizer {
83
145
  return resolveLocalLlmCapabilities(this.config).localLlm && !this.useGatewayModelSource;
84
146
  }
85
147
 
86
- private withGatewayAgent(options: import("./fallback-llm.js").FallbackLlmOptions): import("./fallback-llm.js").FallbackLlmOptions {
148
+ private withGatewayAgent(
149
+ options: import("./fallback-llm.js").FallbackLlmOptions
150
+ ): import("./fallback-llm.js").FallbackLlmOptions {
87
151
  if (!this.useGatewayModelSource) return options;
88
152
  // Shared resolution (taskModelChain > gatewayAgentId) — gotcha #22. Issue #1365.
89
153
  return { ...options, ...gatewayTaskChainOptions(this.config) };
@@ -95,10 +159,7 @@ export class HourlySummarizer {
95
159
  }
96
160
 
97
161
  private async summarySessionDir(sessionKey: string): Promise<string> {
98
- return resolveSafeStoragePath(
99
- this.summariesDir,
100
- encodeStoragePathSegment(sessionKey, "session"),
101
- );
162
+ return resolveSafeStoragePath(this.summariesDir, encodeStoragePathSegment(sessionKey, "session"));
102
163
  }
103
164
 
104
165
  private async legacySummarySessionDir(sessionKey: string): Promise<string | null> {
@@ -127,9 +188,7 @@ export class HourlySummarizer {
127
188
  if (entries.length === 0) return null;
128
189
 
129
190
  // Format entries for the LLM
130
- const conversation = entries
131
- .map((e) => `[${e.role}] ${e.content}`)
132
- .join("\n\n");
191
+ const conversation = entries.map((e) => `[${e.role}] ${e.content}`).join("\n\n");
133
192
 
134
193
  if (resolvePipelineProcessingCapabilities(this.config).hourlySummariesExtended) {
135
194
  const extended = await this.generateExtended(sessionKey, hourStart, conversation, entries);
@@ -163,9 +222,7 @@ export class HourlySummarizer {
163
222
  const localResult = await this.generateWithLocalLlm(conversation);
164
223
  if (localResult) {
165
224
  const durationMs = Date.now() - startTime;
166
- log.debug(
167
- `generated hourly summary for ${sessionKey} at ${hourIso} in ${durationMs}ms using local LLM`
168
- );
225
+ log.debug(`generated hourly summary for ${sessionKey} at ${hourIso} in ${durationMs}ms using local LLM`);
169
226
  return {
170
227
  hour: hourIso,
171
228
  sessionKey,
@@ -217,15 +274,13 @@ Respond with valid JSON matching this schema:
217
274
  const result = await this.fallbackLlm.parseWithSchema(
218
275
  messages,
219
276
  HourlySummarySchema,
220
- this.withGatewayAgent({ temperature: 0.3, maxTokens: 8192 }),
277
+ this.withGatewayAgent({ temperature: 0.3, maxTokens: 8192 })
221
278
  );
222
279
 
223
280
  const durationMs = Date.now() - startTime;
224
281
 
225
282
  if (result) {
226
- log.debug(
227
- `generated hourly summary for ${sessionKey} at ${hourIso} in ${durationMs}ms via fallback`,
228
- );
283
+ log.debug(`generated hourly summary for ${sessionKey} at ${hourIso} in ${durationMs}ms via fallback`);
229
284
  return {
230
285
  hour: hourIso,
231
286
  sessionKey,
@@ -247,7 +302,7 @@ Respond with valid JSON matching this schema:
247
302
  sessionKey: string,
248
303
  hourStart: Date,
249
304
  conversation: string,
250
- entries: TranscriptEntry[],
305
+ entries: TranscriptEntry[]
251
306
  ): Promise<(HourlySummaryExtendedResult & { _meta: HourlySummaryExtendedMeta }) | null> {
252
307
  const hourIso = hourStart.toISOString();
253
308
  const startTime = Date.now();
@@ -261,12 +316,17 @@ Respond with valid JSON matching this schema:
261
316
 
262
317
  const sys = `You are a conversation summarization system.\n\nSummarize the hour into structured sections.\n\nReturn valid JSON matching:\n{\n \"topics\": [\"...\"],\n \"decisions\": [\"...\"],\n \"actionItems\": [\"...\"],\n \"rejected\": [\"...\"]\n}\n\nGuidelines:\n- Prefer concrete topics and decisions.\n- Action items should be imperative.\n- Rejected ideas are things that were explicitly discarded or reversed.\n- If there are none for a section, return an empty array.\n`;
263
318
 
264
- const toolStatsLine = Object.keys(toolCounts).length > 0
265
- ? `Tools used (counts): ${Object.entries(toolCounts).sort((a,b)=>b[1]-a[1]).slice(0,10).map(([k,v])=>`${k}=${v}`).join(", ")}\n\n`
266
- : "";
319
+ const toolStatsLine =
320
+ Object.keys(toolCounts).length > 0
321
+ ? `Tools used (counts): ${Object.entries(toolCounts)
322
+ .sort((a, b) => b[1] - a[1])
323
+ .slice(0, 10)
324
+ .map(([k, v]) => `${k}=${v}`)
325
+ .join(", ")}\n\n`
326
+ : "";
267
327
  const userTurns = entries.filter((e) => e.role === "user").length;
268
328
  const assistantTurns = entries.filter((e) => e.role === "assistant").length;
269
- const toolCalls = Object.values(toolCounts).reduce((a,b)=>a+b,0);
329
+ const toolCalls = Object.values(toolCounts).reduce((a, b) => a + b, 0);
270
330
  const statsLine = `Stats: userTurns=${userTurns}, assistantTurns=${assistantTurns}, toolCalls=${toolCalls}\n\n`;
271
331
 
272
332
  const user = `Hour: ${hourIso}\nSession: ${sessionKey}\n\n${statsLine}${toolStatsLine}Conversation:\n${conversation}\n`;
@@ -274,8 +334,14 @@ Respond with valid JSON matching this schema:
274
334
  // Try local LLM first if enabled
275
335
  if (this.shouldUseLocalLlm) {
276
336
  try {
277
- const contextSizes = this.modelRegistry.calculateContextSizes(this.config.localLlmModel, this.config.localLlmMaxContext);
278
- const truncated = user.length > contextSizes.maxInputChars ? user.slice(0, contextSizes.maxInputChars) + "\n\n[truncated]" : user;
337
+ const contextSizes = this.modelRegistry.calculateContextSizes(
338
+ this.config.localLlmModel,
339
+ this.config.localLlmMaxContext
340
+ );
341
+ const truncated =
342
+ user.length > contextSizes.maxInputChars
343
+ ? user.slice(0, contextSizes.maxInputChars) + "\n\n[truncated]"
344
+ : user;
279
345
  const response = await this.localLlm.chatCompletion(
280
346
  [
281
347
  { role: "system", content: "Output valid JSON only." },
@@ -286,7 +352,7 @@ Respond with valid JSON matching this schema:
286
352
  maxTokens: contextSizes.maxOutputTokens,
287
353
  operation: "hourly_summary_extended",
288
354
  priority: "background",
289
- },
355
+ }
290
356
  );
291
357
  if (response?.content) {
292
358
  const content = response.content.trim();
@@ -295,7 +361,7 @@ Respond with valid JSON matching this schema:
295
361
  const parsed = JSON.parse(candidate);
296
362
  const result = HourlySummaryExtendedSchema.parse(parsed);
297
363
  log.debug(
298
- `generated extended hourly summary for ${sessionKey} at ${hourIso} in ${Date.now() - startTime}ms (local)`,
364
+ `generated extended hourly summary for ${sessionKey} at ${hourIso} in ${Date.now() - startTime}ms (local)`
299
365
  );
300
366
  return { ...result, _meta: { userTurns, assistantTurns, toolCalls, toolCounts } };
301
367
  } catch {
@@ -316,10 +382,12 @@ Respond with valid JSON matching this schema:
316
382
  { role: "user" as const, content: user },
317
383
  ],
318
384
  HourlySummaryExtendedSchema,
319
- this.withGatewayAgent({ temperature: 0.2, maxTokens: 2048 }),
385
+ this.withGatewayAgent({ temperature: 0.2, maxTokens: 2048 })
320
386
  );
321
387
  if (result) {
322
- log.debug(`generated extended hourly summary for ${sessionKey} at ${hourIso} in ${Date.now() - startTime}ms (fallback)`);
388
+ log.debug(
389
+ `generated extended hourly summary for ${sessionKey} at ${hourIso} in ${Date.now() - startTime}ms (fallback)`
390
+ );
323
391
  return { ...result, _meta: { userTurns, assistantTurns, toolCalls, toolCounts } };
324
392
  }
325
393
  return null;
@@ -342,9 +410,10 @@ Respond with valid JSON matching this schema:
342
410
  log.debug(`Summarizer model context: ${contextSizes.description}`);
343
411
 
344
412
  const maxConversationChars = contextSizes.maxInputChars;
345
- const truncatedConversation = conversation.length > maxConversationChars
346
- ? conversation.slice(0, maxConversationChars) + "\n\n[truncated]"
347
- : conversation;
413
+ const truncatedConversation =
414
+ conversation.length > maxConversationChars
415
+ ? conversation.slice(0, maxConversationChars) + "\n\n[truncated]"
416
+ : conversation;
348
417
 
349
418
  const instructions = `You are a conversation summarization system. Summarize the following conversation transcript into 3-5 concise bullet points.
350
419
 
@@ -373,7 +442,7 @@ Respond with valid JSON matching this schema:
373
442
  maxTokens: contextSizes.maxOutputTokens,
374
443
  operation: "hourly_summary",
375
444
  priority: "background",
376
- },
445
+ }
377
446
  );
378
447
 
379
448
  if (!response?.content) {
@@ -433,9 +502,7 @@ Respond with valid JSON matching this schema:
433
502
  nextHeaderPattern.lastIndex = sectionStart + hourHeader.length;
434
503
  const nextHeader = nextHeaderPattern.exec(existingContent);
435
504
  const beforeHour = existingContent.slice(0, sectionStart);
436
- const afterHour = nextHeader
437
- ? existingContent.slice(nextHeader.index + 1)
438
- : "";
505
+ const afterHour = nextHeader ? existingContent.slice(nextHeader.index + 1) : "";
439
506
  const newSection = this.formatHourSection(summary, hourHeader);
440
507
  existingContent = beforeHour + newSection.trimEnd() + (afterHour ? "\n\n" + afterHour : "\n");
441
508
 
@@ -459,13 +526,15 @@ Respond with valid JSON matching this schema:
459
526
  await upsertSummarySnapshot(this.config.memoryDir, summary);
460
527
  } catch (error) {
461
528
  log.warn(
462
- `hourly summarizer: failed to update summary snapshot for ${summary.sessionKey} (fail-open): ${String(error)}`,
529
+ `hourly summarizer: failed to update summary snapshot for ${summary.sessionKey} (fail-open): ${String(error)}`
463
530
  );
464
531
  }
465
532
  }
466
533
 
467
534
  private formatHourSection(summary: HourlySummary, hourHeader: string): string {
468
- const ext = (summary as any)._extended as (HourlySummaryExtendedResult & { _meta?: HourlySummaryExtendedMeta }) | undefined;
535
+ const ext = (summary as any)._extended as
536
+ | (HourlySummaryExtendedResult & { _meta?: HourlySummaryExtendedMeta })
537
+ | undefined;
469
538
  const meta = (summary as any)._extendedMeta as HourlySummaryExtendedMeta | undefined;
470
539
  const lines: string[] = [hourHeader, ""];
471
540
 
@@ -537,24 +606,18 @@ Respond with valid JSON matching this schema:
537
606
  }
538
607
 
539
608
  const sortedSummaries = Array.from(byHour.values()).sort(
540
- (a, b) => new Date(b.hour).getTime() - new Date(a.hour).getTime(),
609
+ (a, b) => new Date(b.hour).getTime() - new Date(a.hour).getTime()
541
610
  );
542
611
 
543
612
  // Filter to recent hours while materializing the full parsed history.
544
- const recent = sortedSummaries.filter(
545
- (s) => new Date(s.hour).getTime() >= cutoffTime,
546
- );
613
+ const recent = sortedSummaries.filter((s) => new Date(s.hour).getTime() >= cutoffTime);
547
614
 
548
615
  if (sortedSummaries.length > 0) {
549
616
  try {
550
- await writeSummarySnapshot(
551
- this.config.memoryDir,
552
- sessionKey,
553
- sortedSummaries,
554
- );
617
+ await writeSummarySnapshot(this.config.memoryDir, sessionKey, sortedSummaries);
555
618
  } catch (error) {
556
619
  log.warn(
557
- `hourly summarizer: failed to materialize summary snapshot for ${sessionKey} (fail-open): ${String(error)}`,
620
+ `hourly summarizer: failed to materialize summary snapshot for ${sessionKey} (fail-open): ${String(error)}`
558
621
  );
559
622
  }
560
623
  }
@@ -566,10 +629,7 @@ Respond with valid JSON matching this schema:
566
629
  }
567
630
  }
568
631
 
569
- private async readSummaryDir(
570
- sessionDir: string,
571
- sessionKey: string,
572
- ): Promise<HourlySummary[]> {
632
+ private async readSummaryDir(sessionDir: string, sessionKey: string): Promise<HourlySummary[]> {
573
633
  let files: string[];
574
634
  try {
575
635
  files = await readdir(sessionDir);
@@ -594,11 +654,7 @@ Respond with valid JSON matching this schema:
594
654
  return summaries;
595
655
  }
596
656
 
597
- private parseSummaryFile(
598
- content: string,
599
- sessionKey: string,
600
- filename: string
601
- ): HourlySummary[] {
657
+ private parseSummaryFile(content: string, sessionKey: string, filename: string): HourlySummary[] {
602
658
  const summaries: HourlySummary[] = [];
603
659
 
604
660
  // Extract date from filename (YYYY-MM-DD.md)
@@ -671,11 +727,16 @@ Respond with valid JSON matching this schema:
671
727
  }
672
728
 
673
729
  // Main entry point for cron job
674
- async runHourly(): Promise<void> {
730
+ async runHourly(): Promise<HourlySummarizerRunStats> {
675
731
  log.debug("running hourly summary generation");
676
732
 
677
- // Get active sessions from transcript
678
- const sessions = await this.getActiveSessions();
733
+ // Get active sessions from transcript. The scan outcome is kept LOCAL to
734
+ // this invocation (review round 2): shared instance state would let two
735
+ // concurrent runHourly calls cross-report each other's timestamps.
736
+ const scan = await this.getActiveSessions();
737
+ const sessions = scan.sessionKeys;
738
+ let sessionsWithEntries = 0;
739
+ let summariesWritten = 0;
679
740
 
680
741
  for (const sessionKey of sessions) {
681
742
  // Calculate the hour we want to summarize (previous hour)
@@ -691,26 +752,86 @@ Respond with valid JSON matching this schema:
691
752
  log.debug(`no transcript entries for ${sessionKey} at ${hourStart.toISOString()}`);
692
753
  continue;
693
754
  }
755
+ sessionsWithEntries += 1;
694
756
 
695
757
  // Generate and save summary
696
758
  const summary = await this.generateSummary(sessionKey, hourStart, entries);
697
759
  if (summary) {
698
760
  await this.saveSummary(summary);
761
+ summariesWritten += 1;
699
762
  log.info(`generated hourly summary for ${sessionKey} (${entries.length} turns)`);
700
763
  }
701
764
  }
765
+
766
+ return {
767
+ sessionsConsidered: sessions.length,
768
+ sessionsWithEntries,
769
+ summariesWritten,
770
+ // Staleness signal (issue #2783): newest entry across the whole
771
+ // store, from the same scan getActiveSessions already performs.
772
+ staleStore:
773
+ scan.newestEntryTimestamp !== null &&
774
+ Date.now() - new Date(scan.newestEntryTimestamp).getTime() > STALE_STORE_MS,
775
+ newestEntryTimestamp: scan.newestEntryTimestamp,
776
+ scanFailed: scan.scanFailed,
777
+ };
702
778
  }
703
779
 
704
- // Get list of active sessions from transcript directory
705
- private async getActiveSessions(): Promise<string[]> {
706
- const transcriptDir = await resolveSafeStoragePath(
707
- this.config.memoryDir,
708
- "transcripts",
709
- ).catch(() => null);
710
- if (transcriptDir === null) return [];
780
+ // Get list of active sessions from the transcript directory, plus the
781
+ // scan bookkeeping runHourly reports: newest entry timestamp (staleness
782
+ // signal) and whether the scan itself FAILED. A failed scan must not be
783
+ // reported as an empty store — those are different incidents (review
784
+ // round 2).
785
+ private async getActiveSessions(): Promise<{
786
+ sessionKeys: string[];
787
+ newestEntryTimestamp: string | null;
788
+ scanFailed: boolean;
789
+ }> {
790
+ const transcriptDir = await resolveSafeStoragePath(this.config.memoryDir, "transcripts").catch(() => null);
791
+ if (transcriptDir === null) {
792
+ return { sessionKeys: [], newestEntryTimestamp: null, scanFailed: false };
793
+ }
794
+
795
+ const sessionKeys = new Set<string>();
796
+ let newestEntryTimestamp: string | null = null;
797
+ let newestEntryTimeMs = Number.NaN;
798
+ let fileReadFailed = false;
799
+ const collect = async (transcriptPath: string): Promise<void> => {
800
+ try {
801
+ const raw = await readFile(transcriptPath, "utf-8");
802
+ for (const line of raw.split("\n")) {
803
+ if (!line.trim()) continue;
804
+ try {
805
+ const entry = JSON.parse(line) as TranscriptEntry;
806
+ if (typeof entry.sessionKey === "string" && entry.sessionKey.length > 0) {
807
+ sessionKeys.add(entry.sessionKey);
808
+ }
809
+ // Compare parsed epoch values, never strings: a malformed
810
+ // timestamp in a hand-edited file must not poison the staleness
811
+ // signal with a lexically-maximal garbage value (review).
812
+ if (typeof entry.timestamp === "string") {
813
+ const timeMs = new Date(entry.timestamp).getTime();
814
+ if (Number.isFinite(timeMs) && (Number.isNaN(newestEntryTimeMs) || timeMs > newestEntryTimeMs)) {
815
+ newestEntryTimeMs = timeMs;
816
+ newestEntryTimestamp = entry.timestamp;
817
+ }
818
+ }
819
+ } catch {
820
+ // ignore malformed transcript lines
821
+ }
822
+ }
823
+ } catch (err) {
824
+ // ENOENT is a concurrently-deleted file — ignore. Any other read
825
+ // failure (permissions, I/O) means the store is partially UNREADABLE:
826
+ // mark the scan failed so the caller warns instead of reporting an
827
+ // empty store (review round 3).
828
+ if ((err as NodeJS.ErrnoException)?.code !== "ENOENT") {
829
+ fileReadFailed = true;
830
+ }
831
+ }
832
+ };
711
833
 
712
834
  try {
713
- const sessionKeys = new Set<string>();
714
835
  const typeEntries = await readdir(transcriptDir, { withFileTypes: true });
715
836
  for (const typeEnt of typeEntries) {
716
837
  if (!typeEnt.isDirectory()) continue;
@@ -725,44 +846,29 @@ Respond with valid JSON matching this schema:
725
846
  for (const file of files) {
726
847
  const transcriptPath = await resolveSafeStoragePath(chanDir, file).catch(() => null);
727
848
  if (transcriptPath === null) continue;
728
- await this.collectTranscriptSessionKeys(transcriptPath, sessionKeys);
849
+ await collect(transcriptPath);
729
850
  }
730
851
  }
731
852
  }
732
- return Array.from(sessionKeys);
733
- } catch {
734
- return [];
735
- }
736
- }
737
-
738
- private async collectTranscriptSessionKeys(
739
- transcriptPath: string,
740
- sessionKeys: Set<string>,
741
- ): Promise<void> {
742
- try {
743
- const raw = await readFile(transcriptPath, "utf-8");
744
- for (const line of raw.split("\n")) {
745
- if (!line.trim()) continue;
746
- try {
747
- const entry = JSON.parse(line) as TranscriptEntry;
748
- if (typeof entry.sessionKey === "string" && entry.sessionKey.length > 0) {
749
- sessionKeys.add(entry.sessionKey);
750
- }
751
- } catch {
752
- // ignore malformed transcript lines
753
- }
853
+ return {
854
+ sessionKeys: Array.from(sessionKeys),
855
+ newestEntryTimestamp,
856
+ scanFailed: fileReadFailed,
857
+ };
858
+ } catch (err) {
859
+ // ENOENT on the root is a never-written store — an EMPTY store, not a
860
+ // scan failure (those are different incidents).
861
+ const code = (err as NodeJS.ErrnoException)?.code;
862
+ if (code === "ENOENT") {
863
+ return { sessionKeys: [], newestEntryTimestamp: null, scanFailed: false };
754
864
  }
755
- } catch {
756
- // ignore unreadable transcript files
865
+ log.warn(`transcript scan failed: ${err}`);
866
+ return { sessionKeys: [], newestEntryTimestamp: null, scanFailed: true };
757
867
  }
758
868
  }
759
869
 
760
870
  // Get transcript entries for a session within a time range
761
- private async getTranscriptEntries(
762
- sessionKey: string,
763
- startTime: Date,
764
- endTime: Date
765
- ): Promise<TranscriptEntry[]> {
871
+ private async getTranscriptEntries(sessionKey: string, startTime: Date, endTime: Date): Promise<TranscriptEntry[]> {
766
872
  // Shared session-identity layer (issue #1496, rule #22). Arbitrary keys
767
873
  // route to `session/<hash>`; legacy `agent:<id>:...` keep their paths. The
768
874
  // shared helper also supplies the read-back-only candidate dirs (mirrors
@@ -774,8 +880,8 @@ Respond with valid JSON matching this schema:
774
880
  const transcriptRoot = path.join(this.config.memoryDir, "transcripts");
775
881
  const candidateDirs = new Set(
776
882
  [paths.dir, paths.alternateDir, paths.legacyDir, ...paths.readbackDirs].filter(
777
- (dir): dir is string => typeof dir === "string" && dir.length > 0,
778
- ),
883
+ (dir): dir is string => typeof dir === "string" && dir.length > 0
884
+ )
779
885
  );
780
886
  const entries: TranscriptEntry[] = [];
781
887
  // Dedup identical raw rows that a partially-applied migration may have
@@ -605,10 +605,11 @@ test("runHourly keeps processing later sessions when snapshot upsert fails after
605
605
  },
606
606
  ] as any[];
607
607
 
608
- (summarizer as any).getActiveSessions = async () => [
609
- failingSession,
610
- succeedingSession,
611
- ];
608
+ (summarizer as any).getActiveSessions = async () => ({
609
+ sessionKeys: [failingSession, succeedingSession],
610
+ newestEntryTimestamp: null,
611
+ scanFailed: false,
612
+ });
612
613
  (summarizer as any).getTranscriptEntries = async () => fakeEntries;
613
614
  (summarizer as any).generateSummary = async (
614
615
  sessionKey: string,
@@ -680,11 +681,12 @@ test("hourly active session discovery reads every session key in a transcript fi
680
681
  "utf-8",
681
682
  );
682
683
 
683
- const sessions = await (summarizer as any).getActiveSessions();
684
+ const scan = await (summarizer as any).getActiveSessions();
684
685
  assert.deepEqual(
685
- [...sessions].sort(),
686
+ [...scan.sessionKeys].sort(),
686
687
  ["agent:first:main", "agent:second:main"],
687
688
  );
689
+ assert.equal(scan.scanFailed, false);
688
690
  });
689
691
 
690
692
  test("hourly transcript lookup ignores traversal channel paths", async () => {
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/access-mcp-output-schemas.ts"],"sourcesContent":["/**\n * Output-schema registry for MCP tools — extracted from access-mcp.ts to\n * keep that file under the 3000-LOC structural ratchet.\n *\n * Contains the per-suffix JSON-Schema declarations (derived from\n * production TS return contracts) and the application helper that\n * assigns schemas to tool objects.\n */\n\nconst T_STRING = { type: \"string\" } as const;\nconst T_NUMBER = { type: \"number\" } as const;\nconst T_BOOLEAN = { type: \"boolean\" } as const;\nconst T_ARRAY = { type: \"array\" } as const;\nconst T_OBJECT = { type: \"object\" } as const;\nconst T_NULLABLE_OBJECT = { type: [\"object\", \"null\"] } as const;\nconst T_NULLABLE_STRING = { type: [\"string\", \"null\"] } as const;\n\n/** Build a JSON Schema object type with the given properties. */\nfunction objectSchema(\n properties: Record<string, Readonly<Record<string, unknown>>>,\n required?: readonly string[],\n): Record<string, unknown> {\n return {\n type: \"object\",\n properties,\n ...(required && required.length > 0 ? { required } : {}),\n additionalProperties: true,\n };\n}\n\n/**\n * Per-suffix outputSchema registry. Tools not present here fall back to\n * `{ type: \"object\", additionalProperties: true }` in the constructor pass.\n * The `chatgpt_memory_inspector` tool ships its own precise schema and is\n * intentionally absent — the apply pass skips tools that already have one.\n */\nconst TOOL_OUTPUT_SCHEMAS: Readonly<Record<string, Record<string, unknown>>> = {\n recall: objectSchema({\n query: T_STRING,\n namespace: T_STRING,\n context: T_STRING,\n contextComposition: objectSchema({ context: T_STRING, footer: T_STRING }),\n count: T_NUMBER,\n memoryIds: T_ARRAY,\n results: T_ARRAY,\n fallbackUsed: T_BOOLEAN,\n sourcesUsed: T_ARRAY,\n }),\n recall_explain: objectSchema({\n found: T_BOOLEAN,\n snapshot: T_OBJECT,\n intent: T_NULLABLE_OBJECT,\n graph: T_NULLABLE_OBJECT,\n }),\n recall_tier_explain: objectSchema({ snapshotFound: T_BOOLEAN, tierExplain: T_NULLABLE_OBJECT }),\n recall_xray: objectSchema({ snapshotFound: T_BOOLEAN, snapshot: T_OBJECT }),\n who_knows: objectSchema({ topic: T_STRING, results: T_ARRAY }),\n promotion_candidates: objectSchema({ namespace: T_STRING, targetNamespace: T_STRING, candidates: T_ARRAY }),\n set_coding_context: objectSchema({ ok: T_BOOLEAN }),\n wearables_status: objectSchema({\n enabled: T_BOOLEAN,\n timezone: T_STRING,\n sources: T_ARRAY,\n connectorsInstalled: T_ARRAY,\n }),\n wearables_sync: objectSchema({ summaries: T_ARRAY }, [\"summaries\"]),\n transcript_day: objectSchema({ transcripts: T_ARRAY }, [\"transcripts\"]),\n transcript_search: objectSchema({ results: T_ARRAY }, [\"results\"]),\n transcript_memories: objectSchema({ memories: T_ARRAY }, [\"memories\"]),\n location_status: objectSchema({ enabled: T_BOOLEAN, timezone: T_STRING, sources: T_ARRAY, recentDays: T_ARRAY }),\n location_check: objectSchema({ results: T_ARRAY }, [\"results\"]),\n location_sync: objectSchema({ days: T_ARRAY }, [\"days\"]),\n location_backfill: objectSchema({ days: T_ARRAY }, [\"days\"]),\n location_day: objectSchema({ date: T_STRING, found: T_BOOLEAN, sources: T_ARRAY, observationCount: T_NUMBER }),\n meetings_list: objectSchema({ enabled: T_BOOLEAN, days: T_ARRAY }),\n meetings_get: objectSchema({ enabled: T_BOOLEAN, found: T_BOOLEAN, id: T_STRING, record: T_NULLABLE_STRING }),\n meetings_build: objectSchema({\n date: T_STRING,\n enabled: T_BOOLEAN,\n meetings: T_ARRAY,\n built: T_NUMBER,\n skipped: T_NUMBER,\n removed: T_ARRAY,\n }),\n deep_recall: objectSchema({ ok: T_BOOLEAN, error: T_NULLABLE_STRING, entries: T_ARRAY, trace: T_ARRAY, rendered: T_STRING }, [\"entries\", \"trace\"]),\n standup: objectSchema({ date: T_STRING, yesterday: T_STRING, today: T_STRING, highlights: T_ARRAY, priorities: T_ARRAY, blockers: T_ARRAY, activityGrid: T_STRING, markdown: T_STRING }),\n action_confidence: objectSchema({\n schemaVersion: T_NUMBER,\n decision: T_STRING,\n confidence: T_NUMBER,\n risk: T_STRING,\n contextReadiness: T_STRING,\n intendedAction: T_STRING,\n attentionPolicy: T_STRING,\n principle: T_STRING,\n reasons: T_ARRAY,\n blockers: T_ARRAY,\n factors: T_ARRAY,\n retrievedMemoryCount: T_NUMBER,\n scopeMismatchCount: T_NUMBER,\n safeToAct: T_BOOLEAN,\n }),\n day_summary: objectSchema({\n summary: T_STRING,\n bullets: T_ARRAY,\n next_actions: T_ARRAY,\n risks_or_open_loops: T_ARRAY,\n }),\n capsule_export: objectSchema({\n archivePath: T_STRING,\n manifestPath: T_STRING,\n encryptedArchivePath: T_NULLABLE_STRING,\n manifest: T_OBJECT,\n }),\n capsule_import: objectSchema({ imported: T_ARRAY, skipped: T_ARRAY, manifest: T_OBJECT }),\n capsule_list: objectSchema({ namespace: T_STRING, capsulesDir: T_STRING, capsules: T_ARRAY }),\n entity_synthesis_run: objectSchema({\n namespace: T_STRING,\n requested: T_NUMBER,\n processed: T_NUMBER,\n remaining: T_NUMBER,\n }),\n memory_governance_run: objectSchema({\n namespace: T_STRING,\n runId: T_STRING,\n traceId: T_STRING,\n mode: T_STRING,\n reviewQueueCount: T_NUMBER,\n proposedActionCount: T_NUMBER,\n appliedActionCount: T_NUMBER,\n summaryPath: T_STRING,\n reportPath: T_STRING,\n }),\n procedure_mining_run: objectSchema({ namespace: T_STRING, clustersProcessed: T_NUMBER, proceduresWritten: T_NUMBER }),\n pattern_reinforcement_run: objectSchema({\n namespace: T_STRING,\n ran: T_BOOLEAN,\n clustersFound: T_NUMBER,\n canonicalsUpdated: T_NUMBER,\n duplicatesSuperseded: T_NUMBER,\n }),\n procedural_stats: objectSchema({ namespace: T_STRING, counts: T_OBJECT, recent: T_OBJECT }),\n procedure_library_maintenance: objectSchema({\n enabled: T_BOOLEAN,\n namespace: T_STRING,\n report: T_OBJECT,\n }),\n memory_get: objectSchema({ found: T_BOOLEAN, namespace: T_STRING, memory: T_NULLABLE_OBJECT }),\n memory_timeline: objectSchema({ found: T_BOOLEAN, namespace: T_STRING, count: T_NUMBER, timeline: T_ARRAY }),\n memory_store: objectSchema({\n schemaVersion: T_NUMBER,\n operation: T_STRING,\n namespace: T_STRING,\n dryRun: T_BOOLEAN,\n accepted: T_BOOLEAN,\n queued: T_BOOLEAN,\n status: T_STRING,\n memoryId: T_STRING,\n }),\n suggestion_submit: objectSchema({\n schemaVersion: T_NUMBER,\n operation: T_STRING,\n namespace: T_STRING,\n dryRun: T_BOOLEAN,\n accepted: T_BOOLEAN,\n queued: T_BOOLEAN,\n status: T_STRING,\n memoryId: T_STRING,\n }),\n entity_get: objectSchema({ found: T_BOOLEAN, namespace: T_STRING, entity: T_NULLABLE_OBJECT }),\n review_queue_list: objectSchema({ found: T_BOOLEAN, runId: T_STRING, reviewQueue: T_ARRAY }),\n observe: objectSchema({\n accepted: T_NUMBER,\n sessionKey: T_STRING,\n namespace: T_STRING,\n effectiveNamespace: T_STRING,\n lcmArchived: T_BOOLEAN,\n extractionQueued: T_BOOLEAN,\n }),\n lcm_search: objectSchema({\n query: T_STRING,\n namespace: T_STRING,\n results: T_ARRAY,\n count: T_NUMBER,\n lcmEnabled: T_BOOLEAN,\n }),\n lcm_compaction_flush: objectSchema({\n enabled: T_BOOLEAN,\n flushed: T_BOOLEAN,\n sessionKey: T_STRING,\n namespace: T_STRING,\n }),\n extraction_force_flush: objectSchema({\n flushed: T_BOOLEAN,\n sessionKey: T_STRING,\n namespace: T_STRING,\n effectiveNamespace: T_STRING,\n }),\n lcm_compaction_record: objectSchema({\n enabled: T_BOOLEAN,\n recorded: T_BOOLEAN,\n sessionKey: T_STRING,\n namespace: T_STRING,\n }),\n continuity_audit_generate: objectSchema({ enabled: T_BOOLEAN, period: T_STRING, reportPath: T_STRING }),\n continuity_incident_open: objectSchema({ created: T_BOOLEAN, incident: T_NULLABLE_OBJECT }),\n continuity_incident_close: objectSchema({ closed: T_BOOLEAN, incident: T_NULLABLE_OBJECT }),\n continuity_incident_list: objectSchema({ incidents: T_ARRAY }),\n continuity_loop_add_or_update: objectSchema({ saved: T_BOOLEAN, loop: T_NULLABLE_OBJECT }),\n continuity_loop_review: objectSchema({ reviewed: T_BOOLEAN, loop: T_NULLABLE_OBJECT }),\n identity_anchor_get: objectSchema({ found: T_BOOLEAN, anchor: T_NULLABLE_STRING }),\n identity_anchor_update: objectSchema({ updated: T_BOOLEAN, sections: T_ARRAY }),\n memory_identity: objectSchema({ found: T_BOOLEAN, identity: T_NULLABLE_STRING, message: T_STRING }),\n work_task: objectSchema({\n action: T_STRING,\n task: T_NULLABLE_OBJECT,\n tasks: T_ARRAY,\n count: T_NUMBER,\n deleted: T_BOOLEAN,\n }),\n work_project: objectSchema({\n action: T_STRING,\n project: T_NULLABLE_OBJECT,\n projects: T_ARRAY,\n count: T_NUMBER,\n deleted: T_BOOLEAN,\n }),\n work_board: objectSchema({ action: T_STRING, markdown: T_STRING, snapshot: T_OBJECT, result: T_OBJECT }),\n shared_context_write_output: objectSchema({ written: T_BOOLEAN, path: T_STRING }),\n shared_feedback_record: objectSchema({ recorded: T_BOOLEAN }),\n shared_priorities_append: objectSchema({ appended: T_BOOLEAN }),\n shared_context_cross_signals_run: objectSchema({\n crossSignalsMarkdownPath: T_STRING,\n crossSignalsPath: T_STRING,\n sourceCount: T_NUMBER,\n feedbackCount: T_NUMBER,\n overlapCount: T_NUMBER,\n }),\n shared_context_curate_daily: objectSchema({\n roundtablePath: T_STRING,\n crossSignalsMarkdownPath: T_STRING,\n crossSignalsPath: T_STRING,\n overlapCount: T_NUMBER,\n }),\n compounding_weekly_synthesize: objectSchema({\n weekId: T_STRING,\n reportPath: T_STRING,\n reportJsonPath: T_STRING,\n rubricsPath: T_STRING,\n rubricsIndexPath: T_STRING,\n mistakesCount: T_NUMBER,\n promotionCandidateCount: T_NUMBER,\n }),\n compounding_promote_candidate: objectSchema({\n enabled: T_BOOLEAN,\n dryRun: T_BOOLEAN,\n weekId: T_STRING,\n promoted: T_ARRAY,\n skipped: T_ARRAY,\n tombstoneBlocked: T_ARRAY,\n }),\n compression_guidelines_optimize: objectSchema({\n enabled: T_BOOLEAN,\n dryRun: T_BOOLEAN,\n eventCount: T_NUMBER,\n nextGuidelineVersion: T_NUMBER,\n changedRules: T_NUMBER,\n semanticRefinementApplied: T_BOOLEAN,\n persisted: T_BOOLEAN,\n }),\n compression_guidelines_activate: objectSchema({\n enabled: T_BOOLEAN,\n activated: T_BOOLEAN,\n guidelineVersion: { type: [\"number\", \"null\"] } as const,\n }),\n memory_search: objectSchema({ query: T_STRING, results: T_ARRAY, count: T_NUMBER }),\n external_wiki_search: objectSchema({\n query: T_STRING,\n hits: {\n type: \"array\",\n items: {\n type: \"object\",\n properties: {\n wikiId: T_STRING,\n title: T_STRING,\n path: T_STRING,\n snippet: T_STRING,\n score: T_NUMBER,\n rank: T_NUMBER,\n citations: {\n type: \"array\",\n items: {\n type: \"object\",\n properties: {\n path: T_STRING,\n lineStart: T_NUMBER,\n lineEnd: T_NUMBER,\n note: T_STRING,\n },\n required: [\"path\", \"lineStart\", \"lineEnd\", \"note\"],\n additionalProperties: false,\n },\n },\n indexBlurb: T_STRING,\n },\n required: [\"wikiId\", \"title\", \"path\", \"snippet\", \"score\", \"rank\", \"citations\"],\n additionalProperties: false,\n },\n },\n count: T_NUMBER,\n degradedWikiIds: T_ARRAY,\n }, [\"query\", \"hits\", \"count\", \"degradedWikiIds\"]),\n memory_profile: objectSchema({ profile: T_STRING }),\n memory_entities_list: objectSchema({ entities: T_ARRAY, count: T_NUMBER }),\n memory_questions: objectSchema({ questions: T_ARRAY, count: T_NUMBER }),\n memory_last_recall: objectSchema({\n sessionKey: T_STRING,\n recordedAt: T_STRING,\n queryHash: T_STRING,\n queryLen: T_NUMBER,\n memoryIds: T_ARRAY,\n namespace: T_STRING,\n recallNamespaces: T_ARRAY,\n plannerMode: T_STRING,\n requestedMode: T_STRING,\n source: T_STRING,\n fallbackUsed: T_BOOLEAN,\n sourcesUsed: T_ARRAY,\n latencyMs: T_NUMBER,\n includedMemories: T_ARRAY,\n message: T_NULLABLE_STRING,\n }),\n memory_intent_debug: objectSchema({\n recordedAt: T_STRING,\n promptHash: T_STRING,\n promptLength: T_NUMBER,\n retrievalQueryHash: T_STRING,\n retrievalQueryLength: T_NUMBER,\n plannerEnabled: T_BOOLEAN,\n plannedMode: T_STRING,\n effectiveMode: T_STRING,\n recallResultLimit: T_NUMBER,\n queryIntent: T_OBJECT,\n graphExpandedIntentDetected: T_BOOLEAN,\n graphDecision: T_OBJECT,\n message: T_NULLABLE_STRING,\n }),\n memory_qmd_debug: objectSchema({\n recordedAt: T_STRING,\n queryHash: T_STRING,\n queryLength: T_NUMBER,\n collection: T_STRING,\n namespaces: T_ARRAY,\n fetchLimit: T_NUMBER,\n primaryResultCount: T_NUMBER,\n hybridResultCount: T_NUMBER,\n queryAwareSeedCount: T_NUMBER,\n resultCount: T_NUMBER,\n intentHint: T_STRING,\n explainEnabled: T_BOOLEAN,\n hybridTopUpUsed: T_BOOLEAN,\n hybridTopUpSkippedReason: T_STRING,\n results: T_ARRAY,\n message: T_NULLABLE_STRING,\n }),\n memory_graph_explain: objectSchema({ explanation: T_STRING }),\n graph_snapshot: objectSchema({ nodes: T_ARRAY, edges: T_ARRAY }),\n memory_feedback: objectSchema({ recorded: T_BOOLEAN, enabled: T_BOOLEAN }),\n memory_promote: objectSchema({ promoted: T_BOOLEAN, memoryId: T_STRING }),\n memory_outcome: objectSchema({\n ok: T_BOOLEAN,\n memoryId: T_STRING,\n mw_success: T_NUMBER,\n mw_fail: T_NUMBER,\n reason: T_STRING,\n message: T_STRING,\n }),\n memory_action_apply: objectSchema({ recorded: T_BOOLEAN, event: T_OBJECT }),\n context_checkpoint: objectSchema({ saved: T_BOOLEAN }),\n briefing: objectSchema({\n markdown: T_STRING,\n json: T_OBJECT,\n window: T_OBJECT,\n format: T_STRING,\n namespace: T_STRING,\n }),\n review_list: objectSchema({ pairs: T_ARRAY, total: T_NUMBER, durationMs: T_NUMBER }),\n review_resolve: objectSchema({ pairId: T_STRING, verb: T_STRING, affectedIds: T_ARRAY, message: T_STRING }),\n contradiction_scan_run: objectSchema({\n scanned: T_NUMBER,\n candidates: T_NUMBER,\n judged: T_NUMBER,\n queued: T_NUMBER,\n cooledDown: T_NUMBER,\n elapsedMs: T_NUMBER,\n }),\n preference_drift_scan: objectSchema({\n schemaVersion: T_NUMBER,\n generatedAt: T_STRING,\n mode: T_STRING,\n namespace: T_STRING,\n scanned: T_NUMBER,\n eligible: T_NUMBER,\n findings: T_ARRAY,\n counts: T_OBJECT,\n appliedCount: T_NUMBER,\n reviewItemsOpened: T_NUMBER,\n elapsedMs: T_NUMBER,\n skippedReason: T_STRING,\n }),\n memory_summarize_hourly: objectSchema({ ok: T_BOOLEAN, message: T_STRING }),\n conversation_index_update: objectSchema({\n enabled: T_BOOLEAN,\n sessions: T_NUMBER,\n chunks: T_NUMBER,\n skipped: T_NUMBER,\n embeddedRuns: T_NUMBER,\n }),\n profiling_report: objectSchema({\n enabled: T_BOOLEAN,\n format: T_STRING,\n traces: T_ARRAY,\n stats: T_OBJECT,\n bottleneck: T_NULLABLE_STRING,\n }),\n graph_edge_decay_run: objectSchema({ ranAt: T_STRING, disabled: T_BOOLEAN, reason: T_STRING, results: T_ARRAY }),\n live_connectors_run: objectSchema({\n ranAt: T_STRING,\n force: T_BOOLEAN,\n totalDocsImported: T_NUMBER,\n ranCount: T_NUMBER,\n skippedCount: T_NUMBER,\n errorCount: T_NUMBER,\n results: T_ARRAY,\n }),\n peer_list: objectSchema({ peers: T_ARRAY }),\n peer_get: objectSchema({ found: T_BOOLEAN, peer: T_NULLABLE_OBJECT }),\n peer_set: objectSchema({ ok: T_BOOLEAN, created: T_BOOLEAN, peer: T_OBJECT }),\n peer_delete: objectSchema({ ok: T_BOOLEAN, deleted: T_BOOLEAN }),\n peer_profile_get: objectSchema({\n found: T_BOOLEAN,\n profile: {\n type: \"object\",\n properties: {\n peerId: T_STRING,\n updatedAt: T_STRING,\n fields: { type: \"object\", additionalProperties: T_STRING },\n provenance: {\n type: \"object\",\n additionalProperties: {\n type: \"array\",\n items: {\n type: \"object\",\n properties: {\n observedAt: T_STRING,\n signal: T_STRING,\n sourceSessionId: T_STRING,\n note: T_STRING,\n },\n required: [\"observedAt\", \"signal\"],\n additionalProperties: true,\n },\n },\n },\n },\n required: [\"peerId\", \"updatedAt\", \"fields\", \"provenance\"],\n additionalProperties: true,\n },\n }),\n peer_forget: objectSchema({ ok: T_BOOLEAN, purged: T_BOOLEAN }),\n console_state: objectSchema({\n capturedAt: T_STRING,\n bufferState: T_OBJECT,\n extractionQueue: T_OBJECT,\n dedupRecent: T_ARRAY,\n maintenanceLedgerTail: T_ARRAY,\n qmdProbe: T_OBJECT,\n daemon: T_OBJECT,\n errors: T_ARRAY,\n }),\n dreams_status: objectSchema({ phases: T_OBJECT, windowStart: T_STRING, windowEnd: T_STRING }),\n dreams_run: objectSchema({ phase: T_STRING, durationMs: T_NUMBER, itemsProcessed: T_NUMBER }),\n coding_decision: objectSchema({\n subcommand: T_STRING,\n records: T_ARRAY,\n count: T_NUMBER,\n found: T_BOOLEAN,\n memoryId: T_STRING,\n status: T_STRING,\n supersededMemoryId: T_STRING,\n replacementMemoryId: T_STRING,\n }),\n coding_architecture: objectSchema({\n subcommand: T_STRING,\n found: T_BOOLEAN,\n refreshed: T_BOOLEAN,\n memoryId: T_STRING,\n }),\n coding_delta: objectSchema({\n subcommand: T_STRING,\n ok: T_BOOLEAN,\n kind: T_STRING,\n delta: T_OBJECT,\n nextState: T_OBJECT,\n }),\n memory_correct_plan: objectSchema({\n planId: T_STRING,\n namespace: T_STRING,\n diff: T_STRING,\n actions: T_ARRAY,\n confidence: T_NUMBER,\n }),\n memory_correct_apply: objectSchema({\n planId: T_STRING,\n status: T_STRING,\n results: T_ARRAY,\n auditMemoryId: T_STRING,\n appliedAt: T_STRING,\n }),\n memory_chat: objectSchema({\n reply: T_STRING,\n chatSessionId: T_STRING,\n pendingPlan: {\n type: \"object\",\n properties: { planId: T_STRING, preview: T_STRING },\n required: [\"planId\", \"preview\"],\n additionalProperties: true,\n },\n skippedTools: { type: \"array\", items: T_STRING },\n }),\n codegraph_index: objectSchema({ ok: T_BOOLEAN, result: T_OBJECT }),\n codegraph_list_projects: objectSchema({ ok: T_BOOLEAN, result: T_OBJECT }),\n codegraph_delete_project: objectSchema({ ok: T_BOOLEAN, result: T_OBJECT }),\n codegraph_index_status: objectSchema({ ok: T_BOOLEAN, result: T_OBJECT }),\n codegraph_search_graph: objectSchema({ ok: T_BOOLEAN, result: T_OBJECT }),\n codegraph_trace_path: objectSchema({ ok: T_BOOLEAN, result: T_OBJECT }),\n codegraph_detect_changes: objectSchema({ ok: T_BOOLEAN, result: T_OBJECT }),\n codegraph_query_graph: objectSchema({ ok: T_BOOLEAN, result: T_OBJECT }),\n codegraph_get_schema: objectSchema({ ok: T_BOOLEAN, result: T_OBJECT }),\n codegraph_get_snippet: objectSchema({ ok: T_BOOLEAN, result: T_OBJECT }),\n codegraph_get_architecture: objectSchema({ ok: T_BOOLEAN, result: T_OBJECT }),\n codegraph_search_code: objectSchema({ ok: T_BOOLEAN, result: T_OBJECT }),\n codegraph_manage_adr: objectSchema({ ok: T_BOOLEAN, result: T_OBJECT }),\n codegraph_ingest_traces: objectSchema({ ok: T_BOOLEAN, result: T_OBJECT }),\n};\n\n/**\n * Apply outputSchema from the registry to every tool that lacks one.\n * Suffix resolution strips the canonical or legacy prefix so both\n * `remnic_*` and `engram.*` aliases inherit the same schema.\n * Tools that already have an explicit outputSchema are skipped.\n */\nexport function applyToolOutputSchemas<T extends { name: string; outputSchema?: unknown }>(\n tools: ReadonlyArray<T>,\n canonicalPrefix: string,\n legacyPrefix: string\n): T[] {\n return tools.map((tool) => {\n if (tool.outputSchema) return tool;\n const name = tool.name as string;\n const suffix = name.startsWith(canonicalPrefix)\n ? name.slice(canonicalPrefix.length)\n : name.startsWith(legacyPrefix)\n ? name.slice(legacyPrefix.length)\n : name;\n return { ...tool, outputSchema: TOOL_OUTPUT_SCHEMAS[suffix] ?? { type: \"object\", additionalProperties: true } };\n });\n}\n"],"mappings":"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","names":[]}