Chapter 03 · Week 3

Requirements: Saying Exactly What You Will Build

What makes a word trustworthy?

Chapter 3 — Requirements: Saying Exactly What You Will Build

“The hardest single part of building a software system is deciding precisely what to build.” — Frederick P. Brooks, Jr., “No Silver Bullet — Essence and Accident in Software Engineering” (1987)

“Let what you say be simply ‘Yes’ or ‘No’; anything more than this comes from evil.” — Matthew 5:37 (ESV)


Why This Matters

Two weeks ago you had nothing. Last week you had three candidate ideas and you killed two of them on purpose. You are holding one project and a scoping memo that says, roughly, what it is and roughly why it is worth 240 hours. Roughly is where we stop.

This week you put on the hat of the business analyst — the person on a real team whose entire job is to stand between a vague human desire and a team of engineers who need to be told exactly what to build. On a funded product team that is one or two full-time people. This week it is you, and you are also the person they hand the work to, which means you get to discover the specific misery of receiving your own vague instructions.

You are in the requirements phase of the life cycle. It runs two weeks: this one for the functional requirements — what the system does — and next week for the ones nobody writes down, the non-functional requirements that quietly decide whether the thing is usable, secure, accessible, and maintainable. Everything downstream reads from what you write now. The technical specification in Week 6 is an answer to this document. The work breakdown in Week 7 is an estimate against this document. The test plan in Week 11 tests exactly what this document promised. The Week-16 rubric grades whether the thing you shipped is the thing you said you would ship. Get this wrong and you do not find out in Week 3. You find out in Week 12, when you discover you have built something nobody agreed to and there is no time to build the other thing.

Brooks is right, and he is right in an uncomfortable way. Deciding precisely what to build is harder than building it. Building it is a skill you have; you have been doing that since your first course. Deciding precisely — writing a sentence so unambiguous that a stranger could read it, build it, and hand you back the thing you meant — is a skill almost nobody teaches, and it is one of two or three things that separates a junior engineer from someone worth listening to. The industry’s evidence on this is directionally clear even where the exact numbers are disputed: a requirements defect is cheapest to fix the day it is written, more expensive when it reaches the design, and vastly more expensive when it reaches production. Barry Boehm’s work in the 1980s put famous multipliers on that curve; those specific multipliers have been argued about ever since, and you should treat them as a shape rather than a measurement. But nobody argues about the direction. A sentence you fix today costs you ten minutes. The same sentence, discovered wrong in Week 13, costs you a feature.

The AI thread runs hard through this week from both sides. As a tool, an assistant is genuinely useful here in one specific way: it is a tireless interviewer that will ask you the questions you have been avoiding, and it will enumerate edge cases faster than you can. It is genuinely dangerous in another: ask it to “write the requirements for my app” and it will hand you forty confident, fluent, plausible sentences, most of them vague, several of them for features you never intended, and none of them traceable to a human being who wants them. Generated requirements are the single most convincing bad artifact in this course, because bad requirements look exactly like good ones until somebody tries to verify one. As a workload, if your project has an AI feature, this is the week you learn to specify something whose output is probabilistic — which turns out to be possible, but only if you stop trying to specify the output and start specifying the envelope around it.

Which brings the week’s question, and it is not a soft one: what makes a word trustworthy? Your requirements document is a set of promises made in writing to people who are not in the room — your instructor, your user, the engineer who inherits the repository. Some documents can be trusted and some cannot, and the difference is not sincerity. Let’s find out what it actually is.


3.1 — Elicitation When the Stakeholder Is You

Elicitation is the industry word for finding out what a system needs to do. It is deliberately not “requirements gathering,” because gathering implies the requirements are lying around waiting to be picked up. They are not. Most of what a system needs to do exists only as unarticulated habit inside somebody’s head, and your job is to draw it out — which is what elicit means. The capstone has a specific problem here: you are frequently your own primary stakeholder. You picked the idea. You have opinions. And a stakeholder who is also the builder is the worst kind, because you will silently resolve every ambiguity in favor of whatever you already feel like building.

There are five elicitation techniques that work at capstone scale. Use at least three.

TechniqueWhat you doWhat it producesCost
InterviewSit with one real user for 30 minutes; ask about the last time, not the general caseFacts about current behavior; the workaround that is a feature request1 hour incl. write-up
ObservationWatch someone do the task without helpingThe steps they never mention because they are automatic30 min
Artifact analysisLook at what they use today — spreadsheet, whiteboard, group chat, paperYour data model, essentially for free30 min
Competitive teardownUse three existing tools for the same problem; log every annoyanceTable stakes you would have forgotten; the gap you are filling2 hours
The day-in-the-life walkthroughNarrate the whole task start to finish, out loud, in writingEvery step between the steps you were thinking about45 min

The single most productive question in requirements work is “walk me through the last time you did this.” Not “what do you need,” which produces a wish list, and not “would you use an app that…,” which produces politeness. The last time. The specific episode. People are unreliable about general preferences and remarkably reliable about what they actually did on Tuesday. Use the eight-question script in code/elicitation-interview-guide.md; it takes thirty minutes and it is the highest-value half hour in this chapter.

When you are your own stakeholder, run the interview on yourself in writing — but change the rules to compensate for your bias. Write the answers before you write any requirements. Then hand the notes to one other human and ask them to circle everything they do not understand. Every circle is an ambiguity you could not see because you already knew what you meant.

Coach’s Note — The workaround is the requirement. Whenever somebody describes an awkward thing they do to get around a problem — the spreadsheet tab named temp2, the text message they send themselves, the photo of the whiteboard — you have found a requirement that is already validated by the fact that a human was willing to do manual work to get it. Those are worth ten features you invented.


3.2 — Stakeholders, Personas, and the User You Will Never Meet

A stakeholder is anyone who is affected by the system or can affect it. A persona is a short, concrete, evidence-backed sketch of one class of user, written so that you can ask “would Dana do this?” and get a real answer.

Personas fail in a predictable way: students invent them. An invented persona is worse than no persona, because it launders your own preferences into something that looks like evidence. The rule is simple and it is graded: every persona names the evidence it came from. An interview date. An observation. A screenshot of the thing they use today. If you cannot name the evidence, the persona is a character in a story you are telling yourself.

Here is the running example’s persona set. PantryPilot — introduced last week — is a small web application that lets a shared household track what food it has, what is about to expire, and what can be cooked from it tonight. Your project is not a pantry app; the shape of the artifact is what transfers.

PersonaSketchNeedsEvidence
Dana, 22 — the organizerBuys most of the groceries. Keeps a whiteboard list that goes stale in four days.To see in ten seconds what will spoil this weekInterview 2026-02-03; photo of the whiteboard
Marcus, 21 — the passive housemateWill open the app only when something pings him. Will never enter data.To be told what to eat tonight without typing anythingInterview 2026-02-04
The next maintainerClones the repository in Week 17 knowing nothing.To understand what every feature was for, from the document aloneThe course’s own handoff test

That third one is not a joke, and it is the persona students skip. Somebody is going to inherit this repository — a grader, a future employer reading your GitHub, an engineer at the internship you get because of it. They are a stakeholder with real needs, and they are the only stakeholder guaranteed to exist. Chapter 13 will test them explicitly with a clean-machine walkthrough. Write them down now. Then refuse two anti-personas. “Users” is not a persona; it is the word people use when they have not talked to anyone. “Everyone” is worse — a system for everyone has no acceptance criteria, because there is no specific human whose success or failure you can observe.

Contrast helps. TraceLens — the book’s second example, a command-line tool that parses server logs and reports anomalies — has exactly one persona that matters: Priya, an on-call site reliability engineer, at 2 a.m., on a laptop, angry. One persona. No UI. No accounts. Every requirement in that project is shaped by the fact that Priya is tired and in a hurry, and that shape is completely different from Dana’s. Same process, different answers.


3.3 — User Stories, and What They Are Not

The user story is the most-used and most-misunderstood artifact in software. The canonical form, popularized by Mike Cohn in User Stories Applied (2004) and older than that in the extreme-programming community:

As a <specific persona>,
I want <a capability>,
so that <a benefit that matters to them>.

Here is what a user story is: a placeholder for a conversation, and a unit of planning. Ron Jeffries described it as three Cs — the Card (the short sentence), the Conversation (the discussion it triggers), and the Confirmation (how you will know it is done). The card is deliberately too small to build from. That is a feature. Here is what a story is not: a requirement. It is not verifiable. It has no identifier, no priority, no condition, no acceptance criteria, and no stated behavior when things go wrong. A backlog of forty stories is not a specification; it is a to-do list with feelings.

This trips up capstone students constantly, because agile teams in industry often do work from stories alone — and they can, because they have a product owner in the room to answer the conversation part, every day. You do not. Your conversation partner is a document you write now and read in Week 12, when you have forgotten everything. So in this course, stories are the input and requirements are the output. You write stories to think; you write requirements to build.

Screen every story with INVEST (Bill Wake, 2003) before it earns a requirement:

LetterTestThe failure it catches
IndependentCan this be built without three other stories?A story that is really an epic
NegotiableIs it a need, not a design?”I want a dropdown”
ValuableCan the persona say why they care?A story you wrote for yourself
EstimableCould you guess the hours within 2×?Hidden unknowns
SmallUnder about a day of work?An unbuildable blob
TestableCould someone else tell it was done?“so that it’s better”

Worked conversion. Dana’s story — “As Dana, I want to see what is about to go bad, so that I cook it instead of throwing it away” — passes five INVEST letters and fails the sixth: Testable. “About to go bad” has no definition, so nobody but Dana could tell whether it was done. Fixing that failure is what turns the card into FR-EXP-02 in the next section, and it is the only work the conversion actually required.

Coach’s Note — Write stories in the language your interviewee used, not in yours. If Dana said “go bad,” write “go bad” on the card and define it precisely in the requirement. The card is where their words live; the requirement is where your precision lives. Losing their words costs you the ability to check whether you drifted.


3.4 — The Anatomy of a Functional Requirement

A functional requirement says what the system does. In this course it has six parts, and it is not complete until all six are present.

PartQuestion it answersExample
IdentifierHow do we refer to this in a board, a test, a commit?FR-EXP-02
ActorWho or what triggers it?a signed-in household member
ActionWhat can they do?view
ObjectTo or with what?every pantry item
ConditionUnder what circumstance, with what bound?whose expiry date falls within the next seven days, ordered soonest first
PriorityMust, Should, Could, or Won’t this releaseMust

Assembled, in the house sentence shape: FR-EXP-02Expiring-soon view, Priority: Must — “A signed-in household member shall be able to view every pantry item whose expiry date falls within the next seven days, ordered soonest first.”

Rules for the identifier, and they matter more than they look:

  • Format FR-<AREA>-<nn>, or flat FR-<nnn> — pick one and never mix. The area-scoped form is what I recommend and what this chapter’s templates use: the prefix (INV, EXP, SCAN, REC, ACC) lets you read a test name or a commit message and know what part of the system it touches without opening anything. The flat form is legal too, and some of the book’s later worked artifacts use it. The linter accepts either and errors the moment it finds both in one document — because FR-014 and FR-EXP-14 are the same requirement to you and two different rows to every script you will ever write against this file. Decide this week; see Appendix B.
  • Assign once. Never reuse. Never renumber. When a requirement dies, mark it Withdrawn and leave the number in the document. Renumbering silently breaks every reference in your board, your tests, your commits, and your Week-4 traceability matrix. Students do this in Week 6 to “tidy up” and spend Week 11 confused.
  • The identifier is the join key for the whole course. Board card, branch name, test name, defect report, and the final rubric all point at it. git commit -m "FR-EXP-02: expiring-soon ordering" is a sentence your grader can follow.

On shall. It reads stiff, and that is exactly why it is used: “shall” marks a binding obligation and nothing else in English does that job as cleanly. Keep “should,” “may,” and “will” out of requirement sentences entirely — put the strength in the priority field, where it can be sorted and counted. A document where every requirement says “shall” and a separate column says Must/Should/Could/Won’t is a document you can filter. One where the strength is buried in the verb is a document you have to read carefully, forever. The industry standards say the same thing at more length. IEEE Std 830-1998 was the long-standing recommended practice for requirements specifications and has since been superseded; ISO/IEC/IEEE 29148 is the current requirements-engineering standard, and you should check its current revision rather than trusting a year quoted in a textbook. Both converge on the same short list of qualities for an individual requirement, and it is the list you are actually graded against: unambiguous, verifiable, singular, feasible, necessary, implementation-free, and traceable. Seven words. Tape them above your desk this week.


3.5 — Acceptance Criteria: How Anyone Else Can Tell It Works

A requirement without acceptance criteria is an opinion. The criteria are what make it checkable by someone who is not you — which is the entire point, because in Week 16 someone who is not you decides whether you built it.

The house form is Given a specific starting state / When a specific actor does a specific thing / Then a specific, observable result — borrowed from behavior-driven development (Dan North’s formulation, early 2000s), because it forces you to state three things students routinely skip: the starting state, the trigger, and the result.

The word doing the work is observable. “Then the item is saved” is weak — saved where, visible to whom? “Then the item appears in the household pantry list within one page refresh and is visible to every member of that household” can be checked by a stranger with no access to your code.

Every Must and Should requirement needs at least two criteria: the happy path and one thing going wrong. If you only ever write happy paths, you will build a system that works exactly once, in the demo, on your machine, with the data you seeded. Here is the pair for FR-INV-01:

Given a signed-in member on the pantry screen,
when they submit a name, quantity, unit, and expiry date,
then the item appears in the household pantry list within one page
     refresh and is visible to every member of that household.

Given a submission missing the item name,
when the member submits,
then the system rejects the submission and states which field is missing.

Notice what the second one did. It turned “validation” — a word you would have hand-waved — into a decision you have now made in writing: rejection, not silent default, with a message that names the field. That is a design decision made in Week 3 for free, instead of in Week 10 under pressure.

Three tests for a criterion. The stranger test: could someone who has never seen your code run this and get an unambiguous pass or fail? The number test: does every quantity have a number — “soon,” “recent,” “large,” and “several” are not numbers. The failure test: have you said what happens when the input is bad, the network is down, or the list is empty?

Coach’s Note — Write the acceptance criteria before you write any code for that requirement. Not because it is virtuous — because it is faster. Criteria written first take ten minutes and become your test names in Week 11. Criteria written afterward take an hour, because you will unconsciously write them to describe whatever you happened to build.


This is the section that pays for the chapter. Twelve real-looking bad requirements — the exact sentences that appear in capstone drafts every single semester — with their defects named from a fixed palette and a rewrite that would survive review.

The palette, which is also the palette the widget uses:

ambiguous · unverifiable · compound · solution-biased · missing actor · missing condition · unmeasurable


1 · “The system shall be user-friendly.”ambiguous · unverifiable · unmeasurable · missing actor

NFR-USE-01 (Should) — A first-time user who has never seen PantryPilot shall be
able to add their first pantry item within 90 seconds of first sign-in.
Acceptance: five first-time testers observed; at least four succeed under 90 s.

“User-friendly” is a quality, not a function, and qualities are real only when they are measured. This one is a non-functional requirement — Chapter 4 owns the category — but the move never changes: name the metric, the threshold, the condition, and the measurement method.

2 · “Users can manage their pantry.”ambiguous · compound · unverifiable · missing condition

FR-INV-04 (Must) — A signed-in household member shall be able to mark a pantry
item as consumed, which removes it from the active pantry list.
Acceptance: Given an item in the active list, when a member marks it consumed,
then it no longer appears in the active list.

Four requirements, not one — FR-INV-01 add, FR-INV-02 edit, FR-INV-03 list, FR-INV-04 remove, of which one is shown. “Manage” is a word that hides somewhere between two and eight features.

3 · “The system should send notifications when food is about to expire.”unmeasurable · missing condition · priority hidden in “should”

FR-EXP-05 (Should) — The system shall send one notification per household per
day, at a household-configured time, listing every item expiring within the
next three days, to each member who has enabled notifications.

Three decisions were hiding in “about to expire”: the window (three days), the cadence (one per day), and the recipient rule (opted-in members). Each was going to be decided anyway — the only question was whether you decided it in writing now or by accident in Week 12.

4 · “The app will use React and PostgreSQL to store the pantry data.”solution-biased · compound · missing actor

FR-INV-06 (Must) — Pantry items entered by any household member shall persist
across sessions and across devices, remaining available after the member signs
out and back in on a different device.

A requirement states the need; the stack is an answer to the need, and it belongs in an architecture decision record in Week 5. Write the technology into the requirement and you delete your own ability to change your mind — and throw away the reasoning that would have justified the choice.

5 · “The system shall handle errors gracefully.”ambiguous · unverifiable · missing condition

FR-SCAN-02 (Must) — When the product-lookup service does not respond within
five seconds, the system shall present the manual add-item form with any data
the member has already entered preserved.
Acceptance: Given the lookup service is unreachable, when a member submits a
barcode, then within six seconds the manual form appears with the barcode
retained and a message stating that lookup is unavailable.

“Gracefully” is not a behavior. Every real error case is its own requirement with its own defined behavior. You will not enumerate all of them; enumerate the three that will actually happen.

6 · “The system shall support barcode scanning and manual entry and bulk import from CSV.”compound · unverifiable as one unit · priority absent — Three requirements: FR-SCAN-01 (Should), FR-INV-01 (Must), FR-INV-07 (Won’t, this release). Splitting exposes the truth — two are core and one is an idea nobody asked for twice. Bundled together, all three would have been built.

7 · “As a user, I want the app to be good so that I like it.”missing actor · ambiguous · unverifiable · circular benefit

STORY  As Marcus, who will never enter data, I want to be told what to cook
       tonight, so that I stop ordering delivery three nights a week.
FR-REC-01 (Should) — A signed-in household member shall be able to request a
cooking suggestion based on the household's current pantry contents.

This is not a requirements problem, it is an elicitation problem. Go back to 3.1 and find out who “a user” is.

8 · “The system shall notify the user quickly.”unmeasurable · missing condition · mixes function with quality — Split it. The functional half is FR-EXP-05 above. The timing half is a non-functional requirement with a number: notification dispatched within five minutes of the configured send time, at the ninety-fifth percentile over a week. “Quickly” was doing two jobs badly.

9 · “Admins should probably be able to reset a user’s password.”hedged modality · missing condition · the actor may not exist

FR-ACC-04 (Won't, this release) — Administrative password reset. PantryPilot
has no administrator role. Members recover access by email link (FR-ACC-03).

Answer the real question first: does your system have administrators? “Should probably” is the sound of a decision not being made, and every hedge in a specification is a decision deferred to a version of you with less time.

10 · TraceLens: “The tool shall parse log files.”ambiguous · missing condition · unverifiable

FR-PARSE-01 (Must) — The tool shall parse log files in Common Log Format and in
newline-delimited JSON, writing any line it cannot parse to a rejects file with
its line number, and continuing without terminating.
Acceptance: Given a 10,000-line file with 12 malformed lines, when the tool
runs, then 9,988 records are parsed and the rejects file contains 12 entries
with their original line numbers.

Naming the formats converts an infinite obligation into a finite one. The rejects behavior is the part students forget and the part that decides whether the tool is usable at 2 a.m.

11 · TraceLens: “The tool shall detect anomalies efficiently.”ambiguous · unmeasurable · compound

FR-DETECT-01 (Must) — The tool shall report every one-minute interval in which
the count of HTTP 5xx responses exceeds three standard deviations above the
mean 5xx count for the preceding sixty minutes.
NFR-PERF-02 (Should) — The tool shall process a 1 GB log file in under 120
seconds on the reference machine named in the technical specification.

“Anomaly” had to be given an operational definition before anything could be built or tested. Notice that the rewrite is a genuine engineering decision — you chose a detection rule — and you now owe a rationale for it. That is what the rationale line is for.

12 · “The AI shall suggest good recipes.”every defect on the palette

FR-REC-02 (Should) — Given at least five items in the household pantry, the
system shall return between one and three recipe suggestions within eight
seconds, each listing the pantry items it uses and any ingredients not on hand.
Acceptance: against the fixed 20-case evaluation set committed to the repository,
at least 16 cases return 1-3 suggestions within 8 s, each using >= 3 on-hand
items, with zero suggestions presenting a missing ingredient as on hand.

You cannot specify what a probabilistic system will say. You can specify the envelope it must stay inside, and you can fix the evaluation set in advance. That is section 3.9, and it is the hardest idea in this chapter. Six worked requirements, with their rationale and source lines intact and set inside a real document, are in code/pantrypilot-requirements-sample.md; read it before you write your own, because seeing the finished shape saves an hour of guessing.


3.7 — MoSCoW, and the Discipline of Writing Down What You Will Not Build

MoSCoW — from the DSDM agile-delivery tradition — sorts requirements into four buckets, and the fourth is the one that matters.

BucketMeaningThe honest test
MustWithout it the release is not the thing you promisedIf this is missing, would you refuse to demo?
ShouldPainful to omit, but the release is still realWould you ship without it and feel bad?
CouldGenuinely nice; the first thing cut under pressureWould anyone notice it was missing?
Won’t (this release)A decision, recordedWill you be tempted by this in Week 12?

The discipline is a ratio. For a 240-hour capstone, aim for Musts at no more than about half your total requirements — because Musts consume the Week 9–12 construction budget and there is no slack behind them. When a draft comes in at 90% Must, the student has not prioritized; they have relabeled “everything” in project-management vocabulary. Force the ranking: if every requirement is critical, sort them anyway and look at what landed at the bottom. That is your real priority order, and now you can see it.

The Won’t-have list is a first-class deliverable, and Milestone 3 grades it, for three reasons. It is the only defense against scope creep — in Week 11 you will have an idea, everyone does, and without a written list you will build it because it is more fun than fixing the defect log. It shows judgment — a grader cannot distinguish a student who considered exports and rejected them from one who never thought about exports, unless the rejection is written down with a reason. And it protects you from your own demo: the features you did not build are not failures, they are decisions, and a decision you can defend in Week 16 is worth more than a feature you half-built.

A Won’t row has three columns: what you are not building, why not, and when it would be revisited. Five rows minimum. If you cannot find five things a reasonable person might expect and are not delivering, you have not thought about the boundary of your system yet.

Coach’s Note — The hardest No is the one you say to yourself. Half the items on your Won’t list will be features you thought of and were excited about. Write them down anyway, with the honest reason: “twenty-five hours the budget does not have.” That sentence, written in Week 3, is what lets you finish in Week 14 instead of shipping something broken in Week 16.


3.8 — AI at the Requirements Table: The Interview, and the Rewrite

There is a right way and a wrong way to point an assistant at requirements, and they produce artifacts that look nearly identical. The wrong way, which will be attempted this week by roughly everyone: “Write the functional requirements for a pantry-tracking app.” You will get thirty to fifty polished sentences in about eight seconds. They will be organized. They will use “shall.” Several will be vague in exactly the ways section 3.6 catalogued, a third will be for features you never intended (social sharing, gamified streaks, an admin dashboard), and none of them will trace back to a human being who wants them. It is a spectacular artifact and it is worth nothing, because a requirement’s value comes entirely from the fact that somebody who understands the problem decided it was true.

The right way uses the model as an interviewer, not an author. Three prompts that actually earn their tokens:

INTERROGATE  "You are a business analyst. I am building <one paragraph>. Ask me
twenty questions, one at a time, whose answers you would need before you could
write a requirement. Start with the ones I am most likely to have skipped. Do
not write any requirements."

FIND THE HOLES  "Here are my 24 functional requirements. Do not rewrite them.
List every situation a user could get into that none of these requirements
covers, and for each, name the identifier that should have covered it."

ATTACK ONE  "Here is one requirement and its acceptance criteria. Find every way
two different engineers could read this sentence and build different things."

Notice what all three share: the model never produces the artifact. It produces questions about the artifact, which you answer, in your words, from your evidence. INTERROGATE will surface half a dozen things you had not decided. FIND THE HOLES is the strongest use of an assistant in this entire chapter — enumerating unhandled cases is a genuine model strength and a genuine human weakness. ATTACK ONE is a free ambiguity review.

And the failure modes, which you must be able to name:

  • Invention. It will produce requirements for features nobody mentioned, stated with the same confidence as the ones you asked for. Every requirement in your document needs a Source: line naming a human, an observation, or your own recorded decision. A requirement whose source is “the model suggested it” gets deleted or gets a real source.
  • Vagueness that reads as polish. Generated requirements are fluent, and fluency is easy to mistake for precision. Run code/check_requirements.py over anything a model touched. It flags the weasel words the model reaches for by default.
  • Over-scoping. An assistant has no concept of your 240 hours. It will cheerfully specify a system that takes 900. You are the only one in the loop who knows the budget.
  • No accountability. This is the one that matters. A requirement is a promise, and a promise requires somebody who can be held to it. The model cannot be held to anything.

The spine rule for this week, stated plainly: the assistant may ask, enumerate, and critique. You decide, you write the sentence, and you sign it. Log every use in docs/ai-usage.md — which tool, which prompt shape, what you kept, what you threw away. That log is graded in Week 16, and an honest one with real “I discarded this” entries reads far better than a suspiciously empty one.


3.9 — Specifying a Feature Whose Output Is Probabilistic

If your project has an AI feature — a recommendation, a summary, a classification, a generated draft — you are about to hit a wall that most requirements teaching does not prepare you for. You cannot write “the system shall return the correct recipe,” because there is no single correct recipe and the same input will not always produce the same output.

The move is to stop specifying the output and specify five things around it.

What you specifyFor PantryPilot’s recipe suggester
The envelope — input preconditions, output shape and count, latency bound≥ 5 pantry items in; 1–3 suggestions out; within 8 seconds
The guardrails — what it must never doNever present an ingredient the household does not have as on hand; never state a nutrition or allergen claim
The fallback — behavior when the model is slow, unavailable, or returns garbageAfter 8 seconds or on a malformed response, show the three items closest to expiry with no suggestion, and say why
The evaluation set — a fixed set of inputs with a pass bar, written before you build20 pantry states committed to the repository; ≥ 16 must satisfy the envelope; graded by you against a written scale
The disclosure and the override — what the user is told, and how they refuse itOutput labeled as generated; the member can dismiss a suggestion, and a dismissed suggestion is not re-shown that day

Three points about that table are easy to skim past. The evaluation set is the acceptance criterion — fixed in advance, committed to the repository, and unchanged after you see the results. This is the same discipline a researcher uses when locking an analysis plan before collecting data, and it exists for the same reason: once you have seen the output, every failing case will look like a case that “doesn’t count.” The pass bar is a fraction, not a promise — “16 of 20” is an honest requirement for a probabilistic feature; “all suggestions shall be good” is a hope with a “shall” in front of it.

And the fallback is a Must even when the feature itself is a Should. Your third-party model endpoint will be slow or down at some point this semester, and the most likely moment is your Week-16 demo. A feature with no defined behavior under failure is a feature that will fail in front of an audience.

One accuracy note, because it will cost you money if you skip it: model pricing, free-tier allowances, rate limits, and context windows change frequently and vary by vendor and region. Do not write a number into your specification from memory or from a blog post. Look it up on the vendor’s own pricing page, write the number with the date you checked it, and put it in your assumptions section. Then set yourself a reminder to re-check before Week 14. A specification that says “as of 2026-02-09, the free tier allowed N requests per day — verify before release” is a professional document. One that states a limit with no date is a liability.


3.10 — Assembling the Software Requirements Specification

The document has nine sections. Copy code/srs-template.md into your repository as docs/requirements.md and fill it in; the numbering is what the Week-4 traceability matrix and the Week-16 rubric key off.

§SectionWhy a grader reads it
1Purpose and scopeCan a stranger tell what this is in thirty seconds?
2Stakeholders and personasIs there evidence a user exists?
3DefinitionsDid you define the words your requirements depend on?
4Assumptions and dependenciesDo you know what you are betting on?
5Functional requirementsThe bulk. This week’s work.
6Non-functional requirementsEmpty this week. Chapter 4 fills it.
7Out of scope (the Won’t list)Judgment, made visible
8Open questionsHonesty about what you do not know yet
9Document change logProof the document is alive

Two sections students leave empty and should not. Section 4, assumptions and dependencies: an assumption is something you are treating as true without proof — “the barcode service covers the products this household buys,” “my roommates will actually enter data.” A dependency is something external you rely on. Write both with an if-false clause, because in Week 7 you will build a risk register and this section is literally its raw material. An assumption without a consequence is a note; an assumption with a consequence is a risk you have already half-managed.

Section 9, the change log. This is the section that makes the whole document trustworthy, and it connects directly to this week’s question. Requirements change. That is normal and expected; a document that never changed across sixteen weeks means you were not learning. What separates a professional document from a student one is whether the changes are recorded. One row per change: date, what changed, why. A requirement quietly deleted in Week 11 because it got hard is dishonest. The same requirement moved to Won’t with a dated row saying “cut Week 11; integration cost exceeded remaining budget; see ADR-0006” is engineering.

Before you commit, run your own review pass — then run it mechanically with python3 check_requirements.py docs/requirements.md, using the linter in code/check_requirements.py. The script flags missing priorities, missing acceptance criteria on Musts and Shoulds, duplicate identifiers, weasel words, implementation names inside requirement sentences, and criteria that are not in Given/When/Then form. Run it against the provided sample first to see what a clean report looks like, then against your own draft to see the truth. It cannot tell you whether a requirement is right — no tool can — but it will find, in two seconds, every defect from section 3.6 that you left in.


3.11 — Interactive Lab: The Requirement Rewriter

Below this chapter on the website is The Requirement Rewriter. Do it before you write a single requirement of your own, and do the whole run — a dozen items — in one sitting.

Each item shows you a real-looking bad requirement. Your job is two-part. First, tag every defect from the fixed palette: ambiguous, unverifiable, compound, solution-biased, missing actor, missing condition, unmeasurable. Then type a rewrite. The widget scores your tags against the answer key, then shows the model rewrite with its identifier, its priority, and its acceptance criteria, and moves you to the next item with a running score.

Two things it teaches that reading cannot. The first is that most bad requirements have more than one defect, and students consistently spot one and stop. “The system shall handle errors gracefully” is not just vague; it is also missing an actor and missing every condition. Training yourself to keep looking after the first hit is the whole skill. The second is calibration: after twelve items you will have a felt sense for the shape of a bad sentence, and you will start catching your own mid-keystroke. That transfer is the point. Score under 70% on the tagging? Run it again before you open your own document. This is conditioning, and conditioning is cheap.


3.12 — What Makes a Word Trustworthy?

“Let what you say be simply ‘Yes’ or ‘No’; anything more than this comes from evil.” (Matthew 5:37, ESV)

Jesus is addressing a culture of oaths. People had developed an elaborate grammar of swearing — by heaven, by earth, by Jerusalem — and the grammar existed for a reason that will be familiar to anyone who has read a bad specification: plain speech was not trusted, so speech got inflated to compensate. If your ordinary yes might mean anything, you need an oath to signal that this time you mean it. And once oaths exist, they stratify: some bind you and some do not, and now there is a whole technology for sounding committed while remaining free.

His answer is not a better oath. It is a plainer word. A person whose ordinary yes is reliable has no use for an oath, because the oath was only ever compensating for a deficit of trustworthiness. Read the week’s requirements gallery again with that in your ear. “The system shall be user-friendly.” “The system should probably support exports.” “Errors shall be handled gracefully.” These sentences are not lies, and the student writing them is not dishonest. But notice what they are doing: they use the vocabulary of commitment — shall, the system, the numbered heading, the whole formal apparatus — while carefully retaining an escape hatch. In Week 16, when somebody asks whether the system is user-friendly, there is no answer that can be wrong. That is the point of the sentence. It is oath-language without obligation.

Vagueness in a specification feels like humility. It is not. Humility is “I do not know yet, and here is the open question with a date on it.” Vagueness is deniability — language engineered so that no future outcome can convict it. The verifiable requirement is the plain yes: a signed-in household member shall be able to view every pantry item expiring within seven days, ordered soonest first. Either it does that or it does not. There is nowhere to hide. That exposure is exactly what makes it trustworthy.

And the No is half the verse, which is the half students skip. The Won’t-have list is a document full of Nos, said plainly, in advance, with reasons. It is harder to write than the Musts, because a No forecloses something. Proverbs puts it sharply: “Like clouds and wind without rain is a man who boasts of a gift he does not give” (Proverbs 25:14, ESV). A requirements document that promises forty features and delivers twelve has not been ambitious. It has been clouds and wind. Twelve promised and twelve delivered is a smaller document and an incomparably more trustworthy one.

There is one more turn, and it is the one that keeps this from becoming legalism. Requirements change. You will learn something in Week 10 that makes a Week-3 requirement wrong. Is changing it breaking your word? No — concealing the change is. The psalmist praises the one “who swears to his own hurt and does not change” (Psalm 15:4, ESV), and there is real weight in that: sometimes keeping a commitment costs you, and you keep it anyway. But there is a difference between a promise abandoned quietly because it got inconvenient and a promise revised openly because the world turned out different than you thought. The change log in section 9 is where that difference lives. One row, dated, with a reason. It converts a broken promise into an honest revision, and it is the cheapest integrity you will ever buy.

Finally, the thing that makes all of this urgent this particular semester. An assistant can generate a hundred requirements in eight seconds, every one of them fluent, formatted, confident, and using “shall” correctly. What it cannot generate is the thing that makes a word trustworthy in the first place: a person standing behind it who can be held to it. Trust is not a property of a sentence’s grammar. It is a property of the relationship between the sentence and whoever signed it. That is why your name goes at the top of docs/requirements.md, and it is why “the model wrote it” will never be a defense in this course or in any job you take afterward. Let your yes be yes. Then be the kind of person whose yes means something.


3.13 — Common Pitfalls

Pitfall: Writing requirements backwards from the solution you have already designed in your head. Example: “The system shall display a modal dialog with a date picker for expiry entry.” You have specified a widget, not a need — and you have now made the design decision in the wrong document, with no rationale recorded. Fix: Ask “what does the user need to accomplish?” and stop there. Every technology and interface noun in a requirement sentence is a design decision that belongs in Week 5 or 6, where it will get an ADR and a defensible reason.


Pitfall: The compound requirement — two or three obligations wearing one identifier. Example: “The system shall allow users to add, edit, and delete items, and export them to CSV.” Fix: One requirement, one verifiable obligation. If the acceptance criteria need the word “and” between two independent outcomes, you have two requirements. Split them, give each an identifier, and watch how differently they get prioritized once they are separate.


Pitfall: Renumbering identifiers to tidy the document. Example: In Week 6 you delete FR-INV-03 and shift everything below it up, so FR-INV-04 is now a different requirement than the one your board card, your branch name, and your test file refer to. Fix: Never reuse and never renumber. Mark the dead requirement Withdrawn, leave the number in place, and add a change-log row. The identifier is the join key for your board, your tests, your commits, and your traceability matrix.


Pitfall: No Won’t-have list, so scope creep has nothing to push against. Example: Week 11 arrives, you get a good idea about a shopping-list feature, and you build it instead of fixing the four open defects, because nothing written down said not to. Fix: Five or more Won’t rows this week, each with a reason and a revisit condition. The list is not pessimism; it is the only mechanism that lets you say “already considered, already decided” without re-litigating it under time pressure.


Pitfall: Accepting an assistant’s generated requirements wholesale because they look professional. Example: Thirty-eight requirements pasted in, including an admin dashboard, social sharing, and a gamified streak counter that no interviewee mentioned and no persona wants. Fix: Every requirement carries a Source: line naming a human, an observation, or a decision you made and recorded. Anything sourced only to a model gets deleted or gets a real source. Use the model to ask questions (3.8), not to write sentences.


Pitfall: Requirements that exist because you want to learn a technology. Example: “The system shall deploy to a container orchestration cluster” — in a project with three users and no scaling requirement whatsoever. Fix: Learning goals are legitimate and belong in your charter, not disguised as user needs. If you genuinely want the experience, say so out loud in the rationale line: “no user requires this; included as a stated learning objective, budgeted at 8 hours, cuttable.” Now it is honest, and now it is cuttable.


3.14 — Where Your Hours Went This Week

Fifteen hours, realistically spent. Log them honestly in your hours log as you go — Week 7’s estimating work is only as good as the data you are collecting right now.

ActivityHours
Re-reading the Week-2 scoping memo; listing feature areas and fixing the ID scheme1.0
Persona work plus one real elicitation interview, including the write-up2.5
Drafting user stories and screening them with INVEST2.0
Writing functional requirements with acceptance criteria — the bulk of the week5.0
MoSCoW triage and building the Won’t-have list1.5
Self-review pass, running the linter, fixing what it found1.5
Reps, the weekly quiz, and committing everything (board, hours log, AI log)1.5
Total15.0

If you are well under, you almost certainly skipped elicitation and wrote requirements out of your own head. If you are well over, you are probably writing prose where a bulleted criterion would do, or designing while you specify. Both are common; both are fixable next week.


3.15 — Reps

The reps are in the exercises, and this week they are not warmups — they build the milestone piece by piece. Five of the twelve:

  • Rep 2 — build a persona set where every persona names its evidence.
  • Rep 3 — run the elicitation interview with a real human using code/elicitation-interview-guide.md.
  • Rep 6 — convert eight INVEST-screened stories into six-part requirements.
  • Rep 8 — the rewrite drill: five of your own worst sentences, defect-tagged and rewritten.
  • Rep 10 — run code/check_requirements.py over your draft and fix every error it finds.

Do the on-page Check Your Reps quiz when you finish the chapter — it is the ungraded rehearsal for Week 3 Quiz in Canvas, which is the graded one. Its real job is to tell you — this week, not in Week 12 — whether you are on pace.


3.16 — This Week’s Milestone

Milestone 3Milestone 3: Software Requirements Specification v1. You will produce docs/requirements.md in your repository: nine sections, eighteen to thirty-five functional requirements with identifiers and acceptance criteria, two to three evidence-backed personas, MoSCoW on everything, a Won’t-have list of at least five rows, dated elicitation notes, and the identifiers mirrored onto your project board. Remember the grading contract, because it is easy to misread this week. Milestones are graded twice — once as the 25% milestone line, and again as part of the 50% final, because the milestones are the final deliverable, produced one week at a time. A weak requirements document does not cost you a few points in Week 3. It costs you the milestone points now, the same artifact points again in Week 16, plus the four weeks of rework it causes in between. The full contract is in Appendix C.


3.17 — Coach’s Final Word

Here is the thing about this week that nobody believes until they have lived it: the requirements document is the cheapest place in the entire project to be wrong.

Right now, changing your mind costs a sentence. In Week 6 it costs a diagram. In Week 10 it costs code. In Week 13 it costs code, tests, documentation, and the demo you had already rehearsed. Every hour you spend this week arguing with yourself about what “about to expire” means is an hour that buys back five later. That is not a motivational claim; it is the arithmetic of the whole discipline, and it is why Brooks called this the hardest part.

You will be tempted to rush it. Requirements do not feel like progress — nothing runs, nothing renders, there is no green check mark. Sit with that. The discomfort of writing precise sentences before you get to build is the exact discomfort every senior engineer has learned to tolerate, and tolerating it is a large part of what makes them senior. So write the boring sentences. Number them. Give each one a way to be proven wrong. Say No, in writing, to five things you would enjoy building. Then sign the document with your name at the top, and mean it.

Let your yes be yes.

See you on Monday.


Up next: the exercises builds the specification rep by rep · Milestone 3 is Milestone 3, the Software Requirements Specification v1 · then Chapter 4 — the requirements nobody writes down, where every quality word you dodged this week finally gets a number. Reference appendices: Appendix A (your workbench), Appendix B (the document kit — templates with worked good and bad examples), Appendix C (the grading contract), Appendix E (glossary). Previous: Chapter 2.

Interactive Lab — Week 3
The Requirement Rewriter

Twelve requirements pulled from the places yours will come from. For each one: tick every defect you can name, type your own version in the box, then press Score this item. The palette marks which tags the key found and which you over-tagged, the panel beside your rewrite runs six mechanical checks on the sentence you actually typed, and the model answer arrives with its identifier, MoSCoW priority, and acceptance criteria. The defects overlap on purpose — read the note under each key.

Item 1 of 12 Defects found 0/0 · over-tagged 0 · rewrites checked 0
Kickoff meeting with your sponsor

The system shall be user-friendly and fast.

Step 1 — tag every defect in the sentence above

The lint is mechanical — it reads shape, not meaning, and a sentence can pass all six checks and still be wrong. Numbers in the model rewrites (2 seconds, 10 MB, 80%) are placeholders: on your project those come from your stakeholder and go in the specification beside the section that justifies them.

Check Your Reps

Week 3 Knowledge Check

Question 1 of 5
Here is a line from a capstone requirements draft. Using the chapter's fixed defect palette — ambiguous · unverifiable · compound · solution-biased · missing actor · missing condition · unmeasurable — which tags apply?
The system shall allow users to add, edit, and delete pantry
items, and export them to CSV.
Why: One requirement, one verifiable obligation. If the acceptance criteria need the word and between two independent outcomes, you have two requirements. The real payoff of splitting is priority: add, edit and delete may all be Must while CSV export turns out to be the Won't that nobody asked for twice. Bundled into one sentence, all four would have been built. Most bad requirements carry more than one defect — students spot one and stop, and training yourself to keep looking after the first hit is the whole skill.
Question 2 of 5
In Week 6 you delete FR-INV-03 and shift FR-INV-04 through FR-INV-09 up one number so the document reads cleanly. What does Chapter 3 say to do instead?
Why: Assign once. Never reuse. Never renumber. The identifier is what a board card, a branch name, a test name, a defect report, and the Week-16 rubric all point at — git commit -m "FR-EXP-02: expiring-soon ordering" is a sentence your grader can follow. Students tidy the numbering in Week 6 and spend Week 11 confused about which requirement a failing test belongs to. A dead requirement stays in the document, marked Withdrawn, with a dated change-log row explaining the decision. That row is also what turns a broken promise into an honest revision.
Question 3 of 5
Apply the chapter's three tests — the stranger test, the number test, and the failure test — to this acceptance criterion. What is wrong with it?
Given a user is on the app,
when they add an item,
then the item is saved.
Why: The word doing the work in a criterion is observable. Compare the chapter's version: then the item appears in the household pantry list within one page refresh and is visible to every member of that household — a stranger with no access to your code can execute that and get an unambiguous pass or fail. Then pair it with the failure case: given a submission missing the item name, when the member submits, then the system rejects the submission and states which field is missing. That second criterion just turned 'validation' from a word you would have hand-waved into a design decision made in Week 3 for free.
Question 4 of 5
Your draft has 24 functional requirements and 22 of them are labeled Must. What does the chapter say this means, and what is the fix?
Why: The discipline is a ratio, and it is arithmetic rather than attitude: Musts consume the Week 9-12 construction budget and there is no slack behind them. If every requirement feels critical, sort them against each other anyway and look at what landed at the bottom — that is your real priority order, now visible. The same honesty produces the other half of the milestone: a Won't-have list of at least five rows, each with what you are not building, why not, and when it would be revisited. Half of those rows will be features you were excited about, and writing them down in Week 3 is what lets you finish in Week 14.
Question 5 of 5
A classmate has 24 well-formed requirements with correct identifiers and two criteria on every Must. He has not spoken to a single human being; his three personas came out of his head. How does that land against Milestone 3?
Why: The rule is simple and it is graded: every persona names the evidence it came from — an interview date, an observation, a screenshot of what they use today. Milestone 3 also requires docs/elicitation-notes.md, dated, with every sentence marked F (fact about today), W (want), or O (opinion). The linter cannot rescue him, because no tool can tell you whether a requirement is right — only whether it is well formed. And this is exactly what the weekly quiz is for: it is the early-warning system, and a student who cannot answer this question in Week 3 finds out now rather than in Week 12.
YOU FINISHED. NICE WORK.