skill · phase: requirements
Requirements Phase
Purpose
Translate the ideation output (or the user's direct request) into precise, testable acceptance criteria.
Entry Criteria
{{glossary:scope}}
- Ideation phase complete (Full scope) OR instance created with Standard scope
- The instance is claimed by this session
Entering in a fresh session
Read only:
instance.yaml- the ideation artifact (
idea.md, orresearch-question.mdforspike) — Full scope only - the roadmap item this instance was promoted from — Standard scope, where it replaces the ideation artifact as input
- the always-read guidance layers named in
.aidlc/guidance/index.yaml(see The always-read rule (.aidlc/resources/rules/always-read.md)) .aidlc/context/constitution.md, when it exists- the spec corpus files in
.aidlc/specs/for the capabilities the change touches —aidlc spec showlists them
Not the ideation conversation — the artifact is what it was written for.
See The context rule (.aidlc/resources/rules/context.md).
Required Artifacts
requirements.md— User stories, acceptance criteria, scope boundaries, non-functional requirements
Instructions
{{glossary:artifact}}
- Gather requirements. If a Full scope, read the ideation phase's artifact for context (
idea.mdfor the feature templates,research-question.mdforspike;phase-ideation.yamlnames it). At Standard scope, read the roadmap item the instance was promoted from (roadmap-item.mdin its state directory). Ask the user to describe the desired behaviour only when there is neither. Unattended (AIDLC_UNATTENDED=1): no artifact and no item is a hard stop, per.aidlc/resources/rules/unattended.md. Read the always-read guidance layers from.aidlc/guidance/index.yaml— see The always-read rule (.aidlc/resources/rules/always-read.md) for which layers those are and when to reach for the fulllessons.md. Read.aidlc/context/constitution.mdwhen it exists and apply the constitution rule in.aidlc/resources/rules/constitution.md. - Write user stories. Use the format: "As a [role], I want [capability], so that [benefit]."
- Define acceptance criteria. Each criterion must be:
Specific and unambiguous
Testable (an observable outcome)
Independent (not relying on unstated assumptions)
Identified: write every criterion as a list item
- AC-<n>: <text>(bold variants- **AC-<n>**: ...and- **AC-<n>:** ...are also valid). AssignAC-1,AC-2, ... sequentially. IDs are never renumbered or reused — an amended criterion keeps its meaning or is retired: mark it- AC-<n> (retired YYYY-MM-DD, superseded by AC-<m>): <text>and issue a new ID. The testing-phase gate parses these IDs and fails on any active criterion without a referencing test.Shaped, when the criterion is a behaviour. Write the text after the colon in one of four shapes, each naming its own test — the condition to set up and the response to check:
- Event —
- AC-1: WHEN the user presses Save, THE SYSTEM SHALL write the draft to disk - State —
- AC-2: WHILE the draft is unsaved, THE SYSTEM SHALL show a dot in the tab - Unwanted —
- AC-3: IF the disk is full, THEN THE SYSTEM SHALL keep the draft in memory and say so - Optional —
- AC-4: WHERE autosave is on, THE SYSTEM SHALL save the draft every 30 seconds
A criterion that is not a behaviour — a performance budget, a docs change, a file that must exist — stays a plain sentence. A plain criterion is valid: the gate checks the ID, never the shape.
- Event —
- Set scope boundaries. Explicitly state what is NOT included.
- Non-functional requirements. Address performance, security, accessibility, and compatibility where relevant.
- Write the change as a spec delta.
.aidlc/specs/<capability>.mdsays what the system does today. Read the files your change touches, then endrequirements.mdwith a## Spec deltasection: one### ADDED <capability>: <requirement name>,### MODIFIED …or### REMOVED …block per change. ADDED and MODIFIED blocks hold the requirement's full new text, written as what the system does. MODIFIED and REMOVED blocks start withBase: <revision>, copied fromaidlc spec show <capability>. Capabilities are lowercase kebab-case names; a new one is created by its first ADDED block. Runaidlc spec fold <instance> --dry-runbefore the phase closes — it reports every error and conflict, and the same fold runs at completion, where a conflict blocks it. Skip the section when the change alters no lasting behaviour, as most bugfixes do not. - For open decisions: When a decision would change what
requirements.mdsays, ask it through the Question Protocol (.aidlc/resources/rules/question-protocol.md) — questions for this phase go to.aidlc/state/<instance>/requirements-questions.md. Prefer draftingrequirements.mdearly with the unresolved points marked as explicit decision blocks: users decide better reacting to a concrete draft than answering abstract questions. Fold each answer into the draft and leave the question file as the record of what was decided and why. A question the roadmap item's## Decisionssection answers is not asked — its author answered it at capture: write the answer intorequirements.md, citingroadmap-item.md## Decisions.
Bugfix Reproduction (bugfix template)
When the instance uses the bugfix template, this phase produces reproduction.md and a bugfix-shaped requirements.md:
- Reproduce first. Capture: observed behavior, expected behavior, minimal reproduction steps, affected versions/environment. A bug that cannot be reproduced gets documented as such — with the evidence tried — before any fix work.
- Acceptance criteria for the fix follow the same
AC-<n>ID rules as regular requirements (the reproduction steps typically become the test). - Write
requirements.mdin three sections, in this order. The testing gate reads criteria fromrequirements.mdonly, so they go here, not inreproduction.md:- Current behaviour — what happens today. Description only; no IDs.
- Expected behaviour — what the fix makes happen. Each line an
AC-<n>criterion. - Unchanged behaviour — what works next to the fix today and must still work after it. Each line an
AC-<n>criterion, so the gate demands a test for it. If you find nothing, write "None found" and say why; never leave the section out.
- Propose defect linkage (
caused_by). Identify which instance(s) likely introduced the defect:git blamethe defective lines and match commits to instance branches (fix|feat|chore/<YYYYMMDD>-<name>)- Query the knowledge graph for the module's history
- Check instance state dirs and the registry for names
Present the candidates as guesses with the evidence. The user confirms, edits, or declines —
caused_byis never written without explicit user confirmation, and declining leaves the field absent (absent = unknown, never an error). Unattended (AIDLC_UNATTENDED=1): a hard stop, per.aidlc/resources/rules/unattended.md.
- Write the confirmed linkage to
instance.yamlas a list:caused_by: [<instance>, ...](single cause = one-element list). Validate every name against existing state dirs or registry entries — an unknown name needs re-confirmation; reject the bugfix's own name (no self-reference).
Exit Criteria
requirements.mdexists with at least one user story and corresponding acceptance criteria- Each acceptance criterion is testable (has an observable pass/fail condition)
- The phase ends by naming each open decision — asked through the Question Protocol (
.aidlc/resources/rules/question-protocol.md) in.aidlc/state/<instance>/requirements-questions.md— or by saying "Nothing open", written intorequirements.mdas a line of its own: autopilot reads that line to skip a pause with nothing to decide. Do not ask the user to confirm the whole document. Unattended (AIDLC_UNATTENDED=1): nothing is confirmed or logged; hard-stop when the requirements reach beyond the roadmap item, per.aidlc/resources/rules/unattended.md.
Guidance
{{context:style-guide}} {{guidance:secure-defaults}}
Security Confirmation
If requirements reference sensitive data handling, authentication flows, or access control:
- Explicitly document the security requirements as acceptance criteria
- Flag that a security review will be needed before deployment
- Never embed credentials or secrets in requirement examples
Completion
When exit criteria are met, update phase-requirements.yaml status to complete and append a transition record to transitions.log.
Then end the turn as The next-steps rule (.aidlc/resources/rules/next-steps.md) says.
Amending a Completed Phase
A completed phase's artifact is changed only through an amendment. Editing
requirements.md after its phase closed leaves phase-requirements.yaml saying
complete, leaves the design and the code describing the old criterion, and leaves every
gate passing — because gates check that artifacts exist, not that they still agree with
each other. That is silent drift, and it is the most common real-world mess in any
lifecycle.
To change a criterion after its phase closed:
Edit the definition bullet in place into the retired form —
- AC-<n> (retired YYYY-MM-DD, superseded by AC-<m>): <one-line summary of what it said>— and add the replacement as a new criterion with a fresh ID. IDs are never renumbered or reused.Append an amendment section to
requirements.md:## Amendment 1 — 2026-09-07, after the design review - **Retires:** AC-4, AC-9 - **Issues:** AC-31 - **Reopens:** design - **Reason:** the customer integration needs JSON as well as CSVField bullets accept
Retires:,**Retires**:and**Retires:**alike. AC lists take wholeAC-<n>tokens only —AC-4..AC-6is not a range and contributes nothing. A wrapped bullet is still one bullet.Run
aidlc amend <instance> --impactto see which tasks, tests and artifacts still cite the retired criteria. It ends with one line naming the smallestReopens:the write will accept:none, or the earliest completed phase that still cites a retired criterion.Put the phases you actually want reopened in
Reopens:, then runaidlc amend <instance>. It reopens that phase and every phase between it and the current one, re-arming their gates, and records atype: reopenentry intransitions.logso the churn is visible in history rather than reading as a normal forward pass. From testing onwards it requires--confirm, which only a person can give: the command refuses it without a terminal or underAIDLC_UNATTENDED=1, so ask the user to run it.When the correction is confined to the phase you are in — nothing in a completed phase cites what you retired — write
Reopens: none(naming the current phase means the same). The amendment is recorded and nothing is reopened.aidlc amendchecks rather than trusts this: it refuses anyReopens:,noneincluded, that would leave a completed phase citing a retired criterion, and prints the line it would accept. No flag skips that check.
Amendments append; the definition bullet's status changes. Never rewrite an amendment that has already been applied — write the next one.