# The artifact chain

URL: https://developertoolkit.ai/en/method/lifecycle/artifact-chain/
Description: Turn a ticket into intent.md, spec.md, plan.md, a diff with test evidence, and review findings, each committed and accepted before the next stage starts.

The artifact chain is a sequence of committed files that carries a change from idea to production: `intent.md`, `spec.md`, `plan.md` with its task list, the diff with test evidence, review findings, and an incident record that becomes the next intent. Each stage reads the previous artifact, and a named person accepts it before the next stage starts.

You have a ticket that says "Add user notifications", and it is due Friday. You paste it into the agent, and it writes 400 lines that look plausible, miss half the requirements, invent a `notifications` table that clashes with your `events` table, and ignore your API conventions. The agent did not fail. It made architectural decisions nobody asked it to make, and nothing written down told it otherwise.

This page is for developers who run agents on real features and for tech leads who want every change to leave the same trail. It replaces the older "PRD → plan → todo" method on this site: the PRD became `intent.md` and `spec.md`, the plan became `plan.md`, and the todo list became the task section of `plan.md`.

## What the artifact chain gives you on your next feature

- Six artifacts, each with a template, an owner who accepts it, and the proof that goes with it.
- Six copy-paste prompts: interview you into an intent, read a spec for gaps, draft a plan, execute one task, check the diff for drift, and audit a codebase into plans.
- The plan-mode commands for Claude Code, Codex, and Cursor, and where each one's output has to end up.
- A way to check each hand-off with tests, acceptance criteria, and a drift review, so you do not have to read every line the agent writes.

## Which files make up the artifact chain?

Every stage ends by committing one artifact. The next stage begins by reading it.

| Stage | Artifact | Who accepts it | What proves it is done |
| ----- | -------- | -------------- | ---------------------- |
| Plan | `intent.md` | Product owner | Problem, outcome, and constraints are stated; open questions are listed, not guessed |
| Design | `spec.md` | Product owner, plus a tech lead on higher-risk work | Every requirement has an acceptance criterion that a test can check |
| Build | `plan.md` with its task list, then the diff | Engineer (routine); tech lead or architect (higher risk) | Each task names its files and the command that proves it |
| Test | Test output, build log, or screenshot diff attached to the PR | Code owner reviewing the PR | The commands in the plan's **Proof** section pass in CI |
| Deploy | Pull request with review findings | Code owner; release manager at the production gate | No open finding tagged Important |
| Maintain | Incident record, then a new `intent.md` | Service owner or on-call, then the product owner | The next intent links the incident |

Up to the plan, the artifact is markdown, because a product owner and an agent can both read and act on the same file. From build onward, the artifact is code and its records. The stage pages hold the full procedure for each file: [Plan](/en/method/lifecycle/plan/) for `intent.md`, [Design](/en/method/lifecycle/design/) for `spec.md`, and [Build](/en/method/lifecycle/build/) for `plan.md`.

**Where to put the files**

Keep one folder per feature in the product repository: `intent/<feature>/intent.md`, `intent/<feature>/spec.md`, and `intent/<feature>/plan.md`. Every prompt on this page uses that layout. If your team already keeps plans in `docs/plans/`, point the prompts there instead, but pick one layout. A separate intent repository is worth the overhead only when one intent spans many repositories.

## Name one source of truth for each artifact

Your process already tracks these artifacts, just not as markdown. Work items live in Jira, requirements in a tool with regulatory traceability, designs in Figma, and change approvals with a change board. Auditors accept those systems, so they are hard to displace.

For every artifact, name **one** system as the source of truth. Everything else holds a copy or a link. Pick one of the following configurations per artifact:

| Configuration | The authoritative record | How the agent works with it | Choose it when |
| ------------- | ------------------------ | --------------------------- | -------------- |
| Repository | The markdown file | Reads and edits the file; the ticket links the commit | Engineering owns the process, and you want one timestamp authority |
| Legacy system | The Jira, ServiceNow, or requirements-tool record | Reads the record at session start and writes the outcome back through an MCP server in the same session | Auditors or regulators already accept that system |
| Linkage only | Both, cross-referenced | Every file notes the record ID; every record holds the commit SHA of the file | You cannot pick a single source yet; start here |

The Legacy-system configuration needs an MCP server for that system. For Jira, use the Atlassian Rovo MCP server at `https://mcp.atlassian.com/v2/mcp`; for GitHub issues, the GitHub MCP server. Add the Atlassian server in your tool:

**Claude Code**

    ```bash
    claude mcp add --transport http atlassian https://mcp.atlassian.com/v2/mcp
    ```
    Then run `/mcp` in a session to sign in.

**Codex**

    ```bash
    codex mcp add atlassian --url https://mcp.atlassian.com/v2/mcp
    ```

**Cursor**

    Install the Atlassian plugin from Cursor's marketplace, or add the server to `mcp.json`:
    ```json
    { "mcpServers": { "atlassian": { "url": "https://mcp.atlassian.com/v2/mcp" } } }
    ```

For authentication options and other trackers, see [Atlassian MCP](/en/ecosystem/mcp/atlassian-mcp/), [project-management servers](/en/ecosystem/mcp/project-management/) for Linear and others, and [version-control servers](/en/ecosystem/mcp/github-mcp/).

## Walk one feature through the chain

The following steps take the notifications ticket from the opening scenario through the whole chain. Each step names its prompt.

1. **Capture intent.** When all you have is a one-line ticket, make the agent interview you rather than writing the intent alone. Commit the result as `intent/notifications/intent.md` and have the product owner accept it.

   **Copy-paste prompt: interview me into an intent**

   ```text
   I want to add in-app and email notifications when a teammate comments on a
   document. Interview me before writing anything. Ask one question at a time
   about users, triggers, delivery channels, opt-out, volume, edge cases, and
   constraints, and dig into the parts I have not thought about. When we have
   covered everything, write intent/notifications/intent.md with the sections
   Problem, Proposed outcome, Affected users and systems, Constraints, and Open
   questions. Put anything I could not answer under Open questions. Do not
   propose a design and do not write code.
   ```

   In Claude Code, the agent can ask through its `AskUserQuestion` tool, which gives you multiple-choice questions instead of a wall of text (present in v2.1.283).

2. **Write the spec, then have the agent read it for gaps.** Follow [Design](/en/method/lifecycle/design/) to produce `spec.md`. Before any plan exists, start a fresh session and have the agent read the spec against the code. This step catches the clashing table before it is written.

   **Copy-paste prompt: read the spec against the codebase**

   ```text
   Read intent/notifications/spec.md. Do not write or change any files.
   1. Restate each requirement in one sentence.
   2. List every ambiguity or gap, and the question that would close it.
   3. Find the existing code, tables, and API patterns this feature touches,
      with file paths.
   4. Flag every place where the spec conflicts with the current architecture,
      for example a new table where an existing one could be extended.
   5. List each requirement that has no testable acceptance criterion.
   ```

   Close each gap in `spec.md`, not in the chat. A decision that lives only in a conversation is lost when the session ends.

3. **Draft the plan in plan mode.** Plan mode lets the agent read the code without changing it. Ask for a plan that reuses what exists and ends with a task list.

   **Copy-paste prompt: draft plan.md with tasks**

   ```text
   Using intent/notifications/spec.md and what you found in the codebase, write
   intent/notifications/plan.md with these sections:
   - Files that change, with the existing file you use as the pattern for each.
   - Decisions: every choice with a real trade-off, the options, and your pick.
   - Tasks: an ordered checklist (- [ ]). Each task fits one focused session,
     names its files, states its acceptance check, and is followed by the test
     that proves it. Order by dependency: migration, then API, then UI.
   - Risks.
   - Proof: the exact commands that show the whole change works.
   Prefer dependencies already in package.json. Do not implement anything.
   ```

   Push back on the plan the way you would in a design review. For example: "The plan adds a `notifications` table. What are the trade-offs against extending `events`, and which one matches our existing patterns?" Then have the tech lead or the engineer accept `plan.md` and commit it.

4. **Execute one task per turn.** Each task is small enough to verify and to throw away. When the agent goes wrong on task 7, you lose task 7, not the feature.

   **Copy-paste prompt: execute the next task**

   ```text
   Read intent/notifications/plan.md. Implement only the first unchecked task.
   Then run the test named in that task and the lint and type checks. If they
   pass, tick the task in plan.md and commit the code and plan.md together with
   a message that names the task. If the implementation has to depart from the
   plan, stop and tell me what and why instead of improvising. Stop after this
   one task.
   ```

5. **Check the diff against the chain.** Before the pull request goes to a human, run a review pass that compares what was built with what was accepted. Put the same pass in a repository-root `REVIEW.md` (template below); Claude Code's managed Code Review reads it (Team and Enterprise; generally available per Anthropic, checked 2026-10-16). Local `/code-review` does not read it, so run the drift prompt below as an ordinary prompt instead. With Codex, pass it as the prompt: `codex review "Follow REVIEW.md. Compare this branch with main against intent/notifications/spec.md and plan.md."`. A custom prompt cannot be combined with `--base` (checked v0.157.1), so name the branch in the prompt.

   **Copy-paste prompt: drift review against spec and plan**

   ```text
   Compare the diff on this branch with main against intent/notifications/spec.md
   and intent/notifications/plan.md. Do not change code. Report:
   1. Files changed that plan.md does not list.
   2. Tasks ticked in plan.md without a test that exercises them.
   3. Spec requirements with no test, or with a test that cannot fail.
   4. Behaviour in the diff that the spec does not ask for.
   Tag each finding Important or Nit, and quote the spec line it relates to.
   ```

6. **Merge, then close the loop.** The pull request carries the review findings and the test evidence. When the feature causes an incident or reveals a missing requirement, the record becomes a new `intent.md` — see [Maintain](/en/method/lifecycle/maintain/).

## How do you enter plan mode in Claude Code, Codex, and Cursor?

The chain is the same in every tool. What differs is how you keep the agent read-only while it plans, and where the plan lands. In all three, the plan only counts once it is a committed file: that file is what CI, review agents, and the next session read.

**Claude Code**

    - Enter plan mode with Shift+Tab, `/plan`, or `claude --permission-mode plan`. From v2.1.283 (both release channels on 2026-10-12), interactive terminal and VS Code sessions start in auto mode, so switch to plan mode deliberately; `claude -p` and the Agent SDK (except on third-party providers or with telemetry off, where they start in auto mode from v2.1.285), sessions where settings set `disableAutoMode`, and sessions on a model that auto mode does not support still start in Manual.
    - Press Ctrl+G to open the proposed plan in your external editor and edit it before you accept it.
    - Ctrl+T toggles the built-in task list. Set `CLAUDE_CODE_TASK_LIST_ID` to share one task list across sessions. Treat that list as a working view; `plan.md` stays the record.
    - Run `claude -w notifications` to work in a new Git worktree, and `claude -c` to continue the most recent conversation.

**Codex**

    - Enter plan mode with `/plan` in the CLI.
    - The `update_plan` planning tool is off by default since v0.152.0, so Codex does not keep a live checklist unless you enable `tools.update_plan.enabled = true`. Keep the tasks in `plan.md`, where they survive every session.
    - Run `codex --worktree` for a session in a new managed Git worktree (v0.157.1), and `codex resume --last` to pick up the most recent session.
    - For one task at a time without a chat, pass the "execute the next task" prompt to `codex exec`.

**Cursor**

    - Pick Plan in the agent's mode selector. Plan Mode "creates detailed implementation plans before writing any code" (Cursor docs, checked 2026-08-28).
    - Save the approved plan into the repository as `plan.md` before you build, so reviewers, CI, and the other tools read the same file.
    - Run the drift-review prompt from step 5 in a new Agent chat, so the reviewer does not inherit the context that wrote the code.
    - Worktrees "let Agent work in isolated Git checkouts" (Cursor docs, checked 2026-08-28), which keeps a parallel task off your working branch.

For the full per-tool mapping of every stage, see [the tool map](/en/method/lifecycle/tool-map/).

## Templates for each artifact

Copy these shapes into your repository. Replace the `UPPER_SNAKE_CASE` placeholders.

### Template: intent.md

```markdown
# Intent: INTENT_TITLE
Author: AUTHOR_NAME (TEAM). Status: draft | accepted. Ticket: TICKET_ID

## Problem
WHAT_IS_BROKEN_OR_MISSING

## Proposed outcome
WHAT_BETTER_LOOKS_LIKE

## Affected users and systems
USERS_AND_SYSTEMS

## Constraints
CONSTRAINTS

## Open questions
OPEN_QUESTIONS
```

### Template: spec.md

```markdown
# Spec: SPEC_TITLE (from intent.md, accepted DATE)
Status: ready-for-plan

## Requirements and acceptance criteria
- R1: REQUIREMENT. Accepted when: CHECKABLE_CRITERION

## Architecture and design
DESIGN_DETAILS

## Out of scope
OUT_OF_SCOPE

## Skills and policies applied
- Security: POLICIES_APPLIED
- Brand and UX: GUIDELINES_APPLIED

## Flagged concerns
CONCERNS_FOR_POLICY_OWNERS
```

### Template: plan.md

```markdown
# Plan: PLAN_TITLE (from spec.md, accepted DATE)

## Files that change
FILE_LIST_WITH_REFERENCE_PATTERNS

## Decisions
DECISION: OPTIONS, CHOICE, REASON

## Tasks
- [ ] 1. TASK (files: FILES). Accepted when: CHECK. Test: TEST_COMMAND
- [ ] 2. TASK (files: FILES). Accepted when: CHECK. Test: TEST_COMMAND

## Risks
RISKS

## Proof
COMMANDS_THAT_SHOW_THE_CHANGE_WORKS
```

When the implementation departs from the plan, update `plan.md` in the same commit as the code.

### Template: REVIEW.md

```markdown
# Review instructions

## Passes
Run four passes and tag each finding with its pass:
- Bugs: logic errors, broken edge cases, subtle regressions
- Security: injection risks, authentication gaps, PII in logs
- Compliance: the change matches spec.md, plan.md, and design principles
- Drift: files changed outside plan.md, ticked tasks without tests

## Severity criteria
- Important: broken behaviour, leaked data, security vulnerability, policy breach
- Nit: formatting, naming, cosmetic refactors (cap at 5 nits total)

## Exclusions
Exclude generated code under src/gen/, dist/, and checks already enforced by CI.
```

If you would rather adopt the chain as a packaged framework, GitHub Spec Kit runs the same sequence through its `/speckit-specify`, `/speckit-plan`, `/speckit-tasks`, and `/speckit-implement` commands (github/spec-kit, checked 2026-09-26). See [Spec Kit](/en/ecosystem/frameworks/spec-kit/) and [spec-driven development](/en/workflows/plan/spec-driven-development/) for when plain markdown is enough.

## Should you plan with a stronger model than you execute with?

Planning and execution reward different things. The plan needs the model to read widely, weigh trade-offs, and notice edge cases. A well-specified task is comparatively mechanical. Follow the site-wide rule: start on your tool's default model, raise the effort for planning before you switch models, and switch only when your own evals show a gain.

When you do split the work, Claude Code has a built-in alias for it: `opusplan` uses Opus in plan mode and Sonnet for execution. In any tool, the committed `plan.md` is what makes the split possible, because the executing session reads the file rather than the planning conversation. For model choice, see [model routing](/en/developer-scorecard-guide/model-routing/) and [the models hub](/en/ecosystem/models/).

The same split scales to a backlog. One thorough session audits the codebase and writes plans. Later sessions, or parallel ones in separate worktrees, execute them.

**Copy-paste prompt: audit the codebase into plans**

```text
Audit this codebase for the highest-impact improvements: correctness bugs,
performance, security, missing tests, and tech debt. Do not fix anything. For
each finding, write a self-contained plan to docs/improvement-plans/NN-slug.md
with the files to change, the approach, the acceptance criteria, and the test
that proves it. Order the files by impact against effort. A separate session
will execute each plan without access to this conversation, so leave nothing
implicit.
```

## How do you verify each hand-off without reading every line?

Each artifact carries the evidence for the next gate, so a reviewer checks the evidence, not every line of the diff.

- **Spec to tests.** Every requirement in `spec.md` has an acceptance criterion. Turn each criterion into a failing test before implementation starts — see [executable acceptance criteria](/en/workflows/plan/acceptance-criteria/) and [test-driven development](/en/method/principles/test-driven-development/).
- **Plan to proof.** Each task names its test, and the **Proof** section names the commands. CI runs them; a human reads the result, not the code.
- **Diff to plan.** The drift review in step 5 flags files outside the plan and ticked tasks without tests. An agent runs it, and a human reads only the findings tagged Important.
- **Pull request to production.** The code owner accepts findings and test evidence; the release manager owns the production gate. See [reviewing agent pull requests](/en/workflows/ship/agent-pr-review/).
- **Chain completeness.** Before merge, confirm that the pull request links `intent.md`, `spec.md`, and `plan.md`, and that every task in `plan.md` is ticked or explicitly deferred.

Who signs off stays fixed: the acceptor column in the table at the top of this page. An agent can draft every artifact and review every diff, but it does not accept its own work.

## When the artifact chain breaks and how to recover

**The intent is too vague to plan.** "Make notifications better" cannot produce a spec. Run the interview prompt, and put everything the requester cannot answer under **Open questions**. Do not start the spec until the product owner closes them.

**The plan is too big.** A plan with 40 or more tasks is several features. Split it into milestones that each deliver something a user can see, and ship the first before you plan the second.

**The agent drifts from the plan in a long session.** The planning conversation falls out of the context window, and the agent starts improvising. Name the plan file in every prompt, clear the context between tasks (`/clear` in Claude Code, `/new` in Codex, a new chat in Cursor), and resume from `plan.md`, not from the chat. See [context windows](/en/workflows/context/context-windows/).

**The code and the plan diverge.** Someone fixed a bug the plan did not foresee and never updated `plan.md`. The next session then trusts a stale plan. Make "update `plan.md` in the same commit" a rule in `REVIEW.md`, and let the drift review catch the misses.

**The plan never left the tool.** The approved plan exists only in a plan-mode draft or a chat, so review agents and CI cannot read it. Commit it as `plan.md` before the first task runs.

**Two sources of truth disagree.** The Jira ticket says one thing and `spec.md` another. Check which system your configuration names as authoritative, correct the other one, and record the commit SHA or record ID in both.

**You skip the chain "just this once".** A one-file change can go straight to a task. Anything that touches a schema, a public API, or more than one layer gets at least `spec.md` and `plan.md`, because that is where the clashing-table class of mistake is caught.

## Checklist: is the artifact chain working in your repository?

- You can point to one home for `intent.md`, `spec.md`, and `plan.md`.
- Each artifact type has one named source of truth.
- A new contributor can find the last accepted `intent.md` and the `spec.md` and `plan.md` derived from it without asking anyone.
- Every merged pull request in the last month links its `plan.md`, and its tasks are ticked or deferred.

## Where to go next with the artifact chain

- [Plan: capture intent.md](/en/method/lifecycle/plan/) — The first link in the chain, step by step.
- [Executable acceptance criteria](/en/workflows/plan/acceptance-criteria/) — Turn each requirement in spec.md into a failing test.
- [Human in the loop](/en/method/principles/human-in-the-loop/) — When to intervene during execution and when to let the agent run.
- [The AI-native SDLC](/en/method/lifecycle/) — The six stages that the chain connects.
