@cleocode/core 2026.4.57 → 2026.4.59

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 (933) hide show
  1. package/dist/adapters/adapter-registry.js +64 -0
  2. package/dist/adapters/adapter-registry.js.map +1 -0
  3. package/dist/adapters/discovery.js +83 -0
  4. package/dist/adapters/discovery.js.map +1 -0
  5. package/dist/adapters/index.js +9 -0
  6. package/dist/adapters/index.js.map +1 -0
  7. package/dist/adapters/manager.js +260 -0
  8. package/dist/adapters/manager.js.map +1 -0
  9. package/dist/admin/export-tasks.js +171 -0
  10. package/dist/admin/export-tasks.js.map +1 -0
  11. package/dist/admin/export.js +103 -0
  12. package/dist/admin/export.js.map +1 -0
  13. package/dist/admin/help.js +106 -0
  14. package/dist/admin/help.js.map +1 -0
  15. package/dist/admin/import-tasks.js +182 -0
  16. package/dist/admin/import-tasks.js.map +1 -0
  17. package/dist/admin/import.js +129 -0
  18. package/dist/admin/import.js.map +1 -0
  19. package/dist/admin/index.js +13 -0
  20. package/dist/admin/index.js.map +1 -0
  21. package/dist/adrs/find.js +134 -0
  22. package/dist/adrs/find.js.map +1 -0
  23. package/dist/adrs/index.js +15 -0
  24. package/dist/adrs/index.js.map +1 -0
  25. package/dist/adrs/link-pipeline.js +160 -0
  26. package/dist/adrs/link-pipeline.js.map +1 -0
  27. package/dist/adrs/list.js +43 -0
  28. package/dist/adrs/list.js.map +1 -0
  29. package/dist/adrs/parse.js +51 -0
  30. package/dist/adrs/parse.js.map +1 -0
  31. package/dist/adrs/show.js +22 -0
  32. package/dist/adrs/show.js.map +1 -0
  33. package/dist/adrs/sync.js +232 -0
  34. package/dist/adrs/sync.js.map +1 -0
  35. package/dist/adrs/types.js +9 -0
  36. package/dist/adrs/types.js.map +1 -0
  37. package/dist/adrs/validate.js +57 -0
  38. package/dist/adrs/validate.js.map +1 -0
  39. package/dist/agents/agent-registry.js +288 -0
  40. package/dist/agents/agent-registry.js.map +1 -0
  41. package/dist/agents/agent-schema.js +82 -0
  42. package/dist/agents/agent-schema.js.map +1 -0
  43. package/dist/agents/capacity.js +116 -0
  44. package/dist/agents/capacity.js.map +1 -0
  45. package/dist/agents/execution-learning.js +474 -0
  46. package/dist/agents/execution-learning.js.map +1 -0
  47. package/dist/agents/health-monitor.js +217 -0
  48. package/dist/agents/health-monitor.js.map +1 -0
  49. package/dist/agents/index.js +29 -0
  50. package/dist/agents/index.js.map +1 -0
  51. package/dist/agents/registry.js +314 -0
  52. package/dist/agents/registry.js.map +1 -0
  53. package/dist/agents/retry.js +215 -0
  54. package/dist/agents/retry.js.map +1 -0
  55. package/dist/audit-prune.js +94 -0
  56. package/dist/audit-prune.js.map +1 -0
  57. package/dist/audit.js +68 -0
  58. package/dist/audit.js.map +1 -0
  59. package/dist/backfill/index.js +229 -0
  60. package/dist/backfill/index.js.map +1 -0
  61. package/dist/bootstrap.js +435 -0
  62. package/dist/bootstrap.js.map +1 -0
  63. package/dist/caamp/adapter.js +259 -0
  64. package/dist/caamp/adapter.js.map +1 -0
  65. package/dist/caamp/capability-check.js +38 -0
  66. package/dist/caamp/capability-check.js.map +1 -0
  67. package/dist/caamp/index.js +21 -0
  68. package/dist/caamp/index.js.map +1 -0
  69. package/dist/caamp-init.js +16 -0
  70. package/dist/caamp-init.js.map +1 -0
  71. package/dist/cleo.js +322 -0
  72. package/dist/cleo.js.map +1 -0
  73. package/dist/code/index.js +14 -0
  74. package/dist/code/index.js.map +1 -0
  75. package/dist/code/outline.js +165 -0
  76. package/dist/code/outline.js.map +1 -0
  77. package/dist/code/parser.js +420 -0
  78. package/dist/code/parser.js.map +1 -0
  79. package/dist/code/search.js +135 -0
  80. package/dist/code/search.js.map +1 -0
  81. package/dist/code/unfold.js +155 -0
  82. package/dist/code/unfold.js.map +1 -0
  83. package/dist/codebase-map/analyzers/architecture.js +129 -0
  84. package/dist/codebase-map/analyzers/architecture.js.map +1 -0
  85. package/dist/codebase-map/analyzers/concerns.js +122 -0
  86. package/dist/codebase-map/analyzers/concerns.js.map +1 -0
  87. package/dist/codebase-map/analyzers/conventions.js +149 -0
  88. package/dist/codebase-map/analyzers/conventions.js.map +1 -0
  89. package/dist/codebase-map/analyzers/integrations.js +108 -0
  90. package/dist/codebase-map/analyzers/integrations.js.map +1 -0
  91. package/dist/codebase-map/analyzers/stack.js +117 -0
  92. package/dist/codebase-map/analyzers/stack.js.map +1 -0
  93. package/dist/codebase-map/analyzers/structure.js +137 -0
  94. package/dist/codebase-map/analyzers/structure.js.map +1 -0
  95. package/dist/codebase-map/analyzers/testing.js +118 -0
  96. package/dist/codebase-map/analyzers/testing.js.map +1 -0
  97. package/dist/codebase-map/index.js +57 -0
  98. package/dist/codebase-map/index.js.map +1 -0
  99. package/dist/codebase-map/store.js +122 -0
  100. package/dist/codebase-map/store.js.map +1 -0
  101. package/dist/codebase-map/summary.js +152 -0
  102. package/dist/codebase-map/summary.js.map +1 -0
  103. package/dist/compliance/index.js +288 -0
  104. package/dist/compliance/index.js.map +1 -0
  105. package/dist/compliance/protocol-enforcement.js +332 -0
  106. package/dist/compliance/protocol-enforcement.js.map +1 -0
  107. package/dist/compliance/protocol-rules.js +786 -0
  108. package/dist/compliance/protocol-rules.js.map +1 -0
  109. package/dist/compliance/protocol-types.js +79 -0
  110. package/dist/compliance/protocol-types.js.map +1 -0
  111. package/dist/compliance/store.js +53 -0
  112. package/dist/compliance/store.js.map +1 -0
  113. package/dist/conduit/conduit-client.js +107 -0
  114. package/dist/conduit/conduit-client.js.map +1 -0
  115. package/dist/conduit/factory.js +55 -0
  116. package/dist/conduit/factory.js.map +1 -0
  117. package/dist/conduit/http-transport.js +155 -0
  118. package/dist/conduit/http-transport.js.map +1 -0
  119. package/dist/conduit/local-transport.js +255 -0
  120. package/dist/conduit/local-transport.js.map +1 -0
  121. package/dist/conduit/sse-transport.js +299 -0
  122. package/dist/conduit/sse-transport.js.map +1 -0
  123. package/dist/config/build-config.js +29 -0
  124. package/dist/config/build-config.js.map +1 -0
  125. package/dist/config.js +407 -0
  126. package/dist/config.js.map +1 -0
  127. package/dist/constants.js +18 -0
  128. package/dist/constants.js.map +1 -0
  129. package/dist/context/index.js +137 -0
  130. package/dist/context/index.js.map +1 -0
  131. package/dist/crypto/credentials.js +219 -0
  132. package/dist/crypto/credentials.js.map +1 -0
  133. package/dist/discovery.js +182 -0
  134. package/dist/discovery.js.map +1 -0
  135. package/dist/engine-result.js +12 -0
  136. package/dist/engine-result.js.map +1 -0
  137. package/dist/error-catalog.js +404 -0
  138. package/dist/error-catalog.js.map +1 -0
  139. package/dist/error-registry.js +393 -0
  140. package/dist/error-registry.js.map +1 -0
  141. package/dist/errors.js +173 -0
  142. package/dist/errors.js.map +1 -0
  143. package/dist/hooks/handlers/agent-hooks.js +106 -0
  144. package/dist/hooks/handlers/agent-hooks.js.map +1 -0
  145. package/dist/hooks/handlers/conduit-hooks.js +229 -0
  146. package/dist/hooks/handlers/conduit-hooks.js.map +1 -0
  147. package/dist/hooks/handlers/context-hooks.js +111 -0
  148. package/dist/hooks/handlers/context-hooks.js.map +1 -0
  149. package/dist/hooks/handlers/error-hooks.js +52 -0
  150. package/dist/hooks/handlers/error-hooks.js.map +1 -0
  151. package/dist/hooks/handlers/file-hooks.js +104 -0
  152. package/dist/hooks/handlers/file-hooks.js.map +1 -0
  153. package/dist/hooks/handlers/handler-helpers.js +61 -0
  154. package/dist/hooks/handlers/handler-helpers.js.map +1 -0
  155. package/dist/hooks/handlers/index.js +37 -0
  156. package/dist/hooks/handlers/index.js.map +1 -0
  157. package/dist/hooks/handlers/intelligence-hooks.js +69 -0
  158. package/dist/hooks/handlers/intelligence-hooks.js.map +1 -0
  159. package/dist/hooks/handlers/memory-bridge-refresh.js +42 -0
  160. package/dist/hooks/handlers/memory-bridge-refresh.js.map +1 -0
  161. package/dist/hooks/handlers/notification-hooks.js +62 -0
  162. package/dist/hooks/handlers/notification-hooks.js.map +1 -0
  163. package/dist/hooks/handlers/session-hooks.js +190 -0
  164. package/dist/hooks/handlers/session-hooks.js.map +1 -0
  165. package/dist/hooks/handlers/task-hooks.js +90 -0
  166. package/dist/hooks/handlers/task-hooks.js.map +1 -0
  167. package/dist/hooks/handlers/watchdog-hooks.js +162 -0
  168. package/dist/hooks/handlers/watchdog-hooks.js.map +1 -0
  169. package/dist/hooks/handlers/work-capture-hooks.js +165 -0
  170. package/dist/hooks/handlers/work-capture-hooks.js.map +1 -0
  171. package/dist/hooks/index.js +13 -0
  172. package/dist/hooks/index.js.map +1 -0
  173. package/dist/hooks/payload-schemas.js +220 -0
  174. package/dist/hooks/payload-schemas.js.map +1 -0
  175. package/dist/hooks/provider-hooks.js +66 -0
  176. package/dist/hooks/provider-hooks.js.map +1 -0
  177. package/dist/hooks/registry.js +229 -0
  178. package/dist/hooks/registry.js.map +1 -0
  179. package/dist/hooks/types.js +66 -0
  180. package/dist/hooks/types.js.map +1 -0
  181. package/dist/hooks.js +136 -0
  182. package/dist/hooks.js.map +1 -0
  183. package/dist/init.js +959 -0
  184. package/dist/init.js.map +1 -0
  185. package/dist/inject/index.js +82 -0
  186. package/dist/inject/index.js.map +1 -0
  187. package/dist/injection.js +377 -0
  188. package/dist/injection.js.map +1 -0
  189. package/dist/intelligence/adaptive-validation.js +497 -0
  190. package/dist/intelligence/adaptive-validation.js.map +1 -0
  191. package/dist/intelligence/impact.js +675 -0
  192. package/dist/intelligence/impact.js.map +1 -0
  193. package/dist/intelligence/index.js +22 -0
  194. package/dist/intelligence/index.js.map +1 -0
  195. package/dist/intelligence/patterns.js +492 -0
  196. package/dist/intelligence/patterns.js.map +1 -0
  197. package/dist/intelligence/prediction.js +499 -0
  198. package/dist/intelligence/prediction.js.map +1 -0
  199. package/dist/intelligence/types.js +13 -0
  200. package/dist/intelligence/types.js.map +1 -0
  201. package/dist/issue/create.js +121 -0
  202. package/dist/issue/create.js.map +1 -0
  203. package/dist/issue/diagnostics.js +59 -0
  204. package/dist/issue/diagnostics.js.map +1 -0
  205. package/dist/issue/index.js +10 -0
  206. package/dist/issue/index.js.map +1 -0
  207. package/dist/issue/template-parser.js +267 -0
  208. package/dist/issue/template-parser.js.map +1 -0
  209. package/dist/json-schema-validator.js +76 -0
  210. package/dist/json-schema-validator.js.map +1 -0
  211. package/dist/lib/index.js +11 -0
  212. package/dist/lib/index.js.map +1 -0
  213. package/dist/lib/retry.js +152 -0
  214. package/dist/lib/retry.js.map +1 -0
  215. package/dist/lib/tree-sitter-languages.js +75 -0
  216. package/dist/lib/tree-sitter-languages.js.map +1 -0
  217. package/dist/lifecycle/chain-composition.js +152 -0
  218. package/dist/lifecycle/chain-composition.js.map +1 -0
  219. package/dist/lifecycle/chain-store.js +246 -0
  220. package/dist/lifecycle/chain-store.js.map +1 -0
  221. package/dist/lifecycle/consolidate-rcasd.js +352 -0
  222. package/dist/lifecycle/consolidate-rcasd.js.map +1 -0
  223. package/dist/lifecycle/default-chain.js +176 -0
  224. package/dist/lifecycle/default-chain.js.map +1 -0
  225. package/dist/lifecycle/evidence.js +180 -0
  226. package/dist/lifecycle/evidence.js.map +1 -0
  227. package/dist/lifecycle/frontmatter.js +363 -0
  228. package/dist/lifecycle/frontmatter.js.map +1 -0
  229. package/dist/lifecycle/index.js +756 -0
  230. package/dist/lifecycle/index.js.map +1 -0
  231. package/dist/lifecycle/pipeline.js +656 -0
  232. package/dist/lifecycle/pipeline.js.map +1 -0
  233. package/dist/lifecycle/rcasd-index.js +326 -0
  234. package/dist/lifecycle/rcasd-index.js.map +1 -0
  235. package/dist/lifecycle/rcasd-paths.js +220 -0
  236. package/dist/lifecycle/rcasd-paths.js.map +1 -0
  237. package/dist/lifecycle/resume.js +864 -0
  238. package/dist/lifecycle/resume.js.map +1 -0
  239. package/dist/lifecycle/stage-artifacts.js +94 -0
  240. package/dist/lifecycle/stage-artifacts.js.map +1 -0
  241. package/dist/lifecycle/stage-guidance.js +234 -0
  242. package/dist/lifecycle/stage-guidance.js.map +1 -0
  243. package/dist/lifecycle/stages.js +534 -0
  244. package/dist/lifecycle/stages.js.map +1 -0
  245. package/dist/lifecycle/state-machine.js +516 -0
  246. package/dist/lifecycle/state-machine.js.map +1 -0
  247. package/dist/lifecycle/tessera-engine.js +249 -0
  248. package/dist/lifecycle/tessera-engine.js.map +1 -0
  249. package/dist/logger.js +140 -0
  250. package/dist/logger.js.map +1 -0
  251. package/dist/memory/anthropic-key-resolver.js +105 -0
  252. package/dist/memory/anthropic-key-resolver.js.map +1 -0
  253. package/dist/memory/auto-extract.js +77 -0
  254. package/dist/memory/auto-extract.js.map +1 -0
  255. package/dist/memory/brain-backfill.js +389 -0
  256. package/dist/memory/brain-backfill.js.map +1 -0
  257. package/dist/memory/brain-consolidator.js +294 -0
  258. package/dist/memory/brain-consolidator.js.map +1 -0
  259. package/dist/memory/brain-embedding.js +66 -0
  260. package/dist/memory/brain-embedding.js.map +1 -0
  261. package/dist/memory/brain-export.js +239 -0
  262. package/dist/memory/brain-export.js.map +1 -0
  263. package/dist/memory/brain-lifecycle.js +841 -0
  264. package/dist/memory/brain-lifecycle.js.map +1 -0
  265. package/dist/memory/brain-links.js +161 -0
  266. package/dist/memory/brain-links.js.map +1 -0
  267. package/dist/memory/brain-maintenance.js +125 -0
  268. package/dist/memory/brain-maintenance.js.map +1 -0
  269. package/dist/memory/brain-migration.js +149 -0
  270. package/dist/memory/brain-migration.js.map +1 -0
  271. package/dist/memory/brain-purge.js +243 -0
  272. package/dist/memory/brain-purge.js.map +1 -0
  273. package/dist/memory/brain-reasoning.js +215 -0
  274. package/dist/memory/brain-reasoning.js.map +1 -0
  275. package/dist/memory/brain-retrieval.js +1088 -0
  276. package/dist/memory/brain-retrieval.js.map +1 -0
  277. package/dist/memory/brain-row-types.js +10 -0
  278. package/dist/memory/brain-row-types.js.map +1 -0
  279. package/dist/memory/brain-search.js +613 -0
  280. package/dist/memory/brain-search.js.map +1 -0
  281. package/dist/memory/brain-similarity.js +145 -0
  282. package/dist/memory/brain-similarity.js.map +1 -0
  283. package/dist/memory/brain-stdp.js +297 -0
  284. package/dist/memory/brain-stdp.js.map +1 -0
  285. package/dist/memory/claude-mem-migration.js +277 -0
  286. package/dist/memory/claude-mem-migration.js.map +1 -0
  287. package/dist/memory/decision-cross-link.js +228 -0
  288. package/dist/memory/decision-cross-link.js.map +1 -0
  289. package/dist/memory/decisions.js +242 -0
  290. package/dist/memory/decisions.js.map +1 -0
  291. package/dist/memory/edge-types.js +31 -0
  292. package/dist/memory/edge-types.js.map +1 -0
  293. package/dist/memory/embedding-local.js +102 -0
  294. package/dist/memory/embedding-local.js.map +1 -0
  295. package/dist/memory/embedding-queue.js +271 -0
  296. package/dist/memory/embedding-queue.js.map +1 -0
  297. package/dist/memory/embedding-worker.js +58 -0
  298. package/dist/memory/embedding-worker.js.map +1 -0
  299. package/dist/memory/engine-compat.js +1597 -0
  300. package/dist/memory/engine-compat.js.map +1 -0
  301. package/dist/memory/extraction-gate.js +459 -0
  302. package/dist/memory/extraction-gate.js.map +1 -0
  303. package/dist/memory/graph-auto-populate.js +148 -0
  304. package/dist/memory/graph-auto-populate.js.map +1 -0
  305. package/dist/memory/graph-memory-bridge.js +517 -0
  306. package/dist/memory/graph-memory-bridge.js.map +1 -0
  307. package/dist/memory/graph-queries.js +290 -0
  308. package/dist/memory/graph-queries.js.map +1 -0
  309. package/dist/memory/index.js +1148 -0
  310. package/dist/memory/index.js.map +1 -0
  311. package/dist/memory/learnings.js +197 -0
  312. package/dist/memory/learnings.js.map +1 -0
  313. package/dist/memory/llm-extraction.js +425 -0
  314. package/dist/memory/llm-extraction.js.map +1 -0
  315. package/dist/memory/memory-bridge.js +382 -0
  316. package/dist/memory/memory-bridge.js.map +1 -0
  317. package/dist/memory/mental-model-injection.js +61 -0
  318. package/dist/memory/mental-model-injection.js.map +1 -0
  319. package/dist/memory/mental-model-queue.js +211 -0
  320. package/dist/memory/mental-model-queue.js.map +1 -0
  321. package/dist/memory/observer-reflector.js +626 -0
  322. package/dist/memory/observer-reflector.js.map +1 -0
  323. package/dist/memory/patterns.js +192 -0
  324. package/dist/memory/patterns.js.map +1 -0
  325. package/dist/memory/pipeline-manifest-sqlite.js +975 -0
  326. package/dist/memory/pipeline-manifest-sqlite.js.map +1 -0
  327. package/dist/memory/quality-feedback.js +449 -0
  328. package/dist/memory/quality-feedback.js.map +1 -0
  329. package/dist/memory/quality-scoring.js +182 -0
  330. package/dist/memory/quality-scoring.js.map +1 -0
  331. package/dist/memory/session-memory.js +331 -0
  332. package/dist/memory/session-memory.js.map +1 -0
  333. package/dist/memory/sleep-consolidation.js +706 -0
  334. package/dist/memory/sleep-consolidation.js.map +1 -0
  335. package/dist/memory/temporal-supersession.js +403 -0
  336. package/dist/memory/temporal-supersession.js.map +1 -0
  337. package/dist/metrics/ab-test.js +260 -0
  338. package/dist/metrics/ab-test.js.map +1 -0
  339. package/dist/metrics/aggregation.js +363 -0
  340. package/dist/metrics/aggregation.js.map +1 -0
  341. package/dist/metrics/common.js +64 -0
  342. package/dist/metrics/common.js.map +1 -0
  343. package/dist/metrics/enums.js +78 -0
  344. package/dist/metrics/enums.js.map +1 -0
  345. package/dist/metrics/index.js +19 -0
  346. package/dist/metrics/index.js.map +1 -0
  347. package/dist/metrics/model-provider-registry.js +88 -0
  348. package/dist/metrics/model-provider-registry.js.map +1 -0
  349. package/dist/metrics/otel-integration.js +263 -0
  350. package/dist/metrics/otel-integration.js.map +1 -0
  351. package/dist/metrics/provider-detection.js +103 -0
  352. package/dist/metrics/provider-detection.js.map +1 -0
  353. package/dist/metrics/token-estimation.js +253 -0
  354. package/dist/metrics/token-estimation.js.map +1 -0
  355. package/dist/metrics/token-service.js +450 -0
  356. package/dist/metrics/token-service.js.map +1 -0
  357. package/dist/migration/agent-outputs.js +316 -0
  358. package/dist/migration/agent-outputs.js.map +1 -0
  359. package/dist/migration/checksum.js +92 -0
  360. package/dist/migration/checksum.js.map +1 -0
  361. package/dist/migration/index.js +282 -0
  362. package/dist/migration/index.js.map +1 -0
  363. package/dist/migration/logger.js +360 -0
  364. package/dist/migration/logger.js.map +1 -0
  365. package/dist/migration/preflight.js +9 -0
  366. package/dist/migration/preflight.js.map +1 -0
  367. package/dist/migration/state.js +421 -0
  368. package/dist/migration/state.js.map +1 -0
  369. package/dist/migration/validate.js +241 -0
  370. package/dist/migration/validate.js.map +1 -0
  371. package/dist/mvi-helpers.js +73 -0
  372. package/dist/mvi-helpers.js.map +1 -0
  373. package/dist/nexus/deps.js +375 -0
  374. package/dist/nexus/deps.js.map +1 -0
  375. package/dist/nexus/discover.js +288 -0
  376. package/dist/nexus/discover.js.map +1 -0
  377. package/dist/nexus/hash.js +10 -0
  378. package/dist/nexus/hash.js.map +1 -0
  379. package/dist/nexus/index.js +40 -0
  380. package/dist/nexus/index.js.map +1 -0
  381. package/dist/nexus/migrate-json-to-sqlite.js +115 -0
  382. package/dist/nexus/migrate-json-to-sqlite.js.map +1 -0
  383. package/dist/nexus/nexus-bridge.js +321 -0
  384. package/dist/nexus/nexus-bridge.js.map +1 -0
  385. package/dist/nexus/permissions.js +105 -0
  386. package/dist/nexus/permissions.js.map +1 -0
  387. package/dist/nexus/query.js +175 -0
  388. package/dist/nexus/query.js.map +1 -0
  389. package/dist/nexus/registry.js +665 -0
  390. package/dist/nexus/registry.js.map +1 -0
  391. package/dist/nexus/sharing/index.js +288 -0
  392. package/dist/nexus/sharing/index.js.map +1 -0
  393. package/dist/nexus/transfer-types.js +8 -0
  394. package/dist/nexus/transfer-types.js.map +1 -0
  395. package/dist/nexus/transfer.js +271 -0
  396. package/dist/nexus/transfer.js.map +1 -0
  397. package/dist/nexus/workspace.js +355 -0
  398. package/dist/nexus/workspace.js.map +1 -0
  399. package/dist/observability/index.js +103 -0
  400. package/dist/observability/index.js.map +1 -0
  401. package/dist/observability/log-filter.js +63 -0
  402. package/dist/observability/log-filter.js.map +1 -0
  403. package/dist/observability/log-parser.js +99 -0
  404. package/dist/observability/log-parser.js.map +1 -0
  405. package/dist/observability/log-reader.js +139 -0
  406. package/dist/observability/log-reader.js.map +1 -0
  407. package/dist/observability/types.js +19 -0
  408. package/dist/observability/types.js.map +1 -0
  409. package/dist/orchestration/analyze.js +107 -0
  410. package/dist/orchestration/analyze.js.map +1 -0
  411. package/dist/orchestration/bootstrap.js +132 -0
  412. package/dist/orchestration/bootstrap.js.map +1 -0
  413. package/dist/orchestration/context.js +56 -0
  414. package/dist/orchestration/context.js.map +1 -0
  415. package/dist/orchestration/critical-path.js +100 -0
  416. package/dist/orchestration/critical-path.js.map +1 -0
  417. package/dist/orchestration/hierarchy.js +183 -0
  418. package/dist/orchestration/hierarchy.js.map +1 -0
  419. package/dist/orchestration/index.js +287 -0
  420. package/dist/orchestration/index.js.map +1 -0
  421. package/dist/orchestration/parallel.js +89 -0
  422. package/dist/orchestration/parallel.js.map +1 -0
  423. package/dist/orchestration/protocol-validators.js +815 -0
  424. package/dist/orchestration/protocol-validators.js.map +1 -0
  425. package/dist/orchestration/skill-ops.js +98 -0
  426. package/dist/orchestration/skill-ops.js.map +1 -0
  427. package/dist/orchestration/status.js +107 -0
  428. package/dist/orchestration/status.js.map +1 -0
  429. package/dist/orchestration/unblock.js +103 -0
  430. package/dist/orchestration/unblock.js.map +1 -0
  431. package/dist/orchestration/validate-spawn.js +67 -0
  432. package/dist/orchestration/validate-spawn.js.map +1 -0
  433. package/dist/orchestration/waves.js +86 -0
  434. package/dist/orchestration/waves.js.map +1 -0
  435. package/dist/otel/index.js +163 -0
  436. package/dist/otel/index.js.map +1 -0
  437. package/dist/output.js +164 -0
  438. package/dist/output.js.map +1 -0
  439. package/dist/pagination.js +64 -0
  440. package/dist/pagination.js.map +1 -0
  441. package/dist/paths.js +882 -0
  442. package/dist/paths.js.map +1 -0
  443. package/dist/phases/deps.js +372 -0
  444. package/dist/phases/deps.js.map +1 -0
  445. package/dist/phases/index.js +349 -0
  446. package/dist/phases/index.js.map +1 -0
  447. package/dist/pipeline/index.js +10 -0
  448. package/dist/pipeline/index.js.map +1 -0
  449. package/dist/pipeline/phase.js +45 -0
  450. package/dist/pipeline/phase.js.map +1 -0
  451. package/dist/platform.js +211 -0
  452. package/dist/platform.js.map +1 -0
  453. package/dist/project-info.js +84 -0
  454. package/dist/project-info.js.map +1 -0
  455. package/dist/reconciliation/index.js +10 -0
  456. package/dist/reconciliation/index.js.map +1 -0
  457. package/dist/reconciliation/link-store.js +175 -0
  458. package/dist/reconciliation/link-store.js.map +1 -0
  459. package/dist/reconciliation/reconciliation-engine.js +298 -0
  460. package/dist/reconciliation/reconciliation-engine.js.map +1 -0
  461. package/dist/release/artifacts.js +427 -0
  462. package/dist/release/artifacts.js.map +1 -0
  463. package/dist/release/changelog-writer.js +151 -0
  464. package/dist/release/changelog-writer.js.map +1 -0
  465. package/dist/release/channel.js +144 -0
  466. package/dist/release/channel.js.map +1 -0
  467. package/dist/release/ci.js +166 -0
  468. package/dist/release/ci.js.map +1 -0
  469. package/dist/release/github-pr.js +225 -0
  470. package/dist/release/github-pr.js.map +1 -0
  471. package/dist/release/guards.js +116 -0
  472. package/dist/release/guards.js.map +1 -0
  473. package/dist/release/index.js +22 -0
  474. package/dist/release/index.js.map +1 -0
  475. package/dist/release/release-config.js +158 -0
  476. package/dist/release/release-config.js.map +1 -0
  477. package/dist/release/release-manifest.js +1019 -0
  478. package/dist/release/release-manifest.js.map +1 -0
  479. package/dist/release/version-bump.js +255 -0
  480. package/dist/release/version-bump.js.map +1 -0
  481. package/dist/remote/index.js +257 -0
  482. package/dist/remote/index.js.map +1 -0
  483. package/dist/repair.js +130 -0
  484. package/dist/repair.js.map +1 -0
  485. package/dist/research/index.js +2 -0
  486. package/dist/research/index.js.map +1 -0
  487. package/dist/roadmap/index.js +59 -0
  488. package/dist/roadmap/index.js.map +1 -0
  489. package/dist/routing/capability-matrix.js +1556 -0
  490. package/dist/routing/capability-matrix.js.map +1 -0
  491. package/dist/routing/index.js +9 -0
  492. package/dist/routing/index.js.map +1 -0
  493. package/dist/scaffold.js +1937 -0
  494. package/dist/scaffold.js.map +1 -0
  495. package/dist/schema-management.js +295 -0
  496. package/dist/schema-management.js.map +1 -0
  497. package/dist/security/index.js +9 -0
  498. package/dist/security/index.js.map +1 -0
  499. package/dist/security/input-sanitization.js +326 -0
  500. package/dist/security/input-sanitization.js.map +1 -0
  501. package/dist/sequence/index.js +295 -0
  502. package/dist/sequence/index.js.map +1 -0
  503. package/dist/sessions/assumptions.js +54 -0
  504. package/dist/sessions/assumptions.js.map +1 -0
  505. package/dist/sessions/briefing.js +377 -0
  506. package/dist/sessions/briefing.js.map +1 -0
  507. package/dist/sessions/context-alert.js +222 -0
  508. package/dist/sessions/context-alert.js.map +1 -0
  509. package/dist/sessions/context-inject.js +61 -0
  510. package/dist/sessions/context-inject.js.map +1 -0
  511. package/dist/sessions/context-monitor.js +98 -0
  512. package/dist/sessions/context-monitor.js.map +1 -0
  513. package/dist/sessions/decisions.js +65 -0
  514. package/dist/sessions/decisions.js.map +1 -0
  515. package/dist/sessions/find.js +65 -0
  516. package/dist/sessions/find.js.map +1 -0
  517. package/dist/sessions/handoff.js +328 -0
  518. package/dist/sessions/handoff.js.map +1 -0
  519. package/dist/sessions/hitl-warnings.js +254 -0
  520. package/dist/sessions/hitl-warnings.js.map +1 -0
  521. package/dist/sessions/index.js +327 -0
  522. package/dist/sessions/index.js.map +1 -0
  523. package/dist/sessions/session-archive.js +40 -0
  524. package/dist/sessions/session-archive.js.map +1 -0
  525. package/dist/sessions/session-cleanup.js +59 -0
  526. package/dist/sessions/session-cleanup.js.map +1 -0
  527. package/dist/sessions/session-drift.js +134 -0
  528. package/dist/sessions/session-drift.js.map +1 -0
  529. package/dist/sessions/session-enforcement.js +144 -0
  530. package/dist/sessions/session-enforcement.js.map +1 -0
  531. package/dist/sessions/session-grade.js +253 -0
  532. package/dist/sessions/session-grade.js.map +1 -0
  533. package/dist/sessions/session-history.js +42 -0
  534. package/dist/sessions/session-history.js.map +1 -0
  535. package/dist/sessions/session-id.js +81 -0
  536. package/dist/sessions/session-id.js.map +1 -0
  537. package/dist/sessions/session-memory-bridge.js +30 -0
  538. package/dist/sessions/session-memory-bridge.js.map +1 -0
  539. package/dist/sessions/session-show.js +24 -0
  540. package/dist/sessions/session-show.js.map +1 -0
  541. package/dist/sessions/session-stats.js +69 -0
  542. package/dist/sessions/session-stats.js.map +1 -0
  543. package/dist/sessions/session-suspend.js +39 -0
  544. package/dist/sessions/session-suspend.js.map +1 -0
  545. package/dist/sessions/session-switch.js +51 -0
  546. package/dist/sessions/session-switch.js.map +1 -0
  547. package/dist/sessions/session-view.js +76 -0
  548. package/dist/sessions/session-view.js.map +1 -0
  549. package/dist/sessions/snapshot.js +213 -0
  550. package/dist/sessions/snapshot.js.map +1 -0
  551. package/dist/sessions/statusline-setup.js +85 -0
  552. package/dist/sessions/statusline-setup.js.map +1 -0
  553. package/dist/sessions/types.js +8 -0
  554. package/dist/sessions/types.js.map +1 -0
  555. package/dist/skills/agents/config.js +94 -0
  556. package/dist/skills/agents/config.js.map +1 -0
  557. package/dist/skills/agents/install.js +116 -0
  558. package/dist/skills/agents/install.js.map +1 -0
  559. package/dist/skills/agents/registry.js +161 -0
  560. package/dist/skills/agents/registry.js.map +1 -0
  561. package/dist/skills/discovery.js +333 -0
  562. package/dist/skills/discovery.js.map +1 -0
  563. package/dist/skills/dispatch.js +347 -0
  564. package/dist/skills/dispatch.js.map +1 -0
  565. package/dist/skills/dynamic-skill-generator.js +87 -0
  566. package/dist/skills/dynamic-skill-generator.js.map +1 -0
  567. package/dist/skills/index.js +44 -0
  568. package/dist/skills/index.js.map +1 -0
  569. package/dist/skills/injection/subagent.js +195 -0
  570. package/dist/skills/injection/subagent.js.map +1 -0
  571. package/dist/skills/injection/token.js +260 -0
  572. package/dist/skills/injection/token.js.map +1 -0
  573. package/dist/skills/install.js +40 -0
  574. package/dist/skills/install.js.map +1 -0
  575. package/dist/skills/manifests/contribution.js +175 -0
  576. package/dist/skills/manifests/contribution.js.map +1 -0
  577. package/dist/skills/manifests/research.js +281 -0
  578. package/dist/skills/manifests/research.js.map +1 -0
  579. package/dist/skills/manifests/resolver.js +146 -0
  580. package/dist/skills/manifests/resolver.js.map +1 -0
  581. package/dist/skills/marketplace.js +90 -0
  582. package/dist/skills/marketplace.js.map +1 -0
  583. package/dist/skills/orchestrator/spawn.js +178 -0
  584. package/dist/skills/orchestrator/spawn.js.map +1 -0
  585. package/dist/skills/orchestrator/startup.js +451 -0
  586. package/dist/skills/orchestrator/startup.js.map +1 -0
  587. package/dist/skills/orchestrator/validator.js +301 -0
  588. package/dist/skills/orchestrator/validator.js.map +1 -0
  589. package/dist/skills/precedence-integration.js +73 -0
  590. package/dist/skills/precedence-integration.js.map +1 -0
  591. package/dist/skills/precedence-types.js +16 -0
  592. package/dist/skills/precedence-types.js.map +1 -0
  593. package/dist/skills/routing-table.js +63 -0
  594. package/dist/skills/routing-table.js.map +1 -0
  595. package/dist/skills/skill-paths.js +217 -0
  596. package/dist/skills/skill-paths.js.map +1 -0
  597. package/dist/skills/test-utility.js +55 -0
  598. package/dist/skills/test-utility.js.map +1 -0
  599. package/dist/skills/types.js +118 -0
  600. package/dist/skills/types.js.map +1 -0
  601. package/dist/skills/validation.js +183 -0
  602. package/dist/skills/validation.js.map +1 -0
  603. package/dist/skills/version.js +57 -0
  604. package/dist/skills/version.js.map +1 -0
  605. package/dist/snapshot/index.js +188 -0
  606. package/dist/snapshot/index.js.map +1 -0
  607. package/dist/spawn/adapter-registry.js +246 -0
  608. package/dist/spawn/adapter-registry.js.map +1 -0
  609. package/dist/spawn/index.js +10 -0
  610. package/dist/spawn/index.js.map +1 -0
  611. package/dist/stats/index.js +350 -0
  612. package/dist/stats/index.js.map +1 -0
  613. package/dist/stats/workflow-telemetry.js +400 -0
  614. package/dist/stats/workflow-telemetry.js.map +1 -0
  615. package/dist/sticky/archive.js +47 -0
  616. package/dist/sticky/archive.js.map +1 -0
  617. package/dist/sticky/convert.js +235 -0
  618. package/dist/sticky/convert.js.map +1 -0
  619. package/dist/sticky/create.js +48 -0
  620. package/dist/sticky/create.js.map +1 -0
  621. package/dist/sticky/id.js +35 -0
  622. package/dist/sticky/id.js.map +1 -0
  623. package/dist/sticky/index.js +16 -0
  624. package/dist/sticky/index.js.map +1 -0
  625. package/dist/sticky/list.js +57 -0
  626. package/dist/sticky/list.js.map +1 -0
  627. package/dist/sticky/purge.js +45 -0
  628. package/dist/sticky/purge.js.map +1 -0
  629. package/dist/sticky/show.js +42 -0
  630. package/dist/sticky/show.js.map +1 -0
  631. package/dist/sticky/types.js +10 -0
  632. package/dist/sticky/types.js.map +1 -0
  633. package/dist/store/agent-registry-accessor.js +886 -0
  634. package/dist/store/agent-registry-accessor.js.map +1 -0
  635. package/dist/store/api-key-kdf.js +84 -0
  636. package/dist/store/api-key-kdf.js.map +1 -0
  637. package/dist/store/atomic.js +167 -0
  638. package/dist/store/atomic.js.map +1 -0
  639. package/dist/store/backup-crypto.js +184 -0
  640. package/dist/store/backup-crypto.js.map +1 -0
  641. package/dist/store/backup-pack.js +581 -0
  642. package/dist/store/backup-pack.js.map +1 -0
  643. package/dist/store/backup-unpack.js +449 -0
  644. package/dist/store/backup-unpack.js.map +1 -0
  645. package/dist/store/backup.js +94 -0
  646. package/dist/store/backup.js.map +1 -0
  647. package/dist/store/brain-accessor.js +429 -0
  648. package/dist/store/brain-accessor.js.map +1 -0
  649. package/dist/store/brain-schema.js +628 -0
  650. package/dist/store/brain-schema.js.map +1 -0
  651. package/dist/store/brain-sqlite.js +320 -0
  652. package/dist/store/brain-sqlite.js.map +1 -0
  653. package/dist/store/cache.js +168 -0
  654. package/dist/store/cache.js.map +1 -0
  655. package/dist/store/chain-schema.js +51 -0
  656. package/dist/store/chain-schema.js.map +1 -0
  657. package/dist/store/cleanup-legacy.js +171 -0
  658. package/dist/store/cleanup-legacy.js.map +1 -0
  659. package/dist/store/conduit-sqlite.js +570 -0
  660. package/dist/store/conduit-sqlite.js.map +1 -0
  661. package/dist/store/converters.js +124 -0
  662. package/dist/store/converters.js.map +1 -0
  663. package/dist/store/cross-db-cleanup.js +319 -0
  664. package/dist/store/cross-db-cleanup.js.map +1 -0
  665. package/dist/store/data-accessor.js +26 -0
  666. package/dist/store/data-accessor.js.map +1 -0
  667. package/dist/store/data-safety-central.js +269 -0
  668. package/dist/store/data-safety-central.js.map +1 -0
  669. package/dist/store/data-safety.js +274 -0
  670. package/dist/store/data-safety.js.map +1 -0
  671. package/dist/store/db-helpers.js +241 -0
  672. package/dist/store/db-helpers.js.map +1 -0
  673. package/dist/store/export.js +155 -0
  674. package/dist/store/export.js.map +1 -0
  675. package/dist/store/file-utils.js +270 -0
  676. package/dist/store/file-utils.js.map +1 -0
  677. package/dist/store/git-checkpoint.js +365 -0
  678. package/dist/store/git-checkpoint.js.map +1 -0
  679. package/dist/store/global-salt.js +147 -0
  680. package/dist/store/global-salt.js.map +1 -0
  681. package/dist/store/import-logging.js +139 -0
  682. package/dist/store/import-logging.js.map +1 -0
  683. package/dist/store/import-remap.js +145 -0
  684. package/dist/store/import-remap.js.map +1 -0
  685. package/dist/store/import-sort.js +121 -0
  686. package/dist/store/import-sort.js.map +1 -0
  687. package/dist/store/index.js +29 -0
  688. package/dist/store/index.js.map +1 -0
  689. package/dist/store/json.js +208 -0
  690. package/dist/store/json.js.map +1 -0
  691. package/dist/store/lifecycle-store.js +249 -0
  692. package/dist/store/lifecycle-store.js.map +1 -0
  693. package/dist/store/lock.js +70 -0
  694. package/dist/store/lock.js.map +1 -0
  695. package/dist/store/migrate-signaldock-to-conduit.js +562 -0
  696. package/dist/store/migrate-signaldock-to-conduit.js.map +1 -0
  697. package/dist/store/migration-manager.js +403 -0
  698. package/dist/store/migration-manager.js.map +1 -0
  699. package/dist/store/migration-sqlite.js +676 -0
  700. package/dist/store/migration-sqlite.js.map +1 -0
  701. package/dist/store/nexus-schema.js +277 -0
  702. package/dist/store/nexus-schema.js.map +1 -0
  703. package/dist/store/nexus-sqlite.js +242 -0
  704. package/dist/store/nexus-sqlite.js.map +1 -0
  705. package/dist/store/nexus-validation-schemas.js +40 -0
  706. package/dist/store/nexus-validation-schemas.js.map +1 -0
  707. package/dist/store/parsers.js +37 -0
  708. package/dist/store/parsers.js.map +1 -0
  709. package/dist/store/project-detect.js +457 -0
  710. package/dist/store/project-detect.js.map +1 -0
  711. package/dist/store/provider.js +101 -0
  712. package/dist/store/provider.js.map +1 -0
  713. package/dist/store/regenerators.js +207 -0
  714. package/dist/store/regenerators.js.map +1 -0
  715. package/dist/store/restore-conflict-report.js +206 -0
  716. package/dist/store/restore-conflict-report.js.map +1 -0
  717. package/dist/store/restore-json-merge.js +454 -0
  718. package/dist/store/restore-json-merge.js.map +1 -0
  719. package/dist/store/safety-data-accessor.js +257 -0
  720. package/dist/store/safety-data-accessor.js.map +1 -0
  721. package/dist/store/schema.js +7 -0
  722. package/dist/store/schema.js.map +1 -0
  723. package/dist/store/session-store.js +219 -0
  724. package/dist/store/session-store.js.map +1 -0
  725. package/dist/store/signaldock-sqlite.js +550 -0
  726. package/dist/store/signaldock-sqlite.js.map +1 -0
  727. package/dist/store/sqlite-backup.js +498 -0
  728. package/dist/store/sqlite-backup.js.map +1 -0
  729. package/dist/store/sqlite-data-accessor.js +788 -0
  730. package/dist/store/sqlite-data-accessor.js.map +1 -0
  731. package/dist/store/sqlite.js +483 -0
  732. package/dist/store/sqlite.js.map +1 -0
  733. package/dist/store/status-registry.js +8 -0
  734. package/dist/store/status-registry.js.map +1 -0
  735. package/dist/store/t310-readiness.js +115 -0
  736. package/dist/store/t310-readiness.js.map +1 -0
  737. package/dist/store/task-store.js +358 -0
  738. package/dist/store/task-store.js.map +1 -0
  739. package/dist/store/tasks-schema.js +610 -0
  740. package/dist/store/tasks-schema.js.map +1 -0
  741. package/dist/store/typed-query.js +15 -0
  742. package/dist/store/typed-query.js.map +1 -0
  743. package/dist/store/validation-schemas.js +278 -0
  744. package/dist/store/validation-schemas.js.map +1 -0
  745. package/dist/system/archive-analytics.js +277 -0
  746. package/dist/system/archive-analytics.js.map +1 -0
  747. package/dist/system/archive-stats.js +64 -0
  748. package/dist/system/archive-stats.js.map +1 -0
  749. package/dist/system/audit.js +145 -0
  750. package/dist/system/audit.js.map +1 -0
  751. package/dist/system/backup.js +280 -0
  752. package/dist/system/backup.js.map +1 -0
  753. package/dist/system/cleanup.js +134 -0
  754. package/dist/system/cleanup.js.map +1 -0
  755. package/dist/system/dependencies.js +466 -0
  756. package/dist/system/dependencies.js.map +1 -0
  757. package/dist/system/health.js +1207 -0
  758. package/dist/system/health.js.map +1 -0
  759. package/dist/system/index.js +18 -0
  760. package/dist/system/index.js.map +1 -0
  761. package/dist/system/inject-generate.js +122 -0
  762. package/dist/system/inject-generate.js.map +1 -0
  763. package/dist/system/labels.js +38 -0
  764. package/dist/system/labels.js.map +1 -0
  765. package/dist/system/metrics.js +61 -0
  766. package/dist/system/metrics.js.map +1 -0
  767. package/dist/system/migrate.js +43 -0
  768. package/dist/system/migrate.js.map +1 -0
  769. package/dist/system/platform-paths.js +80 -0
  770. package/dist/system/platform-paths.js.map +1 -0
  771. package/dist/system/runtime.js +161 -0
  772. package/dist/system/runtime.js.map +1 -0
  773. package/dist/system/safestop.js +89 -0
  774. package/dist/system/safestop.js.map +1 -0
  775. package/dist/system/storage-preflight.js +123 -0
  776. package/dist/system/storage-preflight.js.map +1 -0
  777. package/dist/task-work/index.js +159 -0
  778. package/dist/task-work/index.js.map +1 -0
  779. package/dist/tasks/add.js +837 -0
  780. package/dist/tasks/add.js.map +1 -0
  781. package/dist/tasks/analyze.js +85 -0
  782. package/dist/tasks/analyze.js.map +1 -0
  783. package/dist/tasks/archive.js +90 -0
  784. package/dist/tasks/archive.js.map +1 -0
  785. package/dist/tasks/atomicity.js +83 -0
  786. package/dist/tasks/atomicity.js.map +1 -0
  787. package/dist/tasks/cancel-ops.js +83 -0
  788. package/dist/tasks/cancel-ops.js.map +1 -0
  789. package/dist/tasks/complete.js +252 -0
  790. package/dist/tasks/complete.js.map +1 -0
  791. package/dist/tasks/crossref-extract.js +73 -0
  792. package/dist/tasks/crossref-extract.js.map +1 -0
  793. package/dist/tasks/delete-preview.js +192 -0
  794. package/dist/tasks/delete-preview.js.map +1 -0
  795. package/dist/tasks/delete.js +120 -0
  796. package/dist/tasks/delete.js.map +1 -0
  797. package/dist/tasks/deletion-strategy.js +200 -0
  798. package/dist/tasks/deletion-strategy.js.map +1 -0
  799. package/dist/tasks/dependency-check.js +278 -0
  800. package/dist/tasks/dependency-check.js.map +1 -0
  801. package/dist/tasks/deps-ready.js +32 -0
  802. package/dist/tasks/deps-ready.js.map +1 -0
  803. package/dist/tasks/enforcement.js +86 -0
  804. package/dist/tasks/enforcement.js.map +1 -0
  805. package/dist/tasks/epic-enforcement.js +294 -0
  806. package/dist/tasks/epic-enforcement.js.map +1 -0
  807. package/dist/tasks/find.js +163 -0
  808. package/dist/tasks/find.js.map +1 -0
  809. package/dist/tasks/graph-cache.js +127 -0
  810. package/dist/tasks/graph-cache.js.map +1 -0
  811. package/dist/tasks/graph-ops.js +173 -0
  812. package/dist/tasks/graph-ops.js.map +1 -0
  813. package/dist/tasks/graph-rag.js +328 -0
  814. package/dist/tasks/graph-rag.js.map +1 -0
  815. package/dist/tasks/hierarchy-policy.js +149 -0
  816. package/dist/tasks/hierarchy-policy.js.map +1 -0
  817. package/dist/tasks/hierarchy.js +185 -0
  818. package/dist/tasks/hierarchy.js.map +1 -0
  819. package/dist/tasks/id-generator.js +65 -0
  820. package/dist/tasks/id-generator.js.map +1 -0
  821. package/dist/tasks/index.js +14 -0
  822. package/dist/tasks/index.js.map +1 -0
  823. package/dist/tasks/labels.js +55 -0
  824. package/dist/tasks/labels.js.map +1 -0
  825. package/dist/tasks/list.js +75 -0
  826. package/dist/tasks/list.js.map +1 -0
  827. package/dist/tasks/phase-tracking.js +133 -0
  828. package/dist/tasks/phase-tracking.js.map +1 -0
  829. package/dist/tasks/pipeline-stage.js +248 -0
  830. package/dist/tasks/pipeline-stage.js.map +1 -0
  831. package/dist/tasks/plan.js +268 -0
  832. package/dist/tasks/plan.js.map +1 -0
  833. package/dist/tasks/relates.js +101 -0
  834. package/dist/tasks/relates.js.map +1 -0
  835. package/dist/tasks/show.js +83 -0
  836. package/dist/tasks/show.js.map +1 -0
  837. package/dist/tasks/size-weighting.js +86 -0
  838. package/dist/tasks/size-weighting.js.map +1 -0
  839. package/dist/tasks/staleness.js +86 -0
  840. package/dist/tasks/staleness.js.map +1 -0
  841. package/dist/tasks/task-ops.js +1741 -0
  842. package/dist/tasks/task-ops.js.map +1 -0
  843. package/dist/tasks/update.js +303 -0
  844. package/dist/tasks/update.js.map +1 -0
  845. package/dist/telemetry/index.js +249 -0
  846. package/dist/telemetry/index.js.map +1 -0
  847. package/dist/telemetry/schema.js +60 -0
  848. package/dist/telemetry/schema.js.map +1 -0
  849. package/dist/telemetry/sqlite.js +111 -0
  850. package/dist/telemetry/sqlite.js.map +1 -0
  851. package/dist/templates/index.js +10 -0
  852. package/dist/templates/index.js.map +1 -0
  853. package/dist/templates/parser.js +254 -0
  854. package/dist/templates/parser.js.map +1 -0
  855. package/dist/ui/aliases.js +153 -0
  856. package/dist/ui/aliases.js.map +1 -0
  857. package/dist/ui/changelog.js +184 -0
  858. package/dist/ui/changelog.js.map +1 -0
  859. package/dist/ui/command-registry.js +168 -0
  860. package/dist/ui/command-registry.js.map +1 -0
  861. package/dist/ui/flags.js +94 -0
  862. package/dist/ui/flags.js.map +1 -0
  863. package/dist/ui/index.js +24 -0
  864. package/dist/ui/index.js.map +1 -0
  865. package/dist/upgrade.js +1387 -0
  866. package/dist/upgrade.js.map +1 -0
  867. package/dist/validation/chain-validation.js +146 -0
  868. package/dist/validation/chain-validation.js.map +1 -0
  869. package/dist/validation/compliance.js +155 -0
  870. package/dist/validation/compliance.js.map +1 -0
  871. package/dist/validation/docs-sync.js +212 -0
  872. package/dist/validation/docs-sync.js.map +1 -0
  873. package/dist/validation/doctor/checks.js +1069 -0
  874. package/dist/validation/doctor/checks.js.map +1 -0
  875. package/dist/validation/doctor/index.js +9 -0
  876. package/dist/validation/doctor/index.js.map +1 -0
  877. package/dist/validation/doctor/project-cache.js +160 -0
  878. package/dist/validation/doctor/project-cache.js.map +1 -0
  879. package/dist/validation/doctor/utils.js +155 -0
  880. package/dist/validation/doctor/utils.js.map +1 -0
  881. package/dist/validation/engine.js +914 -0
  882. package/dist/validation/engine.js.map +1 -0
  883. package/dist/validation/gap-check.js +175 -0
  884. package/dist/validation/gap-check.js.map +1 -0
  885. package/dist/validation/index.js +40 -0
  886. package/dist/validation/index.js.map +1 -0
  887. package/dist/validation/manifest.js +237 -0
  888. package/dist/validation/manifest.js.map +1 -0
  889. package/dist/validation/operation-gate-validators.js +724 -0
  890. package/dist/validation/operation-gate-validators.js.map +1 -0
  891. package/dist/validation/operation-verification-gates.js +532 -0
  892. package/dist/validation/operation-verification-gates.js.map +1 -0
  893. package/dist/validation/param-utils.js +141 -0
  894. package/dist/validation/param-utils.js.map +1 -0
  895. package/dist/validation/protocol-common.js +300 -0
  896. package/dist/validation/protocol-common.js.map +1 -0
  897. package/dist/validation/protocols/_shared.js +82 -0
  898. package/dist/validation/protocols/_shared.js.map +1 -0
  899. package/dist/validation/protocols/architecture-decision.js +31 -0
  900. package/dist/validation/protocols/architecture-decision.js.map +1 -0
  901. package/dist/validation/protocols/artifact-publish.js +28 -0
  902. package/dist/validation/protocols/artifact-publish.js.map +1 -0
  903. package/dist/validation/protocols/consensus.js +41 -0
  904. package/dist/validation/protocols/consensus.js.map +1 -0
  905. package/dist/validation/protocols/contribution.js +27 -0
  906. package/dist/validation/protocols/contribution.js.map +1 -0
  907. package/dist/validation/protocols/decomposition.js +28 -0
  908. package/dist/validation/protocols/decomposition.js.map +1 -0
  909. package/dist/validation/protocols/implementation.js +24 -0
  910. package/dist/validation/protocols/implementation.js.map +1 -0
  911. package/dist/validation/protocols/provenance.js +29 -0
  912. package/dist/validation/protocols/provenance.js.map +1 -0
  913. package/dist/validation/protocols/release.js +29 -0
  914. package/dist/validation/protocols/release.js.map +1 -0
  915. package/dist/validation/protocols/research.js +24 -0
  916. package/dist/validation/protocols/research.js.map +1 -0
  917. package/dist/validation/protocols/specification.js +27 -0
  918. package/dist/validation/protocols/specification.js.map +1 -0
  919. package/dist/validation/protocols/testing.js +30 -0
  920. package/dist/validation/protocols/testing.js.map +1 -0
  921. package/dist/validation/protocols/validation.js +30 -0
  922. package/dist/validation/protocols/validation.js.map +1 -0
  923. package/dist/validation/schema-integrity.js +170 -0
  924. package/dist/validation/schema-integrity.js.map +1 -0
  925. package/dist/validation/schema-validator.js +176 -0
  926. package/dist/validation/schema-validator.js.map +1 -0
  927. package/dist/validation/validate-ops.js +937 -0
  928. package/dist/validation/validate-ops.js.map +1 -0
  929. package/dist/validation/validation-rules.js +226 -0
  930. package/dist/validation/validation-rules.js.map +1 -0
  931. package/dist/validation/verification.js +321 -0
  932. package/dist/validation/verification.js.map +1 -0
  933. package/package.json +8 -8
@@ -0,0 +1,1088 @@
1
+ /**
2
+ * BRAIN Retrieval Operations — 3-layer pattern (search -> timeline -> fetch).
3
+ *
4
+ * Provides token-efficient memory access modeled after claude-mem's
5
+ * search/timeline/get_observations workflow:
6
+ *
7
+ * 1. searchBrainCompact — lightweight index (IDs + titles, ~50 tokens/hit)
8
+ * 2. timelineBrain — chronological context around an anchor entry
9
+ * 3. fetchBrainEntries — full details for a filtered set of IDs
10
+ * 4. observeBrain — unified save (observations table)
11
+ *
12
+ * Wave 2A provides the core implementations; Wave 2B wires them through
13
+ * the dispatch layer (engine-compat -> domain handler -> CLI gateway).
14
+ *
15
+ * @task T5131 T5132 T5133 T5134 T5135
16
+ * @epic T5149
17
+ */
18
+ import { createHash } from 'node:crypto';
19
+ import { memoryFindHitNext } from '../mvi-helpers.js';
20
+ import { getBrainAccessor } from '../store/brain-accessor.js';
21
+ import { sessionExistsInTasksDb } from '../store/cross-db-cleanup.js';
22
+ import { getDb } from '../store/sqlite.js';
23
+ import { typedAll } from '../store/typed-query.js';
24
+ import { embedText, isEmbeddingAvailable } from './brain-embedding.js';
25
+ import { hybridSearch, searchBrain } from './brain-search.js';
26
+ import { searchSimilar } from './brain-similarity.js';
27
+ import { addGraphEdge, upsertGraphNode } from './graph-auto-populate.js';
28
+ import { computeObservationQuality } from './quality-scoring.js';
29
+ // ============================================================================
30
+ // Layer 1: Compact Search
31
+ // ============================================================================
32
+ /**
33
+ * Token-efficient compact search across BRAIN tables.
34
+ * Returns index-level hits (~50 tokens per result).
35
+ *
36
+ * Delegates to searchBrain() from brain-search.ts for FTS5/LIKE search,
37
+ * then projects results to a compact format with optional date filtering.
38
+ *
39
+ * @param projectRoot - Project root directory
40
+ * @param params - Search parameters
41
+ * @returns Compact search results with token estimate
42
+ */
43
+ export async function searchBrainCompact(projectRoot, params) {
44
+ const { query, limit, tables, dateStart, dateEnd, agent, useRRF = true } = params;
45
+ if (!query?.trim()) {
46
+ return { results: [], total: 0, tokensEstimated: 0 };
47
+ }
48
+ const effectiveLimit = limit ?? 10;
49
+ // T418: agent filter always forces FTS-only on observations table
50
+ const agentFilter = agent !== undefined && agent !== null;
51
+ // ----- RRF path (default) -----
52
+ if (useRRF && !agentFilter) {
53
+ // Run FTS (for dates + table-level data) and RRF fusion in parallel.
54
+ // FTS gives us row-level dates; RRF gives us the fused ranking order.
55
+ const [ftsResult, rrfResults] = await Promise.all([
56
+ searchBrain(projectRoot, query, { limit: effectiveLimit * 3, tables }).catch(() => ({
57
+ decisions: [],
58
+ patterns: [],
59
+ learnings: [],
60
+ observations: [],
61
+ })),
62
+ hybridSearch(query, projectRoot, { limit: effectiveLimit * 2 }),
63
+ ]);
64
+ // Build a date map from FTS rows (id -> date string)
65
+ const dateMap = new Map();
66
+ for (const d of ftsResult.decisions) {
67
+ const raw = d;
68
+ dateMap.set(d.id, (d.createdAt ?? raw['created_at']) || '');
69
+ }
70
+ for (const p of ftsResult.patterns) {
71
+ const raw = p;
72
+ dateMap.set(p.id, (p.extractedAt ?? raw['extracted_at']) || '');
73
+ }
74
+ for (const l of ftsResult.learnings) {
75
+ const raw = l;
76
+ dateMap.set(l.id, (l.createdAt ?? raw['created_at']) || '');
77
+ }
78
+ for (const o of ftsResult.observations) {
79
+ const raw = o;
80
+ dateMap.set(o.id, (o.createdAt ?? raw['created_at']) || '');
81
+ }
82
+ // Apply table filter when specified (map singular type names to plural table names)
83
+ const singularToTable = {
84
+ decision: 'decisions',
85
+ pattern: 'patterns',
86
+ learning: 'learnings',
87
+ observation: 'observations',
88
+ };
89
+ let results = rrfResults
90
+ .map((r) => ({
91
+ id: r.id,
92
+ type: r.type,
93
+ title: r.title.slice(0, 80),
94
+ date: dateMap.get(r.id) ?? '',
95
+ relevance: r.score,
96
+ }))
97
+ .filter((r) => {
98
+ // Only include items that the FTS scan returned (ensures quality gating is respected)
99
+ return dateMap.has(r.id);
100
+ });
101
+ if (tables && tables.length > 0) {
102
+ results = results.filter((r) => tables.includes(singularToTable[r.type]));
103
+ }
104
+ // Apply date filters client-side
105
+ if (dateStart)
106
+ results = results.filter((r) => !r.date || r.date >= dateStart);
107
+ if (dateEnd)
108
+ results = results.filter((r) => !r.date || r.date <= dateEnd);
109
+ results = results.slice(0, effectiveLimit);
110
+ for (const hit of results) {
111
+ hit._next = memoryFindHitNext(hit.id);
112
+ }
113
+ if (results.length > 0) {
114
+ const returnedIds = results.map((r) => r.id);
115
+ setImmediate(() => {
116
+ incrementCitationCounts(projectRoot, returnedIds).catch(() => { });
117
+ getCurrentSessionId(projectRoot)
118
+ .then((sessionId) => {
119
+ return logRetrieval(projectRoot, query, returnedIds, 'find-rrf', results.length * 50, sessionId);
120
+ })
121
+ .catch(() => { });
122
+ });
123
+ }
124
+ return { results, total: results.length, tokensEstimated: results.length * 50 };
125
+ }
126
+ // ----- FTS-only path (useRRF=false or agent filter) -----
127
+ const effectiveTables = agentFilter
128
+ ? ['observations']
129
+ : tables;
130
+ const searchResult = await searchBrain(projectRoot, query, {
131
+ limit: effectiveLimit,
132
+ tables: effectiveTables,
133
+ });
134
+ // Project full results to compact format.
135
+ // Note: searchBrain() returns rows from raw SQL (nativeDb) which use
136
+ // snake_case column names, but the TypeScript types are camelCase.
137
+ // We handle both naming conventions for robustness.
138
+ let results = [];
139
+ if (!agentFilter) {
140
+ for (const d of searchResult.decisions) {
141
+ const raw = d;
142
+ results.push({
143
+ id: d.id,
144
+ type: 'decision',
145
+ title: d.decision.slice(0, 80),
146
+ date: (d.createdAt ?? raw['created_at']) || '',
147
+ });
148
+ }
149
+ for (const p of searchResult.patterns) {
150
+ const raw = p;
151
+ results.push({
152
+ id: p.id,
153
+ type: 'pattern',
154
+ title: p.pattern.slice(0, 80),
155
+ date: (p.extractedAt ?? raw['extracted_at']) || '',
156
+ });
157
+ }
158
+ for (const l of searchResult.learnings) {
159
+ const raw = l;
160
+ results.push({
161
+ id: l.id,
162
+ type: 'learning',
163
+ title: l.insight.slice(0, 80),
164
+ date: (l.createdAt ?? raw['created_at']) || '',
165
+ });
166
+ }
167
+ }
168
+ for (const o of searchResult.observations) {
169
+ const raw = o;
170
+ // T418: apply agent post-filter when specified
171
+ if (agentFilter) {
172
+ const rowAgent = o.agent ?? raw['agent'] ?? null;
173
+ if (rowAgent !== agent)
174
+ continue;
175
+ }
176
+ results.push({
177
+ id: o.id,
178
+ type: 'observation',
179
+ title: o.title.slice(0, 80),
180
+ date: (o.createdAt ?? raw['created_at']) || '',
181
+ });
182
+ }
183
+ // Apply date filters client-side if provided
184
+ if (dateStart)
185
+ results = results.filter((r) => r.date >= dateStart);
186
+ if (dateEnd)
187
+ results = results.filter((r) => r.date <= dateEnd);
188
+ // Enrich each hit with _next progressive disclosure directives
189
+ for (const hit of results) {
190
+ hit._next = memoryFindHitNext(hit.id);
191
+ }
192
+ // Citation tracking + retrieval logging (non-blocking)
193
+ if (results.length > 0) {
194
+ const returnedIds = results.map((r) => r.id);
195
+ setImmediate(() => {
196
+ incrementCitationCounts(projectRoot, returnedIds).catch(() => { });
197
+ getCurrentSessionId(projectRoot)
198
+ .then((sessionId) => {
199
+ return logRetrieval(projectRoot, query, returnedIds, 'find', results.length * 50, sessionId);
200
+ })
201
+ .catch(() => { });
202
+ });
203
+ }
204
+ return {
205
+ results,
206
+ total: results.length,
207
+ tokensEstimated: results.length * 50,
208
+ };
209
+ }
210
+ // ============================================================================
211
+ // Layer 2: Timeline
212
+ // ============================================================================
213
+ /**
214
+ * Determine the entry type from its ID prefix.
215
+ *
216
+ * Conventions:
217
+ * - D... -> decision (D001, D-xxx)
218
+ * - P... -> pattern (P001, P-xxx)
219
+ * - L... -> learning (L001, L-xxx)
220
+ * - O... or CM-... -> observation (O-xxx, CM-xxx)
221
+ */
222
+ function parseIdPrefix(id) {
223
+ if (id.startsWith('D-') || /^D\d/.test(id))
224
+ return 'decision';
225
+ if (id.startsWith('P-') || /^P\d/.test(id))
226
+ return 'pattern';
227
+ if (id.startsWith('L-') || /^L\d/.test(id))
228
+ return 'learning';
229
+ if (id.startsWith('O-') || id.startsWith('O') || id.startsWith('CM-'))
230
+ return 'observation';
231
+ return null;
232
+ }
233
+ /**
234
+ * Get chronological context around an anchor entry.
235
+ * Fetches the anchor's full data, then queries all 4 BRAIN tables
236
+ * via UNION ALL to find chronological neighbors.
237
+ *
238
+ * @param projectRoot - Project root directory
239
+ * @param params - Timeline parameters with anchor ID and depth
240
+ * @returns Anchor entry data with surrounding chronological entries
241
+ */
242
+ export async function timelineBrain(projectRoot, params) {
243
+ const { anchor: anchorId, depthBefore = 3, depthAfter = 3 } = params;
244
+ // Ensure DB is initialized
245
+ const { getBrainDb, getBrainNativeDb } = await import('../store/brain-sqlite.js');
246
+ await getBrainDb(projectRoot);
247
+ const nativeDb = getBrainNativeDb();
248
+ if (!nativeDb) {
249
+ return { anchor: null, before: [], after: [] };
250
+ }
251
+ // Determine anchor type and fetch it via accessor
252
+ const anchorType = parseIdPrefix(anchorId);
253
+ if (!anchorType) {
254
+ return { anchor: null, before: [], after: [] };
255
+ }
256
+ const accessor = await getBrainAccessor(projectRoot);
257
+ let anchorData = null;
258
+ let anchorDate = null;
259
+ switch (anchorType) {
260
+ case 'decision': {
261
+ const row = await accessor.getDecision(anchorId);
262
+ if (row) {
263
+ anchorData = row;
264
+ anchorDate = row.createdAt;
265
+ }
266
+ break;
267
+ }
268
+ case 'pattern': {
269
+ const row = await accessor.getPattern(anchorId);
270
+ if (row) {
271
+ anchorData = row;
272
+ anchorDate = row.extractedAt;
273
+ }
274
+ break;
275
+ }
276
+ case 'learning': {
277
+ const row = await accessor.getLearning(anchorId);
278
+ if (row) {
279
+ anchorData = row;
280
+ anchorDate = row.createdAt;
281
+ }
282
+ break;
283
+ }
284
+ case 'observation': {
285
+ const row = await accessor.getObservation(anchorId);
286
+ if (row) {
287
+ anchorData = row;
288
+ anchorDate = row.createdAt;
289
+ }
290
+ break;
291
+ }
292
+ }
293
+ if (!anchorData || !anchorDate) {
294
+ return { anchor: null, before: [], after: [] };
295
+ }
296
+ // UNION ALL across all 4 tables to get chronological neighbors.
297
+ // Excludes the anchor itself.
298
+ const beforeRows = typedAll(nativeDb.prepare(`
299
+ SELECT id, 'decision' AS type, created_at AS date FROM brain_decisions WHERE created_at < ? AND id != ?
300
+ UNION ALL
301
+ SELECT id, 'pattern' AS type, extracted_at AS date FROM brain_patterns WHERE extracted_at < ? AND id != ?
302
+ UNION ALL
303
+ SELECT id, 'learning' AS type, created_at AS date FROM brain_learnings WHERE created_at < ? AND id != ?
304
+ UNION ALL
305
+ SELECT id, 'observation' AS type, created_at AS date FROM brain_observations WHERE created_at < ? AND id != ?
306
+ ORDER BY date DESC
307
+ LIMIT ?
308
+ `), anchorDate, anchorId, anchorDate, anchorId, anchorDate, anchorId, anchorDate, anchorId, depthBefore);
309
+ const afterRows = typedAll(nativeDb.prepare(`
310
+ SELECT id, 'decision' AS type, created_at AS date FROM brain_decisions WHERE created_at > ? AND id != ?
311
+ UNION ALL
312
+ SELECT id, 'pattern' AS type, extracted_at AS date FROM brain_patterns WHERE extracted_at > ? AND id != ?
313
+ UNION ALL
314
+ SELECT id, 'learning' AS type, created_at AS date FROM brain_learnings WHERE created_at > ? AND id != ?
315
+ UNION ALL
316
+ SELECT id, 'observation' AS type, created_at AS date FROM brain_observations WHERE created_at > ? AND id != ?
317
+ ORDER BY date ASC
318
+ LIMIT ?
319
+ `), anchorDate, anchorId, anchorDate, anchorId, anchorDate, anchorId, anchorDate, anchorId, depthAfter);
320
+ return {
321
+ anchor: { id: anchorId, type: anchorType, data: anchorData },
322
+ before: beforeRows.map((r) => ({ id: r.id, type: r.type, date: r.date })),
323
+ after: afterRows.map((r) => ({ id: r.id, type: r.type, date: r.date })),
324
+ };
325
+ }
326
+ // ============================================================================
327
+ // Layer 3: Batch Fetch
328
+ // ============================================================================
329
+ /**
330
+ * Batch-fetch full details by IDs.
331
+ * Groups IDs by prefix to query the correct tables via BrainDataAccessor.
332
+ *
333
+ * @param projectRoot - Project root directory
334
+ * @param params - Fetch parameters with IDs
335
+ * @returns Full entry data for each found ID, plus not-found list
336
+ */
337
+ export async function fetchBrainEntries(projectRoot, params) {
338
+ const { ids } = params;
339
+ if (!ids || ids.length === 0) {
340
+ return { results: [], notFound: [], tokensEstimated: 0 };
341
+ }
342
+ const accessor = await getBrainAccessor(projectRoot);
343
+ // Group IDs by type prefix
344
+ const decisionIds = [];
345
+ const patternIds = [];
346
+ const learningIds = [];
347
+ const observationIds = [];
348
+ const unknownIds = [];
349
+ for (const id of ids) {
350
+ const type = parseIdPrefix(id);
351
+ switch (type) {
352
+ case 'decision':
353
+ decisionIds.push(id);
354
+ break;
355
+ case 'pattern':
356
+ patternIds.push(id);
357
+ break;
358
+ case 'learning':
359
+ learningIds.push(id);
360
+ break;
361
+ case 'observation':
362
+ observationIds.push(id);
363
+ break;
364
+ default:
365
+ unknownIds.push(id);
366
+ }
367
+ }
368
+ const results = [];
369
+ const notFound = [...unknownIds];
370
+ // Fetch decisions
371
+ for (const id of decisionIds) {
372
+ const row = await accessor.getDecision(id);
373
+ if (row) {
374
+ results.push({ id, type: 'decision', data: row });
375
+ }
376
+ else {
377
+ notFound.push(id);
378
+ }
379
+ }
380
+ // Fetch patterns
381
+ for (const id of patternIds) {
382
+ const row = await accessor.getPattern(id);
383
+ if (row) {
384
+ results.push({ id, type: 'pattern', data: row });
385
+ }
386
+ else {
387
+ notFound.push(id);
388
+ }
389
+ }
390
+ // Fetch learnings
391
+ for (const id of learningIds) {
392
+ const row = await accessor.getLearning(id);
393
+ if (row) {
394
+ results.push({ id, type: 'learning', data: row });
395
+ }
396
+ else {
397
+ notFound.push(id);
398
+ }
399
+ }
400
+ // Fetch observations
401
+ for (const id of observationIds) {
402
+ const row = await accessor.getObservation(id);
403
+ if (row) {
404
+ results.push({ id, type: 'observation', data: row });
405
+ }
406
+ else {
407
+ notFound.push(id);
408
+ }
409
+ }
410
+ // Citation tracking + retrieval logging (non-blocking)
411
+ if (results.length > 0) {
412
+ const fetchedIds = results.map((r) => r.id);
413
+ setImmediate(() => {
414
+ incrementCitationCounts(projectRoot, fetchedIds).catch(() => { });
415
+ getCurrentSessionId(projectRoot)
416
+ .then((sessionId) => {
417
+ return logRetrieval(projectRoot, fetchedIds.join(','), fetchedIds, 'fetch', results.length * 500, sessionId);
418
+ })
419
+ .catch(() => { });
420
+ });
421
+ }
422
+ return {
423
+ results,
424
+ notFound,
425
+ tokensEstimated: results.length * 500,
426
+ };
427
+ }
428
+ // ============================================================================
429
+ // Observe (Unified Save)
430
+ // ============================================================================
431
+ /**
432
+ * Keyword patterns for auto-classifying observation type from text.
433
+ */
434
+ const TYPE_KEYWORDS = [
435
+ { keywords: ['bug', 'fix', 'error', 'crash'], type: 'bugfix' },
436
+ { keywords: ['refactor', 'rename', 'extract', 'move'], type: 'refactor' },
437
+ { keywords: ['add', 'create', 'implement', 'new'], type: 'feature' },
438
+ { keywords: ['decide', 'chose', 'pick', 'instead'], type: 'decision' },
439
+ { keywords: ['update', 'change', 'modify', 'upgrade'], type: 'change' },
440
+ ];
441
+ /**
442
+ * Auto-classify observation type from text using keyword matching.
443
+ */
444
+ function classifyObservationType(text) {
445
+ const lower = text.toLowerCase();
446
+ for (const { keywords, type } of TYPE_KEYWORDS) {
447
+ for (const keyword of keywords) {
448
+ if (lower.includes(keyword)) {
449
+ return type;
450
+ }
451
+ }
452
+ }
453
+ return 'discovery';
454
+ }
455
+ /** Monotonic counter to prevent ID collisions within the same millisecond. */
456
+ let observeSeq = 0;
457
+ /**
458
+ * Save an observation to the BRAIN observations table.
459
+ * Replaces the external claude-mem save_observation pattern.
460
+ *
461
+ * Auto-classifies type from text if not provided. Generates a
462
+ * unique ID with O- prefix + base36 timestamp.
463
+ *
464
+ * @param projectRoot - Project root directory
465
+ * @param params - Observation data
466
+ * @returns Created observation ID, type, and timestamp
467
+ */
468
+ export async function observeBrain(projectRoot, params) {
469
+ const { text, title: titleParam, type: typeParam, project, sourceSessionId, sourceType, agent, sourceConfidence: sourceConfidenceParam, } = params;
470
+ if (!text?.trim()) {
471
+ throw new Error('Observation text is required');
472
+ }
473
+ const type = typeParam ?? classifyObservationType(text);
474
+ const title = titleParam ?? text.slice(0, 120);
475
+ const now = new Date().toISOString().replace('T', ' ').slice(0, 19);
476
+ // T549 Wave 1-A: Tier routing for observations.
477
+ // Observations always start as short-term episodic entries.
478
+ // sourceConfidence routing (spec §4.1 Decision Tree):
479
+ // - sourceType 'manual' → 'owner' (owner-stated facts skip short-term in consolidator)
480
+ // - sourceType 'session-debrief' → 'task-outcome' (synthesized summaries)
481
+ // - otherwise → 'agent' (default for all hook/agent writes)
482
+ // Source confidence routing (spec §4.1 Decision Tree):
483
+ // - sourceType 'manual' → 'owner' (owner-stated facts are ground truth)
484
+ // - sourceType 'session-debrief' → 'task-outcome' (verified by completion)
485
+ // - otherwise → 'agent' (default for all hook/agent writes)
486
+ // Owner and task-outcome sources are auto-verified as ground truth.
487
+ // Agent-inferred entries start unverified — consolidator promotes via corroboration.
488
+ const resolvedSourceConfidence = sourceConfidenceParam ??
489
+ (sourceType === 'manual'
490
+ ? 'owner'
491
+ : sourceType === 'session-debrief'
492
+ ? 'task-outcome'
493
+ : 'agent');
494
+ const memoryTier = 'short';
495
+ const memoryType = 'episodic';
496
+ const verified = resolvedSourceConfidence === 'owner' || resolvedSourceConfidence === 'task-outcome';
497
+ // Content-hash dedup: SHA-256 prefix of title+text
498
+ const contentHash = createHash('sha256')
499
+ .update(title + text)
500
+ .digest('hex')
501
+ .slice(0, 16);
502
+ // Check for recent duplicate (same content within last 30 seconds)
503
+ const { getBrainNativeDb } = await import('../store/brain-sqlite.js');
504
+ const nativeDb = getBrainNativeDb();
505
+ if (nativeDb) {
506
+ const cutoff = new Date(Date.now() - 30000).toISOString().replace('T', ' ').slice(0, 19);
507
+ const existing = typedAll(nativeDb.prepare('SELECT id, type, created_at FROM brain_observations WHERE content_hash = ? AND created_at > ?'), contentHash, cutoff);
508
+ if (existing.length > 0) {
509
+ return {
510
+ id: existing[0].id,
511
+ type: existing[0].type,
512
+ createdAt: existing[0].created_at,
513
+ };
514
+ }
515
+ }
516
+ // Write-guard: validate cross-db session reference before inserting
517
+ let validSessionId = sourceSessionId ?? null;
518
+ if (validSessionId) {
519
+ try {
520
+ const tasksDb = await getDb(projectRoot);
521
+ if (!(await sessionExistsInTasksDb(validSessionId, tasksDb))) {
522
+ validSessionId = null;
523
+ }
524
+ }
525
+ catch {
526
+ // Best-effort: if tasks.db unavailable, null out the reference
527
+ validSessionId = null;
528
+ }
529
+ }
530
+ // Compute quality score from text richness, title length, and T549 source multiplier.
531
+ const qualityScore = computeObservationQuality({
532
+ text,
533
+ title,
534
+ sourceConfidence: resolvedSourceConfidence,
535
+ memoryTier,
536
+ });
537
+ const id = `O-${Date.now().toString(36)}-${(observeSeq++ % 1000).toString(36)}`;
538
+ const accessor = await getBrainAccessor(projectRoot);
539
+ const row = await accessor.addObservation({
540
+ id,
541
+ type,
542
+ title,
543
+ narrative: text,
544
+ contentHash,
545
+ project: project ?? null,
546
+ sourceSessionId: validSessionId,
547
+ sourceType: sourceType ?? 'agent',
548
+ agent: agent ?? null,
549
+ qualityScore,
550
+ createdAt: now,
551
+ // T549 Wave 1-A: tier/type/confidence assigned at write time
552
+ memoryTier,
553
+ memoryType,
554
+ sourceConfidence: resolvedSourceConfidence,
555
+ verified,
556
+ });
557
+ // Populate embedding if provider is available (T5387).
558
+ // Fire-and-forget: embedding runs in the background so it never blocks the CLI.
559
+ // The observation is already saved above — if embedding fails, the observation
560
+ // still exists, just without vector similarity search capability. (T027)
561
+ if (isEmbeddingAvailable()) {
562
+ setImmediate(() => {
563
+ embedText(text)
564
+ .then((vector) => {
565
+ if (vector && nativeDb) {
566
+ nativeDb
567
+ .prepare('INSERT OR REPLACE INTO brain_embeddings (id, embedding) VALUES (?, ?)')
568
+ .run(id, Buffer.from(vector.buffer));
569
+ }
570
+ })
571
+ .catch(() => {
572
+ // Silently skip embedding failures — observation is already persisted
573
+ });
574
+ });
575
+ }
576
+ // Regenerate memory bridge for high-value observation types (T5240).
577
+ // Only learning and decision types trigger bridge refresh to avoid excessive writes.
578
+ if (type === 'decision') {
579
+ import('./memory-bridge.js')
580
+ .then(({ refreshMemoryBridge }) => refreshMemoryBridge(projectRoot))
581
+ .catch(() => {
582
+ /* Memory bridge refresh is best-effort */
583
+ });
584
+ }
585
+ // Auto-link observation to the currently focused task when a session is active. (T141)
586
+ // This is a fire-and-forget side effect — linking failure MUST NOT block the return.
587
+ if (validSessionId) {
588
+ autoLinkObservationToTask(projectRoot, row.id, accessor).catch(() => {
589
+ /* Auto-linking is best-effort */
590
+ });
591
+ }
592
+ // Auto-populate graph node + edges for this observation (best-effort, T537).
593
+ try {
594
+ await upsertGraphNode(projectRoot, `observation:${row.id}`, 'observation', row.title.substring(0, 200), row.qualityScore ?? 0.5, row.narrative ?? row.title, { sourceType: row.sourceType, agent: row.agent ?? undefined });
595
+ // Link observation → session when the observation has a session context.
596
+ if (validSessionId) {
597
+ await upsertGraphNode(projectRoot, `session:${validSessionId}`, 'session', validSessionId, 0.8, '');
598
+ await addGraphEdge(projectRoot, `observation:${row.id}`, `session:${validSessionId}`, 'produced_by', 1.0, 'auto:observe');
599
+ }
600
+ }
601
+ catch {
602
+ /* Graph population is best-effort — never block the primary return */
603
+ }
604
+ return {
605
+ id: row.id,
606
+ type: row.type,
607
+ createdAt: row.createdAt,
608
+ };
609
+ }
610
+ /**
611
+ * Auto-link a newly created observation to the currently focused task.
612
+ *
613
+ * Queries the active session via sessionStatus() and reads taskWork.taskId.
614
+ * If a task is focused, inserts a brain_memory_links row linking the
615
+ * observation to that task with linkType 'produced_by'.
616
+ *
617
+ * All failures are silently swallowed — this is a best-effort side effect.
618
+ *
619
+ * @param projectRoot - Project root directory
620
+ * @param observationId - ID of the newly created observation
621
+ * @param accessor - BrainDataAccessor to use for the link insert
622
+ */
623
+ async function autoLinkObservationToTask(projectRoot, observationId, accessor) {
624
+ const { sessionStatus } = await import('../sessions/index.js');
625
+ const session = await sessionStatus(projectRoot);
626
+ if (!session)
627
+ return;
628
+ const taskId = session.taskWork?.taskId;
629
+ if (!taskId)
630
+ return;
631
+ await accessor.addLink({
632
+ memoryType: 'observation',
633
+ memoryId: observationId,
634
+ taskId,
635
+ linkType: 'produced_by',
636
+ });
637
+ }
638
+ /**
639
+ * Backfill embeddings for existing observations that lack them.
640
+ *
641
+ * Iterates through observations not yet in brain_embeddings and
642
+ * generates vectors using the registered embedding provider.
643
+ * Processes in batches to avoid memory pressure.
644
+ *
645
+ * An optional {@link PopulateEmbeddingsOptions.onProgress} callback is called
646
+ * after each observation is attempted, enabling callers to report progress.
647
+ *
648
+ * @param projectRoot - Project root directory
649
+ * @param options - Optional batch size and progress callback
650
+ * @returns Count of processed, skipped, and errored observations
651
+ *
652
+ * @epic T134
653
+ * @task T142
654
+ */
655
+ export async function populateEmbeddings(projectRoot, options) {
656
+ if (!isEmbeddingAvailable()) {
657
+ return { processed: 0, skipped: 0, errors: 0 };
658
+ }
659
+ const { getBrainDb, getBrainNativeDb } = await import('../store/brain-sqlite.js');
660
+ await getBrainDb(projectRoot);
661
+ const nativeDb = getBrainNativeDb();
662
+ if (!nativeDb) {
663
+ return { processed: 0, skipped: 0, errors: 0 };
664
+ }
665
+ const batchSize = options?.batchSize ?? 50;
666
+ const { onProgress } = options ?? {};
667
+ let processed = 0;
668
+ let skipped = 0;
669
+ let errors = 0;
670
+ // Find observations without embeddings
671
+ const rows = typedAll(nativeDb.prepare(`
672
+ SELECT o.id, o.narrative, o.title
673
+ FROM brain_observations o
674
+ LEFT JOIN brain_embeddings e ON o.id = e.id
675
+ WHERE e.id IS NULL AND o.narrative IS NOT NULL
676
+ ORDER BY o.created_at DESC
677
+ `));
678
+ const total = rows.length;
679
+ let attempted = 0;
680
+ for (let i = 0; i < rows.length; i += batchSize) {
681
+ const batch = rows.slice(i, i + batchSize);
682
+ for (const row of batch) {
683
+ try {
684
+ const vector = await embedText(row.narrative || row.title);
685
+ if (vector) {
686
+ nativeDb
687
+ .prepare('INSERT OR REPLACE INTO brain_embeddings (id, embedding) VALUES (?, ?)')
688
+ .run(row.id, Buffer.from(vector.buffer));
689
+ processed++;
690
+ }
691
+ else {
692
+ skipped++;
693
+ }
694
+ }
695
+ catch {
696
+ errors++;
697
+ }
698
+ attempted++;
699
+ onProgress?.(attempted, total);
700
+ }
701
+ }
702
+ return { processed, skipped, errors };
703
+ }
704
+ /**
705
+ * Budget-aware hybrid retrieval combining FTS5, vector KNN, and graph neighbor scores.
706
+ *
707
+ * Strategy (parallel where possible):
708
+ * A. FTS5 BM25 search (always) — keyword precision (50% weight)
709
+ * B. Vector KNN search (optional) — semantic recall (40% weight, skipped if no embeddings)
710
+ * C. Graph neighbors (optional) — associative context (10% weight, skipped if graph empty)
711
+ *
712
+ * Score fusion: final = (fts*0.50 + vec*0.40 + graph*0.10) × qualityScore
713
+ * Recency boost: +0.05 for entries updated in last 7 days.
714
+ * Type priority: procedural entries get +0.10 (always-useful rules).
715
+ *
716
+ * Budget enforcement:
717
+ * - Rank top-50 candidates by fused score.
718
+ * - Walk list, accumulate token cost (≈ textLen/4), stop at budget.
719
+ * - Episodic entries dropped first when budget is tight.
720
+ *
721
+ * Citation tracking: increments citationCount for returned entries in background (setImmediate).
722
+ *
723
+ * @param projectRoot - Project root directory
724
+ * @param query - Text to search for
725
+ * @param tokenBudget - Maximum tokens to spend on results (default 500)
726
+ * @param options - Optional filters (types, tiers, verified)
727
+ * @returns Retrieved entries within budget with token accounting
728
+ */
729
+ export async function retrieveWithBudget(projectRoot, query, tokenBudget = 500, options) {
730
+ if (!query?.trim()) {
731
+ return { entries: [], tokensUsed: 0, tokensRemaining: tokenBudget, excluded: 0 };
732
+ }
733
+ // -------------------------------------------------------------------------
734
+ // Run search strategies in parallel
735
+ // -------------------------------------------------------------------------
736
+ const [ftsResult, vecResults, graphNeighbors] = await Promise.all([
737
+ // A. FTS5
738
+ searchBrain(projectRoot, query, { limit: 30 }).catch(() => ({
739
+ decisions: [],
740
+ patterns: [],
741
+ learnings: [],
742
+ observations: [],
743
+ })),
744
+ // B. Vector KNN (degrades gracefully when unavailable)
745
+ searchSimilar(query, projectRoot, 20).catch(() => []),
746
+ // C. Graph neighbors from top FTS hit
747
+ Promise.resolve([]),
748
+ ]);
749
+ const candidateMap = new Map();
750
+ // FTS results (normalized score 0.5 starting point — BM25 doesn't give 0..1)
751
+ const FTS_BASE = 0.5;
752
+ for (const d of ftsResult.decisions) {
753
+ const raw = d;
754
+ const id = d.id;
755
+ const tier = (d.memoryTier ?? raw['memory_tier']) || undefined;
756
+ const mtype = (d.memoryType ?? raw['memory_type']) || undefined;
757
+ const updatedAt = (d.updatedAt ?? raw['updated_at']) || undefined;
758
+ candidateMap.set(id, {
759
+ id,
760
+ type: 'decision',
761
+ title: d.decision.slice(0, 120),
762
+ text: `${d.decision} — ${d.rationale}`,
763
+ ftsScore: FTS_BASE,
764
+ vecScore: 0,
765
+ graphScore: 0,
766
+ qualityScore: d.qualityScore ?? 0.5,
767
+ memoryTier: tier,
768
+ memoryType: mtype,
769
+ updatedAt,
770
+ });
771
+ }
772
+ for (const p of ftsResult.patterns) {
773
+ const raw = p;
774
+ const id = p.id;
775
+ const tier = (p.memoryTier ?? raw['memory_tier']) || undefined;
776
+ const mtype = (p.memoryType ?? raw['memory_type']) || undefined;
777
+ const updatedAt = (p.updatedAt ?? raw['updated_at']) || undefined;
778
+ candidateMap.set(id, {
779
+ id,
780
+ type: 'pattern',
781
+ title: p.pattern.slice(0, 120),
782
+ text: `${p.pattern} — ${p.context}`,
783
+ ftsScore: FTS_BASE,
784
+ vecScore: 0,
785
+ graphScore: 0,
786
+ qualityScore: p.qualityScore ?? 0.5,
787
+ memoryTier: tier,
788
+ memoryType: mtype,
789
+ updatedAt,
790
+ });
791
+ }
792
+ for (const l of ftsResult.learnings) {
793
+ const raw = l;
794
+ const id = l.id;
795
+ const tier = (l.memoryTier ?? raw['memory_tier']) || undefined;
796
+ const mtype = (l.memoryType ?? raw['memory_type']) || undefined;
797
+ const updatedAt = (l.updatedAt ?? raw['updated_at']) || undefined;
798
+ candidateMap.set(id, {
799
+ id,
800
+ type: 'learning',
801
+ title: l.insight.slice(0, 120),
802
+ text: `${l.insight} (source: ${l.source})`,
803
+ ftsScore: FTS_BASE,
804
+ vecScore: 0,
805
+ graphScore: 0,
806
+ qualityScore: l.qualityScore ?? 0.5,
807
+ memoryTier: tier,
808
+ memoryType: mtype,
809
+ updatedAt,
810
+ });
811
+ }
812
+ for (const o of ftsResult.observations) {
813
+ const raw = o;
814
+ const id = o.id;
815
+ const tier = (o.memoryTier ?? raw['memory_tier']) || undefined;
816
+ const mtype = (o.memoryType ?? raw['memory_type']) || undefined;
817
+ const updatedAt = (o.updatedAt ?? raw['updated_at']) || undefined;
818
+ candidateMap.set(id, {
819
+ id,
820
+ type: 'observation',
821
+ title: o.title.slice(0, 120),
822
+ text: o.narrative ?? o.title,
823
+ ftsScore: FTS_BASE,
824
+ vecScore: 0,
825
+ graphScore: 0,
826
+ qualityScore: o.qualityScore ?? 0.5,
827
+ memoryTier: tier,
828
+ memoryType: mtype,
829
+ updatedAt,
830
+ });
831
+ }
832
+ // B. Merge vector scores (distance → similarity: similarity = 1 - distance)
833
+ for (const v of vecResults) {
834
+ const simScore = Math.max(0, 1 - v.distance);
835
+ const existing = candidateMap.get(v.id);
836
+ if (existing) {
837
+ existing.vecScore = simScore;
838
+ }
839
+ else {
840
+ candidateMap.set(v.id, {
841
+ id: v.id,
842
+ type: v.type,
843
+ title: v.title.slice(0, 120),
844
+ text: v.text,
845
+ ftsScore: 0,
846
+ vecScore: simScore,
847
+ graphScore: 0,
848
+ qualityScore: 0.5,
849
+ memoryTier: undefined,
850
+ memoryType: undefined,
851
+ });
852
+ }
853
+ }
854
+ // C. Merge graph scores
855
+ for (const g of graphNeighbors) {
856
+ const existing = candidateMap.get(g.id);
857
+ if (existing) {
858
+ existing.graphScore = g.graphScore;
859
+ }
860
+ }
861
+ // -------------------------------------------------------------------------
862
+ // Score fusion + ranking
863
+ // -------------------------------------------------------------------------
864
+ const sevenDaysAgo = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000)
865
+ .toISOString()
866
+ .replace('T', ' ')
867
+ .slice(0, 19);
868
+ const candidates = Array.from(candidateMap.values()).map((c) => {
869
+ // Fused score
870
+ let score = c.ftsScore * 0.5 + c.vecScore * 0.4 + c.graphScore * 0.1;
871
+ // Quality multiplier
872
+ score *= c.qualityScore;
873
+ // Recency boost for recently-updated entries
874
+ if (c.updatedAt && c.updatedAt >= sevenDaysAgo) {
875
+ score += 0.05;
876
+ }
877
+ // Type priority boost for procedural entries (always-useful rules)
878
+ if (c.memoryType === 'procedural' || c.type === 'pattern') {
879
+ score += 0.1;
880
+ }
881
+ return { ...c, score };
882
+ });
883
+ // -------------------------------------------------------------------------
884
+ // Apply option filters (types, tiers, verified)
885
+ // -------------------------------------------------------------------------
886
+ // We'll apply verified filter by checking the DB if requested
887
+ let filtered = candidates;
888
+ if (options?.types && options.types.length > 0) {
889
+ const allowedTypes = new Set(options.types);
890
+ filtered = filtered.filter((c) => {
891
+ if (!c.memoryType)
892
+ return true; // unknown type — include
893
+ return allowedTypes.has(c.memoryType);
894
+ });
895
+ }
896
+ if (options?.tiers && options.tiers.length > 0) {
897
+ const allowedTiers = new Set(options.tiers);
898
+ filtered = filtered.filter((c) => {
899
+ if (!c.memoryTier)
900
+ return true; // unknown tier — include
901
+ return allowedTiers.has(c.memoryTier);
902
+ });
903
+ }
904
+ // -------------------------------------------------------------------------
905
+ // Sort: procedural first, then by score descending
906
+ // -------------------------------------------------------------------------
907
+ filtered.sort((a, b) => {
908
+ const aProcedural = a.memoryType === 'procedural' || a.type === 'pattern' ? 1 : 0;
909
+ const bProcedural = b.memoryType === 'procedural' || b.type === 'pattern' ? 1 : 0;
910
+ if (aProcedural !== bProcedural)
911
+ return bProcedural - aProcedural;
912
+ return b.score - a.score;
913
+ });
914
+ // Cap candidate list at top 50
915
+ const topCandidates = filtered.slice(0, 50);
916
+ // -------------------------------------------------------------------------
917
+ // Budget enforcement — episodic entries are dropped first when budget tight
918
+ // -------------------------------------------------------------------------
919
+ // Sort for budget walk: procedural first, semantic second, episodic last
920
+ const typeOrder = (c) => {
921
+ if (c.memoryType === 'procedural' || c.type === 'pattern')
922
+ return 0;
923
+ if (c.memoryType === 'semantic' || c.type === 'decision' || c.type === 'learning')
924
+ return 1;
925
+ return 2; // episodic
926
+ };
927
+ const budgetOrdered = [...topCandidates].sort((a, b) => {
928
+ const orderDiff = typeOrder(a) - typeOrder(b);
929
+ if (orderDiff !== 0)
930
+ return orderDiff;
931
+ return b.score - a.score;
932
+ });
933
+ const result = [];
934
+ let tokensUsed = 0;
935
+ let excluded = 0;
936
+ for (const candidate of budgetOrdered) {
937
+ const entryTokens = Math.ceil(candidate.text.length / 4);
938
+ if (tokensUsed + entryTokens > tokenBudget) {
939
+ excluded++;
940
+ continue;
941
+ }
942
+ result.push({
943
+ id: candidate.id,
944
+ type: candidate.type,
945
+ title: candidate.title,
946
+ text: candidate.text,
947
+ score: candidate.score,
948
+ tokensEstimated: entryTokens,
949
+ memoryTier: candidate.memoryTier,
950
+ memoryType: candidate.memoryType,
951
+ });
952
+ tokensUsed += entryTokens;
953
+ }
954
+ // -------------------------------------------------------------------------
955
+ // Citation tracking — non-blocking background increment
956
+ // -------------------------------------------------------------------------
957
+ if (result.length > 0) {
958
+ const returnedIds = result.map((e) => e.id);
959
+ setImmediate(() => {
960
+ incrementCitationCounts(projectRoot, returnedIds).catch(() => {
961
+ /* best-effort */
962
+ });
963
+ });
964
+ }
965
+ return {
966
+ entries: result,
967
+ tokensUsed,
968
+ tokensRemaining: tokenBudget - tokensUsed,
969
+ excluded,
970
+ };
971
+ }
972
+ // ============================================================================
973
+ // Session ID Retrieval (for logRetrieval)
974
+ // ============================================================================
975
+ /**
976
+ * Get the current session ID from the session manager.
977
+ *
978
+ * This is a best-effort operation — if no session is active or session
979
+ * manager is unavailable, returns null. Used by logRetrieval to group
980
+ * retrievals by session for STDP analysis.
981
+ *
982
+ * @param projectRoot - Project root directory
983
+ * @returns Current session ID or null if unavailable
984
+ */
985
+ async function getCurrentSessionId(projectRoot) {
986
+ try {
987
+ const { sessionStatus } = await import('../sessions/index.js');
988
+ const session = await sessionStatus(projectRoot);
989
+ return session?.id;
990
+ }
991
+ catch {
992
+ // Session manager unavailable or other error — log retrievals without session
993
+ return undefined;
994
+ }
995
+ }
996
+ // ============================================================================
997
+ // Citation Count Increment (non-blocking helper)
998
+ // ============================================================================
999
+ /**
1000
+ * Increment citationCount for a list of entry IDs.
1001
+ *
1002
+ * Routes each ID to the correct table based on its ID prefix. All updates
1003
+ * are best-effort — errors are silently swallowed.
1004
+ *
1005
+ * @param projectRoot - Project root for brain.db resolution
1006
+ * @param ids - Entry IDs whose citation counts should be incremented
1007
+ */
1008
+ async function incrementCitationCounts(projectRoot, ids) {
1009
+ if (ids.length === 0)
1010
+ return;
1011
+ const { getBrainDb, getBrainNativeDb } = await import('../store/brain-sqlite.js');
1012
+ await getBrainDb(projectRoot);
1013
+ const nativeDb = getBrainNativeDb();
1014
+ if (!nativeDb)
1015
+ return;
1016
+ const now = new Date().toISOString().replace('T', ' ').slice(0, 19);
1017
+ for (const id of ids) {
1018
+ let table;
1019
+ if (id.startsWith('D-') || /^D\d/.test(id)) {
1020
+ table = 'brain_decisions';
1021
+ }
1022
+ else if (id.startsWith('P-') || /^P\d/.test(id)) {
1023
+ table = 'brain_patterns';
1024
+ }
1025
+ else if (id.startsWith('L-') || /^L\d/.test(id)) {
1026
+ table = 'brain_learnings';
1027
+ }
1028
+ else {
1029
+ table = 'brain_observations';
1030
+ }
1031
+ try {
1032
+ nativeDb
1033
+ .prepare(`UPDATE ${table} SET citation_count = citation_count + 1, updated_at = ? WHERE id = ?`)
1034
+ .run(now, id);
1035
+ }
1036
+ catch {
1037
+ /* best-effort — column may not exist in older schemas */
1038
+ }
1039
+ }
1040
+ }
1041
+ /**
1042
+ * Log a retrieval event to brain_retrieval_log for co-retrieval analysis.
1043
+ *
1044
+ * Creates the table on first use if it doesn't exist (self-healing).
1045
+ * Best-effort: errors are silently swallowed.
1046
+ *
1047
+ * @param projectRoot - Project root directory
1048
+ * @param query - The search query or fetch IDs
1049
+ * @param entryIds - Array of entry IDs returned in this retrieval
1050
+ * @param source - Retrieval source ('find', 'fetch', 'hybrid', 'timeline', 'budget')
1051
+ * @param tokensUsed - Estimated tokens consumed (optional)
1052
+ * @param sessionId - Session ID for grouping retrievals by session (optional, soft FK to tasks.db)
1053
+ */
1054
+ async function logRetrieval(projectRoot, query, entryIds, source, tokensUsed, sessionId) {
1055
+ if (entryIds.length === 0)
1056
+ return;
1057
+ const { getBrainDb, getBrainNativeDb } = await import('../store/brain-sqlite.js');
1058
+ await getBrainDb(projectRoot);
1059
+ const nativeDb = getBrainNativeDb();
1060
+ if (!nativeDb)
1061
+ return;
1062
+ // Self-healing: create table if not exists (includes session_id column)
1063
+ const createSql = 'CREATE TABLE IF NOT EXISTS brain_retrieval_log (' +
1064
+ 'id INTEGER PRIMARY KEY AUTOINCREMENT,' +
1065
+ 'query TEXT NOT NULL,' +
1066
+ 'entry_ids TEXT NOT NULL,' +
1067
+ 'entry_count INTEGER NOT NULL,' +
1068
+ 'source TEXT NOT NULL,' +
1069
+ 'tokens_used INTEGER,' +
1070
+ 'session_id TEXT,' +
1071
+ "created_at TEXT NOT NULL DEFAULT (datetime('now'))" +
1072
+ ')';
1073
+ try {
1074
+ nativeDb.prepare(createSql).run();
1075
+ }
1076
+ catch {
1077
+ return;
1078
+ }
1079
+ try {
1080
+ nativeDb
1081
+ .prepare('INSERT INTO brain_retrieval_log (query, entry_ids, entry_count, source, tokens_used, session_id) VALUES (?, ?, ?, ?, ?, ?)')
1082
+ .run(query, entryIds.join(','), entryIds.length, source, tokensUsed ?? null, sessionId ?? null);
1083
+ }
1084
+ catch {
1085
+ /* best-effort */
1086
+ }
1087
+ }
1088
+ //# sourceMappingURL=brain-retrieval.js.map