Write a Sprint Plan
The sprint plan (plan.yaml) is the only input you write for each sprint. PRIME reads it daily and generates a focused Story Card with acceptance criteria, scope boundaries, and context for FORGE. A well-written plan produces better code and fewer HOLD decisions.
File location
your-repo/└── plan.yaml ← your sprint plan lives here (repository root)Minimal structure (v3)
release: v1.0
stories: - id: story-1 title: "User model and password hashing" status: pending acceptance_criteria: - "User.create() stores bcrypt-hashed password" - "User.verify_password() returns True for correct password" - "Tests cover both happy path and incorrect password" out_of_scope: - "OAuth / social login" - "Email verification"Full field reference
release: string # Required — matches releases[].name in pace.config.yaml
stories: - id: story-N # Required — e.g. story-1, story-2 (1-indexed) title: string # Required — short imperative description status: string # Required — pending | in_progress | shipped | hold shipped_at: string # Optional — ISO 8601 timestamp, set by PACE on SHIP human_gate: bool # Optional — if true, PACE pauses after this story for human review notes: string # Optional — free-text context for PRIME (architecture decisions, constraints) acceptance_criteria: - string # Testable, concrete conditions. Start with a verb. out_of_scope: - string # Explicitly deferred items — GATE can PARTIAL against theseWriting good acceptance criteria
Each criterion should be:
- Testable — GATE must be able to verify it with test output or CI results.
- Specific — name the function, endpoint, or behaviour, not a vague quality.
- Atomic — one condition per criterion.
Good examples
acceptance_criteria: - "POST /auth/login returns 200 + JWT for valid credentials" - "POST /auth/login returns 401 for invalid password" - "JWT expires in 24 hours (exp claim verified in tests)" - "pytest exits 0 with all auth tests passing"Weak examples (avoid)
acceptance_criteria: - "Authentication works" # Not testable - "Good test coverage" # Not specific - "Handles errors correctly" # VagueUsing out_of_scope
out_of_scope lets GATE issue a PARTIAL verdict rather than FAIL for known deferred items. Without it, GATE will FAIL any criterion it cannot verify.
stories: - title: "User login" acceptance_criteria: - "POST /auth/login returns JWT" - "CI pipeline is green" out_of_scope: - "CI pipeline — not yet configured in this sprint"Now if GATE cannot find a green CI run, it marks “CI pipeline” as PARTIAL (mapped to out_of_scope) instead of FAIL.
Multi-story days
A day can have multiple stories. PRIME will include all of them in the Story Card, and FORGE will implement them sequentially:
- day: 2 theme: "Login + logout endpoints" stories: - title: "POST /auth/login" acceptance_criteria: - "Returns 200 + token for valid credentials" - "Returns 401 for invalid credentials" - title: "POST /auth/logout" acceptance_criteria: - "Invalidates token server-side" - "Returns 204 on success"Using notes for architectural context
Add notes when FORGE needs to know about constraints that aren’t expressed in the acceptance criteria:
- day: 3 theme: "Refresh token rotation" notes: > We store refresh tokens in the database (not in-memory) because we need to support multi-device sessions. The RefreshToken model is already stubbed in src/models/refresh_token.py from Day 2. stories: - title: "POST /auth/refresh" acceptance_criteria: - "Issues new access token given valid refresh token" - "Rotates the refresh token (old token invalidated)"Clearance days
On days where human_gate: true or when the orchestrator is configured with advisory clearance days, GATE, SENTINEL, and CONDUIT receive the full advisory backlog and must resolve every open item:
- day: 5 theme: "Final review and advisory clearance" human_gate: true stories: - title: "Resolve all open advisories" acceptance_criteria: - "All SENTINEL advisories from Days 1-4 are explicitly resolved" - "All CONDUIT advisories from Days 1-4 are explicitly resolved"See Set Human Gate Days for more on human gates.
Example: 5-story sprint plan
release: v1.0
stories: - id: story-1 title: "User creation with hashed passwords" status: pending acceptance_criteria: - "User.create() stores bcrypt-hashed password" - "User.verify_password() returns True/False correctly" - "Unit tests pass for both cases"
- id: story-2 title: "POST /auth/login" status: pending acceptance_criteria: - "Returns 200 + signed JWT for valid credentials" - "Returns 401 for invalid credentials" - "Token payload includes user_id and exp"
- id: story-3 title: "Clear advisory backlog" status: pending notes: "Review and close all advisories from stories 1-2" acceptance_criteria: - "All SENTINEL and CONDUIT advisories from stories 1-2 resolved"
- id: story-4 title: "JWT middleware" status: pending acceptance_criteria: - "Protected routes return 401 for missing/invalid token" - "Protected routes return 200 for valid token"
- id: story-5 title: "POST /auth/refresh" status: pending acceptance_criteria: - "Issues new access token from valid refresh token" - "Rotates refresh token on each use" - "Returns 401 for expired or revoked refresh token"