@soleri/core 2.1.0 → 2.5.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 (377) hide show
  1. package/dist/brain/brain.d.ts +10 -1
  2. package/dist/brain/brain.d.ts.map +1 -1
  3. package/dist/brain/brain.js +116 -13
  4. package/dist/brain/brain.js.map +1 -1
  5. package/dist/brain/intelligence.d.ts +36 -1
  6. package/dist/brain/intelligence.d.ts.map +1 -1
  7. package/dist/brain/intelligence.js +119 -14
  8. package/dist/brain/intelligence.js.map +1 -1
  9. package/dist/brain/types.d.ts +34 -2
  10. package/dist/brain/types.d.ts.map +1 -1
  11. package/dist/cognee/client.d.ts +3 -0
  12. package/dist/cognee/client.d.ts.map +1 -1
  13. package/dist/cognee/client.js +17 -0
  14. package/dist/cognee/client.js.map +1 -1
  15. package/dist/cognee/sync-manager.d.ts +94 -0
  16. package/dist/cognee/sync-manager.d.ts.map +1 -0
  17. package/dist/cognee/sync-manager.js +293 -0
  18. package/dist/cognee/sync-manager.js.map +1 -0
  19. package/dist/control/identity-manager.d.ts +22 -0
  20. package/dist/control/identity-manager.d.ts.map +1 -0
  21. package/dist/control/identity-manager.js +233 -0
  22. package/dist/control/identity-manager.js.map +1 -0
  23. package/dist/control/intent-router.d.ts +32 -0
  24. package/dist/control/intent-router.d.ts.map +1 -0
  25. package/dist/control/intent-router.js +242 -0
  26. package/dist/control/intent-router.js.map +1 -0
  27. package/dist/control/types.d.ts +68 -0
  28. package/dist/control/types.d.ts.map +1 -0
  29. package/dist/control/types.js +9 -0
  30. package/dist/control/types.js.map +1 -0
  31. package/dist/curator/curator.d.ts +37 -1
  32. package/dist/curator/curator.d.ts.map +1 -1
  33. package/dist/curator/curator.js +199 -1
  34. package/dist/curator/curator.js.map +1 -1
  35. package/dist/errors/classify.d.ts +13 -0
  36. package/dist/errors/classify.d.ts.map +1 -0
  37. package/dist/errors/classify.js +97 -0
  38. package/dist/errors/classify.js.map +1 -0
  39. package/dist/errors/index.d.ts +6 -0
  40. package/dist/errors/index.d.ts.map +1 -0
  41. package/dist/errors/index.js +4 -0
  42. package/dist/errors/index.js.map +1 -0
  43. package/dist/errors/retry.d.ts +40 -0
  44. package/dist/errors/retry.d.ts.map +1 -0
  45. package/dist/errors/retry.js +97 -0
  46. package/dist/errors/retry.js.map +1 -0
  47. package/dist/errors/types.d.ts +48 -0
  48. package/dist/errors/types.d.ts.map +1 -0
  49. package/dist/errors/types.js +59 -0
  50. package/dist/errors/types.js.map +1 -0
  51. package/dist/facades/types.d.ts +1 -1
  52. package/dist/governance/governance.d.ts +42 -0
  53. package/dist/governance/governance.d.ts.map +1 -0
  54. package/dist/governance/governance.js +488 -0
  55. package/dist/governance/governance.js.map +1 -0
  56. package/dist/governance/index.d.ts +3 -0
  57. package/dist/governance/index.d.ts.map +1 -0
  58. package/dist/governance/index.js +2 -0
  59. package/dist/governance/index.js.map +1 -0
  60. package/dist/governance/types.d.ts +102 -0
  61. package/dist/governance/types.d.ts.map +1 -0
  62. package/dist/governance/types.js +3 -0
  63. package/dist/governance/types.js.map +1 -0
  64. package/dist/index.d.ts +52 -3
  65. package/dist/index.d.ts.map +1 -1
  66. package/dist/index.js +47 -1
  67. package/dist/index.js.map +1 -1
  68. package/dist/intake/content-classifier.d.ts +14 -0
  69. package/dist/intake/content-classifier.d.ts.map +1 -0
  70. package/dist/intake/content-classifier.js +125 -0
  71. package/dist/intake/content-classifier.js.map +1 -0
  72. package/dist/intake/dedup-gate.d.ts +17 -0
  73. package/dist/intake/dedup-gate.d.ts.map +1 -0
  74. package/dist/intake/dedup-gate.js +66 -0
  75. package/dist/intake/dedup-gate.js.map +1 -0
  76. package/dist/intake/intake-pipeline.d.ts +63 -0
  77. package/dist/intake/intake-pipeline.d.ts.map +1 -0
  78. package/dist/intake/intake-pipeline.js +373 -0
  79. package/dist/intake/intake-pipeline.js.map +1 -0
  80. package/dist/intake/types.d.ts +65 -0
  81. package/dist/intake/types.d.ts.map +1 -0
  82. package/dist/intake/types.js +3 -0
  83. package/dist/intake/types.js.map +1 -0
  84. package/dist/intelligence/loader.js +1 -1
  85. package/dist/intelligence/loader.js.map +1 -1
  86. package/dist/intelligence/types.d.ts +3 -1
  87. package/dist/intelligence/types.d.ts.map +1 -1
  88. package/dist/logging/logger.d.ts +37 -0
  89. package/dist/logging/logger.d.ts.map +1 -0
  90. package/dist/logging/logger.js +145 -0
  91. package/dist/logging/logger.js.map +1 -0
  92. package/dist/logging/types.d.ts +19 -0
  93. package/dist/logging/types.d.ts.map +1 -0
  94. package/dist/logging/types.js +2 -0
  95. package/dist/logging/types.js.map +1 -0
  96. package/dist/loop/loop-manager.d.ts +100 -0
  97. package/dist/loop/loop-manager.d.ts.map +1 -0
  98. package/dist/loop/loop-manager.js +379 -0
  99. package/dist/loop/loop-manager.js.map +1 -0
  100. package/dist/loop/types.d.ts +103 -0
  101. package/dist/loop/types.d.ts.map +1 -0
  102. package/dist/loop/types.js +11 -0
  103. package/dist/loop/types.js.map +1 -0
  104. package/dist/persistence/index.d.ts +3 -0
  105. package/dist/persistence/index.d.ts.map +1 -0
  106. package/dist/persistence/index.js +2 -0
  107. package/dist/persistence/index.js.map +1 -0
  108. package/dist/persistence/sqlite-provider.d.ts +25 -0
  109. package/dist/persistence/sqlite-provider.d.ts.map +1 -0
  110. package/dist/persistence/sqlite-provider.js +59 -0
  111. package/dist/persistence/sqlite-provider.js.map +1 -0
  112. package/dist/persistence/types.d.ts +36 -0
  113. package/dist/persistence/types.d.ts.map +1 -0
  114. package/dist/persistence/types.js +8 -0
  115. package/dist/persistence/types.js.map +1 -0
  116. package/dist/planning/gap-analysis.d.ts +72 -0
  117. package/dist/planning/gap-analysis.d.ts.map +1 -0
  118. package/dist/planning/gap-analysis.js +442 -0
  119. package/dist/planning/gap-analysis.js.map +1 -0
  120. package/dist/planning/gap-types.d.ts +29 -0
  121. package/dist/planning/gap-types.d.ts.map +1 -0
  122. package/dist/planning/gap-types.js +28 -0
  123. package/dist/planning/gap-types.js.map +1 -0
  124. package/dist/planning/planner.d.ts +421 -4
  125. package/dist/planning/planner.d.ts.map +1 -1
  126. package/dist/planning/planner.js +949 -21
  127. package/dist/planning/planner.js.map +1 -1
  128. package/dist/playbooks/generic/brainstorming.d.ts +9 -0
  129. package/dist/playbooks/generic/brainstorming.d.ts.map +1 -0
  130. package/dist/playbooks/generic/brainstorming.js +105 -0
  131. package/dist/playbooks/generic/brainstorming.js.map +1 -0
  132. package/dist/playbooks/generic/code-review.d.ts +11 -0
  133. package/dist/playbooks/generic/code-review.d.ts.map +1 -0
  134. package/dist/playbooks/generic/code-review.js +176 -0
  135. package/dist/playbooks/generic/code-review.js.map +1 -0
  136. package/dist/playbooks/generic/subagent-execution.d.ts +9 -0
  137. package/dist/playbooks/generic/subagent-execution.d.ts.map +1 -0
  138. package/dist/playbooks/generic/subagent-execution.js +68 -0
  139. package/dist/playbooks/generic/subagent-execution.js.map +1 -0
  140. package/dist/playbooks/generic/systematic-debugging.d.ts +9 -0
  141. package/dist/playbooks/generic/systematic-debugging.d.ts.map +1 -0
  142. package/dist/playbooks/generic/systematic-debugging.js +87 -0
  143. package/dist/playbooks/generic/systematic-debugging.js.map +1 -0
  144. package/dist/playbooks/generic/tdd.d.ts +9 -0
  145. package/dist/playbooks/generic/tdd.d.ts.map +1 -0
  146. package/dist/playbooks/generic/tdd.js +70 -0
  147. package/dist/playbooks/generic/tdd.js.map +1 -0
  148. package/dist/playbooks/generic/verification.d.ts +9 -0
  149. package/dist/playbooks/generic/verification.d.ts.map +1 -0
  150. package/dist/playbooks/generic/verification.js +74 -0
  151. package/dist/playbooks/generic/verification.js.map +1 -0
  152. package/dist/playbooks/index.d.ts +4 -0
  153. package/dist/playbooks/index.d.ts.map +1 -0
  154. package/dist/playbooks/index.js +5 -0
  155. package/dist/playbooks/index.js.map +1 -0
  156. package/dist/playbooks/playbook-registry.d.ts +42 -0
  157. package/dist/playbooks/playbook-registry.d.ts.map +1 -0
  158. package/dist/playbooks/playbook-registry.js +227 -0
  159. package/dist/playbooks/playbook-registry.js.map +1 -0
  160. package/dist/playbooks/playbook-seeder.d.ts +47 -0
  161. package/dist/playbooks/playbook-seeder.d.ts.map +1 -0
  162. package/dist/playbooks/playbook-seeder.js +104 -0
  163. package/dist/playbooks/playbook-seeder.js.map +1 -0
  164. package/dist/playbooks/playbook-types.d.ts +132 -0
  165. package/dist/playbooks/playbook-types.d.ts.map +1 -0
  166. package/dist/playbooks/playbook-types.js +12 -0
  167. package/dist/playbooks/playbook-types.js.map +1 -0
  168. package/dist/project/project-registry.d.ts +79 -0
  169. package/dist/project/project-registry.d.ts.map +1 -0
  170. package/dist/project/project-registry.js +274 -0
  171. package/dist/project/project-registry.js.map +1 -0
  172. package/dist/project/types.d.ts +28 -0
  173. package/dist/project/types.d.ts.map +1 -0
  174. package/dist/project/types.js +5 -0
  175. package/dist/project/types.js.map +1 -0
  176. package/dist/prompts/index.d.ts +4 -0
  177. package/dist/prompts/index.d.ts.map +1 -0
  178. package/dist/prompts/index.js +3 -0
  179. package/dist/prompts/index.js.map +1 -0
  180. package/dist/prompts/parser.d.ts +17 -0
  181. package/dist/prompts/parser.d.ts.map +1 -0
  182. package/dist/prompts/parser.js +47 -0
  183. package/dist/prompts/parser.js.map +1 -0
  184. package/dist/prompts/template-manager.d.ts +25 -0
  185. package/dist/prompts/template-manager.d.ts.map +1 -0
  186. package/dist/prompts/template-manager.js +71 -0
  187. package/dist/prompts/template-manager.js.map +1 -0
  188. package/dist/prompts/types.d.ts +26 -0
  189. package/dist/prompts/types.d.ts.map +1 -0
  190. package/dist/prompts/types.js +5 -0
  191. package/dist/prompts/types.js.map +1 -0
  192. package/dist/runtime/admin-extra-ops.d.ts +15 -0
  193. package/dist/runtime/admin-extra-ops.d.ts.map +1 -0
  194. package/dist/runtime/admin-extra-ops.js +595 -0
  195. package/dist/runtime/admin-extra-ops.js.map +1 -0
  196. package/dist/runtime/admin-ops.d.ts +15 -0
  197. package/dist/runtime/admin-ops.d.ts.map +1 -0
  198. package/dist/runtime/admin-ops.js +329 -0
  199. package/dist/runtime/admin-ops.js.map +1 -0
  200. package/dist/runtime/capture-ops.d.ts +15 -0
  201. package/dist/runtime/capture-ops.d.ts.map +1 -0
  202. package/dist/runtime/capture-ops.js +363 -0
  203. package/dist/runtime/capture-ops.js.map +1 -0
  204. package/dist/runtime/cognee-sync-ops.d.ts +12 -0
  205. package/dist/runtime/cognee-sync-ops.d.ts.map +1 -0
  206. package/dist/runtime/cognee-sync-ops.js +55 -0
  207. package/dist/runtime/cognee-sync-ops.js.map +1 -0
  208. package/dist/runtime/core-ops.d.ts +9 -3
  209. package/dist/runtime/core-ops.d.ts.map +1 -1
  210. package/dist/runtime/core-ops.js +693 -10
  211. package/dist/runtime/core-ops.js.map +1 -1
  212. package/dist/runtime/curator-extra-ops.d.ts +9 -0
  213. package/dist/runtime/curator-extra-ops.d.ts.map +1 -0
  214. package/dist/runtime/curator-extra-ops.js +71 -0
  215. package/dist/runtime/curator-extra-ops.js.map +1 -0
  216. package/dist/runtime/domain-ops.d.ts.map +1 -1
  217. package/dist/runtime/domain-ops.js +61 -15
  218. package/dist/runtime/domain-ops.js.map +1 -1
  219. package/dist/runtime/grading-ops.d.ts +14 -0
  220. package/dist/runtime/grading-ops.d.ts.map +1 -0
  221. package/dist/runtime/grading-ops.js +105 -0
  222. package/dist/runtime/grading-ops.js.map +1 -0
  223. package/dist/runtime/intake-ops.d.ts +14 -0
  224. package/dist/runtime/intake-ops.d.ts.map +1 -0
  225. package/dist/runtime/intake-ops.js +110 -0
  226. package/dist/runtime/intake-ops.js.map +1 -0
  227. package/dist/runtime/loop-ops.d.ts +14 -0
  228. package/dist/runtime/loop-ops.d.ts.map +1 -0
  229. package/dist/runtime/loop-ops.js +251 -0
  230. package/dist/runtime/loop-ops.js.map +1 -0
  231. package/dist/runtime/memory-cross-project-ops.d.ts +12 -0
  232. package/dist/runtime/memory-cross-project-ops.d.ts.map +1 -0
  233. package/dist/runtime/memory-cross-project-ops.js +165 -0
  234. package/dist/runtime/memory-cross-project-ops.js.map +1 -0
  235. package/dist/runtime/memory-extra-ops.d.ts +13 -0
  236. package/dist/runtime/memory-extra-ops.d.ts.map +1 -0
  237. package/dist/runtime/memory-extra-ops.js +173 -0
  238. package/dist/runtime/memory-extra-ops.js.map +1 -0
  239. package/dist/runtime/orchestrate-ops.d.ts +17 -0
  240. package/dist/runtime/orchestrate-ops.d.ts.map +1 -0
  241. package/dist/runtime/orchestrate-ops.js +246 -0
  242. package/dist/runtime/orchestrate-ops.js.map +1 -0
  243. package/dist/runtime/planning-extra-ops.d.ts +25 -0
  244. package/dist/runtime/planning-extra-ops.d.ts.map +1 -0
  245. package/dist/runtime/planning-extra-ops.js +663 -0
  246. package/dist/runtime/planning-extra-ops.js.map +1 -0
  247. package/dist/runtime/playbook-ops.d.ts +14 -0
  248. package/dist/runtime/playbook-ops.d.ts.map +1 -0
  249. package/dist/runtime/playbook-ops.js +141 -0
  250. package/dist/runtime/playbook-ops.js.map +1 -0
  251. package/dist/runtime/project-ops.d.ts +15 -0
  252. package/dist/runtime/project-ops.d.ts.map +1 -0
  253. package/dist/runtime/project-ops.js +186 -0
  254. package/dist/runtime/project-ops.js.map +1 -0
  255. package/dist/runtime/runtime.d.ts.map +1 -1
  256. package/dist/runtime/runtime.js +65 -3
  257. package/dist/runtime/runtime.js.map +1 -1
  258. package/dist/runtime/types.d.ts +29 -0
  259. package/dist/runtime/types.d.ts.map +1 -1
  260. package/dist/runtime/vault-extra-ops.d.ts +10 -0
  261. package/dist/runtime/vault-extra-ops.d.ts.map +1 -0
  262. package/dist/runtime/vault-extra-ops.js +536 -0
  263. package/dist/runtime/vault-extra-ops.js.map +1 -0
  264. package/dist/telemetry/telemetry.d.ts +48 -0
  265. package/dist/telemetry/telemetry.d.ts.map +1 -0
  266. package/dist/telemetry/telemetry.js +87 -0
  267. package/dist/telemetry/telemetry.js.map +1 -0
  268. package/dist/vault/playbook.d.ts +34 -0
  269. package/dist/vault/playbook.d.ts.map +1 -0
  270. package/dist/vault/playbook.js +60 -0
  271. package/dist/vault/playbook.js.map +1 -0
  272. package/dist/vault/vault.d.ts +97 -4
  273. package/dist/vault/vault.d.ts.map +1 -1
  274. package/dist/vault/vault.js +424 -65
  275. package/dist/vault/vault.js.map +1 -1
  276. package/package.json +7 -3
  277. package/src/__tests__/admin-extra-ops.test.ts +467 -0
  278. package/src/__tests__/admin-ops.test.ts +271 -0
  279. package/src/__tests__/brain-intelligence.test.ts +205 -0
  280. package/src/__tests__/brain.test.ts +134 -3
  281. package/src/__tests__/capture-ops.test.ts +509 -0
  282. package/src/__tests__/cognee-integration.test.ts +80 -0
  283. package/src/__tests__/cognee-sync-manager.test.ts +103 -0
  284. package/src/__tests__/core-ops.test.ts +292 -2
  285. package/src/__tests__/curator-extra-ops.test.ts +381 -0
  286. package/src/__tests__/domain-ops.test.ts +66 -0
  287. package/src/__tests__/errors.test.ts +388 -0
  288. package/src/__tests__/governance.test.ts +522 -0
  289. package/src/__tests__/grading-ops.test.ts +361 -0
  290. package/src/__tests__/identity-manager.test.ts +243 -0
  291. package/src/__tests__/intake-pipeline.test.ts +162 -0
  292. package/src/__tests__/intent-router.test.ts +222 -0
  293. package/src/__tests__/logger.test.ts +200 -0
  294. package/src/__tests__/loop-ops.test.ts +469 -0
  295. package/src/__tests__/memory-cross-project-ops.test.ts +248 -0
  296. package/src/__tests__/memory-extra-ops.test.ts +352 -0
  297. package/src/__tests__/orchestrate-ops.test.ts +289 -0
  298. package/src/__tests__/persistence.test.ts +225 -0
  299. package/src/__tests__/planner.test.ts +416 -7
  300. package/src/__tests__/planning-extra-ops.test.ts +706 -0
  301. package/src/__tests__/playbook-registry.test.ts +326 -0
  302. package/src/__tests__/playbook-seeder.test.ts +163 -0
  303. package/src/__tests__/playbook.test.ts +389 -0
  304. package/src/__tests__/project-ops.test.ts +381 -0
  305. package/src/__tests__/template-manager.test.ts +222 -0
  306. package/src/__tests__/vault-extra-ops.test.ts +482 -0
  307. package/src/brain/brain.ts +185 -16
  308. package/src/brain/intelligence.ts +179 -10
  309. package/src/brain/types.ts +40 -2
  310. package/src/cognee/client.ts +18 -0
  311. package/src/cognee/sync-manager.ts +389 -0
  312. package/src/control/identity-manager.ts +354 -0
  313. package/src/control/intent-router.ts +326 -0
  314. package/src/control/types.ts +102 -0
  315. package/src/curator/curator.ts +295 -1
  316. package/src/errors/classify.ts +102 -0
  317. package/src/errors/index.ts +5 -0
  318. package/src/errors/retry.ts +132 -0
  319. package/src/errors/types.ts +81 -0
  320. package/src/governance/governance.ts +698 -0
  321. package/src/governance/index.ts +18 -0
  322. package/src/governance/types.ts +111 -0
  323. package/src/index.ts +213 -2
  324. package/src/intake/content-classifier.ts +146 -0
  325. package/src/intake/dedup-gate.ts +92 -0
  326. package/src/intake/intake-pipeline.ts +503 -0
  327. package/src/intake/types.ts +69 -0
  328. package/src/intelligence/loader.ts +1 -1
  329. package/src/intelligence/types.ts +3 -1
  330. package/src/logging/logger.ts +154 -0
  331. package/src/logging/types.ts +21 -0
  332. package/src/loop/loop-manager.ts +448 -0
  333. package/src/loop/types.ts +115 -0
  334. package/src/persistence/index.ts +7 -0
  335. package/src/persistence/sqlite-provider.ts +62 -0
  336. package/src/persistence/types.ts +44 -0
  337. package/src/planning/gap-analysis.ts +775 -0
  338. package/src/planning/gap-types.ts +61 -0
  339. package/src/planning/planner.ts +1273 -24
  340. package/src/playbooks/generic/brainstorming.ts +110 -0
  341. package/src/playbooks/generic/code-review.ts +181 -0
  342. package/src/playbooks/generic/subagent-execution.ts +74 -0
  343. package/src/playbooks/generic/systematic-debugging.ts +92 -0
  344. package/src/playbooks/generic/tdd.ts +75 -0
  345. package/src/playbooks/generic/verification.ts +79 -0
  346. package/src/playbooks/index.ts +27 -0
  347. package/src/playbooks/playbook-registry.ts +284 -0
  348. package/src/playbooks/playbook-seeder.ts +119 -0
  349. package/src/playbooks/playbook-types.ts +162 -0
  350. package/src/project/project-registry.ts +370 -0
  351. package/src/project/types.ts +31 -0
  352. package/src/prompts/index.ts +3 -0
  353. package/src/prompts/parser.ts +59 -0
  354. package/src/prompts/template-manager.ts +77 -0
  355. package/src/prompts/types.ts +28 -0
  356. package/src/runtime/admin-extra-ops.ts +652 -0
  357. package/src/runtime/admin-ops.ts +340 -0
  358. package/src/runtime/capture-ops.ts +404 -0
  359. package/src/runtime/cognee-sync-ops.ts +63 -0
  360. package/src/runtime/core-ops.ts +787 -9
  361. package/src/runtime/curator-extra-ops.ts +85 -0
  362. package/src/runtime/domain-ops.ts +67 -15
  363. package/src/runtime/grading-ops.ts +130 -0
  364. package/src/runtime/intake-ops.ts +126 -0
  365. package/src/runtime/loop-ops.ts +277 -0
  366. package/src/runtime/memory-cross-project-ops.ts +191 -0
  367. package/src/runtime/memory-extra-ops.ts +186 -0
  368. package/src/runtime/orchestrate-ops.ts +278 -0
  369. package/src/runtime/planning-extra-ops.ts +718 -0
  370. package/src/runtime/playbook-ops.ts +169 -0
  371. package/src/runtime/project-ops.ts +202 -0
  372. package/src/runtime/runtime.ts +77 -3
  373. package/src/runtime/types.ts +29 -0
  374. package/src/runtime/vault-extra-ops.ts +606 -0
  375. package/src/telemetry/telemetry.ts +118 -0
  376. package/src/vault/playbook.ts +87 -0
  377. package/src/vault/vault.ts +575 -98
@@ -17,6 +17,9 @@ import type {
17
17
  CaptureResult,
18
18
  BrainStats,
19
19
  QueryContext,
20
+ FeedbackInput,
21
+ FeedbackEntry,
22
+ FeedbackStats,
20
23
  } from './types.js';
21
24
 
22
25
  // Re-export types for backward compatibility
@@ -44,7 +47,7 @@ const DEFAULT_WEIGHTS: ScoringWeights = {
44
47
  semantic: 0.4,
45
48
  vector: 0.0,
46
49
  severity: 0.15,
47
- recency: 0.15,
50
+ temporalDecay: 0.15,
48
51
  tagOverlap: 0.15,
49
52
  domainMatch: 0.15,
50
53
  };
@@ -53,7 +56,7 @@ const COGNEE_WEIGHTS: ScoringWeights = {
53
56
  semantic: 0.25,
54
57
  vector: 0.35,
55
58
  severity: 0.1,
56
- recency: 0.1,
59
+ temporalDecay: 0.1,
57
60
  tagOverlap: 0.1,
58
61
  domainMatch: 0.1,
59
62
  };
@@ -268,14 +271,109 @@ export class Brain {
268
271
  return result;
269
272
  }
270
273
 
271
- recordFeedback(query: string, entryId: string, action: 'accepted' | 'dismissed'): void {
274
+ recordFeedback(query: string, entryId: string, action: 'accepted' | 'dismissed'): void;
275
+ recordFeedback(input: FeedbackInput): FeedbackEntry;
276
+ recordFeedback(
277
+ queryOrInput: string | FeedbackInput,
278
+ entryId?: string,
279
+ action?: 'accepted' | 'dismissed',
280
+ ): void | FeedbackEntry {
272
281
  const db = this.vault.getDb();
273
- db.prepare('INSERT INTO brain_feedback (query, entry_id, action) VALUES (?, ?, ?)').run(
274
- query,
275
- entryId,
276
- action,
282
+
283
+ // Normalize to FeedbackInput
284
+ const input: FeedbackInput =
285
+ typeof queryOrInput === 'string'
286
+ ? { query: queryOrInput, entryId: entryId!, action: action! }
287
+ : queryOrInput;
288
+
289
+ db.prepare(
290
+ `INSERT INTO brain_feedback (query, entry_id, action, source, confidence, duration, context, reason)
291
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,
292
+ ).run(
293
+ input.query,
294
+ input.entryId,
295
+ input.action,
296
+ input.source ?? 'search',
297
+ input.confidence ?? 0.6,
298
+ input.duration ?? null,
299
+ input.context ?? '{}',
300
+ input.reason ?? null,
277
301
  );
278
302
  this.recomputeWeights();
303
+
304
+ // Return FeedbackEntry only for the object overload
305
+ if (typeof queryOrInput !== 'string') {
306
+ const row = db
307
+ .prepare(
308
+ 'SELECT * FROM brain_feedback WHERE query = ? AND entry_id = ? ORDER BY id DESC LIMIT 1',
309
+ )
310
+ .get(input.query, input.entryId) as {
311
+ id: number;
312
+ query: string;
313
+ entry_id: string;
314
+ action: string;
315
+ source: string;
316
+ confidence: number;
317
+ duration: number | null;
318
+ context: string;
319
+ reason: string | null;
320
+ created_at: number;
321
+ };
322
+ return {
323
+ id: row.id,
324
+ query: row.query,
325
+ entryId: row.entry_id,
326
+ action: row.action as FeedbackEntry['action'],
327
+ source: row.source as FeedbackEntry['source'],
328
+ confidence: row.confidence,
329
+ duration: row.duration,
330
+ context: row.context,
331
+ reason: row.reason,
332
+ createdAt: row.created_at,
333
+ };
334
+ }
335
+ }
336
+
337
+ getFeedbackStats(): FeedbackStats {
338
+ const db = this.vault.getDb();
339
+
340
+ const total = (
341
+ db.prepare('SELECT COUNT(*) as count FROM brain_feedback').get() as { count: number }
342
+ ).count;
343
+
344
+ const byAction: Record<string, number> = {};
345
+ const actionRows = db
346
+ .prepare('SELECT action, COUNT(*) as count FROM brain_feedback GROUP BY action')
347
+ .all() as Array<{ action: string; count: number }>;
348
+ for (const row of actionRows) {
349
+ byAction[row.action] = row.count;
350
+ }
351
+
352
+ const bySource: Record<string, number> = {};
353
+ const sourceRows = db
354
+ .prepare('SELECT source, COUNT(*) as count FROM brain_feedback GROUP BY source')
355
+ .all() as Array<{ source: string; count: number }>;
356
+ for (const row of sourceRows) {
357
+ bySource[row.source] = row.count;
358
+ }
359
+
360
+ const accepted = byAction['accepted'] ?? 0;
361
+ const acceptanceRate = total > 0 ? accepted / total : 0;
362
+
363
+ const avgConf =
364
+ (
365
+ db.prepare('SELECT AVG(confidence) as avg FROM brain_feedback').get() as {
366
+ avg: number | null;
367
+ }
368
+ ).avg ?? 0;
369
+
370
+ return {
371
+ total,
372
+ byAction,
373
+ bySource,
374
+ acceptanceRate,
375
+ averageConfidence: avgConf,
376
+ };
279
377
  }
280
378
 
281
379
  async getRelevantPatterns(context: QueryContext): Promise<RankedResult[]> {
@@ -356,6 +454,42 @@ export class Brain {
356
454
  return this.vocabulary.size;
357
455
  }
358
456
 
457
+ async getDecayReport(
458
+ query: string,
459
+ limit: number = 10,
460
+ ): Promise<
461
+ Array<{
462
+ id: string;
463
+ title: string;
464
+ decayScore: number;
465
+ validUntil: number | null;
466
+ status: 'active' | 'expiring' | 'expired';
467
+ }>
468
+ > {
469
+ const results = await this.intelligentSearch(query, { limit });
470
+ const now = Math.floor(Date.now() / 1000);
471
+ return results.map((r) => {
472
+ const validUntil = r.entry.validUntil ?? null;
473
+ let status: 'active' | 'expiring' | 'expired' = 'active';
474
+ if (validUntil) {
475
+ if (validUntil <= now) status = 'expired';
476
+ else {
477
+ const validFrom = r.entry.validFrom ?? now;
478
+ const totalWindow = validUntil - validFrom;
479
+ const remaining = validUntil - now;
480
+ if (remaining <= totalWindow * 0.25) status = 'expiring';
481
+ }
482
+ }
483
+ return {
484
+ id: r.entry.id,
485
+ title: r.entry.title,
486
+ decayScore: r.breakdown.temporalDecay,
487
+ validUntil,
488
+ status,
489
+ };
490
+ });
491
+ }
492
+
359
493
  // ─── Private methods ─────────────────────────────────────────────
360
494
 
361
495
  private scoreEntry(
@@ -385,9 +519,7 @@ export class Brain {
385
519
 
386
520
  const severity = SEVERITY_SCORES[entry.severity] ?? 0.4;
387
521
 
388
- const entryAge = now - (entry as unknown as { created_at?: number }).created_at!;
389
- const halfLifeSeconds = RECENCY_HALF_LIFE_DAYS * 86400;
390
- const recency = entryAge > 0 ? Math.exp((-Math.LN2 * entryAge) / halfLifeSeconds) : 1;
522
+ const temporalDecay = computeTemporalDecay(entry, now);
391
523
 
392
524
  const tagOverlap = queryTags.length > 0 ? jaccardSimilarity(queryTags, entry.tags) : 0;
393
525
 
@@ -399,11 +531,11 @@ export class Brain {
399
531
  w.semantic * semantic +
400
532
  w.vector * vector +
401
533
  w.severity * severity +
402
- w.recency * recency +
534
+ w.temporalDecay * temporalDecay +
403
535
  w.tagOverlap * tagOverlap +
404
536
  w.domainMatch * domainMatch;
405
537
 
406
- return { semantic, vector, severity, recency, tagOverlap, domainMatch, total };
538
+ return { semantic, vector, severity, temporalDecay, tagOverlap, domainMatch, total };
407
539
  }
408
540
 
409
541
  private generateTags(title: string, description: string, context?: string): string[] {
@@ -503,8 +635,11 @@ export class Brain {
503
635
 
504
636
  private recomputeWeights(): void {
505
637
  const db = this.vault.getDb();
638
+ // Exclude 'failed' from weight computation — system errors don't indicate relevance
506
639
  const feedbackCount = (
507
- db.prepare('SELECT COUNT(*) as count FROM brain_feedback').get() as { count: number }
640
+ db.prepare("SELECT COUNT(*) as count FROM brain_feedback WHERE action != 'failed'").get() as {
641
+ count: number;
642
+ }
508
643
  ).count;
509
644
  if (feedbackCount < FEEDBACK_THRESHOLD) {
510
645
  this.weights = { ...DEFAULT_WEIGHTS };
@@ -516,7 +651,13 @@ export class Brain {
516
651
  .prepare("SELECT COUNT(*) as count FROM brain_feedback WHERE action = 'accepted'")
517
652
  .get() as { count: number }
518
653
  ).count;
519
- const acceptRate = feedbackCount > 0 ? accepted / feedbackCount : 0.5;
654
+ // 'modified' counts as 0.5 positive user adjusted but didn't dismiss
655
+ const modified = (
656
+ db
657
+ .prepare("SELECT COUNT(*) as count FROM brain_feedback WHERE action = 'modified'")
658
+ .get() as { count: number }
659
+ ).count;
660
+ const acceptRate = feedbackCount > 0 ? (accepted + modified * 0.5) / feedbackCount : 0.5;
520
661
 
521
662
  const semanticDelta = (acceptRate - 0.5) * WEIGHT_BOUND * 2;
522
663
 
@@ -533,12 +674,12 @@ export class Brain {
533
674
  const remaining = 1.0 - newWeights.semantic - newWeights.vector;
534
675
  const otherSum =
535
676
  DEFAULT_WEIGHTS.severity +
536
- DEFAULT_WEIGHTS.recency +
677
+ DEFAULT_WEIGHTS.temporalDecay +
537
678
  DEFAULT_WEIGHTS.tagOverlap +
538
679
  DEFAULT_WEIGHTS.domainMatch;
539
680
  const scale = remaining / otherSum;
540
681
  newWeights.severity = DEFAULT_WEIGHTS.severity * scale;
541
- newWeights.recency = DEFAULT_WEIGHTS.recency * scale;
682
+ newWeights.temporalDecay = DEFAULT_WEIGHTS.temporalDecay * scale;
542
683
  newWeights.tagOverlap = DEFAULT_WEIGHTS.tagOverlap * scale;
543
684
  newWeights.domainMatch = DEFAULT_WEIGHTS.domainMatch * scale;
544
685
 
@@ -546,6 +687,34 @@ export class Brain {
546
687
  }
547
688
  }
548
689
 
690
+ function computeTemporalDecay(entry: IntelligenceEntry, now: number): number {
691
+ const entryRecord = entry as unknown as {
692
+ created_at?: number;
693
+ updated_at?: number;
694
+ valid_until?: number;
695
+ valid_from?: number;
696
+ };
697
+ const validUntil = entry.validUntil ?? entryRecord.valid_until;
698
+
699
+ if (!validUntil) {
700
+ // No expiry — use existing age-based exponential decay
701
+ const updatedAt = entryRecord.updated_at ?? entryRecord.created_at ?? now;
702
+ const ageSeconds = now - updatedAt;
703
+ const halfLifeSeconds = RECENCY_HALF_LIFE_DAYS * 86400;
704
+ return ageSeconds > 0 ? Math.exp((-Math.LN2 * ageSeconds) / halfLifeSeconds) : 1;
705
+ }
706
+
707
+ // With valid_until: linear ramp-down in last 25% of validity window
708
+ const validFrom = entry.validFrom ?? entryRecord.valid_from ?? entryRecord.created_at ?? now;
709
+ const totalWindow = validUntil - validFrom;
710
+ const remaining = validUntil - now;
711
+ if (remaining <= 0) return 0; // expired
712
+ if (totalWindow <= 0) return 1; // edge case: bad data
713
+ const decayZone = totalWindow * 0.25;
714
+ if (remaining > decayZone) return 1.0; // fully valid
715
+ return remaining / decayZone; // linear decay in last quarter
716
+ }
717
+
549
718
  function clamp(value: number, min: number, max: number): number {
550
719
  return Math.max(min, Math.min(max, value));
551
720
  }
@@ -77,7 +77,8 @@ export class BrainIntelligence {
77
77
  tools_used TEXT NOT NULL DEFAULT '[]',
78
78
  files_modified TEXT NOT NULL DEFAULT '[]',
79
79
  plan_id TEXT,
80
- plan_outcome TEXT
80
+ plan_outcome TEXT,
81
+ extracted_at TEXT
81
82
  );
82
83
 
83
84
  CREATE TABLE IF NOT EXISTS brain_proposals (
@@ -161,9 +162,34 @@ export class BrainIntelligence {
161
162
  values.push(sessionId);
162
163
  db.prepare(`UPDATE brain_sessions SET ${updates.join(', ')} WHERE id = ?`).run(...values);
163
164
 
165
+ // Auto-extract knowledge if session has enough signal
166
+ this.autoExtractIfReady(this.getSession(sessionId)!);
167
+
168
+ // Return fresh session (extractedAt may have been set by auto-extract)
164
169
  return this.getSession(sessionId)!;
165
170
  }
166
171
 
172
+ /**
173
+ * Attempt auto-extraction after session end if the session has enough signal.
174
+ * Gate: at least 1 tool used OR 1 file modified OR a plan was associated.
175
+ * Silently skips if already extracted or insufficient data.
176
+ */
177
+ private autoExtractIfReady(session: BrainSession): void {
178
+ if (!session.endedAt) return;
179
+ if (session.extractedAt) return;
180
+
181
+ const hasSignal =
182
+ session.toolsUsed.length > 0 || session.filesModified.length > 0 || session.planId !== null;
183
+
184
+ if (!hasSignal) return;
185
+
186
+ try {
187
+ this.extractKnowledge(session.id);
188
+ } catch {
189
+ // Non-critical — don't break session end
190
+ }
191
+ }
192
+
167
193
  getSessionContext(limit = 10): SessionContext {
168
194
  const db = this.vault.getDb();
169
195
 
@@ -179,6 +205,7 @@ export class BrainIntelligence {
179
205
  files_modified: string;
180
206
  plan_id: string | null;
181
207
  plan_outcome: string | null;
208
+ extracted_at: string | null;
182
209
  }>;
183
210
 
184
211
  const sessions = rows.map((r) => this.rowToSession(r));
@@ -230,6 +257,8 @@ export class BrainIntelligence {
230
257
  COUNT(*) as total,
231
258
  SUM(CASE WHEN action = 'accepted' THEN 1 ELSE 0 END) as accepted,
232
259
  SUM(CASE WHEN action = 'dismissed' THEN 1 ELSE 0 END) as dismissed,
260
+ SUM(CASE WHEN action = 'modified' THEN 1 ELSE 0 END) as modified,
261
+ SUM(CASE WHEN action = 'failed' THEN 1 ELSE 0 END) as failed,
233
262
  MAX(created_at) as last_used
234
263
  FROM brain_feedback
235
264
  GROUP BY entry_id`,
@@ -239,6 +268,8 @@ export class BrainIntelligence {
239
268
  total: number;
240
269
  accepted: number;
241
270
  dismissed: number;
271
+ modified: number;
272
+ failed: number;
242
273
  last_used: string;
243
274
  }>;
244
275
 
@@ -265,7 +296,10 @@ export class BrainIntelligence {
265
296
  const spreadScore = Math.min(25, (uniqueContexts / SPREAD_MAX) * 25);
266
297
 
267
298
  // Success score: 25 * successRate
268
- const successRate = row.total > 0 ? row.accepted / row.total : 0;
299
+ // modified = 0.5 positive, failed = excluded (system error, not relevance)
300
+ const relevantTotal = row.total - row.failed;
301
+ const successRate =
302
+ relevantTotal > 0 ? (row.accepted + row.modified * 0.5) / relevantTotal : 0;
269
303
  const successScore = 25 * successRate;
270
304
 
271
305
  // Recency score: max(0, 25 * (1 - daysSince / RECENCY_DECAY_DAYS))
@@ -364,12 +398,17 @@ export class BrainIntelligence {
364
398
  }));
365
399
  }
366
400
 
367
- recommend(context: { domain?: string; task?: string; limit?: number }): PatternStrength[] {
401
+ recommend(context: {
402
+ domain?: string;
403
+ task?: string;
404
+ source?: string;
405
+ limit?: number;
406
+ }): PatternStrength[] {
368
407
  const limit = context.limit ?? 5;
369
408
  const strengths = this.getStrengths({
370
409
  domain: context.domain,
371
410
  minStrength: 30,
372
- limit: limit * 2,
411
+ limit: limit * 3,
373
412
  });
374
413
 
375
414
  // If task context provided, boost patterns with matching terms
@@ -383,9 +422,36 @@ export class BrainIntelligence {
383
422
  (s as { strength: number }).strength += overlap * 5;
384
423
  }
385
424
  }
386
- strengths.sort((a, b) => b.strength - a.strength);
387
425
  }
388
426
 
427
+ // Boost patterns with high source-specific acceptance rates
428
+ if (context.source) {
429
+ const db = this.vault.getDb();
430
+ for (const s of strengths) {
431
+ const row = db
432
+ .prepare(
433
+ `SELECT COUNT(*) as total,
434
+ SUM(CASE WHEN action = 'accepted' THEN 1 ELSE 0 END) as accepted,
435
+ SUM(CASE WHEN action = 'modified' THEN 1 ELSE 0 END) as modified
436
+ FROM brain_feedback
437
+ WHERE entry_id = (SELECT id FROM entries WHERE title = ? LIMIT 1)
438
+ AND source = ?`,
439
+ )
440
+ .get(s.pattern, context.source) as {
441
+ total: number;
442
+ accepted: number;
443
+ modified: number;
444
+ };
445
+
446
+ if (row.total >= 3) {
447
+ const sourceRate = (row.accepted + row.modified * 0.5) / row.total;
448
+ // Boost up to +10 points for high source-specific acceptance
449
+ (s as { strength: number }).strength += sourceRate * 10;
450
+ }
451
+ }
452
+ }
453
+
454
+ strengths.sort((a, b) => b.strength - a.strength);
389
455
  return strengths.slice(0, limit);
390
456
  }
391
457
 
@@ -510,6 +576,11 @@ export class BrainIntelligence {
510
576
  }
511
577
  }
512
578
 
579
+ // Mark session as extracted
580
+ db.prepare("UPDATE brain_sessions SET extracted_at = datetime('now') WHERE id = ?").run(
581
+ sessionId,
582
+ );
583
+
513
584
  return {
514
585
  sessionId,
515
586
  proposals,
@@ -517,6 +588,37 @@ export class BrainIntelligence {
517
588
  };
518
589
  }
519
590
 
591
+ resetExtracted(options?: { sessionId?: string; since?: string; all?: boolean }): {
592
+ reset: number;
593
+ } {
594
+ const db = this.vault.getDb();
595
+
596
+ if (options?.sessionId) {
597
+ const info = db
598
+ .prepare(
599
+ 'UPDATE brain_sessions SET extracted_at = NULL WHERE id = ? AND extracted_at IS NOT NULL',
600
+ )
601
+ .run(options.sessionId);
602
+ return { reset: info.changes };
603
+ }
604
+
605
+ if (options?.since) {
606
+ const info = db
607
+ .prepare('UPDATE brain_sessions SET extracted_at = NULL WHERE extracted_at >= ?')
608
+ .run(options.since);
609
+ return { reset: info.changes };
610
+ }
611
+
612
+ if (options?.all) {
613
+ const info = db
614
+ .prepare('UPDATE brain_sessions SET extracted_at = NULL WHERE extracted_at IS NOT NULL')
615
+ .run();
616
+ return { reset: info.changes };
617
+ }
618
+
619
+ return { reset: 0 };
620
+ }
621
+
520
622
  getProposals(options?: {
521
623
  sessionId?: string;
522
624
  promoted?: boolean;
@@ -556,10 +658,36 @@ export class BrainIntelligence {
556
658
  return rows.map((r) => this.rowToProposal(r));
557
659
  }
558
660
 
559
- promoteProposals(proposalIds: string[]): { promoted: number; failed: string[] } {
661
+ promoteProposals(
662
+ proposalIds: string[],
663
+ governanceGate?: {
664
+ evaluateCapture: (
665
+ projectPath: string,
666
+ entry: { type: string; category: string; title?: string },
667
+ ) => { action: string; reason?: string };
668
+ propose: (
669
+ projectPath: string,
670
+ entryData: {
671
+ entryId?: string;
672
+ title: string;
673
+ type: string;
674
+ category: string;
675
+ data?: Record<string, unknown>;
676
+ },
677
+ source?: string,
678
+ ) => number;
679
+ },
680
+ projectPath?: string,
681
+ ): {
682
+ promoted: number;
683
+ failed: string[];
684
+ gated: Array<{ id: string; action: string; reason?: string }>;
685
+ } {
560
686
  const db = this.vault.getDb();
561
687
  let promoted = 0;
562
688
  const failed: string[] = [];
689
+ const gated: Array<{ id: string; action: string; reason?: string }> = [];
690
+ const pp = projectPath ?? '.';
563
691
 
564
692
  for (const id of proposalIds) {
565
693
  const row = db.prepare('SELECT * FROM brain_proposals WHERE id = ?').get(id) as
@@ -583,10 +711,46 @@ export class BrainIntelligence {
583
711
 
584
712
  if (row.promoted) continue; // Already promoted
585
713
 
586
- // Add to vault as intelligence entry — map workflow to pattern since vault only accepts pattern/anti-pattern/rule
714
+ // Map type for vault
587
715
  const rawType = row.type;
588
716
  const vaultType: 'pattern' | 'anti-pattern' | 'rule' =
589
717
  rawType === 'anti-pattern' ? 'anti-pattern' : 'pattern';
718
+
719
+ // Governance gate (when provided)
720
+ if (governanceGate) {
721
+ const decision = governanceGate.evaluateCapture(pp, {
722
+ type: vaultType,
723
+ category: 'brain-intelligence',
724
+ title: row.title,
725
+ });
726
+
727
+ if (decision.action === 'propose') {
728
+ governanceGate.propose(
729
+ pp,
730
+ {
731
+ entryId: `proposal-${id}`,
732
+ title: row.title,
733
+ type: vaultType,
734
+ category: 'brain-intelligence',
735
+ data: {
736
+ severity: 'suggestion',
737
+ description: row.description,
738
+ tags: ['auto-extracted', row.rule],
739
+ },
740
+ },
741
+ 'brain-promote',
742
+ );
743
+ gated.push({ id, action: 'propose', reason: decision.reason });
744
+ continue;
745
+ }
746
+
747
+ if (decision.action !== 'capture') {
748
+ gated.push({ id, action: decision.action, reason: decision.reason });
749
+ continue;
750
+ }
751
+ }
752
+
753
+ // Capture into vault
590
754
  this.brain.enrichAndCapture({
591
755
  id: `proposal-${id}`,
592
756
  type: vaultType,
@@ -601,7 +765,7 @@ export class BrainIntelligence {
601
765
  promoted++;
602
766
  }
603
767
 
604
- return { promoted, failed };
768
+ return { promoted, failed, gated };
605
769
  }
606
770
 
607
771
  // ─── Intelligence Pipeline ────────────────────────────────────────
@@ -725,6 +889,7 @@ export class BrainIntelligence {
725
889
  files_modified: string;
726
890
  plan_id: string | null;
727
891
  plan_outcome: string | null;
892
+ extracted_at: string | null;
728
893
  }>;
729
894
  const sessions = sessionRows.map((r) => this.rowToSession(r));
730
895
 
@@ -790,8 +955,8 @@ export class BrainIntelligence {
790
955
  // Import sessions
791
956
  const insertSession = db.prepare(
792
957
  `INSERT OR IGNORE INTO brain_sessions
793
- (id, started_at, ended_at, domain, context, tools_used, files_modified, plan_id, plan_outcome)
794
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`,
958
+ (id, started_at, ended_at, domain, context, tools_used, files_modified, plan_id, plan_outcome, extracted_at)
959
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
795
960
  );
796
961
  for (const s of data.sessions) {
797
962
  const changes = insertSession.run(
@@ -804,6 +969,7 @@ export class BrainIntelligence {
804
969
  JSON.stringify(s.filesModified),
805
970
  s.planId,
806
971
  s.planOutcome,
972
+ s.extractedAt ?? null,
807
973
  );
808
974
  if (changes.changes > 0) result.imported.sessions++;
809
975
  }
@@ -883,6 +1049,7 @@ export class BrainIntelligence {
883
1049
  files_modified: string;
884
1050
  plan_id: string | null;
885
1051
  plan_outcome: string | null;
1052
+ extracted_at: string | null;
886
1053
  }
887
1054
  | undefined;
888
1055
 
@@ -900,6 +1067,7 @@ export class BrainIntelligence {
900
1067
  files_modified: string;
901
1068
  plan_id: string | null;
902
1069
  plan_outcome: string | null;
1070
+ extracted_at: string | null;
903
1071
  }): BrainSession {
904
1072
  return {
905
1073
  id: row.id,
@@ -911,6 +1079,7 @@ export class BrainIntelligence {
911
1079
  filesModified: JSON.parse(row.files_modified) as string[],
912
1080
  planId: row.plan_id,
913
1081
  planOutcome: row.plan_outcome,
1082
+ extractedAt: row.extracted_at,
914
1083
  };
915
1084
  }
916
1085
 
@@ -6,7 +6,7 @@ export interface ScoringWeights {
6
6
  semantic: number;
7
7
  vector: number;
8
8
  severity: number;
9
- recency: number;
9
+ temporalDecay: number;
10
10
  tagOverlap: number;
11
11
  domainMatch: number;
12
12
  }
@@ -15,7 +15,7 @@ export interface ScoreBreakdown {
15
15
  semantic: number;
16
16
  vector: number;
17
17
  severity: number;
18
- recency: number;
18
+ temporalDecay: number;
19
19
  tagOverlap: number;
20
20
  domainMatch: number;
21
21
  total: number;
@@ -55,6 +55,43 @@ export interface QueryContext {
55
55
  tags?: string[];
56
56
  }
57
57
 
58
+ // ─── Feedback Types ───────────────────────────────────────────────
59
+
60
+ export type FeedbackType = 'accepted' | 'dismissed' | 'modified' | 'failed';
61
+ export type FeedbackSource = 'search' | 'recommendation' | 'tool-execution' | 'explicit';
62
+
63
+ export interface FeedbackInput {
64
+ query: string;
65
+ entryId: string;
66
+ action: FeedbackType;
67
+ source?: FeedbackSource;
68
+ confidence?: number;
69
+ duration?: number;
70
+ context?: string;
71
+ reason?: string;
72
+ }
73
+
74
+ export interface FeedbackEntry {
75
+ id: number;
76
+ query: string;
77
+ entryId: string;
78
+ action: FeedbackType;
79
+ source: FeedbackSource;
80
+ confidence: number;
81
+ duration: number | null;
82
+ context: string;
83
+ reason: string | null;
84
+ createdAt: number;
85
+ }
86
+
87
+ export interface FeedbackStats {
88
+ total: number;
89
+ byAction: Record<string, number>;
90
+ bySource: Record<string, number>;
91
+ acceptanceRate: number;
92
+ averageConfidence: number;
93
+ }
94
+
58
95
  // ─── Brain Intelligence Types ──────────────────────────────────────
59
96
 
60
97
  export interface PatternStrength {
@@ -87,6 +124,7 @@ export interface BrainSession {
87
124
  filesModified: string[];
88
125
  planId: string | null;
89
126
  planOutcome: string | null;
127
+ extractedAt: string | null;
90
128
  }
91
129
 
92
130
  export interface SessionLifecycleInput {