Day 0 — Sprint Planning
PACE has a dedicated pace-planner CI workflow for Day 0 sprint planning. You trigger it before your sprint begins — it estimates the cost of every story in your plan, opens a plan-approval PR with those estimates for your review, pauses the daily cycle (PACE_PAUSED=true), and waits for you to merge the PR before Day 1 runs.
What the planner does
You trigger pace-planner workflow ↓PLANNER reads plan.yaml ↓For each story (1 – N): human_gate? → $0.00, skip Otherwise → single Sonnet call (~$0.01–0.03) returns predicted_iterations + predicted_cost_usd ↓Writes .pace/day-0/planner.md (per-story breakdown + sprint total)Writes .pace/shipped.yaml (manifest of already-shipped stories)Writes PROGRESS.md (pre-filled with Est. Cost column) ↓Sets PACE_PAUSED=true (daily cycle cannot start yet) ↓Opens plan-approval PR (GitHub only — see platform matrix) ↓You review estimates → merge PR → unset PACE_PAUSED → Day 1 runsEstimation uses claude-sonnet-4-6 (the same model as FORGE) so predictions are calibrated to the actual execution model. The entire planning run costs roughly $0.01–0.03 × N stories — about $0.30–$0.90 for a 30-story sprint.
Platform availability
| Platform | Workflow | Trigger | Plan-approval PR | PACE_PAUSED |
|---|---|---|---|---|
| GitHub | .github/workflows/pace-planner.yml | workflow_dispatch (manual) or scheduled cron | ✅ Opens PR on pace/plan-approval branch | ✅ Set via Actions variable |
| GitLab | pace-planner job in .gitlab-ci.yml | Schedule with PACE_RUN_PLANNER=true, or web trigger | ❌ Artifacts only | Varies |
| Bitbucket | pace-planner custom pipeline in bitbucket-pipelines.yml | Custom run via Bitbucket UI | ❌ Artifacts only | Varies |
| Jenkins | ❌ Not implemented | — | — | — |
| Local | Manual CLI invocation | python pace/orchestrator.py --day 0 | — | — |
Context refresh
Before estimating story costs, the planner checks whether the context documents in .pace/context/ are current. If any source files listed in context.source_docs have changed since the last context build, or if any required context documents are missing, SCRIBE runs automatically and the refreshed documents are committed to the pace/plan-approval branch alongside the cost estimates.
Reviewers can inspect the engineering.md diff in the plan-approval PR to verify that PRIME will have an accurate module map on Day 1.
If SCRIBE fails during the refresh, the planner continues — cost estimates are generated and the PR is opened with the existing (potentially stale) context documents. A scribe_error field in planner.md records what failed.
See Context Refresh for full behaviour details, troubleshooting, and manual refresh instructions.
Triggering the planner
GitHub Actions
- Go to Actions → PACE Planner in your repository.
- Click Run workflow.
- Set
replantofalsefor a new sprint,truefor a mid-sprint re-estimation. - Click Run workflow to confirm.
The workflow runs python pace/planner.py --pipeline, pushes the planner artifacts to the pace/plan-approval branch, and opens (or updates) a plan-approval PR.
Optional scheduled trigger — uncomment the schedule: block in .github/workflows/pace-planner.yml to run the planner automatically at sprint start:
on: workflow_dispatch: inputs: replan: ... schedule: - cron: "0 8 * * 1" # Every Monday at 08:00 UTCGitLab CI/CD
The pace-planner job runs when the pipeline is triggered with PACE_RUN_PLANNER=true. Set this variable either:
- Scheduled pipeline — create a schedule in CI/CD → Schedules with variable
PACE_RUN_PLANNER=true - Web trigger — trigger a pipeline manually via CI/CD → Pipelines → Run pipeline, set
PACE_RUN_PLANNER=true
The job runs python pace/orchestrator.py with PACE_DAY: "0". Artifacts are stored in .pace/day-0/ for 30 days. GitLab does not open a plan-approval MR automatically — review .pace/day-0/planner.md directly from the job artifacts.
To add re-plan support, set PACE_REPLAN=true as an additional pipeline variable.
Bitbucket Pipelines
Run the pace-planner custom pipeline from Repository settings → Pipelines → Run pipeline → Custom → pace-planner. Pass optional variables:
| Variable | Value | Effect |
|---|---|---|
PACE_DAY | 0 | Required — selects planning mode |
PACE_REPLAN | false / true | Re-estimate remaining stories only |
Review .pace/day-0/planner.md from the pipeline artifacts tab.
Local (any platform)
cd pacesource .venv/bin/activatePACE_DAY=0 ANTHROPIC_API_KEY=your-key python pace/orchestrator.pyFor re-planning:
PACE_DAY=0 PACE_REPLAN=true ANTHROPIC_API_KEY=your-key python pace/orchestrator.pyThe local invocation writes planner.md and updates PROGRESS.md but does not set PACE_PAUSED or open a PR.
The plan-approval PR (GitHub)
After the planner runs on GitHub, a PR is opened (or updated) on the pace/plan-approval branch:
PR title: [PACE Plan Approval] Review sprint estimates before resuming
PR body includes:
- Confirmation that
PACE_PAUSED=trueis set - Links to
.pace/day-0/planner.mdand.pace/shipped.yaml - Instructions for resuming after merge
To approve and resume:
- Open the plan-approval PR
- Review
.pace/day-0/planner.md— check per-story estimates and sprint total - Merge the PR (squash merge is fine)
- Go to Settings → Secrets and variables → Actions → Variables and set
PACE_PAUSEDtofalse - The next daily cron trigger will advance to Day 1, or trigger it manually
PROGRESS.md after Day 0
Once the planner completes, PROGRESS.md gains an Est. Cost column:
| Story | Title | Status | Est. Cost | Actual Cost | Notes |
|---|---|---|---|---|---|
| Day 0 | Sprint planning | 📋 PLAN | — | $0.0523 | Cost estimation |
| story-1 | Repo scaffold | ⏳ PENDING | $1.10 | — | |
| story-2 | CLI skeleton | ⏳ PENDING | $2.00 | — | |
| … | … | … | … | … |
After each story ships, Actual Cost is filled in from cycle.md. After the final story, a Cost Summary section is added:
## Cost Summary
| Metric | Value || --- | --- || Total estimated (story-1 – story-30) | $45.00 || Total actual (incl. retries) | $52.14 || Wasted on retries | $4.30 || story-2 (2×): $6.59 | || FORGE-only (all stories) | $38.20 || Day 0 planning cost | $0.0523 |Artifacts written
.pace/day-0/planner.md — per-story cost breakdown:
day: 0agent: PLANNERgenerated_at: "2026-03-19T08:00:00Z"estimation_model: claude-sonnet-4-6total_estimated_usd: 45.00planning_cost_usd: 0.0523replan: falseestimates: - story: story-1 title: "Repo scaffold" predicted_iterations: 8 predicted_cost_usd: 1.10 reasoning: "Simple scaffold with 2-3 files and a CI pass." - story: story-2 title: "CLI skeleton" predicted_iterations: 12 predicted_cost_usd: 2.00 reasoning: "Medium complexity with flag wiring.".pace/shipped.yaml — manifest of stories that have already shipped (protected from re-estimation on re-plan runs).
Tuning expectations
Day 0 estimates are directional, not exact. Treat them as order-of-magnitude signals:
| Estimate range | What to expect |
|---|---|
| < $1.20 | Simple story — FORGE finishes in under 15 iterations |
| $1.20 – $2.50 | Medium story — well within the 35-iteration budget |
| $2.50 – $3.50 | Rich story — consider reducing acceptance criteria count |
| > $3.50 | Complex story — PRIME refinement will trigger (if max_story_cost_usd is set) |
Because the planner only sees the plan entry (not a full story card), estimates are less precise than the in-cycle SCOPE check. The in-cycle SCOPE check — run after PRIME generates an actual story card — is the authoritative pre-FORGE estimate.
See Proactive Story Scoping for how SCOPE and PRIME refinement work.
Re-planning mid-sprint
Trigger the planner again at any point during a sprint to refresh estimates for remaining stories while preserving actuals for completed stories.
GitHub: Run the PACE Planner workflow with replan: true. A new plan-approval PR is opened with updated estimates.
GitLab / Bitbucket: Re-trigger with PACE_REPLAN=true.
Local:
PACE_DAY=0 PACE_REPLAN=true python pace/orchestrator.pyWhat re-planning does:
- Reads completed stories from
PROGRESS.md— preserves their actual costs - Re-estimates only remaining (pending) stories with a fresh Sonnet call
- Updates
planner.mdandPROGRESS.mdwith new estimates alongside actuals - The
replan: truefield inplanner.mdmarks the report as a re-plan
When to re-plan:
- Scope changed significantly mid-sprint (new requirements, deferred stories)
- Several stories came in well above estimate and you want recalibration
- After a human gate pause/resume to refresh the remaining budget forecast