← Back to Index

Lesson 12

Specs as Living Artifacts

Shifting How You Think About Specs

You already use spec mode - but if you've been treating specs as planning scaffolding that you discard once the feature ships, this lesson reframes them as living verification artifacts that serve multiple purposes over the life of the code.

The key shift: specs aren't just "how we planned the work." They're the source of truth from which code and tests are independently derived. They're the "why" that outlives any particular implementation.

The Two Spec Types

Kiro has two distinct spec types, each modelling a different development workflow:

Feature Specs

For building new capabilities. Two workflow variants:

VariantStarting pointFlowBest when
Requirements-FirstWhat the system should doRequirements → Design → TasksYou know the behaviour you want but not the implementation
Design-FirstHow to build it technicallyDesign → Requirements → TasksYou have a technical approach in mind and want to formalise it

Both produce the same three artifacts:

  1. Requirements - what the system shall do (EARS notation)
  2. Design - how it will be built (architecture, data model, interfaces)
  3. Tasks - discrete implementation steps Kiro executes

You can't switch variants mid-spec. If you need to change approach, create a new spec.

Bugfix Specs

For fixing defects. Models how experienced developers approach bugs:

  1. Root cause analysis - identify why the bug exists, not just what it does
  2. Fix design - what should change AND what should NOT change
  3. Regression prevention - ensure the fix doesn't break existing behaviour

The "explicitly preserve what shouldn't change" part is key - it prevents the fix from being broader than necessary.

When to use which: Building something new → Feature Spec. Something is broken → Bugfix Spec. The workflows are fundamentally different - a bugfix spec focuses on surgical change and preservation, not on designing from scratch.

How to initiate each type

When you start a Spec session, you should see the choice between Feature Spec and Bugfix Spec. The exact UI may vary by Kiro version - look for a type selector when creating a new spec, or describe your intent clearly ("I need to fix a bug where...") and Kiro may route you to the bugfix workflow based on your description. If you don't see a choice, try explicitly stating "create a bugfix spec" in your prompt.

The Bug-as-Spec-Gap Pattern

When a bug appears in code that was built from a spec, ask: did the spec miss this case, or did the implementation deviate from the spec?

This is a diagnostic mental model - but it's also a prompt you can give Kiro directly. Point Kiro at the spec and the bug, and ask: "Does the spec cover this scenario? Are the property tests passing?" Kiro can read both artifacts and tell you where the chain broke.

DiagnosisAction
Spec was incomplete - didn't cover this scenarioUpdate the original feature spec with the missing requirement, then re-derive property tests for the new requirement. Fix only the affected area.
Code diverged from spec - spec is correct but code doesn't matchUse a bugfix spec to fix the code. The property tests from the original spec should already be failing - confirming the divergence.
Both - spec was ambiguous, code interpreted it wrongClarify the spec first, then fix the code. Re-run full PBT to verify.

This is powerful because it turns debugging into a structured process: check the spec, check the tests, identify where the chain broke.

Feature Spec Anatomy (What Lives in .kiro/specs/)

Each spec creates a directory:

.kiro/specs/
└── order-discount-rules/
    ├── requirements.md      # EARS-format requirements
    ├── design.md            # Technical design decisions
    └── tasks.md             # Implementation tasks (with status)

These are markdown files - human-readable, committable to git, reviewable in PRs.

Ad

EARS: Writing Requirements That Generate Good Tests

EARS (Easy Approach to Requirements Syntax) is the notation Kiro uses for requirements. It matters because property-based tests are derived directly from these statements - clearer requirements → better properties.

PatternTemplateExample
UbiquitousTHE [system] SHALL [behaviour]THE System SHALL display prices in GBP
Event-drivenWHEN [trigger], THE [system] SHALL [behaviour]WHEN a user adds an item to cart, THE System SHALL update the cart total
State-drivenWHILE [state], THE [system] SHALL [behaviour]WHILE the user is unauthenticated, THE System SHALL redirect to login
OptionalWHERE [feature], THE [system] SHALL [behaviour]WHERE premium subscription is active, THE System SHALL show ad-free content
UnwantedIF [condition], THEN THE [system] SHALL [behaviour]IF the payment gateway times out, THEN THE System SHALL retry once then show an error

Each requirement maps naturally to a property test:

The more structured your requirements, the better Kiro can derive properties.

Parallel Task Execution

When you click "Run all Tasks" on a spec, Kiro doesn't just run them sequentially. It:

  1. Builds a dependency graph from the task list
  2. Identifies which tasks touch the same files (never run in parallel)
  3. Identifies which are truly independent (run concurrently)
  4. Runs setup/infrastructure tasks first
  5. Runs independent implementation tasks in parallel via sub-agents

This connects directly to Lesson 8 (Sub-agents) - each parallel task runs in its own isolated context.

Spec Lifecycle: From Creation to Maintenance

Create spec → Define requirements → Generate design → Generate tasks
     │
     ▼
Execute tasks (parallel where possible) → PBT verifies each task
     │
     ▼
Feature ships → Spec stays committed in git
     │
     ▼  (months later)
Bug reported → Check: is spec incomplete or did code diverge?
     │
     ├── Spec gap → Update spec → Re-derive property tests → Fix code
     │
     └── Code divergence → Bugfix spec → Surgical fix → PBT re-run
     │
     ▼
Requirements change → Update spec → Kiro re-derives tests → Implement delta

Specs in Pull Requests

Since specs are committed to git, they appear in pull requests alongside the code. This transforms code review:

This is especially powerful for team code review - junior developers get clarity on intent, senior developers can review the design without reading every line of code.

Iterating on Specs

Specs aren't frozen after creation. If during implementation you realise a requirement is wrong, missing, or ambiguous:

  1. Update the requirement in requirements.md
  2. Regenerate affected tasks (or add new ones)
  3. Continue implementation from where you left off

The spec stays as the authoritative record of what changed and why. This is normal - specs evolve as you learn more about the problem. The key is that the spec always reflects current intent, not original intent.

Strategic Spec Management

Organising specs at scale

With hundreds of specs over time, organisation matters. Kiro stores specs flat in .kiro/specs/, but you can add structure:

Naming conventions:

Archiving completed specs:

Linking related specs:

In requirements.md, reference related specs: "See also: ../payment-processing/ for the upstream pricing model this depends on." This creates a navigable web of intent.

General principles:

Cross-cutting context lives in steering, not specs

Application-wide knowledge (architecture, conventions, shared patterns) belongs in steering. Each spec is self-contained for its feature but reads steering for the broader context. This avoids duplication across specs.

Meta-overview for humans

Consider maintaining a manual steering file or reference doc that indexes your specs by domain - not for Kiro (it reads specs directly) but for humans navigating the project:

---
inclusion: manual
---

# Spec Index
## Commerce Domain
- order-discount-rules/ — discount calculation logic
- payment-processing/ — Stripe integration, retry logic
- cart-management/ — add/remove items, persistence

## User Domain
- user-authentication/ — login, session, JWT
- notification-preferences/ — email/push settings

When to Create a Spec vs. Just Code

Use a spec whenJust vibe-code when
Complex feature with multiple requirementsSimple change you could describe in one sentence
You want PBT verificationPure UI/styling work
Multiple people need to understand the intentExploratory/prototype work
You need traceability (requirement → test → code)Quick fix where you already know the solution
The feature will be maintained long-termThrowaway or temporary code

Your Tangible Win

You now think about specs strategically: as living verification artifacts, not disposable plans. You know both spec types (feature + bugfix), both feature variants (requirements-first + design-first), how EARS requirements map to property tests, the bug-as-spec-gap pattern, parallel task execution, and how specs/steering/PBT form an integrated system.

Quiz

A bug appears in code that was built from a spec. The spec's property tests are passing. What does that tell you?

The spec likely has a gap - it doesn't cover the failing scenario. Update the spec first.
The code is correct and the bug report is wrong
Property-based tests are unreliable

You have clear requirements but no technical design yet. Which spec variant?

Requirements-First - start with behaviour, then derive design
Design-First - always start with architecture
Bugfix Spec - it handles any scenario

Application-wide conventions should live in:

Every spec's requirements.md
Steering files - specs read them for context but don't duplicate them
A single master spec