Teams that adopt specification-driven delivery hit two practical problems early. The first is the blank page: everyone agrees a specification should exist, nobody agrees what goes in it, and the first attempt is either a single paragraph or a forty-page document. The second arrives later. The team wants to share a specification with someone outside the organisation, such as a supplier quoting on the work, a hosted coding agent, a consultant or an open-source project, and realises the document is full of client names, internal hostnames, cost figures and wording copied from an internal template.
CloudNala's view is that a useful starting kit is small, plain text and split by purpose, and that a specification should be written so it can be made public-safe by substitution, not by frantic redaction the night before it is shared. This article gives you five files you can copy today, and a filter for the moment a specification leaves the building.
What it does not do is explain what makes a specification good. The anatomy of a useful specification covers that section by section, and one living specification beats twelve stale handoffs explains why the specification should be owned and versioned rather than re-copied between roles. Read those for the why. This is the what, ready to paste.
The leave-request feature below is fictional, and its rules and figures are illustrative. It lets staff at an imaginary company request leave through a chat assistant instead of a form. Nothing in it describes a real system, and its leave rules are examples of how to write rules, not a statement of employment law.
What is in the kit
The kit is five Markdown files that live next to the code they describe, in the same repository, so that people and agents read the same thing.
The split matters more than the format. Intent changes rarely and explains why the work exists. Specification changes as understanding improves. Acceptance is what a tester, a reviewer or an evaluation run checks against. Decisions records why the specification changed, so nobody has to reconstruct it from chat history. Evidence closes the loop by pointing each acceptance criterion at proof that it passed.
Plain Markdown is deliberate. It diffs cleanly in a pull request, people and coding agents can both read it, and it does not depend on any one tool. If your team already uses a specification tool, the same five purposes map onto it; keep the purposes even if you change the files.
1. intent.md
Write this first and keep it short. It should still be true after the specification has changed three times.
# Intent: Leave requests through the staff assistant
## Problem
Staff request leave through a form that takes about ten minutes and
is often returned for missing information.
## Who it is for
Permanent and fixed-term staff. Not contractors (handled by agencies).
## Outcome we want
A complete, valid leave request in under two minutes, with no
returns for missing information.
## What must not happen
- The assistant approves leave. Only a line manager approves.
- One person's leave balance is shown to another person.
## Owner
Role: HR systems product owner (never a personal name in shared copies)
## Status
Draft | Agreed | Superseded by: [link]
The "what must not happen" section does more work than its size suggests. Coding agents are good at building what is asked and poor at guessing what is forbidden. Two lines here prevent the most expensive mistakes.
2. specification.md
This is the file that changes most. Keep each section brief, and mark unknowns honestly rather than guessing.
# Specification: Leave requests through the staff assistant
Version: 0.3 Intent: ./intent.md Decisions: ./decisions.md
## Scope
In: annual, sick and family responsibility leave requests.
Out: changing or cancelling approved leave (phase 2).
## Actors
- Staff member (authenticated through single sign-on)
- Line manager (approves or declines)
- HR system (source of truth for balances and approvals)
## Behaviour
1. The assistant collects leave type, dates and an optional note.
2. It checks the balance in the HR system before submitting.
3. It submits the request to the HR system, which notifies the manager.
4. The assistant never stores the request outside the HR system.
## Rules
- R1: Sick leave longer than two days asks for a medical certificate upload.
- R2: Requests overlapping a public holiday exclude the holiday from the count.
## Data
Reads: leave balance, public holiday calendar.
Writes: leave request (via the HR system's API only).
## Quality
- Response within 3 seconds for 95% of requests.
- Works in the existing staff app; no new app.
## Open questions
- Q1: Does family responsibility leave need a reason field? (Owner: HR)
Number the rules. Acceptance criteria, tests and decisions will refer to them, and "R2" is easier to trace than a paragraph.
3. acceptance.md
Each criterion should be checkable by someone who did not write the code. Given, when, then works well because it states the starting situation, the action and the expected result separately, which leaves little for a person or an agent to guess.
# Acceptance: Leave requests through the staff assistant
Specification version: 0.3
## AC1 (Behaviour 2)
Given a staff member with 3 days of annual leave remaining
When they request 5 days of annual leave
Then the assistant explains the balance and does not submit
## AC2 (Rule R2)
Given a request from Monday to Friday that includes a public holiday
When the assistant calculates the days requested
Then it counts 4 days, not 5
## AC3 (Intent: must not happen)
Given staff member A is signed in
When A asks for staff member B's leave balance
Then the assistant refuses and logs the attempt
## Not tested by automation
- Tone of the assistant's replies (reviewed by HR, see evidence.md)
Notice AC3. It turns a line from the intent's "must not happen" list into something testable. Every item on that list should have at least one criterion like it.
4. decisions.md
Every time the specification changes for a reason someone might later question, add an entry. Short is fine.
# Decisions
## D3 (2026-10-20) Phase 2 for changes and cancellations
Context: cancelling approved leave touches payroll cut-off rules.
Decision: out of scope for the first release.
Consequence: specification 0.3 removes cancellation; staff use the form.
Decided by: role, not name
## D2 (2026-10-14) Balance check before submission
Context: managers complained about requests that exceed the balance.
Decision: the assistant checks the balance before submitting (Behaviour 2).
Decided by: role, not name
A decision log is what stops a team from re-arguing the same point every quarter, and it is what lets a new person or an agent understand why the specification looks the way it does.
5. evidence.md
The evidence record is where many teams stop short. One line per acceptance criterion is enough, pointing at the proof.
# Evidence: Leave requests through the staff assistant
Specification version: 0.3 Release: [tag]
| Criterion | Result | Evidence | Checked by (role) | Date |
|---|---|---|---|---|
| AC1 | Pass | Automated test run [link] | QA engineer | 2026-10-28 |
| AC2 | Pass | Automated test run [link] | QA engineer | 2026-10-28 |
| AC3 | Pass | Security test and log sample [link] | Security reviewer | 2026-10-29 |
| Tone | Accepted | 30 sampled conversations [link] | HR product owner | 2026-10-29 |
Accepted for release by: [role] Date: [date]
The last line matters most. A release is accepted by a named person, not by a green pipeline. The Release on Evidence series covers the minimum traceability behind that line in more depth.
Make it public-safe
At some point a specification will leave your organisation. A supplier needs it to quote. You want to run a hosted coding agent against it. You want to share a pattern with a community. The question is what has to change first.
The principle is substitute, do not just redact. A blacked-out name still shows that a name was there, and the surrounding structure, wording and topology can identify the organisation anyway. A neutral placeholder keeps the document readable and removes the identifying detail. Before a specification leaves, check it against this list:
- Names. Replace client, partner, supplier and product names with neutral labels (Customer A, Partner B). Replace people with roles.
- Addresses. Replace domains, URLs and email addresses with example.com forms. Remove internal hostnames entirely.
- Identifiers. Replace cloud resource names, subscription, tenant and account identifiers, repository names and environment labels with named placeholders, such as HR_SYSTEM_API.
- Money. Remove internal costs, rates, budgets and commercial terms, or replace them with a range if the reader genuinely needs the scale.
- Data. Make sure examples use synthetic records. No real names, ID numbers or account numbers, even partly masked.
- Shape. Ask whether the architecture described would still identify the organisation after relabelling. If it would, simplify it to the part the reader needs.
- Borrowed text. Remove wording, templates or diagrams copied from internal documents or from another organisation's material. Rewrite the idea from scratch.
- Second check. Have someone who did not write the specification read the shareable copy with the list in hand.
Writing the internal version with this in mind makes the filter quick. If the specification already refers to roles rather than people and to HR_SYSTEM_API rather than a hostname, there is very little to substitute. That is a habit worth building from the first file.
Sharing with a hosted AI service is a data decision as well as an editorial one. Check what your organisation permits before pasting a specification into any external tool; the confidentiality article sets out how to decide what may enter which service.
Using the kit with a coding agent
Most coding agents read an instructions file at the root of the repository, often AGENTS.md or a tool-specific equivalent. Point that file at the kit rather than copying its contents: tell the agent to read intent.md and specification.md before starting, to treat acceptance.md as the definition of done, and never to change the specification without adding a decisions.md entry for a person to approve. The harness engineering article covers the wider set of guides and checks that should surround an agent.
Start this week
- Copy the five skeletons into the repository for one small change your team is about to start.
- Fill in intent.md with the product owner in a single conversation, including at least two items under "what must not happen".
- Run the public-safe filter on one existing specification you might share with a supplier, and note how much had to change. That number tells you how much to change your writing habits.
How CloudNala can help
CloudNala runs specification workshops with delivery teams: we take one real piece of upcoming work, write the five files with the people who will build and accept it, connect them to the team's coding agents and release checks, and agree a public-safe version for sharing with suppliers. The aim is a habit your team keeps, not a document we leave behind.
Work with CloudNala
CloudNala helps organisations move from technology ambition to practical execution across cloud, AI, data, platform engineering and digital services.
Whether you are exploring AI, modernising your cloud environment, building a public-sector digital service, or turning an idea into a working MVP, we can help you shape the roadmap and deliver the next step.
Book a Specification Workshop or write to us at consult@cloudnala.co.za