Feature Spec - one page, written before any code

Who fills this in: Product (with input from the table). When: in the first 10 minutes, before Gate 1. Why: this is Way #1: Describe before you generate - the contract and the tests are written from this page, not the other way round. Keep it to one page. If you can’t fill it in, you’re not ready to build (QUAL-PRINC-SHIFT-LEFT - prevent defects at inception).

Delete the quote-blocks before you hand it to the team. The worked snippet at the bottom is for the /recommend endpoint - copy its shape, don’t copy its content.


1. Problem - one sentence

What can’t the user do today? Whose pain is this?

e.g. “Alice can see her own assessment scores, but has no way to tell whether she’s ahead of or behind her team.”

2. Consumers - who calls this, and what they do with the answer

Name the caller and the screen/job. This is the API-as-a-product mindset (REQ-API-1). One endpoint serves real consumers - list them.

ConsumerWhat they do with the response

3. Success metric - pick exactly ONE

One measurable thing that tells you it worked. Resist the urge to list five. (ENG-PRIN-SIMPLE-STMT - YAGNI applies to metrics too.)

e.g. “The dashboard renders a per-dimension comparison with no client-side maths - the API does all the averaging.”

4. User stories - Given / When / Then

Behaviour, not implementation. Each story is independently demoable. Keep them small (ENG-PRIN-INCR-STMT).

  • Given [starting state] When [the user / caller does X] Then [observable result].
  • GivenWhenThen

5. Acceptance criteria - the checklist the demo is graded against

Concrete, testable, unambiguous. These become your contract assertions and your tests. “Done” = all boxes ticked (QUAL-PRINC-SDLC - Definition of Done).

  • Errors use the shared Problem envelope (REQ-API-5).

Worked snippet - /recommend (copy the shape, author your own for your endpoint)

This is what a frozen one-pager looks like for the deliberately-incomplete /recommend endpoint. The team writes this before touching ../../../../stacks/nextjs/openapi.yaml - then the OpenAPI RecommendResponse schema and the tests fall straight out of it.

Problem: Alice has two dimensions she scored as N/A (governance, business_impact) and no idea which lesson to start with. She needs the system to point at her biggest gaps.

Consumers:

ConsumerWhat they do with the response
Lessons page “Recommended for you” railRenders a ranked list: lesson title + a one-line reason + a gap indicator
Dashboard nudgeShows the single top recommendation as a call-to-action

Success metric (one): The top recommendation is always a lesson targeting the user’s largest gap, and the user has never already completed it.

User stories:

  • Given Alice has scored governance and business_impact as N/A, When she opens the Lessons page, Then the top recommendations target those two dimensions first.
  • Given Alice has already completed lesson-10 (AI Security Basics), When recommendations are computed, Then lesson-10 never appears.
  • Given two candidate lessons have the same gap, When they are ranked, Then the exploring-stage lesson is listed before building before applying.

Acceptance criteria:

  • gapScore = 1.0 − userDimensionScore. An N/A dimension (responded:false, value 0.0) therefore has gapScore = 1.0 - the maximum.
  • Lessons the user has completed (lesson-1, 4, 7, 8, 10) are excluded.
  • Exactly the top 5 recommendations are returned.
  • Sort order: gapScore descending, then lesson stage (exploringbuildingapplying).
  • Each item carries lesson, a human-readable reason, and gapScore (matches the Recommendation schema already in the OpenAPI file).
  • Errors use application/problem+json (REQ-API-5).

Expected top-5 against the seed data (use this to grade the demo - Alice’s gaps are governance 1.0 and business_impact 1.0):

#LessonDimensionStagegapScoreWhy it ranks here
1lesson-11 Responsible AI Usagegovernanceexploring1.0Max gap, earliest stage
2lesson-16 Measuring AI Productivitybusiness_impactexploring1.0Max gap, earliest stage
3lesson-12 Common AI Security Pitfallsgovernancebuilding1.0Max gap, later stage than #1
4lesson-17 AI ROI for Engineeringbusiness_impactbuilding1.0Max gap, later stage
5lesson-18 Innovation with AIbusiness_impactapplying1.0Max gap, latest stage

Note: lesson-10 (governance, exploring) would otherwise top the list, but it’s completed, so it’s excluded. That exclusion is exactly the kind of thing your contract test should catch.


Next stop: freeze the contract in ../../../../stacks/nextjs/openapi.yaml, then write the failing tests from test-pyramid-starter.md. Built at Innovation Day - the five ways: ways-of-working.md.

Downloads for this session

Grab the templates and sample files used here.