Walkthrough

Step 02 — Rehearse offline

01 Render & integrate · Index · next: 03 Plan →

Before any beat touches a real model or runs a live gate, drive the whole control flow offline with stub leaves and stub gates. This is the single most valuable habit when adopting the harness: it proves the plumbing (state transitions, artifact assembly, archiving on iterate) independent of any model behaviour, in well under a second, for free.

The toy bundle

The template ships a worked brief at examples/toy/brief.md whose only purpose is to let the driver run end-to-end with nothing wired up:

# Brief — issue TOY / off-by-one-in-pager

> A worked toy brief so the driver runs end-to-end offline (stub leaves/gates).
> Replace with real briefs from your Plan beat. The field labels are what the
> driver parses — keep the `- **Label:** value` shape.

- **Slug:** off-by-one-in-pager
- **Defect:** The result pager shows N-1 of N items; the last item is dropped.
- **Success criterion:** Pager shows all N items; a test over a 3-item list asserts 3 are rendered.
- **Repo + branch target:** example-repo @ main
- **Scope:** Fix the pager's range bound. / out of scope: pager styling, pagination size.
- **Repro instruction:** Load a 3-item fixture, open the pager, observe 2 items shown.
- **Test file:** test_toy.py
- **Citations expected:** Do must cite path:line on main for the changed bound.
- **Disposition hint:** likely-fix

Note the - **Label:** value shape — those labels are exactly what the driver parses out of every brief, including your real ones.

Drive it, beat by beat

# seed a bundle from the toy brief  →  state: PLANNED
PYTHONPATH=src python -m pdca_harness.cli init-issue TOY --from-brief examples/toy/brief.md

# advance until the driver halts     →  Do (stub) → gates (stub) → reviewer (stub)
#                                        → assemble SUMMARY → state: AWAITING_SIGNOFF
PYTHONPATH=src python -m pdca_harness.cli run TOY

# see where it stopped
PYTHONPATH=src python -m pdca_harness.cli status

run advances the bundle until it reaches a halted state. With stubs, the builder/reviewer leaves emit canned artifacts and the gates report canned passes, so the bundle sails to AWAITING_SIGNOFF — the driver's "your turn, human" stop. From there you record a verdict exactly as you would on a real cycle (this is step 06):

PYTHONPATH=src python -m pdca_harness.cli signoff TOY --accept     # → COMPLETE
# or try the others to watch the state machine archive + loop:
PYTHONPATH=src python -m pdca_harness.cli signoff TOY --iterate-do    # → archives, back to PLANNED
PYTHONPATH=src python -m pdca_harness.cli signoff TOY --iterate-plan  # → archives brief too, back to UNPLANNED
PYTHONPATH=src python -m pdca_harness.cli signoff TOY --discontinue   # → DISCONTINUED (terminal)

The one-shot rehearsal

Typing the beats individually is good for seeing the state machine. To rehearse the same orchestration make flow uses — Plan → Do → Check → sign-off → publish — but entirely stubbed, use:

make rehearse ID=TOY

This forces PDCA_LEAVES_MODE=stub, stubs the gates, dry-runs the publish, and writes to a throwaway bundle root (.rehearse/, not your real results/). No Claude, no Docker, no network — just the control flow, instantly. gramps used this constantly while building out its engine/ gates, because it answers "did I break the driver?" without "is the model having a bad day?" muddying the signal.

What you've proven

After a green rehearsal you know the plumbing is sound: states derive correctly from files, the SUMMARY assembles, iterate archives into iteration-v<N>/, and the sign-off transitions fire. Now — and only now — is it worth pointing the beats at real models and real gates. The next five steps walk one live gramps cycle through each beat.

01 Render & integrate · Index · next: 03 Plan →