agent-bober 0.15.0 → 0.17.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 (301) hide show
  1. package/.claude-plugin/marketplace.json +20 -0
  2. package/.claude-plugin/plugin.json +2 -2
  3. package/CHANGELOG.md +30 -0
  4. package/README.md +127 -3
  5. package/agents/bober-architect.md +34 -0
  6. package/agents/bober-code-reviewer.md +2 -0
  7. package/agents/bober-curator.md +12 -0
  8. package/agents/bober-documenter.md +129 -0
  9. package/agents/bober-evaluator.md +46 -0
  10. package/agents/bober-generator.md +12 -0
  11. package/agents/bober-planner.md +8 -1
  12. package/dist/cli/commands/graph.js +3 -3
  13. package/dist/cli/commands/graph.js.map +1 -1
  14. package/dist/cli/commands/init.js +4 -0
  15. package/dist/cli/commands/init.js.map +1 -1
  16. package/dist/cli/commands/memory.d.ts +14 -0
  17. package/dist/cli/commands/memory.d.ts.map +1 -0
  18. package/dist/cli/commands/memory.js +132 -0
  19. package/dist/cli/commands/memory.js.map +1 -0
  20. package/dist/cli/index.js +6 -0
  21. package/dist/cli/index.js.map +1 -1
  22. package/dist/config/defaults.d.ts.map +1 -1
  23. package/dist/config/defaults.js +14 -3
  24. package/dist/config/defaults.js.map +1 -1
  25. package/dist/config/loader.d.ts.map +1 -1
  26. package/dist/config/loader.js +7 -0
  27. package/dist/config/loader.js.map +1 -1
  28. package/dist/config/role-providers.d.ts +29 -0
  29. package/dist/config/role-providers.d.ts.map +1 -0
  30. package/dist/config/role-providers.js +115 -0
  31. package/dist/config/role-providers.js.map +1 -0
  32. package/dist/config/schema.d.ts +383 -14
  33. package/dist/config/schema.d.ts.map +1 -1
  34. package/dist/config/schema.js +42 -0
  35. package/dist/config/schema.js.map +1 -1
  36. package/dist/contracts/eval-result.d.ts +112 -56
  37. package/dist/contracts/eval-result.d.ts.map +1 -1
  38. package/dist/contracts/eval-result.js +3 -0
  39. package/dist/contracts/eval-result.js.map +1 -1
  40. package/dist/contracts/sprint-contract.d.ts +30 -30
  41. package/dist/fleet/aggregator.d.ts +5 -0
  42. package/dist/fleet/aggregator.d.ts.map +1 -0
  43. package/dist/fleet/aggregator.js +39 -0
  44. package/dist/fleet/aggregator.js.map +1 -0
  45. package/dist/fleet/child-config.d.ts +12 -0
  46. package/dist/fleet/child-config.d.ts.map +1 -0
  47. package/dist/fleet/child-config.js +38 -0
  48. package/dist/fleet/child-config.js.map +1 -0
  49. package/dist/fleet/coordinator.d.ts +25 -0
  50. package/dist/fleet/coordinator.d.ts.map +1 -0
  51. package/dist/fleet/coordinator.js +40 -0
  52. package/dist/fleet/coordinator.js.map +1 -0
  53. package/dist/fleet/index.d.ts +40 -0
  54. package/dist/fleet/index.d.ts.map +1 -0
  55. package/dist/fleet/index.js +117 -0
  56. package/dist/fleet/index.js.map +1 -0
  57. package/dist/fleet/manifest.d.ts +51 -0
  58. package/dist/fleet/manifest.d.ts.map +1 -0
  59. package/dist/fleet/manifest.js +32 -0
  60. package/dist/fleet/manifest.js.map +1 -0
  61. package/dist/fleet/reporter.d.ts +32 -0
  62. package/dist/fleet/reporter.d.ts.map +1 -0
  63. package/dist/fleet/reporter.js +71 -0
  64. package/dist/fleet/reporter.js.map +1 -0
  65. package/dist/fleet/runner.d.ts +48 -0
  66. package/dist/fleet/runner.d.ts.map +1 -0
  67. package/dist/fleet/runner.js +104 -0
  68. package/dist/fleet/runner.js.map +1 -0
  69. package/dist/fleet/scaffolder.d.ts +12 -0
  70. package/dist/fleet/scaffolder.d.ts.map +1 -0
  71. package/dist/fleet/scaffolder.js +82 -0
  72. package/dist/fleet/scaffolder.js.map +1 -0
  73. package/dist/fleet/types.d.ts +21 -0
  74. package/dist/fleet/types.d.ts.map +1 -0
  75. package/dist/fleet/types.js +2 -0
  76. package/dist/fleet/types.js.map +1 -0
  77. package/dist/graph/cli.d.ts +6 -2
  78. package/dist/graph/cli.d.ts.map +1 -1
  79. package/dist/graph/cli.js +53 -12
  80. package/dist/graph/cli.js.map +1 -1
  81. package/dist/graph/pipeline-lifecycle.d.ts +9 -0
  82. package/dist/graph/pipeline-lifecycle.d.ts.map +1 -1
  83. package/dist/graph/pipeline-lifecycle.js +12 -0
  84. package/dist/graph/pipeline-lifecycle.js.map +1 -1
  85. package/dist/graph/preflight-injector.d.ts +14 -0
  86. package/dist/graph/preflight-injector.d.ts.map +1 -1
  87. package/dist/graph/preflight-injector.js +84 -4
  88. package/dist/graph/preflight-injector.js.map +1 -1
  89. package/dist/incident/types.d.ts +24 -24
  90. package/dist/mcp/tools/graph-schemas.d.ts +7 -7
  91. package/dist/mcp/tools/init.d.ts.map +1 -1
  92. package/dist/mcp/tools/init.js +2 -0
  93. package/dist/mcp/tools/init.js.map +1 -1
  94. package/dist/orchestrator/agent-loader.d.ts.map +1 -1
  95. package/dist/orchestrator/agent-loader.js +15 -1
  96. package/dist/orchestrator/agent-loader.js.map +1 -1
  97. package/dist/orchestrator/agentic-loop.d.ts +51 -0
  98. package/dist/orchestrator/agentic-loop.d.ts.map +1 -1
  99. package/dist/orchestrator/agentic-loop.js +123 -4
  100. package/dist/orchestrator/agentic-loop.js.map +1 -1
  101. package/dist/orchestrator/arch-lenses.d.ts +7 -0
  102. package/dist/orchestrator/arch-lenses.d.ts.map +1 -0
  103. package/dist/orchestrator/arch-lenses.js +22 -0
  104. package/dist/orchestrator/arch-lenses.js.map +1 -0
  105. package/dist/orchestrator/architect-agent.d.ts +16 -0
  106. package/dist/orchestrator/architect-agent.d.ts.map +1 -1
  107. package/dist/orchestrator/architect-agent.js +509 -1
  108. package/dist/orchestrator/architect-agent.js.map +1 -1
  109. package/dist/orchestrator/curator-agent.js +1 -1
  110. package/dist/orchestrator/curator-agent.js.map +1 -1
  111. package/dist/orchestrator/deploy/types.d.ts +2 -2
  112. package/dist/orchestrator/documenter-agent.d.ts +57 -0
  113. package/dist/orchestrator/documenter-agent.d.ts.map +1 -0
  114. package/dist/orchestrator/documenter-agent.js +195 -0
  115. package/dist/orchestrator/documenter-agent.js.map +1 -0
  116. package/dist/orchestrator/environment.d.ts +45 -0
  117. package/dist/orchestrator/environment.d.ts.map +1 -0
  118. package/dist/orchestrator/environment.js +151 -0
  119. package/dist/orchestrator/environment.js.map +1 -0
  120. package/dist/orchestrator/eval-lenses.d.ts +7 -0
  121. package/dist/orchestrator/eval-lenses.d.ts.map +1 -0
  122. package/dist/orchestrator/eval-lenses.js +19 -0
  123. package/dist/orchestrator/eval-lenses.js.map +1 -0
  124. package/dist/orchestrator/eval-persist.d.ts +25 -0
  125. package/dist/orchestrator/eval-persist.d.ts.map +1 -0
  126. package/dist/orchestrator/eval-persist.js +74 -0
  127. package/dist/orchestrator/eval-persist.js.map +1 -0
  128. package/dist/orchestrator/evaluator-agent.d.ts +23 -0
  129. package/dist/orchestrator/evaluator-agent.d.ts.map +1 -1
  130. package/dist/orchestrator/evaluator-agent.js +60 -3
  131. package/dist/orchestrator/evaluator-agent.js.map +1 -1
  132. package/dist/orchestrator/generator-agent.d.ts.map +1 -1
  133. package/dist/orchestrator/generator-agent.js +32 -0
  134. package/dist/orchestrator/generator-agent.js.map +1 -1
  135. package/dist/orchestrator/memory/distill.d.ts +60 -0
  136. package/dist/orchestrator/memory/distill.d.ts.map +1 -0
  137. package/dist/orchestrator/memory/distill.js +177 -0
  138. package/dist/orchestrator/memory/distill.js.map +1 -0
  139. package/dist/orchestrator/memory/eval-source.d.ts +20 -0
  140. package/dist/orchestrator/memory/eval-source.d.ts.map +1 -0
  141. package/dist/orchestrator/memory/eval-source.js +88 -0
  142. package/dist/orchestrator/memory/eval-source.js.map +1 -0
  143. package/dist/orchestrator/memory/retrieve.d.ts +45 -0
  144. package/dist/orchestrator/memory/retrieve.d.ts.map +1 -0
  145. package/dist/orchestrator/memory/retrieve.js +102 -0
  146. package/dist/orchestrator/memory/retrieve.js.map +1 -0
  147. package/dist/orchestrator/model-resolver.d.ts.map +1 -1
  148. package/dist/orchestrator/model-resolver.js +12 -0
  149. package/dist/orchestrator/model-resolver.js.map +1 -1
  150. package/dist/orchestrator/pipeline.d.ts +10 -0
  151. package/dist/orchestrator/pipeline.d.ts.map +1 -1
  152. package/dist/orchestrator/pipeline.js +111 -3
  153. package/dist/orchestrator/pipeline.js.map +1 -1
  154. package/dist/orchestrator/planner-agent.d.ts +22 -1
  155. package/dist/orchestrator/planner-agent.d.ts.map +1 -1
  156. package/dist/orchestrator/planner-agent.js +160 -4
  157. package/dist/orchestrator/planner-agent.js.map +1 -1
  158. package/dist/orchestrator/research-agent.js +2 -2
  159. package/dist/orchestrator/research-agent.js.map +1 -1
  160. package/dist/orchestrator/tools/handlers.d.ts +14 -0
  161. package/dist/orchestrator/tools/handlers.d.ts.map +1 -1
  162. package/dist/orchestrator/tools/handlers.js +29 -4
  163. package/dist/orchestrator/tools/handlers.js.map +1 -1
  164. package/dist/orchestrator/tools/schemas.js +5 -5
  165. package/dist/orchestrator/tools/schemas.js.map +1 -1
  166. package/dist/orchestrator/workflow/args-builder.d.ts +35 -0
  167. package/dist/orchestrator/workflow/args-builder.d.ts.map +1 -0
  168. package/dist/orchestrator/workflow/args-builder.js +142 -0
  169. package/dist/orchestrator/workflow/args-builder.js.map +1 -0
  170. package/dist/orchestrator/workflow/budget.d.ts +57 -0
  171. package/dist/orchestrator/workflow/budget.d.ts.map +1 -0
  172. package/dist/orchestrator/workflow/budget.js +80 -0
  173. package/dist/orchestrator/workflow/budget.js.map +1 -0
  174. package/dist/orchestrator/workflow/conformance.d.ts +27 -0
  175. package/dist/orchestrator/workflow/conformance.d.ts.map +1 -0
  176. package/dist/orchestrator/workflow/conformance.js +111 -0
  177. package/dist/orchestrator/workflow/conformance.js.map +1 -0
  178. package/dist/orchestrator/workflow/eligibility.d.ts +8 -0
  179. package/dist/orchestrator/workflow/eligibility.d.ts.map +1 -0
  180. package/dist/orchestrator/workflow/eligibility.js +10 -0
  181. package/dist/orchestrator/workflow/eligibility.js.map +1 -0
  182. package/dist/orchestrator/workflow/engine.d.ts +10 -0
  183. package/dist/orchestrator/workflow/engine.d.ts.map +1 -0
  184. package/dist/orchestrator/workflow/engine.js +2 -0
  185. package/dist/orchestrator/workflow/engine.js.map +1 -0
  186. package/dist/orchestrator/workflow/errors.d.ts +13 -0
  187. package/dist/orchestrator/workflow/errors.d.ts.map +1 -0
  188. package/dist/orchestrator/workflow/errors.js +26 -0
  189. package/dist/orchestrator/workflow/errors.js.map +1 -0
  190. package/dist/orchestrator/workflow/flusher.d.ts +19 -0
  191. package/dist/orchestrator/workflow/flusher.d.ts.map +1 -0
  192. package/dist/orchestrator/workflow/flusher.js +81 -0
  193. package/dist/orchestrator/workflow/flusher.js.map +1 -0
  194. package/dist/orchestrator/workflow/interpreter.d.ts +48 -0
  195. package/dist/orchestrator/workflow/interpreter.d.ts.map +1 -0
  196. package/dist/orchestrator/workflow/interpreter.js +92 -0
  197. package/dist/orchestrator/workflow/interpreter.js.map +1 -0
  198. package/dist/orchestrator/workflow/pure-sprint.d.ts +65 -0
  199. package/dist/orchestrator/workflow/pure-sprint.d.ts.map +1 -0
  200. package/dist/orchestrator/workflow/pure-sprint.js +82 -0
  201. package/dist/orchestrator/workflow/pure-sprint.js.map +1 -0
  202. package/dist/orchestrator/workflow/reconciler.d.ts +15 -0
  203. package/dist/orchestrator/workflow/reconciler.d.ts.map +1 -0
  204. package/dist/orchestrator/workflow/reconciler.js +65 -0
  205. package/dist/orchestrator/workflow/reconciler.js.map +1 -0
  206. package/dist/orchestrator/workflow/resume-cursor.d.ts +10 -0
  207. package/dist/orchestrator/workflow/resume-cursor.d.ts.map +1 -0
  208. package/dist/orchestrator/workflow/resume-cursor.js +25 -0
  209. package/dist/orchestrator/workflow/resume-cursor.js.map +1 -0
  210. package/dist/orchestrator/workflow/retry.d.ts +50 -0
  211. package/dist/orchestrator/workflow/retry.d.ts.map +1 -0
  212. package/dist/orchestrator/workflow/retry.js +100 -0
  213. package/dist/orchestrator/workflow/retry.js.map +1 -0
  214. package/dist/orchestrator/workflow/scheduler.d.ts +87 -0
  215. package/dist/orchestrator/workflow/scheduler.d.ts.map +1 -0
  216. package/dist/orchestrator/workflow/scheduler.js +158 -0
  217. package/dist/orchestrator/workflow/scheduler.js.map +1 -0
  218. package/dist/orchestrator/workflow/selector.d.ts +26 -0
  219. package/dist/orchestrator/workflow/selector.d.ts.map +1 -0
  220. package/dist/orchestrator/workflow/selector.js +54 -0
  221. package/dist/orchestrator/workflow/selector.js.map +1 -0
  222. package/dist/orchestrator/workflow/synthesizer.d.ts +52 -0
  223. package/dist/orchestrator/workflow/synthesizer.d.ts.map +1 -0
  224. package/dist/orchestrator/workflow/synthesizer.js +75 -0
  225. package/dist/orchestrator/workflow/synthesizer.js.map +1 -0
  226. package/dist/orchestrator/workflow/ts-engine.d.ts +13 -0
  227. package/dist/orchestrator/workflow/ts-engine.d.ts.map +1 -0
  228. package/dist/orchestrator/workflow/ts-engine.js +14 -0
  229. package/dist/orchestrator/workflow/ts-engine.js.map +1 -0
  230. package/dist/orchestrator/workflow/types.d.ts +55 -0
  231. package/dist/orchestrator/workflow/types.d.ts.map +1 -0
  232. package/dist/orchestrator/workflow/types.js +3 -0
  233. package/dist/orchestrator/workflow/types.js.map +1 -0
  234. package/dist/orchestrator/workflow/workflow-engine.d.ts +31 -0
  235. package/dist/orchestrator/workflow/workflow-engine.d.ts.map +1 -0
  236. package/dist/orchestrator/workflow/workflow-engine.js +70 -0
  237. package/dist/orchestrator/workflow/workflow-engine.js.map +1 -0
  238. package/dist/providers/anthropic.d.ts.map +1 -1
  239. package/dist/providers/anthropic.js +49 -6
  240. package/dist/providers/anthropic.js.map +1 -1
  241. package/dist/providers/claude-code.d.ts +44 -0
  242. package/dist/providers/claude-code.d.ts.map +1 -0
  243. package/dist/providers/claude-code.js +143 -0
  244. package/dist/providers/claude-code.js.map +1 -0
  245. package/dist/providers/factory.d.ts +16 -2
  246. package/dist/providers/factory.d.ts.map +1 -1
  247. package/dist/providers/factory.js +66 -12
  248. package/dist/providers/factory.js.map +1 -1
  249. package/dist/providers/google.d.ts.map +1 -1
  250. package/dist/providers/google.js +27 -3
  251. package/dist/providers/google.js.map +1 -1
  252. package/dist/providers/index.d.ts +3 -1
  253. package/dist/providers/index.d.ts.map +1 -1
  254. package/dist/providers/index.js +3 -1
  255. package/dist/providers/index.js.map +1 -1
  256. package/dist/providers/openai.d.ts.map +1 -1
  257. package/dist/providers/openai.js +24 -3
  258. package/dist/providers/openai.js.map +1 -1
  259. package/dist/providers/preflight.d.ts +22 -0
  260. package/dist/providers/preflight.d.ts.map +1 -0
  261. package/dist/providers/preflight.js +54 -0
  262. package/dist/providers/preflight.js.map +1 -0
  263. package/dist/providers/structured.d.ts +130 -0
  264. package/dist/providers/structured.d.ts.map +1 -0
  265. package/dist/providers/structured.js +205 -0
  266. package/dist/providers/structured.js.map +1 -0
  267. package/dist/providers/types.d.ts +28 -0
  268. package/dist/providers/types.d.ts.map +1 -1
  269. package/dist/state/history-rotation.d.ts +17 -0
  270. package/dist/state/history-rotation.d.ts.map +1 -0
  271. package/dist/state/history-rotation.js +84 -0
  272. package/dist/state/history-rotation.js.map +1 -0
  273. package/dist/state/history.d.ts +16 -4
  274. package/dist/state/history.d.ts.map +1 -1
  275. package/dist/state/history.js +62 -20
  276. package/dist/state/history.js.map +1 -1
  277. package/dist/state/index.d.ts +1 -1
  278. package/dist/state/index.d.ts.map +1 -1
  279. package/dist/state/index.js +1 -1
  280. package/dist/state/index.js.map +1 -1
  281. package/dist/state/memory.d.ts +60 -0
  282. package/dist/state/memory.d.ts.map +1 -0
  283. package/dist/state/memory.js +242 -0
  284. package/dist/state/memory.js.map +1 -0
  285. package/hooks/hooks.json +12 -2
  286. package/package.json +9 -5
  287. package/scripts/spike-claude-code-provider.mjs +66 -0
  288. package/scripts/spike-deepseek.mjs +63 -0
  289. package/scripts/sync-targets.json +12 -0
  290. package/scripts/update-all.mjs +255 -0
  291. package/skills/bober.architect/SKILL.md +13 -0
  292. package/skills/bober.architect/references/arch-lens-panel.md +126 -0
  293. package/skills/bober.eval/SKILL.md +9 -0
  294. package/skills/bober.eval/references/lens-panel.md +115 -0
  295. package/skills/bober.plan/SKILL.md +6 -0
  296. package/skills/bober.run/SKILL.md +23 -4
  297. package/skills/bober.run/references/lens-panel.md +115 -0
  298. package/skills/bober.sprint/SKILL.md +44 -2
  299. package/skills/bober.sprint/references/lens-panel.md +115 -0
  300. package/skills/shared/arch-lens-panel.md +126 -0
  301. package/skills/shared/lens-panel.md +115 -0
@@ -0,0 +1,81 @@
1
+ // ── RunResultFlusher ─────────────────────────────────────────────────
2
+ //
3
+ // Host-side flusher: commits a WorkflowRunResult from the JS workflow script
4
+ // to durable .bober/ state. This class is the ONLY clock source for the
5
+ // workflow engine — new Date() is called here, never in the script.
6
+ //
7
+ // Flush strategy:
8
+ // - Per-contract: update status + write contract, then updateProgress (crash-safe).
9
+ // - pendingHistory: appended ONCE after all contracts have been flushed
10
+ // (history entries are not per-contract; the list is global to the run).
11
+ // Re-flushing the same result appends the same entries again — callers
12
+ // must ensure idempotency at the orchestration layer (skip-completed cursor).
13
+ import { updateContractStatus } from "../../contracts/sprint-contract.js";
14
+ import { updateContract, loadContract, listContracts } from "../../state/sprint-state.js";
15
+ import { appendHistory, updateProgress } from "../../state/history.js";
16
+ import { ensureBoberDir, saveSpec } from "../../state/index.js";
17
+ export class RunResultFlusher {
18
+ /**
19
+ * Commit a WorkflowRunResult to durable .bober/ state.
20
+ *
21
+ * Write sequence (mirrors pipeline.ts:381-394):
22
+ * 1. For each sprint: updateContractStatus → updateContract (crash-safe per-contract).
23
+ * 2. updateProgress after each contract (cumulative list, crash-safe).
24
+ * 3. After all contracts: appendHistory for each pendingHistory entry (stamped).
25
+ * 4. Save the spec.
26
+ * 5. Return PipelineResult.
27
+ */
28
+ async flush(projectRoot, _config, result) {
29
+ const startTime = Date.now();
30
+ await ensureBoberDir(projectRoot);
31
+ const completedSprints = [];
32
+ const failedSprints = [];
33
+ // ── Per-contract loop (crash-safe: flush after each) ────────────────
34
+ for (const sprint of result.perSprint) {
35
+ const contractStatus = sprint.outcome === "passed"
36
+ ? "passed"
37
+ : sprint.outcome === "needs-rework"
38
+ ? "needs-rework"
39
+ : "failed";
40
+ // Stamp updatedAt / completedAt (host is the only clock)
41
+ const stamped = updateContractStatus(sprint.contract, contractStatus);
42
+ // Persist — atomic per file (updateContract = saveContract with same id)
43
+ await updateContract(projectRoot, stamped);
44
+ // Accumulate before updateProgress so the progress file always reflects
45
+ // all contracts flushed so far
46
+ if (contractStatus === "passed") {
47
+ completedSprints.push(stamped);
48
+ }
49
+ else {
50
+ failedSprints.push(stamped);
51
+ }
52
+ // updateProgress with cumulative list (crash-safe checkpoint after each contract)
53
+ await updateProgress(projectRoot, [...completedSprints, ...failedSprints], result.spec);
54
+ }
55
+ // ── History: append all pendingHistory entries with stamped timestamps ──
56
+ //
57
+ // Appended once after the per-contract loop. Each entry receives a fresh
58
+ // new Date().toISOString() stamp here — the script passed Omit<HistoryEntry,"timestamp">.
59
+ for (const partial of result.pendingHistory) {
60
+ await appendHistory(projectRoot, {
61
+ ...partial,
62
+ timestamp: new Date().toISOString(),
63
+ });
64
+ }
65
+ // ── Persist the spec ────────────────────────────────────────────────
66
+ await saveSpec(projectRoot, result.spec);
67
+ // ── Return PipelineResult (pipeline.ts:809-810 success formula) ─────
68
+ return {
69
+ success: failedSprints.length === 0 && completedSprints.length > 0,
70
+ spec: result.spec,
71
+ completedSprints,
72
+ failedSprints,
73
+ duration: Date.now() - startTime,
74
+ needsClarification: result.needsClarification,
75
+ };
76
+ }
77
+ }
78
+ // Re-export for test convenience (allows tests to load contracts back without
79
+ // importing sprint-state directly if they already import flusher).
80
+ export { loadContract, listContracts };
81
+ //# sourceMappingURL=flusher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flusher.js","sourceRoot":"","sources":["../../../src/orchestrator/workflow/flusher.ts"],"names":[],"mappings":"AAAA,wEAAwE;AACxE,EAAE;AACF,6EAA6E;AAC7E,wEAAwE;AACxE,oEAAoE;AACpE,EAAE;AACF,kBAAkB;AAClB,sFAAsF;AACtF,0EAA0E;AAC1E,6EAA6E;AAC7E,2EAA2E;AAC3E,kFAAkF;AAIlF,OAAO,EAAE,oBAAoB,EAAE,MAAM,oCAAoC,CAAC;AAC1E,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAC1F,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACvE,OAAO,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAIhE,MAAM,OAAO,gBAAgB;IAC3B;;;;;;;;;OASG;IACH,KAAK,CAAC,KAAK,CACT,WAAmB,EACnB,OAAoB,EACpB,MAAyB;QAEzB,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAE7B,MAAM,cAAc,CAAC,WAAW,CAAC,CAAC;QAElC,MAAM,gBAAgB,GAAqB,EAAE,CAAC;QAC9C,MAAM,aAAa,GAAqB,EAAE,CAAC;QAE3C,uEAAuE;QAEvE,KAAK,MAAM,MAAM,IAAI,MAAM,CAAC,SAAS,EAAE,CAAC;YACtC,MAAM,cAAc,GAClB,MAAM,CAAC,OAAO,KAAK,QAAQ;gBACzB,CAAC,CAAC,QAAQ;gBACV,CAAC,CAAC,MAAM,CAAC,OAAO,KAAK,cAAc;oBACjC,CAAC,CAAC,cAAc;oBAChB,CAAC,CAAC,QAAQ,CAAC;YAEjB,yDAAyD;YACzD,MAAM,OAAO,GAAG,oBAAoB,CAAC,MAAM,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAC;YAEtE,yEAAyE;YACzE,MAAM,cAAc,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;YAE3C,wEAAwE;YACxE,+BAA+B;YAC/B,IAAI,cAAc,KAAK,QAAQ,EAAE,CAAC;gBAChC,gBAAgB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YACjC,CAAC;iBAAM,CAAC;gBACN,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YAC9B,CAAC;YAED,kFAAkF;YAClF,MAAM,cAAc,CAClB,WAAW,EACX,CAAC,GAAG,gBAAgB,EAAE,GAAG,aAAa,CAAC,EACvC,MAAM,CAAC,IAAI,CACZ,CAAC;QACJ,CAAC;QAED,2EAA2E;QAC3E,EAAE;QACF,yEAAyE;QACzE,0FAA0F;QAE1F,KAAK,MAAM,OAAO,IAAI,MAAM,CAAC,cAAc,EAAE,CAAC;YAC5C,MAAM,aAAa,CAAC,WAAW,EAAE;gBAC/B,GAAG,OAAO;gBACV,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;aACpC,CAAC,CAAC;QACL,CAAC;QAED,uEAAuE;QAEvE,MAAM,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC;QAEzC,uEAAuE;QAEvE,OAAO;YACL,OAAO,EAAE,aAAa,CAAC,MAAM,KAAK,CAAC,IAAI,gBAAgB,CAAC,MAAM,GAAG,CAAC;YAClE,IAAI,EAAE,MAAM,CAAC,IAAI;YACjB,gBAAgB;YAChB,aAAa;YACb,QAAQ,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS;YAChC,kBAAkB,EAAE,MAAM,CAAC,kBAAkB;SAC9C,CAAC;IACJ,CAAC;CACF;AAED,8EAA8E;AAC9E,mEAAmE;AACnE,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,CAAC"}
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Workflow interpreter — the live body of the (currently dormant) WorkflowEngine
3
+ * invoke() seam.
4
+ *
5
+ * Reproduces the TS pipeline's plan → sprint-loop orchestration as PURE
6
+ * computation: it produces a {@link WorkflowRunResult} and writes nothing.
7
+ * `RunResultFlusher.flush()` commits the result afterward (the sole clock/commit
8
+ * source). Plan / contract-derivation / sprint-cycle are injected
9
+ * ({@link WorkflowDeps}) so the interpreter is hermetically testable; the real
10
+ * agent wiring (default deps) and the invoke() rewire + eligibility flip land in
11
+ * Sprint 5.
12
+ *
13
+ * Resume: contracts whose `sprintNumber` is in `args.resumeCursor.completed-
14
+ * SprintNumbers` are filtered out BEFORE dispatch, so the result only contains
15
+ * newly-run sprints — the flusher then appends only their history (no
16
+ * double-write on re-run).
17
+ */
18
+ import type { WorkflowArgs, WorkflowRunResult } from "./types.js";
19
+ import type { PlanSpec } from "../../contracts/spec.js";
20
+ import type { SprintContract } from "../../contracts/sprint-contract.js";
21
+ import { Scheduler } from "./scheduler.js";
22
+ import type { SprintInput, SprintOutcome } from "./pure-sprint.js";
23
+ export interface PlanResult {
24
+ spec: PlanSpec;
25
+ needsClarification: boolean;
26
+ }
27
+ export interface WorkflowDeps {
28
+ /** Produce or load the plan spec for the run. */
29
+ plan: (args: WorkflowArgs, projectRoot: string) => Promise<PlanResult>;
30
+ /** Derive sprint contracts from a spec (used when preloadedContracts is empty). */
31
+ buildContracts: (spec: PlanSpec, args: WorkflowArgs) => SprintContract[];
32
+ /** Run one sprint's pure (side-effect-free) generate→evaluate cycle. */
33
+ runSprint: (input: SprintInput) => Promise<SprintOutcome>;
34
+ }
35
+ export interface RunWorkflowOptions {
36
+ /**
37
+ * Scheduler used to run the sprint loop. Defaults to a sequential scheduler
38
+ * (maxConcurrent 1) for TS-pipeline parity. Sprint 5 raises the cap and adds
39
+ * dependsOn-aware ordering for true cross-sprint parallelism.
40
+ */
41
+ scheduler?: Scheduler;
42
+ }
43
+ /**
44
+ * Run the workflow: plan → derive contracts → (skip completed) → sprint loop →
45
+ * aggregate into a {@link WorkflowRunResult}. Writes nothing.
46
+ */
47
+ export declare function runWorkflow(args: WorkflowArgs, projectRoot: string, deps: WorkflowDeps, opts?: RunWorkflowOptions): Promise<WorkflowRunResult>;
48
+ //# sourceMappingURL=interpreter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"interpreter.d.ts","sourceRoot":"","sources":["../../../src/orchestrator/workflow/interpreter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAClE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AACxD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AAEzE,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAInE,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,QAAQ,CAAC;IACf,kBAAkB,EAAE,OAAO,CAAC;CAC7B;AAED,MAAM,WAAW,YAAY;IAC3B,iDAAiD;IACjD,IAAI,EAAE,CAAC,IAAI,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,KAAK,OAAO,CAAC,UAAU,CAAC,CAAC;IACvE,mFAAmF;IACnF,cAAc,EAAE,CAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,YAAY,KAAK,cAAc,EAAE,CAAC;IACzE,wEAAwE;IACxE,SAAS,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,OAAO,CAAC,aAAa,CAAC,CAAC;CAC3D;AAED,MAAM,WAAW,kBAAkB;IACjC;;;;OAIG;IACH,SAAS,CAAC,EAAE,SAAS,CAAC;CACvB;AAED;;;GAGG;AACH,wBAAsB,WAAW,CAC/B,IAAI,EAAE,YAAY,EAClB,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE,YAAY,EAClB,IAAI,GAAE,kBAAuB,GAC5B,OAAO,CAAC,iBAAiB,CAAC,CAsF5B"}
@@ -0,0 +1,92 @@
1
+ /**
2
+ * Workflow interpreter — the live body of the (currently dormant) WorkflowEngine
3
+ * invoke() seam.
4
+ *
5
+ * Reproduces the TS pipeline's plan → sprint-loop orchestration as PURE
6
+ * computation: it produces a {@link WorkflowRunResult} and writes nothing.
7
+ * `RunResultFlusher.flush()` commits the result afterward (the sole clock/commit
8
+ * source). Plan / contract-derivation / sprint-cycle are injected
9
+ * ({@link WorkflowDeps}) so the interpreter is hermetically testable; the real
10
+ * agent wiring (default deps) and the invoke() rewire + eligibility flip land in
11
+ * Sprint 5.
12
+ *
13
+ * Resume: contracts whose `sprintNumber` is in `args.resumeCursor.completed-
14
+ * SprintNumbers` are filtered out BEFORE dispatch, so the result only contains
15
+ * newly-run sprints — the flusher then appends only their history (no
16
+ * double-write on re-run).
17
+ */
18
+ import { Scheduler } from "./scheduler.js";
19
+ /**
20
+ * Run the workflow: plan → derive contracts → (skip completed) → sprint loop →
21
+ * aggregate into a {@link WorkflowRunResult}. Writes nothing.
22
+ */
23
+ export async function runWorkflow(args, projectRoot, deps, opts = {}) {
24
+ const scheduler = opts.scheduler ?? new Scheduler({ maxConcurrent: 1 });
25
+ const pendingHistory = [];
26
+ // ── Plan (or reuse preloaded spec on resume) ───────────────────────
27
+ let spec;
28
+ let needsClarification = false;
29
+ if (args.preloadedSpec) {
30
+ spec = args.preloadedSpec;
31
+ }
32
+ else {
33
+ const planned = await deps.plan(args, projectRoot);
34
+ spec = planned.spec;
35
+ needsClarification = planned.needsClarification;
36
+ }
37
+ pendingHistory.push({
38
+ event: "workflow-planning-complete",
39
+ phase: "planning",
40
+ details: { specId: spec.specId },
41
+ });
42
+ if (needsClarification) {
43
+ pendingHistory.push({
44
+ event: "planning-needs-clarification",
45
+ phase: "planning",
46
+ details: { specId: spec.specId },
47
+ });
48
+ return { spec, perSprint: [], needsClarification: true, pendingHistory };
49
+ }
50
+ // ── Contracts (preloaded on resume, else derived from the spec) ────
51
+ const allContracts = args.preloadedContracts.length > 0
52
+ ? args.preloadedContracts
53
+ : deps.buildContracts(spec, args);
54
+ const capped = allContracts.slice(0, Math.min(allContracts.length, args.knobs.maxSprints));
55
+ // ── Skip-completed (resume) — filter BEFORE dispatch ───────────────
56
+ const completed = new Set(args.resumeCursor.completedSprintNumbers);
57
+ const pending = capped.filter((c) => !completed.has(c.sprintNumber));
58
+ // ── Sprint loop (scheduler-bounded; results index-aligned) ─────────
59
+ const outcomes = await scheduler.parallel(pending.map((contract) => () => deps.runSprint({
60
+ contract,
61
+ spec,
62
+ maxIterations: args.knobs.maxIterations,
63
+ priorPassed: [],
64
+ })));
65
+ const perSprint = outcomes.map((o) => ({
66
+ contract: o.contract,
67
+ finalVerdict: o.finalVerdict,
68
+ iterationsUsed: o.iterationsUsed,
69
+ outcome: o.outcome,
70
+ lensVerdicts: o.lensVerdicts,
71
+ }));
72
+ for (const o of outcomes) {
73
+ pendingHistory.push({
74
+ event: "workflow-sprint-evaluated",
75
+ phase: o.outcome === "passed" ? "complete" : "evaluating",
76
+ sprintId: o.contract.contractId,
77
+ details: { outcome: o.outcome, iterations: o.iterationsUsed },
78
+ });
79
+ }
80
+ const allPassed = perSprint.length > 0 && perSprint.every((p) => p.outcome === "passed");
81
+ pendingHistory.push({
82
+ event: "workflow-complete",
83
+ phase: allPassed ? "complete" : "failed",
84
+ details: {
85
+ total: perSprint.length,
86
+ passed: perSprint.filter((p) => p.outcome === "passed").length,
87
+ failed: perSprint.filter((p) => p.outcome !== "passed").length,
88
+ },
89
+ });
90
+ return { spec, perSprint, needsClarification: false, pendingHistory };
91
+ }
92
+ //# sourceMappingURL=interpreter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"interpreter.js","sourceRoot":"","sources":["../../../src/orchestrator/workflow/interpreter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,65 @@
1
+ /**
2
+ * Pure (side-effect-free) sprint cycle for the workflow interpreter.
3
+ *
4
+ * The TS pipeline's `runSprintCycle` (pipeline.ts:131) writes contracts, history,
5
+ * and audit checkpoints to `.bober/` inline. The workflow engine makes
6
+ * `RunResultFlusher` the SOLE clock/commit source — so the interpreter needs a
7
+ * sprint cycle that produces a result WITHOUT touching disk. This is that cycle:
8
+ * a generate→evaluate retry loop that returns a {@link SprintOutcome} and writes
9
+ * nothing. The flusher commits it afterward.
10
+ *
11
+ * The curate / generate / evaluate steps are INJECTED ({@link PureSprintDeps}):
12
+ * Sprint 3 ships the loop + its tests with fakes; the real wiring (runCurator /
13
+ * runGenerator / panel evaluator) is attached in the interpreter's default deps
14
+ * (Sprint 5, when eligibility flips). EvalResult timestamps come from the
15
+ * evaluator (real evaluation data) — never synthesized here — so this stays
16
+ * clock-free for the host's history stamping.
17
+ */
18
+ import type { SprintContract } from "../../contracts/sprint-contract.js";
19
+ import type { EvalResult } from "../../contracts/eval-result.js";
20
+ import type { PlanSpec } from "../../contracts/spec.js";
21
+ export type SprintOutcomeKind = "passed" | "needs-rework" | "failed";
22
+ export interface SprintInput {
23
+ contract: SprintContract;
24
+ spec: PlanSpec;
25
+ /** Max generate→evaluate iterations for this sprint. */
26
+ maxIterations: number;
27
+ /** Contracts that already passed — context for the generator/curator. */
28
+ priorPassed: SprintContract[];
29
+ }
30
+ export interface SprintOutcome {
31
+ contract: SprintContract;
32
+ finalVerdict: EvalResult;
33
+ iterationsUsed: number;
34
+ outcome: SprintOutcomeKind;
35
+ /** The per-lens verdicts from the final iteration (length >= 1). */
36
+ lensVerdicts: EvalResult[];
37
+ }
38
+ /** One generation attempt's result (provider-agnostic, side-effect-free). */
39
+ export interface GenerationResult {
40
+ /** True if the generator hit a hard blocker it could not resolve. */
41
+ blocked: boolean;
42
+ /** Free-form summary, threaded into the next iteration's feedback. */
43
+ summary: string;
44
+ }
45
+ export type ReconcileFn = (contractId: string, iteration: number, verdicts: EvalResult[], timestamp: string) => EvalResult;
46
+ export interface PureSprintDeps {
47
+ /** Optional one-shot context curation; returns a briefing string. */
48
+ curate?: (input: SprintInput) => Promise<string>;
49
+ /** Run one generation attempt. `feedback` is empty on the first iteration. */
50
+ generate: (input: SprintInput, briefing: string, feedback: string) => Promise<GenerationResult>;
51
+ /** Evaluate current state → one or more lens verdicts for this iteration. */
52
+ evaluate: (input: SprintInput, iteration: number) => Promise<EvalResult[]>;
53
+ /** Reduce lens verdicts to one verdict. Defaults to the majority-vote reconciler. */
54
+ reconcile?: ReconcileFn;
55
+ }
56
+ /**
57
+ * Run a single sprint's generate→evaluate retry loop, side-effect-free.
58
+ *
59
+ * Each iteration: (curate once) → generate → evaluate → reconcile. Returns
60
+ * `passed` as soon as a verdict passes (and the generator isn't blocked);
61
+ * `failed` if the generator reports a hard blocker; `needs-rework` if the
62
+ * iteration budget is exhausted without passing.
63
+ */
64
+ export declare function runPureSprint(input: SprintInput, deps: PureSprintDeps): Promise<SprintOutcome>;
65
+ //# sourceMappingURL=pure-sprint.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pure-sprint.d.ts","sourceRoot":"","sources":["../../../src/orchestrator/workflow/pure-sprint.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AACzE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAC;AACjE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAGxD,MAAM,MAAM,iBAAiB,GAAG,QAAQ,GAAG,cAAc,GAAG,QAAQ,CAAC;AAErE,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,cAAc,CAAC;IACzB,IAAI,EAAE,QAAQ,CAAC;IACf,wDAAwD;IACxD,aAAa,EAAE,MAAM,CAAC;IACtB,yEAAyE;IACzE,WAAW,EAAE,cAAc,EAAE,CAAC;CAC/B;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,cAAc,CAAC;IACzB,YAAY,EAAE,UAAU,CAAC;IACzB,cAAc,EAAE,MAAM,CAAC;IACvB,OAAO,EAAE,iBAAiB,CAAC;IAC3B,oEAAoE;IACpE,YAAY,EAAE,UAAU,EAAE,CAAC;CAC5B;AAED,6EAA6E;AAC7E,MAAM,WAAW,gBAAgB;IAC/B,qEAAqE;IACrE,OAAO,EAAE,OAAO,CAAC;IACjB,sEAAsE;IACtE,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,MAAM,WAAW,GAAG,CACxB,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,UAAU,EAAE,EACtB,SAAS,EAAE,MAAM,KACd,UAAU,CAAC;AAEhB,MAAM,WAAW,cAAc;IAC7B,qEAAqE;IACrE,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACjD,8EAA8E;IAC9E,QAAQ,EAAE,CACR,KAAK,EAAE,WAAW,EAClB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,KACb,OAAO,CAAC,gBAAgB,CAAC,CAAC;IAC/B,6EAA6E;IAC7E,QAAQ,EAAE,CAAC,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC;IAC3E,qFAAqF;IACrF,SAAS,CAAC,EAAE,WAAW,CAAC;CACzB;AAaD;;;;;;;GAOG;AACH,wBAAsB,aAAa,CACjC,KAAK,EAAE,WAAW,EAClB,IAAI,EAAE,cAAc,GACnB,OAAO,CAAC,aAAa,CAAC,CAqDxB"}
@@ -0,0 +1,82 @@
1
+ /**
2
+ * Pure (side-effect-free) sprint cycle for the workflow interpreter.
3
+ *
4
+ * The TS pipeline's `runSprintCycle` (pipeline.ts:131) writes contracts, history,
5
+ * and audit checkpoints to `.bober/` inline. The workflow engine makes
6
+ * `RunResultFlusher` the SOLE clock/commit source — so the interpreter needs a
7
+ * sprint cycle that produces a result WITHOUT touching disk. This is that cycle:
8
+ * a generate→evaluate retry loop that returns a {@link SprintOutcome} and writes
9
+ * nothing. The flusher commits it afterward.
10
+ *
11
+ * The curate / generate / evaluate steps are INJECTED ({@link PureSprintDeps}):
12
+ * Sprint 3 ships the loop + its tests with fakes; the real wiring (runCurator /
13
+ * runGenerator / panel evaluator) is attached in the interpreter's default deps
14
+ * (Sprint 5, when eligibility flips). EvalResult timestamps come from the
15
+ * evaluator (real evaluation data) — never synthesized here — so this stays
16
+ * clock-free for the host's history stamping.
17
+ */
18
+ import { reconcile } from "./reconciler.js";
19
+ /** Use a verdict's own timestamp (evaluation data); epoch fallback if none. */
20
+ function pickTimestamp(verdicts) {
21
+ return verdicts[0]?.timestamp ?? new Date(0).toISOString();
22
+ }
23
+ function buildFeedback(verdict, gen) {
24
+ return [verdict.feedback, gen.summary]
25
+ .filter((s) => s.length > 0)
26
+ .join("\n");
27
+ }
28
+ /**
29
+ * Run a single sprint's generate→evaluate retry loop, side-effect-free.
30
+ *
31
+ * Each iteration: (curate once) → generate → evaluate → reconcile. Returns
32
+ * `passed` as soon as a verdict passes (and the generator isn't blocked);
33
+ * `failed` if the generator reports a hard blocker; `needs-rework` if the
34
+ * iteration budget is exhausted without passing.
35
+ */
36
+ export async function runPureSprint(input, deps) {
37
+ const reduce = deps.reconcile ?? reconcile;
38
+ const contractId = input.contract.contractId;
39
+ const briefing = deps.curate ? await deps.curate(input) : "";
40
+ const maxIter = Math.max(1, input.maxIterations);
41
+ let feedback = "";
42
+ let lastVerdict;
43
+ let lastLensVerdicts = [];
44
+ for (let iter = 1; iter <= maxIter; iter += 1) {
45
+ const gen = await deps.generate(input, briefing, feedback);
46
+ const lensVerdicts = await deps.evaluate(input, iter);
47
+ lastLensVerdicts = lensVerdicts;
48
+ const verdict = lensVerdicts.length === 1 && lensVerdicts[0] !== undefined
49
+ ? lensVerdicts[0]
50
+ : reduce(contractId, iter, lensVerdicts, pickTimestamp(lensVerdicts));
51
+ lastVerdict = verdict;
52
+ if (verdict.passed && !gen.blocked) {
53
+ return {
54
+ contract: input.contract,
55
+ finalVerdict: verdict,
56
+ iterationsUsed: iter,
57
+ outcome: "passed",
58
+ lensVerdicts,
59
+ };
60
+ }
61
+ if (gen.blocked) {
62
+ return {
63
+ contract: input.contract,
64
+ finalVerdict: verdict,
65
+ iterationsUsed: iter,
66
+ outcome: "failed",
67
+ lensVerdicts,
68
+ };
69
+ }
70
+ feedback = buildFeedback(verdict, gen);
71
+ }
72
+ // Iteration budget exhausted without passing → retryable rework.
73
+ const finalVerdict = lastVerdict ?? reduce(contractId, maxIter, [], new Date(0).toISOString());
74
+ return {
75
+ contract: input.contract,
76
+ finalVerdict,
77
+ iterationsUsed: maxIter,
78
+ outcome: "needs-rework",
79
+ lensVerdicts: lastLensVerdicts,
80
+ };
81
+ }
82
+ //# sourceMappingURL=pure-sprint.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pure-sprint.js","sourceRoot":"","sources":["../../../src/orchestrator/workflow/pure-sprint.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ import type { EvalResult } from "../../contracts/eval-result.js";
2
+ /**
3
+ * Pure majority-vote reducer over per-lens EvalResult[] (ADR-4).
4
+ * No Date.now / new Date / Math.random / fs — timestamp is a caller arg.
5
+ *
6
+ * Rules:
7
+ * - empty lensVerdicts → throws
8
+ * - passed = passCount > failCount (strict majority, fail-closed on tie)
9
+ * - details = union of all failing details, de-duped by (criterion, message)
10
+ * - feedback = failing lenses' feedback joined with newlines, or "All lenses passed."
11
+ * - evaluator = "panel"
12
+ * - timestamp = the injected timestamp argument (echoed verbatim)
13
+ */
14
+ export declare function reconcile(_sprintId: string, _round: number, lensVerdicts: EvalResult[], timestamp: string): EvalResult;
15
+ //# sourceMappingURL=reconciler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reconciler.d.ts","sourceRoot":"","sources":["../../../src/orchestrator/workflow/reconciler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAc,MAAM,gCAAgC,CAAC;AAI7E;;;;;;;;;;;GAWG;AACH,wBAAgB,SAAS,CACvB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,UAAU,EAAE,EAC1B,SAAS,EAAE,MAAM,GAChB,UAAU,CA4DZ"}
@@ -0,0 +1,65 @@
1
+ // ── Reconciler ─────────────────────────────────────────────────────
2
+ /**
3
+ * Pure majority-vote reducer over per-lens EvalResult[] (ADR-4).
4
+ * No Date.now / new Date / Math.random / fs — timestamp is a caller arg.
5
+ *
6
+ * Rules:
7
+ * - empty lensVerdicts → throws
8
+ * - passed = passCount > failCount (strict majority, fail-closed on tie)
9
+ * - details = union of all failing details, de-duped by (criterion, message)
10
+ * - feedback = failing lenses' feedback joined with newlines, or "All lenses passed."
11
+ * - evaluator = "panel"
12
+ * - timestamp = the injected timestamp argument (echoed verbatim)
13
+ */
14
+ export function reconcile(_sprintId, _round, lensVerdicts, timestamp) {
15
+ if (lensVerdicts.length === 0) {
16
+ throw new Error("reconcile: lensVerdicts must be non-empty");
17
+ }
18
+ const n = lensVerdicts.length;
19
+ // Count passing lenses
20
+ let passCount = 0;
21
+ for (const lens of lensVerdicts) {
22
+ if (lens.passed === true) {
23
+ passCount = passCount + 1;
24
+ }
25
+ }
26
+ const failCount = n - passCount;
27
+ // Strict majority: passCount must exceed failCount (fail-closed on tie)
28
+ const passed = passCount > failCount;
29
+ // Union failing details, de-duped by criterion + message
30
+ const seenKeys = new Set();
31
+ const details = [];
32
+ for (const lens of lensVerdicts) {
33
+ for (const detail of lens.details) {
34
+ if (detail.passed === false) {
35
+ const key = `${detail.criterion}␟${detail.message}`;
36
+ if (!seenKeys.has(key)) {
37
+ seenKeys.add(key);
38
+ details.push(detail);
39
+ }
40
+ }
41
+ }
42
+ }
43
+ // Build summary
44
+ const summary = `Panel verdict: ${passCount}/${n} lenses passed`;
45
+ // Build feedback from failing lenses
46
+ const feedbackParts = [];
47
+ for (const lens of lensVerdicts) {
48
+ if (!lens.passed && lens.feedback) {
49
+ feedbackParts.push(lens.feedback);
50
+ }
51
+ }
52
+ const feedback = feedbackParts.length > 0 ? feedbackParts.join("\n") : "All lenses passed.";
53
+ // Compute optional score
54
+ const score = Math.round((100 * passCount) / n);
55
+ return {
56
+ evaluator: "panel",
57
+ passed,
58
+ score,
59
+ details,
60
+ summary,
61
+ feedback,
62
+ timestamp,
63
+ };
64
+ }
65
+ //# sourceMappingURL=reconciler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reconciler.js","sourceRoot":"","sources":["../../../src/orchestrator/workflow/reconciler.ts"],"names":[],"mappings":"AAEA,sEAAsE;AAEtE;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,SAAS,CACvB,SAAiB,EACjB,MAAc,EACd,YAA0B,EAC1B,SAAiB;IAEjB,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC9B,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC;IAC/D,CAAC;IAED,MAAM,CAAC,GAAG,YAAY,CAAC,MAAM,CAAC;IAE9B,uBAAuB;IACvB,IAAI,SAAS,GAAG,CAAC,CAAC;IAClB,KAAK,MAAM,IAAI,IAAI,YAAY,EAAE,CAAC;QAChC,IAAI,IAAI,CAAC,MAAM,KAAK,IAAI,EAAE,CAAC;YACzB,SAAS,GAAG,SAAS,GAAG,CAAC,CAAC;QAC5B,CAAC;IACH,CAAC;IAED,MAAM,SAAS,GAAG,CAAC,GAAG,SAAS,CAAC;IAEhC,wEAAwE;IACxE,MAAM,MAAM,GAAG,SAAS,GAAG,SAAS,CAAC;IAErC,yDAAyD;IACzD,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAU,CAAC;IACnC,MAAM,OAAO,GAAiB,EAAE,CAAC;IAEjC,KAAK,MAAM,IAAI,IAAI,YAAY,EAAE,CAAC;QAChC,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YAClC,IAAI,MAAM,CAAC,MAAM,KAAK,KAAK,EAAE,CAAC;gBAC5B,MAAM,GAAG,GAAG,GAAG,MAAM,CAAC,SAAS,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;gBACpD,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;oBACvB,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;oBAClB,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;gBACvB,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,gBAAgB;IAChB,MAAM,OAAO,GAAG,kBAAkB,SAAS,IAAI,CAAC,gBAAgB,CAAC;IAEjE,qCAAqC;IACrC,MAAM,aAAa,GAAa,EAAE,CAAC;IACnC,KAAK,MAAM,IAAI,IAAI,YAAY,EAAE,CAAC;QAChC,IAAI,CAAC,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAClC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACpC,CAAC;IACH,CAAC;IACD,MAAM,QAAQ,GAAG,aAAa,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,oBAAoB,CAAC;IAE5F,yBAAyB;IACzB,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC;IAEhD,OAAO;QACL,SAAS,EAAE,OAAO;QAClB,MAAM;QACN,KAAK;QACL,OAAO;QACP,OAAO;QACP,QAAQ;QACR,SAAS;KACV,CAAC;AACJ,CAAC"}
@@ -0,0 +1,10 @@
1
+ import type { ResumeCursor } from "./types.js";
2
+ /**
3
+ * Reconstructs a ResumeCursor from durable contract status and history.
4
+ * Contract status is the source of truth — history is corroboration only.
5
+ * When history and contract status conflict, contract status wins.
6
+ */
7
+ export declare class ResumeCursorReconstructor {
8
+ reconstruct(projectRoot: string, specId: string): Promise<ResumeCursor>;
9
+ }
10
+ //# sourceMappingURL=resume-cursor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resume-cursor.d.ts","sourceRoot":"","sources":["../../../src/orchestrator/workflow/resume-cursor.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C;;;;GAIG;AACH,qBAAa,yBAAyB;IAC9B,WAAW,CAAC,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;CAoB9E"}
@@ -0,0 +1,25 @@
1
+ // ── ResumeCursorReconstructor ───────────────────────────────────────
2
+ import { listContracts } from "../../state/sprint-state.js";
3
+ import { loadHistory } from "../../state/history.js";
4
+ /**
5
+ * Reconstructs a ResumeCursor from durable contract status and history.
6
+ * Contract status is the source of truth — history is corroboration only.
7
+ * When history and contract status conflict, contract status wins.
8
+ */
9
+ export class ResumeCursorReconstructor {
10
+ async reconstruct(projectRoot, specId) {
11
+ const contracts = (await listContracts(projectRoot)).filter((c) => c.specId === specId);
12
+ // Corroborate with history, but contract status WINS on conflict
13
+ await loadHistory(projectRoot);
14
+ const completed = contracts
15
+ .filter((c) => c.status === "passed" || c.status === "completed")
16
+ .map((c) => c.sprintNumber);
17
+ const allNumbers = contracts.map((c) => c.sprintNumber);
18
+ return {
19
+ specId,
20
+ completedSprintNumbers: [...completed].sort((a, b) => a - b),
21
+ lastObservedSprintNumber: allNumbers.length ? Math.max(...allNumbers) : 0,
22
+ };
23
+ }
24
+ }
25
+ //# sourceMappingURL=resume-cursor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resume-cursor.js","sourceRoot":"","sources":["../../../src/orchestrator/workflow/resume-cursor.ts"],"names":[],"mappings":"AAAA,uEAAuE;AAEvE,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAC5D,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAGrD;;;;GAIG;AACH,MAAM,OAAO,yBAAyB;IACpC,KAAK,CAAC,WAAW,CAAC,WAAmB,EAAE,MAAc;QACnD,MAAM,SAAS,GAAG,CAAC,MAAM,aAAa,CAAC,WAAW,CAAC,CAAC,CAAC,MAAM,CACzD,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,MAAM,CAC3B,CAAC;QAEF,iEAAiE;QACjE,MAAM,WAAW,CAAC,WAAW,CAAC,CAAC;QAE/B,MAAM,SAAS,GAAG,SAAS;aACxB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,QAAQ,IAAI,CAAC,CAAC,MAAM,KAAK,WAAW,CAAC;aAChE,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC;QAE9B,MAAM,UAAU,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC;QAExD,OAAO;YACL,MAAM;YACN,sBAAsB,EAAE,CAAC,GAAG,SAAS,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC;YAC5D,wBAAwB,EAAE,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;SAC1E,CAAC;IACJ,CAAC;CACF"}
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Exponential-backoff retry for transient provider failures.
3
+ *
4
+ * Today the agentic loop ends on the first `client.chat()` error
5
+ * (agentic-loop.ts), which is fragile when hammering a single local model
6
+ * server (Ollama/vLLM return 429/503 under load). `withRetry` wraps a call in
7
+ * bounded exponential backoff with jitter, retrying only TRANSIENT failures
8
+ * (rate limits, overload, timeouts, network resets) and surfacing everything
9
+ * else immediately.
10
+ *
11
+ * The scheduler / interpreter wraps each provider call in this, so every
12
+ * provider benefits without per-adapter changes. `sleep` and `jitter` are
13
+ * injectable so tests are deterministic and instant.
14
+ */
15
+ /**
16
+ * Heuristic: is this error worth retrying? True for HTTP 408/429 and 5xx,
17
+ * known transient network codes, and overload/rate-limit/timeout messages.
18
+ */
19
+ export declare function classifyTransient(err: unknown): boolean;
20
+ export interface RetryOptions {
21
+ /** Max retries AFTER the first attempt. Default 3 (=> up to 4 calls). */
22
+ maxRetries?: number;
23
+ /** Base delay in ms for the first backoff. Default 500. */
24
+ baseDelayMs?: number;
25
+ /** Upper bound on a single backoff delay. Default 30_000. */
26
+ maxDelayMs?: number;
27
+ /** Exponential growth factor. Default 2. */
28
+ factor?: number;
29
+ /** Returns a value in [0, 1) for jitter. Default Math.random. Inject for tests. */
30
+ jitter?: () => number;
31
+ /** Sleeps for `ms`. Default setTimeout-backed. Inject for tests. */
32
+ sleep?: (ms: number) => Promise<void>;
33
+ /** Decides whether an error is retryable. Default {@link classifyTransient}. */
34
+ isTransient?: (err: unknown) => boolean;
35
+ /** Called before each backoff sleep (for logging / telemetry). */
36
+ onRetry?: (info: {
37
+ attempt: number;
38
+ delayMs: number;
39
+ error: unknown;
40
+ }) => void;
41
+ }
42
+ /**
43
+ * Run `fn`, retrying TRANSIENT failures with exponential backoff + jitter.
44
+ * Non-transient errors and the final exhausted error are rethrown.
45
+ *
46
+ * Backoff for retry `n` (0-based): `min(maxDelayMs, baseDelayMs * factor**n)`,
47
+ * then jittered to 50–100% of that value (decorrelated, avoids thundering herd).
48
+ */
49
+ export declare function withRetry<T>(fn: () => Promise<T>, opts?: RetryOptions): Promise<T>;
50
+ //# sourceMappingURL=retry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"retry.d.ts","sourceRoot":"","sources":["../../../src/orchestrator/workflow/retry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AA2CH;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CASvD;AAID,MAAM,WAAW,YAAY;IAC3B,yEAAyE;IACzE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,2DAA2D;IAC3D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,6DAA6D;IAC7D,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,4CAA4C;IAC5C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,mFAAmF;IACnF,MAAM,CAAC,EAAE,MAAM,MAAM,CAAC;IACtB,oEAAoE;IACpE,KAAK,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACtC,gFAAgF;IAChF,WAAW,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,OAAO,CAAC;IACxC,kEAAkE;IAClE,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,OAAO,CAAA;KAAE,KAAK,IAAI,CAAC;CAChF;AAKD;;;;;;GAMG;AACH,wBAAsB,SAAS,CAAC,CAAC,EAC/B,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACpB,IAAI,GAAE,YAAiB,GACtB,OAAO,CAAC,CAAC,CAAC,CAyBZ"}