agent-bober 0.11.6 → 0.15.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 (570) hide show
  1. package/CHANGELOG.md +311 -0
  2. package/README.md +124 -9
  3. package/agents/bober-architect.md +38 -0
  4. package/agents/bober-code-reviewer.md +236 -0
  5. package/agents/bober-curator.md +37 -0
  6. package/agents/bober-deployer.md +267 -0
  7. package/agents/bober-diagnoser.md +289 -0
  8. package/agents/bober-evaluator.md +127 -1
  9. package/agents/bober-generator.md +122 -3
  10. package/agents/bober-planner.md +293 -32
  11. package/agents/bober-postmortemer.md +185 -0
  12. package/agents/bober-researcher.md +38 -0
  13. package/dist/cli/commands/approve.d.ts +17 -0
  14. package/dist/cli/commands/approve.d.ts.map +1 -0
  15. package/dist/cli/commands/approve.js +64 -0
  16. package/dist/cli/commands/approve.js.map +1 -0
  17. package/dist/cli/commands/audit-show.d.ts +14 -0
  18. package/dist/cli/commands/audit-show.d.ts.map +1 -0
  19. package/dist/cli/commands/audit-show.js +85 -0
  20. package/dist/cli/commands/audit-show.js.map +1 -0
  21. package/dist/cli/commands/config.d.ts +10 -0
  22. package/dist/cli/commands/config.d.ts.map +1 -0
  23. package/dist/cli/commands/config.js +73 -0
  24. package/dist/cli/commands/config.js.map +1 -0
  25. package/dist/cli/commands/eval.js +6 -6
  26. package/dist/cli/commands/eval.js.map +1 -1
  27. package/dist/cli/commands/graph.d.ts +8 -0
  28. package/dist/cli/commands/graph.d.ts.map +1 -0
  29. package/dist/cli/commands/graph.js +219 -0
  30. package/dist/cli/commands/graph.js.map +1 -0
  31. package/dist/cli/commands/impact.d.ts +19 -0
  32. package/dist/cli/commands/impact.d.ts.map +1 -0
  33. package/dist/cli/commands/impact.js +191 -0
  34. package/dist/cli/commands/impact.js.map +1 -0
  35. package/dist/cli/commands/incident.d.ts +19 -0
  36. package/dist/cli/commands/incident.d.ts.map +1 -0
  37. package/dist/cli/commands/incident.js +324 -0
  38. package/dist/cli/commands/incident.js.map +1 -0
  39. package/dist/cli/commands/init.js +82 -3
  40. package/dist/cli/commands/init.js.map +1 -1
  41. package/dist/cli/commands/list-approvals.d.ts +16 -0
  42. package/dist/cli/commands/list-approvals.d.ts.map +1 -0
  43. package/dist/cli/commands/list-approvals.js +57 -0
  44. package/dist/cli/commands/list-approvals.js.map +1 -0
  45. package/dist/cli/commands/onboard.d.ts +3 -0
  46. package/dist/cli/commands/onboard.d.ts.map +1 -0
  47. package/dist/cli/commands/onboard.js +190 -0
  48. package/dist/cli/commands/onboard.js.map +1 -0
  49. package/dist/cli/commands/plan.d.ts +12 -0
  50. package/dist/cli/commands/plan.d.ts.map +1 -1
  51. package/dist/cli/commands/plan.js +232 -37
  52. package/dist/cli/commands/plan.js.map +1 -1
  53. package/dist/cli/commands/playbook.d.ts +17 -0
  54. package/dist/cli/commands/playbook.d.ts.map +1 -0
  55. package/dist/cli/commands/playbook.js +123 -0
  56. package/dist/cli/commands/playbook.js.map +1 -0
  57. package/dist/cli/commands/postmortem.d.ts +12 -0
  58. package/dist/cli/commands/postmortem.d.ts.map +1 -0
  59. package/dist/cli/commands/postmortem.js +67 -0
  60. package/dist/cli/commands/postmortem.js.map +1 -0
  61. package/dist/cli/commands/reject.d.ts +17 -0
  62. package/dist/cli/commands/reject.d.ts.map +1 -0
  63. package/dist/cli/commands/reject.js +52 -0
  64. package/dist/cli/commands/reject.js.map +1 -0
  65. package/dist/cli/commands/rollback.d.ts +21 -0
  66. package/dist/cli/commands/rollback.d.ts.map +1 -0
  67. package/dist/cli/commands/rollback.js +90 -0
  68. package/dist/cli/commands/rollback.js.map +1 -0
  69. package/dist/cli/commands/run.d.ts +9 -0
  70. package/dist/cli/commands/run.d.ts.map +1 -1
  71. package/dist/cli/commands/run.js +31 -2
  72. package/dist/cli/commands/run.js.map +1 -1
  73. package/dist/cli/commands/sprint.d.ts.map +1 -1
  74. package/dist/cli/commands/sprint.js +8 -8
  75. package/dist/cli/commands/sprint.js.map +1 -1
  76. package/dist/cli/commands/telemetry.d.ts +16 -0
  77. package/dist/cli/commands/telemetry.d.ts.map +1 -0
  78. package/dist/cli/commands/telemetry.js +152 -0
  79. package/dist/cli/commands/telemetry.js.map +1 -0
  80. package/dist/cli/commands/worktree.d.ts +12 -0
  81. package/dist/cli/commands/worktree.d.ts.map +1 -0
  82. package/dist/cli/commands/worktree.js +57 -0
  83. package/dist/cli/commands/worktree.js.map +1 -0
  84. package/dist/cli/index.js +73 -2
  85. package/dist/cli/index.js.map +1 -1
  86. package/dist/config/defaults.d.ts.map +1 -1
  87. package/dist/config/defaults.js +27 -0
  88. package/dist/config/defaults.js.map +1 -1
  89. package/dist/config/index.d.ts +1 -1
  90. package/dist/config/index.d.ts.map +1 -1
  91. package/dist/config/index.js +4 -0
  92. package/dist/config/index.js.map +1 -1
  93. package/dist/config/loader.d.ts.map +1 -1
  94. package/dist/config/loader.js +18 -1
  95. package/dist/config/loader.js.map +1 -1
  96. package/dist/config/schema.d.ts +1016 -96
  97. package/dist/config/schema.d.ts.map +1 -1
  98. package/dist/config/schema.js +147 -0
  99. package/dist/config/schema.js.map +1 -1
  100. package/dist/contracts/eval-result.d.ts +38 -38
  101. package/dist/contracts/index.d.ts +2 -2
  102. package/dist/contracts/index.d.ts.map +1 -1
  103. package/dist/contracts/index.js +8 -4
  104. package/dist/contracts/index.js.map +1 -1
  105. package/dist/contracts/spec.d.ts +335 -40
  106. package/dist/contracts/spec.d.ts.map +1 -1
  107. package/dist/contracts/spec.js +210 -18
  108. package/dist/contracts/spec.js.map +1 -1
  109. package/dist/contracts/sprint-contract.d.ts +155 -88
  110. package/dist/contracts/sprint-contract.d.ts.map +1 -1
  111. package/dist/contracts/sprint-contract.js +176 -29
  112. package/dist/contracts/sprint-contract.js.map +1 -1
  113. package/dist/evaluators/builtin/api-check.js +1 -1
  114. package/dist/evaluators/builtin/api-check.js.map +1 -1
  115. package/dist/graph/artifact-store.d.ts +14 -0
  116. package/dist/graph/artifact-store.d.ts.map +1 -0
  117. package/dist/graph/artifact-store.js +100 -0
  118. package/dist/graph/artifact-store.js.map +1 -0
  119. package/dist/graph/cli.d.ts +49 -0
  120. package/dist/graph/cli.d.ts.map +1 -0
  121. package/dist/graph/cli.js +140 -0
  122. package/dist/graph/cli.js.map +1 -0
  123. package/dist/graph/client.d.ts +64 -0
  124. package/dist/graph/client.d.ts.map +1 -0
  125. package/dist/graph/client.js +216 -0
  126. package/dist/graph/client.js.map +1 -0
  127. package/dist/graph/fallback.d.ts +13 -0
  128. package/dist/graph/fallback.d.ts.map +1 -0
  129. package/dist/graph/fallback.js +57 -0
  130. package/dist/graph/fallback.js.map +1 -0
  131. package/dist/graph/hook-handler.d.ts +50 -0
  132. package/dist/graph/hook-handler.d.ts.map +1 -0
  133. package/dist/graph/hook-handler.js +217 -0
  134. package/dist/graph/hook-handler.js.map +1 -0
  135. package/dist/graph/incidents.d.ts +59 -0
  136. package/dist/graph/incidents.d.ts.map +1 -0
  137. package/dist/graph/incidents.js +22 -0
  138. package/dist/graph/incidents.js.map +1 -0
  139. package/dist/graph/mcp-client.d.ts +51 -0
  140. package/dist/graph/mcp-client.d.ts.map +1 -0
  141. package/dist/graph/mcp-client.js +285 -0
  142. package/dist/graph/mcp-client.js.map +1 -0
  143. package/dist/graph/onboarding-composer.d.ts +30 -0
  144. package/dist/graph/onboarding-composer.d.ts.map +1 -0
  145. package/dist/graph/onboarding-composer.js +275 -0
  146. package/dist/graph/onboarding-composer.js.map +1 -0
  147. package/dist/graph/pipeline-lifecycle.d.ts +86 -0
  148. package/dist/graph/pipeline-lifecycle.d.ts.map +1 -0
  149. package/dist/graph/pipeline-lifecycle.js +329 -0
  150. package/dist/graph/pipeline-lifecycle.js.map +1 -0
  151. package/dist/graph/preflight-budgets.d.ts +52 -0
  152. package/dist/graph/preflight-budgets.d.ts.map +1 -0
  153. package/dist/graph/preflight-budgets.js +78 -0
  154. package/dist/graph/preflight-budgets.js.map +1 -0
  155. package/dist/graph/preflight-injector.d.ts +116 -0
  156. package/dist/graph/preflight-injector.d.ts.map +1 -0
  157. package/dist/graph/preflight-injector.js +538 -0
  158. package/dist/graph/preflight-injector.js.map +1 -0
  159. package/dist/graph/prereq.d.ts +12 -0
  160. package/dist/graph/prereq.d.ts.map +1 -0
  161. package/dist/graph/prereq.js +61 -0
  162. package/dist/graph/prereq.js.map +1 -0
  163. package/dist/graph/prompts.d.ts +42 -0
  164. package/dist/graph/prompts.d.ts.map +1 -0
  165. package/dist/graph/prompts.js +80 -0
  166. package/dist/graph/prompts.js.map +1 -0
  167. package/dist/graph/sandbox.d.ts +19 -0
  168. package/dist/graph/sandbox.d.ts.map +1 -0
  169. package/dist/graph/sandbox.js +25 -0
  170. package/dist/graph/sandbox.js.map +1 -0
  171. package/dist/graph/token-usage.d.ts +21 -0
  172. package/dist/graph/token-usage.d.ts.map +1 -0
  173. package/dist/graph/token-usage.js +22 -0
  174. package/dist/graph/token-usage.js.map +1 -0
  175. package/dist/graph/types.d.ts +129 -0
  176. package/dist/graph/types.d.ts.map +1 -0
  177. package/dist/graph/types.js +12 -0
  178. package/dist/graph/types.js.map +1 -0
  179. package/dist/incident/orchestrator.d.ts +168 -0
  180. package/dist/incident/orchestrator.d.ts.map +1 -0
  181. package/dist/incident/orchestrator.js +279 -0
  182. package/dist/incident/orchestrator.js.map +1 -0
  183. package/dist/incident/playbook-search.d.ts +67 -0
  184. package/dist/incident/playbook-search.d.ts.map +1 -0
  185. package/dist/incident/playbook-search.js +288 -0
  186. package/dist/incident/playbook-search.js.map +1 -0
  187. package/dist/incident/postmortem.d.ts +44 -0
  188. package/dist/incident/postmortem.d.ts.map +1 -0
  189. package/dist/incident/postmortem.js +486 -0
  190. package/dist/incident/postmortem.js.map +1 -0
  191. package/dist/incident/resolution-verify.d.ts +186 -0
  192. package/dist/incident/resolution-verify.d.ts.map +1 -0
  193. package/dist/incident/resolution-verify.js +210 -0
  194. package/dist/incident/resolution-verify.js.map +1 -0
  195. package/dist/incident/rollback.d.ts +137 -0
  196. package/dist/incident/rollback.d.ts.map +1 -0
  197. package/dist/incident/rollback.js +328 -0
  198. package/dist/incident/rollback.js.map +1 -0
  199. package/dist/incident/timeline.d.ts +147 -0
  200. package/dist/incident/timeline.d.ts.map +1 -0
  201. package/dist/incident/timeline.js +452 -0
  202. package/dist/incident/timeline.js.map +1 -0
  203. package/dist/incident/types.d.ts +335 -0
  204. package/dist/incident/types.d.ts.map +1 -0
  205. package/dist/incident/types.js +158 -0
  206. package/dist/incident/types.js.map +1 -0
  207. package/dist/index.d.ts +3 -3
  208. package/dist/index.d.ts.map +1 -1
  209. package/dist/index.js +3 -3
  210. package/dist/index.js.map +1 -1
  211. package/dist/mcp/event-stream.d.ts +46 -0
  212. package/dist/mcp/event-stream.d.ts.map +1 -0
  213. package/dist/mcp/event-stream.js +421 -0
  214. package/dist/mcp/event-stream.js.map +1 -0
  215. package/dist/mcp/external-client.d.ts +38 -0
  216. package/dist/mcp/external-client.d.ts.map +1 -0
  217. package/dist/mcp/external-client.js +121 -0
  218. package/dist/mcp/external-client.js.map +1 -0
  219. package/dist/mcp/run-manager.d.ts +74 -9
  220. package/dist/mcp/run-manager.d.ts.map +1 -1
  221. package/dist/mcp/run-manager.js +127 -31
  222. package/dist/mcp/run-manager.js.map +1 -1
  223. package/dist/mcp/server.d.ts.map +1 -1
  224. package/dist/mcp/server.js +56 -0
  225. package/dist/mcp/server.js.map +1 -1
  226. package/dist/mcp/tools/abort-run.d.ts +2 -0
  227. package/dist/mcp/tools/abort-run.d.ts.map +1 -0
  228. package/dist/mcp/tools/abort-run.js +62 -0
  229. package/dist/mcp/tools/abort-run.js.map +1 -0
  230. package/dist/mcp/tools/anchor.js +1 -1
  231. package/dist/mcp/tools/anchor.js.map +1 -1
  232. package/dist/mcp/tools/approve-checkpoint.d.ts +2 -0
  233. package/dist/mcp/tools/approve-checkpoint.d.ts.map +1 -0
  234. package/dist/mcp/tools/approve-checkpoint.js +70 -0
  235. package/dist/mcp/tools/approve-checkpoint.js.map +1 -0
  236. package/dist/mcp/tools/brownfield.js +1 -1
  237. package/dist/mcp/tools/brownfield.js.map +1 -1
  238. package/dist/mcp/tools/contracts.js +2 -2
  239. package/dist/mcp/tools/contracts.js.map +1 -1
  240. package/dist/mcp/tools/eval.js +8 -8
  241. package/dist/mcp/tools/eval.js.map +1 -1
  242. package/dist/mcp/tools/get-project-state.d.ts +2 -0
  243. package/dist/mcp/tools/get-project-state.d.ts.map +1 -0
  244. package/dist/mcp/tools/get-project-state.js +107 -0
  245. package/dist/mcp/tools/get-project-state.js.map +1 -0
  246. package/dist/mcp/tools/get-run-status.d.ts +2 -0
  247. package/dist/mcp/tools/get-run-status.d.ts.map +1 -0
  248. package/dist/mcp/tools/get-run-status.js +40 -0
  249. package/dist/mcp/tools/get-run-status.js.map +1 -0
  250. package/dist/mcp/tools/graph-schemas.d.ts +100 -0
  251. package/dist/mcp/tools/graph-schemas.d.ts.map +1 -0
  252. package/dist/mcp/tools/graph-schemas.js +39 -0
  253. package/dist/mcp/tools/graph-schemas.js.map +1 -0
  254. package/dist/mcp/tools/graph.d.ts +19 -0
  255. package/dist/mcp/tools/graph.d.ts.map +1 -0
  256. package/dist/mcp/tools/graph.js +263 -0
  257. package/dist/mcp/tools/graph.js.map +1 -0
  258. package/dist/mcp/tools/incident.d.ts +2 -0
  259. package/dist/mcp/tools/incident.d.ts.map +1 -0
  260. package/dist/mcp/tools/incident.js +246 -0
  261. package/dist/mcp/tools/incident.js.map +1 -0
  262. package/dist/mcp/tools/index.d.ts +38 -18
  263. package/dist/mcp/tools/index.d.ts.map +1 -1
  264. package/dist/mcp/tools/index.js +74 -18
  265. package/dist/mcp/tools/index.js.map +1 -1
  266. package/dist/mcp/tools/list-active-runs.d.ts +2 -0
  267. package/dist/mcp/tools/list-active-runs.d.ts.map +1 -0
  268. package/dist/mcp/tools/list-active-runs.js +35 -0
  269. package/dist/mcp/tools/list-active-runs.js.map +1 -0
  270. package/dist/mcp/tools/list-pending-approvals.d.ts +2 -0
  271. package/dist/mcp/tools/list-pending-approvals.d.ts.map +1 -0
  272. package/dist/mcp/tools/list-pending-approvals.js +40 -0
  273. package/dist/mcp/tools/list-pending-approvals.js.map +1 -0
  274. package/dist/mcp/tools/list-projects.d.ts +2 -0
  275. package/dist/mcp/tools/list-projects.d.ts.map +1 -0
  276. package/dist/mcp/tools/list-projects.js +101 -0
  277. package/dist/mcp/tools/list-projects.js.map +1 -0
  278. package/dist/mcp/tools/list-specs.d.ts +2 -0
  279. package/dist/mcp/tools/list-specs.d.ts.map +1 -0
  280. package/dist/mcp/tools/list-specs.js +48 -0
  281. package/dist/mcp/tools/list-specs.js.map +1 -0
  282. package/dist/mcp/tools/plan.d.ts.map +1 -1
  283. package/dist/mcp/tools/plan.js +40 -14
  284. package/dist/mcp/tools/plan.js.map +1 -1
  285. package/dist/mcp/tools/playbook.d.ts +2 -0
  286. package/dist/mcp/tools/playbook.d.ts.map +1 -0
  287. package/dist/mcp/tools/playbook.js +104 -0
  288. package/dist/mcp/tools/playbook.js.map +1 -0
  289. package/dist/mcp/tools/postmortem.d.ts +2 -0
  290. package/dist/mcp/tools/postmortem.d.ts.map +1 -0
  291. package/dist/mcp/tools/postmortem.js +75 -0
  292. package/dist/mcp/tools/postmortem.js.map +1 -0
  293. package/dist/mcp/tools/react.js +1 -1
  294. package/dist/mcp/tools/react.js.map +1 -1
  295. package/dist/mcp/tools/reject-checkpoint.d.ts +2 -0
  296. package/dist/mcp/tools/reject-checkpoint.d.ts.map +1 -0
  297. package/dist/mcp/tools/reject-checkpoint.js +79 -0
  298. package/dist/mcp/tools/reject-checkpoint.js.map +1 -0
  299. package/dist/mcp/tools/rollback.d.ts +2 -0
  300. package/dist/mcp/tools/rollback.d.ts.map +1 -0
  301. package/dist/mcp/tools/rollback.js +78 -0
  302. package/dist/mcp/tools/rollback.js.map +1 -0
  303. package/dist/mcp/tools/run-in-worktree.d.ts +2 -0
  304. package/dist/mcp/tools/run-in-worktree.d.ts.map +1 -0
  305. package/dist/mcp/tools/run-in-worktree.js +90 -0
  306. package/dist/mcp/tools/run-in-worktree.js.map +1 -0
  307. package/dist/mcp/tools/run.js +1 -1
  308. package/dist/mcp/tools/run.js.map +1 -1
  309. package/dist/mcp/tools/solidity.js +1 -1
  310. package/dist/mcp/tools/solidity.js.map +1 -1
  311. package/dist/mcp/tools/sprint.d.ts.map +1 -1
  312. package/dist/mcp/tools/sprint.js +11 -11
  313. package/dist/mcp/tools/sprint.js.map +1 -1
  314. package/dist/mcp/tools/status.d.ts.map +1 -1
  315. package/dist/mcp/tools/status.js +11 -0
  316. package/dist/mcp/tools/status.js.map +1 -1
  317. package/dist/mcp/tools/subscribe-events.d.ts +2 -0
  318. package/dist/mcp/tools/subscribe-events.d.ts.map +1 -0
  319. package/dist/mcp/tools/subscribe-events.js +48 -0
  320. package/dist/mcp/tools/subscribe-events.js.map +1 -0
  321. package/dist/mcp/tools/unsubscribe-events.d.ts +2 -0
  322. package/dist/mcp/tools/unsubscribe-events.d.ts.map +1 -0
  323. package/dist/mcp/tools/unsubscribe-events.js +45 -0
  324. package/dist/mcp/tools/unsubscribe-events.js.map +1 -0
  325. package/dist/orchestrator/agent-loader.d.ts +16 -0
  326. package/dist/orchestrator/agent-loader.d.ts.map +1 -1
  327. package/dist/orchestrator/agent-loader.js +16 -0
  328. package/dist/orchestrator/agent-loader.js.map +1 -1
  329. package/dist/orchestrator/architect-agent.d.ts.map +1 -1
  330. package/dist/orchestrator/architect-agent.js +37 -8
  331. package/dist/orchestrator/architect-agent.js.map +1 -1
  332. package/dist/orchestrator/checkpoints/audit.d.ts +128 -0
  333. package/dist/orchestrator/checkpoints/audit.d.ts.map +1 -0
  334. package/dist/orchestrator/checkpoints/audit.js +272 -0
  335. package/dist/orchestrator/checkpoints/audit.js.map +1 -0
  336. package/dist/orchestrator/checkpoints/feedback-router.d.ts +213 -0
  337. package/dist/orchestrator/checkpoints/feedback-router.d.ts.map +1 -0
  338. package/dist/orchestrator/checkpoints/feedback-router.js +438 -0
  339. package/dist/orchestrator/checkpoints/feedback-router.js.map +1 -0
  340. package/dist/orchestrator/checkpoints/index.d.ts +11 -0
  341. package/dist/orchestrator/checkpoints/index.d.ts.map +1 -0
  342. package/dist/orchestrator/checkpoints/index.js +12 -0
  343. package/dist/orchestrator/checkpoints/index.js.map +1 -0
  344. package/dist/orchestrator/checkpoints/mechanisms/cli.d.ts +35 -0
  345. package/dist/orchestrator/checkpoints/mechanisms/cli.d.ts.map +1 -0
  346. package/dist/orchestrator/checkpoints/mechanisms/cli.js +153 -0
  347. package/dist/orchestrator/checkpoints/mechanisms/cli.js.map +1 -0
  348. package/dist/orchestrator/checkpoints/mechanisms/disk.d.ts +34 -0
  349. package/dist/orchestrator/checkpoints/mechanisms/disk.d.ts.map +1 -0
  350. package/dist/orchestrator/checkpoints/mechanisms/disk.js +139 -0
  351. package/dist/orchestrator/checkpoints/mechanisms/disk.js.map +1 -0
  352. package/dist/orchestrator/checkpoints/mechanisms/pr.d.ts +141 -0
  353. package/dist/orchestrator/checkpoints/mechanisms/pr.d.ts.map +1 -0
  354. package/dist/orchestrator/checkpoints/mechanisms/pr.js +445 -0
  355. package/dist/orchestrator/checkpoints/mechanisms/pr.js.map +1 -0
  356. package/dist/orchestrator/checkpoints/noop.d.ts +12 -0
  357. package/dist/orchestrator/checkpoints/noop.d.ts.map +1 -0
  358. package/dist/orchestrator/checkpoints/noop.js +13 -0
  359. package/dist/orchestrator/checkpoints/noop.js.map +1 -0
  360. package/dist/orchestrator/checkpoints/registry.d.ts +48 -0
  361. package/dist/orchestrator/checkpoints/registry.d.ts.map +1 -0
  362. package/dist/orchestrator/checkpoints/registry.js +89 -0
  363. package/dist/orchestrator/checkpoints/registry.js.map +1 -0
  364. package/dist/orchestrator/checkpoints/renderers/_util.d.ts +50 -0
  365. package/dist/orchestrator/checkpoints/renderers/_util.d.ts.map +1 -0
  366. package/dist/orchestrator/checkpoints/renderers/_util.js +137 -0
  367. package/dist/orchestrator/checkpoints/renderers/_util.js.map +1 -0
  368. package/dist/orchestrator/checkpoints/renderers/code-review.d.ts +15 -0
  369. package/dist/orchestrator/checkpoints/renderers/code-review.d.ts.map +1 -0
  370. package/dist/orchestrator/checkpoints/renderers/code-review.js +66 -0
  371. package/dist/orchestrator/checkpoints/renderers/code-review.js.map +1 -0
  372. package/dist/orchestrator/checkpoints/renderers/curator-briefing.d.ts +15 -0
  373. package/dist/orchestrator/checkpoints/renderers/curator-briefing.d.ts.map +1 -0
  374. package/dist/orchestrator/checkpoints/renderers/curator-briefing.js +40 -0
  375. package/dist/orchestrator/checkpoints/renderers/curator-briefing.js.map +1 -0
  376. package/dist/orchestrator/checkpoints/renderers/eval-result.d.ts +15 -0
  377. package/dist/orchestrator/checkpoints/renderers/eval-result.d.ts.map +1 -0
  378. package/dist/orchestrator/checkpoints/renderers/eval-result.js +54 -0
  379. package/dist/orchestrator/checkpoints/renderers/eval-result.js.map +1 -0
  380. package/dist/orchestrator/checkpoints/renderers/generator-diff.d.ts +49 -0
  381. package/dist/orchestrator/checkpoints/renderers/generator-diff.d.ts.map +1 -0
  382. package/dist/orchestrator/checkpoints/renderers/generator-diff.js +154 -0
  383. package/dist/orchestrator/checkpoints/renderers/generator-diff.js.map +1 -0
  384. package/dist/orchestrator/checkpoints/renderers/pipeline-summary.d.ts +15 -0
  385. package/dist/orchestrator/checkpoints/renderers/pipeline-summary.d.ts.map +1 -0
  386. package/dist/orchestrator/checkpoints/renderers/pipeline-summary.js +59 -0
  387. package/dist/orchestrator/checkpoints/renderers/pipeline-summary.js.map +1 -0
  388. package/dist/orchestrator/checkpoints/renderers/plan.d.ts +15 -0
  389. package/dist/orchestrator/checkpoints/renderers/plan.d.ts.map +1 -0
  390. package/dist/orchestrator/checkpoints/renderers/plan.js +34 -0
  391. package/dist/orchestrator/checkpoints/renderers/plan.js.map +1 -0
  392. package/dist/orchestrator/checkpoints/renderers/registry.d.ts +43 -0
  393. package/dist/orchestrator/checkpoints/renderers/registry.d.ts.map +1 -0
  394. package/dist/orchestrator/checkpoints/renderers/registry.js +83 -0
  395. package/dist/orchestrator/checkpoints/renderers/registry.js.map +1 -0
  396. package/dist/orchestrator/checkpoints/renderers/research.d.ts +15 -0
  397. package/dist/orchestrator/checkpoints/renderers/research.d.ts.map +1 -0
  398. package/dist/orchestrator/checkpoints/renderers/research.js +39 -0
  399. package/dist/orchestrator/checkpoints/renderers/research.js.map +1 -0
  400. package/dist/orchestrator/checkpoints/renderers/sprint-contract.d.ts +20 -0
  401. package/dist/orchestrator/checkpoints/renderers/sprint-contract.d.ts.map +1 -0
  402. package/dist/orchestrator/checkpoints/renderers/sprint-contract.js +57 -0
  403. package/dist/orchestrator/checkpoints/renderers/sprint-contract.js.map +1 -0
  404. package/dist/orchestrator/checkpoints/renderers/sprint-summary.d.ts +15 -0
  405. package/dist/orchestrator/checkpoints/renderers/sprint-summary.d.ts.map +1 -0
  406. package/dist/orchestrator/checkpoints/renderers/sprint-summary.js +38 -0
  407. package/dist/orchestrator/checkpoints/renderers/sprint-summary.js.map +1 -0
  408. package/dist/orchestrator/checkpoints/sites.d.ts +22 -0
  409. package/dist/orchestrator/checkpoints/sites.d.ts.map +1 -0
  410. package/dist/orchestrator/checkpoints/sites.js +57 -0
  411. package/dist/orchestrator/checkpoints/sites.js.map +1 -0
  412. package/dist/orchestrator/checkpoints/types.d.ts +51 -0
  413. package/dist/orchestrator/checkpoints/types.d.ts.map +1 -0
  414. package/dist/orchestrator/checkpoints/types.js +9 -0
  415. package/dist/orchestrator/checkpoints/types.js.map +1 -0
  416. package/dist/orchestrator/code-reviewer-agent.d.ts +50 -0
  417. package/dist/orchestrator/code-reviewer-agent.d.ts.map +1 -0
  418. package/dist/orchestrator/code-reviewer-agent.js +283 -0
  419. package/dist/orchestrator/code-reviewer-agent.js.map +1 -0
  420. package/dist/orchestrator/context-handoff.d.ts +484 -224
  421. package/dist/orchestrator/context-handoff.d.ts.map +1 -1
  422. package/dist/orchestrator/context-handoff.js +32 -12
  423. package/dist/orchestrator/context-handoff.js.map +1 -1
  424. package/dist/orchestrator/curator-agent.d.ts.map +1 -1
  425. package/dist/orchestrator/curator-agent.js +63 -12
  426. package/dist/orchestrator/curator-agent.js.map +1 -1
  427. package/dist/orchestrator/deploy/classify.d.ts +31 -0
  428. package/dist/orchestrator/deploy/classify.d.ts.map +1 -0
  429. package/dist/orchestrator/deploy/classify.js +109 -0
  430. package/dist/orchestrator/deploy/classify.js.map +1 -0
  431. package/dist/orchestrator/deploy/execute.d.ts +45 -0
  432. package/dist/orchestrator/deploy/execute.d.ts.map +1 -0
  433. package/dist/orchestrator/deploy/execute.js +146 -0
  434. package/dist/orchestrator/deploy/execute.js.map +1 -0
  435. package/dist/orchestrator/deploy/executor.d.ts +22 -0
  436. package/dist/orchestrator/deploy/executor.d.ts.map +1 -0
  437. package/dist/orchestrator/deploy/executor.js +31 -0
  438. package/dist/orchestrator/deploy/executor.js.map +1 -0
  439. package/dist/orchestrator/deploy/index.d.ts +21 -0
  440. package/dist/orchestrator/deploy/index.d.ts.map +1 -0
  441. package/dist/orchestrator/deploy/index.js +21 -0
  442. package/dist/orchestrator/deploy/index.js.map +1 -0
  443. package/dist/orchestrator/deploy/resolve.d.ts +51 -0
  444. package/dist/orchestrator/deploy/resolve.d.ts.map +1 -0
  445. package/dist/orchestrator/deploy/resolve.js +53 -0
  446. package/dist/orchestrator/deploy/resolve.js.map +1 -0
  447. package/dist/orchestrator/deploy/spawn.d.ts +60 -0
  448. package/dist/orchestrator/deploy/spawn.d.ts.map +1 -0
  449. package/dist/orchestrator/deploy/spawn.js +62 -0
  450. package/dist/orchestrator/deploy/spawn.js.map +1 -0
  451. package/dist/orchestrator/deploy/types.d.ts +98 -0
  452. package/dist/orchestrator/deploy/types.d.ts.map +1 -0
  453. package/dist/orchestrator/deploy/types.js +39 -0
  454. package/dist/orchestrator/deploy/types.js.map +1 -0
  455. package/dist/orchestrator/evaluator-agent.d.ts.map +1 -1
  456. package/dist/orchestrator/evaluator-agent.js +23 -10
  457. package/dist/orchestrator/evaluator-agent.js.map +1 -1
  458. package/dist/orchestrator/generator-agent.d.ts.map +1 -1
  459. package/dist/orchestrator/generator-agent.js +24 -11
  460. package/dist/orchestrator/generator-agent.js.map +1 -1
  461. package/dist/orchestrator/model-resolver.d.ts.map +1 -1
  462. package/dist/orchestrator/model-resolver.js +4 -2
  463. package/dist/orchestrator/model-resolver.js.map +1 -1
  464. package/dist/orchestrator/observability/index.d.ts +12 -0
  465. package/dist/orchestrator/observability/index.d.ts.map +1 -0
  466. package/dist/orchestrator/observability/index.js +12 -0
  467. package/dist/orchestrator/observability/index.js.map +1 -0
  468. package/dist/orchestrator/observability/merge.d.ts +73 -0
  469. package/dist/orchestrator/observability/merge.d.ts.map +1 -0
  470. package/dist/orchestrator/observability/merge.js +110 -0
  471. package/dist/orchestrator/observability/merge.js.map +1 -0
  472. package/dist/orchestrator/pipeline.d.ts +28 -0
  473. package/dist/orchestrator/pipeline.d.ts.map +1 -1
  474. package/dist/orchestrator/pipeline.js +223 -30
  475. package/dist/orchestrator/pipeline.js.map +1 -1
  476. package/dist/orchestrator/planner-agent.d.ts +21 -1
  477. package/dist/orchestrator/planner-agent.d.ts.map +1 -1
  478. package/dist/orchestrator/planner-agent.js +16 -6
  479. package/dist/orchestrator/planner-agent.js.map +1 -1
  480. package/dist/orchestrator/research-agent.d.ts.map +1 -1
  481. package/dist/orchestrator/research-agent.js +46 -9
  482. package/dist/orchestrator/research-agent.js.map +1 -1
  483. package/dist/orchestrator/tools/handlers.d.ts +2 -0
  484. package/dist/orchestrator/tools/handlers.d.ts.map +1 -1
  485. package/dist/orchestrator/tools/handlers.js +1 -1
  486. package/dist/orchestrator/tools/handlers.js.map +1 -1
  487. package/dist/orchestrator/tools/index.d.ts +84 -1
  488. package/dist/orchestrator/tools/index.d.ts.map +1 -1
  489. package/dist/orchestrator/tools/index.js +164 -1
  490. package/dist/orchestrator/tools/index.js.map +1 -1
  491. package/dist/orchestrator/worktree.d.ts +18 -0
  492. package/dist/orchestrator/worktree.d.ts.map +1 -0
  493. package/dist/orchestrator/worktree.js +129 -0
  494. package/dist/orchestrator/worktree.js.map +1 -0
  495. package/dist/providers/anthropic.d.ts +8 -1
  496. package/dist/providers/anthropic.d.ts.map +1 -1
  497. package/dist/providers/anthropic.js +86 -5
  498. package/dist/providers/anthropic.js.map +1 -1
  499. package/dist/providers/factory.d.ts.map +1 -1
  500. package/dist/providers/factory.js +35 -2
  501. package/dist/providers/factory.js.map +1 -1
  502. package/dist/providers/google.d.ts.map +1 -1
  503. package/dist/providers/google.js +5 -0
  504. package/dist/providers/google.js.map +1 -1
  505. package/dist/providers/index.d.ts +1 -1
  506. package/dist/providers/index.d.ts.map +1 -1
  507. package/dist/providers/index.js.map +1 -1
  508. package/dist/providers/openai.d.ts.map +1 -1
  509. package/dist/providers/openai.js +4 -0
  510. package/dist/providers/openai.js.map +1 -1
  511. package/dist/providers/types.d.ts +25 -2
  512. package/dist/providers/types.d.ts.map +1 -1
  513. package/dist/state/approval-state.d.ts +74 -0
  514. package/dist/state/approval-state.d.ts.map +1 -0
  515. package/dist/state/approval-state.js +127 -0
  516. package/dist/state/approval-state.js.map +1 -0
  517. package/dist/state/history.d.ts.map +1 -1
  518. package/dist/state/history.js +3 -3
  519. package/dist/state/history.js.map +1 -1
  520. package/dist/state/index.d.ts +3 -0
  521. package/dist/state/index.d.ts.map +1 -1
  522. package/dist/state/index.js +4 -1
  523. package/dist/state/index.js.map +1 -1
  524. package/dist/state/plan-state.js +1 -1
  525. package/dist/state/plan-state.js.map +1 -1
  526. package/dist/state/review-state.d.ts +15 -0
  527. package/dist/state/review-state.d.ts.map +1 -0
  528. package/dist/state/review-state.js +51 -0
  529. package/dist/state/review-state.js.map +1 -0
  530. package/dist/state/run-state.d.ts +39 -0
  531. package/dist/state/run-state.d.ts.map +1 -0
  532. package/dist/state/run-state.js +101 -0
  533. package/dist/state/run-state.js.map +1 -0
  534. package/dist/state/sprint-state.d.ts +9 -2
  535. package/dist/state/sprint-state.d.ts.map +1 -1
  536. package/dist/state/sprint-state.js +25 -11
  537. package/dist/state/sprint-state.js.map +1 -1
  538. package/dist/telemetry/emit.d.ts +41 -0
  539. package/dist/telemetry/emit.d.ts.map +1 -0
  540. package/dist/telemetry/emit.js +65 -0
  541. package/dist/telemetry/emit.js.map +1 -0
  542. package/dist/utils/git.d.ts +27 -0
  543. package/dist/utils/git.d.ts.map +1 -1
  544. package/dist/utils/git.js +50 -0
  545. package/dist/utils/git.js.map +1 -1
  546. package/hooks/hooks.json +17 -1
  547. package/hooks/session-start +42 -0
  548. package/package.json +6 -2
  549. package/scripts/check-prereqs.sh +12 -0
  550. package/scripts/e2e-graph-smoke.sh +167 -0
  551. package/scripts/graph-hook.mjs +151 -0
  552. package/scripts/migrate-specs.mjs +127 -0
  553. package/scripts/run-kpi-gate.mjs +245 -0
  554. package/scripts/sync-skills.mjs +99 -0
  555. package/skills/bober.code-review/SKILL.md +186 -0
  556. package/skills/bober.debug/SKILL.md +300 -0
  557. package/skills/bober.deploy/SKILL.md +262 -0
  558. package/skills/bober.diagnose/SKILL.md +254 -0
  559. package/skills/bober.graph/SKILL.md +85 -0
  560. package/skills/bober.impact/SKILL.md +101 -0
  561. package/skills/bober.incident/SKILL.md +245 -0
  562. package/skills/bober.onboard/SKILL.md +84 -0
  563. package/skills/bober.plan/SKILL.md +51 -0
  564. package/skills/bober.plan/references/spec-schema.md +31 -4
  565. package/skills/bober.postmortem/SKILL.md +231 -0
  566. package/skills/bober.run/SKILL.md +41 -7
  567. package/skills/bober.runbook/SKILL.md +335 -0
  568. package/skills/bober.sprint/SKILL.md +6 -259
  569. package/skills/bober.using-bober/SKILL.md +133 -0
  570. package/skills/bober.verify/SKILL.md +143 -0
@@ -0,0 +1,151 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * PostToolUse hook for Edit|Write tools.
4
+ *
5
+ * Claude Code invokes this script after every Edit/Write tool call,
6
+ * passing tool metadata via stdin (JSON) per the hook contract.
7
+ *
8
+ * Contract:
9
+ * - Read bober.config.json sync; exit 0 if graph.enabled=false or graph.autoSync=false.
10
+ * - Read JSON payload from stdin (Claude Code hook protocol).
11
+ * - Extract file paths (tool_input.file_path for Edit/Write).
12
+ * - Validate each path is inside the project root (sandboxPath logic mirrored
13
+ * from src/orchestrator/tools/handlers.ts:31-45).
14
+ * - Append one JSON line to .bober/graph/.hook-queue.jsonl: {ts, tool, paths}.
15
+ * - Exit 0 in <50ms. No tokensave invocation here.
16
+ *
17
+ * Cross-platform notes:
18
+ * - Shebang is present but Windows uses the hooks.json command directly:
19
+ * "command": "node scripts/graph-hook.mjs" (NOT a bare path).
20
+ * - All path operations use node:path, no shell quoting.
21
+ * - Uses fs SYNC calls only (readFileSync, appendFileSync) so the script
22
+ * can return as soon as the event loop drains. No promises.
23
+ */
24
+
25
+ import { readFileSync, appendFileSync, mkdirSync, existsSync } from "node:fs";
26
+ import { resolve, relative, isAbsolute, dirname } from "node:path";
27
+
28
+ const PROJECT_ROOT = process.cwd();
29
+
30
+ // ── Helpers ────────────────────────────────────────────────────────
31
+
32
+ /**
33
+ * Mirror of src/orchestrator/tools/handlers.ts:31-45 sandboxPath.
34
+ * Returns null instead of throwing when the path is outside the sandbox,
35
+ * so the hook script can silently drop + log an incident rather than crash.
36
+ */
37
+ function sandboxPath(projectRoot, inputPath) {
38
+ if (typeof inputPath !== "string" || !inputPath) return null;
39
+ const abs = isAbsolute(inputPath) ? resolve(inputPath) : resolve(projectRoot, inputPath);
40
+ const rel = relative(projectRoot, abs);
41
+ if (rel.startsWith("..") || isAbsolute(rel)) return null;
42
+ return abs;
43
+ }
44
+
45
+ function readConfigSync() {
46
+ for (const candidate of ["bober.config.json", ".bober/config.json"]) {
47
+ const p = resolve(PROJECT_ROOT, candidate);
48
+ if (existsSync(p)) {
49
+ try {
50
+ return JSON.parse(readFileSync(p, "utf-8"));
51
+ } catch {
52
+ return null;
53
+ }
54
+ }
55
+ }
56
+ return null;
57
+ }
58
+
59
+ function readStdinSync() {
60
+ // Read up to 64KB from stdin synchronously via file descriptor 0.
61
+ try {
62
+ return readFileSync(0, "utf-8");
63
+ } catch {
64
+ return "";
65
+ }
66
+ }
67
+
68
+ function appendSandboxDropIncident(file) {
69
+ // Best-effort; mirrors IncidentLog.append for the "sandbox-drop" variant.
70
+ try {
71
+ const incidentsPath = resolve(PROJECT_ROOT, ".bober/graph/incidents.jsonl");
72
+ mkdirSync(dirname(incidentsPath), { recursive: true });
73
+ appendFileSync(
74
+ incidentsPath,
75
+ JSON.stringify({
76
+ ts: new Date().toISOString(),
77
+ event: "sandbox-drop",
78
+ file,
79
+ source: "graph-hook",
80
+ }) + "\n",
81
+ "utf-8",
82
+ );
83
+ } catch {
84
+ // ignore — never block the tool call
85
+ }
86
+ }
87
+
88
+ // ── Main ───────────────────────────────────────────────────────────
89
+
90
+ function main() {
91
+ const config = readConfigSync();
92
+ const graph = config?.graph;
93
+
94
+ // Early exit when graph is disabled or autoSync is off.
95
+ // The hook entry stays registered in hooks.json (per s8-c9) but does nothing.
96
+ if (!graph || graph.enabled === false) return 0;
97
+ if (graph.autoSync === false) return 0;
98
+
99
+ const raw = readStdinSync();
100
+ let payload = {};
101
+ try {
102
+ payload = raw.trim() ? JSON.parse(raw) : {};
103
+ } catch {
104
+ // Malformed payload — exit cleanly with a warning; never crash.
105
+ process.stderr.write("[graph-hook] Warning: malformed stdin payload\n");
106
+ return 0;
107
+ }
108
+
109
+ // Claude Code hook payload shape:
110
+ // { tool_name, tool_input: { file_path?, edits?[{file_path?}] }, ... }
111
+ const tool = payload.tool_name ?? "unknown";
112
+ const candidatePaths = [];
113
+ const ti = payload.tool_input ?? {};
114
+ if (typeof ti.file_path === "string") candidatePaths.push(ti.file_path);
115
+ if (Array.isArray(ti.edits)) {
116
+ for (const e of ti.edits) {
117
+ if (typeof e?.file_path === "string") candidatePaths.push(e.file_path);
118
+ }
119
+ }
120
+
121
+ // Sandbox-validate every path. Drop any path outside the project root
122
+ // with a silent incident log.
123
+ const validated = [];
124
+ for (const p of candidatePaths) {
125
+ const sb = sandboxPath(PROJECT_ROOT, p);
126
+ if (sb === null) appendSandboxDropIncident(p);
127
+ else validated.push(sb);
128
+ }
129
+ if (validated.length === 0) return 0;
130
+
131
+ // Append to IPC queue file. mkdir is defensive.
132
+ const queueFile = resolve(PROJECT_ROOT, ".bober/graph/.hook-queue.jsonl");
133
+ try {
134
+ mkdirSync(dirname(queueFile), { recursive: true });
135
+ appendFileSync(
136
+ queueFile,
137
+ JSON.stringify({
138
+ ts: new Date().toISOString(),
139
+ tool,
140
+ paths: validated,
141
+ }) + "\n",
142
+ "utf-8",
143
+ );
144
+ } catch {
145
+ // Best-effort; never block the tool call
146
+ }
147
+
148
+ return 0;
149
+ }
150
+
151
+ process.exit(main());
@@ -0,0 +1,127 @@
1
+ #!/usr/bin/env node
2
+ // One-off migration: convert legacy PlanSpec JSON files in .bober/specs/
3
+ // to the schema introduced in src/contracts/spec.ts.
4
+ //
5
+ // Idempotent: running again on already-migrated specs is a no-op.
6
+ //
7
+ // Usage: node scripts/migrate-specs.mjs
8
+
9
+ import { readdir, readFile, writeFile } from "node:fs/promises";
10
+ import { join } from "node:path";
11
+
12
+ const SPECS_DIR = ".bober/specs";
13
+
14
+ // Legacy → new priority enum
15
+ const PRIORITY_MAP = {
16
+ must: "must-have",
17
+ should: "should-have",
18
+ could: "nice-to-have",
19
+ };
20
+
21
+ // Legacy estimatedSprints → estimatedComplexity (rough heuristic)
22
+ function complexityFromSprints(n) {
23
+ if (typeof n !== "number") return undefined;
24
+ if (n <= 1) return "low";
25
+ if (n <= 3) return "medium";
26
+ return "high";
27
+ }
28
+
29
+ function migrateFeature(f) {
30
+ const featureId = f.featureId ?? f.id;
31
+ if (!featureId) {
32
+ throw new Error(
33
+ `Feature missing both featureId and id: ${JSON.stringify(f).slice(0, 100)}`,
34
+ );
35
+ }
36
+
37
+ const priority = PRIORITY_MAP[f.priority] ?? f.priority;
38
+
39
+ const out = {
40
+ featureId,
41
+ title: f.title,
42
+ description: f.description,
43
+ priority,
44
+ acceptanceCriteria: f.acceptanceCriteria ?? [],
45
+ dependencies: f.dependencies ?? [],
46
+ };
47
+
48
+ if (f.estimatedComplexity) {
49
+ out.estimatedComplexity = f.estimatedComplexity;
50
+ } else if (f.estimatedSprints !== undefined) {
51
+ const c = complexityFromSprints(f.estimatedSprints);
52
+ if (c) out.estimatedComplexity = c;
53
+ out.estimatedSprints = f.estimatedSprints;
54
+ }
55
+
56
+ return out;
57
+ }
58
+
59
+ function migrateSpec(spec) {
60
+ const mode = spec.mode ?? spec.projectType ?? "greenfield";
61
+ if (mode !== "greenfield" && mode !== "brownfield") {
62
+ throw new Error(
63
+ `Spec ${spec.specId}: mode must be greenfield|brownfield (got ${mode})`,
64
+ );
65
+ }
66
+
67
+ return {
68
+ specId: spec.specId,
69
+ version: spec.version ?? 1,
70
+ title: spec.title,
71
+ description: spec.description,
72
+ status: spec.status ?? "completed",
73
+ mode,
74
+ features: (spec.features ?? []).map(migrateFeature),
75
+ assumptions: spec.assumptions ?? [],
76
+ outOfScope: spec.outOfScope ?? [],
77
+ ambiguityScore: spec.ambiguityScore,
78
+ clarificationQuestions: spec.clarificationQuestions ?? [],
79
+ resolvedClarifications: spec.resolvedClarifications ?? [],
80
+ techStack: spec.techStack ?? [],
81
+ techNotes: spec.techNotes,
82
+ nonFunctionalRequirements:
83
+ spec.nonFunctionalRequirements ??
84
+ // legacy: convert nonFunctional string[] to richer objects
85
+ (spec.nonFunctional ?? []).map((req) => ({ requirement: req })),
86
+ constraints: spec.constraints ?? [],
87
+ sprints: spec.sprints,
88
+ metadata: spec.metadata,
89
+ createdAt: spec.createdAt,
90
+ updatedAt: new Date().toISOString(),
91
+ completedAt: spec.completedAt,
92
+ };
93
+ }
94
+
95
+ async function main() {
96
+ const entries = await readdir(SPECS_DIR);
97
+ const jsonFiles = entries.filter((f) => f.endsWith(".json")).sort();
98
+
99
+ console.log(`Migrating ${jsonFiles.length} specs...`);
100
+
101
+ for (const file of jsonFiles) {
102
+ const path = join(SPECS_DIR, file);
103
+ const content = await readFile(path, "utf-8");
104
+ const parsed = JSON.parse(content);
105
+
106
+ let migrated;
107
+ try {
108
+ migrated = migrateSpec(parsed);
109
+ } catch (err) {
110
+ console.error(`✗ ${file}: ${err.message}`);
111
+ process.exitCode = 1;
112
+ continue;
113
+ }
114
+
115
+ // Strip undefineds before serializing for cleaner JSON
116
+ const cleaned = JSON.parse(JSON.stringify(migrated));
117
+ await writeFile(path, JSON.stringify(cleaned, null, 2) + "\n", "utf-8");
118
+ console.log(`✓ ${file}`);
119
+ }
120
+
121
+ console.log("Done.");
122
+ }
123
+
124
+ main().catch((err) => {
125
+ console.error(err);
126
+ process.exit(1);
127
+ });
@@ -0,0 +1,245 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * KPI Gate (Sprint 7) — Go/No-Go for Sprints 8-10.
4
+ *
5
+ * Reads token-usage data (real or fixture), computes per-role percent
6
+ * reduction (baseline vs graph-enabled), writes a structured report to
7
+ * .bober/graph/kpi-gate-report.json, and exits:
8
+ * - 0 on pass (reduction.combined >= threshold)
9
+ * - 2 on fail
10
+ * - 1 on script error (cannot read fixtures, invalid env, etc.)
11
+ *
12
+ * Default threshold: 40. Override with env KPI_GATE_THRESHOLD.
13
+ *
14
+ * Modes:
15
+ * 1. Fixture mode (auto when --use-fixtures, KPI_FIXTURE_FILE, or any
16
+ * KPI_*_TOKENS_* env var is set):
17
+ * - Reads token data from KPI_FIXTURE_FILE (default:
18
+ * .bober/graph/token-usage.jsonl), OR
19
+ * - Reads directly from env: KPI_BASELINE_TOKENS_RESEARCHER_PHASE2,
20
+ * KPI_BASELINE_TOKENS_CURATOR, KPI_BASELINE_TOKENS_ARCHITECT,
21
+ * KPI_GATED_TOKENS_RESEARCHER_PHASE2, KPI_GATED_TOKENS_CURATOR,
22
+ * KPI_GATED_TOKENS_ARCHITECT (and the matching *_TURNS_* counts).
23
+ * 2. Real-pipeline mode (default when no fixture flags/env): TODO —
24
+ * run the benchmark contract twice via runPipeline(). Deferred to
25
+ * manual post-merge runs (per orchestrator autonomous-mode rule).
26
+ */
27
+
28
+ import { readFile, writeFile, mkdir } from "node:fs/promises";
29
+ import { resolve, dirname } from "node:path";
30
+ import { fileURLToPath } from "node:url";
31
+
32
+ const __dirname = dirname(fileURLToPath(import.meta.url));
33
+ const ROOT = resolve(__dirname, "..");
34
+
35
+ const ROLES = ["researcher-phase2", "curator", "architect"];
36
+ const DEFAULT_THRESHOLD = 40;
37
+ const DIVERGENCE_PCT = 10; // s7-c9: turn-count vs token-count divergence flag
38
+
39
+ function envInt(name, fallback) {
40
+ const v = process.env[name];
41
+ if (v === undefined) return fallback;
42
+ const n = Number(v);
43
+ if (!Number.isFinite(n)) return fallback;
44
+ return n;
45
+ }
46
+
47
+ function tokensEnvFor(prefix, role) {
48
+ // KPI_BASELINE_TOKENS_RESEARCHER_PHASE2, KPI_GATED_TOKENS_CURATOR, etc.
49
+ const upper = role.toUpperCase().replace(/-/g, "_");
50
+ return envInt(`${prefix}_${upper}`, undefined);
51
+ }
52
+
53
+ function turnsEnvFor(prefix, role) {
54
+ const upper = role.toUpperCase().replace(/-/g, "_");
55
+ return envInt(`${prefix}_TURNS_${upper}`, undefined);
56
+ }
57
+
58
+ function shouldUseFixtures(argv) {
59
+ if (argv.includes("--use-fixtures")) return true;
60
+ if (process.env.KPI_FIXTURE_FILE) return true;
61
+ for (const role of ROLES) {
62
+ if (tokensEnvFor("KPI_BASELINE_TOKENS", role) !== undefined) return true;
63
+ if (tokensEnvFor("KPI_GATED_TOKENS", role) !== undefined) return true;
64
+ }
65
+ return false;
66
+ }
67
+
68
+ async function loadFixtureRecords(filePath) {
69
+ // Read JSONL — one record per line, same shape as src/graph/token-usage.ts.
70
+ const raw = await readFile(filePath, "utf-8");
71
+ const records = [];
72
+ for (const line of raw.split("\n")) {
73
+ const t = line.trim();
74
+ if (!t) continue;
75
+ try {
76
+ records.push(JSON.parse(t));
77
+ } catch {
78
+ // Skip malformed lines (incidents.jsonl style — never throw).
79
+ }
80
+ }
81
+ return records;
82
+ }
83
+
84
+ function aggregateRecords(records) {
85
+ // Returns: { baseline: {role: {tokens, turns}}, gated: {...} }
86
+ // tokens = inputTokens + outputTokens, turns = count of records per role.
87
+ const out = { baseline: {}, gated: {} };
88
+ for (const role of ROLES) {
89
+ out.baseline[role] = { tokens: 0, turns: 0 };
90
+ out.gated[role] = { tokens: 0, turns: 0 };
91
+ }
92
+ for (const r of records) {
93
+ if (!r || typeof r !== "object") continue;
94
+ if (!ROLES.includes(r.agent)) continue;
95
+ const bucket = r.graphEnabled === true ? out.gated : out.baseline;
96
+ const slot = bucket[r.agent];
97
+ slot.tokens += (r.inputTokens ?? 0) + (r.outputTokens ?? 0);
98
+ slot.turns += 1;
99
+ }
100
+ return out;
101
+ }
102
+
103
+ function overrideWithEnv(agg) {
104
+ // Env vars take precedence over JSONL fixture for explicit pass/fail cases.
105
+ for (const role of ROLES) {
106
+ const bTok = tokensEnvFor("KPI_BASELINE_TOKENS", role);
107
+ if (bTok !== undefined) agg.baseline[role].tokens = bTok;
108
+ const gTok = tokensEnvFor("KPI_GATED_TOKENS", role);
109
+ if (gTok !== undefined) agg.gated[role].tokens = gTok;
110
+ const bTurns = turnsEnvFor("KPI_BASELINE", role);
111
+ if (bTurns !== undefined) agg.baseline[role].turns = bTurns;
112
+ const gTurns = turnsEnvFor("KPI_GATED", role);
113
+ if (gTurns !== undefined) agg.gated[role].turns = gTurns;
114
+ }
115
+ return agg;
116
+ }
117
+
118
+ function pct(baseline, gated) {
119
+ if (!Number.isFinite(baseline) || baseline <= 0) return 0;
120
+ return Number((((baseline - gated) / baseline) * 100).toFixed(2));
121
+ }
122
+
123
+ function computeReduction(agg) {
124
+ const reduction = {};
125
+ let totalBaseline = 0;
126
+ let weightedSum = 0;
127
+ for (const role of ROLES) {
128
+ const b = agg.baseline[role].tokens;
129
+ const g = agg.gated[role].tokens;
130
+ reduction[role] = pct(b, g);
131
+ totalBaseline += b;
132
+ weightedSum += (b - g);
133
+ }
134
+ reduction.combined = totalBaseline > 0
135
+ ? Number(((weightedSum / totalBaseline) * 100).toFixed(2))
136
+ : 0;
137
+ return reduction;
138
+ }
139
+
140
+ function computeTurnDelta(agg) {
141
+ const delta = {};
142
+ for (const role of ROLES) {
143
+ delta[role] = pct(agg.baseline[role].turns, agg.gated[role].turns);
144
+ }
145
+ return delta;
146
+ }
147
+
148
+ function hasDivergence(reduction, turnDelta) {
149
+ // s7-c9: if turn-delta and token-delta differ by >10 pp for any gated role,
150
+ // flag for human review.
151
+ for (const role of ROLES) {
152
+ if (Math.abs(reduction[role] - turnDelta[role]) > DIVERGENCE_PCT) return true;
153
+ }
154
+ return false;
155
+ }
156
+
157
+ function buildRecommendations(report) {
158
+ const lines = [];
159
+ if (report.gatePass) return lines;
160
+ const arch = ".bober/architecture/arch-20260524-port-code-review-graph-architecture.md";
161
+ lines.push(`Combined reduction ${report.reduction.combined}% is below threshold ${report.threshold}%.`);
162
+ lines.push(`Review per-role deltas: researcher-phase2=${report.reduction["researcher-phase2"]}%, curator=${report.reduction.curator}%, architect=${report.reduction.architect}%.`);
163
+ lines.push(`Open questions on budget tuning: see ${arch} (preflight-budgets section).`);
164
+ lines.push(`Consider: (a) raising per-role token budgets, (b) tightening QUERY_BATCHES, (c) adding graph_review_context calls in agent prompts.`);
165
+ return lines;
166
+ }
167
+
168
+ async function main() {
169
+ const argv = process.argv.slice(2);
170
+ const threshold = envInt("KPI_GATE_THRESHOLD", DEFAULT_THRESHOLD);
171
+
172
+ let agg;
173
+ if (shouldUseFixtures(argv)) {
174
+ const fixturePath = process.env.KPI_FIXTURE_FILE
175
+ ?? resolve(ROOT, ".bober/graph/token-usage.jsonl");
176
+ let records = [];
177
+ try {
178
+ records = await loadFixtureRecords(fixturePath);
179
+ } catch (err) {
180
+ // Missing fixture file is OK when env overrides will fill the values.
181
+ if (err && err.code !== "ENOENT") throw err;
182
+ }
183
+ agg = aggregateRecords(records);
184
+ agg = overrideWithEnv(agg);
185
+ } else {
186
+ console.error("Real-pipeline KPI mode not implemented in this script. Use --use-fixtures or env overrides.");
187
+ console.error("TODO: invoke runPipeline twice (graphEnabled=false, then graphEnabled=true) against tests/benchmarks/curator-benchmark-contract.json.");
188
+ process.exit(1);
189
+ }
190
+
191
+ const reduction = computeReduction(agg);
192
+ const turnDelta = computeTurnDelta(agg);
193
+ const divergenceFlag = hasDivergence(reduction, turnDelta);
194
+ const gatePass = reduction.combined >= threshold;
195
+
196
+ const report = {
197
+ baseline: {
198
+ "researcher-phase2": agg.baseline["researcher-phase2"].tokens,
199
+ curator: agg.baseline.curator.tokens,
200
+ architect: agg.baseline.architect.tokens,
201
+ },
202
+ gated: {
203
+ "researcher-phase2": agg.gated["researcher-phase2"].tokens,
204
+ curator: agg.gated.curator.tokens,
205
+ architect: agg.gated.architect.tokens,
206
+ },
207
+ reduction, // includes researcher-phase2, curator, architect, combined
208
+ turnCounts: {
209
+ baseline: {
210
+ "researcher-phase2": agg.baseline["researcher-phase2"].turns,
211
+ curator: agg.baseline.curator.turns,
212
+ architect: agg.baseline.architect.turns,
213
+ },
214
+ gated: {
215
+ "researcher-phase2": agg.gated["researcher-phase2"].turns,
216
+ curator: agg.gated.curator.turns,
217
+ architect: agg.gated.architect.turns,
218
+ },
219
+ },
220
+ turnCountDelta: turnDelta,
221
+ divergenceFlag,
222
+ gatePass,
223
+ threshold,
224
+ timestamp: new Date().toISOString(),
225
+ recommendations: undefined, // filled below
226
+ };
227
+ report.recommendations = buildRecommendations(report);
228
+
229
+ const outPath = resolve(ROOT, ".bober/graph/kpi-gate-report.json");
230
+ await mkdir(dirname(outPath), { recursive: true });
231
+ await writeFile(outPath, JSON.stringify(report, null, 2) + "\n", "utf-8");
232
+
233
+ console.log(`KPI gate: ${gatePass ? "PASS" : "FAIL"} (combined=${reduction.combined}%, threshold=${threshold}%)`);
234
+ console.log(`Report: ${outPath}`);
235
+ if (divergenceFlag) {
236
+ console.warn("Warning: TURNCOUNT_DIVERGENCE — turn-count and token-count reductions diverge by >10pp on at least one role.");
237
+ }
238
+
239
+ process.exit(gatePass ? 0 : 2);
240
+ }
241
+
242
+ main().catch((err) => {
243
+ console.error("KPI gate script error:", err);
244
+ process.exit(1);
245
+ });
@@ -0,0 +1,99 @@
1
+ #!/usr/bin/env node
2
+ // Reverse-inline: take a `.claude/commands/<skill>.md` (which is SKILL.md +
3
+ // inlined references concatenated by `agent-bober init`) and split it back
4
+ // into `skills/<skill>/SKILL.md` + `skills/<skill>/references/<name>.md`.
5
+ //
6
+ // Idempotent and safe: writes only inside `skills/`. Strips trailing
7
+ // `--- + blank line + <!-- Reference: ... -->` separator that init.ts adds
8
+ // when concatenating.
9
+ //
10
+ // Usage: node scripts/sync-skills.mjs <skill-key>:<command-file> ...
11
+ // e.g.: node scripts/sync-skills.mjs bober.plan:bober-plan.md \
12
+ // bober.run:bober-run.md \
13
+ // bober.sprint:bober-sprint.md \
14
+ // bober.graph:bober-graph.md \
15
+ // bober.onboard:bober-onboard.md \
16
+ // bober.impact:bober-impact.md
17
+
18
+ import { readFile, writeFile, mkdir } from "node:fs/promises";
19
+ import { join, dirname } from "node:path";
20
+
21
+ const REF_RE = /\n+---\n+<!-- Reference: ([^>]+?) -->\n+/g;
22
+
23
+ async function syncSkill(skillKey, cmdFile) {
24
+ const localPath = join(".claude/commands", cmdFile);
25
+ const content = await readFile(localPath, "utf-8");
26
+
27
+ // Split the file at every "<!-- Reference: foo.md -->" marker, capturing
28
+ // the filename. The first segment is SKILL.md; subsequent segments are
29
+ // each named reference, in order.
30
+ const parts = [];
31
+ let lastIdx = 0;
32
+ let lastName = null;
33
+ let m;
34
+ REF_RE.lastIndex = 0;
35
+ while ((m = REF_RE.exec(content)) !== null) {
36
+ parts.push({ name: lastName, body: content.slice(lastIdx, m.index) });
37
+ lastName = m[1].trim();
38
+ lastIdx = m.index + m[0].length;
39
+ }
40
+ parts.push({ name: lastName, body: content.slice(lastIdx) });
41
+
42
+ const skillDir = join("skills", skillKey);
43
+ const refDir = join(skillDir, "references");
44
+
45
+ // Write SKILL.md (the first part, name === null)
46
+ const head = parts[0];
47
+ if (head.name !== null) {
48
+ throw new Error(`First segment of ${cmdFile} should be SKILL.md, got reference ${head.name}`);
49
+ }
50
+ // Trim trailing whitespace so SKILL.md doesn't grow with stray newlines
51
+ const headBody = head.body.replace(/\s+$/, "") + "\n";
52
+ await writeFile(join(skillDir, "SKILL.md"), headBody, "utf-8");
53
+ console.log(` ${skillKey}/SKILL.md (${headBody.split("\n").length} lines)`);
54
+
55
+ // Write references — dedupe by name (some files have duplicate refs from
56
+ // bad re-inits; the last copy wins, but we warn).
57
+ const seen = new Map();
58
+ for (const p of parts.slice(1)) {
59
+ if (!p.name) continue;
60
+ if (seen.has(p.name)) {
61
+ console.warn(` ⚠ duplicate reference ${p.name} in ${cmdFile} — last copy wins`);
62
+ }
63
+ seen.set(p.name, p.body);
64
+ }
65
+
66
+ if (seen.size > 0) {
67
+ await mkdir(refDir, { recursive: true });
68
+ for (const [name, body] of seen) {
69
+ const trimmed = body.replace(/^\s+|\s+$/g, "") + "\n";
70
+ await writeFile(join(refDir, name), trimmed, "utf-8");
71
+ console.log(` ${skillKey}/references/${name} (${trimmed.split("\n").length} lines)`);
72
+ }
73
+ }
74
+ }
75
+
76
+ async function main() {
77
+ const args = process.argv.slice(2);
78
+ if (args.length === 0) {
79
+ console.error("Usage: node scripts/sync-skills.mjs <skillKey>:<commandFile> ...");
80
+ process.exit(1);
81
+ }
82
+
83
+ for (const arg of args) {
84
+ const [skillKey, cmdFile] = arg.split(":");
85
+ if (!skillKey || !cmdFile) {
86
+ console.error(`Bad arg "${arg}" — expected <skillKey>:<commandFile>`);
87
+ process.exit(1);
88
+ }
89
+ console.log(`Syncing ${skillKey} from .claude/commands/${cmdFile}:`);
90
+ await syncSkill(skillKey, cmdFile);
91
+ }
92
+
93
+ console.log("Done.");
94
+ }
95
+
96
+ main().catch((err) => {
97
+ console.error(err);
98
+ process.exit(1);
99
+ });