SDD Change Proposal Template

Use this template when a ticket is too risky for a sentence but too early for implementation detail. It captures the behavior, boundaries, owner, and review evidence before the team writes code.

spec.md
# Change Proposal

Owner:
Status: Draft | Review | Approved
Date:

## Problem
- What is broken, missing, or changing?

## Goal
- What user or system behavior must be true after this ships?

## Non-goals
- What is explicitly out of scope for this change?

## Acceptance Criteria
- Given ...
  When ...
  Then ...

## Open Questions
- [ ] ...

## Evidence Required
- Test:
- Log or metric:
- Manual check:
- Rollback signal:

When to use this template

What a filled version looks like

The template becomes useful after it carries a real decision, owner, and evidence. This is the level of specificity to aim for.

## Goal
- Refund a captured charge within 90 days without creating duplicate refunds.

## Non-goals
- No new payment provider.
- No bulk refund flow.

## Acceptance Criteria
- Given the same idempotency key is replayed
  When the refund endpoint receives it again
  Then the existing refund_id is returned and no second event is emitted.

Field note: refund scope before implementation

A support team asks for "refunds in checkout" after two duplicate refunds were created during provider timeout recovery. The change looks small, but the real decision is replay behavior, support permissions, and the point where a pending refund blocks another action.

Common failure: If the proposal only says "avoid duplicates", an AI coding agent may add a uniqueness constraint while leaving event emission, support UI state, and timeout recovery ambiguous.

How to adapt this template without making it generic

Do not only replace the title and date. A useful version turns every placeholder into a reviewable decision: who owns the change, which behavior must be true, which scope is explicitly excluded, and what evidence must exist before merge. If a field cannot be filled yet, keep it as an open question instead of burying the uncertainty in prose.

When you use this spec.md, start with the part most likely to cause rework. For many teams that is not the implementation step; it is the boundary, exception, compatibility rule, or release evidence. The earlier the template exposes those decisions, the less room an AI coding tool or rushed engineer has to broaden the change silently.

Suggested review path

Use the first pass to review scope: the goal should be singular, the non-goals should block common expansions, and the affected systems should be named. Use the second pass to review testability: acceptance criteria should describe state, trigger, and observable result, not a vague wish that the product feels better. Use the third pass to review evidence: tests, screenshots, logs, metrics, or manual checks should prove each criterion.

Before giving this template to an AI coding tool, ask a human reviewer to confirm allowed files, interfaces that must not change, migration order, and stop signals. The AI should receive an executable spec, not a prompt that looks complete while still leaving the risky decisions implicit.

Review before implementation

Weak vs strong wording

Weak

Allow users to refund orders and make sure duplicate refunds do not happen.

Strong

Captured charges may be refunded for 90 days. Replayed requests with the same idempotency key return the existing refund_id, do not create a second row, and do not emit a second refund_requested event.

When the template stops being empty

The easiest way for a template page to become thin is to provide a clean skeleton without showing how to judge the filled result. A useful version answers three questions: why this change is worth doing now, which scope is explicitly excluded, and which evidence proves the implementation did not drift.

When you use the template for real work, attach the final file to the pull request and mark any section that changed during implementation. A spec is not a one-time document; it should move with the implementation evidence. Readers copying this template should also copy that habit: every sentence that sounds like a decision should be reviewable and traceable.

Where it fits in a complete SDD packet

Do not push every decision into the same file. spec.md should own the layer it is best at: making one category of decision reviewable, linkable, and updateable. Scope, design, tasks, and evidence should connect to each other, but they should not swallow each other. When implementation reveals new facts, the team should know exactly which artifact needs to change.

In practice, use this template as one step in a short chain: write the spec or proposal, add design or tasks only when the work needs them, then feed evidence back into the pull request. Readers copying the template should copy that chain as well. A polished standalone template does not improve delivery by itself; a traceable set of artifacts does.

If the template becomes a team standard, keep one filled example in the repository instead of only publishing an empty skeleton. The example teaches new contributors what "specific enough" looks like and gives AI coding tools a better pattern to follow.

FAQ

Is this different from a PRD?

Yes. A PRD explains product intent. This change proposal turns that intent into engineering behavior, acceptance criteria, and evidence.

How long should it be?

Most useful proposals fit on one page. If the change needs architecture trade-offs, link to a design doc instead of expanding this template forever.

When is it ready for implementation?

It is ready when reviewers agree on scope, non-goals, affected systems, and the evidence required before merge.

Related resources

Editorial note

This template is written for spec-driven development workflows. The example is illustrative and should be adapted to your domain.

Tip: keep it under /docs/specs/ or /.specs/, then update it in the same pull request as implementation changes. Last updated: May 19, 2026.