A tall flat-file map cabinet inside the Plan Forge shop with several wide shallow drawers pulled fully open revealing a fan of architectural blueprint scrolls and pattern diagrams, each blueprint depicting a different repeatable forge configuration, glowing amber rune-annotations marking key components, a smith leaning over the drawer studying one
Appendix Y

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.

How to use this appendix. Read the index, find the pattern that matches your task, jump to its section, and copy the slice shape into your plan draft. The Crucible's forge_crucible_ask can also be asked "which plan pattern fits <task>?" and will return a pointer to the right section here.

Index

PatternWhenSlices
P1 — Add an EntityNew domain object end-to-end (DB → service → API → UI)4–7
P2 — Add an EndpointNew REST / RPC route on existing entity2–3
P3 — Add an External IntegrationWire up a third-party API (Stripe / SendGrid / S3 / etc.)4–5
P4 — Refactor a SubsystemExtract / split / rename module with multiple consumers3–6 (one per consumer)
P5 — Fix a RegressionBug landed in a previous slice; need repro + fix + guard2–3
P6 — HotfixProduction incident, minimal-surface emergency change1–2
P7 — Feature Flag RolloutRisky change you want to ship dark, toggle on later4–5
P8 — Data MigrationSchema change requiring backfill + verification4–6
P9 — Dependency UpgradeBreaking-change SDK / framework bump3–5
P10 — Performance FixProfile-driven targeted optimization2–3
P11 — Security PatchCVE / vulnerability with minimal-surface fix2–3
P12 — Documentation PhaseMulti-document writing pass (manual chapters, runbooks, API docs)1 per document
P13 — CI/CD Workflow ChangeModify GitHub Actions / pipelines / deploy automation1–2 + manual verify
P14 — Spike-Then-BuildUnfamiliar domain; need exploration before committing to a design1 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):

  1. Migration + ORM model.
  2. Repository layer + unit tests.
  3. Service layer (validation, business rules) + unit tests.
  4. Controller / route + integration tests.
  5. (optional) UI component / form.
  6. (optional) Background job / event consumer if the entity participates in async flows.
  7. 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):

  1. Service method + unit test (red → green).
  2. Controller route + integration test + OpenAPI entry.
  3. (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):

  1. Adapter interface + in-process fake (for tests).
  2. Real adapter implementation against the SDK / HTTP client.
  3. Retry + timeout + circuit-breaker configuration.
  4. Caller integration (the service that uses the adapter).
  5. 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):

  1. Introduce new shape alongside the old (no consumer changes yet).
  2. Migrate consumer 1.
  3. Migrate consumer 2.
  4. … (one slice per consumer; keeps each slice individually revertable)
  5. 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):

  1. Red: write the test that captures the broken behavior; assert it fails for the right reason.
  2. Green: minimal change to make the test pass; nothing else.
  3. (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):

  1. The minimum fix + a smoke test that exercises the affected path.
  2. (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):

  1. Flag scaffold (config entry, accessor, default OFF).
  2. New implementation behind the flag (parallel to old).
  3. Tests covering both branches.
  4. Telemetry / metric to compare old vs new behavior in production.
  5. (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):

  1. Schema migration (additive: new columns / tables, old still readable).
  2. Dual-write code (write to both old and new shape).
  3. Backfill script + dry-run validation against a snapshot.
  4. Read-from-new (with fallback to old).
  5. Remove dual-write; remove old shape.
  6. 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):

  1. Pin the new version; run the full sweep to surface every breaking call site.
  2. Fix call sites in module 1.
  3. Fix call sites in module 2 (one slice per cleanly-bounded module).
  4. 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):

  1. Add a benchmark / measurement that pins the current performance number (the baseline).
  2. The fix.
  3. (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):

  1. The minimum-surface fix (upgrade pin, sanitize input, rotate config, whichever applies).
  2. A regression test that asserts the vulnerable path is now safe.
  3. (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):

  1. One slice per document. Each is independent, if slice N fails, slices N+1, N+2 are unaffected.
  2. Scope contract: only the document's source file + any auto-regenerated index files.
  3. 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):

  1. The workflow change itself, with the new step set up to be a no-op (or run against a sandbox branch / test environment).
  2. 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):

  1. 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/.
  2. 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-patternWhy it failsRefactor 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-endAll 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 everything10× 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