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,280 @@
1
+ ---
2
+ name: bober.sprint
3
+ description: Execute the next pending sprint — negotiate contracts, run the Generator, evaluate output, and iterate until passing or exhausting retries.
4
+ argument-hint: "[sprint-number]"
5
+ ---
6
+
7
+ # bober.sprint — Sprint Execution Skill
8
+
9
+ You are running the **bober.sprint** skill. Your job is to execute a single sprint from an existing plan through the full Generator-Evaluator loop: negotiate the contract, generate the implementation, evaluate the output, and iterate until the sprint passes or retries are exhausted.
10
+
11
+ ## Prerequisites
12
+
13
+ Before starting, verify these exist:
14
+ - `bober.config.json` in the project root
15
+ - At least one PlanSpec in `.bober/specs/`
16
+ - At least one SprintContract in `.bober/contracts/`
17
+
18
+ If any are missing, tell the user to run `/bober:plan` first.
19
+
20
+ ## Step 1: Identify the Target Sprint
21
+
22
+ **If a sprint number was provided as an argument:**
23
+ - Load the most recent PlanSpec from `.bober/specs/` (sort by `createdAt` descending)
24
+ - Find the contract for that sprint number: `.bober/contracts/sprint-<specId>-<N>.json`
25
+ - Verify it exists and its status is `proposed`, `in-progress`, or `needs-rework`
26
+
27
+ **If no sprint number was provided:**
28
+ - Load the most recent PlanSpec
29
+ - Find the first sprint contract with status `proposed` or `needs-rework`
30
+ - If all sprints are `completed`, tell the user all sprints are done
31
+ - If a sprint is `in-progress`, resume it
32
+
33
+ **Validate dependencies:**
34
+ - Check that all sprints listed in `dependsOn` have status `completed`
35
+ - If any dependency is not complete, tell the user which sprints must be completed first
36
+
37
+ Read the identified contract and the parent PlanSpec.
38
+
39
+ ## Step 2: Contract Negotiation (if status is "proposed")
40
+
41
+ When a contract status is `proposed`, it has not yet been reviewed for executability. Run a brief negotiation phase:
42
+
43
+ 1. **Review the success criteria** in the contract. For each criterion, assess:
44
+ - Is the `verificationMethod` actually executable given the current project setup?
45
+ - Is the criterion specific enough that pass/fail is unambiguous?
46
+ - Can the Evaluator actually verify this criterion independently?
47
+
48
+ 2. **Review the evaluator strategies** in `bober.config.json`. For each strategy:
49
+ - Is the required tooling installed? (e.g., if `playwright` is a strategy, is Playwright installed?)
50
+ - Are the configured commands valid? (e.g., does `commands.test` actually run?)
51
+
52
+ 3. **Adjust if needed:**
53
+ - If a criterion is too vague, make it more specific
54
+ - If a verification method requires tooling that is not set up, either:
55
+ - Add a setup step to the sprint
56
+ - Change the verification method to something available
57
+ - Mark the criterion as `required: false` if it cannot be verified
58
+ - If the sprint scope is too large for the configured sprint size, flag this to the user
59
+
60
+ 4. **Update the contract** status to `in-progress` and save it back to `.bober/contracts/`
61
+
62
+ 5. **Append to `.bober/history.jsonl`:**
63
+ ```json
64
+ {"event":"sprint-started","contractId":"...","specId":"...","timestamp":"..."}
65
+ ```
66
+
67
+ ## Step 3: Create Context Handoff
68
+
69
+ Create a ContextHandoff document for the Generator. This document is the ONLY context the Generator receives -- it must be self-contained.
70
+
71
+ **ContextHandoff structure:**
72
+ ```json
73
+ {
74
+ "handoffId": "handoff-<contractId>-gen-<iteration>",
75
+ "type": "to-generator",
76
+ "contractId": "<contract ID>",
77
+ "specId": "<spec ID>",
78
+ "timestamp": "<ISO-8601>",
79
+ "iteration": 1,
80
+ "context": {
81
+ "projectOverview": "<Brief project description from PlanSpec>",
82
+ "completedSprints": [
83
+ {
84
+ "contractId": "<ID>",
85
+ "title": "<title>",
86
+ "summary": "<what was built>"
87
+ }
88
+ ],
89
+ "currentBranch": "<git branch name>",
90
+ "relevantFiles": [
91
+ "<key files the generator should read>"
92
+ ]
93
+ },
94
+ "contract": { "<full SprintContract object>" },
95
+ "config": {
96
+ "commands": { "<commands section from bober.config.json>" },
97
+ "generator": { "<generator section from bober.config.json>" }
98
+ },
99
+ "evaluatorFeedback": null
100
+ }
101
+ ```
102
+
103
+ Save the handoff to `.bober/handoffs/<handoffId>.json`.
104
+
105
+ **For retry iterations** (iteration > 1), include the evaluator's feedback:
106
+ ```json
107
+ {
108
+ "evaluatorFeedback": {
109
+ "evalId": "<ID of the failed evaluation>",
110
+ "failedCriteria": [
111
+ {
112
+ "criterionId": "sc-1-2",
113
+ "description": "<what failed>",
114
+ "feedback": "<evaluator's detailed feedback>",
115
+ "file": "<file path if applicable>",
116
+ "line": "<line number if applicable>"
117
+ }
118
+ ],
119
+ "regressions": ["<any regressions found>"],
120
+ "generatorFeedback": ["<structured feedback items>"]
121
+ }
122
+ }
123
+ ```
124
+
125
+ ## Step 4: Spawn the Generator
126
+
127
+ Invoke the `bober-generator` subagent with the handoff document.
128
+
129
+ **Before spawning:**
130
+ 1. Ensure the correct git branch exists and is checked out:
131
+ ```bash
132
+ git checkout -b bober/<feature-slug> 2>/dev/null || git checkout bober/<feature-slug>
133
+ ```
134
+ 2. If this is a retry, the Generator should be on the same branch with the previous attempt's code still present.
135
+
136
+ **Spawn the Generator:**
137
+ Use the `bober-generator` agent definition. Pass it the handoff file path.
138
+
139
+ **After the Generator completes:**
140
+ 1. Read the Generator's completion report
141
+ 2. Verify the Generator committed its changes (check `git log`)
142
+ 3. Proceed to evaluation
143
+
144
+ ## Step 5: Spawn the Evaluator
145
+
146
+ Create an Evaluator handoff document:
147
+
148
+ ```json
149
+ {
150
+ "handoffId": "handoff-<contractId>-eval-<iteration>",
151
+ "type": "to-evaluator",
152
+ "contractId": "<contract ID>",
153
+ "specId": "<spec ID>",
154
+ "timestamp": "<ISO-8601>",
155
+ "iteration": 1,
156
+ "context": {
157
+ "generatorReport": { "<Generator's completion report>" },
158
+ "changedFiles": ["<files the generator reports changing>"],
159
+ "branch": "<current branch>"
160
+ },
161
+ "contract": { "<full SprintContract object>" },
162
+ "config": {
163
+ "commands": { "<commands section from bober.config.json>" },
164
+ "evaluator": { "<evaluator section from bober.config.json>" }
165
+ }
166
+ }
167
+ ```
168
+
169
+ Save the handoff to `.bober/handoffs/<handoffId>.json`.
170
+
171
+ **Spawn the Evaluator:**
172
+ Use the `bober-evaluator` agent definition. Pass it the handoff file path.
173
+
174
+ **After the Evaluator completes:**
175
+ 1. Read the EvalResult
176
+ 2. Save the EvalResult to `.bober/eval-results/` if the evaluator could not (it lacks Write tools)
177
+ 3. Determine pass/fail
178
+
179
+ ## Step 6: Process Evaluation Result
180
+
181
+ ### If the sprint PASSES:
182
+
183
+ 1. **Update the contract status** to `completed`:
184
+ ```json
185
+ { "status": "completed", "completedAt": "<ISO-8601>" }
186
+ ```
187
+ Save to `.bober/contracts/<contractId>.json`
188
+
189
+ 2. **Update `.bober/progress.md`:**
190
+ Change the sprint's status from `[in-progress]` to `[completed]`
191
+
192
+ 3. **Append to `.bober/history.jsonl`:**
193
+ ```json
194
+ {"event":"sprint-completed","contractId":"...","specId":"...","iteration":N,"timestamp":"..."}
195
+ ```
196
+
197
+ 4. **Report success to the user:**
198
+ ```
199
+ Sprint <N> PASSED on iteration <M>.
200
+
201
+ Completed: <sprint title>
202
+ Key results:
203
+ - <criterion 1>: PASS
204
+ - <criterion 2>: PASS
205
+ ...
206
+
207
+ Next sprint: <next sprint title> (run /bober.sprint to continue)
208
+ ```
209
+
210
+ ### If the sprint FAILS and retries remain:
211
+
212
+ Check `evaluator.maxIterations` from `bober.config.json` (default: 3). If the current iteration is less than `maxIterations`:
213
+
214
+ 1. **Log the failure:**
215
+ ```json
216
+ {"event":"sprint-iteration-failed","contractId":"...","iteration":N,"failedCriteria":["sc-1-2"],"timestamp":"..."}
217
+ ```
218
+
219
+ 2. **Create a retry handoff** (go back to Step 3 with `iteration + 1` and include evaluator feedback)
220
+
221
+ 3. **Report the retry to the user:**
222
+ ```
223
+ Sprint <N> iteration <M> FAILED. <X> of <Y> criteria not met.
224
+ Retrying (iteration <M+1> of <maxIterations>)...
225
+
226
+ Failed criteria:
227
+ - <criterion>: <brief reason>
228
+ ```
229
+
230
+ 4. **Go to Step 4** (spawn Generator again with feedback)
231
+
232
+ ### If the sprint FAILS and no retries remain:
233
+
234
+ 1. **Update the contract status** to `needs-rework`:
235
+ ```json
236
+ { "status": "needs-rework", "lastEvalId": "<eval ID>" }
237
+ ```
238
+
239
+ 2. **Update `.bober/progress.md`:**
240
+ Change the sprint's status to `[needs-rework]`
241
+
242
+ 3. **Append to `.bober/history.jsonl`:**
243
+ ```json
244
+ {"event":"sprint-failed","contractId":"...","specId":"...","totalIterations":N,"timestamp":"..."}
245
+ ```
246
+
247
+ 4. **Report failure to the user with full context:**
248
+ ```
249
+ Sprint <N> FAILED after <maxIterations> iterations.
250
+
251
+ Contract: <contract title>
252
+ Failed criteria:
253
+ - <criterion>: <detailed failure description>
254
+
255
+ Last evaluator feedback:
256
+ <structured feedback>
257
+
258
+ Recommended actions:
259
+ - Review the failed criteria and evaluator feedback
260
+ - Consider simplifying the sprint scope
261
+ - Run /bober.sprint <N> to retry from scratch
262
+ - Run /bober.plan to revise the plan
263
+ ```
264
+
265
+ ## Step 7: Context Reset
266
+
267
+ After a sprint completes (pass or fail), manage context:
268
+
269
+ Read `pipeline.contextReset` from config:
270
+ - `always`: Context is fully reset between sprints. The next sprint starts fresh with only the handoff document.
271
+ - `on-threshold`: Context resets only if the conversation is getting long. Not applicable in single-sprint skill execution.
272
+ - `never`: Context carries forward. Not recommended.
273
+
274
+ ## Error Handling
275
+
276
+ - **Generator fails to produce any output:** Mark sprint as `needs-rework` with note "Generator produced no output"
277
+ - **Evaluator cannot run strategies:** Report which strategies failed to execute and why. If a required strategy cannot run, mark sprint as `needs-rework` with a configuration issue note.
278
+ - **Git conflicts:** Report the conflict to the user. Do not auto-resolve.
279
+ - **Build broken before sprint started:** Verify the build passes BEFORE starting the Generator. If the build is already broken, report this and do not proceed.
280
+ - **Missing dependencies:** If `npm install` or equivalent has not been run, run it before starting.
@@ -0,0 +1,251 @@
1
+ # SprintContract JSON Schema
2
+
3
+ This document defines the complete schema for SprintContract documents. Sprint contracts are the binding agreement between the Planner, Generator, and Evaluator for a single sprint.
4
+
5
+ ## Location
6
+
7
+ SprintContract files are stored at: `.bober/contracts/<contractId>.json`
8
+
9
+ ## Naming Convention
10
+
11
+ - `contractId` format: `sprint-<specId>-<sprint-number>`
12
+ - Example: `sprint-spec-20260326-user-auth-1`
13
+ - Sprint numbers are 1-indexed (first sprint is 1, not 0)
14
+
15
+ ## Full Schema
16
+
17
+ ```json
18
+ {
19
+ "contractId": "string (required)",
20
+ "specId": "string (required, references parent PlanSpec)",
21
+ "sprintNumber": "number (required, 1-indexed)",
22
+ "title": "string (required, concise sprint title)",
23
+ "description": "string (required, what this sprint delivers)",
24
+ "status": "string (required, one of: proposed, in-progress, completed, needs-rework)",
25
+ "createdAt": "string (required, ISO-8601)",
26
+ "updatedAt": "string (required, ISO-8601)",
27
+ "completedAt": "string (optional, ISO-8601, set when status becomes completed)",
28
+
29
+ "dependsOn": [
30
+ "string — contractId references for sprints that must complete before this one"
31
+ ],
32
+
33
+ "features": [
34
+ "string — featureId references from the parent PlanSpec"
35
+ ],
36
+
37
+ "successCriteria": [
38
+ {
39
+ "criterionId": "string (required, format: sc-<sprint>-<index>)",
40
+ "description": "string (required, specific testable criterion)",
41
+ "verificationMethod": "string (required, one of: manual, typecheck, lint, unit-test, playwright, api-check, build, custom)",
42
+ "required": "boolean (required, true = must pass for sprint to pass)",
43
+ "customCommand": "string (optional, command to run for custom verification)"
44
+ }
45
+ ],
46
+
47
+ "generatorNotes": "string (required, guidance for the Generator agent)",
48
+ "evaluatorNotes": "string (required, guidance for the Evaluator agent)",
49
+
50
+ "estimatedFiles": [
51
+ "string — file paths expected to be created or modified"
52
+ ],
53
+
54
+ "estimatedDuration": "string (required, one of: small, medium, large)",
55
+
56
+ "iterationHistory": [
57
+ {
58
+ "iteration": "number",
59
+ "evalId": "string — reference to EvalResult",
60
+ "result": "string (pass | fail)",
61
+ "timestamp": "string (ISO-8601)"
62
+ }
63
+ ],
64
+
65
+ "lastEvalId": "string (optional, reference to most recent EvalResult)"
66
+ }
67
+ ```
68
+
69
+ ## Field Descriptions
70
+
71
+ ### Core Fields
72
+
73
+ | Field | Description |
74
+ |-------|-------------|
75
+ | `contractId` | Unique identifier. Generated by the Planner. Never changes. |
76
+ | `specId` | Reference to the parent PlanSpec. Used to load broader context. |
77
+ | `sprintNumber` | Position in the sprint sequence. 1-indexed. |
78
+ | `title` | Concise description of what this sprint delivers. Should start with a verb: "Implement...", "Add...", "Create...". |
79
+ | `description` | 2-4 sentences describing the sprint's deliverables and scope. |
80
+ | `status` | Lifecycle state. See Status Transitions below. |
81
+
82
+ ### Status Transitions
83
+
84
+ ```
85
+ proposed → in-progress → completed
86
+
87
+ needs-rework → in-progress → completed
88
+ ```
89
+
90
+ - `proposed`: Created by the Planner. Not yet started or reviewed.
91
+ - `in-progress`: Contract negotiated and Generator is working on it.
92
+ - `completed`: All required success criteria passed evaluation.
93
+ - `needs-rework`: Failed evaluation after maximum iterations. Requires human intervention or plan revision.
94
+
95
+ ### Dependencies
96
+
97
+ | Field | Description |
98
+ |-------|-------------|
99
+ | `dependsOn` | Array of `contractId` values that must have status `completed` before this sprint can start. Empty array for the first sprint. |
100
+ | `features` | Array of `featureId` values from the parent PlanSpec that this sprint implements (partially or fully). |
101
+
102
+ ### Success Criteria
103
+
104
+ Each success criterion is a single testable statement that the Evaluator checks independently.
105
+
106
+ | Field | Description |
107
+ |-------|-------------|
108
+ | `criterionId` | Unique within the contract. Format: `sc-<sprintNumber>-<index>` (1-indexed). |
109
+ | `description` | Specific, testable criterion. Must describe observable behavior or measurable outcome. |
110
+ | `verificationMethod` | How the Evaluator should verify this criterion. |
111
+ | `required` | If `true`, this criterion MUST pass for the sprint to pass. If `false`, it is advisory. |
112
+ | `customCommand` | Only for `verificationMethod: "custom"`. The command the Evaluator should run. |
113
+
114
+ ### Verification Methods
115
+
116
+ | Method | What the Evaluator Does |
117
+ |--------|------------------------|
118
+ | `manual` | Reads source code and assesses whether the criterion is met based on code inspection and logic tracing. |
119
+ | `typecheck` | Runs the configured typecheck command. Criterion passes if zero type errors. |
120
+ | `lint` | Runs the configured lint command. Criterion passes if zero lint errors (warnings OK). |
121
+ | `unit-test` | Runs the configured test command. Criterion passes if all tests pass. |
122
+ | `playwright` | Runs Playwright E2E tests. Criterion passes if all relevant E2E tests pass. |
123
+ | `api-check` | Tests specific API endpoints using curl or similar. Criterion passes if responses match expectations. |
124
+ | `build` | Runs the configured build command. Criterion passes if build succeeds with exit code 0. |
125
+ | `custom` | Runs `customCommand` and interprets the result. Exit code 0 = pass. |
126
+
127
+ ### Agent Notes
128
+
129
+ | Field | Description |
130
+ |-------|-------------|
131
+ | `generatorNotes` | Free-form guidance for the Generator. Should include: key files to examine for patterns, known gotchas, suggested implementation order, references to similar existing code. |
132
+ | `evaluatorNotes` | Free-form guidance for the Evaluator. Should include: specific things to test, edge cases to check, how to verify UI criteria, expected API response shapes. |
133
+
134
+ ### Estimates
135
+
136
+ | Field | Description |
137
+ |-------|-------------|
138
+ | `estimatedFiles` | Array of file paths the Generator is expected to create or modify. This is advisory -- the Generator may touch additional files if needed. The Evaluator uses this to check for unexpected changes. |
139
+ | `estimatedDuration` | Relative size estimate: `small` (30-60 min), `medium` (1-3 hours), `large` (3-5 hours). |
140
+
141
+ ### Iteration History
142
+
143
+ | Field | Description |
144
+ |-------|-------------|
145
+ | `iterationHistory` | Array of past evaluation attempts. Appended after each evaluation. |
146
+ | `lastEvalId` | Reference to the most recent EvalResult. Updated after each evaluation. |
147
+
148
+ ## Complete Example
149
+
150
+ ```json
151
+ {
152
+ "contractId": "sprint-spec-20260326-user-auth-1",
153
+ "specId": "spec-20260326-user-auth",
154
+ "sprintNumber": 1,
155
+ "title": "Implement user registration with form and API",
156
+ "description": "Create the user registration flow end-to-end: a React registration form with email, password, and confirm-password fields; an Express API endpoint that validates input and creates a user record in PostgreSQL with a bcrypt-hashed password; and basic form validation on both client and server.",
157
+ "status": "proposed",
158
+ "createdAt": "2026-03-26T10:00:00Z",
159
+ "updatedAt": "2026-03-26T10:00:00Z",
160
+ "completedAt": null,
161
+
162
+ "dependsOn": [],
163
+
164
+ "features": ["feat-1"],
165
+
166
+ "successCriteria": [
167
+ {
168
+ "criterionId": "sc-1-1",
169
+ "description": "The project builds successfully with zero errors.",
170
+ "verificationMethod": "build",
171
+ "required": true
172
+ },
173
+ {
174
+ "criterionId": "sc-1-2",
175
+ "description": "TypeScript compilation produces zero type errors.",
176
+ "verificationMethod": "typecheck",
177
+ "required": true
178
+ },
179
+ {
180
+ "criterionId": "sc-1-3",
181
+ "description": "A registration form component exists at the /register route with email, password, and confirm-password input fields, each with an associated label.",
182
+ "verificationMethod": "manual",
183
+ "required": true
184
+ },
185
+ {
186
+ "criterionId": "sc-1-4",
187
+ "description": "POST /api/auth/register accepts { email, password } and returns 201 with { id, email } on success.",
188
+ "verificationMethod": "api-check",
189
+ "required": true
190
+ },
191
+ {
192
+ "criterionId": "sc-1-5",
193
+ "description": "POST /api/auth/register returns 400 with an error message when email is already registered.",
194
+ "verificationMethod": "api-check",
195
+ "required": true
196
+ },
197
+ {
198
+ "criterionId": "sc-1-6",
199
+ "description": "The password is stored as a bcrypt hash in the database, never in plain text.",
200
+ "verificationMethod": "manual",
201
+ "required": true
202
+ },
203
+ {
204
+ "criterionId": "sc-1-7",
205
+ "description": "Client-side validation shows an error when password is shorter than 8 characters before form submission.",
206
+ "verificationMethod": "manual",
207
+ "required": true
208
+ },
209
+ {
210
+ "criterionId": "sc-1-8",
211
+ "description": "ESLint reports zero errors on all new and modified files.",
212
+ "verificationMethod": "lint",
213
+ "required": false
214
+ }
215
+ ],
216
+
217
+ "generatorNotes": "Look at existing route definitions in src/routes/ for the Express routing pattern. The project uses Prisma -- check prisma/schema.prisma for the existing schema and add a User model. Use bcrypt (already in package.json) for password hashing. For the React form, follow the pattern in src/components/ -- the project uses controlled components with useState. The registration form should be at src/pages/Register.tsx and the route added to src/App.tsx.",
218
+
219
+ "evaluatorNotes": "For sc-1-3: Read the Register component source and verify it renders three labeled input fields. For sc-1-4 and sc-1-5: Start the dev server and use curl to test the endpoint. For sc-1-6: Read the route handler code and verify bcrypt.hash is called before database insertion. For sc-1-7: Read the form component code and verify client-side validation logic exists for password length.",
220
+
221
+ "estimatedFiles": [
222
+ "prisma/schema.prisma",
223
+ "src/routes/auth.ts",
224
+ "src/pages/Register.tsx",
225
+ "src/App.tsx"
226
+ ],
227
+
228
+ "estimatedDuration": "medium",
229
+
230
+ "iterationHistory": [],
231
+ "lastEvalId": null
232
+ }
233
+ ```
234
+
235
+ ## Writing Good Success Criteria
236
+
237
+ ### Do
238
+
239
+ - Start with an observable action or state: "The form displays...", "The API returns...", "The database contains..."
240
+ - Include specific values: "returns 201", "displays 'Invalid email'", "at least 8 characters"
241
+ - Map each criterion to exactly one verification method
242
+ - Include at least one `build` criterion and one functional criterion per sprint
243
+ - Write criteria the Evaluator can verify without guessing
244
+
245
+ ### Do Not
246
+
247
+ - Use subjective language: "looks good", "works well", "clean code"
248
+ - Combine multiple checks in one criterion (split them)
249
+ - Reference internal implementation details unless checking them IS the criterion
250
+ - Write criteria that require human visual judgment (unless verification method is `manual` and the check is code-inspectable)
251
+ - Assume the Evaluator has context beyond the contract and handoff documents
@@ -0,0 +1,20 @@
1
+ # Project Guide
2
+
3
+ ## Overview
4
+
5
+ This project uses the bober agent harness for autonomous development with Claude.
6
+
7
+ ## Getting Started
8
+
9
+ Check `bober.config.json` for the configured commands and evaluator strategies. Customize them for your stack.
10
+
11
+ ## Conventions
12
+
13
+ - Write clear, well-typed code.
14
+ - Include tests for new functionality.
15
+ - Keep changes focused and minimal per sprint.
16
+ - Follow the patterns established in the sprint contracts.
17
+
18
+ ## Commands
19
+
20
+ Update the `commands` section of `bober.config.json` with your project's build, test, lint, and dev commands.
@@ -0,0 +1,35 @@
1
+ {
2
+ "project": {
3
+ "name": "",
4
+ "mode": "greenfield",
5
+ "description": ""
6
+ },
7
+ "planner": {
8
+ "maxClarifications": 5,
9
+ "model": "opus"
10
+ },
11
+ "generator": {
12
+ "model": "sonnet",
13
+ "maxTurnsPerSprint": 50,
14
+ "autoCommit": true,
15
+ "branchPattern": "bober/{feature-name}"
16
+ },
17
+ "evaluator": {
18
+ "model": "sonnet",
19
+ "strategies": [
20
+ { "type": "build", "required": true }
21
+ ],
22
+ "maxIterations": 3
23
+ },
24
+ "sprint": {
25
+ "maxSprints": 10,
26
+ "requireContracts": true,
27
+ "sprintSize": "medium"
28
+ },
29
+ "pipeline": {
30
+ "maxIterations": 20,
31
+ "requireApproval": false,
32
+ "contextReset": "always"
33
+ },
34
+ "commands": {}
35
+ }
@@ -0,0 +1,34 @@
1
+ # Brownfield Project Guide
2
+
3
+ ## Working with Existing Code
4
+
5
+ This is a brownfield project. The codebase has existing patterns, conventions, and tests that must be respected.
6
+
7
+ ### Before Making Changes
8
+
9
+ 1. **Read first.** Before modifying any file, read the surrounding code to understand local conventions (naming, patterns, abstractions).
10
+ 2. **Run existing tests.** Execute the full test suite before starting work. Record the baseline pass/fail state so you can detect regressions.
11
+ 3. **Understand the dependency graph.** Check imports and exports to know what depends on the code you are changing.
12
+
13
+ ### While Making Changes
14
+
15
+ - **Follow existing patterns.** If the codebase uses a particular abstraction (e.g., repository pattern, custom hooks, service layer), use the same abstraction. Do not introduce competing patterns.
16
+ - **Match the style.** Match indentation, naming conventions, comment style, and file organization of the surrounding code. Consistency matters more than personal preference.
17
+ - **Minimal surface area.** Change only what is necessary to deliver the feature. Avoid drive-by refactors unless they are part of the sprint contract.
18
+ - **Preserve public APIs.** Do not change function signatures, type exports, or module interfaces unless the sprint contract explicitly requires it. Other code depends on them.
19
+ - **Add tests for new behavior.** Every new code path needs a corresponding test. Use the same test framework and patterns already in the project.
20
+
21
+ ### After Making Changes
22
+
23
+ 1. **Run the full test suite.** All previously passing tests must still pass.
24
+ 2. **Run the linter.** Zero new warnings or errors.
25
+ 3. **Run type checking.** Zero new type errors.
26
+ 4. **Review the diff.** The changeset should be focused and minimal. Remove accidental changes (whitespace, formatting, unrelated files).
27
+
28
+ ## Commands
29
+
30
+ Commands are auto-detected from the existing project. Check `bober.config.json` for the resolved command map, or inspect `package.json` / `Makefile` / `pyproject.toml` for the project's native commands.
31
+
32
+ ## Architecture
33
+
34
+ Refer to the project's own README, CLAUDE.md, or architecture docs for structural guidance. The bober planner will analyze the codebase during planning and encode relevant context into sprint contracts.
@@ -0,0 +1,37 @@
1
+ {
2
+ "project": {
3
+ "name": "",
4
+ "mode": "brownfield",
5
+ "description": "Existing codebase — conservative, incremental changes"
6
+ },
7
+ "planner": {
8
+ "maxClarifications": 5,
9
+ "model": "opus"
10
+ },
11
+ "generator": {
12
+ "model": "sonnet",
13
+ "maxTurnsPerSprint": 50,
14
+ "autoCommit": true,
15
+ "branchPattern": "bober/{feature-name}"
16
+ },
17
+ "evaluator": {
18
+ "model": "sonnet",
19
+ "strategies": [
20
+ { "type": "typecheck", "required": true },
21
+ { "type": "lint", "required": true },
22
+ { "type": "unit-test", "required": true }
23
+ ],
24
+ "maxIterations": 5
25
+ },
26
+ "sprint": {
27
+ "maxSprints": 10,
28
+ "requireContracts": true,
29
+ "sprintSize": "small"
30
+ },
31
+ "pipeline": {
32
+ "maxIterations": 15,
33
+ "requireApproval": true,
34
+ "contextReset": "always"
35
+ },
36
+ "commands": {}
37
+ }