nodedex 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (469) hide show
  1. package/adapters/claude-code-watcher.mjs +336 -0
  2. package/adapters/hermes-statedb-watcher.mjs +234 -0
  3. package/adapters/nodedex-capture-core.mjs +129 -0
  4. package/adapters/nodedex-capture.mjs +169 -0
  5. package/dist/agent-protocol.d.ts +7 -0
  6. package/dist/agent-protocol.d.ts.map +1 -0
  7. package/dist/agent-protocol.js +38 -0
  8. package/dist/agent-protocol.js.map +1 -0
  9. package/dist/api-server.d.ts +5 -0
  10. package/dist/api-server.d.ts.map +1 -0
  11. package/dist/api-server.js +351 -0
  12. package/dist/api-server.js.map +1 -0
  13. package/dist/boot-env.d.ts +2 -0
  14. package/dist/boot-env.d.ts.map +1 -0
  15. package/dist/boot-env.js +12 -0
  16. package/dist/boot-env.js.map +1 -0
  17. package/dist/engine/__tests__/search-core.test.d.ts +2 -0
  18. package/dist/engine/__tests__/search-core.test.d.ts.map +1 -0
  19. package/dist/engine/__tests__/search-core.test.js +139 -0
  20. package/dist/engine/__tests__/search-core.test.js.map +1 -0
  21. package/dist/engine/ai-provider.d.ts +45 -0
  22. package/dist/engine/ai-provider.d.ts.map +1 -0
  23. package/dist/engine/ai-provider.js +5 -0
  24. package/dist/engine/ai-provider.js.map +1 -0
  25. package/dist/engine/embeddings.d.ts +51 -0
  26. package/dist/engine/embeddings.d.ts.map +1 -0
  27. package/dist/engine/embeddings.js +89 -0
  28. package/dist/engine/embeddings.js.map +1 -0
  29. package/dist/engine/providers/__tests__/failure-policy.test.d.ts +2 -0
  30. package/dist/engine/providers/__tests__/failure-policy.test.d.ts.map +1 -0
  31. package/dist/engine/providers/__tests__/failure-policy.test.js +134 -0
  32. package/dist/engine/providers/__tests__/failure-policy.test.js.map +1 -0
  33. package/dist/engine/providers/__tests__/model-caps.test.d.ts +2 -0
  34. package/dist/engine/providers/__tests__/model-caps.test.d.ts.map +1 -0
  35. package/dist/engine/providers/__tests__/model-caps.test.js +38 -0
  36. package/dist/engine/providers/__tests__/model-caps.test.js.map +1 -0
  37. package/dist/engine/providers/__tests__/openai-structured.test.d.ts +2 -0
  38. package/dist/engine/providers/__tests__/openai-structured.test.d.ts.map +1 -0
  39. package/dist/engine/providers/__tests__/openai-structured.test.js +73 -0
  40. package/dist/engine/providers/__tests__/openai-structured.test.js.map +1 -0
  41. package/dist/engine/providers/__tests__/usage-ledger.test.d.ts +2 -0
  42. package/dist/engine/providers/__tests__/usage-ledger.test.d.ts.map +1 -0
  43. package/dist/engine/providers/__tests__/usage-ledger.test.js +108 -0
  44. package/dist/engine/providers/__tests__/usage-ledger.test.js.map +1 -0
  45. package/dist/engine/providers/anthropic.d.ts +17 -0
  46. package/dist/engine/providers/anthropic.d.ts.map +1 -0
  47. package/dist/engine/providers/anthropic.js +125 -0
  48. package/dist/engine/providers/anthropic.js.map +1 -0
  49. package/dist/engine/providers/failure-policy.d.ts +56 -0
  50. package/dist/engine/providers/failure-policy.d.ts.map +1 -0
  51. package/dist/engine/providers/failure-policy.js +120 -0
  52. package/dist/engine/providers/failure-policy.js.map +1 -0
  53. package/dist/engine/providers/gemini.d.ts +22 -0
  54. package/dist/engine/providers/gemini.d.ts.map +1 -0
  55. package/dist/engine/providers/gemini.js +180 -0
  56. package/dist/engine/providers/gemini.js.map +1 -0
  57. package/dist/engine/providers/index.d.ts +8 -0
  58. package/dist/engine/providers/index.d.ts.map +1 -0
  59. package/dist/engine/providers/index.js +67 -0
  60. package/dist/engine/providers/index.js.map +1 -0
  61. package/dist/engine/providers/local.d.ts +12 -0
  62. package/dist/engine/providers/local.d.ts.map +1 -0
  63. package/dist/engine/providers/local.js +46 -0
  64. package/dist/engine/providers/local.js.map +1 -0
  65. package/dist/engine/providers/model-caps.d.ts +6 -0
  66. package/dist/engine/providers/model-caps.d.ts.map +1 -0
  67. package/dist/engine/providers/model-caps.js +49 -0
  68. package/dist/engine/providers/model-caps.js.map +1 -0
  69. package/dist/engine/providers/openai.d.ts +30 -0
  70. package/dist/engine/providers/openai.d.ts.map +1 -0
  71. package/dist/engine/providers/openai.js +309 -0
  72. package/dist/engine/providers/openai.js.map +1 -0
  73. package/dist/engine/providers/usage-ledger.d.ts +69 -0
  74. package/dist/engine/providers/usage-ledger.d.ts.map +1 -0
  75. package/dist/engine/providers/usage-ledger.js +209 -0
  76. package/dist/engine/providers/usage-ledger.js.map +1 -0
  77. package/dist/engine/search-core.d.ts +40 -0
  78. package/dist/engine/search-core.d.ts.map +1 -0
  79. package/dist/engine/search-core.js +109 -0
  80. package/dist/engine/search-core.js.map +1 -0
  81. package/dist/engine/vector-math.d.ts +5 -0
  82. package/dist/engine/vector-math.d.ts.map +1 -0
  83. package/dist/engine/vector-math.js +25 -0
  84. package/dist/engine/vector-math.js.map +1 -0
  85. package/dist/home-env.d.ts +26 -0
  86. package/dist/home-env.d.ts.map +1 -0
  87. package/dist/home-env.js +87 -0
  88. package/dist/home-env.js.map +1 -0
  89. package/dist/mcp-server.d.ts +13 -0
  90. package/dist/mcp-server.d.ts.map +1 -0
  91. package/dist/mcp-server.js +79 -0
  92. package/dist/mcp-server.js.map +1 -0
  93. package/dist/middleware/auth.d.ts +23 -0
  94. package/dist/middleware/auth.d.ts.map +1 -0
  95. package/dist/middleware/auth.js +104 -0
  96. package/dist/middleware/auth.js.map +1 -0
  97. package/dist/middleware/auto-recall.d.ts +7 -0
  98. package/dist/middleware/auto-recall.d.ts.map +1 -0
  99. package/dist/middleware/auto-recall.js +257 -0
  100. package/dist/middleware/auto-recall.js.map +1 -0
  101. package/dist/middleware/auto-reflect.d.ts +4 -0
  102. package/dist/middleware/auto-reflect.d.ts.map +1 -0
  103. package/dist/middleware/auto-reflect.js +5 -0
  104. package/dist/middleware/auto-reflect.js.map +1 -0
  105. package/dist/middleware/reflect/apply-flag-verdict.d.ts +27 -0
  106. package/dist/middleware/reflect/apply-flag-verdict.d.ts.map +1 -0
  107. package/dist/middleware/reflect/apply-flag-verdict.js +57 -0
  108. package/dist/middleware/reflect/apply-flag-verdict.js.map +1 -0
  109. package/dist/middleware/reflect/arc-entity-resolve.d.ts +29 -0
  110. package/dist/middleware/reflect/arc-entity-resolve.d.ts.map +1 -0
  111. package/dist/middleware/reflect/arc-entity-resolve.js +356 -0
  112. package/dist/middleware/reflect/arc-entity-resolve.js.map +1 -0
  113. package/dist/middleware/reflect/arc-inactivity-timer.d.ts +47 -0
  114. package/dist/middleware/reflect/arc-inactivity-timer.d.ts.map +1 -0
  115. package/dist/middleware/reflect/arc-inactivity-timer.js +175 -0
  116. package/dist/middleware/reflect/arc-inactivity-timer.js.map +1 -0
  117. package/dist/middleware/reflect/arc-pipeline.d.ts +33 -0
  118. package/dist/middleware/reflect/arc-pipeline.d.ts.map +1 -0
  119. package/dist/middleware/reflect/arc-pipeline.js +498 -0
  120. package/dist/middleware/reflect/arc-pipeline.js.map +1 -0
  121. package/dist/middleware/reflect/comprehend-pergroup.d.ts +100 -0
  122. package/dist/middleware/reflect/comprehend-pergroup.d.ts.map +1 -0
  123. package/dist/middleware/reflect/comprehend-pergroup.js +610 -0
  124. package/dist/middleware/reflect/comprehend-pergroup.js.map +1 -0
  125. package/dist/middleware/reflect/comprehend.d.ts +237 -0
  126. package/dist/middleware/reflect/comprehend.d.ts.map +1 -0
  127. package/dist/middleware/reflect/comprehend.js +706 -0
  128. package/dist/middleware/reflect/comprehend.js.map +1 -0
  129. package/dist/middleware/reflect/config.d.ts +34 -0
  130. package/dist/middleware/reflect/config.d.ts.map +1 -0
  131. package/dist/middleware/reflect/config.js +131 -0
  132. package/dist/middleware/reflect/config.js.map +1 -0
  133. package/dist/middleware/reflect/context.d.ts +138 -0
  134. package/dist/middleware/reflect/context.d.ts.map +1 -0
  135. package/dist/middleware/reflect/context.js +619 -0
  136. package/dist/middleware/reflect/context.js.map +1 -0
  137. package/dist/middleware/reflect/cost-breakdown.d.ts +69 -0
  138. package/dist/middleware/reflect/cost-breakdown.d.ts.map +1 -0
  139. package/dist/middleware/reflect/cost-breakdown.js +63 -0
  140. package/dist/middleware/reflect/cost-breakdown.js.map +1 -0
  141. package/dist/middleware/reflect/cost-guard.d.ts +102 -0
  142. package/dist/middleware/reflect/cost-guard.d.ts.map +1 -0
  143. package/dist/middleware/reflect/cost-guard.js +243 -0
  144. package/dist/middleware/reflect/cost-guard.js.map +1 -0
  145. package/dist/middleware/reflect/cost-pricing.d.ts +54 -0
  146. package/dist/middleware/reflect/cost-pricing.d.ts.map +1 -0
  147. package/dist/middleware/reflect/cost-pricing.js +148 -0
  148. package/dist/middleware/reflect/cost-pricing.js.map +1 -0
  149. package/dist/middleware/reflect/cross-group-link.d.ts +61 -0
  150. package/dist/middleware/reflect/cross-group-link.d.ts.map +1 -0
  151. package/dist/middleware/reflect/cross-group-link.js +212 -0
  152. package/dist/middleware/reflect/cross-group-link.js.map +1 -0
  153. package/dist/middleware/reflect/dedup-by-source-and-value.d.ts +70 -0
  154. package/dist/middleware/reflect/dedup-by-source-and-value.d.ts.map +1 -0
  155. package/dist/middleware/reflect/dedup-by-source-and-value.js +0 -0
  156. package/dist/middleware/reflect/dedup-by-source-and-value.js.map +1 -0
  157. package/dist/middleware/reflect/describe-roots.d.ts +58 -0
  158. package/dist/middleware/reflect/describe-roots.d.ts.map +1 -0
  159. package/dist/middleware/reflect/describe-roots.js +266 -0
  160. package/dist/middleware/reflect/describe-roots.js.map +1 -0
  161. package/dist/middleware/reflect/flag-reviewer-startup.d.ts +16 -0
  162. package/dist/middleware/reflect/flag-reviewer-startup.d.ts.map +1 -0
  163. package/dist/middleware/reflect/flag-reviewer-startup.js +107 -0
  164. package/dist/middleware/reflect/flag-reviewer-startup.js.map +1 -0
  165. package/dist/middleware/reflect/flag-reviewer.d.ts +69 -0
  166. package/dist/middleware/reflect/flag-reviewer.d.ts.map +1 -0
  167. package/dist/middleware/reflect/flag-reviewer.js +520 -0
  168. package/dist/middleware/reflect/flag-reviewer.js.map +1 -0
  169. package/dist/middleware/reflect/inline-dedup.d.ts +26 -0
  170. package/dist/middleware/reflect/inline-dedup.d.ts.map +1 -0
  171. package/dist/middleware/reflect/inline-dedup.js +131 -0
  172. package/dist/middleware/reflect/inline-dedup.js.map +1 -0
  173. package/dist/middleware/reflect/justify-decisions.d.ts +37 -0
  174. package/dist/middleware/reflect/justify-decisions.d.ts.map +1 -0
  175. package/dist/middleware/reflect/justify-decisions.js +159 -0
  176. package/dist/middleware/reflect/justify-decisions.js.map +1 -0
  177. package/dist/middleware/reflect/nl-accept.d.ts +35 -0
  178. package/dist/middleware/reflect/nl-accept.d.ts.map +1 -0
  179. package/dist/middleware/reflect/nl-accept.js +167 -0
  180. package/dist/middleware/reflect/nl-accept.js.map +1 -0
  181. package/dist/middleware/reflect/pass0.d.ts +20 -0
  182. package/dist/middleware/reflect/pass0.d.ts.map +1 -0
  183. package/dist/middleware/reflect/pass0.js +423 -0
  184. package/dist/middleware/reflect/pass0.js.map +1 -0
  185. package/dist/middleware/reflect/pass1.d.ts +17 -0
  186. package/dist/middleware/reflect/pass1.d.ts.map +1 -0
  187. package/dist/middleware/reflect/pass1.js +241 -0
  188. package/dist/middleware/reflect/pass1.js.map +1 -0
  189. package/dist/middleware/reflect/pass2-quarantine.d.ts +129 -0
  190. package/dist/middleware/reflect/pass2-quarantine.d.ts.map +1 -0
  191. package/dist/middleware/reflect/pass2-quarantine.js +272 -0
  192. package/dist/middleware/reflect/pass2-quarantine.js.map +1 -0
  193. package/dist/middleware/reflect/pass2-seams.d.ts +205 -0
  194. package/dist/middleware/reflect/pass2-seams.d.ts.map +1 -0
  195. package/dist/middleware/reflect/pass2-seams.js +279 -0
  196. package/dist/middleware/reflect/pass2-seams.js.map +1 -0
  197. package/dist/middleware/reflect/pass2-split-orchestrator.d.ts +37 -0
  198. package/dist/middleware/reflect/pass2-split-orchestrator.d.ts.map +1 -0
  199. package/dist/middleware/reflect/pass2-split-orchestrator.js +531 -0
  200. package/dist/middleware/reflect/pass2-split-orchestrator.js.map +1 -0
  201. package/dist/middleware/reflect/pass2.d.ts +17 -0
  202. package/dist/middleware/reflect/pass2.d.ts.map +1 -0
  203. package/dist/middleware/reflect/pass2.js +324 -0
  204. package/dist/middleware/reflect/pass2.js.map +1 -0
  205. package/dist/middleware/reflect/pass2a.d.ts +141 -0
  206. package/dist/middleware/reflect/pass2a.d.ts.map +1 -0
  207. package/dist/middleware/reflect/pass2a.js +404 -0
  208. package/dist/middleware/reflect/pass2a.js.map +1 -0
  209. package/dist/middleware/reflect/pass2b.d.ts +108 -0
  210. package/dist/middleware/reflect/pass2b.d.ts.map +1 -0
  211. package/dist/middleware/reflect/pass2b.js +480 -0
  212. package/dist/middleware/reflect/pass2b.js.map +1 -0
  213. package/dist/middleware/reflect/pass2c.d.ts +113 -0
  214. package/dist/middleware/reflect/pass2c.d.ts.map +1 -0
  215. package/dist/middleware/reflect/pass2c.js +360 -0
  216. package/dist/middleware/reflect/pass2c.js.map +1 -0
  217. package/dist/middleware/reflect/pass3-batch.d.ts +62 -0
  218. package/dist/middleware/reflect/pass3-batch.d.ts.map +1 -0
  219. package/dist/middleware/reflect/pass3-batch.js +139 -0
  220. package/dist/middleware/reflect/pass3-batch.js.map +1 -0
  221. package/dist/middleware/reflect/pass3.d.ts +23 -0
  222. package/dist/middleware/reflect/pass3.d.ts.map +1 -0
  223. package/dist/middleware/reflect/pass3.js +371 -0
  224. package/dist/middleware/reflect/pass3.js.map +1 -0
  225. package/dist/middleware/reflect/pass4-slice.d.ts +25 -0
  226. package/dist/middleware/reflect/pass4-slice.d.ts.map +1 -0
  227. package/dist/middleware/reflect/pass4-slice.js +315 -0
  228. package/dist/middleware/reflect/pass4-slice.js.map +1 -0
  229. package/dist/middleware/reflect/pass4.d.ts +30 -0
  230. package/dist/middleware/reflect/pass4.d.ts.map +1 -0
  231. package/dist/middleware/reflect/pass4.js +193 -0
  232. package/dist/middleware/reflect/pass4.js.map +1 -0
  233. package/dist/middleware/reflect/pass5.d.ts +22 -0
  234. package/dist/middleware/reflect/pass5.d.ts.map +1 -0
  235. package/dist/middleware/reflect/pass5.js +178 -0
  236. package/dist/middleware/reflect/pass5.js.map +1 -0
  237. package/dist/middleware/reflect/pass_judge.d.ts +44 -0
  238. package/dist/middleware/reflect/pass_judge.d.ts.map +1 -0
  239. package/dist/middleware/reflect/pass_judge.js +263 -0
  240. package/dist/middleware/reflect/pass_judge.js.map +1 -0
  241. package/dist/middleware/reflect/pipeline-flags.d.ts +140 -0
  242. package/dist/middleware/reflect/pipeline-flags.d.ts.map +1 -0
  243. package/dist/middleware/reflect/pipeline-flags.js +314 -0
  244. package/dist/middleware/reflect/pipeline-flags.js.map +1 -0
  245. package/dist/middleware/reflect/pipeline.d.ts +237 -0
  246. package/dist/middleware/reflect/pipeline.d.ts.map +1 -0
  247. package/dist/middleware/reflect/pipeline.js +3114 -0
  248. package/dist/middleware/reflect/pipeline.js.map +1 -0
  249. package/dist/middleware/reflect/promptOverride.d.ts +14 -0
  250. package/dist/middleware/reflect/promptOverride.d.ts.map +1 -0
  251. package/dist/middleware/reflect/promptOverride.js +28 -0
  252. package/dist/middleware/reflect/promptOverride.js.map +1 -0
  253. package/dist/middleware/reflect/provenance-check.d.ts +48 -0
  254. package/dist/middleware/reflect/provenance-check.d.ts.map +1 -0
  255. package/dist/middleware/reflect/provenance-check.js +180 -0
  256. package/dist/middleware/reflect/provenance-check.js.map +1 -0
  257. package/dist/middleware/reflect/provenance-reviewer.d.ts +52 -0
  258. package/dist/middleware/reflect/provenance-reviewer.d.ts.map +1 -0
  259. package/dist/middleware/reflect/provenance-reviewer.js +253 -0
  260. package/dist/middleware/reflect/provenance-reviewer.js.map +1 -0
  261. package/dist/middleware/reflect/prune-collapsed-types.d.ts +11 -0
  262. package/dist/middleware/reflect/prune-collapsed-types.d.ts.map +1 -0
  263. package/dist/middleware/reflect/prune-collapsed-types.js +32 -0
  264. package/dist/middleware/reflect/prune-collapsed-types.js.map +1 -0
  265. package/dist/middleware/reflect/recognize-root.d.ts +75 -0
  266. package/dist/middleware/reflect/recognize-root.d.ts.map +1 -0
  267. package/dist/middleware/reflect/recognize-root.js +204 -0
  268. package/dist/middleware/reflect/recognize-root.js.map +1 -0
  269. package/dist/middleware/reflect/render-agent-flag.d.ts +25 -0
  270. package/dist/middleware/reflect/render-agent-flag.d.ts.map +1 -0
  271. package/dist/middleware/reflect/render-agent-flag.js +39 -0
  272. package/dist/middleware/reflect/render-agent-flag.js.map +1 -0
  273. package/dist/middleware/reflect/retrieve-graph-slice.d.ts +54 -0
  274. package/dist/middleware/reflect/retrieve-graph-slice.d.ts.map +1 -0
  275. package/dist/middleware/reflect/retrieve-graph-slice.js +173 -0
  276. package/dist/middleware/reflect/retrieve-graph-slice.js.map +1 -0
  277. package/dist/middleware/reflect/root-relatedness.d.ts +31 -0
  278. package/dist/middleware/reflect/root-relatedness.d.ts.map +1 -0
  279. package/dist/middleware/reflect/root-relatedness.js +92 -0
  280. package/dist/middleware/reflect/root-relatedness.js.map +1 -0
  281. package/dist/middleware/reflect/schema-heal.d.ts +22 -0
  282. package/dist/middleware/reflect/schema-heal.d.ts.map +1 -0
  283. package/dist/middleware/reflect/schema-heal.js +119 -0
  284. package/dist/middleware/reflect/schema-heal.js.map +1 -0
  285. package/dist/middleware/reflect/schema-validator.d.ts +85 -0
  286. package/dist/middleware/reflect/schema-validator.d.ts.map +1 -0
  287. package/dist/middleware/reflect/schema-validator.js +196 -0
  288. package/dist/middleware/reflect/schema-validator.js.map +1 -0
  289. package/dist/middleware/reflect/stage-audit-graph.d.ts +115 -0
  290. package/dist/middleware/reflect/stage-audit-graph.d.ts.map +1 -0
  291. package/dist/middleware/reflect/stage-audit-graph.js +563 -0
  292. package/dist/middleware/reflect/stage-audit-graph.js.map +1 -0
  293. package/dist/middleware/reflect/stage-d-resolve-graph.d.ts +87 -0
  294. package/dist/middleware/reflect/stage-d-resolve-graph.d.ts.map +1 -0
  295. package/dist/middleware/reflect/stage-d-resolve-graph.js +256 -0
  296. package/dist/middleware/reflect/stage-d-resolve-graph.js.map +1 -0
  297. package/dist/middleware/reflect/synthesizeFromSceneCard.d.ts +15 -0
  298. package/dist/middleware/reflect/synthesizeFromSceneCard.d.ts.map +1 -0
  299. package/dist/middleware/reflect/synthesizeFromSceneCard.js +91 -0
  300. package/dist/middleware/reflect/synthesizeFromSceneCard.js.map +1 -0
  301. package/dist/middleware/reflect/types.d.ts +261 -0
  302. package/dist/middleware/reflect/types.d.ts.map +1 -0
  303. package/dist/middleware/reflect/types.js +3 -0
  304. package/dist/middleware/reflect/types.js.map +1 -0
  305. package/dist/middleware/reflect/v2-integrate.d.ts +120 -0
  306. package/dist/middleware/reflect/v2-integrate.d.ts.map +1 -0
  307. package/dist/middleware/reflect/v2-integrate.js +388 -0
  308. package/dist/middleware/reflect/v2-integrate.js.map +1 -0
  309. package/dist/middleware/reflect/v2-judge.d.ts +44 -0
  310. package/dist/middleware/reflect/v2-judge.d.ts.map +1 -0
  311. package/dist/middleware/reflect/v2-judge.js +191 -0
  312. package/dist/middleware/reflect/v2-judge.js.map +1 -0
  313. package/dist/relation-sets.d.ts +2 -0
  314. package/dist/relation-sets.d.ts.map +1 -0
  315. package/dist/relation-sets.js +35 -0
  316. package/dist/relation-sets.js.map +1 -0
  317. package/dist/routes/__tests__/flags.test.d.ts +2 -0
  318. package/dist/routes/__tests__/flags.test.d.ts.map +1 -0
  319. package/dist/routes/__tests__/flags.test.js +257 -0
  320. package/dist/routes/__tests__/flags.test.js.map +1 -0
  321. package/dist/routes/__tests__/models-catalog.test.d.ts +2 -0
  322. package/dist/routes/__tests__/models-catalog.test.d.ts.map +1 -0
  323. package/dist/routes/__tests__/models-catalog.test.js +130 -0
  324. package/dist/routes/__tests__/models-catalog.test.js.map +1 -0
  325. package/dist/routes/__tests__/reflect-pause-drain.test.d.ts +2 -0
  326. package/dist/routes/__tests__/reflect-pause-drain.test.d.ts.map +1 -0
  327. package/dist/routes/__tests__/reflect-pause-drain.test.js +38 -0
  328. package/dist/routes/__tests__/reflect-pause-drain.test.js.map +1 -0
  329. package/dist/routes/__tests__/spend-pause-drain.test.d.ts +2 -0
  330. package/dist/routes/__tests__/spend-pause-drain.test.d.ts.map +1 -0
  331. package/dist/routes/__tests__/spend-pause-drain.test.js +38 -0
  332. package/dist/routes/__tests__/spend-pause-drain.test.js.map +1 -0
  333. package/dist/routes/admin.d.ts +49 -0
  334. package/dist/routes/admin.d.ts.map +1 -0
  335. package/dist/routes/admin.js +471 -0
  336. package/dist/routes/admin.js.map +1 -0
  337. package/dist/routes/blocks.d.ts +4 -0
  338. package/dist/routes/blocks.d.ts.map +1 -0
  339. package/dist/routes/blocks.js +893 -0
  340. package/dist/routes/blocks.js.map +1 -0
  341. package/dist/routes/chat-proxy.d.ts +5 -0
  342. package/dist/routes/chat-proxy.d.ts.map +1 -0
  343. package/dist/routes/chat-proxy.js +225 -0
  344. package/dist/routes/chat-proxy.js.map +1 -0
  345. package/dist/routes/conversations.d.ts +4 -0
  346. package/dist/routes/conversations.d.ts.map +1 -0
  347. package/dist/routes/conversations.js +139 -0
  348. package/dist/routes/conversations.js.map +1 -0
  349. package/dist/routes/flags.d.ts +4 -0
  350. package/dist/routes/flags.d.ts.map +1 -0
  351. package/dist/routes/flags.js +151 -0
  352. package/dist/routes/flags.js.map +1 -0
  353. package/dist/routes/inject.d.ts +4 -0
  354. package/dist/routes/inject.d.ts.map +1 -0
  355. package/dist/routes/inject.js +183 -0
  356. package/dist/routes/inject.js.map +1 -0
  357. package/dist/routes/mcp-http.d.ts +5 -0
  358. package/dist/routes/mcp-http.d.ts.map +1 -0
  359. package/dist/routes/mcp-http.js +94 -0
  360. package/dist/routes/mcp-http.js.map +1 -0
  361. package/dist/routes/quarantine.d.ts +4 -0
  362. package/dist/routes/quarantine.d.ts.map +1 -0
  363. package/dist/routes/quarantine.js +66 -0
  364. package/dist/routes/quarantine.js.map +1 -0
  365. package/dist/routes/recall.d.ts +5 -0
  366. package/dist/routes/recall.d.ts.map +1 -0
  367. package/dist/routes/recall.js +573 -0
  368. package/dist/routes/recall.js.map +1 -0
  369. package/dist/routes/reflect.d.ts +5 -0
  370. package/dist/routes/reflect.d.ts.map +1 -0
  371. package/dist/routes/reflect.js +231 -0
  372. package/dist/routes/reflect.js.map +1 -0
  373. package/dist/routes/session.d.ts +4 -0
  374. package/dist/routes/session.d.ts.map +1 -0
  375. package/dist/routes/session.js +418 -0
  376. package/dist/routes/session.js.map +1 -0
  377. package/dist/routes/state.d.ts +116 -0
  378. package/dist/routes/state.d.ts.map +1 -0
  379. package/dist/routes/state.js +621 -0
  380. package/dist/routes/state.js.map +1 -0
  381. package/dist/routes/usage.d.ts +3 -0
  382. package/dist/routes/usage.d.ts.map +1 -0
  383. package/dist/routes/usage.js +141 -0
  384. package/dist/routes/usage.js.map +1 -0
  385. package/dist/routes/workspace.d.ts +5 -0
  386. package/dist/routes/workspace.d.ts.map +1 -0
  387. package/dist/routes/workspace.js +435 -0
  388. package/dist/routes/workspace.js.map +1 -0
  389. package/dist/server.d.ts +13 -0
  390. package/dist/server.d.ts.map +1 -0
  391. package/dist/server.js +298 -0
  392. package/dist/server.js.map +1 -0
  393. package/dist/store/__tests__/backup.test.d.ts +2 -0
  394. package/dist/store/__tests__/backup.test.d.ts.map +1 -0
  395. package/dist/store/__tests__/backup.test.js +53 -0
  396. package/dist/store/__tests__/backup.test.js.map +1 -0
  397. package/dist/store/__tests__/quality.test.d.ts +2 -0
  398. package/dist/store/__tests__/quality.test.d.ts.map +1 -0
  399. package/dist/store/__tests__/quality.test.js +75 -0
  400. package/dist/store/__tests__/quality.test.js.map +1 -0
  401. package/dist/store/backup.d.ts +14 -0
  402. package/dist/store/backup.d.ts.map +1 -0
  403. package/dist/store/backup.js +95 -0
  404. package/dist/store/backup.js.map +1 -0
  405. package/dist/store/database.d.ts +407 -0
  406. package/dist/store/database.d.ts.map +1 -0
  407. package/dist/store/database.js +2004 -0
  408. package/dist/store/database.js.map +1 -0
  409. package/dist/store/quality.d.ts +25 -0
  410. package/dist/store/quality.d.ts.map +1 -0
  411. package/dist/store/quality.js +48 -0
  412. package/dist/store/quality.js.map +1 -0
  413. package/dist/tools/__tests__/assemble-block-chains.test.d.ts +2 -0
  414. package/dist/tools/__tests__/assemble-block-chains.test.d.ts.map +1 -0
  415. package/dist/tools/__tests__/assemble-block-chains.test.js +118 -0
  416. package/dist/tools/__tests__/assemble-block-chains.test.js.map +1 -0
  417. package/dist/tools/__tests__/filter-roots-by-concepts.test.d.ts +2 -0
  418. package/dist/tools/__tests__/filter-roots-by-concepts.test.d.ts.map +1 -0
  419. package/dist/tools/__tests__/filter-roots-by-concepts.test.js +68 -0
  420. package/dist/tools/__tests__/filter-roots-by-concepts.test.js.map +1 -0
  421. package/dist/tools/__tests__/flag-surface.test.d.ts +2 -0
  422. package/dist/tools/__tests__/flag-surface.test.d.ts.map +1 -0
  423. package/dist/tools/__tests__/flag-surface.test.js +130 -0
  424. package/dist/tools/__tests__/flag-surface.test.js.map +1 -0
  425. package/dist/tools/core.d.ts +5 -0
  426. package/dist/tools/core.d.ts.map +1 -0
  427. package/dist/tools/core.js +962 -0
  428. package/dist/tools/core.js.map +1 -0
  429. package/dist/tools/derive.d.ts +5 -0
  430. package/dist/tools/derive.d.ts.map +1 -0
  431. package/dist/tools/derive.js +182 -0
  432. package/dist/tools/derive.js.map +1 -0
  433. package/dist/tools/flag-surface.d.ts +26 -0
  434. package/dist/tools/flag-surface.d.ts.map +1 -0
  435. package/dist/tools/flag-surface.js +59 -0
  436. package/dist/tools/flag-surface.js.map +1 -0
  437. package/dist/tools/helpers.d.ts +99 -0
  438. package/dist/tools/helpers.d.ts.map +1 -0
  439. package/dist/tools/helpers.js +243 -0
  440. package/dist/tools/helpers.js.map +1 -0
  441. package/dist/tools/projects.d.ts +5 -0
  442. package/dist/tools/projects.d.ts.map +1 -0
  443. package/dist/tools/projects.js +175 -0
  444. package/dist/tools/projects.js.map +1 -0
  445. package/dist/tools/system.d.ts +5 -0
  446. package/dist/tools/system.d.ts.map +1 -0
  447. package/dist/tools/system.js +1361 -0
  448. package/dist/tools/system.js.map +1 -0
  449. package/dist/tools/tasks.d.ts +5 -0
  450. package/dist/tools/tasks.d.ts.map +1 -0
  451. package/dist/tools/tasks.js +289 -0
  452. package/dist/tools/tasks.js.map +1 -0
  453. package/package.json +69 -0
  454. package/scripts/nodedex-entry.mjs +396 -0
  455. package/tui-dist/App.js +185 -0
  456. package/tui-dist/api.js +197 -0
  457. package/tui-dist/cli.js +53 -0
  458. package/tui-dist/components.js +63 -0
  459. package/tui-dist/config.js +242 -0
  460. package/tui-dist/connect-snippets.js +98 -0
  461. package/tui-dist/feed.js +51 -0
  462. package/tui-dist/health.js +465 -0
  463. package/tui-dist/hooks.js +23 -0
  464. package/tui-dist/memory.js +220 -0
  465. package/tui-dist/onboarding.js +498 -0
  466. package/tui-dist/review.js +193 -0
  467. package/tui-dist/servers.js +556 -0
  468. package/tui-dist/smoke.js +15 -0
  469. package/tui-dist/theme.js +106 -0
@@ -0,0 +1,621 @@
1
+ // routes/state.ts — shared in-memory state + queue processor.
2
+ // All route modules import from here rather than from api-server.ts.
3
+ // Reference: api-server.v1.ts (lines 13-325)
4
+ import { v4 as uuidv4 } from "uuid";
5
+ import { runAutoReflect, reflectTokenStats } from "../middleware/auto-reflect.js";
6
+ import { runComprehendFrontHalf } from "../middleware/reflect/v2-integrate.js";
7
+ import { getLLMProvider } from "../engine/providers/index.js";
8
+ import { evaluateBudgetLive, writeSpendPauseFile, clearSpendPauseFile, creditExhausted, creditRecovered } from "../middleware/reflect/cost-guard.js";
9
+ import { isInsufficientCreditError } from "../engine/providers/failure-policy.js";
10
+ import { resolveRoutedFlagsFromText } from "../middleware/reflect/nl-accept.js";
11
+ import { arcAutoTurns } from "../middleware/reflect/config.js";
12
+ export function resolveStateLabel(agentId) {
13
+ return agentId ? `agent_session_state_${agentId}` : "agent_session_state";
14
+ }
15
+ export const reflectQueue = [];
16
+ export let reflectProcessing = false;
17
+ export let reflectFlushGeneration = 0; // incremented on every flush; each sleeping job checks its own snapshot
18
+ export let reflectPaused = false;
19
+ // SPEND pause — distinct from reflectPaused. reflectPaused stops CAPTURE (drops turns at
20
+ // /trigger) for benchmark/manual isolation; spendPaused stops only SPENDING (halts the
21
+ // drain) while CAPTURE KEEPS QUEUING, so a credit outage loses no turns. Set by the
22
+ // cost-breaker + the credit-out handler; cleared automatically when credit tops back up.
23
+ export let spendPaused = false;
24
+ export function setReflectProcessing(v) { reflectProcessing = v; }
25
+ export function setReflectFlushGeneration(v) { reflectFlushGeneration = v; }
26
+ export function setReflectPaused(v) { reflectPaused = v; }
27
+ export function setSpendPaused(v) { spendPaused = v; }
28
+ // Enqueue ONE captured turn for reflection — the SINGLE in-process path, shared by the
29
+ // HTTP trigger route (where hooks / the tee adapter POST in) and the chat proxy (which
30
+ // enqueues directly, no self-HTTP-call). Mechanics only — the CALLER owns pause policy
31
+ // (the proxy honors reflectPaused; the trigger route additionally bypasses it for
32
+ // benchmark runs) and the <50-char gate. Never throws: capture must never break its caller.
33
+ export function enqueueReflectTurn(db, embeddings, turn) {
34
+ const jobId = `rj_${uuidv4().slice(0, 12)}`;
35
+ try {
36
+ if (turn.agentId)
37
+ db.registerAgent(turn.agentId);
38
+ try {
39
+ db.insertReflectJob(jobId, turn.agentId || null, JSON.stringify({
40
+ agentResponse: turn.agentResponse,
41
+ userMessage: turn.userMessage || "",
42
+ loadedBlockIds: turn.loadedBlockIds || [],
43
+ }));
44
+ }
45
+ catch { /* non-critical — the DB row is for status sync only */ }
46
+ reflectQueue.push({
47
+ agentResponse: turn.agentResponse,
48
+ agentThinking: turn.agentThinking || "",
49
+ userMessage: turn.userMessage || "",
50
+ loadedBlockIds: turn.loadedBlockIds || [],
51
+ agentId: turn.agentId,
52
+ turnNumber: turn.turnNumber,
53
+ turnName: turn.turnName,
54
+ dbId: jobId,
55
+ });
56
+ processReflectQueue(db, embeddings || undefined).catch((e) => console.error("[reflect] worker error:", e));
57
+ }
58
+ catch (e) {
59
+ console.error("[reflect] enqueue error:", e);
60
+ }
61
+ return { jobId, queueDepth: reflectQueue.length };
62
+ }
63
+ export const sessionEvents = [];
64
+ export let sessionEventCounter = 0;
65
+ export const SESSION_EVENT_MAX = 500; // cap at 500 events to avoid unbounded growth
66
+ export function incrementSessionEventCounter() { return ++sessionEventCounter; }
67
+ export const alertStore = [];
68
+ let alertCounter = 0;
69
+ const ALERT_STORE_MAX = 200;
70
+ const ALERT_COOLDOWN_MS = 5 * 60 * 1000; // 5-minute cooldown per condition
71
+ export const alertCooldowns = new Map(); // condition → last fired ms
72
+ /** Reset all session monitoring state (session events, alerts, counters) */
73
+ export function resetMonitoring() {
74
+ sessionEvents.length = 0;
75
+ sessionEventCounter = 0;
76
+ alertStore.length = 0;
77
+ alertCounter = 0;
78
+ alertCooldowns.clear();
79
+ }
80
+ export function fireAlert(condition, severity, message, context) {
81
+ const now = Date.now();
82
+ if ((alertCooldowns.get(condition) ?? 0) + ALERT_COOLDOWN_MS > now)
83
+ return;
84
+ alertCooldowns.set(condition, now);
85
+ const record = { id: ++alertCounter, timestamp: new Date().toISOString(), condition, severity, message, context };
86
+ if (alertStore.length < ALERT_STORE_MAX)
87
+ alertStore.push(record);
88
+ console.warn(`[ALERT:${severity.toUpperCase()}] ${condition}: ${message}`);
89
+ }
90
+ export function evaluateAlertsAfterReflect(evt) {
91
+ // Rate limit hit
92
+ if (evt.rate_limited) {
93
+ fireAlert("rate_limit", "warn", `Pass ${evt.rate_limit_pass ?? "?"} rate limited`, { pass: evt.rate_limit_pass });
94
+ }
95
+ // Processing lag
96
+ if (evt.processing_ms > 120_000) {
97
+ fireAlert("processing_lag_critical", "critical", `Reflect cycle took ${Math.round(evt.processing_ms / 1000)}s (threshold: 120s)`, { processing_ms: evt.processing_ms });
98
+ }
99
+ else if (evt.processing_ms > 60_000) {
100
+ fireAlert("processing_lag_warn", "warn", `Reflect cycle took ${Math.round(evt.processing_ms / 1000)}s (threshold: 60s)`, { processing_ms: evt.processing_ms });
101
+ }
102
+ // Queue backup
103
+ if (reflectQueue.length > 10) {
104
+ fireAlert("queue_backup_critical", "critical", `Queue depth ${reflectQueue.length} (threshold: 10)`, { queue_depth: reflectQueue.length });
105
+ }
106
+ else if (reflectQueue.length > 3) {
107
+ fireAlert("queue_backup_warn", "warn", `Queue depth ${reflectQueue.length} (threshold: 3)`, { queue_depth: reflectQueue.length });
108
+ }
109
+ // Quality drop — last 5 blocks avg < 3
110
+ const allCreatedSoFar = sessionEvents
111
+ .filter((e) => e.type === "reflect")
112
+ .flatMap(e => e.blocks_created);
113
+ const last5 = allCreatedSoFar.slice(-5);
114
+ if (last5.length >= 5) {
115
+ const avgQuality = last5.reduce((s, b) => s + b.quality, 0) / last5.length;
116
+ if (avgQuality < 3) {
117
+ fireAlert("quality_drop", "warn", `Avg quality of last 5 blocks: ${avgQuality.toFixed(1)} (threshold: 3.0)`, { avg_quality: avgQuality, blocks: last5.map(b => b.label) });
118
+ }
119
+ }
120
+ // Block creation spike — this cycle > 2× session avg, min 10 blocks
121
+ const reflectEvtsSoFar = sessionEvents.filter((e) => e.type === "reflect");
122
+ if (reflectEvtsSoFar.length >= 3) {
123
+ const prevAvg = reflectEvtsSoFar.slice(0, -1).reduce((s, e) => s + e.blocks_created.length, 0) / (reflectEvtsSoFar.length - 1);
124
+ const thisCount = evt.blocks_created.length;
125
+ if (prevAvg > 0 && thisCount > prevAvg * 2 && thisCount >= 10) {
126
+ fireAlert("block_creation_spike", "warn", `${thisCount} blocks this cycle (2× avg of ${prevAvg.toFixed(1)})`, { this_cycle: thisCount, session_avg: prevAvg });
127
+ }
128
+ }
129
+ // Block drought — 0 blocks for 3 consecutive cycles despite input tokens
130
+ const recentEvts = reflectEvtsSoFar.slice(-3);
131
+ if (recentEvts.length === 3 && recentEvts.every(e => e.blocks_created.length === 0 && e.tokens.pass1_input > 0)) {
132
+ fireAlert("block_drought", "warn", "0 blocks saved in last 3 reflect cycles despite input being processed", { cycles_checked: 3 });
133
+ }
134
+ }
135
+ export function evaluateAlertsAfterRecall(evt) {
136
+ // Recall pollution threshold scales with project count:
137
+ // Single-project workspace: 25% (cross-project recall is unexpected)
138
+ // Multi-project workspace: 60% (cross-project recall is expected and useful)
139
+ if (evt.total_injected >= 8) {
140
+ const pct = (evt.cross_project_count / evt.total_injected) * 100;
141
+ const threshold = evt.project_count <= 1 ? 25 : 60;
142
+ if (pct > threshold) {
143
+ fireAlert("recall_pollution", "warn", `${pct.toFixed(0)}% of recalled blocks are cross-project (threshold: ${threshold}%)`, { pollution_pct: pct, cross_project: evt.cross_project_count, total: evt.total_injected, query: evt.query, project_count: evt.project_count });
144
+ }
145
+ }
146
+ }
147
+ // ─── Mining candidates (removed — never wired, zero API calls, zero value at 42/42)
148
+ // To restore: add MiningCandidate interface + miningStore here, POST/GET/PATCH
149
+ // /api/mining-candidates in workspace.ts, inject in session.ts GET /api/session,
150
+ // inject in context hook section "3. Mining candidates".
151
+ // ─── Credit-out: pause spending, REQUEUE the turn (never drop) ───────────────────
152
+ // The REACTIVE backstop. When an extraction fails, decide whether it failed because the
153
+ // account is out of credit; if so, pause SPENDING and requeue the turn UNCHANGED so it
154
+ // drains after a top-up. Detection: the DEFINITIVE 402 signal first (isInsufficientCredit
155
+ // on the failure / reason — no network), then a FORCE-REFRESHED balance probe as the net.
156
+ //
157
+ // The requeue is the SAME mechanism as the rate-limit path (unshift + retry_wait row) with
158
+ // ONE deliberate difference: it does NOT increment retryAttempts. A credit outage is a
159
+ // global condition, not this turn's fault — counting it toward the per-turn drop cap would
160
+ // wrongly discard turns during an outage. Pairing it with the spend-pause (instead of a
161
+ // backoff-retry that would just re-hit the 402) is what makes capture-keeps-queuing work.
162
+ async function pauseAndRequeueIfCreditOut(db, job, errOrReason) {
163
+ let remaining = null;
164
+ let out = isInsufficientCreditError(errOrReason);
165
+ if (!out) {
166
+ const c = await creditExhausted();
167
+ out = c.out;
168
+ remaining = c.remaining;
169
+ }
170
+ if (!out)
171
+ return false;
172
+ setSpendPaused(true);
173
+ const reason = `credit exhausted${remaining != null ? ` — remaining $${remaining.toFixed(2)}` : ""} (auto-resume on top-up)`;
174
+ writeSpendPauseFile(reason);
175
+ // Surface it in the monitoring feed (the TUI error terminal reads alertStore) — a
176
+ // timestamped record alongside the standing spend_paused flag. 5-min cooldown built in.
177
+ fireAlert("credit_exhausted", "critical", `Credit exhausted — extraction paused, ${reflectQueue.length + 1} turn(s) queued, auto-resume on top-up`, { remaining });
178
+ // Requeue UNCHANGED — same unshift + retry_wait mechanism as the rate-limit path, but
179
+ // NO attempt increment (a global outage, not this turn's fault → never drop it).
180
+ if (job.dbId)
181
+ db.updateReflectJob(job.dbId, { status: 'retry_wait', error: 'paused: credit exhausted' });
182
+ reflectQueue.unshift(job);
183
+ console.warn(`[reflect-queue] CREDIT EXHAUSTED — ${reason}. Spending paused, ${reflectQueue.length} job(s) preserved + still queuing. Auto-resumes when credit tops up.`);
184
+ return true;
185
+ }
186
+ // ─── Auto-resume: drain again once credit recovers ───────────────────────────────
187
+ // processReflectQueue BREAKS on spendPaused BEFORE the budget re-check, so a paused queue
188
+ // never re-evaluates itself — resume needs a SEPARATE timer. It only ever acts on an active
189
+ // spendPaused (never the capture reflect-pause), force-refreshes the balance, and on recovery
190
+ // clears the spend-pause (flag + its OWN file — never the user's/dogfood reflect-pause) and
191
+ // kicks the drain. Idempotent; unref'd so it never holds the process open (tests/CI safe).
192
+ /**
193
+ * One auto-resume check: if spend-paused AND credit has POSITIVELY recovered, lift the
194
+ * pause + drain. Returns true iff it resumed. Exported so the behavior is unit/live-testable
195
+ * without waiting on the 60s timer. Conservative — `creditRecovered` only confirms recovery
196
+ * on a readable balance above the floor, so an indeterminate balance keeps the pause.
197
+ */
198
+ export async function creditAutoResumeTick(db, embeddings) {
199
+ if (!spendPaused)
200
+ return false;
201
+ let rec;
202
+ try {
203
+ rec = await creditRecovered();
204
+ }
205
+ catch {
206
+ return false;
207
+ }
208
+ if (!rec.recovered)
209
+ return false; // still out / unconfirmed — stay paused
210
+ setSpendPaused(false);
211
+ clearSpendPauseFile();
212
+ console.log(`[cost-breaker] credit recovered${rec.remaining != null ? ` (remaining $${rec.remaining.toFixed(2)})` : ""} — SPENDING RESUMED, draining ${reflectQueue.length} queued job(s)`);
213
+ processReflectQueue(db, embeddings).catch(e => console.error("[cost-breaker] resume drain error:", e));
214
+ // Arc turns aren't in the per-turn reflectQueue — they live as pass01_done conversation_turns,
215
+ // so the drain above can't reach an arc that credit-failed mid-extraction. Re-fire arc
216
+ // extraction for each agent whose arc failed (last_extract_error marker), re-using the SAME
217
+ // runArcExtraction over its full pending range → it re-consolidates ALL pass01_done turns (full
218
+ // arc context, not a fragment) and commits on success, or fail-cleans again if still out.
219
+ try {
220
+ const stuck = db.listAgentsWithFailedArc();
221
+ if (stuck.length) {
222
+ console.log(`[cost-breaker] re-extracting ${stuck.length} arc(s) that the spend-stop paused`);
223
+ void import("../middleware/reflect/arc-pipeline.js").then(({ runArcExtraction }) => {
224
+ for (const agentId of stuck) {
225
+ void runArcExtraction(db, { agent_id: agentId, trigger_source: "auto" })
226
+ .catch((e) => console.warn(`[cost-breaker] arc resume re-extract failed for ${agentId}: ${e?.message ?? e}`));
227
+ }
228
+ }).catch((e) => console.warn(`[cost-breaker] arc resume import failed: ${e?.message ?? e}`));
229
+ }
230
+ }
231
+ catch (e) {
232
+ console.warn(`[cost-breaker] arc resume check failed: ${e?.message}`);
233
+ }
234
+ return true;
235
+ }
236
+ let autoResumeTimer = null;
237
+ export function startCreditAutoResume(db, embeddings, intervalMs = 60_000) {
238
+ if (autoResumeTimer)
239
+ return;
240
+ autoResumeTimer = setInterval(() => { creditAutoResumeTick(db, embeddings).catch(() => { }); }, intervalMs);
241
+ autoResumeTimer.unref?.();
242
+ }
243
+ export function stopCreditAutoResume() {
244
+ if (autoResumeTimer) {
245
+ clearInterval(autoResumeTimer);
246
+ autoResumeTimer = null;
247
+ }
248
+ }
249
+ // ─── Reflect queue processor ──────────────────────────────────────────────────
250
+ export async function processReflectQueue(db, embeddings) {
251
+ if (reflectProcessing)
252
+ return;
253
+ reflectProcessing = true;
254
+ try {
255
+ while (reflectQueue.length > 0) {
256
+ // Pause halts the drain. "Pause" means "stop spending" — and a paused
257
+ // server must never silently resume a recovered queue. Jobs stay queued
258
+ // (and persisted in DB); they drain on the next trigger after resume, or
259
+ // on a restart that boots unpaused. (Before this guard, pause only gated
260
+ // NEW enqueues at /trigger while the existing queue kept draining — the
261
+ // surprising behavior that burned credit on 2026-06-01.)
262
+ if (reflectPaused) {
263
+ console.log(`[reflect-queue] paused — halting drain (${reflectQueue.length} job(s) remain queued)`);
264
+ break;
265
+ }
266
+ // SPEND pause — halts the drain (stop spending) but capture keeps queuing at
267
+ // /trigger, so a credit outage never loses turns. Auto-resumes on top-up.
268
+ if (spendPaused) {
269
+ console.log(`[reflect-queue] spend paused (credit/budget) — halting drain; capture still queuing (${reflectQueue.length} job(s) preserved, auto-resume on top-up)`);
270
+ break;
271
+ }
272
+ // Cost breaker (production gap 2): trip BEFORE pulling a job, reusing the
273
+ // SPEND-pause lever. No-op + no I/O when no budget is configured (the default).
274
+ // Tripping persists the spend-pause file so a restart can't bypass the budget;
275
+ // the queue is preserved (fail-safe) and CAPTURE KEEPS QUEUING. The auto-resume
276
+ // timer drains it when the balance recovers. The designed protections (floor
277
+ // breach, balance-unknown) return a clean tripped verdict; an unexpected THROW
278
+ // here is a breaker BUG, and a guard must never break what it guards — so we fail
279
+ // OPEN on a throw (proceed), never silently halt reflection because the breaker
280
+ // itself errored.
281
+ let budget = null;
282
+ try {
283
+ budget = await evaluateBudgetLive();
284
+ }
285
+ catch (e) {
286
+ console.error("[cost-breaker] evaluation threw — proceeding WITHOUT tripping (breaker bug, not a budget breach):", e);
287
+ }
288
+ if (budget?.tripped) {
289
+ setSpendPaused(true);
290
+ writeSpendPauseFile(budget.reason ?? "cost breaker tripped");
291
+ console.warn(`[cost-breaker] TRIPPED — ${budget.reason}. SPENDING PAUSED (${reflectQueue.length} job(s) preserved + queued; capture continues). Auto-resumes when the balance recovers.`);
292
+ break;
293
+ }
294
+ const job = reflectQueue.shift();
295
+ // Honour retry delay — put back and wait if not ready yet
296
+ if (job.retryAfter && Date.now() < job.retryAfter) {
297
+ const wait = job.retryAfter - Date.now();
298
+ console.log(`[reflect-queue] rate-limit retry in ${Math.round(wait / 1000)}s — pausing queue`);
299
+ reflectQueue.unshift(job);
300
+ // Snapshot generation at sleep entry — flush increments it, so any change means abandon
301
+ const myGeneration = reflectFlushGeneration;
302
+ const sleepUntil = Date.now() + Math.min(wait, 10000);
303
+ while (Date.now() < sleepUntil) {
304
+ await new Promise(r => setTimeout(r, 1000));
305
+ if (reflectFlushGeneration !== myGeneration)
306
+ break;
307
+ }
308
+ if (reflectFlushGeneration !== myGeneration) {
309
+ reflectQueue.length = 0;
310
+ console.log("[reflect-queue] flush acknowledged — sleeping job abandoned");
311
+ break;
312
+ }
313
+ continue;
314
+ }
315
+ // Mark job as actively processing in DB
316
+ if (job.dbId)
317
+ db.updateReflectJob(job.dbId, { status: 'processing' });
318
+ const recalledBlocks = job.loadedBlockIds
319
+ .map(id => db.getBlock(id))
320
+ .filter(Boolean)
321
+ .map((b) => ({ id: b.id, label: b.label, essence: b.essence || "", type: b.type }));
322
+ // FLAG-RESOLUTION (b): if this turn answered a question the system routed to the
323
+ // agent, apply it. Fire-and-forget + independent of extraction. Self-gated
324
+ // (NODEDEX_FLAG_NL_ACCEPT off → instant no-op) and work-gated (no LLM call unless
325
+ // a flag is actually pending), so this is $0 in the common case.
326
+ resolveRoutedFlagsFromText(db, getLLMProvider(), job.agentResponse)
327
+ .then(r => { if (r.addressed)
328
+ console.log(`[nl-accept] addressed=${r.addressed} merged=${r.merged} left=${r.left} split=${r.split} skipped=${r.skipped_low_conf} errors=${r.errors}`); })
329
+ .catch(e => console.warn(`[nl-accept] ${e?.message ?? e}`));
330
+ const jobStart = Date.now();
331
+ const statsBefore = {
332
+ p1in: reflectTokenStats.pass1.input,
333
+ p2in: reflectTokenStats.pass2.input, p2th: reflectTokenStats.pass2.thinking,
334
+ p3in: reflectTokenStats.pass3.input, p3th: reflectTokenStats.pass3.thinking,
335
+ };
336
+ try {
337
+ // Carry forward every completed pass when resuming, so Pass 0/1/2 reasoning
338
+ // ends up in the final turn log regardless of which pass triggered the retry.
339
+ let checkpoint = job.precomputedPass3PendingBlockIds
340
+ ? {
341
+ resumeFrom: 'pass4',
342
+ pass0: job.precomputedPass0,
343
+ pass1Items: job.precomputedPass1?.items,
344
+ pass2Classified: job.precomputedPass2?.classified ?? [],
345
+ p3PendingBlockIds: job.precomputedPass3PendingBlockIds,
346
+ }
347
+ : job.precomputedPass2
348
+ ? {
349
+ resumeFrom: 'pass3',
350
+ pass0: job.precomputedPass0,
351
+ pass1Items: job.precomputedPass1?.items,
352
+ pass2Classified: job.precomputedPass2.classified,
353
+ }
354
+ : job.precomputedPass1
355
+ ? {
356
+ resumeFrom: 'pass2',
357
+ pass0: job.precomputedPass0,
358
+ pass1Items: job.precomputedPass1.items,
359
+ }
360
+ : undefined;
361
+ // ── PIPELINE v2 (per-turn) — gated on its OWN flag, NOT pipelineV2Enabled ─────
362
+ // v2 was arc/batch-only; this brings it to the LIVE per-turn path so a live agent
363
+ // gets v2's worth-gate SELECTOR + (with NODEDEX_V2_MERGE_DUPS) cross-group dedup.
364
+ // SEPARATE flag NODEDEX_V2_PER_TURN so it does NOT auto-fire on the arc-mode
365
+ // NODEDEX_PIPELINE_V2 flag a deployment may set for batch. Routes through
366
+ // runComprehendFrontHalf with holistic:true — a single turn fits ONE COMPREHEND
367
+ // call, so it does NOT use per-group SEGMENT (which exists only as the big-arc
368
+ // truncate fix and, on a single turn's overlapping threads, blind-parallel
369
+ // re-extracts shared claims → cross-group dups). Holistic prevents the dup at the
370
+ // source; the MERGE_DUPS pass then stays a harmless no-op here (arc-mode net).
371
+ // Transcript = USER/AGENT only (matches the arc path; thinking is captured to
372
+ // conversation_turns but not fed to COMPREHEND — it amplified over-seg in testing).
373
+ // Guards: !checkpoint (don't override a retry) · !job.turnNumber (arc mode keeps
374
+ // its Pass 0-1 defer, so this NEVER runs in arc mode). V2-ONLY (2026-06-20): a v2
375
+ // failure NO LONGER degrades to v1 — it REQUEUES (retry v2 with backoff) up to a
376
+ // cap, then fail-cleans (turn skipped, never v1, no silent corruption). This matches
377
+ // the arc path's v2-only fail-clean policy (arc-pipeline.ts §"V2-ONLY failure
378
+ // policy"). ⚠ OLD v1 PIPELINE — DO NOT TURN ON: the NODEDEX_V2_PER_TURN=0
379
+ // off-switch was REMOVED, so v2 per-turn is unconditional and the v1 path below
380
+ // (runAutoReflect with no checkpoint + no turnNumber) is intentionally unreachable.
381
+ let v2PerTurnAttempted = false;
382
+ let v2PerTurnReason = null;
383
+ if (!checkpoint && !job.turnNumber && job.agentResponse) {
384
+ v2PerTurnAttempted = true;
385
+ try {
386
+ const v2Transcript = `USER: ${job.userMessage ?? ""}\nAGENT: ${job.agentResponse}`;
387
+ // holistic by default (1 turn fits one call, no cross-group dup). Set
388
+ // NODEDEX_V2_PER_TURN_PERGROUP=1 to instead run per-group + merge on the
389
+ // per-turn path — under evaluation: per-group runs the cross-group LINKER
390
+ // (no-op on holistic's single group), which may wire based_on/supports that
391
+ // holistic leaves as islands. The wiring-vs-dup A/B decides the default.
392
+ const useHolistic = process.env.NODEDEX_V2_PER_TURN_PERGROUP !== "1";
393
+ const front = await runComprehendFrontHalf(db, getLLMProvider(), v2Transcript, { holistic: useHolistic });
394
+ if (front.checkpoint) {
395
+ checkpoint = front.checkpoint;
396
+ console.log(`[reflect-per-turn] PIPELINE v2: ${front.groups} group(s), ${front.blocks} block(s), ${front.merged ?? 0} merged`);
397
+ }
398
+ else {
399
+ v2PerTurnReason = front.reason ?? "unknown"; // "empty" (legit: nothing to save) | "comprehend_failed" | "seam1_invalid"
400
+ }
401
+ }
402
+ catch (e) {
403
+ v2PerTurnReason = `threw: ${e?.message ?? e}`;
404
+ }
405
+ }
406
+ // V2-ONLY per-turn outcome — never fall through to v1.
407
+ // • checkpoint set → success → fall through to runAutoReflect (v2 back-half).
408
+ // • reason "empty" → legitimately no residue → clean 0-block, done (NOT a failure).
409
+ // • any other failure → REQUEUE (retry v2) up to the cap, then fail-clean.
410
+ if (v2PerTurnAttempted && !checkpoint) {
411
+ if (v2PerTurnReason === "empty") {
412
+ console.log(`[reflect-per-turn] v2: nothing worth saving (empty) — done, 0 blocks`);
413
+ if (job.dbId)
414
+ db.updateReflectJob(job.dbId, { status: 'done' });
415
+ }
416
+ else if (await pauseAndRequeueIfCreditOut(db, job, v2PerTurnReason)) {
417
+ // Out of credit — paused + requeued UNCHANGED (no retry-cap burn). The loop
418
+ // top sees spendPaused and halts the drain; capture keeps queuing.
419
+ continue;
420
+ }
421
+ else {
422
+ const attempts = (job.retryAttempts ?? 0) + 1;
423
+ const maxRetries = Number(process.env.NODEDEX_V2_PER_TURN_MAX_RETRIES) || 3;
424
+ if (attempts <= maxRetries) {
425
+ const base = Math.min(15_000 * Math.pow(2, attempts - 1), 60_000);
426
+ const retryDelay = Math.round(base + Math.random() * base * 0.5);
427
+ console.warn(`[reflect-per-turn] v2 failed (${v2PerTurnReason}) — requeue ${attempts}/${maxRetries} in ${Math.round(retryDelay / 1000)}s (v2-only, NO v1)`);
428
+ const retryJob = { ...job, retryAfter: Date.now() + retryDelay, retryAttempts: attempts };
429
+ if (job.dbId)
430
+ db.updateReflectJob(job.dbId, { status: 'retry_wait', retry_after: retryJob.retryAfter, retry_attempts: attempts });
431
+ reflectQueue.unshift(retryJob);
432
+ }
433
+ else {
434
+ console.warn(`[reflect-per-turn] v2 failed after ${maxRetries} retries (${v2PerTurnReason}) — fail-clean, turn skipped (v2-only, NO v1)`);
435
+ if (job.dbId)
436
+ db.updateReflectJob(job.dbId, { status: 'dead', error: `v2 per-turn failed: ${v2PerTurnReason}`.slice(0, 200) });
437
+ }
438
+ }
439
+ continue; // skip runAutoReflect — the per-turn v2 path never falls to v1
440
+ }
441
+ const r = await runAutoReflect(db, job.agentResponse, job.loadedBlockIds, job.userMessage, job.agentThinking || undefined, embeddings || undefined, recalledBlocks, job.agentId, checkpoint,
442
+ // ── DEBT 5 Phase 2: thread turn identity into pipeline ──
443
+ // When NODEDEX_ARC_EXTRACTION=1 + agentId present + turnNumber present,
444
+ // pipeline persists Pass 0-1 to conversation_turns and defers Pass 2-5
445
+ // to arc-extract trigger. ReflectJob has carried turnNumber/turnName
446
+ // since the inventory pass; this completes the wire.
447
+ job.turnNumber, job.turnName);
448
+ if (r.saved > 0 || r.updated > 0)
449
+ console.log(`[reflect-queue] saved=${r.saved} updated=${r.updated} labels=${r.saved_labels.join(",")}`);
450
+ if (r.uncertain_count > 0)
451
+ console.log(`[reflect-queue] uncertain_refs=${r.uncertain_count} — stored for next turn`);
452
+ // ── Every-N arc auto-extract (safety net) ────────────────────────────────
453
+ // In arc mode this turn was just CAPTURED (pass01_done) but not yet extracted. If
454
+ // the agent doesn't fire workspace_extract_arc itself at a task boundary, auto-commit
455
+ // once N turns have accumulated (NODEDEX_ARC_AUTO_TURNS; 0/unset = off → inert). The
456
+ // guard `job.turnNumber !== undefined` means this NEVER runs in per-turn mode. Fire-
457
+ // and-forget so it never blocks the queue; runArcExtraction's own in-flight + rate
458
+ // guards stop double-firing. Dynamic import avoids a static arc-pipeline↔state cycle.
459
+ const autoN = arcAutoTurns();
460
+ if (autoN > 0 && job.agentId && job.turnNumber !== undefined) {
461
+ try {
462
+ const pending = db.getExtractionStatus(job.agentId).pending?.turns ?? 0;
463
+ if (pending >= autoN) {
464
+ const agentId = job.agentId;
465
+ void import("../middleware/reflect/arc-pipeline.js")
466
+ .then(({ runArcExtraction }) => runArcExtraction(db, { agent_id: agentId, trigger_source: "auto" }))
467
+ .then((res) => { if (res?.status === "extracted")
468
+ console.log(`[arc-auto] committed ${res.turns_consumed} turn(s) for ${agentId} (pending>=${autoN})`); })
469
+ .catch((e) => console.warn(`[arc-auto] ${e?.message ?? e}`));
470
+ }
471
+ }
472
+ catch (e) {
473
+ console.warn(`[arc-auto] check failed: ${e?.message}`);
474
+ }
475
+ }
476
+ // ── Record session event ──────────────────────────────────────────────
477
+ const processing_ms = Date.now() - jobStart;
478
+ const rateLimited = !!r.checkpoint;
479
+ const rateLimitPass = r.checkpoint?.resumeFrom === 'pass1' ? 1 : r.checkpoint?.resumeFrom === 'pass2' ? 2 : r.checkpoint?.resumeFrom === 'pass3' ? 3 : undefined;
480
+ const p1in = reflectTokenStats.pass1.input - statsBefore.p1in;
481
+ const p2in = reflectTokenStats.pass2.input - statsBefore.p2in;
482
+ const p2th = reflectTokenStats.pass2.thinking - statsBefore.p2th;
483
+ const p3in = reflectTokenStats.pass3.input - statsBefore.p3in;
484
+ const p3th = reflectTokenStats.pass3.thinking - statsBefore.p3th;
485
+ const billedEquiv = p1in + p2in + (p2th * 23) + p3in + (p3th * 23);
486
+ if (sessionEvents.length < SESSION_EVENT_MAX) {
487
+ sessionEvents.push({
488
+ id: incrementSessionEventCounter(),
489
+ timestamp: new Date().toISOString(),
490
+ type: "reflect",
491
+ agent_id: job.agentId,
492
+ turn_number: job.turnNumber,
493
+ turn_name: job.turnName,
494
+ blocks_created: r.created_blocks,
495
+ blocks_updated: r.updated_blocks,
496
+ tokens: { pass1_input: p1in, pass2_input: p2in, pass2_thinking: p2th, pass3_input: p3in, pass3_thinking: p3th, billed_equiv: billedEquiv },
497
+ processing_ms,
498
+ rate_limited: rateLimited,
499
+ ...(rateLimitPass ? { rate_limit_pass: rateLimitPass } : {}),
500
+ });
501
+ evaluateAlertsAfterReflect(sessionEvents[sessionEvents.length - 1]);
502
+ }
503
+ // Exponential backoff with full jitter — avoids thundering herd on Gemini 503s.
504
+ // Base: 15s. Doubles each attempt, caps at 60s. Jitter: random 0-50% of base delay.
505
+ // Jobs are never dropped — agent knowledge is permanent. Retries until Gemini is available.
506
+ // Survives server restarts via DB (retry_wait rows recovered on startup).
507
+ const attempts = (job.retryAttempts ?? 0) + 1;
508
+ {
509
+ const baseDelay = Math.min(15_000 * Math.pow(2, attempts - 1), 60_000);
510
+ const jitter = Math.random() * baseDelay * 0.5;
511
+ const retryDelay = Math.round(baseDelay + jitter);
512
+ const retryInSec = Math.round(retryDelay / 1000);
513
+ // Every retry preserves EVERY completed pass so the eventual turn log shows
514
+ // Pass 0/1/2/3 reasoning regardless of where the retry started.
515
+ const pass0Snapshot = r.checkpoint?.pass0 ?? job.precomputedPass0;
516
+ const pass1Snapshot = r.checkpoint?.pass1Items
517
+ ? { items: r.checkpoint.pass1Items }
518
+ : job.precomputedPass1;
519
+ const pass2Snapshot = r.checkpoint?.pass2Classified
520
+ ? { classified: r.checkpoint.pass2Classified }
521
+ : job.precomputedPass2;
522
+ if (r.checkpoint?.resumeFrom === 'pass1') {
523
+ console.log(`[reflect-queue] Pass 1 failed — re-queuing (attempt ${attempts}, retry in ${retryInSec}s)`);
524
+ const retryJob = {
525
+ ...job,
526
+ precomputedPass0: pass0Snapshot,
527
+ precomputedPass1: undefined,
528
+ precomputedPass2: undefined,
529
+ precomputedPass3PendingBlockIds: undefined,
530
+ retryAfter: Date.now() + retryDelay,
531
+ retryAttempts: attempts,
532
+ };
533
+ if (job.dbId)
534
+ db.updateReflectJob(job.dbId, { status: 'retry_wait', retry_after: retryJob.retryAfter, retry_attempts: attempts, precomputed: JSON.stringify({ pass0: pass0Snapshot }) });
535
+ reflectQueue.unshift(retryJob);
536
+ }
537
+ else if (r.checkpoint?.resumeFrom === 'pass2') {
538
+ console.log(`[reflect-queue] Pass 2 failed — re-queuing with Pass 0+1 (attempt ${attempts}, retry in ${retryInSec}s)`);
539
+ const retryJob = {
540
+ ...job,
541
+ precomputedPass0: pass0Snapshot,
542
+ precomputedPass1: pass1Snapshot,
543
+ precomputedPass2: undefined,
544
+ precomputedPass3PendingBlockIds: undefined,
545
+ retryAfter: Date.now() + retryDelay,
546
+ retryAttempts: attempts,
547
+ };
548
+ if (job.dbId)
549
+ db.updateReflectJob(job.dbId, { status: 'retry_wait', retry_after: retryJob.retryAfter, retry_attempts: attempts, precomputed: JSON.stringify({ pass0: pass0Snapshot, pass1: pass1Snapshot }) });
550
+ reflectQueue.unshift(retryJob);
551
+ }
552
+ else if (r.checkpoint?.resumeFrom === 'pass3') {
553
+ console.log(`[reflect-queue] Pass 3 failed — re-queuing with Pass 0+1+2 (attempt ${attempts}, retry in ${retryInSec}s)`);
554
+ const retryJob = {
555
+ ...job,
556
+ precomputedPass0: pass0Snapshot,
557
+ precomputedPass1: pass1Snapshot,
558
+ precomputedPass2: pass2Snapshot,
559
+ precomputedPass3PendingBlockIds: undefined,
560
+ retryAfter: Date.now() + retryDelay,
561
+ retryAttempts: attempts,
562
+ };
563
+ if (job.dbId)
564
+ db.updateReflectJob(job.dbId, { status: 'retry_wait', retry_after: retryJob.retryAfter, retry_attempts: attempts, precomputed: JSON.stringify({ pass0: pass0Snapshot, pass1: pass1Snapshot, pass2: pass2Snapshot }) });
565
+ reflectQueue.unshift(retryJob);
566
+ }
567
+ else if (r.checkpoint?.resumeFrom === 'pass4') {
568
+ console.log(`[reflect-queue] Pass 4 failed — re-queuing with Pass 0+1+2+3 pending blocks (attempt ${attempts}, retry in ${retryInSec}s)`);
569
+ const retryJob = {
570
+ ...job,
571
+ precomputedPass0: pass0Snapshot,
572
+ precomputedPass1: pass1Snapshot,
573
+ precomputedPass2: pass2Snapshot,
574
+ precomputedPass3PendingBlockIds: r.checkpoint.p3PendingBlockIds,
575
+ retryAfter: Date.now() + retryDelay,
576
+ retryAttempts: attempts,
577
+ };
578
+ if (job.dbId)
579
+ db.updateReflectJob(job.dbId, { status: 'retry_wait', retry_after: retryJob.retryAfter, retry_attempts: attempts, precomputed: JSON.stringify({ pass0: pass0Snapshot, pass1: pass1Snapshot, pass2: pass2Snapshot, p3PendingBlockIds: r.checkpoint.p3PendingBlockIds }) });
580
+ reflectQueue.unshift(retryJob);
581
+ }
582
+ else {
583
+ // Job completed successfully
584
+ if (job.dbId)
585
+ db.updateReflectJob(job.dbId, { status: 'done' });
586
+ }
587
+ }
588
+ }
589
+ catch (e) {
590
+ // Out of credit → pause spending + requeue UNCHANGED (never drop, no cap burn).
591
+ // Checked BEFORE the 503/rate-limit branch so a 402 is never mistaken for capacity.
592
+ if (await pauseAndRequeueIfCreditOut(db, job, e)) {
593
+ continue;
594
+ }
595
+ const errStr = String(e);
596
+ const isBothModels503 = errStr.includes("503") || errStr.includes("Service Unavailable") ||
597
+ errStr.includes("high demand") || errStr.includes("429") || errStr.includes("RESOURCE_EXHAUSTED");
598
+ const attempts = (job.retryAttempts ?? 0) + 1;
599
+ if (isBothModels503) {
600
+ // Both primary and fallback returned 503 — park and retry later
601
+ const baseDelay = Math.min(15_000 * Math.pow(2, attempts - 1), 60_000);
602
+ const retryDelay = Math.round(baseDelay + Math.random() * baseDelay * 0.5);
603
+ console.warn(`[reflect-queue] both models 503 — retry ${attempts} in ${Math.round(retryDelay / 1000)}s`);
604
+ const retryJob = { ...job, retryAfter: Date.now() + retryDelay, retryAttempts: attempts };
605
+ if (job.dbId)
606
+ db.updateReflectJob(job.dbId, { status: 'retry_wait', retry_after: retryJob.retryAfter, retry_attempts: attempts });
607
+ reflectQueue.unshift(retryJob);
608
+ }
609
+ else {
610
+ console.error("[reflect-queue] job error:", e);
611
+ if (job.dbId)
612
+ db.updateReflectJob(job.dbId, { status: 'dead', error: errStr.slice(0, 200) });
613
+ }
614
+ }
615
+ }
616
+ }
617
+ finally {
618
+ reflectProcessing = false;
619
+ }
620
+ }
621
+ //# sourceMappingURL=state.js.map