agent-bober 0.17.0 → 0.18.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 (364) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/CHANGELOG.md +25 -0
  4. package/README.md +169 -6
  5. package/dist/chat/answerer.d.ts +17 -0
  6. package/dist/chat/answerer.d.ts.map +1 -0
  7. package/dist/chat/answerer.js +52 -0
  8. package/dist/chat/answerer.js.map +1 -0
  9. package/dist/chat/approval-cursor.d.ts +25 -0
  10. package/dist/chat/approval-cursor.d.ts.map +1 -0
  11. package/dist/chat/approval-cursor.js +61 -0
  12. package/dist/chat/approval-cursor.js.map +1 -0
  13. package/dist/chat/approval-reader.d.ts +11 -0
  14. package/dist/chat/approval-reader.d.ts.map +1 -0
  15. package/dist/chat/approval-reader.js +20 -0
  16. package/dist/chat/approval-reader.js.map +1 -0
  17. package/dist/chat/careful-sidecar.d.ts +15 -0
  18. package/dist/chat/careful-sidecar.d.ts.map +1 -0
  19. package/dist/chat/careful-sidecar.js +39 -0
  20. package/dist/chat/careful-sidecar.js.map +1 -0
  21. package/dist/chat/chat-session.d.ts +129 -0
  22. package/dist/chat/chat-session.d.ts.map +1 -0
  23. package/dist/chat/chat-session.js +470 -0
  24. package/dist/chat/chat-session.js.map +1 -0
  25. package/dist/chat/completion-tailer.d.ts +27 -0
  26. package/dist/chat/completion-tailer.d.ts.map +1 -0
  27. package/dist/chat/completion-tailer.js +187 -0
  28. package/dist/chat/completion-tailer.js.map +1 -0
  29. package/dist/chat/conversation-store.d.ts +22 -0
  30. package/dist/chat/conversation-store.d.ts.map +1 -0
  31. package/dist/chat/conversation-store.js +66 -0
  32. package/dist/chat/conversation-store.js.map +1 -0
  33. package/dist/chat/cursor-store.d.ts +23 -0
  34. package/dist/chat/cursor-store.d.ts.map +1 -0
  35. package/dist/chat/cursor-store.js +42 -0
  36. package/dist/chat/cursor-store.js.map +1 -0
  37. package/dist/chat/pid-sidecar.d.ts +22 -0
  38. package/dist/chat/pid-sidecar.d.ts.map +1 -0
  39. package/dist/chat/pid-sidecar.js +42 -0
  40. package/dist/chat/pid-sidecar.js.map +1 -0
  41. package/dist/chat/roster-reader.d.ts +16 -0
  42. package/dist/chat/roster-reader.d.ts.map +1 -0
  43. package/dist/chat/roster-reader.js +39 -0
  44. package/dist/chat/roster-reader.js.map +1 -0
  45. package/dist/chat/run-spawner.d.ts +71 -0
  46. package/dist/chat/run-spawner.d.ts.map +1 -0
  47. package/dist/chat/run-spawner.js +121 -0
  48. package/dist/chat/run-spawner.js.map +1 -0
  49. package/dist/chat/slash-commands.d.ts +36 -0
  50. package/dist/chat/slash-commands.d.ts.map +1 -0
  51. package/dist/chat/slash-commands.js +133 -0
  52. package/dist/chat/slash-commands.js.map +1 -0
  53. package/dist/chat/steer-cleanup.d.ts +12 -0
  54. package/dist/chat/steer-cleanup.d.ts.map +1 -0
  55. package/dist/chat/steer-cleanup.js +60 -0
  56. package/dist/chat/steer-cleanup.js.map +1 -0
  57. package/dist/chat/turn-classifier.d.ts +43 -0
  58. package/dist/chat/turn-classifier.d.ts.map +1 -0
  59. package/dist/chat/turn-classifier.js +150 -0
  60. package/dist/chat/turn-classifier.js.map +1 -0
  61. package/dist/cli/commands/blackboard.d.ts +33 -0
  62. package/dist/cli/commands/blackboard.d.ts.map +1 -0
  63. package/dist/cli/commands/blackboard.js +114 -0
  64. package/dist/cli/commands/blackboard.js.map +1 -0
  65. package/dist/cli/commands/chat.d.ts +13 -0
  66. package/dist/cli/commands/chat.d.ts.map +1 -0
  67. package/dist/cli/commands/chat.js +43 -0
  68. package/dist/cli/commands/chat.js.map +1 -0
  69. package/dist/cli/commands/evolve.d.ts +18 -0
  70. package/dist/cli/commands/evolve.d.ts.map +1 -0
  71. package/dist/cli/commands/evolve.js +72 -0
  72. package/dist/cli/commands/evolve.js.map +1 -0
  73. package/dist/cli/commands/facts.d.ts +15 -0
  74. package/dist/cli/commands/facts.d.ts.map +1 -0
  75. package/dist/cli/commands/facts.js +213 -0
  76. package/dist/cli/commands/facts.js.map +1 -0
  77. package/dist/cli/commands/init.d.ts +9 -0
  78. package/dist/cli/commands/init.d.ts.map +1 -1
  79. package/dist/cli/commands/init.js +1 -1
  80. package/dist/cli/commands/init.js.map +1 -1
  81. package/dist/cli/commands/medical.d.ts +24 -0
  82. package/dist/cli/commands/medical.d.ts.map +1 -0
  83. package/dist/cli/commands/medical.js +132 -0
  84. package/dist/cli/commands/medical.js.map +1 -0
  85. package/dist/cli/commands/memory.d.ts +2 -1
  86. package/dist/cli/commands/memory.d.ts.map +1 -1
  87. package/dist/cli/commands/memory.js +94 -7
  88. package/dist/cli/commands/memory.js.map +1 -1
  89. package/dist/cli/commands/plan.d.ts.map +1 -1
  90. package/dist/cli/commands/plan.js +29 -3
  91. package/dist/cli/commands/plan.js.map +1 -1
  92. package/dist/cli/commands/replay.d.ts +17 -0
  93. package/dist/cli/commands/replay.d.ts.map +1 -0
  94. package/dist/cli/commands/replay.js +261 -0
  95. package/dist/cli/commands/replay.js.map +1 -0
  96. package/dist/cli/commands/run.d.ts +9 -0
  97. package/dist/cli/commands/run.d.ts.map +1 -1
  98. package/dist/cli/commands/run.js +27 -1
  99. package/dist/cli/commands/run.js.map +1 -1
  100. package/dist/cli/commands/sprint.d.ts.map +1 -1
  101. package/dist/cli/commands/sprint.js +17 -3
  102. package/dist/cli/commands/sprint.js.map +1 -1
  103. package/dist/cli/commands/update.d.ts +18 -0
  104. package/dist/cli/commands/update.d.ts.map +1 -0
  105. package/dist/cli/commands/update.js +81 -0
  106. package/dist/cli/commands/update.js.map +1 -0
  107. package/dist/cli/index.js +15 -0
  108. package/dist/cli/index.js.map +1 -1
  109. package/dist/config/defaults.d.ts.map +1 -1
  110. package/dist/config/defaults.js +8 -0
  111. package/dist/config/defaults.js.map +1 -1
  112. package/dist/config/role-providers.d.ts +1 -1
  113. package/dist/config/role-providers.d.ts.map +1 -1
  114. package/dist/config/role-providers.js +6 -1
  115. package/dist/config/role-providers.js.map +1 -1
  116. package/dist/config/schema.d.ts +467 -222
  117. package/dist/config/schema.d.ts.map +1 -1
  118. package/dist/config/schema.js +25 -0
  119. package/dist/config/schema.js.map +1 -1
  120. package/dist/contracts/eval-result.d.ts +84 -84
  121. package/dist/contracts/spec.d.ts +28 -28
  122. package/dist/contracts/sprint-contract.d.ts +4 -4
  123. package/dist/fleet/critic-deep.d.ts +53 -0
  124. package/dist/fleet/critic-deep.d.ts.map +1 -0
  125. package/dist/fleet/critic-deep.js +199 -0
  126. package/dist/fleet/critic-deep.js.map +1 -0
  127. package/dist/fleet/decomposer-deep-constants.d.ts +4 -0
  128. package/dist/fleet/decomposer-deep-constants.d.ts.map +1 -0
  129. package/dist/fleet/decomposer-deep-constants.js +14 -0
  130. package/dist/fleet/decomposer-deep-constants.js.map +1 -0
  131. package/dist/fleet/decomposer-deep-types.d.ts +8 -0
  132. package/dist/fleet/decomposer-deep-types.d.ts.map +1 -0
  133. package/dist/fleet/decomposer-deep-types.js +9 -0
  134. package/dist/fleet/decomposer-deep-types.js.map +1 -0
  135. package/dist/fleet/decomposer-deep.d.ts +51 -0
  136. package/dist/fleet/decomposer-deep.d.ts.map +1 -0
  137. package/dist/fleet/decomposer-deep.js +261 -0
  138. package/dist/fleet/decomposer-deep.js.map +1 -0
  139. package/dist/fleet/decomposer.d.ts +22 -0
  140. package/dist/fleet/decomposer.d.ts.map +1 -0
  141. package/dist/fleet/decomposer.js +144 -0
  142. package/dist/fleet/decomposer.js.map +1 -0
  143. package/dist/fleet/index.d.ts +93 -0
  144. package/dist/fleet/index.d.ts.map +1 -1
  145. package/dist/fleet/index.js +230 -2
  146. package/dist/fleet/index.js.map +1 -1
  147. package/dist/fleet/manifest-write.d.ts +30 -0
  148. package/dist/fleet/manifest-write.d.ts.map +1 -0
  149. package/dist/fleet/manifest-write.js +90 -0
  150. package/dist/fleet/manifest-write.js.map +1 -0
  151. package/dist/fleet/manifest.d.ts +6 -6
  152. package/dist/fleet/shared-blackboard.d.ts +51 -0
  153. package/dist/fleet/shared-blackboard.d.ts.map +1 -0
  154. package/dist/fleet/shared-blackboard.js +79 -0
  155. package/dist/fleet/shared-blackboard.js.map +1 -0
  156. package/dist/fleet/synthesis.d.ts +16 -0
  157. package/dist/fleet/synthesis.d.ts.map +1 -0
  158. package/dist/fleet/synthesis.js +22 -0
  159. package/dist/fleet/synthesis.js.map +1 -0
  160. package/dist/fleet/tier-policy.d.ts +18 -0
  161. package/dist/fleet/tier-policy.d.ts.map +1 -0
  162. package/dist/fleet/tier-policy.js +53 -0
  163. package/dist/fleet/tier-policy.js.map +1 -0
  164. package/dist/fleet/tool-role-guard.d.ts +24 -0
  165. package/dist/fleet/tool-role-guard.d.ts.map +1 -0
  166. package/dist/fleet/tool-role-guard.js +55 -0
  167. package/dist/fleet/tool-role-guard.js.map +1 -0
  168. package/dist/incident/resolution-verify.d.ts +4 -4
  169. package/dist/incident/types.d.ts +8 -8
  170. package/dist/mcp/run-manager.d.ts +9 -1
  171. package/dist/mcp/run-manager.d.ts.map +1 -1
  172. package/dist/mcp/run-manager.js.map +1 -1
  173. package/dist/medical/adapters/apple-health.d.ts +32 -0
  174. package/dist/medical/adapters/apple-health.d.ts.map +1 -0
  175. package/dist/medical/adapters/apple-health.js +100 -0
  176. package/dist/medical/adapters/apple-health.js.map +1 -0
  177. package/dist/medical/audit.d.ts +31 -0
  178. package/dist/medical/audit.d.ts.map +1 -0
  179. package/dist/medical/audit.js +56 -0
  180. package/dist/medical/audit.js.map +1 -0
  181. package/dist/medical/consent.d.ts +37 -0
  182. package/dist/medical/consent.d.ts.map +1 -0
  183. package/dist/medical/consent.js +73 -0
  184. package/dist/medical/consent.js.map +1 -0
  185. package/dist/medical/disclaimer.d.ts +11 -0
  186. package/dist/medical/disclaimer.d.ts.map +1 -0
  187. package/dist/medical/disclaimer.js +21 -0
  188. package/dist/medical/disclaimer.js.map +1 -0
  189. package/dist/medical/egress.d.ts +30 -0
  190. package/dist/medical/egress.d.ts.map +1 -0
  191. package/dist/medical/egress.js +50 -0
  192. package/dist/medical/egress.js.map +1 -0
  193. package/dist/medical/engine.d.ts +73 -0
  194. package/dist/medical/engine.d.ts.map +1 -0
  195. package/dist/medical/engine.js +333 -0
  196. package/dist/medical/engine.js.map +1 -0
  197. package/dist/medical/guardrails.d.ts +47 -0
  198. package/dist/medical/guardrails.d.ts.map +1 -0
  199. package/dist/medical/guardrails.js +92 -0
  200. package/dist/medical/guardrails.js.map +1 -0
  201. package/dist/medical/health-store.d.ts +80 -0
  202. package/dist/medical/health-store.d.ts.map +1 -0
  203. package/dist/medical/health-store.js +204 -0
  204. package/dist/medical/health-store.js.map +1 -0
  205. package/dist/medical/inference.d.ts +22 -0
  206. package/dist/medical/inference.d.ts.map +1 -0
  207. package/dist/medical/inference.js +39 -0
  208. package/dist/medical/inference.js.map +1 -0
  209. package/dist/medical/ingestion.d.ts +33 -0
  210. package/dist/medical/ingestion.d.ts.map +1 -0
  211. package/dist/medical/ingestion.js +52 -0
  212. package/dist/medical/ingestion.js.map +1 -0
  213. package/dist/medical/numerics.d.ts +66 -0
  214. package/dist/medical/numerics.d.ts.map +1 -0
  215. package/dist/medical/numerics.js +216 -0
  216. package/dist/medical/numerics.js.map +1 -0
  217. package/dist/medical/red-flag.d.ts +42 -0
  218. package/dist/medical/red-flag.d.ts.map +1 -0
  219. package/dist/medical/red-flag.js +161 -0
  220. package/dist/medical/red-flag.js.map +1 -0
  221. package/dist/medical/refusal.d.ts +46 -0
  222. package/dist/medical/refusal.d.ts.map +1 -0
  223. package/dist/medical/refusal.js +131 -0
  224. package/dist/medical/refusal.js.map +1 -0
  225. package/dist/medical/retrieval/grounding-critic.d.ts +34 -0
  226. package/dist/medical/retrieval/grounding-critic.d.ts.map +1 -0
  227. package/dist/medical/retrieval/grounding-critic.js +153 -0
  228. package/dist/medical/retrieval/grounding-critic.js.map +1 -0
  229. package/dist/medical/retrieval/literature.d.ts +78 -0
  230. package/dist/medical/retrieval/literature.d.ts.map +1 -0
  231. package/dist/medical/retrieval/literature.js +292 -0
  232. package/dist/medical/retrieval/literature.js.map +1 -0
  233. package/dist/medical/retrieval/medline-source.d.ts +72 -0
  234. package/dist/medical/retrieval/medline-source.d.ts.map +1 -0
  235. package/dist/medical/retrieval/medline-source.js +120 -0
  236. package/dist/medical/retrieval/medline-source.js.map +1 -0
  237. package/dist/medical/team.d.ts +15 -0
  238. package/dist/medical/team.d.ts.map +1 -0
  239. package/dist/medical/team.js +44 -0
  240. package/dist/medical/team.js.map +1 -0
  241. package/dist/medical/types.d.ts +175 -0
  242. package/dist/medical/types.d.ts.map +1 -0
  243. package/dist/medical/types.js +8 -0
  244. package/dist/medical/types.js.map +1 -0
  245. package/dist/medical/whoop/whoop-client.d.ts +114 -0
  246. package/dist/medical/whoop/whoop-client.d.ts.map +1 -0
  247. package/dist/medical/whoop/whoop-client.js +226 -0
  248. package/dist/medical/whoop/whoop-client.js.map +1 -0
  249. package/dist/medical/whoop/whoop-sync.d.ts +25 -0
  250. package/dist/medical/whoop/whoop-sync.d.ts.map +1 -0
  251. package/dist/medical/whoop/whoop-sync.js +97 -0
  252. package/dist/medical/whoop/whoop-sync.js.map +1 -0
  253. package/dist/medical/whoop/whoop-token.d.ts +44 -0
  254. package/dist/medical/whoop/whoop-token.d.ts.map +1 -0
  255. package/dist/medical/whoop/whoop-token.js +66 -0
  256. package/dist/medical/whoop/whoop-token.js.map +1 -0
  257. package/dist/orchestrator/context-handoff.d.ts +60 -60
  258. package/dist/orchestrator/contract-materialization.d.ts +33 -0
  259. package/dist/orchestrator/contract-materialization.d.ts.map +1 -0
  260. package/dist/orchestrator/contract-materialization.js +113 -0
  261. package/dist/orchestrator/contract-materialization.js.map +1 -0
  262. package/dist/orchestrator/memory/distill.d.ts +4 -1
  263. package/dist/orchestrator/memory/distill.d.ts.map +1 -1
  264. package/dist/orchestrator/memory/distill.js +41 -1
  265. package/dist/orchestrator/memory/distill.js.map +1 -1
  266. package/dist/orchestrator/memory/fact-detector.d.ts +61 -0
  267. package/dist/orchestrator/memory/fact-detector.d.ts.map +1 -0
  268. package/dist/orchestrator/memory/fact-detector.js +153 -0
  269. package/dist/orchestrator/memory/fact-detector.js.map +1 -0
  270. package/dist/orchestrator/memory/fact-judge.d.ts +19 -0
  271. package/dist/orchestrator/memory/fact-judge.d.ts.map +1 -0
  272. package/dist/orchestrator/memory/fact-judge.js +121 -0
  273. package/dist/orchestrator/memory/fact-judge.js.map +1 -0
  274. package/dist/orchestrator/memory/fact-retrieve.d.ts +52 -0
  275. package/dist/orchestrator/memory/fact-retrieve.d.ts.map +1 -0
  276. package/dist/orchestrator/memory/fact-retrieve.js +117 -0
  277. package/dist/orchestrator/memory/fact-retrieve.js.map +1 -0
  278. package/dist/orchestrator/memory/hygiene.d.ts +66 -0
  279. package/dist/orchestrator/memory/hygiene.d.ts.map +1 -0
  280. package/dist/orchestrator/memory/hygiene.js +153 -0
  281. package/dist/orchestrator/memory/hygiene.js.map +1 -0
  282. package/dist/orchestrator/memory/reconcile.d.ts +47 -0
  283. package/dist/orchestrator/memory/reconcile.d.ts.map +1 -0
  284. package/dist/orchestrator/memory/reconcile.js +116 -0
  285. package/dist/orchestrator/memory/reconcile.js.map +1 -0
  286. package/dist/orchestrator/memory/retrieve.d.ts +5 -3
  287. package/dist/orchestrator/memory/retrieve.d.ts.map +1 -1
  288. package/dist/orchestrator/memory/retrieve.js +9 -6
  289. package/dist/orchestrator/memory/retrieve.js.map +1 -1
  290. package/dist/orchestrator/pipeline.d.ts +19 -3
  291. package/dist/orchestrator/pipeline.d.ts.map +1 -1
  292. package/dist/orchestrator/pipeline.js +63 -52
  293. package/dist/orchestrator/pipeline.js.map +1 -1
  294. package/dist/orchestrator/planner-agent.d.ts.map +1 -1
  295. package/dist/orchestrator/planner-agent.js +16 -1
  296. package/dist/orchestrator/planner-agent.js.map +1 -1
  297. package/dist/orchestrator/selfimprove/eval-guards.d.ts +51 -0
  298. package/dist/orchestrator/selfimprove/eval-guards.d.ts.map +1 -0
  299. package/dist/orchestrator/selfimprove/eval-guards.js +120 -0
  300. package/dist/orchestrator/selfimprove/eval-guards.js.map +1 -0
  301. package/dist/orchestrator/selfimprove/gepa.d.ts +74 -0
  302. package/dist/orchestrator/selfimprove/gepa.d.ts.map +1 -0
  303. package/dist/orchestrator/selfimprove/gepa.js +227 -0
  304. package/dist/orchestrator/selfimprove/gepa.js.map +1 -0
  305. package/dist/orchestrator/selfimprove/replay-harness.d.ts +65 -0
  306. package/dist/orchestrator/selfimprove/replay-harness.d.ts.map +1 -0
  307. package/dist/orchestrator/selfimprove/replay-harness.js +134 -0
  308. package/dist/orchestrator/selfimprove/replay-harness.js.map +1 -0
  309. package/dist/orchestrator/selfimprove/replay-store.d.ts +45 -0
  310. package/dist/orchestrator/selfimprove/replay-store.d.ts.map +1 -0
  311. package/dist/orchestrator/selfimprove/replay-store.js +119 -0
  312. package/dist/orchestrator/selfimprove/replay-store.js.map +1 -0
  313. package/dist/orchestrator/selfimprove/replay-types.d.ts +32 -0
  314. package/dist/orchestrator/selfimprove/replay-types.d.ts.map +1 -0
  315. package/dist/orchestrator/selfimprove/replay-types.js +15 -0
  316. package/dist/orchestrator/selfimprove/replay-types.js.map +1 -0
  317. package/dist/orchestrator/workflow/engine.d.ts +3 -1
  318. package/dist/orchestrator/workflow/engine.d.ts.map +1 -1
  319. package/dist/orchestrator/workflow/selector.d.ts +18 -0
  320. package/dist/orchestrator/workflow/selector.d.ts.map +1 -1
  321. package/dist/orchestrator/workflow/selector.js +41 -0
  322. package/dist/orchestrator/workflow/selector.js.map +1 -1
  323. package/dist/orchestrator/workflow/ts-engine.d.ts +3 -1
  324. package/dist/orchestrator/workflow/ts-engine.d.ts.map +1 -1
  325. package/dist/orchestrator/workflow/ts-engine.js +2 -2
  326. package/dist/orchestrator/workflow/ts-engine.js.map +1 -1
  327. package/dist/orchestrator/workflow/workflow-engine.d.ts +3 -1
  328. package/dist/orchestrator/workflow/workflow-engine.d.ts.map +1 -1
  329. package/dist/orchestrator/workflow/workflow-engine.js +3 -3
  330. package/dist/orchestrator/workflow/workflow-engine.js.map +1 -1
  331. package/dist/state/facts.d.ts +110 -0
  332. package/dist/state/facts.d.ts.map +1 -0
  333. package/dist/state/facts.js +208 -0
  334. package/dist/state/facts.js.map +1 -0
  335. package/dist/state/guidance.d.ts +37 -0
  336. package/dist/state/guidance.d.ts.map +1 -0
  337. package/dist/state/guidance.js +144 -0
  338. package/dist/state/guidance.js.map +1 -0
  339. package/dist/state/history.d.ts +2 -2
  340. package/dist/state/index.d.ts +1 -1
  341. package/dist/state/index.d.ts.map +1 -1
  342. package/dist/state/index.js +1 -1
  343. package/dist/state/index.js.map +1 -1
  344. package/dist/state/memory.d.ts +43 -11
  345. package/dist/state/memory.d.ts.map +1 -1
  346. package/dist/state/memory.js +93 -15
  347. package/dist/state/memory.js.map +1 -1
  348. package/dist/state/pause.d.ts +47 -0
  349. package/dist/state/pause.d.ts.map +1 -0
  350. package/dist/state/pause.js +146 -0
  351. package/dist/state/pause.js.map +1 -0
  352. package/dist/state/sprint-state.d.ts +8 -0
  353. package/dist/state/sprint-state.d.ts.map +1 -1
  354. package/dist/state/sprint-state.js +32 -1
  355. package/dist/state/sprint-state.js.map +1 -1
  356. package/dist/teams/registry.d.ts +16 -0
  357. package/dist/teams/registry.d.ts.map +1 -0
  358. package/dist/teams/registry.js +53 -0
  359. package/dist/teams/registry.js.map +1 -0
  360. package/dist/teams/types.d.ts +25 -0
  361. package/dist/teams/types.d.ts.map +1 -0
  362. package/dist/teams/types.js +2 -0
  363. package/dist/teams/types.js.map +1 -0
  364. package/package.json +3 -1
@@ -0,0 +1,74 @@
1
+ import type { BoberConfig } from "../../config/schema.js";
2
+ import { runReplayHarness } from "./replay-harness.js";
3
+ export interface VariantScore {
4
+ variantId: string;
5
+ prompt: string;
6
+ promptLength: number;
7
+ /** replayPassCount = total - regressions; axis 1: maximize (desc). */
8
+ replayPassCount: number;
9
+ regressions: number;
10
+ improvements: number;
11
+ }
12
+ export interface GepaResult {
13
+ promoted: boolean;
14
+ winnerPath: string | null;
15
+ baselineRegressions: number;
16
+ variantsTried: number;
17
+ }
18
+ /**
19
+ * Produces a deterministic set of small textual mutations of `basePrompt`.
20
+ * A fixed seed yields byte-identical variants on every call (no Math.random).
21
+ *
22
+ * Three operator classes applied in order:
23
+ * 1. Append a clarifying constraint sentence.
24
+ * 2. Paraphrase the first markdown heading (## or #).
25
+ * 3. Reorder two adjacent guidance bullets (lines starting with "- ").
26
+ *
27
+ * Each operator uses the PRNG to pick among a small fixed vocabulary so the
28
+ * result space is deterministic and bounded.
29
+ */
30
+ export declare function proposeVariants(basePrompt: string, seed: number): string[];
31
+ /**
32
+ * Returns the non-dominated (Pareto) frontier of `scored`.
33
+ *
34
+ * Dominance axes (both must be worse for a variant to be excluded):
35
+ * axis 1: replayPassCount — higher is better (desc).
36
+ * axis 2: promptLength — lower is better (asc).
37
+ *
38
+ * A variant B is dominated by A iff:
39
+ * A.replayPassCount >= B.replayPassCount AND A.promptLength <= B.promptLength
40
+ * with at least one strict inequality.
41
+ *
42
+ * PURE: no clock, no fs, input array is not mutated.
43
+ */
44
+ export declare function paretoSet(scored: VariantScore[]): VariantScore[];
45
+ /** Options accepted by evolve(). */
46
+ export interface EvolveOptions {
47
+ role: "generator" | "evaluator";
48
+ seed: number;
49
+ dryRun?: boolean;
50
+ /** Injected runId for deterministic test paths. Defaults to `evolve-<Date.now()>`. */
51
+ runId?: string;
52
+ }
53
+ /** DI seam — tests inject a stub harness; production uses the real one. */
54
+ export type HarnessFn = typeof runReplayHarness;
55
+ export interface EvolveDeps {
56
+ harness?: HarnessFn;
57
+ }
58
+ /**
59
+ * Orchestration entry point for offline prompt evolution.
60
+ *
61
+ * Reads the base prompt, proposes variants, scores each via the harness,
62
+ * keeps the Pareto frontier, and writes results under .bober/evolve/<runId>/.
63
+ *
64
+ * Promotion predicate (strict — a tie does NOT promote):
65
+ * eligible ⟺ result.regressions.length === 0 AND result.improvements.length > baseline.improvements.length
66
+ *
67
+ * Writes:
68
+ * report.json — always
69
+ * promoted/<role>.md — only when a winner exists AND !dryRun
70
+ *
71
+ * SAFETY: all write paths are constructed under .bober/evolve/<runId>/ — see SAFETY INVARIANTS above.
72
+ */
73
+ export declare function evolve(projectRoot: string, config: BoberConfig, opts: EvolveOptions, deps?: EvolveDeps): Promise<GepaResult>;
74
+ //# sourceMappingURL=gepa.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gepa.d.ts","sourceRoot":"","sources":["../../../src/orchestrator/selfimprove/gepa.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAE1D,OAAO,EACL,gBAAgB,EAEjB,MAAM,qBAAqB,CAAC;AAK7B,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,sEAAsE;IACtE,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,OAAO,CAAC;IAClB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,mBAAmB,EAAE,MAAM,CAAC;IAC5B,aAAa,EAAE,MAAM,CAAC;CACvB;AAsBD;;;;;;;;;;;GAWG;AACH,wBAAgB,eAAe,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAsD1E;AAID;;;;;;;;;;;;GAYG;AACH,wBAAgB,SAAS,CAAC,MAAM,EAAE,YAAY,EAAE,GAAG,YAAY,EAAE,CAahE;AAID,oCAAoC;AACpC,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,WAAW,GAAG,WAAW,CAAC;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,sFAAsF;IACtF,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,2EAA2E;AAC3E,MAAM,MAAM,SAAS,GAAG,OAAO,gBAAgB,CAAC;AAEhD,MAAM,WAAW,UAAU;IACzB,OAAO,CAAC,EAAE,SAAS,CAAC;CACrB;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,MAAM,CAC1B,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,WAAW,EACnB,IAAI,EAAE,aAAa,EACnB,IAAI,GAAE,UAAe,GACpB,OAAO,CAAC,UAAU,CAAC,CA0GrB"}
@@ -0,0 +1,227 @@
1
+ /**
2
+ * GEPA offline prompt evolution. Replay-gated, Pareto-set, NEVER live.
3
+ *
4
+ * SAFETY INVARIANTS (load-bearing — verified by sc-4-7 guard test):
5
+ * 1. No write path is ever constructed under the live agent definitions directory.
6
+ * All writes go under .bober/evolve/<runId>/.
7
+ * 2. Not imported or called by pipeline.ts. CLI-only entry point.
8
+ * 3. Variants are scored ONLY via runReplayHarness — no live generator/evaluator runs.
9
+ *
10
+ * PURE pieces (proposeVariants, paretoSet): no clock, no fs, no network, no mutation.
11
+ * Orchestration piece (evolve): may touch clock and fs; delegates all scoring to the harness.
12
+ */
13
+ import { join } from "node:path";
14
+ import { writeFile } from "node:fs/promises";
15
+ import { loadAgentDefinition } from "../agent-loader.js";
16
+ import { runReplayHarness, } from "./replay-harness.js";
17
+ import { ensureDir } from "../../state/helpers.js";
18
+ // ── PURE: mulberry32 seeded PRNG (NO Math.random) ─────────────────────────────
19
+ /**
20
+ * Hand-rolled mulberry32: a fast, deterministic 32-bit PRNG.
21
+ * Returns a closure that yields floats in [0, 1) on each call.
22
+ * A fixed seed yields a byte-identical sequence — no external randomness.
23
+ */
24
+ function mulberry32(seed) {
25
+ // bober: simple in-process PRNG; sufficient for small textual mutations.
26
+ let s = seed >>> 0; // treat as unsigned 32-bit int
27
+ return function () {
28
+ s = (s + 0x6d2b79f5) >>> 0;
29
+ let t = Math.imul(s ^ (s >>> 15), 1 | s);
30
+ t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) >>> 0;
31
+ return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
32
+ };
33
+ }
34
+ // ── PURE: proposeVariants ──────────────────────────────────────────────────────
35
+ /**
36
+ * Produces a deterministic set of small textual mutations of `basePrompt`.
37
+ * A fixed seed yields byte-identical variants on every call (no Math.random).
38
+ *
39
+ * Three operator classes applied in order:
40
+ * 1. Append a clarifying constraint sentence.
41
+ * 2. Paraphrase the first markdown heading (## or #).
42
+ * 3. Reorder two adjacent guidance bullets (lines starting with "- ").
43
+ *
44
+ * Each operator uses the PRNG to pick among a small fixed vocabulary so the
45
+ * result space is deterministic and bounded.
46
+ */
47
+ export function proposeVariants(basePrompt, seed) {
48
+ const rng = mulberry32(seed);
49
+ const variants = [];
50
+ // Operator 1: Append a clarifying constraint from a fixed vocabulary.
51
+ const constraints = [
52
+ "\n\nConstraint: Always cite the specific file path and line number when referencing evidence.",
53
+ "\n\nConstraint: Every claim must be grounded in an observable artifact (file, test output, or command exit code).",
54
+ "\n\nConstraint: Prefer the simplest correct solution; mark deliberate shortcuts with a bober: comment naming the ceiling and upgrade path.",
55
+ "\n\nConstraint: Verify all async operations have explicit error handling before declaring the task complete.",
56
+ ];
57
+ const constraintIdx = Math.floor(rng() * constraints.length);
58
+ variants.push(basePrompt + constraints[constraintIdx]);
59
+ // Operator 2: Paraphrase the first ## heading by inserting a qualifier.
60
+ const qualifiers = ["Disciplined", "Rigorous", "Precise", "Systematic"];
61
+ const qualifierIdx = Math.floor(rng() * qualifiers.length);
62
+ const qualifier = qualifiers[qualifierIdx];
63
+ // Replace only the first occurrence of a markdown heading (# or ##).
64
+ const headingReplaced = basePrompt.replace(/^(#{1,3} )(.+)$/m, (_match, hashes, title) => `${hashes}${qualifier} ${title}`);
65
+ // Only add if the replacement actually changed something.
66
+ if (headingReplaced !== basePrompt) {
67
+ variants.push(headingReplaced);
68
+ }
69
+ else {
70
+ // Fallback: append a heading-level clarifier.
71
+ variants.push(basePrompt + `\n\n## ${qualifier} Execution Checklist\n\n- Verify each step before proceeding.\n`);
72
+ }
73
+ // Operator 3: Reorder two adjacent bullet lines (lines starting with "- ").
74
+ const lines = basePrompt.split("\n");
75
+ const bulletIndices = [];
76
+ for (let i = 0; i < lines.length; i++) {
77
+ if (lines[i].trimStart().startsWith("- ")) {
78
+ bulletIndices.push(i);
79
+ }
80
+ }
81
+ // Pick a random pair of adjacent bullets to swap.
82
+ if (bulletIndices.length >= 2) {
83
+ const pairStart = Math.floor(rng() * (bulletIndices.length - 1));
84
+ const idxA = bulletIndices[pairStart];
85
+ const idxB = bulletIndices[pairStart + 1];
86
+ const swapped = [...lines];
87
+ [swapped[idxA], swapped[idxB]] = [swapped[idxB], swapped[idxA]];
88
+ variants.push(swapped.join("\n"));
89
+ }
90
+ else {
91
+ // Fallback: append a brief process note.
92
+ variants.push(basePrompt + "\n\n- Confirm all outputs are deterministic and reproducible.\n");
93
+ }
94
+ return variants;
95
+ }
96
+ // ── PURE: paretoSet ────────────────────────────────────────────────────────────
97
+ /**
98
+ * Returns the non-dominated (Pareto) frontier of `scored`.
99
+ *
100
+ * Dominance axes (both must be worse for a variant to be excluded):
101
+ * axis 1: replayPassCount — higher is better (desc).
102
+ * axis 2: promptLength — lower is better (asc).
103
+ *
104
+ * A variant B is dominated by A iff:
105
+ * A.replayPassCount >= B.replayPassCount AND A.promptLength <= B.promptLength
106
+ * with at least one strict inequality.
107
+ *
108
+ * PURE: no clock, no fs, input array is not mutated.
109
+ */
110
+ export function paretoSet(scored) {
111
+ return scored.filter((candidate) => {
112
+ // candidate is non-dominated iff no other variant dominates it on both axes.
113
+ return !scored.some((other) => other !== candidate &&
114
+ other.replayPassCount >= candidate.replayPassCount &&
115
+ other.promptLength <= candidate.promptLength &&
116
+ // At least one axis strictly better.
117
+ (other.replayPassCount > candidate.replayPassCount ||
118
+ other.promptLength < candidate.promptLength));
119
+ });
120
+ }
121
+ /**
122
+ * Orchestration entry point for offline prompt evolution.
123
+ *
124
+ * Reads the base prompt, proposes variants, scores each via the harness,
125
+ * keeps the Pareto frontier, and writes results under .bober/evolve/<runId>/.
126
+ *
127
+ * Promotion predicate (strict — a tie does NOT promote):
128
+ * eligible ⟺ result.regressions.length === 0 AND result.improvements.length > baseline.improvements.length
129
+ *
130
+ * Writes:
131
+ * report.json — always
132
+ * promoted/<role>.md — only when a winner exists AND !dryRun
133
+ *
134
+ * SAFETY: all write paths are constructed under .bober/evolve/<runId>/ — see SAFETY INVARIANTS above.
135
+ */
136
+ export async function evolve(projectRoot, config, opts, deps = {}) {
137
+ const harness = deps.harness ?? runReplayHarness;
138
+ const runId = opts.runId ?? `evolve-${Date.now()}`;
139
+ // Directory layout: .bober/evolve/<runId>/
140
+ const evolveDir = join(projectRoot, ".bober", "evolve", runId);
141
+ const promotedDir = join(evolveDir, "promoted");
142
+ await ensureDir(evolveDir);
143
+ await ensureDir(promotedDir);
144
+ // Load base prompt via agent-loader (reads the agent definition file).
145
+ // Agent name follows the convention: bober-generator, bober-evaluator.
146
+ const agentName = `bober-${opts.role}`;
147
+ const agentDef = await loadAgentDefinition(agentName, projectRoot);
148
+ const basePrompt = agentDef.systemPrompt;
149
+ // Compute BASELINE once.
150
+ const baselineResult = await harness(projectRoot, config);
151
+ const baselineImprovements = baselineResult.improvements.length;
152
+ const baselineRegressions = baselineResult.regressions.length;
153
+ const baselinePassCount = baselineResult.total - baselineRegressions;
154
+ // Generate deterministic variants.
155
+ const variants = proposeVariants(basePrompt, opts.seed);
156
+ // Score each variant through the harness (DI seam — stub in tests).
157
+ const scores = [];
158
+ for (let i = 0; i < variants.length; i++) {
159
+ const variantPrompt = variants[i];
160
+ // NOTE: runReplayHarness scores the frozen corpus deterministically;
161
+ // it does not re-run live LLMs. The variant text is passed only for
162
+ // bookkeeping — the gate re-derives verdicts from frozen eval_details_json.
163
+ const result = await harness(projectRoot, config);
164
+ const regressions = result.regressions.length;
165
+ const improvements = result.improvements.length;
166
+ const replayPassCount = result.total - regressions;
167
+ scores.push({
168
+ variantId: `v${i}`,
169
+ prompt: variantPrompt,
170
+ promptLength: variantPrompt.length,
171
+ replayPassCount,
172
+ regressions,
173
+ improvements,
174
+ });
175
+ }
176
+ // Compute Pareto frontier.
177
+ const frontier = paretoSet(scores);
178
+ // Promotion predicate: strict improvement, zero regressions.
179
+ const eligible = frontier.filter((v) => v.regressions === 0 && v.improvements > baselineImprovements);
180
+ // Pick best eligible: most improvements, then shortest prompt as tiebreaker.
181
+ eligible.sort((a, b) => b.improvements !== a.improvements
182
+ ? b.improvements - a.improvements
183
+ : a.promptLength - b.promptLength);
184
+ const winner = eligible[0] ?? null;
185
+ const promoted = winner !== null && !opts.dryRun;
186
+ let winnerPath = null;
187
+ if (winner !== null && !opts.dryRun) {
188
+ winnerPath = join(promotedDir, `${opts.role}.md`);
189
+ await writeFile(winnerPath, winner.prompt, "utf-8");
190
+ }
191
+ // Write report.json always.
192
+ const report = {
193
+ runId,
194
+ role: opts.role,
195
+ seed: opts.seed,
196
+ dryRun: opts.dryRun ?? false,
197
+ promoted,
198
+ winnerPath,
199
+ baselineRegressions,
200
+ baselineImprovements,
201
+ baselinePassCount,
202
+ variantsTried: variants.length,
203
+ paretoFrontier: frontier.map((v) => ({
204
+ variantId: v.variantId,
205
+ promptLength: v.promptLength,
206
+ replayPassCount: v.replayPassCount,
207
+ regressions: v.regressions,
208
+ improvements: v.improvements,
209
+ eligible: v.regressions === 0 && v.improvements > baselineImprovements,
210
+ })),
211
+ allScores: scores.map((v) => ({
212
+ variantId: v.variantId,
213
+ promptLength: v.promptLength,
214
+ replayPassCount: v.replayPassCount,
215
+ regressions: v.regressions,
216
+ improvements: v.improvements,
217
+ })),
218
+ };
219
+ await writeFile(join(evolveDir, "report.json"), JSON.stringify(report, null, 2), "utf-8");
220
+ return {
221
+ promoted,
222
+ winnerPath,
223
+ baselineRegressions,
224
+ variantsTried: variants.length,
225
+ };
226
+ }
227
+ //# sourceMappingURL=gepa.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gepa.js","sourceRoot":"","sources":["../../../src/orchestrator/selfimprove/gepa.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAG7C,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EACL,gBAAgB,GAEjB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAqBnD,iFAAiF;AAEjF;;;;GAIG;AACH,SAAS,UAAU,CAAC,IAAY;IAC9B,yEAAyE;IACzE,IAAI,CAAC,GAAG,IAAI,KAAK,CAAC,CAAC,CAAC,+BAA+B;IACnD,OAAO;QACL,CAAC,GAAG,CAAC,CAAC,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;QAC3B,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;QACzC,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;QACjD,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,UAAU,CAAC;IAC/C,CAAC,CAAC;AACJ,CAAC;AAED,kFAAkF;AAElF;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,eAAe,CAAC,UAAkB,EAAE,IAAY;IAC9D,MAAM,GAAG,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;IAE7B,MAAM,QAAQ,GAAa,EAAE,CAAC;IAE9B,sEAAsE;IACtE,MAAM,WAAW,GAAG;QAClB,+FAA+F;QAC/F,mHAAmH;QACnH,4IAA4I;QAC5I,8GAA8G;KAC/G,CAAC;IACF,MAAM,aAAa,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC;IAC7D,QAAQ,CAAC,IAAI,CAAC,UAAU,GAAG,WAAW,CAAC,aAAa,CAAC,CAAC,CAAC;IAEvD,wEAAwE;IACxE,MAAM,UAAU,GAAG,CAAC,aAAa,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,CAAC,CAAC;IACxE,MAAM,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC;IAC3D,MAAM,SAAS,GAAG,UAAU,CAAC,YAAY,CAAC,CAAC;IAC3C,qEAAqE;IACrE,MAAM,eAAe,GAAG,UAAU,CAAC,OAAO,CACxC,kBAAkB,EAClB,CAAC,MAAM,EAAE,MAAc,EAAE,KAAa,EAAE,EAAE,CAAC,GAAG,MAAM,GAAG,SAAS,IAAI,KAAK,EAAE,CAC5E,CAAC;IACF,0DAA0D;IAC1D,IAAI,eAAe,KAAK,UAAU,EAAE,CAAC;QACnC,QAAQ,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;IACjC,CAAC;SAAM,CAAC;QACN,8CAA8C;QAC9C,QAAQ,CAAC,IAAI,CAAC,UAAU,GAAG,UAAU,SAAS,iEAAiE,CAAC,CAAC;IACnH,CAAC;IAED,4EAA4E;IAC5E,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACrC,MAAM,aAAa,GAAa,EAAE,CAAC;IACnC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YAC1C,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACxB,CAAC;IACH,CAAC;IACD,kDAAkD;IAClD,IAAI,aAAa,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC;QAC9B,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,CAAC,aAAa,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC;QACjE,MAAM,IAAI,GAAG,aAAa,CAAC,SAAS,CAAC,CAAC;QACtC,MAAM,IAAI,GAAG,aAAa,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC;QAC1C,MAAM,OAAO,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC;QAC3B,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;QAChE,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IACpC,CAAC;SAAM,CAAC;QACN,yCAAyC;QACzC,QAAQ,CAAC,IAAI,CAAC,UAAU,GAAG,iEAAiE,CAAC,CAAC;IAChG,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,kFAAkF;AAElF;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,SAAS,CAAC,MAAsB;IAC9C,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,EAAE,EAAE;QACjC,6EAA6E;QAC7E,OAAO,CAAC,MAAM,CAAC,IAAI,CACjB,CAAC,KAAK,EAAE,EAAE,CACR,KAAK,KAAK,SAAS;YACnB,KAAK,CAAC,eAAe,IAAI,SAAS,CAAC,eAAe;YAClD,KAAK,CAAC,YAAY,IAAI,SAAS,CAAC,YAAY;YAC5C,qCAAqC;YACrC,CAAC,KAAK,CAAC,eAAe,GAAG,SAAS,CAAC,eAAe;gBAChD,KAAK,CAAC,YAAY,GAAG,SAAS,CAAC,YAAY,CAAC,CACjD,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC;AAoBD;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,KAAK,UAAU,MAAM,CAC1B,WAAmB,EACnB,MAAmB,EACnB,IAAmB,EACnB,OAAmB,EAAE;IAErB,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,gBAAgB,CAAC;IACjD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,UAAU,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;IAEnD,2CAA2C;IAC3C,MAAM,SAAS,GAAG,IAAI,CAAC,WAAW,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC;IAC/D,MAAM,WAAW,GAAG,IAAI,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;IAChD,MAAM,SAAS,CAAC,SAAS,CAAC,CAAC;IAC3B,MAAM,SAAS,CAAC,WAAW,CAAC,CAAC;IAE7B,uEAAuE;IACvE,uEAAuE;IACvE,MAAM,SAAS,GAAG,SAAS,IAAI,CAAC,IAAI,EAAE,CAAC;IACvC,MAAM,QAAQ,GAAG,MAAM,mBAAmB,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC;IACnE,MAAM,UAAU,GAAG,QAAQ,CAAC,YAAY,CAAC;IAEzC,yBAAyB;IACzB,MAAM,cAAc,GAAwB,MAAM,OAAO,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;IAC/E,MAAM,oBAAoB,GAAG,cAAc,CAAC,YAAY,CAAC,MAAM,CAAC;IAChE,MAAM,mBAAmB,GAAG,cAAc,CAAC,WAAW,CAAC,MAAM,CAAC;IAC9D,MAAM,iBAAiB,GAAG,cAAc,CAAC,KAAK,GAAG,mBAAmB,CAAC;IAErE,mCAAmC;IACnC,MAAM,QAAQ,GAAG,eAAe,CAAC,UAAU,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;IAExD,oEAAoE;IACpE,MAAM,MAAM,GAAmB,EAAE,CAAC;IAClC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACzC,MAAM,aAAa,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;QAClC,qEAAqE;QACrE,oEAAoE;QACpE,4EAA4E;QAC5E,MAAM,MAAM,GAAwB,MAAM,OAAO,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;QACvE,MAAM,WAAW,GAAG,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC;QAC9C,MAAM,YAAY,GAAG,MAAM,CAAC,YAAY,CAAC,MAAM,CAAC;QAChD,MAAM,eAAe,GAAG,MAAM,CAAC,KAAK,GAAG,WAAW,CAAC;QACnD,MAAM,CAAC,IAAI,CAAC;YACV,SAAS,EAAE,IAAI,CAAC,EAAE;YAClB,MAAM,EAAE,aAAa;YACrB,YAAY,EAAE,aAAa,CAAC,MAAM;YAClC,eAAe;YACf,WAAW;YACX,YAAY;SACb,CAAC,CAAC;IACL,CAAC;IAED,2BAA2B;IAC3B,MAAM,QAAQ,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC;IAEnC,6DAA6D;IAC7D,MAAM,QAAQ,GAAG,QAAQ,CAAC,MAAM,CAC9B,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,KAAK,CAAC,IAAI,CAAC,CAAC,YAAY,GAAG,oBAAoB,CACpE,CAAC;IAEF,6EAA6E;IAC7E,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CACrB,CAAC,CAAC,YAAY,KAAK,CAAC,CAAC,YAAY;QAC/B,CAAC,CAAC,CAAC,CAAC,YAAY,GAAG,CAAC,CAAC,YAAY;QACjC,CAAC,CAAC,CAAC,CAAC,YAAY,GAAG,CAAC,CAAC,YAAY,CACpC,CAAC;IAEF,MAAM,MAAM,GAAG,QAAQ,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC;IACnC,MAAM,QAAQ,GAAG,MAAM,KAAK,IAAI,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC;IAEjD,IAAI,UAAU,GAAkB,IAAI,CAAC;IACrC,IAAI,MAAM,KAAK,IAAI,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;QACpC,UAAU,GAAG,IAAI,CAAC,WAAW,EAAE,GAAG,IAAI,CAAC,IAAI,KAAK,CAAC,CAAC;QAClD,MAAM,SAAS,CAAC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACtD,CAAC;IAED,4BAA4B;IAC5B,MAAM,MAAM,GAAG;QACb,KAAK;QACL,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,MAAM,EAAE,IAAI,CAAC,MAAM,IAAI,KAAK;QAC5B,QAAQ;QACR,UAAU;QACV,mBAAmB;QACnB,oBAAoB;QACpB,iBAAiB;QACjB,aAAa,EAAE,QAAQ,CAAC,MAAM;QAC9B,cAAc,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACnC,SAAS,EAAE,CAAC,CAAC,SAAS;YACtB,YAAY,EAAE,CAAC,CAAC,YAAY;YAC5B,eAAe,EAAE,CAAC,CAAC,eAAe;YAClC,WAAW,EAAE,CAAC,CAAC,WAAW;YAC1B,YAAY,EAAE,CAAC,CAAC,YAAY;YAC5B,QAAQ,EAAE,CAAC,CAAC,WAAW,KAAK,CAAC,IAAI,CAAC,CAAC,YAAY,GAAG,oBAAoB;SACvE,CAAC,CAAC;QACH,SAAS,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YAC5B,SAAS,EAAE,CAAC,CAAC,SAAS;YACtB,YAAY,EAAE,CAAC,CAAC,YAAY;YAC5B,eAAe,EAAE,CAAC,CAAC,eAAe;YAClC,WAAW,EAAE,CAAC,CAAC,WAAW;YAC1B,YAAY,EAAE,CAAC,CAAC,YAAY;SAC7B,CAAC,CAAC;KACJ,CAAC;IACF,MAAM,SAAS,CAAC,IAAI,CAAC,SAAS,EAAE,aAAa,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;IAE1F,OAAO;QACL,QAAQ;QACR,UAAU;QACV,mBAAmB;QACnB,aAAa,EAAE,QAAQ,CAAC,MAAM;KAC/B,CAAC;AACJ,CAAC"}
@@ -0,0 +1,65 @@
1
+ /**
2
+ * PURE deterministic regression gate for the replay corpus.
3
+ *
4
+ * PURE — compareToBaseline must not import from ../providers; no network, no
5
+ * Date.now(), no side effects, no filesystem access. All inputs are parameters.
6
+ * Fresh verdicts are re-derived from frozen eval_details_json — NOT by
7
+ * re-running the generator or evaluator LLM.
8
+ *
9
+ * Regression / improvement classification:
10
+ * baseline 'pass' + fresh 'fail' → regression
11
+ * baseline 'fail' + fresh 'pass' → improvement
12
+ * same verdict → unchanged
13
+ *
14
+ * A regression is STRICTLY pass→fail. CaseIds present only in fresh (not in
15
+ * baseline) are not classified at all — the baseline corpus defines the gate.
16
+ *
17
+ * Fresh-verdict derivation rule (deterministic, no LLM):
18
+ * Parse evalDetailsJson (JSON array of result objects). The fresh verdict is
19
+ * 'fail' iff any element's failures[] contains an entry with
20
+ * passed === false AND severity === 'error'. Otherwise 'pass'.
21
+ * Malformed / missing fields → treated as 'pass' (no error-severity failure).
22
+ */
23
+ import type { BoberConfig } from "../../config/schema.js";
24
+ export type Verdict = "pass" | "fail";
25
+ export interface ReplayComparison {
26
+ /** caseIds where baseline was 'pass' and fresh is 'fail'. */
27
+ regressions: string[];
28
+ /** caseIds where baseline was 'fail' and fresh is 'pass'. */
29
+ improvements: string[];
30
+ /** caseIds where verdict did not change. */
31
+ unchanged: string[];
32
+ }
33
+ /** Extended comparison result returned by runReplayHarness. */
34
+ export interface ReplayHarnessResult extends ReplayComparison {
35
+ /** Total number of cases in the corpus. */
36
+ total: number;
37
+ /** Fresh verdicts keyed by caseId (for CLI table rendering). */
38
+ fresh: Map<string, Verdict>;
39
+ /** Baseline verdicts keyed by caseId (for CLI table rendering). */
40
+ baseline: Map<string, Verdict>;
41
+ }
42
+ /**
43
+ * PURE comparator. Classifies each caseId present in `baseline` as regression,
44
+ * improvement, or unchanged based on the transition of verdict.
45
+ *
46
+ * PURE — no clock, no fs, no LLM. All inputs are parameters.
47
+ *
48
+ * @param baseline Map<caseId, Verdict> from the captured corpus.
49
+ * @param fresh Map<caseId, Verdict> re-derived from frozen evalDetailsJson.
50
+ * @returns Sorted arrays for deterministic, byte-identical output.
51
+ */
52
+ export declare function compareToBaseline(baseline: Map<string, Verdict>, fresh: Map<string, Verdict>): ReplayComparison;
53
+ /**
54
+ * Open the Sprint-1 ReplayStore, re-derive fresh verdicts deterministically
55
+ * from each case's frozen evalDetailsJson, and return a regression/improvement
56
+ * breakdown via compareToBaseline.
57
+ *
58
+ * NEVER re-runs the generator or evaluator LLM — fresh verdicts come only from
59
+ * the frozen captured eval_details_json (the deterministic fresh-verdict rule).
60
+ *
61
+ * @param projectRoot Absolute path to the project root.
62
+ * @param config Already-loaded BoberConfig. config.selfImprove is OPTIONAL.
63
+ */
64
+ export declare function runReplayHarness(projectRoot: string, config: BoberConfig): Promise<ReplayHarnessResult>;
65
+ //# sourceMappingURL=replay-harness.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"replay-harness.d.ts","sourceRoot":"","sources":["../../../src/orchestrator/selfimprove/replay-harness.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAIH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAK1D,MAAM,MAAM,OAAO,GAAG,MAAM,GAAG,MAAM,CAAC;AAEtC,MAAM,WAAW,gBAAgB;IAC/B,6DAA6D;IAC7D,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,6DAA6D;IAC7D,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,4CAA4C;IAC5C,SAAS,EAAE,MAAM,EAAE,CAAC;CACrB;AAED,+DAA+D;AAC/D,MAAM,WAAW,mBAAoB,SAAQ,gBAAgB;IAC3D,2CAA2C;IAC3C,KAAK,EAAE,MAAM,CAAC;IACd,gEAAgE;IAChE,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC5B,mEAAmE;IACnE,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAChC;AAWD;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9B,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,GAC1B,gBAAgB,CAwBlB;AA6CD;;;;;;;;;;GAUG;AACH,wBAAsB,gBAAgB,CACpC,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,WAAW,GAClB,OAAO,CAAC,mBAAmB,CAAC,CAuB9B"}
@@ -0,0 +1,134 @@
1
+ /**
2
+ * PURE deterministic regression gate for the replay corpus.
3
+ *
4
+ * PURE — compareToBaseline must not import from ../providers; no network, no
5
+ * Date.now(), no side effects, no filesystem access. All inputs are parameters.
6
+ * Fresh verdicts are re-derived from frozen eval_details_json — NOT by
7
+ * re-running the generator or evaluator LLM.
8
+ *
9
+ * Regression / improvement classification:
10
+ * baseline 'pass' + fresh 'fail' → regression
11
+ * baseline 'fail' + fresh 'pass' → improvement
12
+ * same verdict → unchanged
13
+ *
14
+ * A regression is STRICTLY pass→fail. CaseIds present only in fresh (not in
15
+ * baseline) are not classified at all — the baseline corpus defines the gate.
16
+ *
17
+ * Fresh-verdict derivation rule (deterministic, no LLM):
18
+ * Parse evalDetailsJson (JSON array of result objects). The fresh verdict is
19
+ * 'fail' iff any element's failures[] contains an entry with
20
+ * passed === false AND severity === 'error'. Otherwise 'pass'.
21
+ * Malformed / missing fields → treated as 'pass' (no error-severity failure).
22
+ */
23
+ import { join } from "node:path";
24
+ import { ReplayStore } from "./replay-store.js";
25
+ // ── Helpers ───────────────────────────────────────────────────────────
26
+ /** Lenient record narrowing — mirrors distill.ts:83-85. */
27
+ function isRecord(v) {
28
+ return typeof v === "object" && v !== null && !Array.isArray(v);
29
+ }
30
+ // ── PURE: compareToBaseline ───────────────────────────────────────────
31
+ /**
32
+ * PURE comparator. Classifies each caseId present in `baseline` as regression,
33
+ * improvement, or unchanged based on the transition of verdict.
34
+ *
35
+ * PURE — no clock, no fs, no LLM. All inputs are parameters.
36
+ *
37
+ * @param baseline Map<caseId, Verdict> from the captured corpus.
38
+ * @param fresh Map<caseId, Verdict> re-derived from frozen evalDetailsJson.
39
+ * @returns Sorted arrays for deterministic, byte-identical output.
40
+ */
41
+ export function compareToBaseline(baseline, fresh) {
42
+ const regressions = [];
43
+ const improvements = [];
44
+ const unchanged = [];
45
+ for (const [caseId, baselineVerdict] of baseline) {
46
+ // CaseIds absent from fresh use the baseline verdict (treat as unchanged).
47
+ const freshVerdict = fresh.get(caseId) ?? baselineVerdict;
48
+ if (baselineVerdict === "pass" && freshVerdict === "fail") {
49
+ regressions.push(caseId);
50
+ }
51
+ else if (baselineVerdict === "fail" && freshVerdict === "pass") {
52
+ improvements.push(caseId);
53
+ }
54
+ else {
55
+ unchanged.push(caseId);
56
+ }
57
+ }
58
+ // Sort for deterministic, byte-identical output — mirrors distill.ts:286.
59
+ regressions.sort((a, b) => a.localeCompare(b));
60
+ improvements.sort((a, b) => a.localeCompare(b));
61
+ unchanged.sort((a, b) => a.localeCompare(b));
62
+ return { regressions, improvements, unchanged };
63
+ }
64
+ // ── Fresh-verdict derivation (deterministic, NO LLM) ─────────────────
65
+ /**
66
+ * Re-derive a single fresh verdict from the frozen evalDetailsJson string.
67
+ *
68
+ * Rule: parse the JSON array; verdict is 'fail' iff any element's failures[]
69
+ * contains an entry with passed === false AND severity === 'error'.
70
+ * Any malformed / absent field is treated permissively → 'pass'.
71
+ *
72
+ * @param evalDetailsJson JSON.stringify(payload.results) captured at record time.
73
+ */
74
+ function deriveFreshVerdict(evalDetailsJson) {
75
+ let parsed;
76
+ try {
77
+ parsed = JSON.parse(evalDetailsJson);
78
+ }
79
+ catch {
80
+ return "pass"; // Malformed JSON → no error-severity failure found.
81
+ }
82
+ if (!Array.isArray(parsed)) {
83
+ return "pass";
84
+ }
85
+ for (const element of parsed) {
86
+ if (!isRecord(element))
87
+ continue;
88
+ const failures = element["failures"];
89
+ if (!Array.isArray(failures))
90
+ continue;
91
+ for (const detail of failures) {
92
+ if (!isRecord(detail))
93
+ continue;
94
+ if (detail["passed"] === false && detail["severity"] === "error") {
95
+ return "fail";
96
+ }
97
+ }
98
+ }
99
+ return "pass";
100
+ }
101
+ // ── async: runReplayHarness ───────────────────────────────────────────
102
+ /**
103
+ * Open the Sprint-1 ReplayStore, re-derive fresh verdicts deterministically
104
+ * from each case's frozen evalDetailsJson, and return a regression/improvement
105
+ * breakdown via compareToBaseline.
106
+ *
107
+ * NEVER re-runs the generator or evaluator LLM — fresh verdicts come only from
108
+ * the frozen captured eval_details_json (the deterministic fresh-verdict rule).
109
+ *
110
+ * @param projectRoot Absolute path to the project root.
111
+ * @param config Already-loaded BoberConfig. config.selfImprove is OPTIONAL.
112
+ */
113
+ export async function runReplayHarness(projectRoot, config) {
114
+ // bober: default replayDir so missing selfImprove section is non-fatal.
115
+ const replayDir = config.selfImprove?.replayDir ?? ".bober/replay";
116
+ const dbPath = join(projectRoot, replayDir, "replay.db");
117
+ const store = new ReplayStore(dbPath);
118
+ try {
119
+ const cases = store.listCases();
120
+ const total = cases.length;
121
+ const baseline = new Map();
122
+ const fresh = new Map();
123
+ for (const record of cases) {
124
+ baseline.set(record.caseId, record.baselineVerdict);
125
+ fresh.set(record.caseId, deriveFreshVerdict(record.evalDetailsJson));
126
+ }
127
+ const comparison = compareToBaseline(baseline, fresh);
128
+ return { ...comparison, total, baseline, fresh };
129
+ }
130
+ finally {
131
+ store.close();
132
+ }
133
+ }
134
+ //# sourceMappingURL=replay-harness.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"replay-harness.js","sourceRoot":"","sources":["../../../src/orchestrator/selfimprove/replay-harness.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,45 @@
1
+ import { type ReplayCaseInput, type ReplayCaseRecord } from "./replay-types.js";
2
+ /**
3
+ * Derive a deterministic 16-char hex case id from the case signature.
4
+ * caseId = sha256(`${contractId}|${iteration}|${diffDigest}`).slice(0,16)
5
+ * MIRRORS factId at src/state/facts.ts:58-69.
6
+ *
7
+ * NOTE: tCaptured is intentionally EXCLUDED from the hash so the id stays
8
+ * stable across captures — only a change in diffDigest changes the id.
9
+ * Identical inputs always produce the same id — no wall-clock dependency.
10
+ */
11
+ export declare function caseId(contractId: string, iteration: number, diffDigest: string): string;
12
+ /**
13
+ * SQLite-backed replay case store.
14
+ *
15
+ * PURE: Never calls Date.now() or new Date() — every timestamp is a parameter.
16
+ * Hidden behind this interface so the driver (better-sqlite3) is swappable.
17
+ *
18
+ * bober: in-memory or file-backed via better-sqlite3 (synchronous); swap for
19
+ * node:sqlite when engines.node is raised to >=22.5.
20
+ */
21
+ export declare class ReplayStore {
22
+ private db;
23
+ constructor(dbPath: string);
24
+ /**
25
+ * Insert or replace a replay case. Validates input with ReplayCaseSchema and
26
+ * derives the deterministic caseId. Returns the persisted ReplayCaseRecord.
27
+ */
28
+ putCase(input: ReplayCaseInput): ReplayCaseRecord;
29
+ /**
30
+ * Return a single replay case by its id.
31
+ * Returns null if not found.
32
+ */
33
+ getCase(id: string): ReplayCaseRecord | null;
34
+ /**
35
+ * Return all replay cases ordered by t_captured ascending.
36
+ */
37
+ listCases(): ReplayCaseRecord[];
38
+ /**
39
+ * Return the baseline verdict for a case id, or null if not found.
40
+ */
41
+ getBaselineVerdict(id: string): string | null;
42
+ /** Close the underlying database connection. */
43
+ close(): void;
44
+ }
45
+ //# sourceMappingURL=replay-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"replay-store.d.ts","sourceRoot":"","sources":["../../../src/orchestrator/selfimprove/replay-store.ts"],"names":[],"mappings":"AAIA,OAAO,EAEL,KAAK,eAAe,EACpB,KAAK,gBAAgB,EACtB,MAAM,mBAAmB,CAAC;AAI3B;;;;;;;;GAQG;AACH,wBAAgB,MAAM,CACpB,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,GACjB,MAAM,CAKR;AA4BD;;;;;;;;GAQG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,EAAE,CAAe;gBAEb,MAAM,EAAE,MAAM;IAe1B;;;OAGG;IACH,OAAO,CAAC,KAAK,EAAE,eAAe,GAAG,gBAAgB;IAsCjD;;;OAGG;IACH,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,gBAAgB,GAAG,IAAI;IAO5C;;OAEG;IACH,SAAS,IAAI,gBAAgB,EAAE;IAO/B;;OAEG;IACH,kBAAkB,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAO7C,gDAAgD;IAChD,KAAK,IAAI,IAAI;CAGd"}