Skip to content

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, or research-question.md for spike) — 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 show lists 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}}

  1. Gather requirements. If a Full scope, read the ideation phase's artifact for context (idea.md for the feature templates, research-question.md for spike; phase-ideation.yaml names it). At Standard scope, read the roadmap item the instance was promoted from (roadmap-item.md in 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 full lessons.md. Read .aidlc/context/constitution.md when it exists and apply the constitution rule in .aidlc/resources/rules/constitution.md.
  2. Write user stories. Use the format: "As a [role], I want [capability], so that [benefit]."
  3. 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). Assign AC-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.

  4. Set scope boundaries. Explicitly state what is NOT included.
  5. Non-functional requirements. Address performance, security, accessibility, and compatibility where relevant.
  6. Write the change as a spec delta. .aidlc/specs/<capability>.md says what the system does today. Read the files your change touches, then end requirements.md with a ## Spec delta section: 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 with Base: <revision>, copied from aidlc spec show <capability>. Capabilities are lowercase kebab-case names; a new one is created by its first ADDED block. Run aidlc spec fold <instance> --dry-run before 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.
  7. For open decisions: When a decision would change what requirements.md says, 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 drafting requirements.md early 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 ## Decisions section answers is not asked — its author answered it at capture: write the answer into requirements.md, citing roadmap-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:

  1. 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.
  2. Acceptance criteria for the fix follow the same AC-<n> ID rules as regular requirements (the reproduction steps typically become the test).
  3. Write requirements.md in three sections, in this order. The testing gate reads criteria from requirements.md only, so they go here, not in reproduction.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.
  4. Propose defect linkage (caused_by). Identify which instance(s) likely introduced the defect:
    • git blame the 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_by is 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.
  5. Write the confirmed linkage to instance.yaml as 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.md exists 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 into requirements.md as 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:

  1. Explicitly document the security requirements as acceptance criteria
  2. Flag that a security review will be needed before deployment
  3. 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:

  1. 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.

  2. 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 CSV
    

    Field bullets accept Retires:, **Retires**: and **Retires:** alike. AC lists take whole AC-<n> tokens only — AC-4..AC-6 is not a range and contributes nothing. A wrapped bullet is still one bullet.

  3. Run aidlc amend <instance> --impact to see which tasks, tests and artifacts still cite the retired criteria. It ends with one line naming the smallest Reopens: the write will accept: none, or the earliest completed phase that still cites a retired criterion.

  4. Put the phases you actually want reopened in Reopens:, then run aidlc amend <instance>. It reopens that phase and every phase between it and the current one, re-arming their gates, and records a type: reopen entry in transitions.log so 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 under AIDLC_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 amend checks rather than trusts this: it refuses any Reopens:, none included, 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.