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
@@ -0,0 +1,129 @@
1
+ import * as readline from "node:readline";
2
+ import type { LLMClient } from "../providers/types.js";
3
+ import { RunSpawner } from "./run-spawner.js";
4
+ import { CompletionTailer } from "./completion-tailer.js";
5
+ import { ApprovalReader } from "./approval-reader.js";
6
+ export interface ChatSessionOptions {
7
+ llm: LLMClient;
8
+ projectRoot: string;
9
+ sessionId?: string;
10
+ /** Override readline interface for testing (omit to use stdin/stdout). */
11
+ rl?: readline.Interface;
12
+ /** Injected RunSpawner for testing (omit to use a real instance). */
13
+ spawner?: RunSpawner;
14
+ /** Injected clock for deterministic runId generation in tests. */
15
+ now?: () => number;
16
+ /** Injected CompletionTailer for testing (omit to use a real instance). */
17
+ tailer?: CompletionTailer;
18
+ /** Injected ApprovalReader for testing (omit to use a real instance). */
19
+ approvalReader?: ApprovalReader;
20
+ /**
21
+ * Memory namespace for the active team. Omit (or pass "") for the default
22
+ * programming team, which resolves to the current .bober/memory/ path.
23
+ * Sprint 2: threaded through buildMemoryDistill so a named team reads its own subdir.
24
+ */
25
+ memoryNamespace?: string;
26
+ }
27
+ export declare class ChatSession {
28
+ private readonly llm;
29
+ private readonly projectRoot;
30
+ private readonly sessionId;
31
+ private readonly store;
32
+ private readonly roster;
33
+ private readonly classifier;
34
+ private readonly answerer;
35
+ private readonly spawner;
36
+ private readonly tailer;
37
+ private readonly approvalReader;
38
+ private readonly approvalCursor;
39
+ private readonly nowFn;
40
+ private readonly model;
41
+ /** Memory namespace for the active team; undefined means the default .bober/memory/ path. */
42
+ private readonly memoryNamespace;
43
+ /** Phase 2: persists the per-session careful-mode toggle. */
44
+ private readonly carefulSidecar;
45
+ constructor(opts: ChatSessionOptions);
46
+ /** Generate a session-scoped runId using the injected clock. */
47
+ private nextRunId;
48
+ /**
49
+ * Handle a single turn: slash-dispatch or classify→answer→persist.
50
+ * Returns the assistant reply string, or null for /exit.
51
+ */
52
+ handleTurn(input: string): Promise<string | null>;
53
+ /**
54
+ * Stop a run by resolving it against the current disk roster, then calling
55
+ * RunSpawner.stop. Shared by /stop <runId> (deterministic slash path) and
56
+ * classifier steer:stop (natural-language path). Never reaches the LLM.
57
+ */
58
+ private handleStop;
59
+ /**
60
+ * Handle /careful [on|off].
61
+ * - "on" → set careful true, return confirmation
62
+ * - "off" → set careful false, return confirmation
63
+ * - undefined/other → report current state
64
+ */
65
+ private handleCareful;
66
+ /**
67
+ * Approve a pending checkpoint: guard with pendingExists, write the marker,
68
+ * clear the correlated RunState pending fields, and return an ack string.
69
+ * Returns a "no pending checkpoint" message and writes nothing if the pending
70
+ * file does not exist (sc-3-4).
71
+ */
72
+ private handleApprove;
73
+ /**
74
+ * Reject a pending checkpoint: guard with pendingExists, write the marker
75
+ * carrying the feedback string, clear the correlated RunState, and return ack.
76
+ * Returns a "no pending checkpoint" message and writes nothing if absent (sc-3-4).
77
+ */
78
+ private handleReject;
79
+ /**
80
+ * Queue free-text guidance for a run at the next pipeline boundary.
81
+ * Shared by /tell <runId> <text> (deterministic slash path) and
82
+ * classifier tell (natural-language path). Never reaches the LLM.
83
+ *
84
+ * Guards: unknown run (not in roster) → clear error, writes nothing.
85
+ * Path-traversal: appendGuidance validates runId via safeSegment first.
86
+ * Does NOT require careful mode; guidance can be queued for any known run.
87
+ */
88
+ private handleTell;
89
+ /**
90
+ * Soft-pause a run at the next checkpoint boundary.
91
+ *
92
+ * Distinct from handleStop: this does NOT send a kill signal — the process
93
+ * stays alive and will hold at the next cooperative-pause gate in the pipeline.
94
+ *
95
+ * Guards: run must be found in the roster with status "running".
96
+ * Side effects: writes paused.json marker + flips chat-owned RunState to
97
+ * 'paused' (with pausedAt timestamp) via writeRunState.
98
+ */
99
+ private handlePause;
100
+ /**
101
+ * Resume a soft-paused run.
102
+ *
103
+ * Clears the paused.json marker (best-effort) and flips RunState back
104
+ * to 'running' (dropping the pausedAt field). The pipeline's cooperative
105
+ * gate polls isPaused, so removing the marker allows the gate to advance.
106
+ */
107
+ private handleResume;
108
+ /**
109
+ * Clear pending fields from the RunState correlated to this checkpoint.
110
+ * Inverse of the Sprint 2 reflection block: finds the input-required RunState
111
+ * matching this checkpointId, drops the three pending fields, and sets
112
+ * status back to "running". Idempotent — no-op if no correlated state exists.
113
+ */
114
+ private clearPending;
115
+ /**
116
+ * Resolve a checkpoint id for NL approve/reject paths.
117
+ * - If an id is provided, use it directly.
118
+ * - If exactly one pending marker exists, use it.
119
+ * - If zero or multiple pending markers exist (without a named id), return
120
+ * an ambiguous result so the caller can ask the user instead of guessing.
121
+ */
122
+ private resolveCheckpoint;
123
+ /**
124
+ * Start an interactive REPL loop reading from stdin.
125
+ * Use handleTurn() directly in tests instead.
126
+ */
127
+ start(): Promise<void>;
128
+ }
129
+ //# sourceMappingURL=chat-session.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chat-session.d.ts","sourceRoot":"","sources":["../../src/chat/chat-session.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,QAAQ,MAAM,eAAe,CAAC;AAE1C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAOvD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAE9C,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAE1D,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAiBtD,MAAM,WAAW,kBAAkB;IACjC,GAAG,EAAE,SAAS,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,0EAA0E;IAC1E,EAAE,CAAC,EAAE,QAAQ,CAAC,SAAS,CAAC;IACxB,qEAAqE;IACrE,OAAO,CAAC,EAAE,UAAU,CAAC;IACrB,kEAAkE;IAClE,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,2EAA2E;IAC3E,MAAM,CAAC,EAAE,gBAAgB,CAAC;IAC1B,yEAAyE;IACzE,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC;;;;OAIG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AA+BD,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAY;IAChC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAoB;IAC1C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAe;IACtC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAiB;IAC5C,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAW;IACpC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAa;IACrC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAmB;IAC1C,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAiB;IAChD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAiB;IAChD,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAe;IAErC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAkB;IACxC,6FAA6F;IAC7F,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAqB;IACrD,6DAA6D;IAC7D,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAiB;gBAEpC,IAAI,EAAE,kBAAkB;IAyBpC,gEAAgE;IAChE,OAAO,CAAC,SAAS;IAIjB;;;OAGG;IACG,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAgKvD;;;;OAIG;YACW,UAAU;IAYxB;;;;;OAKG;YACW,aAAa;IAa3B;;;;;OAKG;YACW,aAAa;IAa3B;;;;OAIG;YACW,YAAY;IAc1B;;;;;;;;OAQG;YACW,UAAU;IAexB;;;;;;;;;OASG;YACW,WAAW;IAazB;;;;;;OAMG;YACW,YAAY;IAa1B;;;;;OAKG;YACW,YAAY;IAe1B;;;;;;OAMG;YACW,iBAAiB;IAgB/B;;;OAGG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAyC7B"}
@@ -0,0 +1,470 @@
1
+ // ── chat-session.ts ───────────────────────────────────────────────────
2
+ //
3
+ // ChatSession: the main turn loop for `bober chat`.
4
+ // Per turn: classify → answer (or slash-dispatch) → persist.
5
+ import * as readline from "node:readline";
6
+ import { loadLessonIndex, loadLesson } from "../state/memory.js";
7
+ import { ConversationStore } from "./conversation-store.js";
8
+ import { RosterReader } from "./roster-reader.js";
9
+ import { TurnClassifier } from "./turn-classifier.js";
10
+ import { Answerer } from "./answerer.js";
11
+ import { dispatch } from "./slash-commands.js";
12
+ import { RunSpawner } from "./run-spawner.js";
13
+ import { CarefulSidecar } from "./careful-sidecar.js";
14
+ import { CompletionTailer } from "./completion-tailer.js";
15
+ import { ApprovalReader } from "./approval-reader.js";
16
+ import { ApprovalCursor } from "./approval-cursor.js";
17
+ import { writeRunState } from "../state/run-state.js";
18
+ import { saveApproved, saveRejected, pendingExists, } from "../state/approval-state.js";
19
+ import { appendGuidance, hasRunDir } from "../state/guidance.js";
20
+ import { setPaused, clearPaused } from "../state/pause.js";
21
+ import { resolveApprover } from "../cli/commands/approve.js";
22
+ import { cleanupTerminalRun } from "./steer-cleanup.js";
23
+ import { seedProjectFacts } from "../orchestrator/memory/fact-detector.js";
24
+ // ── Memory distill helper ─────────────────────────────────────────────
25
+ /**
26
+ * Compose a compact memory distill string from the team's namespaced .bober/memory/ path.
27
+ * Returns empty string if no lessons are recorded.
28
+ * namespace undefined or "" reads the default .bober/memory/ path (programming team / back-compat).
29
+ */
30
+ async function buildMemoryDistill(projectRoot, namespace) {
31
+ try {
32
+ const index = await loadLessonIndex(projectRoot, { limit: 10 }, namespace);
33
+ if (index.length === 0)
34
+ return "";
35
+ const lines = ["Recent lessons learned:"];
36
+ for (const record of index) {
37
+ try {
38
+ const lesson = await loadLesson(projectRoot, record.lessonId, namespace);
39
+ lines.push(`- [${lesson.severity}] ${lesson.summary}`);
40
+ }
41
+ catch {
42
+ lines.push(`- ${record.summarySnippet}`);
43
+ }
44
+ }
45
+ return lines.join("\n");
46
+ }
47
+ catch {
48
+ return "";
49
+ }
50
+ }
51
+ // ── ChatSession ───────────────────────────────────────────────────────
52
+ export class ChatSession {
53
+ llm;
54
+ projectRoot;
55
+ sessionId;
56
+ store;
57
+ roster;
58
+ classifier;
59
+ answerer;
60
+ spawner;
61
+ tailer;
62
+ approvalReader;
63
+ approvalCursor;
64
+ nowFn;
65
+ // bober: using "opus" as default model; the CLI wires in config.chat?.model via createClient
66
+ model = "opus";
67
+ /** Memory namespace for the active team; undefined means the default .bober/memory/ path. */
68
+ memoryNamespace;
69
+ /** Phase 2: persists the per-session careful-mode toggle. */
70
+ carefulSidecar;
71
+ constructor(opts) {
72
+ this.llm = opts.llm;
73
+ this.projectRoot = opts.projectRoot;
74
+ this.sessionId = opts.sessionId ?? "default";
75
+ this.memoryNamespace = opts.memoryNamespace || undefined;
76
+ this.store = new ConversationStore(this.projectRoot, this.sessionId);
77
+ this.roster = new RosterReader(this.projectRoot);
78
+ this.classifier = new TurnClassifier(this.llm, this.model);
79
+ this.answerer = new Answerer(this.llm, this.model);
80
+ this.nowFn = opts.now ?? (() => Date.now());
81
+ this.spawner =
82
+ opts.spawner ??
83
+ new RunSpawner({
84
+ projectRoot: this.projectRoot,
85
+ sessionId: this.sessionId,
86
+ });
87
+ this.tailer =
88
+ opts.tailer ??
89
+ new CompletionTailer(this.projectRoot, this.sessionId);
90
+ this.approvalReader =
91
+ opts.approvalReader ?? new ApprovalReader(this.projectRoot);
92
+ this.approvalCursor = new ApprovalCursor(this.projectRoot, this.sessionId);
93
+ this.carefulSidecar = new CarefulSidecar(this.projectRoot, this.sessionId);
94
+ }
95
+ /** Generate a session-scoped runId using the injected clock. */
96
+ nextRunId() {
97
+ return `run-${this.nowFn()}`;
98
+ }
99
+ /**
100
+ * Handle a single turn: slash-dispatch or classify→answer→persist.
101
+ * Returns the assistant reply string, or null for /exit.
102
+ */
103
+ async handleTurn(input) {
104
+ // ── Poll for run completions (prelude — runs before slash or LLM path) ─
105
+ let completions = [];
106
+ try {
107
+ completions = await this.tailer.poll();
108
+ }
109
+ catch {
110
+ // Poll errors must never break the turn
111
+ }
112
+ // ── Cleanup hygiene for runs that just went terminal (Sprint 6) ────────
113
+ for (const c of completions) {
114
+ if (c.runId) {
115
+ try {
116
+ await cleanupTerminalRun(this.projectRoot, c.runId);
117
+ }
118
+ catch {
119
+ // best-effort — a cleanup failure must never break the turn
120
+ }
121
+ }
122
+ }
123
+ // ── Poll for pending approvals (prelude) ──────────────────────────────
124
+ let approvalNotice = "";
125
+ try {
126
+ const pending = await this.approvalReader.read();
127
+ if (pending.length > 0) {
128
+ const fresh = await this.approvalCursor.filterNew(pending);
129
+ if (fresh.length > 0) {
130
+ // Reflect correlated markers onto running RunStates (idempotent)
131
+ const states = await this.roster.read();
132
+ for (const m of fresh) {
133
+ if (m.runId) {
134
+ const state = states.find((s) => s.runId === m.runId && s.status === "running");
135
+ if (state) {
136
+ await writeRunState(this.projectRoot, {
137
+ ...state,
138
+ status: "input-required",
139
+ pendingCheckpointId: m.checkpointId,
140
+ pendingPrompt: m.prompt,
141
+ pendingSince: m.requestedAt,
142
+ });
143
+ }
144
+ }
145
+ }
146
+ // Build the notice string
147
+ const notices = fresh
148
+ .map((m) => `[run ${m.runId ?? "unknown"} waiting at ${m.checkpointId}: ${m.prompt}]`)
149
+ .join("\n");
150
+ approvalNotice = notices;
151
+ }
152
+ }
153
+ }
154
+ catch {
155
+ // Approval read errors must never break the turn
156
+ }
157
+ // ── Slash commands (deterministic, no LLM) ─────────────────────────
158
+ const slashResult = await dispatch(input, this.roster, (runId) => this.handleStop(runId), (arg) => this.handleCareful(arg), (id) => this.handleApprove(id), (id, fb) => this.handleReject(id, fb), (runId, text) => this.handleTell(runId, text), (runId) => this.handlePause(runId), (runId) => this.handleResume(runId));
159
+ if (slashResult.handled) {
160
+ if (slashResult.exit)
161
+ return null;
162
+ let output = slashResult.output ?? "";
163
+ // Weave completion notices into slash-command reply as well
164
+ if (completions.length > 0) {
165
+ const notices = completions
166
+ .map((c) => `[run ${c.runId ?? "unknown"} finished: ${c.phase}]`)
167
+ .join("\n");
168
+ output = `${notices}\n\n${output}`;
169
+ }
170
+ // Weave approval notices into slash-command reply
171
+ if (approvalNotice) {
172
+ output = `${approvalNotice}\n\n${output}`;
173
+ }
174
+ // Persist slash command turns for transparency
175
+ await this.store.append({ role: "user", content: input, ts: new Date().toISOString() });
176
+ await this.store.append({ role: "assistant", content: output, ts: new Date().toISOString() });
177
+ return output;
178
+ }
179
+ // ── LLM path: read context ────────────────────────────────────────
180
+ const [states, memoryDistill, recentHistory] = await Promise.all([
181
+ this.roster.read(),
182
+ buildMemoryDistill(this.projectRoot, this.memoryNamespace),
183
+ this.store.loadRecent(20),
184
+ ]);
185
+ const rosterSummary = this.roster.summarize(states);
186
+ // ── Classify ──────────────────────────────────────────────────────
187
+ const action = await this.classifier.classify(input);
188
+ let reply;
189
+ if (action.action === "answer") {
190
+ reply = await this.answerer.answer(input, rosterSummary, memoryDistill, recentHistory);
191
+ }
192
+ else if (action.action === "spawn") {
193
+ const runId = this.nextRunId();
194
+ const careful = await this.carefulSidecar.isCareful();
195
+ const ack = await this.spawner.spawn(action.task, runId, { careful });
196
+ reply = ack.spawnError
197
+ ? `Failed to launch run ${runId}: ${ack.spawnError}`
198
+ : `Launched run ${runId} for: ${action.task}. Use /runs to track it.`;
199
+ }
200
+ else if (action.action === "steer") {
201
+ if (action.op === "inspect") {
202
+ reply = this.roster.summarize(states);
203
+ }
204
+ else {
205
+ // op === "stop", action.runId: string
206
+ reply = await this.handleStop(action.runId);
207
+ }
208
+ }
209
+ else if (action.action === "approve" || action.action === "reject") {
210
+ const target = await this.resolveCheckpoint(action.checkpointId);
211
+ if (target.kind === "ambiguous") {
212
+ reply = target.message;
213
+ }
214
+ else if (action.action === "approve") {
215
+ reply = await this.handleApprove(target.id);
216
+ }
217
+ else {
218
+ reply = await this.handleReject(target.id, action.feedback ?? "");
219
+ }
220
+ }
221
+ else if (action.action === "tell") {
222
+ reply = await this.handleTell(action.runId, action.text);
223
+ }
224
+ else if (action.action === "pause") {
225
+ reply = await this.handlePause(action.runId);
226
+ }
227
+ else if (action.action === "resume") {
228
+ reply = await this.handleResume(action.runId);
229
+ }
230
+ else {
231
+ // Unknown action — should not happen given the classifier union
232
+ reply = `Unrecognised action. For now, try /help for available commands.`;
233
+ }
234
+ // ── Weave completion notices ───────────────────────────────────────
235
+ if (completions.length > 0) {
236
+ const notices = completions
237
+ .map((c) => `[run ${c.runId ?? "unknown"} finished: ${c.phase}]`)
238
+ .join("\n");
239
+ reply = `${notices}\n\n${reply}`;
240
+ }
241
+ // Weave approval notices into LLM reply
242
+ if (approvalNotice) {
243
+ reply = `${approvalNotice}\n\n${reply}`;
244
+ }
245
+ // ── Persist ───────────────────────────────────────────────────────
246
+ const now = new Date().toISOString();
247
+ await this.store.append({ role: "user", content: input, ts: now });
248
+ await this.store.append({ role: "assistant", content: reply, ts: now });
249
+ return reply;
250
+ }
251
+ /**
252
+ * Stop a run by resolving it against the current disk roster, then calling
253
+ * RunSpawner.stop. Shared by /stop <runId> (deterministic slash path) and
254
+ * classifier steer:stop (natural-language path). Never reaches the LLM.
255
+ */
256
+ async handleStop(runId) {
257
+ // Resolve against disk roster at stop-time (sc-4-7 — not from spawn-time memory)
258
+ const states = await this.roster.read();
259
+ const target = states.find((s) => s.runId === runId && s.status === "running");
260
+ if (!target)
261
+ return `No such running run: ${runId}`;
262
+ const result = await this.spawner.stop(runId, "Stopped via chat");
263
+ return result.killedPid !== undefined
264
+ ? `Stopped run ${runId} (killed pid ${result.killedPid}).`
265
+ : `Stopped run ${runId} (no live process found; marked aborted).`;
266
+ }
267
+ /**
268
+ * Handle /careful [on|off].
269
+ * - "on" → set careful true, return confirmation
270
+ * - "off" → set careful false, return confirmation
271
+ * - undefined/other → report current state
272
+ */
273
+ async handleCareful(arg) {
274
+ if (arg === "on") {
275
+ await this.carefulSidecar.setCareful(true);
276
+ return "Careful mode ON — new runs will pause at curated gates.";
277
+ }
278
+ else if (arg === "off") {
279
+ await this.carefulSidecar.setCareful(false);
280
+ return "Careful mode OFF — new runs will run in autopilot.";
281
+ }
282
+ else {
283
+ const current = await this.carefulSidecar.isCareful();
284
+ return `Careful mode is currently ${current ? "ON" : "OFF"}. Use /careful on or /careful off to toggle.`;
285
+ }
286
+ }
287
+ /**
288
+ * Approve a pending checkpoint: guard with pendingExists, write the marker,
289
+ * clear the correlated RunState pending fields, and return an ack string.
290
+ * Returns a "no pending checkpoint" message and writes nothing if the pending
291
+ * file does not exist (sc-3-4).
292
+ */
293
+ async handleApprove(checkpointId) {
294
+ if (!(await pendingExists(this.projectRoot, checkpointId))) {
295
+ return `No pending checkpoint found: ${checkpointId}`;
296
+ }
297
+ const marker = {
298
+ approvedAt: new Date().toISOString(),
299
+ approverId: resolveApprover(),
300
+ };
301
+ await saveApproved(this.projectRoot, checkpointId, marker);
302
+ await this.clearPending(checkpointId);
303
+ return `Approved checkpoint ${checkpointId}. The run will resume.`;
304
+ }
305
+ /**
306
+ * Reject a pending checkpoint: guard with pendingExists, write the marker
307
+ * carrying the feedback string, clear the correlated RunState, and return ack.
308
+ * Returns a "no pending checkpoint" message and writes nothing if absent (sc-3-4).
309
+ */
310
+ async handleReject(checkpointId, feedback) {
311
+ if (!(await pendingExists(this.projectRoot, checkpointId))) {
312
+ return `No pending checkpoint found: ${checkpointId}`;
313
+ }
314
+ const marker = {
315
+ rejectedAt: new Date().toISOString(),
316
+ rejecterId: resolveApprover(),
317
+ feedback,
318
+ };
319
+ await saveRejected(this.projectRoot, checkpointId, marker);
320
+ await this.clearPending(checkpointId);
321
+ return `Rejected checkpoint ${checkpointId}. Feedback sent for rework.`;
322
+ }
323
+ /**
324
+ * Queue free-text guidance for a run at the next pipeline boundary.
325
+ * Shared by /tell <runId> <text> (deterministic slash path) and
326
+ * classifier tell (natural-language path). Never reaches the LLM.
327
+ *
328
+ * Guards: unknown run (not in roster) → clear error, writes nothing.
329
+ * Path-traversal: appendGuidance validates runId via safeSegment first.
330
+ * Does NOT require careful mode; guidance can be queued for any known run.
331
+ */
332
+ async handleTell(runId, text) {
333
+ // Guard: check run exists in the roster (any status — not just running)
334
+ const exists = await hasRunDir(this.projectRoot, runId);
335
+ if (!exists) {
336
+ return `No such run: ${runId}`;
337
+ }
338
+ try {
339
+ await appendGuidance(this.projectRoot, runId, text);
340
+ }
341
+ catch (err) {
342
+ // Surface path-traversal or other appendGuidance errors clearly
343
+ return `Failed to queue guidance: ${err instanceof Error ? err.message : String(err)}`;
344
+ }
345
+ return `Queued guidance for run ${runId}.`;
346
+ }
347
+ /**
348
+ * Soft-pause a run at the next checkpoint boundary.
349
+ *
350
+ * Distinct from handleStop: this does NOT send a kill signal — the process
351
+ * stays alive and will hold at the next cooperative-pause gate in the pipeline.
352
+ *
353
+ * Guards: run must be found in the roster with status "running".
354
+ * Side effects: writes paused.json marker + flips chat-owned RunState to
355
+ * 'paused' (with pausedAt timestamp) via writeRunState.
356
+ */
357
+ async handlePause(runId) {
358
+ const states = await this.roster.read();
359
+ const target = states.find((s) => s.runId === runId && s.status === "running");
360
+ if (!target)
361
+ return `No such running run: ${runId}`;
362
+ await setPaused(this.projectRoot, runId);
363
+ await writeRunState(this.projectRoot, {
364
+ ...target,
365
+ status: "paused",
366
+ pausedAt: new Date().toISOString(),
367
+ });
368
+ return `Paused run ${runId} at the next boundary — the process stays alive (use /resume ${runId} to continue). This is NOT /stop.`;
369
+ }
370
+ /**
371
+ * Resume a soft-paused run.
372
+ *
373
+ * Clears the paused.json marker (best-effort) and flips RunState back
374
+ * to 'running' (dropping the pausedAt field). The pipeline's cooperative
375
+ * gate polls isPaused, so removing the marker allows the gate to advance.
376
+ */
377
+ async handleResume(runId) {
378
+ await clearPaused(this.projectRoot, runId);
379
+ const states = await this.roster.read();
380
+ const target = states.find((s) => s.runId === runId && s.status === "paused");
381
+ if (target) {
382
+ // Destructure out pausedAt so it is NOT serialized back to disk.
383
+ const { pausedAt, ...rest } = target;
384
+ void pausedAt;
385
+ await writeRunState(this.projectRoot, { ...rest, status: "running" });
386
+ }
387
+ return `Resumed run ${runId}.`;
388
+ }
389
+ /**
390
+ * Clear pending fields from the RunState correlated to this checkpoint.
391
+ * Inverse of the Sprint 2 reflection block: finds the input-required RunState
392
+ * matching this checkpointId, drops the three pending fields, and sets
393
+ * status back to "running". Idempotent — no-op if no correlated state exists.
394
+ */
395
+ async clearPending(checkpointId) {
396
+ const states = await this.roster.read();
397
+ const state = states.find((s) => s.status === "input-required" && s.pendingCheckpointId === checkpointId);
398
+ if (!state)
399
+ return;
400
+ // Destructure out the optional pending fields so they are NOT serialized.
401
+ const { pendingCheckpointId, pendingPrompt, pendingSince, ...rest } = state;
402
+ // Suppress unused-variable warnings — these are intentionally destructured out.
403
+ void pendingCheckpointId;
404
+ void pendingPrompt;
405
+ void pendingSince;
406
+ await writeRunState(this.projectRoot, { ...rest, status: "running" });
407
+ }
408
+ /**
409
+ * Resolve a checkpoint id for NL approve/reject paths.
410
+ * - If an id is provided, use it directly.
411
+ * - If exactly one pending marker exists, use it.
412
+ * - If zero or multiple pending markers exist (without a named id), return
413
+ * an ambiguous result so the caller can ask the user instead of guessing.
414
+ */
415
+ async resolveCheckpoint(id) {
416
+ if (id)
417
+ return { kind: "id", id };
418
+ const pending = await this.approvalReader.read();
419
+ if (pending.length === 1)
420
+ return { kind: "id", id: pending[0].checkpointId };
421
+ if (pending.length === 0) {
422
+ return { kind: "ambiguous", message: "No pending checkpoints to act on." };
423
+ }
424
+ const ids = pending.map((p) => p.checkpointId).join(", ");
425
+ return {
426
+ kind: "ambiguous",
427
+ message: `Multiple pending checkpoints — which one? ${ids}`,
428
+ };
429
+ }
430
+ /**
431
+ * Start an interactive REPL loop reading from stdin.
432
+ * Use handleTurn() directly in tests instead.
433
+ */
434
+ async start() {
435
+ const rl = readline.createInterface({
436
+ input: process.stdin,
437
+ output: process.stdout,
438
+ terminal: false,
439
+ });
440
+ process.stdout.write("bober chat — type a question, /help for commands, /exit to quit\n> ");
441
+ // ── Sprint 5: seed project facts at chat startup (best-effort) ──
442
+ // A facts failure must NEVER break chat startup.
443
+ try {
444
+ await seedProjectFacts(this.projectRoot, this.memoryNamespace);
445
+ }
446
+ catch {
447
+ // Swallow silently — facts failure must never abort chat
448
+ }
449
+ for await (const line of rl) {
450
+ const input = line.trim();
451
+ if (!input) {
452
+ process.stdout.write("> ");
453
+ continue;
454
+ }
455
+ try {
456
+ const reply = await this.handleTurn(input);
457
+ if (reply === null) {
458
+ process.stdout.write("Goodbye.\n");
459
+ rl.close();
460
+ return;
461
+ }
462
+ process.stdout.write(`${reply}\n> `);
463
+ }
464
+ catch (err) {
465
+ process.stderr.write(`Error: ${err instanceof Error ? err.message : String(err)}\n> `);
466
+ }
467
+ }
468
+ }
469
+ }
470
+ //# sourceMappingURL=chat-session.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chat-session.js","sourceRoot":"","sources":["../../src/chat/chat-session.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ export interface CompletionEvent {
2
+ runId?: string;
3
+ phase: "complete" | "failed";
4
+ completed: number;
5
+ failed: number;
6
+ durationMs: number;
7
+ timestamp: string;
8
+ }
9
+ export declare class CompletionTailer {
10
+ private readonly projectRoot;
11
+ private readonly store;
12
+ constructor(projectRoot: string, sessionId: string);
13
+ /**
14
+ * Poll .bober/history.jsonl for new pipeline-complete events since the last
15
+ * persisted byte cursor. Returns only newly-seen completions.
16
+ *
17
+ * Algorithm:
18
+ * 1. stat the file; ENOENT → return [].
19
+ * 2. If stat.size < cursor (rotation/shrink) → readFrom = 0.
20
+ * 3. Read bytes [readFrom, EOF) via Buffer slice.
21
+ * 4. Parse complete lines only (skip partial trailing line).
22
+ * 5. Filter for event === "pipeline-complete"; extract runId via marker.
23
+ * 6. Dedupe against seenRunIds; persist updated cursor + seenRunIds.
24
+ */
25
+ poll(): Promise<CompletionEvent[]>;
26
+ }
27
+ //# sourceMappingURL=completion-tailer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"completion-tailer.d.ts","sourceRoot":"","sources":["../../src/chat/completion-tailer.ts"],"names":[],"mappings":"AAqBA,MAAM,WAAW,eAAe;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,UAAU,GAAG,QAAQ,CAAC;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;CACnB;AAoED,qBAAa,gBAAgB;IAIzB,OAAO,CAAC,QAAQ,CAAC,WAAW;IAH9B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAc;gBAGjB,WAAW,EAAE,MAAM,EACpC,SAAS,EAAE,MAAM;IAKnB;;;;;;;;;;;OAWG;IACG,IAAI,IAAI,OAAO,CAAC,eAAe,EAAE,CAAC;CA0GzC"}