agent-bober 0.1.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 (212) hide show
  1. package/.claude-plugin/plugin.json +9 -0
  2. package/LICENSE +21 -0
  3. package/README.md +495 -0
  4. package/agents/bober-evaluator.md +323 -0
  5. package/agents/bober-generator.md +245 -0
  6. package/agents/bober-planner.md +248 -0
  7. package/dist/cli/commands/eval.d.ts +6 -0
  8. package/dist/cli/commands/eval.d.ts.map +1 -0
  9. package/dist/cli/commands/eval.js +129 -0
  10. package/dist/cli/commands/eval.js.map +1 -0
  11. package/dist/cli/commands/init.d.ts +5 -0
  12. package/dist/cli/commands/init.d.ts.map +1 -0
  13. package/dist/cli/commands/init.js +547 -0
  14. package/dist/cli/commands/init.js.map +1 -0
  15. package/dist/cli/commands/plan.d.ts +5 -0
  16. package/dist/cli/commands/plan.d.ts.map +1 -0
  17. package/dist/cli/commands/plan.js +87 -0
  18. package/dist/cli/commands/plan.js.map +1 -0
  19. package/dist/cli/commands/run.d.ts +5 -0
  20. package/dist/cli/commands/run.d.ts.map +1 -0
  21. package/dist/cli/commands/run.js +120 -0
  22. package/dist/cli/commands/run.js.map +1 -0
  23. package/dist/cli/commands/sprint.d.ts +6 -0
  24. package/dist/cli/commands/sprint.d.ts.map +1 -0
  25. package/dist/cli/commands/sprint.js +206 -0
  26. package/dist/cli/commands/sprint.js.map +1 -0
  27. package/dist/cli/index.d.ts +3 -0
  28. package/dist/cli/index.d.ts.map +1 -0
  29. package/dist/cli/index.js +124 -0
  30. package/dist/cli/index.js.map +1 -0
  31. package/dist/config/defaults.d.ts +15 -0
  32. package/dist/config/defaults.d.ts.map +1 -0
  33. package/dist/config/defaults.js +226 -0
  34. package/dist/config/defaults.js.map +1 -0
  35. package/dist/config/index.d.ts +4 -0
  36. package/dist/config/index.d.ts.map +1 -0
  37. package/dist/config/index.js +8 -0
  38. package/dist/config/index.js.map +1 -0
  39. package/dist/config/loader.d.ts +18 -0
  40. package/dist/config/loader.d.ts.map +1 -0
  41. package/dist/config/loader.js +189 -0
  42. package/dist/config/loader.js.map +1 -0
  43. package/dist/config/schema.d.ts +904 -0
  44. package/dist/config/schema.d.ts.map +1 -0
  45. package/dist/config/schema.js +181 -0
  46. package/dist/config/schema.js.map +1 -0
  47. package/dist/contracts/eval-result.d.ts +205 -0
  48. package/dist/contracts/eval-result.d.ts.map +1 -0
  49. package/dist/contracts/eval-result.js +87 -0
  50. package/dist/contracts/eval-result.js.map +1 -0
  51. package/dist/contracts/index.d.ts +4 -0
  52. package/dist/contracts/index.d.ts.map +1 -0
  53. package/dist/contracts/index.js +16 -0
  54. package/dist/contracts/index.js.map +1 -0
  55. package/dist/contracts/spec.d.ts +101 -0
  56. package/dist/contracts/spec.d.ts.map +1 -0
  57. package/dist/contracts/spec.js +51 -0
  58. package/dist/contracts/spec.js.map +1 -0
  59. package/dist/contracts/sprint-contract.d.ts +141 -0
  60. package/dist/contracts/sprint-contract.d.ts.map +1 -0
  61. package/dist/contracts/sprint-contract.js +80 -0
  62. package/dist/contracts/sprint-contract.js.map +1 -0
  63. package/dist/evaluators/builtin/api-check.d.ts +13 -0
  64. package/dist/evaluators/builtin/api-check.d.ts.map +1 -0
  65. package/dist/evaluators/builtin/api-check.js +152 -0
  66. package/dist/evaluators/builtin/api-check.js.map +1 -0
  67. package/dist/evaluators/builtin/build-check.d.ts +17 -0
  68. package/dist/evaluators/builtin/build-check.d.ts.map +1 -0
  69. package/dist/evaluators/builtin/build-check.js +155 -0
  70. package/dist/evaluators/builtin/build-check.js.map +1 -0
  71. package/dist/evaluators/builtin/command-runner.d.ts +26 -0
  72. package/dist/evaluators/builtin/command-runner.d.ts.map +1 -0
  73. package/dist/evaluators/builtin/command-runner.js +114 -0
  74. package/dist/evaluators/builtin/command-runner.js.map +1 -0
  75. package/dist/evaluators/builtin/lint.d.ts +17 -0
  76. package/dist/evaluators/builtin/lint.d.ts.map +1 -0
  77. package/dist/evaluators/builtin/lint.js +264 -0
  78. package/dist/evaluators/builtin/lint.js.map +1 -0
  79. package/dist/evaluators/builtin/playwright.d.ts +16 -0
  80. package/dist/evaluators/builtin/playwright.d.ts.map +1 -0
  81. package/dist/evaluators/builtin/playwright.js +238 -0
  82. package/dist/evaluators/builtin/playwright.js.map +1 -0
  83. package/dist/evaluators/builtin/typescript-check.d.ts +12 -0
  84. package/dist/evaluators/builtin/typescript-check.d.ts.map +1 -0
  85. package/dist/evaluators/builtin/typescript-check.js +155 -0
  86. package/dist/evaluators/builtin/typescript-check.js.map +1 -0
  87. package/dist/evaluators/builtin/unit-test.d.ts +18 -0
  88. package/dist/evaluators/builtin/unit-test.d.ts.map +1 -0
  89. package/dist/evaluators/builtin/unit-test.js +279 -0
  90. package/dist/evaluators/builtin/unit-test.js.map +1 -0
  91. package/dist/evaluators/index.d.ts +11 -0
  92. package/dist/evaluators/index.d.ts.map +1 -0
  93. package/dist/evaluators/index.js +13 -0
  94. package/dist/evaluators/index.js.map +1 -0
  95. package/dist/evaluators/plugin-interface.d.ts +50 -0
  96. package/dist/evaluators/plugin-interface.d.ts.map +1 -0
  97. package/dist/evaluators/plugin-interface.js +2 -0
  98. package/dist/evaluators/plugin-interface.js.map +1 -0
  99. package/dist/evaluators/plugin-loader.d.ts +18 -0
  100. package/dist/evaluators/plugin-loader.d.ts.map +1 -0
  101. package/dist/evaluators/plugin-loader.js +107 -0
  102. package/dist/evaluators/plugin-loader.js.map +1 -0
  103. package/dist/evaluators/registry.d.ts +78 -0
  104. package/dist/evaluators/registry.d.ts.map +1 -0
  105. package/dist/evaluators/registry.js +238 -0
  106. package/dist/evaluators/registry.js.map +1 -0
  107. package/dist/index.d.ts +17 -0
  108. package/dist/index.d.ts.map +1 -0
  109. package/dist/index.js +22 -0
  110. package/dist/index.js.map +1 -0
  111. package/dist/orchestrator/context-handoff.d.ts +543 -0
  112. package/dist/orchestrator/context-handoff.d.ts.map +1 -0
  113. package/dist/orchestrator/context-handoff.js +133 -0
  114. package/dist/orchestrator/context-handoff.js.map +1 -0
  115. package/dist/orchestrator/evaluator-agent.d.ts +15 -0
  116. package/dist/orchestrator/evaluator-agent.d.ts.map +1 -0
  117. package/dist/orchestrator/evaluator-agent.js +233 -0
  118. package/dist/orchestrator/evaluator-agent.js.map +1 -0
  119. package/dist/orchestrator/generator-agent.d.ts +16 -0
  120. package/dist/orchestrator/generator-agent.d.ts.map +1 -0
  121. package/dist/orchestrator/generator-agent.js +147 -0
  122. package/dist/orchestrator/generator-agent.js.map +1 -0
  123. package/dist/orchestrator/pipeline.d.ts +24 -0
  124. package/dist/orchestrator/pipeline.d.ts.map +1 -0
  125. package/dist/orchestrator/pipeline.js +290 -0
  126. package/dist/orchestrator/pipeline.js.map +1 -0
  127. package/dist/orchestrator/planner-agent.d.ts +10 -0
  128. package/dist/orchestrator/planner-agent.d.ts.map +1 -0
  129. package/dist/orchestrator/planner-agent.js +187 -0
  130. package/dist/orchestrator/planner-agent.js.map +1 -0
  131. package/dist/state/helpers.d.ts +5 -0
  132. package/dist/state/helpers.d.ts.map +1 -0
  133. package/dist/state/helpers.js +8 -0
  134. package/dist/state/helpers.js.map +1 -0
  135. package/dist/state/history.d.ts +39 -0
  136. package/dist/state/history.d.ts.map +1 -0
  137. package/dist/state/history.js +162 -0
  138. package/dist/state/history.js.map +1 -0
  139. package/dist/state/index.d.ts +8 -0
  140. package/dist/state/index.d.ts.map +1 -0
  141. package/dist/state/index.js +22 -0
  142. package/dist/state/index.js.map +1 -0
  143. package/dist/state/plan-state.d.ts +21 -0
  144. package/dist/state/plan-state.d.ts.map +1 -0
  145. package/dist/state/plan-state.js +108 -0
  146. package/dist/state/plan-state.js.map +1 -0
  147. package/dist/state/sprint-state.d.ts +20 -0
  148. package/dist/state/sprint-state.d.ts.map +1 -0
  149. package/dist/state/sprint-state.js +98 -0
  150. package/dist/state/sprint-state.js.map +1 -0
  151. package/dist/utils/fs.d.ts +31 -0
  152. package/dist/utils/fs.d.ts.map +1 -0
  153. package/dist/utils/fs.js +67 -0
  154. package/dist/utils/fs.js.map +1 -0
  155. package/dist/utils/git.d.ts +35 -0
  156. package/dist/utils/git.d.ts.map +1 -0
  157. package/dist/utils/git.js +84 -0
  158. package/dist/utils/git.js.map +1 -0
  159. package/dist/utils/index.d.ts +4 -0
  160. package/dist/utils/index.d.ts.map +1 -0
  161. package/dist/utils/index.js +4 -0
  162. package/dist/utils/index.js.map +1 -0
  163. package/dist/utils/logger.d.ts +45 -0
  164. package/dist/utils/logger.d.ts.map +1 -0
  165. package/dist/utils/logger.js +73 -0
  166. package/dist/utils/logger.js.map +1 -0
  167. package/hooks/hooks.json +10 -0
  168. package/package.json +67 -0
  169. package/scripts/detect-stack.sh +287 -0
  170. package/scripts/init-project.sh +206 -0
  171. package/scripts/run-eval.sh +175 -0
  172. package/skills/bober.anchor/SKILL.md +365 -0
  173. package/skills/bober.anchor/references/anchor-guide.md +567 -0
  174. package/skills/bober.brownfield/SKILL.md +422 -0
  175. package/skills/bober.brownfield/references/codebase-analysis.md +304 -0
  176. package/skills/bober.eval/SKILL.md +235 -0
  177. package/skills/bober.eval/references/eval-strategies.md +407 -0
  178. package/skills/bober.eval/references/feedback-format.md +182 -0
  179. package/skills/bober.plan/SKILL.md +244 -0
  180. package/skills/bober.plan/references/clarification-guide.md +124 -0
  181. package/skills/bober.plan/references/spec-schema.md +253 -0
  182. package/skills/bober.react/SKILL.md +330 -0
  183. package/skills/bober.react/references/react-scaffold.md +344 -0
  184. package/skills/bober.run/SKILL.md +303 -0
  185. package/skills/bober.solidity/SKILL.md +416 -0
  186. package/skills/bober.solidity/references/solidity-guide.md +487 -0
  187. package/skills/bober.sprint/SKILL.md +280 -0
  188. package/skills/bober.sprint/references/contract-schema.md +251 -0
  189. package/templates/base/CLAUDE.md +20 -0
  190. package/templates/base/bober.config.json +35 -0
  191. package/templates/brownfield/CLAUDE.md +34 -0
  192. package/templates/brownfield/bober.config.json +37 -0
  193. package/templates/presets/anchor/CLAUDE.md +163 -0
  194. package/templates/presets/anchor/bober.config.json +9 -0
  195. package/templates/presets/api-node/CLAUDE.md +153 -0
  196. package/templates/presets/api-node/bober.config.json +10 -0
  197. package/templates/presets/nextjs/CLAUDE.md +82 -0
  198. package/templates/presets/nextjs/bober.config.json +14 -0
  199. package/templates/presets/python-api/CLAUDE.md +202 -0
  200. package/templates/presets/python-api/bober.config.json +9 -0
  201. package/templates/presets/react-vite/CLAUDE.md +71 -0
  202. package/templates/presets/react-vite/bober.config.json +53 -0
  203. package/templates/presets/react-vite/scaffold/package.json +45 -0
  204. package/templates/presets/react-vite/scaffold/server/index.ts +38 -0
  205. package/templates/presets/react-vite/scaffold/server/tsconfig.json +24 -0
  206. package/templates/presets/react-vite/scaffold/src/App.tsx +37 -0
  207. package/templates/presets/react-vite/scaffold/src/index.html +12 -0
  208. package/templates/presets/react-vite/scaffold/src/main.tsx +12 -0
  209. package/templates/presets/react-vite/scaffold/tsconfig.json +27 -0
  210. package/templates/presets/react-vite/scaffold/vite.config.ts +34 -0
  211. package/templates/presets/solidity/CLAUDE.md +106 -0
  212. package/templates/presets/solidity/bober.config.json +9 -0
@@ -0,0 +1,290 @@
1
+ import { createContract, updateContractStatus, } from "../contracts/sprint-contract.js";
2
+ import { createHandoff, summarizeOlderSprints, } from "./context-handoff.js";
3
+ import { runPlanner } from "./planner-agent.js";
4
+ import { runGenerator } from "./generator-agent.js";
5
+ import { runEvaluatorAgent } from "./evaluator-agent.js";
6
+ import { ensureBoberDir, saveContract, updateContract, appendHistory, } from "../state/index.js";
7
+ import { commitAll, getCurrentBranch, getChangedFiles } from "../utils/git.js";
8
+ import { logger } from "../utils/logger.js";
9
+ // ── Interrupt handling ─────────────────────────────────────────────
10
+ let interrupted = false;
11
+ function setupInterruptHandler() {
12
+ interrupted = false;
13
+ const handler = () => {
14
+ if (interrupted) {
15
+ // Second SIGINT — force exit
16
+ logger.error("Force interrupted. Exiting immediately.");
17
+ process.exit(1);
18
+ }
19
+ interrupted = true;
20
+ logger.warn("Interrupt received. Finishing current sprint, then stopping...");
21
+ };
22
+ process.on("SIGINT", handler);
23
+ return () => {
24
+ process.removeListener("SIGINT", handler);
25
+ };
26
+ }
27
+ // ── Project context helper ─────────────────────────────────────────
28
+ async function buildProjectContext(projectRoot, config) {
29
+ let currentBranch;
30
+ try {
31
+ currentBranch = await getCurrentBranch(projectRoot);
32
+ }
33
+ catch {
34
+ currentBranch = "unknown";
35
+ }
36
+ return {
37
+ name: config.project.name,
38
+ type: config.project.mode,
39
+ techStack: [],
40
+ entryPoints: [],
41
+ currentBranch,
42
+ };
43
+ }
44
+ // ── Sprint cycle ───────────────────────────────────────────────────
45
+ async function runSprintCycle(contract, spec, completedContracts, projectRoot, config, projectContext) {
46
+ const maxIterations = config.evaluator.maxIterations;
47
+ let currentContract = updateContractStatus(contract, "in-progress");
48
+ await updateContract(projectRoot, currentContract);
49
+ let lastEvaluation;
50
+ let lastGeneratorResult;
51
+ for (let iteration = 1; iteration <= maxIterations; iteration++) {
52
+ if (interrupted) {
53
+ logger.warn(`Sprint ${currentContract.id} interrupted at iteration ${iteration}.`);
54
+ break;
55
+ }
56
+ logger.progress(iteration, maxIterations, `Sprint ${currentContract.id} iteration`);
57
+ // Build evaluation feedback from prior round
58
+ const evalFeedback = lastEvaluation
59
+ ? lastEvaluation.summary
60
+ : "";
61
+ // Summarize older sprints to save context
62
+ const completedSummaryHandoff = createHandoff({
63
+ from: iteration === 1 ? "planner" : "evaluator",
64
+ to: "generator",
65
+ projectContext,
66
+ spec,
67
+ currentContract,
68
+ sprintHistory: completedContracts,
69
+ instructions: `Implement sprint: ${currentContract.feature}\n\n${currentContract.description}`,
70
+ changedFiles: lastGeneratorResult?.filesChanged ?? [],
71
+ issues: evalFeedback ? [evalFeedback] : [],
72
+ });
73
+ // Compact older sprint history if needed
74
+ const compactedHandoff = summarizeOlderSprints(completedSummaryHandoff, 3);
75
+ // ── Generate ───────────────────────────────────────────────
76
+ logger.phase(`Sprint ${currentContract.id} - Generate (Round ${iteration})`);
77
+ await appendHistory(projectRoot, {
78
+ timestamp: new Date().toISOString(),
79
+ event: "generator-start",
80
+ phase: "generating",
81
+ sprintId: currentContract.id,
82
+ details: { iteration },
83
+ });
84
+ const generatorResult = await runGenerator(compactedHandoff, projectRoot, config);
85
+ lastGeneratorResult = generatorResult;
86
+ if (!generatorResult.success) {
87
+ logger.warn(`Generator reported failure: ${generatorResult.notes}`);
88
+ currentContract = {
89
+ ...currentContract,
90
+ generatorNotes: generatorResult.notes,
91
+ };
92
+ await updateContract(projectRoot, currentContract);
93
+ if (iteration < maxIterations) {
94
+ logger.info("Retrying generation...");
95
+ continue;
96
+ }
97
+ // Max iterations reached, mark as needs-rework
98
+ currentContract = updateContractStatus(currentContract, "needs-rework");
99
+ currentContract = {
100
+ ...currentContract,
101
+ evaluatorFeedback: "Generator failed to complete the implementation.",
102
+ };
103
+ await updateContract(projectRoot, currentContract);
104
+ return { contract: currentContract, generatorResult };
105
+ }
106
+ currentContract = {
107
+ ...currentContract,
108
+ generatorNotes: generatorResult.notes,
109
+ };
110
+ // Auto-commit if enabled
111
+ if (config.generator.autoCommit) {
112
+ try {
113
+ const commitHash = await commitAll(projectRoot, `bober: ${currentContract.feature} (sprint ${currentContract.id}, round ${iteration})`);
114
+ logger.success(`Committed: ${commitHash}`);
115
+ lastGeneratorResult = { ...generatorResult, commitHash };
116
+ }
117
+ catch (err) {
118
+ logger.debug(`Auto-commit skipped: ${err instanceof Error ? err.message : String(err)}`);
119
+ }
120
+ }
121
+ // ── Evaluate ──────────────────────────────────────────────
122
+ logger.phase(`Sprint ${currentContract.id} - Evaluate (Round ${iteration})`);
123
+ currentContract = updateContractStatus(currentContract, "evaluating");
124
+ await updateContract(projectRoot, currentContract);
125
+ await appendHistory(projectRoot, {
126
+ timestamp: new Date().toISOString(),
127
+ event: "evaluator-start",
128
+ phase: "evaluating",
129
+ sprintId: currentContract.id,
130
+ details: { iteration },
131
+ });
132
+ // Build handoff for evaluator
133
+ let changedFiles;
134
+ try {
135
+ changedFiles = await getChangedFiles(projectRoot);
136
+ }
137
+ catch {
138
+ changedFiles = generatorResult.filesChanged;
139
+ }
140
+ const evalHandoff = {
141
+ ...compactedHandoff,
142
+ from: "generator",
143
+ to: "evaluator",
144
+ changedFiles,
145
+ };
146
+ const evaluation = await runEvaluatorAgent(evalHandoff, projectRoot, config);
147
+ lastEvaluation = evaluation;
148
+ if (evaluation.passed) {
149
+ logger.success(`Sprint ${currentContract.id} passed all evaluations!`);
150
+ currentContract = updateContractStatus(currentContract, "passed");
151
+ currentContract = {
152
+ ...currentContract,
153
+ evaluatorFeedback: evaluation.summary,
154
+ };
155
+ await updateContract(projectRoot, currentContract);
156
+ await appendHistory(projectRoot, {
157
+ timestamp: new Date().toISOString(),
158
+ event: "sprint-passed",
159
+ phase: "complete",
160
+ sprintId: currentContract.id,
161
+ details: { iteration, feedback: evaluation.summary },
162
+ });
163
+ return { contract: currentContract, evaluation, generatorResult: lastGeneratorResult };
164
+ }
165
+ // Evaluation failed
166
+ logger.warn(`Evaluation failed (round ${iteration}/${maxIterations}): ${evaluation.summary.slice(0, 200)}`);
167
+ currentContract = {
168
+ ...currentContract,
169
+ evaluatorFeedback: evaluation.summary,
170
+ };
171
+ await updateContract(projectRoot, currentContract);
172
+ await appendHistory(projectRoot, {
173
+ timestamp: new Date().toISOString(),
174
+ event: "evaluation-failed",
175
+ phase: "rework",
176
+ sprintId: currentContract.id,
177
+ details: { iteration, feedback: evaluation.summary },
178
+ });
179
+ if (iteration >= maxIterations) {
180
+ logger.error(`Sprint ${currentContract.id} exceeded max iterations (${maxIterations}).`);
181
+ currentContract = updateContractStatus(currentContract, "needs-rework");
182
+ await updateContract(projectRoot, currentContract);
183
+ return { contract: currentContract, evaluation };
184
+ }
185
+ logger.info("Feeding evaluation feedback into next iteration...");
186
+ }
187
+ // Should not normally reach here
188
+ return { contract: currentContract, evaluation: lastEvaluation };
189
+ }
190
+ // ── Main pipeline ──────────────────────────────────────────────────
191
+ /**
192
+ * Run the complete orchestration pipeline:
193
+ *
194
+ * 1. **Plan** — Call the planner agent to produce a PlanSpec
195
+ * 2. **Sprint loop** — For each feature, create sprint contracts and
196
+ * run the generate-evaluate-iterate cycle
197
+ * 3. **Result** — Return aggregated results
198
+ *
199
+ * Each agent invocation is a FRESH call (new message thread). Context
200
+ * is carried via the ContextHandoff document.
201
+ */
202
+ export async function runPipeline(userPrompt, projectRoot, config) {
203
+ const startTime = Date.now();
204
+ const cleanup = setupInterruptHandler();
205
+ try {
206
+ // Ensure .bober/ directory structure exists
207
+ await ensureBoberDir(projectRoot);
208
+ await appendHistory(projectRoot, {
209
+ timestamp: new Date().toISOString(),
210
+ event: "pipeline-start",
211
+ phase: "init",
212
+ details: { userPrompt: userPrompt.slice(0, 200) },
213
+ });
214
+ // ── Phase 1: Planning ────────────────────────────────────────
215
+ const spec = await runPlanner(userPrompt, projectRoot, config);
216
+ logger.info(`Plan: "${spec.title}" with ${spec.features.length} features`);
217
+ await appendHistory(projectRoot, {
218
+ timestamp: new Date().toISOString(),
219
+ event: "planning-complete",
220
+ phase: "planning",
221
+ details: {
222
+ specId: spec.id,
223
+ featureCount: spec.features.length,
224
+ },
225
+ });
226
+ // ── Phase 2: Sprint loop ─────────────────────────────────────
227
+ logger.phase("Sprint Execution");
228
+ // Create sprint contracts from features
229
+ const contracts = [];
230
+ for (const feature of spec.features) {
231
+ const contract = createContract(feature.title, feature.description, feature.acceptanceCriteria.map((ac, idx) => ({
232
+ id: `${feature.id}-criterion-${idx + 1}`,
233
+ description: ac,
234
+ verificationMethod: "agent-evaluation",
235
+ })));
236
+ contracts.push(contract);
237
+ await saveContract(projectRoot, contract);
238
+ }
239
+ const completedSprints = [];
240
+ const failedSprints = [];
241
+ const projectContext = await buildProjectContext(projectRoot, config);
242
+ const maxSprints = Math.min(contracts.length, config.sprint.maxSprints);
243
+ for (let i = 0; i < maxSprints; i++) {
244
+ if (interrupted) {
245
+ logger.warn("Pipeline interrupted by user.");
246
+ break;
247
+ }
248
+ const contract = contracts[i];
249
+ logger.progress(i + 1, maxSprints, contract.feature);
250
+ const result = await runSprintCycle(contract, spec, completedSprints, projectRoot, config, projectContext);
251
+ if (result.contract.status === "passed") {
252
+ completedSprints.push(result.contract);
253
+ }
254
+ else {
255
+ failedSprints.push(result.contract);
256
+ // Check if we should continue after failure
257
+ if (config.sprint.requireContracts &&
258
+ result.contract.status !== "needs-rework") {
259
+ logger.error(`Sprint ${result.contract.id} failed and contracts are required. Stopping pipeline.`);
260
+ break;
261
+ }
262
+ }
263
+ }
264
+ // ── Phase 3: Results ─────────────────────────────────────────
265
+ logger.phase("Pipeline Complete");
266
+ const duration = Date.now() - startTime;
267
+ const success = failedSprints.length === 0 && completedSprints.length > 0;
268
+ await appendHistory(projectRoot, {
269
+ timestamp: new Date().toISOString(),
270
+ event: "pipeline-complete",
271
+ phase: success ? "complete" : "failed",
272
+ details: {
273
+ completed: completedSprints.length,
274
+ failed: failedSprints.length,
275
+ durationMs: duration,
276
+ },
277
+ });
278
+ return {
279
+ success,
280
+ spec,
281
+ completedSprints,
282
+ failedSprints,
283
+ duration,
284
+ };
285
+ }
286
+ finally {
287
+ cleanup();
288
+ }
289
+ }
290
+ //# sourceMappingURL=pipeline.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pipeline.js","sourceRoot":"","sources":["../../src/orchestrator/pipeline.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import type { BoberConfig } from "../config/schema.js";
2
+ import type { PlanSpec } from "../contracts/spec.js";
3
+ /**
4
+ * Run the planner agent to produce a PlanSpec from a user prompt.
5
+ *
6
+ * Uses the Anthropic SDK to create a single-turn message with the
7
+ * planner system prompt and project context.
8
+ */
9
+ export declare function runPlanner(userPrompt: string, projectRoot: string, config: BoberConfig): Promise<PlanSpec>;
10
+ //# sourceMappingURL=planner-agent.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"planner-agent.d.ts","sourceRoot":"","sources":["../../src/orchestrator/planner-agent.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AA0GrD;;;;;GAKG;AACH,wBAAsB,UAAU,CAC9B,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,WAAW,GAClB,OAAO,CAAC,QAAQ,CAAC,CAkDnB"}
@@ -0,0 +1,187 @@
1
+ import Anthropic from "@anthropic-ai/sdk";
2
+ import { readFile } from "node:fs/promises";
3
+ import { join } from "node:path";
4
+ import { PlanSpecSchema } from "../contracts/spec.js";
5
+ import { saveSpec } from "../state/index.js";
6
+ import { fileExists } from "../utils/fs.js";
7
+ import { logger } from "../utils/logger.js";
8
+ // ── Model mapping ──────────────────────────────────────────────────
9
+ function resolveModel(choice) {
10
+ switch (choice) {
11
+ case "opus":
12
+ return "claude-sonnet-4-20250514";
13
+ case "sonnet":
14
+ return "claude-sonnet-4-20250514";
15
+ case "haiku":
16
+ return "claude-haiku-4-20250414";
17
+ default:
18
+ return "claude-sonnet-4-20250514";
19
+ }
20
+ }
21
+ // ── System prompt ──────────────────────────────────────────────────
22
+ const PLANNER_SYSTEM_PROMPT = `You are the Bober Planner agent. Your job is to take a user's project description and produce a detailed plan specification (PlanSpec) as JSON.
23
+
24
+ You must output ONLY valid JSON matching this schema:
25
+ {
26
+ "id": "spec-<timestamp>",
27
+ "title": "Short plan title",
28
+ "description": "Detailed description of what will be built",
29
+ "projectType": "<mode>[ / <preset>]",
30
+ "techStack": ["list", "of", "technologies"],
31
+ "features": [
32
+ {
33
+ "id": "feature-1",
34
+ "title": "Feature title",
35
+ "description": "What this feature does",
36
+ "priority": "must" | "should" | "could",
37
+ "estimatedSprints": 1,
38
+ "acceptanceCriteria": ["Criterion 1", "Criterion 2"]
39
+ }
40
+ ],
41
+ "nonFunctional": ["NFR 1", "NFR 2"],
42
+ "constraints": ["Constraint 1"],
43
+ "createdAt": "<ISO datetime>",
44
+ "updatedAt": "<ISO datetime>"
45
+ }
46
+
47
+ Guidelines:
48
+ - Break the project into small, independently testable features.
49
+ - Each feature should be completable in 1-3 sprints.
50
+ - Order features by dependency — foundational features first.
51
+ - "must" priority features are the MVP. "should" are important. "could" are nice-to-have.
52
+ - Acceptance criteria must be specific and verifiable.
53
+ - Consider the project's existing tech stack and configuration.
54
+ - Keep sprint sizes reasonable — each sprint should produce a working increment.
55
+
56
+ Output ONLY the JSON object. No markdown fences, no explanation, just the JSON.`;
57
+ // ── Context gathering ──────────────────────────────────────────────
58
+ async function gatherProjectContext(projectRoot, config) {
59
+ const sections = [];
60
+ // Package.json
61
+ const pkgPath = join(projectRoot, "package.json");
62
+ if (await fileExists(pkgPath)) {
63
+ const content = await readFile(pkgPath, "utf-8");
64
+ sections.push(`## package.json\n\`\`\`json\n${content}\n\`\`\``);
65
+ }
66
+ // CLAUDE.md
67
+ const claudeMdPath = join(projectRoot, "CLAUDE.md");
68
+ if (await fileExists(claudeMdPath)) {
69
+ const content = await readFile(claudeMdPath, "utf-8");
70
+ sections.push(`## CLAUDE.md\n${content}`);
71
+ }
72
+ // bober.config.json
73
+ sections.push(`## bober.config.json\n\`\`\`json\n${JSON.stringify(config, null, 2)}\n\`\`\``);
74
+ // Additional context files from config
75
+ if (config.planner.contextFiles) {
76
+ for (const relPath of config.planner.contextFiles) {
77
+ const fullPath = join(projectRoot, relPath);
78
+ if (await fileExists(fullPath)) {
79
+ try {
80
+ const content = await readFile(fullPath, "utf-8");
81
+ sections.push(`## ${relPath}\n\`\`\`\n${content}\n\`\`\``);
82
+ }
83
+ catch {
84
+ // Skip unreadable files
85
+ }
86
+ }
87
+ }
88
+ }
89
+ return sections.join("\n\n");
90
+ }
91
+ // ── Main ───────────────────────────────────────────────────────────
92
+ /**
93
+ * Run the planner agent to produce a PlanSpec from a user prompt.
94
+ *
95
+ * Uses the Anthropic SDK to create a single-turn message with the
96
+ * planner system prompt and project context.
97
+ */
98
+ export async function runPlanner(userPrompt, projectRoot, config) {
99
+ logger.phase("Planning Phase");
100
+ logger.info("Gathering project context...");
101
+ const context = await gatherProjectContext(projectRoot, config);
102
+ const model = resolveModel(config.planner.model);
103
+ const client = new Anthropic();
104
+ const userMessage = `# Task Description
105
+ ${userPrompt}
106
+
107
+ # Project Context
108
+ ${context}
109
+
110
+ Produce a PlanSpec JSON for this project. Remember: output ONLY valid JSON, no markdown fences.`;
111
+ logger.info(`Calling planner model (${config.planner.model})...`);
112
+ logger.debug(`Using model: ${model}`);
113
+ const response = await client.messages.create({
114
+ model,
115
+ max_tokens: 8192,
116
+ system: PLANNER_SYSTEM_PROMPT,
117
+ messages: [
118
+ {
119
+ role: "user",
120
+ content: userMessage,
121
+ },
122
+ ],
123
+ });
124
+ // Extract text content from the response
125
+ let responseText = "";
126
+ for (const block of response.content) {
127
+ if (block.type === "text") {
128
+ responseText += block.text;
129
+ }
130
+ }
131
+ logger.debug("Raw planner response received, parsing...");
132
+ // Try to extract JSON from the response
133
+ const spec = parsePlanSpec(responseText);
134
+ // Save to .bober/specs/
135
+ await saveSpec(projectRoot, spec);
136
+ logger.success(`Plan saved: ${spec.title} (${spec.features.length} features)`);
137
+ return spec;
138
+ }
139
+ /**
140
+ * Parse the planner response text into a validated PlanSpec.
141
+ */
142
+ function parsePlanSpec(text) {
143
+ // Try direct parse first
144
+ let parsed;
145
+ try {
146
+ parsed = JSON.parse(text.trim());
147
+ }
148
+ catch {
149
+ // Try extracting JSON from markdown code fences
150
+ const fenceMatch = /```(?:json)?\s*\n?([\s\S]*?)\n?\s*```/.exec(text);
151
+ if (fenceMatch) {
152
+ try {
153
+ parsed = JSON.parse(fenceMatch[1].trim());
154
+ }
155
+ catch {
156
+ // Fall through to error
157
+ }
158
+ }
159
+ // Try finding the first { ... } block
160
+ if (!parsed) {
161
+ const braceStart = text.indexOf("{");
162
+ const braceEnd = text.lastIndexOf("}");
163
+ if (braceStart !== -1 && braceEnd > braceStart) {
164
+ try {
165
+ parsed = JSON.parse(text.slice(braceStart, braceEnd + 1));
166
+ }
167
+ catch {
168
+ throw new Error("Failed to parse planner response as JSON. Raw response:\n" +
169
+ text.slice(0, 500));
170
+ }
171
+ }
172
+ else {
173
+ throw new Error("No JSON object found in planner response. Raw response:\n" +
174
+ text.slice(0, 500));
175
+ }
176
+ }
177
+ }
178
+ const result = PlanSpecSchema.safeParse(parsed);
179
+ if (!result.success) {
180
+ const issues = result.error.issues
181
+ .map((i) => ` - ${i.path.join(".")}: ${i.message}`)
182
+ .join("\n");
183
+ throw new Error(`Planner produced invalid PlanSpec:\n${issues}\n\nRaw:\n${JSON.stringify(parsed, null, 2).slice(0, 1000)}`);
184
+ }
185
+ return result.data;
186
+ }
187
+ //# sourceMappingURL=planner-agent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"planner-agent.js","sourceRoot":"","sources":["../../src/orchestrator/planner-agent.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Ensure a directory exists, creating it recursively if needed.
3
+ */
4
+ export declare function ensureDir(dirPath: string): Promise<void>;
5
+ //# sourceMappingURL=helpers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../src/state/helpers.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,wBAAsB,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE9D"}
@@ -0,0 +1,8 @@
1
+ import { mkdir } from "node:fs/promises";
2
+ /**
3
+ * Ensure a directory exists, creating it recursively if needed.
4
+ */
5
+ export async function ensureDir(dirPath) {
6
+ await mkdir(dirPath, { recursive: true });
7
+ }
8
+ //# sourceMappingURL=helpers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helpers.js","sourceRoot":"","sources":["../../src/state/helpers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAEzC;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,OAAe;IAC7C,MAAM,KAAK,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;AAC5C,CAAC"}
@@ -0,0 +1,39 @@
1
+ import { z } from "zod";
2
+ import type { SprintContract } from "../contracts/sprint-contract.js";
3
+ import type { PlanSpec } from "../contracts/spec.js";
4
+ export declare const PhaseSchema: z.ZodEnum<["init", "planning", "generating", "evaluating", "rework", "complete", "failed"]>;
5
+ export type Phase = z.infer<typeof PhaseSchema>;
6
+ export declare const HistoryEntrySchema: z.ZodObject<{
7
+ timestamp: z.ZodString;
8
+ event: z.ZodString;
9
+ phase: z.ZodEnum<["init", "planning", "generating", "evaluating", "rework", "complete", "failed"]>;
10
+ sprintId: z.ZodOptional<z.ZodString>;
11
+ details: z.ZodRecord<z.ZodString, z.ZodUnknown>;
12
+ }, "strip", z.ZodTypeAny, {
13
+ timestamp: string;
14
+ details: Record<string, unknown>;
15
+ event: string;
16
+ phase: "evaluating" | "failed" | "init" | "planning" | "generating" | "rework" | "complete";
17
+ sprintId?: string | undefined;
18
+ }, {
19
+ timestamp: string;
20
+ details: Record<string, unknown>;
21
+ event: string;
22
+ phase: "evaluating" | "failed" | "init" | "planning" | "generating" | "rework" | "complete";
23
+ sprintId?: string | undefined;
24
+ }>;
25
+ export type HistoryEntry = z.infer<typeof HistoryEntrySchema>;
26
+ /**
27
+ * Append a history entry to the JSONL log file.
28
+ */
29
+ export declare function appendHistory(projectRoot: string, entry: HistoryEntry): Promise<void>;
30
+ /**
31
+ * Load all history entries from the JSONL log.
32
+ * Skips malformed lines.
33
+ */
34
+ export declare function loadHistory(projectRoot: string): Promise<HistoryEntry[]>;
35
+ /**
36
+ * Update the human-readable progress.md file with current state.
37
+ */
38
+ export declare function updateProgress(projectRoot: string, contracts: SprintContract[], spec: PlanSpec | null): Promise<void>;
39
+ //# sourceMappingURL=history.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"history.d.ts","sourceRoot":"","sources":["../../src/state/history.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AACtE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAmBrD,eAAO,MAAM,WAAW,6FAQtB,CAAC;AACH,MAAM,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC,CAAC;AAEhD,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;EAM7B,CAAC;AACH,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAI9D;;GAEG;AACH,wBAAsB,aAAa,CACjC,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,YAAY,GAClB,OAAO,CAAC,IAAI,CAAC,CAcf;AAED;;;GAGG;AACH,wBAAsB,WAAW,CAC/B,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,YAAY,EAAE,CAAC,CAyBzB;AAID;;GAEG;AACH,wBAAsB,cAAc,CAClC,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,cAAc,EAAE,EAC3B,IAAI,EAAE,QAAQ,GAAG,IAAI,GACpB,OAAO,CAAC,IAAI,CAAC,CAqFf"}