agent-bober 0.11.6 → 0.12.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.
- package/CHANGELOG.md +98 -0
- package/README.md +12 -6
- package/agents/bober-evaluator.md +38 -0
- package/agents/bober-generator.md +54 -0
- package/agents/bober-planner.md +256 -34
- package/dist/cli/commands/eval.js +6 -6
- package/dist/cli/commands/eval.js.map +1 -1
- package/dist/cli/commands/init.js +46 -2
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/plan.d.ts +12 -0
- package/dist/cli/commands/plan.d.ts.map +1 -1
- package/dist/cli/commands/plan.js +232 -37
- package/dist/cli/commands/plan.js.map +1 -1
- package/dist/cli/commands/run.js +2 -2
- package/dist/cli/commands/run.js.map +1 -1
- package/dist/cli/commands/sprint.d.ts.map +1 -1
- package/dist/cli/commands/sprint.js +8 -8
- package/dist/cli/commands/sprint.js.map +1 -1
- package/dist/cli/index.js +23 -2
- package/dist/cli/index.js.map +1 -1
- package/dist/config/schema.d.ts +40 -40
- package/dist/contracts/eval-result.d.ts +38 -38
- package/dist/contracts/index.d.ts +2 -2
- package/dist/contracts/index.d.ts.map +1 -1
- package/dist/contracts/index.js +8 -4
- package/dist/contracts/index.js.map +1 -1
- package/dist/contracts/spec.d.ts +335 -40
- package/dist/contracts/spec.d.ts.map +1 -1
- package/dist/contracts/spec.js +210 -18
- package/dist/contracts/spec.js.map +1 -1
- package/dist/contracts/sprint-contract.d.ts +155 -88
- package/dist/contracts/sprint-contract.d.ts.map +1 -1
- package/dist/contracts/sprint-contract.js +176 -29
- package/dist/contracts/sprint-contract.js.map +1 -1
- package/dist/evaluators/builtin/api-check.js +1 -1
- package/dist/evaluators/builtin/api-check.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/mcp/tools/contracts.js +2 -2
- package/dist/mcp/tools/contracts.js.map +1 -1
- package/dist/mcp/tools/eval.js +8 -8
- package/dist/mcp/tools/eval.js.map +1 -1
- package/dist/mcp/tools/plan.d.ts.map +1 -1
- package/dist/mcp/tools/plan.js +40 -14
- package/dist/mcp/tools/plan.js.map +1 -1
- package/dist/mcp/tools/sprint.d.ts.map +1 -1
- package/dist/mcp/tools/sprint.js +11 -11
- package/dist/mcp/tools/sprint.js.map +1 -1
- package/dist/orchestrator/context-handoff.d.ts +484 -224
- package/dist/orchestrator/context-handoff.d.ts.map +1 -1
- package/dist/orchestrator/context-handoff.js +32 -12
- package/dist/orchestrator/context-handoff.js.map +1 -1
- package/dist/orchestrator/curator-agent.d.ts.map +1 -1
- package/dist/orchestrator/curator-agent.js +4 -4
- package/dist/orchestrator/curator-agent.js.map +1 -1
- package/dist/orchestrator/evaluator-agent.js +2 -2
- package/dist/orchestrator/evaluator-agent.js.map +1 -1
- package/dist/orchestrator/generator-agent.js +3 -3
- package/dist/orchestrator/generator-agent.js.map +1 -1
- package/dist/orchestrator/model-resolver.js +2 -2
- package/dist/orchestrator/model-resolver.js.map +1 -1
- package/dist/orchestrator/pipeline.d.ts +7 -0
- package/dist/orchestrator/pipeline.d.ts.map +1 -1
- package/dist/orchestrator/pipeline.js +67 -28
- package/dist/orchestrator/pipeline.js.map +1 -1
- package/dist/orchestrator/planner-agent.d.ts +21 -1
- package/dist/orchestrator/planner-agent.d.ts.map +1 -1
- package/dist/orchestrator/planner-agent.js +11 -2
- package/dist/orchestrator/planner-agent.js.map +1 -1
- package/dist/state/history.d.ts.map +1 -1
- package/dist/state/history.js +3 -3
- package/dist/state/history.js.map +1 -1
- package/dist/state/plan-state.js +1 -1
- package/dist/state/plan-state.js.map +1 -1
- package/dist/state/sprint-state.d.ts +9 -2
- package/dist/state/sprint-state.d.ts.map +1 -1
- package/dist/state/sprint-state.js +25 -11
- package/dist/state/sprint-state.js.map +1 -1
- package/package.json +2 -1
- package/scripts/migrate-specs.mjs +127 -0
- package/scripts/sync-skills.mjs +96 -0
- package/skills/bober.plan/SKILL.md +41 -0
- package/skills/bober.plan/references/spec-schema.md +31 -4
- package/skills/bober.run/SKILL.md +41 -7
- package/skills/bober.sprint/SKILL.md +6 -259
|
@@ -24,10 +24,34 @@ PlanSpec files are stored at: `.bober/specs/<specId>.json`
|
|
|
24
24
|
"description": "string (required, 2-3 sentences)",
|
|
25
25
|
"mode": "string (required, one of: greenfield, brownfield)",
|
|
26
26
|
"preset": "string (optional, e.g.: nextjs, react-vite, solidity, anchor, api-node, python-api)",
|
|
27
|
-
"status": "string (required, one of:
|
|
27
|
+
"status": "string (required, one of: draft, needs-clarification, ready, in-progress, completed, abandoned)",
|
|
28
|
+
|
|
29
|
+
"ambiguityScore": "number (optional, 0-10) — planner's self-rated ambiguity. >= 7 forces status='needs-clarification'.",
|
|
30
|
+
|
|
31
|
+
"clarificationQuestions": [
|
|
32
|
+
{
|
|
33
|
+
"questionId": "string (required, e.g. 'Q1')",
|
|
34
|
+
"category": "string (required, one of: scope | user-personas | data-model | tech-constraints | design-ux | integrations | non-functional | error-handling | integration-risk | pattern-conflict | regression-risk | other)",
|
|
35
|
+
"question": "string (required, ends in '?')",
|
|
36
|
+
"options": [
|
|
37
|
+
{ "label": "string (e.g. 'A')", "description": "string" }
|
|
38
|
+
],
|
|
39
|
+
"recommendation": "string (optional, planner's suggested answer based on codebase evidence)",
|
|
40
|
+
"ambiguityWeight": "number (optional, 0-10, how much this question contributes to overall ambiguity)"
|
|
41
|
+
}
|
|
42
|
+
],
|
|
43
|
+
|
|
44
|
+
"resolvedClarifications": [
|
|
45
|
+
{
|
|
46
|
+
"questionId": "string (required, matches a clarificationQuestions entry)",
|
|
47
|
+
"answer": "string (required, free-form)",
|
|
48
|
+
"resolvedAt": "string (required, ISO-8601)",
|
|
49
|
+
"resolvedBy": "string (required, one of: user | planner)"
|
|
50
|
+
}
|
|
51
|
+
],
|
|
28
52
|
|
|
29
53
|
"assumptions": [
|
|
30
|
-
"string — each assumption the planner is making"
|
|
54
|
+
"string — each assumption the planner is making, ideally with codebase evidence"
|
|
31
55
|
],
|
|
32
56
|
|
|
33
57
|
"outOfScope": [
|
|
@@ -90,7 +114,10 @@ PlanSpec files are stored at: `.bober/specs/<specId>.json`
|
|
|
90
114
|
| `description` | 2-3 sentence summary of the feature and its user value. |
|
|
91
115
|
| `mode` | Must match the `project.mode` in `bober.config.json` (`greenfield` or `brownfield`). |
|
|
92
116
|
| `preset` | Must match the `project.preset` in `bober.config.json`, if set (e.g., `nextjs`, `solidity`, `anchor`). |
|
|
93
|
-
| `status` | Lifecycle state
|
|
117
|
+
| `status` | Lifecycle state. `draft`: planner emitted a complete plan, no sprints run yet. `needs-clarification`: planner refused to fully decompose; user must answer the open `clarificationQuestions` before sprints can run. `ready`: clarifications resolved, pipeline may proceed. `in-progress`: at least one sprint has started. `completed`: all sprints done. `abandoned`: planner or user dropped this spec. |
|
|
118
|
+
| `ambiguityScore` | Planner's self-rating 0-10. If `>= 7`, the planner MUST set `status: "needs-clarification"` and emit at least one `clarificationQuestions` entry — the pipeline will refuse to run sprints from such a spec. |
|
|
119
|
+
| `clarificationQuestions` | Open questions awaiting user answers. Each unresolved entry blocks sprint execution. |
|
|
120
|
+
| `resolvedClarifications` | Question/answer history (both autonomous self-answers and user inputs via `bober plan answer`). |
|
|
94
121
|
|
|
95
122
|
### Features Array
|
|
96
123
|
|
|
@@ -155,7 +182,7 @@ Bad criteria:
|
|
|
155
182
|
"description": "A complete user authentication system supporting email/password registration and login, with session management and protected routes. This enables the application to identify users and restrict access to authorized content.",
|
|
156
183
|
"mode": "greenfield",
|
|
157
184
|
"preset": "react-vite",
|
|
158
|
-
"status": "
|
|
185
|
+
"status": "draft",
|
|
159
186
|
"assumptions": [
|
|
160
187
|
"The application does not currently have any authentication system",
|
|
161
188
|
"PostgreSQL is the database, as configured in the project",
|
|
@@ -91,9 +91,18 @@ If it fails, report the missing prerequisites and stop.
|
|
|
91
91
|
|
|
92
92
|
### 1c. Check for Existing Plans
|
|
93
93
|
|
|
94
|
-
List all spec files in `.bober/specs/`. For each spec, read only the **first
|
|
94
|
+
List all spec files in `.bober/specs/`. For each spec, read only the **first 10 lines** of the JSON file. The `status` field is near the top — apply the following triage:
|
|
95
95
|
|
|
96
|
-
|
|
96
|
+
- `"completed"` or `"abandoned"` → skip entirely (do not load its contracts).
|
|
97
|
+
- `"needs-clarification"` → **BLOCK and surface to user.** Read the spec's `clarificationQuestions` array and print each one with its category, options, and recommendation. Tell the user to resolve via:
|
|
98
|
+
- `npx agent-bober plan answer <specId>` (interactive walkthrough), or
|
|
99
|
+
- `npx agent-bober plan answer <specId> <questionId> "<answer>"` (one-shot per question), or
|
|
100
|
+
- Edit `.bober/specs/<specId>.json` directly and flip `status` to `"ready"` after answering.
|
|
101
|
+
|
|
102
|
+
Do NOT include this spec in the actionable set. Do NOT proceed past the planning phase if this is the only spec — the user must answer first.
|
|
103
|
+
- `"draft"`, `"ready"`, `"in-progress"` → this is an **actionable spec**, collect it.
|
|
104
|
+
|
|
105
|
+
Collect only the actionable specs.
|
|
97
106
|
|
|
98
107
|
- **No actionable specs + user provided a new task:** Create a new plan (go to Step 2).
|
|
99
108
|
- **No actionable specs + no task provided:** Tell the user all plans are complete. Stop.
|
|
@@ -166,10 +175,34 @@ When done, respond with EXACTLY this JSON structure (no other text):
|
|
|
166
175
|
|
|
167
176
|
**After the planner subagent returns:**
|
|
168
177
|
|
|
169
|
-
1. Parse the planner's response
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
178
|
+
1. Parse the planner's response. Inspect the `status` field FIRST.
|
|
179
|
+
|
|
180
|
+
2. **If `status` is `"needs-clarification"`:** The planner refused to fully decompose the request. STOP the pipeline. Read `.bober/specs/<specId>.json` and print the open `clarificationQuestions` to the user:
|
|
181
|
+
|
|
182
|
+
```
|
|
183
|
+
=== PLAN BLOCKED — NEEDS CLARIFICATION ===
|
|
184
|
+
Spec: <specId>
|
|
185
|
+
Title: <title>
|
|
186
|
+
Ambiguity score: <N>/10
|
|
187
|
+
|
|
188
|
+
Open questions:
|
|
189
|
+
Q1 [<category>]: <question>
|
|
190
|
+
A) <option> — <description>
|
|
191
|
+
B) <option> — <description>
|
|
192
|
+
💡 Suggested: <recommendation if any>
|
|
193
|
+
Q2 [<category>]: <question>
|
|
194
|
+
...
|
|
195
|
+
|
|
196
|
+
Resolve via either:
|
|
197
|
+
npx agent-bober plan answer <specId> (interactive)
|
|
198
|
+
npx agent-bober plan answer <specId> Q1 "<your answer>" (one-shot)
|
|
199
|
+
Or edit .bober/specs/<specId>.json directly and flip status to "ready".
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
Do NOT proceed to Step 3. Do NOT spawn the generator subagent. The user must resolve the questions before the pipeline can continue. Exit cleanly.
|
|
203
|
+
|
|
204
|
+
3. **If `status` is `"draft"` or `"ready"`:** Extract `specId` and `contractIds`. Read `.bober/specs/<specId>.json` to verify it was created. Read each contract file in `.bober/contracts/` to verify they exist. Print the plan summary:
|
|
205
|
+
|
|
173
206
|
```
|
|
174
207
|
=== PLAN CREATED ===
|
|
175
208
|
Spec: <specId>
|
|
@@ -179,7 +212,8 @@ When done, respond with EXACTLY this JSON structure (no other text):
|
|
|
179
212
|
2. <Sprint 2 title>
|
|
180
213
|
...
|
|
181
214
|
```
|
|
182
|
-
|
|
215
|
+
|
|
216
|
+
4. If the planner subagent failed or returned an error, report it and stop the pipeline.
|
|
183
217
|
|
|
184
218
|
---
|
|
185
219
|
|
|
@@ -30,9 +30,13 @@ Also read `.bober/principles.md` if it exists. You will include the principles t
|
|
|
30
30
|
|
|
31
31
|
## Step 1: Identify the Target Sprint
|
|
32
32
|
|
|
33
|
-
**Find the active PlanSpec.** List all specs in `.bober/specs/`. For each spec, read only the **first
|
|
33
|
+
**Find the active PlanSpec.** List all specs in `.bober/specs/`. For each spec, read only the **first 10 lines** — the `status` field is near the top. Apply this triage:
|
|
34
34
|
|
|
35
|
-
|
|
35
|
+
- `"completed"` or `"abandoned"` → skip entirely.
|
|
36
|
+
- `"needs-clarification"` → BLOCK this spec from sprint execution. Print the open `clarificationQuestions` from the spec and tell the user to resolve via `npx agent-bober plan answer <specId>` (interactive) or `npx agent-bober plan answer <specId> <questionId> "<answer>"` (one-shot). Do NOT spawn the generator. Do NOT pick this spec as the active one. If it's the only spec, exit.
|
|
37
|
+
- `"draft"`, `"ready"`, `"in-progress"` → eligible. From the eligible specs, pick the most recent one (sort by `createdAt` descending).
|
|
38
|
+
|
|
39
|
+
If all specs are `completed`/`abandoned` and no sprint number was provided, tell the user all plans are complete. If the only remaining spec is `needs-clarification`, exit with the clarification message.
|
|
36
40
|
|
|
37
41
|
**If a sprint number was provided as an argument:**
|
|
38
42
|
- Find the contract for that sprint number: `.bober/contracts/sprint-<specId>-<N>.json`
|
|
@@ -463,260 +467,3 @@ Read `pipeline.contextReset` from config:
|
|
|
463
467
|
After completing this phase, suggest the following next steps to the user:
|
|
464
468
|
- `/bober-eval` — Evaluate the current sprint output independently
|
|
465
469
|
- `/bober-sprint` — Execute the next sprint in the plan
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
---
|
|
469
|
-
|
|
470
|
-
<!-- Reference: contract-schema.md -->
|
|
471
|
-
|
|
472
|
-
# SprintContract JSON Schema
|
|
473
|
-
|
|
474
|
-
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.
|
|
475
|
-
|
|
476
|
-
## Location
|
|
477
|
-
|
|
478
|
-
SprintContract files are stored at: `.bober/contracts/<contractId>.json`
|
|
479
|
-
|
|
480
|
-
## Naming Convention
|
|
481
|
-
|
|
482
|
-
- `contractId` format: `sprint-<specId>-<sprint-number>`
|
|
483
|
-
- Example: `sprint-spec-20260326-user-auth-1`
|
|
484
|
-
- Sprint numbers are 1-indexed (first sprint is 1, not 0)
|
|
485
|
-
|
|
486
|
-
## Full Schema
|
|
487
|
-
|
|
488
|
-
```json
|
|
489
|
-
{
|
|
490
|
-
"contractId": "string (required)",
|
|
491
|
-
"specId": "string (required, references parent PlanSpec)",
|
|
492
|
-
"sprintNumber": "number (required, 1-indexed)",
|
|
493
|
-
"title": "string (required, concise sprint title)",
|
|
494
|
-
"description": "string (required, what this sprint delivers)",
|
|
495
|
-
"status": "string (required, one of: proposed, in-progress, completed, needs-rework)",
|
|
496
|
-
"createdAt": "string (required, ISO-8601)",
|
|
497
|
-
"updatedAt": "string (required, ISO-8601)",
|
|
498
|
-
"completedAt": "string (optional, ISO-8601, set when status becomes completed)",
|
|
499
|
-
|
|
500
|
-
"dependsOn": [
|
|
501
|
-
"string — contractId references for sprints that must complete before this one"
|
|
502
|
-
],
|
|
503
|
-
|
|
504
|
-
"features": [
|
|
505
|
-
"string — featureId references from the parent PlanSpec"
|
|
506
|
-
],
|
|
507
|
-
|
|
508
|
-
"successCriteria": [
|
|
509
|
-
{
|
|
510
|
-
"criterionId": "string (required, format: sc-<sprint>-<index>)",
|
|
511
|
-
"description": "string (required, specific testable criterion)",
|
|
512
|
-
"verificationMethod": "string (required, one of: manual, typecheck, lint, unit-test, playwright, api-check, build, custom)",
|
|
513
|
-
"required": "boolean (required, true = must pass for sprint to pass)",
|
|
514
|
-
"customCommand": "string (optional, command to run for custom verification)"
|
|
515
|
-
}
|
|
516
|
-
],
|
|
517
|
-
|
|
518
|
-
"generatorNotes": "string (required, guidance for the Generator agent)",
|
|
519
|
-
"evaluatorNotes": "string (required, guidance for the Evaluator agent)",
|
|
520
|
-
|
|
521
|
-
"estimatedFiles": [
|
|
522
|
-
"string — file paths expected to be created or modified"
|
|
523
|
-
],
|
|
524
|
-
|
|
525
|
-
"estimatedDuration": "string (required, one of: small, medium, large)",
|
|
526
|
-
|
|
527
|
-
"iterationHistory": [
|
|
528
|
-
{
|
|
529
|
-
"iteration": "number",
|
|
530
|
-
"evalId": "string — reference to EvalResult",
|
|
531
|
-
"result": "string (pass | fail)",
|
|
532
|
-
"timestamp": "string (ISO-8601)"
|
|
533
|
-
}
|
|
534
|
-
],
|
|
535
|
-
|
|
536
|
-
"lastEvalId": "string (optional, reference to most recent EvalResult)"
|
|
537
|
-
}
|
|
538
|
-
```
|
|
539
|
-
|
|
540
|
-
## Field Descriptions
|
|
541
|
-
|
|
542
|
-
### Core Fields
|
|
543
|
-
|
|
544
|
-
| Field | Description |
|
|
545
|
-
|-------|-------------|
|
|
546
|
-
| `contractId` | Unique identifier. Generated by the Planner. Never changes. |
|
|
547
|
-
| `specId` | Reference to the parent PlanSpec. Used to load broader context. |
|
|
548
|
-
| `sprintNumber` | Position in the sprint sequence. 1-indexed. |
|
|
549
|
-
| `title` | Concise description of what this sprint delivers. Should start with a verb: "Implement...", "Add...", "Create...". |
|
|
550
|
-
| `description` | 2-4 sentences describing the sprint's deliverables and scope. |
|
|
551
|
-
| `status` | Lifecycle state. See Status Transitions below. |
|
|
552
|
-
|
|
553
|
-
### Status Transitions
|
|
554
|
-
|
|
555
|
-
```
|
|
556
|
-
proposed → in-progress → completed
|
|
557
|
-
↓
|
|
558
|
-
needs-rework → in-progress → completed
|
|
559
|
-
```
|
|
560
|
-
|
|
561
|
-
- `proposed`: Created by the Planner. Not yet started or reviewed.
|
|
562
|
-
- `in-progress`: Contract negotiated and Generator is working on it.
|
|
563
|
-
- `completed`: All required success criteria passed evaluation.
|
|
564
|
-
- `needs-rework`: Failed evaluation after maximum iterations. Requires human intervention or plan revision.
|
|
565
|
-
|
|
566
|
-
### Dependencies
|
|
567
|
-
|
|
568
|
-
| Field | Description |
|
|
569
|
-
|-------|-------------|
|
|
570
|
-
| `dependsOn` | Array of `contractId` values that must have status `completed` before this sprint can start. Empty array for the first sprint. |
|
|
571
|
-
| `features` | Array of `featureId` values from the parent PlanSpec that this sprint implements (partially or fully). |
|
|
572
|
-
|
|
573
|
-
### Success Criteria
|
|
574
|
-
|
|
575
|
-
Each success criterion is a single testable statement that the Evaluator checks independently.
|
|
576
|
-
|
|
577
|
-
| Field | Description |
|
|
578
|
-
|-------|-------------|
|
|
579
|
-
| `criterionId` | Unique within the contract. Format: `sc-<sprintNumber>-<index>` (1-indexed). |
|
|
580
|
-
| `description` | Specific, testable criterion. Must describe observable behavior or measurable outcome. |
|
|
581
|
-
| `verificationMethod` | How the Evaluator should verify this criterion. |
|
|
582
|
-
| `required` | If `true`, this criterion MUST pass for the sprint to pass. If `false`, it is advisory. |
|
|
583
|
-
| `customCommand` | Only for `verificationMethod: "custom"`. The command the Evaluator should run. |
|
|
584
|
-
|
|
585
|
-
### Verification Methods
|
|
586
|
-
|
|
587
|
-
| Method | What the Evaluator Does |
|
|
588
|
-
|--------|------------------------|
|
|
589
|
-
| `manual` | Reads source code and assesses whether the criterion is met based on code inspection and logic tracing. |
|
|
590
|
-
| `typecheck` | Runs the configured typecheck command. Criterion passes if zero type errors. |
|
|
591
|
-
| `lint` | Runs the configured lint command. Criterion passes if zero lint errors (warnings OK). |
|
|
592
|
-
| `unit-test` | Runs the configured test command. Criterion passes if all tests pass. |
|
|
593
|
-
| `playwright` | Runs Playwright E2E tests. Criterion passes if all relevant E2E tests pass. |
|
|
594
|
-
| `api-check` | Tests specific API endpoints using curl or similar. Criterion passes if responses match expectations. |
|
|
595
|
-
| `build` | Runs the configured build command. Criterion passes if build succeeds with exit code 0. |
|
|
596
|
-
| `custom` | Runs `customCommand` and interprets the result. Exit code 0 = pass. |
|
|
597
|
-
|
|
598
|
-
### Agent Notes
|
|
599
|
-
|
|
600
|
-
| Field | Description |
|
|
601
|
-
|-------|-------------|
|
|
602
|
-
| `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. |
|
|
603
|
-
| `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. |
|
|
604
|
-
|
|
605
|
-
### Estimates
|
|
606
|
-
|
|
607
|
-
| Field | Description |
|
|
608
|
-
|-------|-------------|
|
|
609
|
-
| `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. |
|
|
610
|
-
| `estimatedDuration` | Relative size estimate: `small` (30-60 min), `medium` (1-3 hours), `large` (3-5 hours). |
|
|
611
|
-
|
|
612
|
-
### Iteration History
|
|
613
|
-
|
|
614
|
-
| Field | Description |
|
|
615
|
-
|-------|-------------|
|
|
616
|
-
| `iterationHistory` | Array of past evaluation attempts. Appended after each evaluation. |
|
|
617
|
-
| `lastEvalId` | Reference to the most recent EvalResult. Updated after each evaluation. |
|
|
618
|
-
|
|
619
|
-
## Complete Example
|
|
620
|
-
|
|
621
|
-
```json
|
|
622
|
-
{
|
|
623
|
-
"contractId": "sprint-spec-20260326-user-auth-1",
|
|
624
|
-
"specId": "spec-20260326-user-auth",
|
|
625
|
-
"sprintNumber": 1,
|
|
626
|
-
"title": "Implement user registration with form and API",
|
|
627
|
-
"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.",
|
|
628
|
-
"status": "proposed",
|
|
629
|
-
"createdAt": "2026-03-26T10:00:00Z",
|
|
630
|
-
"updatedAt": "2026-03-26T10:00:00Z",
|
|
631
|
-
"completedAt": null,
|
|
632
|
-
|
|
633
|
-
"dependsOn": [],
|
|
634
|
-
|
|
635
|
-
"features": ["feat-1"],
|
|
636
|
-
|
|
637
|
-
"successCriteria": [
|
|
638
|
-
{
|
|
639
|
-
"criterionId": "sc-1-1",
|
|
640
|
-
"description": "The project builds successfully with zero errors.",
|
|
641
|
-
"verificationMethod": "build",
|
|
642
|
-
"required": true
|
|
643
|
-
},
|
|
644
|
-
{
|
|
645
|
-
"criterionId": "sc-1-2",
|
|
646
|
-
"description": "TypeScript compilation produces zero type errors.",
|
|
647
|
-
"verificationMethod": "typecheck",
|
|
648
|
-
"required": true
|
|
649
|
-
},
|
|
650
|
-
{
|
|
651
|
-
"criterionId": "sc-1-3",
|
|
652
|
-
"description": "A registration form component exists at the /register route with email, password, and confirm-password input fields, each with an associated label.",
|
|
653
|
-
"verificationMethod": "manual",
|
|
654
|
-
"required": true
|
|
655
|
-
},
|
|
656
|
-
{
|
|
657
|
-
"criterionId": "sc-1-4",
|
|
658
|
-
"description": "POST /api/auth/register accepts { email, password } and returns 201 with { id, email } on success.",
|
|
659
|
-
"verificationMethod": "api-check",
|
|
660
|
-
"required": true
|
|
661
|
-
},
|
|
662
|
-
{
|
|
663
|
-
"criterionId": "sc-1-5",
|
|
664
|
-
"description": "POST /api/auth/register returns 400 with an error message when email is already registered.",
|
|
665
|
-
"verificationMethod": "api-check",
|
|
666
|
-
"required": true
|
|
667
|
-
},
|
|
668
|
-
{
|
|
669
|
-
"criterionId": "sc-1-6",
|
|
670
|
-
"description": "The password is stored as a bcrypt hash in the database, never in plain text.",
|
|
671
|
-
"verificationMethod": "manual",
|
|
672
|
-
"required": true
|
|
673
|
-
},
|
|
674
|
-
{
|
|
675
|
-
"criterionId": "sc-1-7",
|
|
676
|
-
"description": "Client-side validation shows an error when password is shorter than 8 characters before form submission.",
|
|
677
|
-
"verificationMethod": "manual",
|
|
678
|
-
"required": true
|
|
679
|
-
},
|
|
680
|
-
{
|
|
681
|
-
"criterionId": "sc-1-8",
|
|
682
|
-
"description": "ESLint reports zero errors on all new and modified files.",
|
|
683
|
-
"verificationMethod": "lint",
|
|
684
|
-
"required": false
|
|
685
|
-
}
|
|
686
|
-
],
|
|
687
|
-
|
|
688
|
-
"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.",
|
|
689
|
-
|
|
690
|
-
"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.",
|
|
691
|
-
|
|
692
|
-
"estimatedFiles": [
|
|
693
|
-
"prisma/schema.prisma",
|
|
694
|
-
"src/routes/auth.ts",
|
|
695
|
-
"src/pages/Register.tsx",
|
|
696
|
-
"src/App.tsx"
|
|
697
|
-
],
|
|
698
|
-
|
|
699
|
-
"estimatedDuration": "medium",
|
|
700
|
-
|
|
701
|
-
"iterationHistory": [],
|
|
702
|
-
"lastEvalId": null
|
|
703
|
-
}
|
|
704
|
-
```
|
|
705
|
-
|
|
706
|
-
## Writing Good Success Criteria
|
|
707
|
-
|
|
708
|
-
### Do
|
|
709
|
-
|
|
710
|
-
- Start with an observable action or state: "The form displays...", "The API returns...", "The database contains..."
|
|
711
|
-
- Include specific values: "returns 201", "displays 'Invalid email'", "at least 8 characters"
|
|
712
|
-
- Map each criterion to exactly one verification method
|
|
713
|
-
- Include at least one `build` criterion and one functional criterion per sprint
|
|
714
|
-
- Write criteria the Evaluator can verify without guessing
|
|
715
|
-
|
|
716
|
-
### Do Not
|
|
717
|
-
|
|
718
|
-
- Use subjective language: "looks good", "works well", "clean code"
|
|
719
|
-
- Combine multiple checks in one criterion (split them)
|
|
720
|
-
- Reference internal implementation details unless checking them IS the criterion
|
|
721
|
-
- Write criteria that require human visual judgment (unless verification method is `manual` and the check is code-inspectable)
|
|
722
|
-
- Assume the Evaluator has context beyond the contract and handoff documents
|