agent-bober 0.17.1 → 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 (355) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/CHANGELOG.md +15 -0
  3. package/README.md +158 -5
  4. package/dist/chat/answerer.d.ts +17 -0
  5. package/dist/chat/answerer.d.ts.map +1 -0
  6. package/dist/chat/answerer.js +52 -0
  7. package/dist/chat/answerer.js.map +1 -0
  8. package/dist/chat/approval-cursor.d.ts +25 -0
  9. package/dist/chat/approval-cursor.d.ts.map +1 -0
  10. package/dist/chat/approval-cursor.js +61 -0
  11. package/dist/chat/approval-cursor.js.map +1 -0
  12. package/dist/chat/approval-reader.d.ts +11 -0
  13. package/dist/chat/approval-reader.d.ts.map +1 -0
  14. package/dist/chat/approval-reader.js +20 -0
  15. package/dist/chat/approval-reader.js.map +1 -0
  16. package/dist/chat/careful-sidecar.d.ts +15 -0
  17. package/dist/chat/careful-sidecar.d.ts.map +1 -0
  18. package/dist/chat/careful-sidecar.js +39 -0
  19. package/dist/chat/careful-sidecar.js.map +1 -0
  20. package/dist/chat/chat-session.d.ts +129 -0
  21. package/dist/chat/chat-session.d.ts.map +1 -0
  22. package/dist/chat/chat-session.js +470 -0
  23. package/dist/chat/chat-session.js.map +1 -0
  24. package/dist/chat/completion-tailer.d.ts +27 -0
  25. package/dist/chat/completion-tailer.d.ts.map +1 -0
  26. package/dist/chat/completion-tailer.js +187 -0
  27. package/dist/chat/completion-tailer.js.map +1 -0
  28. package/dist/chat/conversation-store.d.ts +22 -0
  29. package/dist/chat/conversation-store.d.ts.map +1 -0
  30. package/dist/chat/conversation-store.js +66 -0
  31. package/dist/chat/conversation-store.js.map +1 -0
  32. package/dist/chat/cursor-store.d.ts +23 -0
  33. package/dist/chat/cursor-store.d.ts.map +1 -0
  34. package/dist/chat/cursor-store.js +42 -0
  35. package/dist/chat/cursor-store.js.map +1 -0
  36. package/dist/chat/pid-sidecar.d.ts +22 -0
  37. package/dist/chat/pid-sidecar.d.ts.map +1 -0
  38. package/dist/chat/pid-sidecar.js +42 -0
  39. package/dist/chat/pid-sidecar.js.map +1 -0
  40. package/dist/chat/roster-reader.d.ts +16 -0
  41. package/dist/chat/roster-reader.d.ts.map +1 -0
  42. package/dist/chat/roster-reader.js +39 -0
  43. package/dist/chat/roster-reader.js.map +1 -0
  44. package/dist/chat/run-spawner.d.ts +71 -0
  45. package/dist/chat/run-spawner.d.ts.map +1 -0
  46. package/dist/chat/run-spawner.js +121 -0
  47. package/dist/chat/run-spawner.js.map +1 -0
  48. package/dist/chat/slash-commands.d.ts +36 -0
  49. package/dist/chat/slash-commands.d.ts.map +1 -0
  50. package/dist/chat/slash-commands.js +133 -0
  51. package/dist/chat/slash-commands.js.map +1 -0
  52. package/dist/chat/steer-cleanup.d.ts +12 -0
  53. package/dist/chat/steer-cleanup.d.ts.map +1 -0
  54. package/dist/chat/steer-cleanup.js +60 -0
  55. package/dist/chat/steer-cleanup.js.map +1 -0
  56. package/dist/chat/turn-classifier.d.ts +43 -0
  57. package/dist/chat/turn-classifier.d.ts.map +1 -0
  58. package/dist/chat/turn-classifier.js +150 -0
  59. package/dist/chat/turn-classifier.js.map +1 -0
  60. package/dist/cli/commands/blackboard.d.ts +33 -0
  61. package/dist/cli/commands/blackboard.d.ts.map +1 -0
  62. package/dist/cli/commands/blackboard.js +114 -0
  63. package/dist/cli/commands/blackboard.js.map +1 -0
  64. package/dist/cli/commands/chat.d.ts +13 -0
  65. package/dist/cli/commands/chat.d.ts.map +1 -0
  66. package/dist/cli/commands/chat.js +43 -0
  67. package/dist/cli/commands/chat.js.map +1 -0
  68. package/dist/cli/commands/evolve.d.ts +18 -0
  69. package/dist/cli/commands/evolve.d.ts.map +1 -0
  70. package/dist/cli/commands/evolve.js +72 -0
  71. package/dist/cli/commands/evolve.js.map +1 -0
  72. package/dist/cli/commands/facts.d.ts +15 -0
  73. package/dist/cli/commands/facts.d.ts.map +1 -0
  74. package/dist/cli/commands/facts.js +213 -0
  75. package/dist/cli/commands/facts.js.map +1 -0
  76. package/dist/cli/commands/medical.d.ts +24 -0
  77. package/dist/cli/commands/medical.d.ts.map +1 -0
  78. package/dist/cli/commands/medical.js +132 -0
  79. package/dist/cli/commands/medical.js.map +1 -0
  80. package/dist/cli/commands/memory.d.ts +2 -1
  81. package/dist/cli/commands/memory.d.ts.map +1 -1
  82. package/dist/cli/commands/memory.js +94 -7
  83. package/dist/cli/commands/memory.js.map +1 -1
  84. package/dist/cli/commands/plan.d.ts.map +1 -1
  85. package/dist/cli/commands/plan.js +29 -3
  86. package/dist/cli/commands/plan.js.map +1 -1
  87. package/dist/cli/commands/replay.d.ts +17 -0
  88. package/dist/cli/commands/replay.d.ts.map +1 -0
  89. package/dist/cli/commands/replay.js +261 -0
  90. package/dist/cli/commands/replay.js.map +1 -0
  91. package/dist/cli/commands/run.d.ts +9 -0
  92. package/dist/cli/commands/run.d.ts.map +1 -1
  93. package/dist/cli/commands/run.js +27 -1
  94. package/dist/cli/commands/run.js.map +1 -1
  95. package/dist/cli/commands/sprint.d.ts.map +1 -1
  96. package/dist/cli/commands/sprint.js +17 -3
  97. package/dist/cli/commands/sprint.js.map +1 -1
  98. package/dist/cli/index.js +12 -0
  99. package/dist/cli/index.js.map +1 -1
  100. package/dist/config/defaults.d.ts.map +1 -1
  101. package/dist/config/defaults.js +8 -0
  102. package/dist/config/defaults.js.map +1 -1
  103. package/dist/config/role-providers.d.ts +1 -1
  104. package/dist/config/role-providers.d.ts.map +1 -1
  105. package/dist/config/role-providers.js +6 -1
  106. package/dist/config/role-providers.js.map +1 -1
  107. package/dist/config/schema.d.ts +467 -222
  108. package/dist/config/schema.d.ts.map +1 -1
  109. package/dist/config/schema.js +25 -0
  110. package/dist/config/schema.js.map +1 -1
  111. package/dist/contracts/eval-result.d.ts +84 -84
  112. package/dist/contracts/spec.d.ts +28 -28
  113. package/dist/contracts/sprint-contract.d.ts +4 -4
  114. package/dist/fleet/critic-deep.d.ts +53 -0
  115. package/dist/fleet/critic-deep.d.ts.map +1 -0
  116. package/dist/fleet/critic-deep.js +199 -0
  117. package/dist/fleet/critic-deep.js.map +1 -0
  118. package/dist/fleet/decomposer-deep-constants.d.ts +4 -0
  119. package/dist/fleet/decomposer-deep-constants.d.ts.map +1 -0
  120. package/dist/fleet/decomposer-deep-constants.js +14 -0
  121. package/dist/fleet/decomposer-deep-constants.js.map +1 -0
  122. package/dist/fleet/decomposer-deep-types.d.ts +8 -0
  123. package/dist/fleet/decomposer-deep-types.d.ts.map +1 -0
  124. package/dist/fleet/decomposer-deep-types.js +9 -0
  125. package/dist/fleet/decomposer-deep-types.js.map +1 -0
  126. package/dist/fleet/decomposer-deep.d.ts +51 -0
  127. package/dist/fleet/decomposer-deep.d.ts.map +1 -0
  128. package/dist/fleet/decomposer-deep.js +261 -0
  129. package/dist/fleet/decomposer-deep.js.map +1 -0
  130. package/dist/fleet/decomposer.d.ts +22 -0
  131. package/dist/fleet/decomposer.d.ts.map +1 -0
  132. package/dist/fleet/decomposer.js +144 -0
  133. package/dist/fleet/decomposer.js.map +1 -0
  134. package/dist/fleet/index.d.ts +93 -0
  135. package/dist/fleet/index.d.ts.map +1 -1
  136. package/dist/fleet/index.js +230 -2
  137. package/dist/fleet/index.js.map +1 -1
  138. package/dist/fleet/manifest-write.d.ts +30 -0
  139. package/dist/fleet/manifest-write.d.ts.map +1 -0
  140. package/dist/fleet/manifest-write.js +90 -0
  141. package/dist/fleet/manifest-write.js.map +1 -0
  142. package/dist/fleet/manifest.d.ts +6 -6
  143. package/dist/fleet/shared-blackboard.d.ts +51 -0
  144. package/dist/fleet/shared-blackboard.d.ts.map +1 -0
  145. package/dist/fleet/shared-blackboard.js +79 -0
  146. package/dist/fleet/shared-blackboard.js.map +1 -0
  147. package/dist/fleet/synthesis.d.ts +16 -0
  148. package/dist/fleet/synthesis.d.ts.map +1 -0
  149. package/dist/fleet/synthesis.js +22 -0
  150. package/dist/fleet/synthesis.js.map +1 -0
  151. package/dist/fleet/tier-policy.d.ts +18 -0
  152. package/dist/fleet/tier-policy.d.ts.map +1 -0
  153. package/dist/fleet/tier-policy.js +53 -0
  154. package/dist/fleet/tier-policy.js.map +1 -0
  155. package/dist/fleet/tool-role-guard.d.ts +24 -0
  156. package/dist/fleet/tool-role-guard.d.ts.map +1 -0
  157. package/dist/fleet/tool-role-guard.js +55 -0
  158. package/dist/fleet/tool-role-guard.js.map +1 -0
  159. package/dist/incident/resolution-verify.d.ts +4 -4
  160. package/dist/incident/types.d.ts +8 -8
  161. package/dist/mcp/run-manager.d.ts +9 -1
  162. package/dist/mcp/run-manager.d.ts.map +1 -1
  163. package/dist/mcp/run-manager.js.map +1 -1
  164. package/dist/medical/adapters/apple-health.d.ts +32 -0
  165. package/dist/medical/adapters/apple-health.d.ts.map +1 -0
  166. package/dist/medical/adapters/apple-health.js +100 -0
  167. package/dist/medical/adapters/apple-health.js.map +1 -0
  168. package/dist/medical/audit.d.ts +31 -0
  169. package/dist/medical/audit.d.ts.map +1 -0
  170. package/dist/medical/audit.js +56 -0
  171. package/dist/medical/audit.js.map +1 -0
  172. package/dist/medical/consent.d.ts +37 -0
  173. package/dist/medical/consent.d.ts.map +1 -0
  174. package/dist/medical/consent.js +73 -0
  175. package/dist/medical/consent.js.map +1 -0
  176. package/dist/medical/disclaimer.d.ts +11 -0
  177. package/dist/medical/disclaimer.d.ts.map +1 -0
  178. package/dist/medical/disclaimer.js +21 -0
  179. package/dist/medical/disclaimer.js.map +1 -0
  180. package/dist/medical/egress.d.ts +30 -0
  181. package/dist/medical/egress.d.ts.map +1 -0
  182. package/dist/medical/egress.js +50 -0
  183. package/dist/medical/egress.js.map +1 -0
  184. package/dist/medical/engine.d.ts +73 -0
  185. package/dist/medical/engine.d.ts.map +1 -0
  186. package/dist/medical/engine.js +333 -0
  187. package/dist/medical/engine.js.map +1 -0
  188. package/dist/medical/guardrails.d.ts +47 -0
  189. package/dist/medical/guardrails.d.ts.map +1 -0
  190. package/dist/medical/guardrails.js +92 -0
  191. package/dist/medical/guardrails.js.map +1 -0
  192. package/dist/medical/health-store.d.ts +80 -0
  193. package/dist/medical/health-store.d.ts.map +1 -0
  194. package/dist/medical/health-store.js +204 -0
  195. package/dist/medical/health-store.js.map +1 -0
  196. package/dist/medical/inference.d.ts +22 -0
  197. package/dist/medical/inference.d.ts.map +1 -0
  198. package/dist/medical/inference.js +39 -0
  199. package/dist/medical/inference.js.map +1 -0
  200. package/dist/medical/ingestion.d.ts +33 -0
  201. package/dist/medical/ingestion.d.ts.map +1 -0
  202. package/dist/medical/ingestion.js +52 -0
  203. package/dist/medical/ingestion.js.map +1 -0
  204. package/dist/medical/numerics.d.ts +66 -0
  205. package/dist/medical/numerics.d.ts.map +1 -0
  206. package/dist/medical/numerics.js +216 -0
  207. package/dist/medical/numerics.js.map +1 -0
  208. package/dist/medical/red-flag.d.ts +42 -0
  209. package/dist/medical/red-flag.d.ts.map +1 -0
  210. package/dist/medical/red-flag.js +161 -0
  211. package/dist/medical/red-flag.js.map +1 -0
  212. package/dist/medical/refusal.d.ts +46 -0
  213. package/dist/medical/refusal.d.ts.map +1 -0
  214. package/dist/medical/refusal.js +131 -0
  215. package/dist/medical/refusal.js.map +1 -0
  216. package/dist/medical/retrieval/grounding-critic.d.ts +34 -0
  217. package/dist/medical/retrieval/grounding-critic.d.ts.map +1 -0
  218. package/dist/medical/retrieval/grounding-critic.js +153 -0
  219. package/dist/medical/retrieval/grounding-critic.js.map +1 -0
  220. package/dist/medical/retrieval/literature.d.ts +78 -0
  221. package/dist/medical/retrieval/literature.d.ts.map +1 -0
  222. package/dist/medical/retrieval/literature.js +292 -0
  223. package/dist/medical/retrieval/literature.js.map +1 -0
  224. package/dist/medical/retrieval/medline-source.d.ts +72 -0
  225. package/dist/medical/retrieval/medline-source.d.ts.map +1 -0
  226. package/dist/medical/retrieval/medline-source.js +120 -0
  227. package/dist/medical/retrieval/medline-source.js.map +1 -0
  228. package/dist/medical/team.d.ts +15 -0
  229. package/dist/medical/team.d.ts.map +1 -0
  230. package/dist/medical/team.js +44 -0
  231. package/dist/medical/team.js.map +1 -0
  232. package/dist/medical/types.d.ts +175 -0
  233. package/dist/medical/types.d.ts.map +1 -0
  234. package/dist/medical/types.js +8 -0
  235. package/dist/medical/types.js.map +1 -0
  236. package/dist/medical/whoop/whoop-client.d.ts +114 -0
  237. package/dist/medical/whoop/whoop-client.d.ts.map +1 -0
  238. package/dist/medical/whoop/whoop-client.js +226 -0
  239. package/dist/medical/whoop/whoop-client.js.map +1 -0
  240. package/dist/medical/whoop/whoop-sync.d.ts +25 -0
  241. package/dist/medical/whoop/whoop-sync.d.ts.map +1 -0
  242. package/dist/medical/whoop/whoop-sync.js +97 -0
  243. package/dist/medical/whoop/whoop-sync.js.map +1 -0
  244. package/dist/medical/whoop/whoop-token.d.ts +44 -0
  245. package/dist/medical/whoop/whoop-token.d.ts.map +1 -0
  246. package/dist/medical/whoop/whoop-token.js +66 -0
  247. package/dist/medical/whoop/whoop-token.js.map +1 -0
  248. package/dist/orchestrator/context-handoff.d.ts +60 -60
  249. package/dist/orchestrator/contract-materialization.d.ts +33 -0
  250. package/dist/orchestrator/contract-materialization.d.ts.map +1 -0
  251. package/dist/orchestrator/contract-materialization.js +113 -0
  252. package/dist/orchestrator/contract-materialization.js.map +1 -0
  253. package/dist/orchestrator/memory/distill.d.ts +4 -1
  254. package/dist/orchestrator/memory/distill.d.ts.map +1 -1
  255. package/dist/orchestrator/memory/distill.js +41 -1
  256. package/dist/orchestrator/memory/distill.js.map +1 -1
  257. package/dist/orchestrator/memory/fact-detector.d.ts +61 -0
  258. package/dist/orchestrator/memory/fact-detector.d.ts.map +1 -0
  259. package/dist/orchestrator/memory/fact-detector.js +153 -0
  260. package/dist/orchestrator/memory/fact-detector.js.map +1 -0
  261. package/dist/orchestrator/memory/fact-judge.d.ts +19 -0
  262. package/dist/orchestrator/memory/fact-judge.d.ts.map +1 -0
  263. package/dist/orchestrator/memory/fact-judge.js +121 -0
  264. package/dist/orchestrator/memory/fact-judge.js.map +1 -0
  265. package/dist/orchestrator/memory/fact-retrieve.d.ts +52 -0
  266. package/dist/orchestrator/memory/fact-retrieve.d.ts.map +1 -0
  267. package/dist/orchestrator/memory/fact-retrieve.js +117 -0
  268. package/dist/orchestrator/memory/fact-retrieve.js.map +1 -0
  269. package/dist/orchestrator/memory/hygiene.d.ts +66 -0
  270. package/dist/orchestrator/memory/hygiene.d.ts.map +1 -0
  271. package/dist/orchestrator/memory/hygiene.js +153 -0
  272. package/dist/orchestrator/memory/hygiene.js.map +1 -0
  273. package/dist/orchestrator/memory/reconcile.d.ts +47 -0
  274. package/dist/orchestrator/memory/reconcile.d.ts.map +1 -0
  275. package/dist/orchestrator/memory/reconcile.js +116 -0
  276. package/dist/orchestrator/memory/reconcile.js.map +1 -0
  277. package/dist/orchestrator/memory/retrieve.d.ts +5 -3
  278. package/dist/orchestrator/memory/retrieve.d.ts.map +1 -1
  279. package/dist/orchestrator/memory/retrieve.js +9 -6
  280. package/dist/orchestrator/memory/retrieve.js.map +1 -1
  281. package/dist/orchestrator/pipeline.d.ts +19 -3
  282. package/dist/orchestrator/pipeline.d.ts.map +1 -1
  283. package/dist/orchestrator/pipeline.js +63 -52
  284. package/dist/orchestrator/pipeline.js.map +1 -1
  285. package/dist/orchestrator/planner-agent.d.ts.map +1 -1
  286. package/dist/orchestrator/planner-agent.js +16 -1
  287. package/dist/orchestrator/planner-agent.js.map +1 -1
  288. package/dist/orchestrator/selfimprove/eval-guards.d.ts +51 -0
  289. package/dist/orchestrator/selfimprove/eval-guards.d.ts.map +1 -0
  290. package/dist/orchestrator/selfimprove/eval-guards.js +120 -0
  291. package/dist/orchestrator/selfimprove/eval-guards.js.map +1 -0
  292. package/dist/orchestrator/selfimprove/gepa.d.ts +74 -0
  293. package/dist/orchestrator/selfimprove/gepa.d.ts.map +1 -0
  294. package/dist/orchestrator/selfimprove/gepa.js +227 -0
  295. package/dist/orchestrator/selfimprove/gepa.js.map +1 -0
  296. package/dist/orchestrator/selfimprove/replay-harness.d.ts +65 -0
  297. package/dist/orchestrator/selfimprove/replay-harness.d.ts.map +1 -0
  298. package/dist/orchestrator/selfimprove/replay-harness.js +134 -0
  299. package/dist/orchestrator/selfimprove/replay-harness.js.map +1 -0
  300. package/dist/orchestrator/selfimprove/replay-store.d.ts +45 -0
  301. package/dist/orchestrator/selfimprove/replay-store.d.ts.map +1 -0
  302. package/dist/orchestrator/selfimprove/replay-store.js +119 -0
  303. package/dist/orchestrator/selfimprove/replay-store.js.map +1 -0
  304. package/dist/orchestrator/selfimprove/replay-types.d.ts +32 -0
  305. package/dist/orchestrator/selfimprove/replay-types.d.ts.map +1 -0
  306. package/dist/orchestrator/selfimprove/replay-types.js +15 -0
  307. package/dist/orchestrator/selfimprove/replay-types.js.map +1 -0
  308. package/dist/orchestrator/workflow/engine.d.ts +3 -1
  309. package/dist/orchestrator/workflow/engine.d.ts.map +1 -1
  310. package/dist/orchestrator/workflow/selector.d.ts +18 -0
  311. package/dist/orchestrator/workflow/selector.d.ts.map +1 -1
  312. package/dist/orchestrator/workflow/selector.js +41 -0
  313. package/dist/orchestrator/workflow/selector.js.map +1 -1
  314. package/dist/orchestrator/workflow/ts-engine.d.ts +3 -1
  315. package/dist/orchestrator/workflow/ts-engine.d.ts.map +1 -1
  316. package/dist/orchestrator/workflow/ts-engine.js +2 -2
  317. package/dist/orchestrator/workflow/ts-engine.js.map +1 -1
  318. package/dist/orchestrator/workflow/workflow-engine.d.ts +3 -1
  319. package/dist/orchestrator/workflow/workflow-engine.d.ts.map +1 -1
  320. package/dist/orchestrator/workflow/workflow-engine.js +3 -3
  321. package/dist/orchestrator/workflow/workflow-engine.js.map +1 -1
  322. package/dist/state/facts.d.ts +110 -0
  323. package/dist/state/facts.d.ts.map +1 -0
  324. package/dist/state/facts.js +208 -0
  325. package/dist/state/facts.js.map +1 -0
  326. package/dist/state/guidance.d.ts +37 -0
  327. package/dist/state/guidance.d.ts.map +1 -0
  328. package/dist/state/guidance.js +144 -0
  329. package/dist/state/guidance.js.map +1 -0
  330. package/dist/state/history.d.ts +2 -2
  331. package/dist/state/index.d.ts +1 -1
  332. package/dist/state/index.d.ts.map +1 -1
  333. package/dist/state/index.js +1 -1
  334. package/dist/state/index.js.map +1 -1
  335. package/dist/state/memory.d.ts +43 -11
  336. package/dist/state/memory.d.ts.map +1 -1
  337. package/dist/state/memory.js +93 -15
  338. package/dist/state/memory.js.map +1 -1
  339. package/dist/state/pause.d.ts +47 -0
  340. package/dist/state/pause.d.ts.map +1 -0
  341. package/dist/state/pause.js +146 -0
  342. package/dist/state/pause.js.map +1 -0
  343. package/dist/state/sprint-state.d.ts +8 -0
  344. package/dist/state/sprint-state.d.ts.map +1 -1
  345. package/dist/state/sprint-state.js +32 -1
  346. package/dist/state/sprint-state.js.map +1 -1
  347. package/dist/teams/registry.d.ts +16 -0
  348. package/dist/teams/registry.d.ts.map +1 -0
  349. package/dist/teams/registry.js +53 -0
  350. package/dist/teams/registry.js.map +1 -0
  351. package/dist/teams/types.d.ts +25 -0
  352. package/dist/teams/types.d.ts.map +1 -0
  353. package/dist/teams/types.js +2 -0
  354. package/dist/teams/types.js.map +1 -0
  355. package/package.json +3 -1
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "bober",
3
3
  "description": "Generator-Evaluator multi-agent harness for building applications autonomously with Claude",
4
- "version": "0.17.1",
4
+ "version": "0.18.0",
5
5
  "author": { "name": "BOBER3r" },
6
6
  "homepage": "https://agentbober.com",
7
7
  "repository": "https://github.com/BOBER3r/agent-bober",
package/CHANGELOG.md CHANGED
@@ -7,6 +7,21 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.18.0] — 2026-06-23
11
+
12
+ ### Fixed
13
+
14
+ - **Standalone `plan` → `sprint` flow**: `plan` now materializes sprint contracts to `.bober/contracts/` after planning. Previously only the `run` pipeline did this, so a standalone `plan` followed by `sprint` failed with "No sprint contracts found." `plan answer` likewise materializes contracts when it resolves a spec to `ready`, and the next-step hints now correctly point to `npx agent-bober sprint`.
15
+
16
+ ### Added
17
+
18
+ - **Shared `materializeContracts` helper** (`src/orchestrator/contract-materialization.ts`) used by both `plan` and the `run` pipeline as the single source of truth for spec → contract materialization. It prefers valid embedded `spec.sprints[]` (e.g. planner-authored contracts), falling back to feature-derived generation when they are absent or invalid. Contract ids are now deterministic and zero-padded (`sprint-<specId>-NN`) so `listContracts` ordering matches execution order at ten or more sprints.
19
+ - **`run` honors embedded `spec.sprints[]`**: when the planner emits valid embedded contracts, `run` uses them and skips the per-feature precision LLM calls.
20
+
21
+ ### Changed
22
+
23
+ - **`sprint` scopes to the active spec**: contract selection is now filtered to the latest spec's `specId`, so stale contracts from other specs are not executed. `sprint` also refuses a `needs-clarification` spec (printing the open questions and the correct `plan answer` command) and gives a clearer empty-contracts message pointing at `plan` or `run`.
24
+
10
25
  ## [0.17.1] — 2026-06-13
11
26
 
12
27
  ### Added
package/README.md CHANGED
@@ -211,15 +211,27 @@ agent-bober is **provider-agnostic**. Use any LLM provider for any agent role. M
211
211
 
212
212
  ### Supported Providers
213
213
 
214
- | Provider | Shorthands | API Key |
214
+ | Provider | Shorthands | API Key (env var) |
215
215
  |----------|-----------|---------|
216
216
  | **Anthropic** (default) | `opus`, `sonnet`, `haiku` | `ANTHROPIC_API_KEY` |
217
+ | **DeepSeek** | `deepseek`, `deepseek-v4-pro`, `deepseek-v4-flash` | `DEEPSEEK_API_KEY` |
217
218
  | **OpenAI** | Any OpenAI model ID | `OPENAI_API_KEY` |
218
219
  | **Google Gemini** | `gemini-pro`, `gemini-flash` | `GOOGLE_API_KEY` or `GEMINI_API_KEY` |
219
- | **OpenAI-Compatible** | Any model (Ollama, LM Studio, Groq, DeepSeek, etc.) | Optional |
220
+ | **OpenAI-Compatible** | Any model (Ollama, LM Studio, Groq, custom endpoints) | Optional (none for local servers) |
220
221
 
221
222
  Shorthands resolve to the latest model version automatically. You can also pass any full model ID directly -- it will be sent to the provider as-is.
222
223
 
224
+ > **Which API key do I need? (read this first)**
225
+ >
226
+ > **The default is Anthropic, so `ANTHROPIC_API_KEY` on its own means every role calls Claude — nothing else.** Setting `ANTHROPIC_API_KEY` does **not** turn on DeepSeek. Provider selection is **config-driven, not key-driven**: a key is only used if a role is actually pointed at that provider.
227
+ >
228
+ > To use **DeepSeek** you need **three** things together:
229
+ > 1. `npm install openai` — the OpenAI SDK is the OpenAI-compatible client DeepSeek runs through (an optional peer dependency).
230
+ > 2. `export DEEPSEEK_API_KEY=sk-...` — get a key at <https://platform.deepseek.com>. (`ANTHROPIC_API_KEY` is **not** needed if no role uses Anthropic.)
231
+ > 3. Point one or more roles at DeepSeek in `bober.config.json` — see [DeepSeek setup (full example)](#deepseek-setup-full-example) below.
232
+ >
233
+ > DeepSeek is **not** reachable with the `--provider` CLI flag alone (that flag only swaps the provider name; DeepSeek also needs its model + endpoint) — configure it in `bober.config.json`.
234
+
223
235
  ### Capability Matrix
224
236
 
225
237
  > **This matrix applies to the standalone CLI / programmatic provider layer only** (`npx agent-bober run …`), where bober calls each provider's API directly. It does **not** apply to the **Claude Code plugin**: when you run a skill like `/bober-run` inside Claude Code, the roles are spawned as Claude Code subagents on your Claude subscription, so provider selection (including `claude-code`) does not apply. See [Claude Code Plugin](#claude-code-plugin) below.
@@ -246,6 +258,65 @@ Each `claude -p` call injects approximately **40,000 tokens of system-prompt ove
246
258
 
247
259
  See [`docs/providers.md`](docs/providers.md) for copy-paste config snippets for each provider.
248
260
 
261
+ ### DeepSeek setup (full example)
262
+
263
+ DeepSeek runs through the built-in OpenAI-compatible adapter pointed at `https://api.deepseek.com`. End-to-end:
264
+
265
+ **1. Install the OpenAI-compatible client** (one-time):
266
+
267
+ ```bash
268
+ npm install openai
269
+ ```
270
+
271
+ **2. Export your DeepSeek key** (get one at <https://platform.deepseek.com>):
272
+
273
+ ```bash
274
+ export DEEPSEEK_API_KEY=sk-...
275
+ ```
276
+
277
+ **3a. Configure roles — shorthand (simplest).** Set only the `model`; the provider (`openai-compat`) and the `https://api.deepseek.com` endpoint are inferred automatically:
278
+
279
+ ```jsonc
280
+ // bober.config.json — DeepSeek for every role
281
+ {
282
+ "planner": { "model": "deepseek-v4-pro" },
283
+ "researcher": { "model": "deepseek-v4-flash" },
284
+ "curator": { "model": "deepseek-v4-pro" },
285
+ "generator": { "model": "deepseek-v4-pro" },
286
+ "evaluator": { "model": "deepseek-v4-flash" }
287
+ }
288
+ ```
289
+
290
+ **3b. Configure roles — explicit (equivalent).** Spell out the provider and endpoint if you prefer — also the form to use for a self-hosted DeepSeek-compatible gateway:
291
+
292
+ ```jsonc
293
+ {
294
+ "generator": {
295
+ "provider": "openai-compat",
296
+ "model": "deepseek-v4-pro",
297
+ "endpoint": "https://api.deepseek.com"
298
+ }
299
+ }
300
+ ```
301
+
302
+ **4. Run:**
303
+
304
+ ```bash
305
+ agent-bober run "Build a REST API with auth and CRUD"
306
+ ```
307
+
308
+ > Use `"provider": "openai-compat"` (as in 3b), **not** `"provider": "deepseek"` — `deepseek` is a *model* shorthand, not a provider name, so `"provider": "deepseek"` is rejected as an unsupported provider.
309
+
310
+ **Mix providers** — e.g. plan on Claude (highest quality) and generate/evaluate on DeepSeek (cheaper). You then need **both** `ANTHROPIC_API_KEY` and `DEEPSEEK_API_KEY` in your environment:
311
+
312
+ ```jsonc
313
+ {
314
+ "planner": { "model": "opus" },
315
+ "generator": { "model": "deepseek-v4-pro" },
316
+ "evaluator": { "model": "deepseek-v4-flash" }
317
+ }
318
+ ```
319
+
249
320
  ### Configuration
250
321
 
251
322
  Set providers per agent role in `bober.config.json`:
@@ -437,15 +508,39 @@ The `/bober-principles` command also triggers auto-discovery when called with no
437
508
  ```bash
438
509
  npx agent-bober init [preset] # Initialize project (with provider selection)
439
510
  npx agent-bober update # Refresh .claude/ commands + agents after upgrading the package
440
- npx agent-bober plan "feature" # Run the planner
511
+ npx agent-bober plan "feature" # Run the planner (also materializes sprint contracts)
441
512
  npx agent-bober plan answer <specId> # Resolve clarification questions interactively
442
513
  npx agent-bober plan answer <specId> <questionId> "..." # Resolve a single clarification question
443
- npx agent-bober sprint # Execute next sprint
514
+ npx agent-bober sprint # Execute next sprint (consumes plan's contracts)
444
515
  npx agent-bober eval # Evaluate current sprint
445
516
  npx agent-bober run "feature" # Full autonomous loop
517
+ npx agent-bober run "feature" --team example # Full autonomous loop using the 'example' team
518
+ npx agent-bober chat # Interactive chat REPL (roster + memory aware)
519
+ npx agent-bober chat example # Interactive chat REPL using the 'example' team
446
520
  npx agent-bober mcp # Start MCP server (Cursor/Windsurf)
447
521
  ```
448
522
 
523
+ #### Chat Steer Commands (Phase 2 — mid-flight HITL)
524
+
525
+ Inside the `bober chat` REPL you can steer in-flight runs with these commands:
526
+
527
+ | Command | Description |
528
+ |---|---|
529
+ | `/careful [on\|off]` | Toggle approval gates for new runs. When ON, new runs spawn with `--approve-gates post-research,post-plan,post-sprint` and pause at each curated gate waiting for human input. |
530
+ | `/approve <checkpointId>` | Approve a pending checkpoint (e.g. `post-plan`, `post-sprint`) and resume the run. |
531
+ | `/reject <checkpointId> [feedback]` | Reject a pending checkpoint with optional feedback for the run to use on retry. |
532
+ | `/tell <runId> <text>` | Queue free-text guidance for a run — applied at the next pipeline boundary. |
533
+ | `/pause <runId>` | Soft-pause a run at the next cooperative boundary. The process stays alive. |
534
+ | `/resume <runId>` | Resume a soft-paused run. |
535
+ | `/stop <runId>` | Hard-stop a run by killing its process (contrast with `/pause` which is cooperative). |
536
+ | `/runs` | List all active and recent runs. |
537
+ | `/help` | Show the full command list. |
538
+ | `/exit` | Exit the chat session. |
539
+
540
+ **Curated gates** (triggered by `--approve-gates`): `post-research`, `post-plan`, `post-sprint`. Each gate pauses the run and surfaces a notice in the next chat turn. Use `/approve` or `/reject` to resolve.
541
+
542
+ **Limitation:** Only one careful run at a time is fully supported. Pending markers are checkpointId-keyed in a shared `.bober/approvals/` directory, so two concurrent careful runs that hit the same gate id would collide. The non-chat equivalents (`list-approvals`, `approve`, `reject`) remain available as fallback. See `docs/chat-steer.md` for the full model and the documented limitations.
543
+
449
544
  #### New Commands (Sprints 9–25)
450
545
 
451
546
  The following commands were added after the initial release. Full reference in [COMMANDS.md](./COMMANDS.md).
@@ -481,7 +576,7 @@ npx agent-bober playbook search '<symptom>' # Search by symptom
481
576
 
482
577
  #### Clarification gating
483
578
 
484
- When the planner can't fully decompose a feature without more information, it stops with `status: "needs-clarification"` instead of fabricating sprints. The CLI surfaces the open questions and you resolve them via `plan answer`. After the last question is answered the spec auto-promotes to `status: "ready"` and the next `sprint`/`run` proceeds. See the **Architecture** section for the full lifecycle.
579
+ When the planner can't fully decompose a feature without more information, it stops with `status: "needs-clarification"` instead of fabricating sprints — and writes **no** contracts. The CLI surfaces the open questions and you resolve them via `plan answer`. After the last question is answered the spec auto-promotes to `status: "ready"`, its sprint contracts are materialized into `.bober/contracts/`, and the next `sprint`/`run` proceeds. See the **Architecture** section for the full lifecycle.
485
580
 
486
581
  ### Fully Autonomous Mode (no human in the loop)
487
582
 
@@ -519,6 +614,17 @@ agent-bober init nextjs
519
614
  agent-bober run "Build a complete dashboard with auth, CRUD, and charts" --provider openai
520
615
  ```
521
616
 
617
+ For **DeepSeek**, set `DEEPSEEK_API_KEY` and point your roles at the `deepseek` model in `bober.config.json` — the `--provider` flag alone is not enough, since DeepSeek also needs its model + endpoint (see [DeepSeek setup (full example)](#deepseek-setup-full-example)):
618
+
619
+ ```bash
620
+ npm install openai
621
+ export DEEPSEEK_API_KEY=sk-...
622
+ cd your-project
623
+ agent-bober init nextjs
624
+ # in bober.config.json set "model": "deepseek-v4-pro" on the roles you want
625
+ agent-bober run "Build a complete dashboard with auth, CRUD, and charts"
626
+ ```
627
+
522
628
  ---
523
629
 
524
630
  ## Lens Panels (multi-perspective evaluation & architecture)
@@ -547,6 +653,38 @@ Leave `lenses` empty to use the full built-in set; `maxConcurrent` bounds how ma
547
653
 
548
654
  ---
549
655
 
656
+ ## Teams
657
+
658
+ agent-bober supports domain-agnostic **teams** — named configurations that route each run or chat session to a distinct set of providers, a separate memory namespace, and a chosen pipeline shape. **Adding a team is data, not code**: declare it in `bober.config.json`, no source changes required.
659
+
660
+ ```jsonc
661
+ {
662
+ "defaultTeam": "programming", // Active team when --team / chat <team> is omitted
663
+ "teams": {
664
+ "example": {
665
+ "displayName": "Example research team",
666
+ "memoryNamespace": "example", // Lessons land in .bober/memory/example/
667
+ "pipelineShape": "ts",
668
+ "providers": { "chat": "openai" }
669
+ }
670
+ }
671
+ }
672
+ ```
673
+
674
+ ```bash
675
+ npx agent-bober run "summarise research" --team example
676
+ npx agent-bober chat example
677
+ ```
678
+
679
+ The built-in **programming** team is always available (no config entry needed) and uses
680
+ the default `.bober/memory/` path and the project's configured providers.
681
+
682
+ For full documentation on the three differentiation axes (provider routing / memory
683
+ namespace / pipeline shape), the built-in programming team, and the deferred
684
+ `.bober/teams/*.json` file registry, see [docs/teams.md](./docs/teams.md).
685
+
686
+ ---
687
+
550
688
  ## Configuration
551
689
 
552
690
  All configuration lives in `bober.config.json` at your project root. The `init` command creates this file from a template, and you can customize it afterward.
@@ -662,6 +800,17 @@ All configuration lives in `bober.config.json` at your project root. The `init`
662
800
  "lint": "npm run lint",
663
801
  "dev": "npm run dev",
664
802
  "typecheck": "npx tsc --noEmit"
803
+ },
804
+
805
+ // -- Teams (NEW: adding a team is data, not code) ----
806
+ "defaultTeam": "programming", // Optional. Active team when --team / chat <team> is omitted.
807
+ "teams": { // Optional. Each entry is a team defined purely as DATA.
808
+ "example": {
809
+ "displayName": "Example research team",
810
+ "memoryNamespace": "example", // Lessons land in .bober/memory/example/
811
+ "pipelineShape": "ts", // "ts" | "skill" | "workflow"
812
+ "providers": { "chat": "openai" } // Partial role->provider override; unset roles keep defaults
813
+ }
665
814
  }
666
815
  }
667
816
  ```
@@ -957,6 +1106,10 @@ All bober state lives in the `.bober/` directory:
957
1106
  briefings/ Sprint Briefings (curated codebase context per sprint)
958
1107
  eval-results/ Evaluation result logs
959
1108
  handoffs/ Context handoff documents
1109
+ memory/ Self-improvement memory (per-team namespaced)
1110
+ INDEX.md Distilled lessons index (planner-read)
1111
+ QUARANTINE.md Pruned/contradictory lessons (moved, never deleted)
1112
+ facts.db Bi-temporal SQLite semantic-facts store (auto-produced, planner-read)
960
1113
  progress.md Human-readable progress tracker
961
1114
  history.jsonl Machine-readable event log
962
1115
  ```
@@ -0,0 +1,17 @@
1
+ import type { LLMClient } from "../providers/types.js";
2
+ import type { TurnRecord } from "./conversation-store.js";
3
+ export declare class Answerer {
4
+ private readonly llm;
5
+ private readonly model;
6
+ constructor(llm: LLMClient, model: string);
7
+ /**
8
+ * Produce an answer to the user's input, given context.
9
+ *
10
+ * @param input - The current user message.
11
+ * @param rosterSummary - Compact string summary of active runs.
12
+ * @param memoryDistill - Compact string of lessons from .bober/memory/.
13
+ * @param recentHistory - Recent prior turns for conversation context.
14
+ */
15
+ answer(input: string, rosterSummary: string, memoryDistill: string, recentHistory: TurnRecord[]): Promise<string>;
16
+ }
17
+ //# sourceMappingURL=answerer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"answerer.d.ts","sourceRoot":"","sources":["../../src/chat/answerer.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,SAAS,EAAe,MAAM,uBAAuB,CAAC;AACpE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAI1D,qBAAa,QAAQ;IACnB,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAY;IAChC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;gBAEnB,GAAG,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM;IAKzC;;;;;;;OAOG;IACG,MAAM,CACV,KAAK,EAAE,MAAM,EACb,aAAa,EAAE,MAAM,EACrB,aAAa,EAAE,MAAM,EACrB,aAAa,EAAE,UAAU,EAAE,GAC1B,OAAO,CAAC,MAAM,CAAC;CAiCnB"}
@@ -0,0 +1,52 @@
1
+ // ── answerer.ts ──────────────────────────────────────────────────────
2
+ //
3
+ // Composes roster summary + memory distill + recent history into one
4
+ // LLMClient.chat call (no jsonObjectMode) and returns the text response.
5
+ // ── Answerer ──────────────────────────────────────────────────────────
6
+ export class Answerer {
7
+ llm;
8
+ model;
9
+ constructor(llm, model) {
10
+ this.llm = llm;
11
+ this.model = model;
12
+ }
13
+ /**
14
+ * Produce an answer to the user's input, given context.
15
+ *
16
+ * @param input - The current user message.
17
+ * @param rosterSummary - Compact string summary of active runs.
18
+ * @param memoryDistill - Compact string of lessons from .bober/memory/.
19
+ * @param recentHistory - Recent prior turns for conversation context.
20
+ */
21
+ async answer(input, rosterSummary, memoryDistill, recentHistory) {
22
+ const systemParts = [
23
+ "You are bober, an AI assistant integrated with the agent-bober engineering workflow.",
24
+ "",
25
+ "You have access to the following context:",
26
+ "",
27
+ "## Active Runs",
28
+ rosterSummary || "No runs found.",
29
+ "",
30
+ "## Project Memory (Lessons Learned)",
31
+ memoryDistill || "No lessons recorded yet.",
32
+ "",
33
+ "Answer the user's question concisely and helpfully.",
34
+ "If the user asks about runs or agents, use the Active Runs context above.",
35
+ "If the user asks about past mistakes or learnings, use the Project Memory context.",
36
+ ];
37
+ const system = systemParts.join("\n");
38
+ // Build message history from stored turns + current input
39
+ const messages = [];
40
+ for (const turn of recentHistory) {
41
+ messages.push({ role: turn.role, content: turn.content });
42
+ }
43
+ messages.push({ role: "user", content: input });
44
+ const response = await this.llm.chat({
45
+ model: this.model,
46
+ system,
47
+ messages,
48
+ });
49
+ return response.text;
50
+ }
51
+ }
52
+ //# sourceMappingURL=answerer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"answerer.js","sourceRoot":"","sources":["../../src/chat/answerer.ts"],"names":[],"mappings":"AAAA,wEAAwE;AACxE,EAAE;AACF,qEAAqE;AACrE,yEAAyE;AAKzE,yEAAyE;AAEzE,MAAM,OAAO,QAAQ;IACF,GAAG,CAAY;IACf,KAAK,CAAS;IAE/B,YAAY,GAAc,EAAE,KAAa;QACvC,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;QACf,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;IACrB,CAAC;IAED;;;;;;;OAOG;IACH,KAAK,CAAC,MAAM,CACV,KAAa,EACb,aAAqB,EACrB,aAAqB,EACrB,aAA2B;QAE3B,MAAM,WAAW,GAAa;YAC5B,sFAAsF;YACtF,EAAE;YACF,2CAA2C;YAC3C,EAAE;YACF,gBAAgB;YAChB,aAAa,IAAI,gBAAgB;YACjC,EAAE;YACF,qCAAqC;YACrC,aAAa,IAAI,0BAA0B;YAC3C,EAAE;YACF,qDAAqD;YACrD,2EAA2E;YAC3E,oFAAoF;SACrF,CAAC;QACF,MAAM,MAAM,GAAG,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAEtC,0DAA0D;QAC1D,MAAM,QAAQ,GAAkB,EAAE,CAAC;QACnC,KAAK,MAAM,IAAI,IAAI,aAAa,EAAE,CAAC;YACjC,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;QAC5D,CAAC;QACD,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;QAEhD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC;YACnC,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,MAAM;YACN,QAAQ;SACT,CAAC,CAAC;QAEH,OAAO,QAAQ,CAAC,IAAI,CAAC;IACvB,CAAC;CACF"}
@@ -0,0 +1,25 @@
1
+ import type { PendingMarker } from "../state/approval-state.js";
2
+ /**
3
+ * Stable identity key for a pending marker.
4
+ * Changes when a gate is re-requested in a later round (different requestedAt),
5
+ * but is stable while the gate remains at the same requestedAt.
6
+ */
7
+ export declare function markerKey(m: PendingMarker): string;
8
+ export declare class ApprovalCursor {
9
+ private readonly projectRoot;
10
+ private readonly sessionId;
11
+ constructor(projectRoot: string, sessionId: string);
12
+ private path;
13
+ /**
14
+ * Read the set of already-announced marker keys.
15
+ * Returns empty set on missing file or malformed JSON — never throws.
16
+ */
17
+ private readFile;
18
+ /**
19
+ * Return the subset of markers not yet announced, and atomically record
20
+ * them as announced for this session. Idempotent: calling again with
21
+ * the same markers returns [].
22
+ */
23
+ filterNew(markers: PendingMarker[]): Promise<PendingMarker[]>;
24
+ }
25
+ //# sourceMappingURL=approval-cursor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"approval-cursor.d.ts","sourceRoot":"","sources":["../../src/chat/approval-cursor.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAYhE;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,CAAC,EAAE,aAAa,GAAG,MAAM,CAElD;AAID,qBAAa,cAAc;IAEvB,OAAO,CAAC,QAAQ,CAAC,WAAW;IAC5B,OAAO,CAAC,QAAQ,CAAC,SAAS;gBADT,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM;IAGpC,OAAO,CAAC,IAAI;IASZ;;;OAGG;YACW,QAAQ;IAQtB;;;;OAIG;IACG,SAAS,CAAC,OAAO,EAAE,aAAa,EAAE,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC;CAmBpE"}
@@ -0,0 +1,61 @@
1
+ // ── approval-cursor.ts ────────────────────────────────────────────────
2
+ //
3
+ // Tracks which pending markers have already been announced in chat, by
4
+ // key `${checkpointId}@${requestedAt}`. Persists at
5
+ // .bober/chat/<sessionId>.approvals-cursor.json. Mirrors cursor-store.ts.
6
+ import { readFile, writeFile } from "node:fs/promises";
7
+ import { join } from "node:path";
8
+ import { ensureDir } from "../utils/fs.js";
9
+ const EMPTY = { announced: [] };
10
+ // ── Helpers ───────────────────────────────────────────────────────────
11
+ /**
12
+ * Stable identity key for a pending marker.
13
+ * Changes when a gate is re-requested in a later round (different requestedAt),
14
+ * but is stable while the gate remains at the same requestedAt.
15
+ */
16
+ export function markerKey(m) {
17
+ return `${m.checkpointId}@${m.requestedAt}`;
18
+ }
19
+ // ── ApprovalCursor ────────────────────────────────────────────────────
20
+ export class ApprovalCursor {
21
+ projectRoot;
22
+ sessionId;
23
+ constructor(projectRoot, sessionId) {
24
+ this.projectRoot = projectRoot;
25
+ this.sessionId = sessionId;
26
+ }
27
+ path() {
28
+ return join(this.projectRoot, ".bober", "chat", `${this.sessionId}.approvals-cursor.json`);
29
+ }
30
+ /**
31
+ * Read the set of already-announced marker keys.
32
+ * Returns empty set on missing file or malformed JSON — never throws.
33
+ */
34
+ async readFile() {
35
+ try {
36
+ return JSON.parse(await readFile(this.path(), "utf-8"));
37
+ }
38
+ catch {
39
+ return { ...EMPTY };
40
+ }
41
+ }
42
+ /**
43
+ * Return the subset of markers not yet announced, and atomically record
44
+ * them as announced for this session. Idempotent: calling again with
45
+ * the same markers returns [].
46
+ */
47
+ async filterNew(markers) {
48
+ const file = await this.readFile();
49
+ const seen = new Set(file.announced);
50
+ const fresh = markers.filter((m) => !seen.has(markerKey(m)));
51
+ if (fresh.length > 0) {
52
+ for (const m of fresh) {
53
+ seen.add(markerKey(m));
54
+ }
55
+ await ensureDir(join(this.projectRoot, ".bober", "chat"));
56
+ await writeFile(this.path(), JSON.stringify({ announced: [...seen] }, null, 2) + "\n", { encoding: "utf-8", mode: 0o600 });
57
+ }
58
+ return fresh;
59
+ }
60
+ }
61
+ //# sourceMappingURL=approval-cursor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"approval-cursor.js","sourceRoot":"","sources":["../../src/chat/approval-cursor.ts"],"names":[],"mappings":"AAAA,yEAAyE;AACzE,EAAE;AACF,uEAAuE;AACvE,oDAAoD;AACpD,0EAA0E;AAE1E,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAS3C,MAAM,KAAK,GAAkB,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC;AAE/C,yEAAyE;AAEzE;;;;GAIG;AACH,MAAM,UAAU,SAAS,CAAC,CAAgB;IACxC,OAAO,GAAG,CAAC,CAAC,YAAY,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;AAC9C,CAAC;AAED,yEAAyE;AAEzE,MAAM,OAAO,cAAc;IAEN;IACA;IAFnB,YACmB,WAAmB,EACnB,SAAiB;QADjB,gBAAW,GAAX,WAAW,CAAQ;QACnB,cAAS,GAAT,SAAS,CAAQ;IACjC,CAAC;IAEI,IAAI;QACV,OAAO,IAAI,CACT,IAAI,CAAC,WAAW,EAChB,QAAQ,EACR,MAAM,EACN,GAAG,IAAI,CAAC,SAAS,wBAAwB,CAC1C,CAAC;IACJ,CAAC;IAED;;;OAGG;IACK,KAAK,CAAC,QAAQ;QACpB,IAAI,CAAC;YACH,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,OAAO,CAAC,CAAkB,CAAC;QAC3E,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,EAAE,GAAG,KAAK,EAAE,CAAC;QACtB,CAAC;IACH,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,SAAS,CAAC,OAAwB;QACtC,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,QAAQ,EAAE,CAAC;QACnC,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACrC,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAE7D,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACrB,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;gBACtB,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;YACzB,CAAC;YACD,MAAM,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC;YAC1D,MAAM,SAAS,CACb,IAAI,CAAC,IAAI,EAAE,EACX,IAAI,CAAC,SAAS,CAAC,EAAE,SAAS,EAAE,CAAC,GAAG,IAAI,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,EACxD,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,CACnC,CAAC;QACJ,CAAC;QAED,OAAO,KAAK,CAAC;IACf,CAAC;CACF"}
@@ -0,0 +1,11 @@
1
+ import type { PendingMarker } from "../state/approval-state.js";
2
+ export declare class ApprovalReader {
3
+ private readonly projectRoot;
4
+ constructor(projectRoot: string);
5
+ /**
6
+ * Read all pending markers from .bober/approvals/*.pending.json.
7
+ * Missing dir => []; corrupt files skipped silently (delegated to listPending).
8
+ */
9
+ read(): Promise<PendingMarker[]>;
10
+ }
11
+ //# sourceMappingURL=approval-reader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"approval-reader.d.ts","sourceRoot":"","sources":["../../src/chat/approval-reader.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAIhE,qBAAa,cAAc;IACb,OAAO,CAAC,QAAQ,CAAC,WAAW;gBAAX,WAAW,EAAE,MAAM;IAEhD;;;OAGG;IACG,IAAI,IAAI,OAAO,CAAC,aAAa,EAAE,CAAC;CAGvC"}
@@ -0,0 +1,20 @@
1
+ // ── approval-reader.ts ────────────────────────────────────────────────
2
+ //
3
+ // Read-only wrapper over listPending for chat context.
4
+ // NEVER writes approval markers (Sprint 3 owns the write path).
5
+ import { listPending } from "../state/approval-state.js";
6
+ // ── ApprovalReader ────────────────────────────────────────────────────
7
+ export class ApprovalReader {
8
+ projectRoot;
9
+ constructor(projectRoot) {
10
+ this.projectRoot = projectRoot;
11
+ }
12
+ /**
13
+ * Read all pending markers from .bober/approvals/*.pending.json.
14
+ * Missing dir => []; corrupt files skipped silently (delegated to listPending).
15
+ */
16
+ async read() {
17
+ return listPending(this.projectRoot);
18
+ }
19
+ }
20
+ //# sourceMappingURL=approval-reader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"approval-reader.js","sourceRoot":"","sources":["../../src/chat/approval-reader.ts"],"names":[],"mappings":"AAAA,yEAAyE;AACzE,EAAE;AACF,uDAAuD;AACvD,gEAAgE;AAEhE,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAGzD,yEAAyE;AAEzE,MAAM,OAAO,cAAc;IACI;IAA7B,YAA6B,WAAmB;QAAnB,gBAAW,GAAX,WAAW,CAAQ;IAAG,CAAC;IAEpD;;;OAGG;IACH,KAAK,CAAC,IAAI;QACR,OAAO,WAAW,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IACvC,CAAC;CACF"}
@@ -0,0 +1,15 @@
1
+ export declare class CarefulSidecar {
2
+ private readonly projectRoot;
3
+ private readonly sessionId;
4
+ constructor(projectRoot: string, sessionId: string);
5
+ private path;
6
+ /**
7
+ * Read the careful flag. Missing/malformed file => false (autopilot). Never throws.
8
+ */
9
+ isCareful(): Promise<boolean>;
10
+ /**
11
+ * Persist the careful flag atomically.
12
+ */
13
+ setCareful(on: boolean): Promise<void>;
14
+ }
15
+ //# sourceMappingURL=careful-sidecar.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"careful-sidecar.d.ts","sourceRoot":"","sources":["../../src/chat/careful-sidecar.ts"],"names":[],"mappings":"AAYA,qBAAa,cAAc;IAEvB,OAAO,CAAC,QAAQ,CAAC,WAAW;IAC5B,OAAO,CAAC,QAAQ,CAAC,SAAS;gBADT,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM;IAGpC,OAAO,CAAC,IAAI;IAIZ;;OAEG;IACG,SAAS,IAAI,OAAO,CAAC,OAAO,CAAC;IASnC;;OAEG;IACG,UAAU,CAAC,EAAE,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;CAQ7C"}
@@ -0,0 +1,39 @@
1
+ // ── careful-sidecar.ts ─────────────────────────────────────────────────
2
+ //
3
+ // Persists the per-session "careful mode" toggle at
4
+ // .bober/chat/<sessionId>.careful.json. Default off → autopilot (Phase 1).
5
+ import { readFile, writeFile } from "node:fs/promises";
6
+ import { join } from "node:path";
7
+ import { ensureDir } from "../utils/fs.js";
8
+ // ── CarefulSidecar ────────────────────────────────────────────────────
9
+ export class CarefulSidecar {
10
+ projectRoot;
11
+ sessionId;
12
+ constructor(projectRoot, sessionId) {
13
+ this.projectRoot = projectRoot;
14
+ this.sessionId = sessionId;
15
+ }
16
+ path() {
17
+ return join(this.projectRoot, ".bober", "chat", `${this.sessionId}.careful.json`);
18
+ }
19
+ /**
20
+ * Read the careful flag. Missing/malformed file => false (autopilot). Never throws.
21
+ */
22
+ async isCareful() {
23
+ try {
24
+ const data = JSON.parse(await readFile(this.path(), "utf-8"));
25
+ return data.careful === true;
26
+ }
27
+ catch {
28
+ return false;
29
+ }
30
+ }
31
+ /**
32
+ * Persist the careful flag atomically.
33
+ */
34
+ async setCareful(on) {
35
+ await ensureDir(join(this.projectRoot, ".bober", "chat"));
36
+ await writeFile(this.path(), JSON.stringify({ careful: on }, null, 2) + "\n", { encoding: "utf-8", mode: 0o600 });
37
+ }
38
+ }
39
+ //# sourceMappingURL=careful-sidecar.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"careful-sidecar.js","sourceRoot":"","sources":["../../src/chat/careful-sidecar.ts"],"names":[],"mappings":"AAAA,0EAA0E;AAC1E,EAAE;AACF,oDAAoD;AACpD,2EAA2E;AAE3E,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAE3C,yEAAyE;AAEzE,MAAM,OAAO,cAAc;IAEN;IACA;IAFnB,YACmB,WAAmB,EACnB,SAAiB;QADjB,gBAAW,GAAX,WAAW,CAAQ;QACnB,cAAS,GAAT,SAAS,CAAQ;IACjC,CAAC;IAEI,IAAI;QACV,OAAO,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC,SAAS,eAAe,CAAC,CAAC;IACpF,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,SAAS;QACb,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,OAAO,CAAC,CAA0B,CAAC;YACvF,OAAO,IAAI,CAAC,OAAO,KAAK,IAAI,CAAC;QAC/B,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,UAAU,CAAC,EAAW;QAC1B,MAAM,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC;QAC1D,MAAM,SAAS,CACb,IAAI,CAAC,IAAI,EAAE,EACX,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,EAC/C,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,CACnC,CAAC;IACJ,CAAC;CACF"}