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,706 @@
1
+ // ═══════════════════════════════════════════════════════════════════════════════
2
+ // PIPELINE v2 (TRANSFORM) — COMPREHEND fragment: schema + SEAM 1 + converter
3
+ // ═══════════════════════════════════════════════════════════════════════════════
4
+ //
5
+ // Design: docs/PIPELINE-TRANSFORM-DESIGN.md + docs/PIPELINE-V2-MOVING-PARTS.md.
6
+ //
7
+ // This is build STEP 2 (the schema foundation). $0 / no LLM. Default-OFF
8
+ // (NODEDEX_PIPELINE_V2). NOTHING here is wired into the live pipeline yet — it is
9
+ // the contract + the deterministic code that proves the fragment maps onto the
10
+ // EXISTING machinery (so LLM 2 / WRITE reuse is real, not aspirational).
11
+ //
12
+ // WHAT COMPREHEND (LLM 1, built in step 3) will emit:
13
+ // one holistic read of an arc → topic GROUPS → typed schema blocks + the
14
+ // within-group causal links it READ from the prose + a provenance excerpt per
15
+ // block + PROVISIONAL names. It replaces Pass 0+1+JUDGE+2a+2b+2c and kills Pass
16
+ // 2c's O(n²) (links are read, not pair-compared).
17
+ //
18
+ // THE BRIDGE (this file): `comprehendResultToPass2Items` flattens the grouped
19
+ // fragment into Pass2Item[] — the exact shape Pass 3 / resolve / dedup / WRITE
20
+ // already consume. The within-group links distribute onto Pass2Item's existing
21
+ // causal fields (triggered_by_items / based_on_items / extends_item / relations).
22
+ // So the v2 producer feeds the v1 consumer: swap the engine, not the car.
23
+ //
24
+ // MEANING-FIRST reuse (not a parallel vocabulary):
25
+ // - types + unique{} field shape ← schema-validator.ts (TYPE_UNIQUE_SCHEMA /
26
+ // validateUniqueSchema) — the SAME source of truth Pass 2/save use.
27
+ // - link relation types ← the subset of pipeline.ts ALLOWED_RELS a holistic
28
+ // READ produces (see COMPREHEND_LINK_RELS).
29
+ // - block shape ← Pass2Item (types.ts).
30
+ //
31
+ // NAMING IS PROVISIONAL ONLY here. Canonical strict labels + project-root
32
+ // resolution happen in LLM 2 (INTEGRATE), AFTER resolve — naming-before-resolve
33
+ // is the root-fork bug (recognizer design, Insight 2).
34
+ import { TYPE_UNIQUE_SCHEMA, validateUniqueSchema } from "./schema-validator.js";
35
+ import { getThinkingBudget, modelOverride, intFromEnv } from "./config.js";
36
+ // ─── Flag gate ──────────────────────────────────────────────────────────────
37
+ // Default OFF. Mirrors recognizerEnabled() ("1" convention). The current
38
+ // pipeline stays the default until the A/B (§12) earns a flip.
39
+ export function pipelineV2Enabled() {
40
+ // ⚠ OLD v1 PIPELINE — DO NOT TURN ON. v2 (COMPREHEND / transform) is the ONLY
41
+ // extraction engine in this release. The v1 front-half (pass2a / pass2c /
42
+ // pass_judge / split-orchestrator / seams / quarantine / synthesizeFromSceneCard)
43
+ // is RETIRED — kept in-tree for reference only, never executed. The
44
+ // NODEDEX_PIPELINE_V2 env var is now INERT: there is no off-switch back to v1.
45
+ // (Pre-release, =0 ran the v1 front-half as the primary engine; that path is
46
+ // intentionally unreachable now.)
47
+ return true;
48
+ }
49
+ /** Bounded inline retry budget for the v2 ARC path — applied at BOTH failure sites:
50
+ * the front-half (COMPREHEND failed / SEAM-1 invalid / threw) AND the back-half
51
+ * (Pass 3 returned a re-queue checkpoint = items dropped). On exhaustion the arc
52
+ * FAILS CLEAN: turns are left re-extractable (never marked extracted with unsaved
53
+ * residue) and — v2-only — it NEVER auto-falls to v1. A fresh COMPREHEND / a
54
+ * resume-from-pass3 re-run recovers LLM-variance failures; the cap stops a
55
+ * deterministic fault from looping. Default 2 (→ up to 3 attempts total); set 0 to
56
+ * fail clean on the first failure. NODEDEX_ARC_MAX_RETRIES. */
57
+ export function arcMaxRetries() {
58
+ return intFromEnv("NODEDEX_ARC_MAX_RETRIES", 2, 0);
59
+ }
60
+ // Gap (cost): v2-aware LAZY CAPTURE. The v2 arc engine re-reads the RAW transcript
61
+ // and IGNORES the per-turn pass01 items, so running Pass 0-1 at capture is pure
62
+ // waste in v2 mode (~25% of an arc's spend). When ON, the per-turn capture stores
63
+ // the raw transcript + marks the turn arc-ready WITHOUT running Pass 0-1. If v2
64
+ // later fails at arc, the v1 fallback fills Pass 0-1 lazily from the raw transcript
65
+ // (so the safety net is preserved — the cost just moves to the rare failure path).
66
+ // Default ON (promoted 2026-06-14 — validated ~42% capture-cost win); set =0 to opt out.
67
+ // Only meaningful when v2 is the engine.
68
+ export function v2LazyCaptureEnabled() {
69
+ return process.env.NODEDEX_V2_LAZY_CAPTURE !== "0";
70
+ }
71
+ // ─── Within-group link relations COMPREHEND may emit ──────────────────────────
72
+ // The subset of pipeline.ts ALLOWED_RELS that a holistic READ of the prose
73
+ // produces. EXCLUDES: superseded_by (auto-inverse, written at WRITE), part_of /
74
+ // member_of (structural containment / clustering, not the causal thread — wired
75
+ // at WRITE from project resolution + groups).
76
+ // ⚠ KEEP IN SYNC with ALLOWED_RELS in pipeline.ts (it is duplicated inline there,
77
+ // not exported; if that set changes, change this).
78
+ export const COMPREHEND_LINK_RELS = new Set([
79
+ "prompted_by", // consequence → trigger → Pass2Item.triggered_by_items[]
80
+ "based_on", // conclusion → evidence → Pass2Item.based_on_items[]
81
+ "extends", // specific → broader → Pass2Item.extends_item (single)
82
+ "supersedes", // new → old → Pass2Item.supersedes_ref (single)
83
+ "resolves", // answer → question → Pass2Item.resolved_ref (single)
84
+ "supports", // fact → hypothesis → Pass2Item.relations[]
85
+ "contradicts", // A ↔ B → Pass2Item.relations[]
86
+ "related_to", // A ↔ B → Pass2Item.relations[]
87
+ "derived_from", // derived → source → Pass2Item.relations[]
88
+ "affects", // agent → patient (x-proj)→ Pass2Item.relations[]
89
+ ]);
90
+ export function validateComprehendResult(result) {
91
+ const errors = [];
92
+ const warnings = [];
93
+ const err = (message, group_id, local_id) => errors.push({ severity: "error", message, group_id, local_id });
94
+ const warn = (message, group_id, local_id) => warnings.push({ severity: "warning", message, group_id, local_id });
95
+ const r = result;
96
+ if (!r || typeof r !== "object" || !Array.isArray(r.groups)) {
97
+ err("result.groups is missing or not an array");
98
+ return { valid: false, errors, warnings };
99
+ }
100
+ // Legitimately empty = the session had no residue worth saving. VALID → the
101
+ // pipeline saves nothing (not an error, not a retry). Distinct from malformed
102
+ // above. A real outcome of the worth gate (e.g. pure debugging chatter — the
103
+ // noise trap that produced the old 87-job junk).
104
+ if (r.groups.length === 0)
105
+ return { valid: true, errors, warnings };
106
+ // local_ids are GROUP-SCOPED — the LLM numbers blocks per group (block_1, block_2,
107
+ // … restart in each group). So uniqueness + link resolution are checked WITHIN
108
+ // each group; within_group_links only reference blocks of their own group (a
109
+ // reference to another group's block = not a within-group link → LLM 2's job, and
110
+ // surfaces here as "no block in this group"). The converter qualifies ids by
111
+ // group to make them globally unique downstream.
112
+ for (const group of r.groups) {
113
+ const gid = group?.group_id;
114
+ if (!gid)
115
+ err("group missing group_id");
116
+ if (!Array.isArray(group?.blocks)) {
117
+ err("group missing blocks[]", gid);
118
+ continue;
119
+ }
120
+ const idsInGroup = new Set();
121
+ const decisionIds = new Set();
122
+ for (const b of group.blocks) {
123
+ const lid = b?.local_id;
124
+ if (!lid) {
125
+ err("block missing local_id", gid);
126
+ continue;
127
+ }
128
+ if (idsInGroup.has(lid))
129
+ err(`duplicate local_id "${lid}" within group`, gid, lid);
130
+ idsInGroup.add(lid);
131
+ if (!b.type) {
132
+ err("block missing type", gid, lid);
133
+ }
134
+ else {
135
+ if (b.type === "decision")
136
+ decisionIds.add(lid);
137
+ // Unknown type with no schema{} → warning (novel types are trusted IF
138
+ // they declare schema{}, exactly like schema-validator.ts).
139
+ if (!(b.type in TYPE_UNIQUE_SCHEMA) && !b.schema) {
140
+ warn(`unknown type "${b.type}" without schema{}`, gid, lid);
141
+ }
142
+ }
143
+ if (!b.provenance || !b.provenance.trim()) {
144
+ err("block missing provenance excerpt", gid, lid); // HARD — anti-confab key
145
+ }
146
+ if (!b.essence || !b.essence.trim()) {
147
+ warn("block missing essence", gid, lid);
148
+ }
149
+ // unique{} key-set shape — SOFT (reuse the save-time validator)
150
+ const chk = validateUniqueSchema(b.type, b.unique);
151
+ if (!chk.ok)
152
+ warn(`unique{} ${chk.detail}`, gid, lid);
153
+ }
154
+ // Links resolve WITHIN this group. ALL link defects are warnings — every one
155
+ // is dropped at convert (the converter skips unresolvable/unknown links), and
156
+ // a dropped link is repairable downstream; a degraded arc is not (see the seam
157
+ // header). A dangling endpoint usually means the LLM renamed a block it DID
158
+ // emit (it recalls the meaning, not the exact id) — the blocks are fine.
159
+ const links = Array.isArray(group?.within_group_links) ? group.within_group_links : [];
160
+ const hasBasedOnFrom = new Set();
161
+ for (const link of links) {
162
+ if (!COMPREHEND_LINK_RELS.has(link?.type)) {
163
+ warn(`link with unknown/unsupported relation "${link?.type}" (dropped at convert)`, gid);
164
+ }
165
+ if (!idsInGroup.has(link?.from))
166
+ warn(`link.from "${link?.from}" references no block in this group (dropped at convert)`, gid);
167
+ if (!idsInGroup.has(link?.to))
168
+ warn(`link.to "${link?.to}" references no block in this group (dropped at convert)`, gid);
169
+ // Only a link that will actually SURVIVE convert satisfies the decision's
170
+ // based_on requirement — a dangling one is dropped, leaving the decision
171
+ // unwired, which the warning below must report truthfully (JUSTIFY's
172
+ // detect step then finds the genuinely-empty based_on and repairs it).
173
+ if (link?.type === "based_on" && link?.from && idsInGroup.has(link?.to))
174
+ hasBasedOnFrom.add(link.from);
175
+ }
176
+ // decision must be justified by ≥1 based_on (block-types.md:54). SOFT: if the
177
+ // evidence isn't in the transcript that's a flag, not a fabrication.
178
+ for (const did of decisionIds) {
179
+ if (!hasBasedOnFrom.has(did)) {
180
+ warn("decision has no based_on link (block-types.md requires one)", gid, did);
181
+ }
182
+ }
183
+ }
184
+ return { valid: errors.length === 0, errors, warnings };
185
+ }
186
+ /** Bucket COMPREHEND validation WARNINGS for a quieter, honest log line. Most fire on
187
+ * the raw draft and are REPAIRED DOWNSTREAM — unique{} shape by Pass 2b fill, dangling
188
+ * within-group links dropped at convert, a decision's missing based_on by JUSTIFY — so
189
+ * counting them raw made a clean arc look alarming ("warnings=35"). `notable` is the few
190
+ * worth a glance (missing essence, unknown type, a group with no topic/root). Pure. */
191
+ export function summarizeWarnings(warnings) {
192
+ let draft = 0;
193
+ let notable = 0;
194
+ for (const w of warnings ?? []) {
195
+ const m = w?.message ?? "";
196
+ if (m.includes("unique{}") || m.includes("link") || m.includes("based_on"))
197
+ draft++;
198
+ else
199
+ notable++;
200
+ }
201
+ return `${notable} notable` + (draft ? `, ${draft} draft (repaired downstream)` : "");
202
+ }
203
+ /** Group-scoped local_id → a globally-unique Pass2Item id. The LLM numbers
204
+ * blocks per group (block_1 in every group), so we namespace by group. */
205
+ function qualifyId(groupId, localId) {
206
+ return `${groupId}::${localId}`;
207
+ }
208
+ /**
209
+ * Distribute ONE link onto the SOURCE item's existing causal field by relation
210
+ * type — the single source of truth for the link→field mapping. Used by the
211
+ * within-group converter AND the cross-group linker (cross-group-link.ts) so they
212
+ * never drift on which field a relation lands in. Caller must pre-validate that
213
+ * `type` ∈ COMPREHEND_LINK_RELS and that `toId` resolves to a real item.
214
+ */
215
+ export function applyLinkToPass2Item(from, type, toId, reasoning) {
216
+ switch (type) {
217
+ case "prompted_by":
218
+ from.triggered_by_items.push(toId);
219
+ break;
220
+ case "based_on":
221
+ from.based_on_items.push(toId);
222
+ break;
223
+ case "extends":
224
+ from.extends_item = toId;
225
+ break; // single; last wins
226
+ case "supersedes":
227
+ from.supersedes_ref = toId;
228
+ break;
229
+ case "resolves":
230
+ from.resolved_ref = toId;
231
+ break;
232
+ default: // supports / contradicts / related_to / derived_from / affects
233
+ (from.relations ??= []).push({ type, target: toId, reasoning });
234
+ break;
235
+ }
236
+ }
237
+ /**
238
+ * A project name is a single label DIMENSION ({project}_{entity}_{type}_{concept}),
239
+ * so it MUST be hyphens-only — an underscore would fake a dimension boundary and
240
+ * make Pass 3 fork a DUPLICATE root (the hyphenated project_creates root vs the
241
+ * verbatim underscore block label). COMPREHEND occasionally emits underscores
242
+ * (e.g. "backend_api_service"); the other passes enforce hyphens via a PROMPT
243
+ * instruction (pass0/pass3), which COMPREHEND doesn't carry — so we enforce it
244
+ * deterministically here, where item.project is born. Lossless for already-valid
245
+ * names; undefined in → undefined out (no project). (Run 9 big-arc bug.)
246
+ */
247
+ export function normalizeProjectName(p) {
248
+ if (!p)
249
+ return undefined;
250
+ const out = p.trim().toLowerCase()
251
+ .replace(/[\s_]+/g, "-") // underscores + whitespace → hyphen (the dimension rule)
252
+ .replace(/[^a-z0-9-]/g, "") // strip anything not lowercase-alnum-hyphen
253
+ .replace(/-+/g, "-") // collapse repeats
254
+ .replace(/^-|-$/g, ""); // trim edge hyphens
255
+ return out.length > 0 ? out : undefined;
256
+ }
257
+ /** The most common normalized provisional_project across an arc's groups — the arc's
258
+ * ROOT to inherit when an individual group's guess is missing. Groups in one arc
259
+ * usually belong to ONE root, so inheriting the dominant guess keeps clusters together
260
+ * rather than fragmenting (each empty group otherwise becoming its own topic-named
261
+ * root). undefined only when NO group named a project. Pure / testable. */
262
+ export function dominantProvisionalProject(groups) {
263
+ const counts = new Map();
264
+ for (const g of groups ?? []) {
265
+ const p = normalizeProjectName(g.provisional_project);
266
+ if (p)
267
+ counts.set(p, (counts.get(p) ?? 0) + 1);
268
+ }
269
+ let best;
270
+ let bestN = 0;
271
+ for (const [p, n] of counts)
272
+ if (n > bestN) {
273
+ best = p;
274
+ bestN = n;
275
+ }
276
+ return best;
277
+ }
278
+ /**
279
+ * Flatten the grouped fragment into Pass2Item[], distributing each within-group
280
+ * link onto the SOURCE item's existing causal field by relation type. local_ids
281
+ * are GROUP-SCOPED → qualified to `{group_id}::{local_id}` for global uniqueness;
282
+ * links resolve within their own group. Pure + defensive: skips links whose
283
+ * endpoints don't resolve (the validator reports those as errors; the converter
284
+ * must not throw on them).
285
+ *
286
+ * NOTE: `project` is set to the group's PROVISIONAL project. LLM 2 / the
287
+ * recognizer overrides it with the canonical root before WRITE.
288
+ */
289
+ export function comprehendResultToPass2Items(result) {
290
+ const items = [];
291
+ const groupByItemId = {};
292
+ const itemById = new Map();
293
+ // item.project is BORN here from the GUESS (provisional_project). The holistic
294
+ // COMPREHEND schema once made that guess OPTIONAL, so it could arrive empty — and an
295
+ // undefined item.project starves the recognizer (newRootCandidateNames skips
296
+ // undef-project items) AND leaves Pass 3 to coin a placeholder root (the "group_1"
297
+ // regression, 2026-06-14). Guarantee a real name: the group's own guess, else the
298
+ // arc's DOMINANT guess (groups in one arc usually share a root — keeps "one root,
299
+ // many clusters" instead of fragmenting on topic), else the group's topic. Only
300
+ // undefined when the arc named nothing at all.
301
+ const arcRoot = dominantProvisionalProject(result.groups ?? []);
302
+ for (const group of result.groups ?? []) {
303
+ const gid = group.group_id;
304
+ const groupProject = normalizeProjectName(group.provisional_project) ?? arcRoot ?? normalizeProjectName(group.topic);
305
+ for (const b of group.blocks ?? []) {
306
+ const id = qualifyId(gid, b.local_id);
307
+ const item = {
308
+ id,
309
+ text: b.essence ?? "",
310
+ type: b.type,
311
+ project: groupProject,
312
+ unique: b.unique,
313
+ schema: b.schema,
314
+ excerpt: b.provenance,
315
+ triggered_by_items: [],
316
+ based_on_items: [],
317
+ relations: [],
318
+ // Observability: the LLM's own worth + typing rationale MUST survive to the
319
+ // turn-log (charter rule 8 — diagnose from reasoning). Dropped here before
320
+ // 2026-06-12 → per-turn v2 logs had no auditable reasoning. Pass 3 strips
321
+ // these from its prompt copy, so they never reach a downstream LLM.
322
+ keep_reason: b.keep_reason,
323
+ type_reasoning: b.type_reasoning,
324
+ };
325
+ if (b.uncertain)
326
+ item.review_reason = "comprehend_uncertain";
327
+ items.push(item);
328
+ itemById.set(id, item);
329
+ groupByItemId[id] = gid;
330
+ }
331
+ }
332
+ for (const group of result.groups ?? []) {
333
+ const gid = group.group_id;
334
+ for (const link of group.within_group_links ?? []) {
335
+ // Drop links the model mis-typed (a relation outside COMPREHEND_LINK_RELS —
336
+ // usually a unique{} field name). SEAM 1 warns; the info lives in the block's
337
+ // own field. Dropping here keeps junk relations out of the graph.
338
+ if (!COMPREHEND_LINK_RELS.has(link.type))
339
+ continue;
340
+ const fromId = qualifyId(gid, link.from);
341
+ const toId = qualifyId(gid, link.to);
342
+ const from = itemById.get(fromId);
343
+ if (!from || !itemById.has(toId))
344
+ continue; // the designed drop — seam 1 warns on these (never fatal)
345
+ applyLinkToPass2Item(from, link.type, toId, link.reasoning);
346
+ }
347
+ }
348
+ return { items, groupByItemId };
349
+ }
350
+ // ═══════════════════════════════════════════════════════════════════════════════
351
+ // BRIDGE TO RUNNABLE — fragment → a Pass-3-resume checkpoint
352
+ // ═══════════════════════════════════════════════════════════════════════════════
353
+ //
354
+ // runAutoReflect already supports resuming from a checkpoint: when
355
+ // `checkpoint.pass2Classified` is set it SKIPS Pass 0/1/2 and runs Pass 3+ on
356
+ // those items (pipeline.ts:934). v2 reuses that seam — COMPREHEND produces the
357
+ // classified items, this builds the checkpoint, and the EXISTING back-half
358
+ // (Pass 3→5 + recognizer/Stage D + chain-stamp) runs unchanged. No hot-path edit.
359
+ //
360
+ // pass1Items are derived (minimal) so Pass 3's budget hint + any pass1 reference
361
+ // is satisfied; pass0.sceneCard is left undefined (Pass 3 handles its absence).
362
+ export function comprehendResultToCheckpoint(result) {
363
+ const { items } = comprehendResultToPass2Items(result);
364
+ const pass1Items = items.map((it) => ({
365
+ id: it.id,
366
+ text: it.text,
367
+ source: "comprehend",
368
+ excerpt: it.excerpt ?? "",
369
+ provisional_type: it.type,
370
+ }));
371
+ return {
372
+ resumeFrom: "pass3",
373
+ pass0: { sceneCard: undefined, raw: undefined },
374
+ pass1Items,
375
+ pass2Classified: items,
376
+ };
377
+ }
378
+ // ═══════════════════════════════════════════════════════════════════════════════
379
+ // LLM 1 — COMPREHEND: the prompt + the call (build step 3)
380
+ // ═══════════════════════════════════════════════════════════════════════════════
381
+ //
382
+ // One holistic read of the whole session → grouped typed blocks + the links it
383
+ // READ from the prose + provenance. Replaces Pass 0/1/JUDGE/2a/2b/2c. The output
384
+ // is validated by SEAM 1 (validateComprehendResult) and converted to Pass2Item[]
385
+ // (comprehendResultToPass2Items) which the EXISTING Pass 3+ back-half consumes.
386
+ //
387
+ // Prompt discipline (PROMPT-CHARTER): reason about MEANING, never match surface
388
+ // words; universal across domains (no signal words, no domain examples); reuse the
389
+ // worth spine + STATE CONVENTION verbatim from the current JUDGE/Pass-1 prompts;
390
+ // types defined by epistemic role, not text shape.
391
+ export const COMPREHEND_PROMPT = `You read ONE complete work session between a user and an AI agent, and transcribe
392
+ its already-structured story into the memory schema. Read the whole session first,
393
+ then write.
394
+
395
+ Decide EVERYTHING by reasoning about MEANING in this session's context — what role
396
+ each piece played in what actually happened here. Never decide by matching surface
397
+ words, phrasings, or connectors. The same meaning appears in countless wordings
398
+ across domains; you are reading for the structure beneath the words.
399
+
400
+ ── STATE CONVENTION ─────────────────────────────────────────────────────────
401
+ "State" = text in the TRANSCRIPT below. Your training knowledge and "what's
402
+ commonly known" are NOT state. Every block must quote a verbatim excerpt from the
403
+ transcript as its provenance. If it is not in the transcript, do not write it.
404
+ Familiarity ≠ recorded.
405
+
406
+ ── WHAT TO KEEP (reason per candidate, from this session) ───────────────────
407
+ Keep the irreplaceable RESIDUE of this session — what was DECIDED, TRIED-AND-
408
+ ABANDONED, CONSTRAINED, OBSERVED, or STATED here — together with the REASONING.
409
+
410
+ The spine question, per candidate:
411
+ "Could a competent model — given the project context but WITHOUT having lived
412
+ this session — already produce this?"
413
+ YES → it is knowledge the model already carries → do not emit.
414
+ NO → it exists only because this session happened → emit it.
415
+
416
+ Asymmetric cost: anything that exists ONLY because this session happened is
417
+ unrecoverable once dropped — not just a decision / dead_end / constraint, but also a
418
+ session-specific observation, measurement, or stated value. Only what the model
419
+ ALREADY carries regenerates for free; a value measured or stated here is not that.
420
+ When unsure → keep.
421
+
422
+ Consulting the agent's own memory is not such a happening. A statement whose subject
423
+ is that MEMORY itself — that what is already stored is complete, was reviewed, or that
424
+ reading it changed nothing — is not residue, even though the reading occurred this
425
+ session; reading memory is not an action in the work. Emit only what the work produced
426
+ about ITS subject, never the agent's reading of what it had already stored.
427
+
428
+ A conclusion's EVIDENCE is residue too — the observation, measurement, or result it
429
+ is reasoned from. Keep it as its own block and ground the conclusion to it
430
+ (based_on / supports); a conclusion saved without what it rests on is
431
+ half the record. Keep that evidence EVEN when nothing links to it yet — a later
432
+ session grounds it; never drop a session-specific observation for lack of a link.
433
+
434
+ Do not emit:
435
+ • an option that was only RAISED in thought — never chosen, entered, or acted on.
436
+ • a bare sequence of steps carrying no reason that nothing rests on — the WHEN with
437
+ no WHY. (A step or value a conclusion is reasoned from is not bare — keep it.)
438
+
439
+ If the same claim appears more than once in the session (e.g. restated in a recap),
440
+ write it once, using its most complete statement.
441
+
442
+ If the session holds no residue at all — pure procedure, scaffolding, or chatter —
443
+ write nothing. An empty result is correct when nothing here could only have come
444
+ from this session.
445
+
446
+ Every block carries keep_reason: one line, from the session, naming what makes it
447
+ residue (it was chosen / entered-then-abandoned / imposed / measured / asserted by
448
+ a party), or why you kept it when it was borderline.
449
+
450
+ Every block also carries type_reasoning: one line stating why THIS type's epistemic
451
+ role fits — what distinguishes it from the neighbouring types, judged by the role the
452
+ block plays for a future reader, not by surface wording. Decide this before you commit
453
+ the type.
454
+
455
+ ── STEP 1 — SEGMENT into GROUPS (clusters under a root) ─────────────────────
456
+ FIRST split the session into GROUPS. A group is one coherent sub-thread — a single
457
+ problem worked, question pursued, or thing decided. KEEP DISTINCT SUB-THREADS AS
458
+ SEPARATE GROUPS even when they belong to the same overall project; one sub-thread
459
+ scattered across the session is one group. Judge by what the participants were
460
+ trying to do, not by topic words. Do NOT collapse several sub-threads into one big
461
+ group — keep them fine-grained.
462
+
463
+ THEN assign each group a provisional_project — the ONE overarching ROOT it belongs
464
+ to. The ROOT is the project; the GROUP is a CLUSTER under it; ONE root has MANY
465
+ clusters. Sub-threads of the same overall effort SHARE a root but STAY SEPARATE
466
+ GROUPS — same root, several clusters; do NOT merge them into one group.
467
+ • Use a DIFFERENT provisional_project ONLY for a genuinely separate topic — a
468
+ real context-switch or an unrelated tangent.
469
+ • A separate root must have a NAMEABLE SUBJECT: you must be able to say what the
470
+ group's work is ABOUT without referring to the speaker's own remembering,
471
+ reasoning, or composing of replies in this conversation. Recalling, weighing,
472
+ and planning how to respond are the MEANS of every conversation, never a topic
473
+ of their own — claims born of that procedure belong under the root of the work
474
+ they serve (and only those that pass the residue test above).
475
+ • When unsure whether two groups share a root, prefer the SAME root — splitting
476
+ one topic across many roots (fragmentation) is worse than a slightly-broad root.
477
+ • NAME the root with the most SPECIFIC identifier the session gives the SUBJECT the
478
+ work is ABOUT — named as specifically as the session itself names it. NEVER a
479
+ generic category word, a placeholder, or the group_id. If nothing that specific is
480
+ named, use the clearest phrase for what the work is about — never a bare
481
+ "group"/number. lowercase, hyphens only, no underscores. provisional_project must
482
+ always be filled.
483
+ This is provisional; cross-SESSION matching to existing roots happens later.
484
+
485
+ ── STEP 2 — within each group, write TYPED blocks ───────────────────────────
486
+ A type is the agent's RELATIONSHIP to the knowledge, not its subject matter — the
487
+ same type spans every domain. For each piece of residue, reason about which
488
+ relationship fits, then FILL THAT TYPE'S unique{} FIELDS — this is the block's
489
+ structured identity and is REQUIRED, never empty. Put the actual content there
490
+ (the choice + reason, the value, the limit, the approach + why it failed), in the
491
+ session's own language. essence is only a one-line SUMMARY of those fields — it
492
+ does not replace them. A block whose unique{} is empty is incomplete; fill every
493
+ field of the type that the session supports. One passage can carry several
494
+ relationships → several blocks.
495
+
496
+ CORE relationships (consider these first):
497
+ decision {choice, reason, alternatives_rejected} — the participants CLOSED a
498
+ fork: a path was committed to, adopted, or acted on. The decision is
499
+ the path TAKEN; a path they CLOSED OFF is a dead_end (below), not a
500
+ decision — even when one passage both settles the choice and rules out
501
+ the alternative. A path one participant PUT FORWARD for another to
502
+ accept leaves the fork open — that is a blueprint (below), not a
503
+ decision, no matter how strongly it was urged. To type decision you
504
+ must be able to point at WHERE the fork closed, not just where a path
505
+ was proposed. Justify it: link based_on >=1 fact/constraint (Step 3).
506
+ dead_end {approach, reason, alternative} — an approach CLOSED OFF for a stated
507
+ reason, so a future reader should not re-open it. Covers one tried then
508
+ abandoned AND one evaluated and definitively rejected before trying. A
509
+ path merely floated with no verdict is NOT a dead_end — the close-off
510
+ must be definite and reasoned.
511
+ constraint {limit, reason, source} — a boundary that bounds EVERY option and that
512
+ the participants must work within. May be imposed from outside OR set by
513
+ the participants as a fixed limit; what makes it a constraint is that it
514
+ GOVERNS the other choices rather than being one of them.
515
+ fact {value, why_matters} — a specific observed value or concrete state.
516
+ insight {observation, implication} — a realization drawn from combining things.
517
+ blueprint {purpose, status, trigger_to_implement} — a planned or proposed path
518
+ whose outcome is not yet settled: a plan adopted but not yet executed,
519
+ OR a path put forward that no one has yet accepted. The fork is still
520
+ open; when it later closes, a decision supersedes this.
521
+ preference {lean, over, condition} — a standing lean that shapes future choices,
522
+ short of a committed decision.
523
+ question {question, why_matters} — left genuinely open, with no path forward.
524
+
525
+ When the level of commitment is unclear, type the LESS-committed role (blueprint
526
+ over decision, preference over constraint): the residue is still captured, and a
527
+ later session promotes it (a decision supersedes its blueprint). A false decision
528
+ misleads every future reader into treating an open fork as closed.
529
+
530
+ OTHER roles, with their REQUIRED fields (fill these exact field names), when none of
531
+ the above fits:
532
+ hypothesis {proposal, evidence_against} — a claim offered as possibly true but
533
+ NOT yet verified: reasoned TOWARD, not asserted as established. What it
534
+ rests on is recorded as its OWN block and linked (based_on), not
535
+ restated here; evidence_against is only what would weigh against it.
536
+ entity {name, role} — a thing the work REFERS TO by name, not a claim about it;
537
+ identity is the name, role is the part it plays in the work.
538
+ task {status, description, owner} — work still TO BE DONE, tracked by its state
539
+ of completion and who holds it.
540
+ event {what_happened, outcome, date} — a thing that OCCURRED at a point in time,
541
+ as opposed to a standing truth that simply holds.
542
+ note {} — no field schema; the catch-all, only when no sharper role fits.
543
+ If a genuinely distinct epistemic role STILL fits none of these, name the type and
544
+ include schema{} (field -> what it captures).
545
+
546
+ Each block also carries: essence (one sentence, <=120 chars — what it is and why
547
+ it matters), concepts (a few terms naming what it is about), provisional_name (a
548
+ short slug for the thing — provisional, not a final label), provenance, keep_reason.
549
+
550
+ ── STEP 3 — WIRE the relationships WITHIN each group ─────────────────────────
551
+ Where the session shows one block standing in a real relationship to another —
552
+ one thing led to another, justified it, replaced it, answered it, elaborates it,
553
+ provides evidence for it, or conflicts with it — record that link. Infer it from
554
+ what happened, whether or not any connecting word is present.
555
+
556
+ Each link is {from, to, type}, where "from" holds the relationship. Choose the
557
+ type whose MEANING matches:
558
+ prompted_by — from happened as a consequence of to (to is the trigger)
559
+ based_on — from is a conclusion grounded in to (evidence)
560
+ extends — from is a more specific case of to (broader)
561
+ supersedes — from replaces an earlier to
562
+ resolves — from answers the open question to
563
+ supports — from is evidence for the proposal to
564
+ contradicts — from and to conflict
565
+ related_to — from and to are associated, with no sharper relationship
566
+ derived_from — from was reasoned out from to
567
+ affects — from has an impact on to
568
+
569
+ Reach for the SHARPEST relation the meaning supports. related_to and affects are the
570
+ WEAKEST — a last resort, used ONLY when no grounding, consequence, replacement, or
571
+ answer actually holds.
572
+
573
+ Every block sits in a HISTORY — wire each way it connects BACKWARD to what came
574
+ before, not only its evidence:
575
+ - what it was REASONED FROM: the observation, measurement, or result a later
576
+ realization, boundary, choice, or lean rests on (based_on / supports / derived_from);
577
+ - what it REPLACED: an earlier approach, value, or state this makes obsolete. The
578
+ earlier block stays as history and MUST be linked FROM the newer one (supersedes) —
579
+ never leave a superseded block standing as if nothing replaced it;
580
+ - what TRIGGERED it: the event, failure, or need it arose as a consequence of
581
+ (prompted_by);
582
+ - the open QUESTION it answers (resolves).
583
+ The trap to avoid, for ANY block type: a block that REPLACED or was TRIGGERED BY
584
+ another, but is wired only to its supporting evidence, leaves that other block
585
+ ORPHANED — you recorded why it is justified but dropped what it displaced or
586
+ responded to. Both are how the state was reached; wire both.
587
+
588
+ The link type MUST be exactly one of these ten relations — never invent one, and
589
+ never use a block's unique{} field name as a link type. A detail that belongs to a
590
+ single block (a decision's rejected alternatives, a constraint's source, and the
591
+ like) is recorded INSIDE that block's own fields — never as a link, and never as a
592
+ separate block created only so something can link to it.
593
+
594
+ Every decision — and every hypothesis or insight that rests on a finding — needs >=1
595
+ based_on to the observation it is reasoned from. If that evidence is genuinely not in
596
+ this session, mark the block uncertain — never supply the evidence yourself.
597
+
598
+ Stay within this session: do not assign final names, do not match against any
599
+ existing memory, do not link across groups. Those are later stages.`;
600
+ // Structured-output schema for COMPREHEND. Mirrors ComprehendResult. unique{} and
601
+ // schema{} are freeform maps (type:object) — the system's most complex schema, so
602
+ // the universality path (tool-use for Anthropic + prompt-JSON fallback, b8513a5)
603
+ // carries it; round-trip-verify on the target model before any A/B spend.
604
+ export const COMPREHEND_SCHEMA = {
605
+ type: "object",
606
+ properties: {
607
+ groups: {
608
+ type: "array",
609
+ items: {
610
+ type: "object",
611
+ properties: {
612
+ group_id: { type: "string" },
613
+ topic: { type: "string" },
614
+ provisional_project: { type: "string" },
615
+ blocks: {
616
+ type: "array",
617
+ items: {
618
+ type: "object",
619
+ properties: {
620
+ local_id: { type: "string" },
621
+ type: { type: "string" },
622
+ unique: {
623
+ type: "object",
624
+ description: "REQUIRED structured identity fields for the type — never empty. e.g. decision: {choice, reason, alternatives_rejected}; fact: {value, why_matters}; dead_end: {approach, reason, alternative}; constraint: {limit, reason, source}; insight: {observation, implication}. Fill from the transcript.",
625
+ },
626
+ schema: { type: "object" },
627
+ essence: { type: "string" },
628
+ concepts: { type: "array", items: { type: "string" } },
629
+ provisional_name: { type: "string" },
630
+ provenance: { type: "string" },
631
+ keep_reason: { type: "string" },
632
+ type_reasoning: { type: "string" },
633
+ uncertain: { type: "boolean" },
634
+ },
635
+ required: ["local_id", "type", "unique", "essence", "provenance", "keep_reason"],
636
+ },
637
+ },
638
+ within_group_links: {
639
+ type: "array",
640
+ items: {
641
+ type: "object",
642
+ properties: {
643
+ from: { type: "string" },
644
+ to: { type: "string" },
645
+ type: { type: "string" },
646
+ reasoning: { type: "string" },
647
+ },
648
+ required: ["from", "to", "type"],
649
+ },
650
+ },
651
+ },
652
+ required: ["group_id", "topic", "provisional_project", "blocks", "within_group_links"],
653
+ },
654
+ },
655
+ reasoning: { type: "string" },
656
+ },
657
+ required: ["groups"],
658
+ };
659
+ // Model override for COMPREHEND (the bet → strong model). Undefined → provider
660
+ // default. Own env var (PassId union has no "comprehend", so modelForPass can't
661
+ // route it).
662
+ /** Single source for all three COMPREHEND-path callers (here, per-group, cross-link). */
663
+ export function comprehendModel() {
664
+ return modelOverride("NODEDEX_COMPREHEND_MODEL");
665
+ }
666
+ /**
667
+ * Run the single COMPREHEND read over a session transcript. Graph-blind: input is
668
+ * the raw transcript ONLY (the caller assembles user+agent turns — the all-sources
669
+ * lesson). Validates via SEAM 1 but does not throw or mutate global token stats —
670
+ * the caller decides retry/quarantine and attributes cost.
671
+ */
672
+ export async function callComprehendLLM(provider, transcript, thinkingBudget = 8192) {
673
+ const userInput = `TRANSCRIPT (one work session — read all of it before writing):\n\n${transcript}`;
674
+ const r = await provider.generateStructured(COMPREHEND_PROMPT, userInput, COMPREHEND_SCHEMA, {
675
+ thinkingBudget: getThinkingBudget(thinkingBudget),
676
+ // INTERIM PATCH (latency, not capture): 65536 (the model max) let a runaway
677
+ // generation burn the full budget before failing a JSON.parse → "truncated"
678
+ // → re-roll, costing ~200s+ (the 307s arc). 32768 fails ~2x faster AND gives
679
+ // the provider's 1.5x truncation-bump real headroom (32768→49152, vs a no-op
680
+ // at 65536). Biggest legit fragment seen = 13347 tokens (Run 9, 57 blocks),
681
+ // so 32768 keeps a ~2.4x margin. DEBT this buys time against: the SINGLE
682
+ // monolithic COMPREHEND call is a latency/single-point wildcard — the
683
+ // structural fix is PER-GROUP COMPREHEND (segment once → bounded parallel
684
+ // per-group production; design §11 risk 3). Capture is already safe (a
685
+ // persistent COMPREHEND failure degrades to v1 in arc-pipeline.ts).
686
+ maxOutputTokens: 32768,
687
+ modelOverride: comprehendModel(),
688
+ });
689
+ let validation = null;
690
+ if (r.result) {
691
+ validation = validateComprehendResult(r.result);
692
+ const groups = r.result.groups?.length ?? 0;
693
+ const blocks = (r.result.groups ?? []).reduce((n, g) => n + (g.blocks?.length ?? 0), 0);
694
+ console.log(`Auto-Reflect COMPREHEND: ${groups} groups, ${blocks} blocks | valid=${validation.valid} ` +
695
+ `errors=${validation.errors.length} warnings: ${summarizeWarnings(validation.warnings)} | ` +
696
+ `tokens: in=${r.usage?.input ?? "?"} think=${r.usage?.thinking ?? "?"} out=${r.usage?.output ?? "?"}`);
697
+ for (const e of validation.errors) {
698
+ console.warn(` [COMPREHEND error] ${e.message}${e.local_id ? ` (${e.local_id})` : ""}`);
699
+ }
700
+ }
701
+ else {
702
+ console.warn(`Auto-Reflect COMPREHEND: ${r.rateLimited ? "rate limited" : "failed"} — no fragment produced`);
703
+ }
704
+ return { result: r.result, validation, rateLimited: r.rateLimited, creditExhausted: r.creditExhausted, model: r.model, attempts: r.attempts, usage: r.usage };
705
+ }
706
+ //# sourceMappingURL=comprehend.js.map