Plan Pattern Library
A catalog of reusable plan archetypes. For each pattern: when to reach for it, the typical slice shape, the validation gate flavor, recommended quorum mode, and the failure modes the pattern is designed to avoid. Use this when starting a new plan and you want to skip thinking about structure from scratch.
forge_crucible_ask can also be asked "which plan pattern fits <task>?" and will return a pointer to the right section here.
Index
| Pattern | When | Slices |
|---|---|---|
| P1 — Add an Entity | New domain object end-to-end (DB → service → API → UI) | 4–7 |
| P2 — Add an Endpoint | New REST / RPC route on existing entity | 2–3 |
| P3 — Add an External Integration | Wire up a third-party API (Stripe / SendGrid / S3 / etc.) | 4–5 |
| P4 — Refactor a Subsystem | Extract / split / rename module with multiple consumers | 3–6 (one per consumer) |
| P5 — Fix a Regression | Bug landed in a previous slice; need repro + fix + guard | 2–3 |
| P6 — Hotfix | Production incident, minimal-surface emergency change | 1–2 |
| P7 — Feature Flag Rollout | Risky change you want to ship dark, toggle on later | 4–5 |
| P8 — Data Migration | Schema change requiring backfill + verification | 4–6 |
| P9 — Dependency Upgrade | Breaking-change SDK / framework bump | 3–5 |
| P10 — Performance Fix | Profile-driven targeted optimization | 2–3 |
| P11 — Security Patch | CVE / vulnerability with minimal-surface fix | 2–3 |
| P12 — Documentation Phase | Multi-document writing pass (manual chapters, runbooks, API docs) | 1 per document |
| P13 — CI/CD Workflow Change | Modify GitHub Actions / pipelines / deploy automation | 1–2 + manual verify |
| P14 — Spike-Then-Build | Unfamiliar domain; need exploration before committing to a design | 1 spike + N build slices in a follow-up plan |
P1 — Add an Entity
When: a new first-class noun in your domain that needs persistence, an API surface, and (often) a UI. The most common shape.
Slice shape (4–7 slices):
- Migration + ORM model.
- Repository layer + unit tests.
- Service layer (validation, business rules) + unit tests.
- Controller / route + integration tests.
- (optional) UI component / form.
- (optional) Background job / event consumer if the entity participates in async flows.
- OpenAPI / docs update.
Gate flavor: each slice ends with the test command for its layer (vitest repository.test, vitest service.test, vitest controller.integration.test). The final slice runs the full sweep.
Quorum: auto. The slices are routine; power is overkill.
Failure modes avoided: collapsing layers (controller doing DB writes), missing the OpenAPI update, forgetting to wire the migration into the test setup.
P2 — Add an Endpoint
When: a new route on an existing entity. No schema change, no UI.
Slice shape (2–3 slices):
- Service method + unit test (red → green).
- Controller route + integration test + OpenAPI entry.
- (optional) Client SDK regenerate.
Gate flavor: per-slice unit / integration test command. Final gate also runs the OpenAPI lint / contract diff.
Quorum: auto or disabled for trivial CRUD additions.
Failure modes avoided: route registered but not wired to service; OpenAPI drift from implementation.
P3 — Add an External Integration
When: bringing in Stripe, SendGrid, S3, Twilio, an internal RPC service, anywhere your code calls an outside system.
Slice shape (4–5 slices):
- Adapter interface + in-process fake (for tests).
- Real adapter implementation against the SDK / HTTP client.
- Retry + timeout + circuit-breaker configuration.
- Caller integration (the service that uses the adapter).
- Secret wiring + env-var documentation + runbook entry.
Gate flavor: unit tests use the fake; the real-adapter slice may have an opt-in SMOKE=1 guard that hits a sandbox.
Quorum: auto; bump to power for the retry/circuit-breaker slice if SLA-critical.
Failure modes avoided: timeouts not configured (hang forever), retries not idempotent-safe, secrets in source.
P4 — Refactor a Subsystem
When: extracting a module, splitting a god-class, renaming a heavily-referenced symbol. Multiple consumers must update.
Slice shape (3–6 slices):
- Introduce new shape alongside the old (no consumer changes yet).
- Migrate consumer 1.
- Migrate consumer 2.
- … (one slice per consumer; keeps each slice individually revertable)
- Delete the old shape; run full sweep.
Gate flavor: per-consumer slice gates run that consumer's test file. Final slice runs the full sweep + a grep that asserts zero references to the old shape.
Quorum: auto. Per-consumer slices are mechanical; quorum doesn't help.
Failure modes avoided: big-bang rename that breaks the whole tree at once; consumer drift (one consumer left on the old shape).
P5 — Fix a Regression
When: a bug that worked before now doesn't. The previous slice that introduced it is identified.
Slice shape (2–3 slices, strict TDD):
- Red: write the test that captures the broken behavior; assert it fails for the right reason.
- Green: minimal change to make the test pass; nothing else.
- (optional) Refactor: clean up if the green slice introduced obvious duplication.
Gate flavor: the red slice's gate must assert the test fails (e.g. vitest run regression.test 2>&1 | grep -q "1 failed"). The green slice's gate asserts it now passes.
Quorum: auto for green; disabled often fine for red.
Failure modes avoided: "fix" that doesn't actually fix; scope creep that buries the actual fix in unrelated changes.
P6 — Hotfix
When: production is broken; minutes matter; the change is small and reversible.
Slice shape (1–2 slices):
- The minimum fix + a smoke test that exercises the affected path.
- (optional, follow-up) Proper regression test if the smoke wasn't tight enough.
Gate flavor: fast (under 30s if possible). Skip the broad sweep; run only the affected test file. The completeness sweep can be deferred to a follow-up plan.
Quorum: disabled. Hotfix is about speed and reversibility, not consensus.
Failure modes avoided: bundling "improvements" into the hotfix (each line shipped is a line to roll back); over-validation while production burns.
Follow-up: file a P5 (Fix a Regression) plan once the fire is out, to add proper test coverage and address root cause.
P7 — Feature Flag Rollout
When: a change risky enough to ship dark, new algorithm, vendor swap, UI redesign.
Slice shape (4–5 slices):
- Flag scaffold (config entry, accessor, default OFF).
- New implementation behind the flag (parallel to old).
- Tests covering both branches.
- Telemetry / metric to compare old vs new behavior in production.
- (separate, later plan) Cleanup: remove the flag and the old branch once new is proven.
Gate flavor: tests must pass with flag both ON and OFF. The implementation slice's gate explicitly runs the suite twice with different env vars.
Quorum: power for the implementation slice (high blast radius); auto elsewhere.
Failure modes avoided: flag-on path untested; flag never cleaned up (becomes permanent technical debt).
P8 — Data Migration
When: a schema change requires moving / reshaping existing data, not just altering the schema.
Slice shape (4–6 slices):
- Schema migration (additive: new columns / tables, old still readable).
- Dual-write code (write to both old and new shape).
- Backfill script + dry-run validation against a snapshot.
- Read-from-new (with fallback to old).
- Remove dual-write; remove old shape.
- Rollback playbook documented in the plan's Notes section.
Gate flavor: each slice's gate asserts the migration is idempotent (re-running it leaves the DB unchanged). Final slice's gate runs against a production-shape fixture.
Quorum: power for the migration, backfill, and remove-old slices (irreversible if wrong); auto elsewhere.
Failure modes avoided: irreversible migrations without a rollback path; backfills that lock production tables; reads switching before the data is fully migrated.
P9 — Dependency Upgrade
When: a major-version bump on a library / framework / SDK with breaking changes.
Slice shape (3–5 slices):
- Pin the new version; run the full sweep to surface every breaking call site.
- Fix call sites in module 1.
- Fix call sites in module 2 (one slice per cleanly-bounded module).
- …
- Final slice: full sweep + lint + type-check all green.
Gate flavor: each per-module slice's gate runs the test set for that module. Final slice's gate runs the full sweep.
Quorum: auto. Mechanical replacements; quorum adds little.
Failure modes avoided: trying to do all the fixes in one slice (un-reviewable diff); missing transitive breakage (final-sweep gate catches it).
P10 — Performance Fix
When: profiling has identified a specific hotspot and you want to fix it without speculative changes.
Slice shape (2–3 slices):
- Add a benchmark / measurement that pins the current performance number (the baseline).
- The fix.
- (optional) A regression-guard test that fails if perf drops back below threshold.
Gate flavor: the fix slice's gate runs the benchmark and asserts the new number beats the baseline by the documented margin (e.g. node bench/users.bench.mjs | grep -E "throughput.*[5-9][0-9]{3}").
Quorum: auto. The hot loop is small; the change should be small.
Failure modes avoided: optimizing without measuring; broad refactors disguised as performance work.
P11 — Security Patch
When: a CVE in a dependency, a misconfiguration finding, or a discovered vulnerability in your own code.
Slice shape (2–3 slices):
- The minimum-surface fix (upgrade pin, sanitize input, rotate config, whichever applies).
- A regression test that asserts the vulnerable path is now safe.
- (optional) Advisory / disclosure write-up.
Gate flavor: the fix slice's gate runs the regression test plus forge_secret_scan on the diff. PreDeploy LiveGuard hook applies if shipping to a deploy slice.
Quorum: auto or power, depends on blast radius.
Failure modes avoided: scope creep (fixing other things "while we're here"); regression test that doesn't actually exercise the vulnerable path.
See also Chapter 30 — Incident response.
P12 — Documentation Phase
When: writing several documents at once (manual chapters, runbooks, API docs) over multiple sessions.
Slice shape (1 per document):
- One slice per document. Each is independent, if slice N fails, slices N+1, N+2 are unaffected.
- Scope contract: only the document's source file + any auto-regenerated index files.
- Gate: the documentation maintainer's validator (e.g.
node docs/manual/maintain.mjs).
Gate flavor: validator runs twice consecutively, first pass detects drift, second pass confirms the auto-regeneration converged.
Quorum: auto. Doc writing is iterative; quorum doesn't help much.
Failure modes avoided: documents that reference each other but drift apart; orphan files not registered in indexes; bundled commits that touch many unrelated documents at once.
Real-world example: this manual's Phase-MANUAL-EBOOK-COMPLETION-PLAN.md is a literal P12 instance.
P13 — CI/CD Workflow Change
When: modifying GitHub Actions, deploy pipelines, or release automation. The change can't be fully tested locally.
Slice shape (1–2 slices + manual verify):
- The workflow change itself, with the new step set up to be a no-op (or run against a sandbox branch / test environment).
- Promote: flip the no-op to real, after the first slice's CI run has been observed end-to-end.
Gate flavor: local syntax check (e.g. actionlint .github/workflows/*.yml); the real verification happens by observing the next CI run on a branch.
Quorum: auto; bump to power if the change touches deploy gating.
Failure modes avoided: committing a broken workflow that bricks CI for the whole team; deploy steps that worked in the sandbox but fail in production.
P14 — Spike-Then-Build
When: unfamiliar domain, unclear design space. You need to learn before you commit.
Slice shape (1 spike + a follow-up build plan):
- Spike slice: explicitly time-boxed exploration. Output is a document (an ADR, a design note, an annotated prototype), not production code. Forbidden Actions deny edits outside
docs/research/. - Spike output feeds a new plan in a new session (using whichever pattern P1–P13 fits).
Gate flavor: the spike's gate is "an ADR or design note exists" (e.g. test -f docs/research/spike-NN-decision.md). Time-box is enforced by reviewing the document and explicitly killing the run if it produced code.
Quorum: power. Spikes benefit from diverse perspectives precisely because the question is open.
Failure modes avoided: spike code accidentally landing in production; spike that produces no decision (just code); spike that bleeds into multi-week exploration without a checkpoint.
Composing patterns
Real phases often combine patterns. A typical feature ship might be:
- Phase-NN.1, P14 spike to settle the API shape.
- Phase-NN.2, P1 add entity (backend).
- Phase-NN.3, P7 feature-flag rollout for the UI / risky behavior.
- Phase-NN.4, P12 documentation phase (runbook + API docs).
Each phase is a separate plan file, runnable independently, revertable independently, reviewable independently. That's the architectural payoff, small phases compose; mega-phases don't.
Anti-patterns
Shapes that look like patterns but degrade outcomes. If your plan resembles one of these, refactor the plan before running it.
| Anti-pattern | Why it fails | Refactor to |
|---|---|---|
| Mega-slice (one slice, 20+ files) | Un-reviewable diff; one failure rolls back everything; no useful intermediate state. | Split into per-layer / per-consumer slices, P1 or P4. |
| Test-after (separate slice that only adds tests for code shipped earlier) | Test slice often "happens to pass" because it's written to match observed behavior, not specified behavior. | Move tests into the slice that ships the code (or use P5's strict red-then-green for genuine retrofit). |
| Sweep-only-at-end | All earlier slices appeared green; the sweep at the end discovers cross-slice breakage that's now expensive to localize. | Run sweep as part of every slice's gate (cost: seconds; benefit: bisectability). |
| Plan-as-essay (long prose, vague scope contracts) | Worker treats it as inspiration rather than contract; scope drift becomes the norm. | Use the standard plan template: explicit Scope Contract + Forbidden Actions + per-slice gate command. See the AI Plan Hardening Runbook. |
| Quorum-power for everything | 10× cost without measurable quality lift on routine slices. | Default auto; opt into power per-slice or per-phase where it actually helps. |
| No rollback path (data migration, infra change with no documented revert) | If anything goes wrong post-deploy, you're improvising under stress. | P8 explicitly lists rollback as a slice; P13 requires a no-op step before promote. Add a Notes section to every plan that describes the revert path. |
See also
- AI Plan Hardening Runbook, the standard plan template these patterns plug into.
- Chapter 6 — Your First Plan, the narrative walkthrough of plan authoring.
- Chapter 31 — Cost-effective workflows, per-slice economics that informed pattern choices.
- Chapter 14 — Quorum & Multi-Agent, how the quorum recommendation per pattern is enforced at runtime.
- Chapter 30 — Incident response, the runbook backing P6 (Hotfix) and P11 (Security Patch).
- Appendix X — Errors & Exit Codes, gate failure surface every pattern relies on.