From vague requirement to executable spec

These examples show the exact move Spec Coding is built around: take a weak AI coding prompt and turn it into files that reviewers, testers, and agents can follow.

BeforeAmbiguous ticket or prompt
AfterSpec, tasks, acceptance, evidence
UseCopy into issues, PRs, or repos

Example 1: notification preferences

Vague ticket

Make notification settings clearer.
Users should know what they are subscribed to.

Spec packet version

spec.md
- Goal: show email, in-app, and push preferences per event.
- Non-goal: no new notification provider.
- Risk: duplicate sends during migration.

acceptance-criteria.md
- Given an existing user with email disabled
  When preferences are migrated
  Then email remains disabled for every event.

test-evidence.md
- migration dry run
- old mobile client screenshot
- duplicate notification regression test

Example 2: API error handling

Vague ticket

Improve API errors.
Make them easier for clients to handle.

Spec packet version

spec.md
- Goal: standardize error code, message, trace_id, and retryable.
- Non-goal: no endpoint behavior changes.
- Constraint: old SDKs must parse the response.

acceptance-criteria.md
- Given a validation failure
  When the API returns 422
  Then response includes code, message, field_errors, trace_id.

test-evidence.md
- contract test for 400/401/409/422
- SDK compatibility fixture
- release note for changed examples

Example 3: report export

Vague ticket

Add CSV export to reports.
Should work for large accounts.

Spec packet version

spec.md
- Goal: async CSV export for reports up to 1M rows.
- Non-goal: no PDF export.
- Risk: long-running jobs and stale filters.

tasks.md
- persist export request with filters
- run worker with retry and idempotency key
- notify user when file is ready

test-evidence.md
- 1M row load test
- failed worker retry test
- expired download link check

Complete case studies

Checkout coupon code

See how a money-touching checkout request becomes a bounded spec with validation, total calculation, and rollback evidence.

Open the coupon case

API error taxonomy

See how an API error cleanup request becomes a compatibility-safe contract with fixtures, SDK checks, and OpenAPI examples.

Open the API error case

Notification preference migration

See how a broad settings request becomes a migration-safe packet with opt-out preservation, duplicate-send evidence, and worker checks.

Open the notification case

Database schema change

See how a vague schema request becomes an expand/backfill/switch plan with parity checks, rollback boundaries, and cleanup timing.

Open the database case

AI PR scope drift

See how a broad AI-generated PR becomes a bounded review packet with allowed paths, non-goals, and changed-file evidence.

Open the AI PR case

Large report export

See how a CSV export request becomes an async job spec with permissions, state transitions, queue evidence, and failure handling.

Open the export case

When a quick rewrite needs a full case

A compact before/after rewrite is enough for small UI or copy changes. Promote it into a full spec packet when the implementation can silently change money, permissions, user consent, external contracts, migrations, or background jobs.

Shared contract

If another client, SDK, integration, or workflow consumes the result, add compatibility notes and fixtures instead of relying on prose.

State migration

If old records have to be backfilled, split the packet into expand, dry run, switch, and cleanup steps with a rollback signal for each phase.

Human trust

If the change affects billing, notifications, privacy, or consent, require evidence that proves existing user choices were preserved.

Rewrite rules behind the examples

The pattern is deliberately repetitive because the failure mode is repetitive: a request describes the desired output, but leaves the boundaries, risks, and proof implicit. The rewrite does not need to become a full PRD. It needs to answer the questions a reviewer will otherwise ask after the first AI-generated diff is already too broad.

A good rewrite names the actor, the current state, the trigger, and the observable result. It also states what should not change. For AI coding, the non-goal is often the most important line in the packet because it stops the assistant from "helpfully" rebuilding adjacent systems.

Keep

The user's intent, the operational risk, and the output that must be observable after the change ships.

Add

Non-goals, constraints, acceptance criteria, allowed implementation slices, and evidence required before merge.

Remove

Generic phrases such as "make it better", "handle edge cases", or "improve UX" unless they are tied to a testable state.

Quality checklist before using a rewrite

Can QA test it?

If QA would need to interview the author before writing a test, the acceptance criteria are still too vague.

Can review reject drift?

If a reviewer cannot point to a non-goal or allowed-file boundary, the packet will not stop an oversized diff.

Can release prove it?

If the evidence file only says "tests pass", add the exact command, fixture, screenshot, log query, or metric.

How to adapt these examples

Do not copy the domain details first. Copy the transformation. Start with the vague sentence your team would normally send to an AI coding tool, then force it through four filters: what behavior changes, what stays out of scope, which failure mode is most likely, and what proof should exist before the pull request is merged.

For small work, the rewrite may fit in a single issue comment. For risky work, split it into separate files so each artifact has one job. The spec owns behavior and boundaries. Tasks own implementation slices. Acceptance owns observable outcomes. Evidence owns proof. Keeping those roles separate makes the packet easier to review and easier to update when implementation reveals a new constraint.

The examples also show when to stop writing. Once a reviewer can understand the intended behavior, reject scope drift, and name the verification evidence, adding more prose usually makes the packet worse. The goal is not long documentation; the goal is enough structure that code generation has fewer hidden assumptions to execute.

Rewrite anti-patterns

These mistakes make a rewrite look tidy while leaving the implementation risk unchanged.

Renaming the vague request

Changing the title without adding boundaries leaves the same ambiguity for the implementer.

Listing tasks before behavior

Tasks are useful only after the desired behavior and non-goals are clear.

Evidence without owner

A checklist item is weak if nobody owns the test, screenshot, log query, or follow-up date.

Turn your own ticket into a packet

Use the generator when a request is clear enough to discuss, but still too vague to hand directly to an AI coding tool.

Generate a spec packet

Editorial note

These examples are maintained as practical teaching artifacts. Each one is written to show a concrete before/after move, not a generic best-practices list.