Atomic Spec — a methodology for collaboration between PM, Developer Agent, and Tester Agent. One source of truth. Full decision history. Every requirement's status — visible without a meeting.
git log spec.md — full history: who, when, why, at whose initiativegit diff release/v1..release/v2 — exact list of what changed in scenariosEach requirement is a separate .spec.md. Contains intent, domain rules, Gherkin scenarios, and platform contract. Adding a requirement = creating a file.
File in the folder root — verified and current. In _draft/ — has open questions. In _deprecated/ — history. Status is visible without opening the file.
Who changed it, when, why, at whose initiative — in the commit message. Diff between release tags — exact list of changes for each role.
Detailed instructions, file examples, git commands, and workflows — tailored for each role.
Not "I think we agreed on everything," but a precise answer: what's verified, what's in progress, what needs to be resolved right now.
Not "I think we agreed," but an exact delta: what changed in the requirements while you were working, and who decided it.
git log spec.md — full decision history. Decision Log explains why the alternative was not chosen.git diff main HEAD -- specs/ — make sure the requirement in your branch is up to date. If the analyst changed something in main while you were working — you'll see the diff.
Not "test everything," but an exact diff of scenarios between tags. What's new, what changed, what blocks the release.
git diff release/v1..release/v2 -- specs/ — exact list of files and scenario delta. Nothing extra.blocks-release: true + verification.status: none — the list of exactly those files. Everything else is secondary.§ Acceptance Criteria section between releases shows not the whole file, but only behavior changes.The state of every domain, open decisions, sprint risks — at any moment, straight from the repository.
All numbers from a single command. Real state, not what's written in a report.
domain/AUTH/v1.0 → v3.1 — three Breaking, one Additive.sprint-locked — an explicit conflict between a requirement and current development.blocks-release: true and verification: none — a precise answer: can we ship?The analyst is the atom owner. They create requirements, resolve open questions, and verify domain model changes. All analyst work is done in .spec.md files and PRs.
Each atom progresses through positions in the file tree:
| Type | When | Who Verifies | Blocks Sprint |
|---|---|---|---|
ParameterChange | Value change: timeout, limit, size | 1 stakeholder | no |
RuleChange | New, changed, or removed domain rule | Product + Tech | possibly |
FlowChange | New scenario step, branch change | Product | possibly |
ModelChange | New aggregate, field, event | Product + Tech + Architect | yes |
BoundaryChange | Aggregate transfer, domain split | CTO + Architect + Product | yes, RFC |
If a requirement changed while development is in progress, do not modify the original atom — create an amendment:
Open Questions are the only reason to be in _draft/. As long as there is at least one status: open, the file does not move to root.
| OQ Status | Meaning | Action |
|---|---|---|
open | Question is open, no decision made | File remains in _draft/ |
blocked | Depends on another OQ | File remains in _draft/ |
resolved | Decision made and recorded | If all resolved → PR to root |
AUTH-REG-030_github-oauth-registration.spec.md in _draft/AUTH~MODEL-003~model_identity-aggregate.spec.md in _draft/affects-atoms — all affected use-casesThe developer is the atom consumer. They read requirements, implement the platform contract, update implementation.status, and flag conflicts between requirements and implementation.
git diff main HEAD -- specs/. Make sure the requirement in your branch is up to date. The analyst may have changed something in main while you were working.
At the start of each workday — three commands:
The developer reads sections top to bottom, stopping at the needed level of detail:
| Section | What It Gives the Developer | Required |
|---|---|---|
§ Intent | Understand why this feature exists | yes |
§ Domain Rules | Invariants and business rules — must not be violated | yes |
§ Acceptance Criteria | Gherkin — what must work (test foundation) | yes |
§ Domain Model Touch | Which aggregates are created/modified | yes |
§ Platform: Web API | Exact API contract — endpoint, body, responses | yes |
§ Platform Tests | Ready-made test cases for implementation | take as-is |
§ Decision Log | Why it's done this way — decision context | when questions arise |
The § Platform: Web API section is the official contract. No need to ask the analyst "which endpoint", no need to check Swagger. Everything is in the file.
The analyst created an amendment file alongside your atom. What to do:
conflict.status in the amendmentsprint-locked → finish the current task as-is, amendment goes to the next PRpulled → task returned, implementation needs updatingamendment-status after your decisionconflict.resolution.
Create a leaf atom in _draft/ yourself, open an OQ, ask the analyst to close it. Do not invent behavior on your own — record the question.
Add a see-also link, create an OQ in both atoms, block the PR until resolved. The conflict must be visible to the analyst.
Wait until the analyst merges the ~model_ atom into main. Start implementation only after. ModelChange blocks the sprint — this is normal.
The tester is the atom verifier. They check that the implementation matches the scenarios in § Acceptance Criteria, update verification.status, and block the release on mismatch.
git diff release/v1..release/v2 -- specs/.
The diff of the § Acceptance Criteria section is the list of what needs re-verification:
The tester sees: the old test with 20s needs to be updated to 60s. A new scenario with account locking was added.
| blocks-release | verification | Action |
|---|---|---|
true | none | 🔴 URGENT — cannot release without this |
true | in-progress | 🟡 In progress — track |
true | passed | ✅ Done — not blocking |
false | none | ⬜ Can be done after release |
true | failed | 🔴 STOP — release blocked |
Update verification.status: failed, add a comment with details, create a bug report referencing the atom (spec: AUTH-REG-020). If blocks-release: true — the release is automatically blocked at the next check.
Open an OQ in the atom (the analyst gets the signal), do not close verification as passed. System behavior must match the scenario — not the other way around.
The old test (20s) needs updating to the new value (60s). The amendment file contains the exact was / becomes — use it as instructions for updating the test.
The manager is the system state reader. Atoms provide a complete picture without the need to gather statuses from the team: what is implemented, what is untested, which decisions are blocked, and what risks the current sprint carries.
Three signals that require management attention:
| Signal | Meaning | Action |
|---|---|---|
| sprint-locked in amendment | Requirement changed mid-sprint | Confirm decision: pull or amendment to next sprint |
| HIGH risk in use-case | High-risk feature in current sprint | Dedicate a separate PR, additional review |
| ModelChange not merged | Architectural change blocks sprint | Prioritize domain change review |
Before each release — four checks:
blocks-release: true + verification: none → list is emptyverification.status: failed → 0amendment-status: pending in Done tasks → 0status: open outside _draft/ → anomaly, requires attention| Metric | How to Calculate | Target |
|---|---|---|
| Ratio draft/active | Files in _draft / total active | < 20% — no long-standing uncertainties |
| Amendment frequency | Amendment files per sprint | 0-1 — requirements are stable before sprint |
| Verification lag | Days from implementation: done to verification: passed | < 5 days |
| OQ resolution time | Average time from open to resolved | < 3 days — no stuck decisions |
| Breaking per quarter | ModelChange + BoundaryChange tags | < 3 — architecture is stable |
Atomic Spec is a collaborative requirements methodology that combines four approaches into a single knowledge management system in a git repository.
| Approach | What We Take |
|---|---|
| Domain-Driven Design | Domain model (aggregates, events, bounded context) as the source of the team's ubiquitous language |
| Test-Driven Development | Acceptance criteria (Gherkin) inside the requirement itself — test and requirement are inseparable |
| Use Case Driven | Use cases as the atomic unit of functionality |
| Requirements-Driven | Requirements as living artifacts with history, not frozen documents |
The central idea: one file — one unit of knowledge. Atoms form a hierarchy, reference each other, and contain everything — from business intent to test cases and platform contracts.
git log on *.spec.md files? Yes → the methodology is applied correctly.
Five problems that Atomic Spec solves:
| Problem | How It Solves It |
|---|---|
| Requirements scattered across Confluence, Jira, Slack | Everything in one .spec.md file next to the code |
| Unclear why a decision was made | § Decision Log and git log — complete history |
| Tester doesn't know what changed | git diff release/v1..release/v2 — exact scenario delta |
| PM changed a requirement during sprint — team doesn't know | Amendment file with explicit conflict.status |
| Manager can't see the real status | File tree = live dashboard without meetings |
| Level | File | Cost of Change | RFC |
|---|---|---|---|
| System | system.spec.md | Critical — affects all domains | required |
| Domain | domain.spec.md | High — 3+ verifiers | recommended |
| Use Case | DOMAIN-TYPE-NNN_slug.spec.md | Medium — 2 verifiers | no |
| Scenario | DOMAIN-TYPE-NNN_slug.spec.md | Low — 1 verifier | no |
File = YAML frontmatter + Markdown sections. Sections go from abstract to concrete. Each role reads their own sections — no one is forced to read everything.
Three positions define the state of a requirement. A file is always in exactly one of them.
| Question | Answer Without Opening the File |
|---|---|
| Can it be taken into work? | File in the folder root → yes |
| Are there open questions? | File in _draft/ → no, stop |
| Is the requirement outdated? | File in _deprecated/ → history |
| Currently in development? | Open PR in git |
| Implemented? | implementation.status: done + merged PR |
| Tested? | verification.status: passed |
Each directory contains _index.md — a table of all files with quick status. This is the directory's live dashboard.
Frontmatter contains only what cannot be learned from git: structural links between atoms, open questions, and statuses on three axes (semantic, implementation, testing).
git log and PR description. No need to duplicate it in the file.
Each requirement change is classified before implementation. The type determines: who verifies, whether it blocks the sprint, whether an RFC is needed, and the radius of affected atoms.
| Type | What Changes | Example | Verifiers | Blocks Sprint |
|---|---|---|---|---|
| ParameterChange | Constant value | Timeout 20s → 60s | 1 stakeholder | no |
| RuleChange | Domain rule DR | Add attempt limit | Product + Tech | possibly |
| FlowChange | Scenario step, branch | Add resend step | Product | possibly |
| ModelChange | Aggregate, field, event | New Identity aggregate | Product + Tech + Arch | yes |
| BoundaryChange | Domain boundaries | Extract OTP domain | CTO + Arch + Product | yes + RFC |
PlatformChange | API contract | New field in response | Tech Lead | no |
When a requirement changes while the atom is already in development, the change is not made to the original file. A separate amendment file is created with an explicit conflict indication.
Three Scenarios when a change conflicts with the sprint:
| Situation | Action |
|---|---|
Atom is still in _draft/ or _ready/ | Update the file in place, record in changelog commit |
| In development, already pulled | Return to _ready/, update, reconsider sprint |
| In development or already done | Create an amendment file alongside, conflict.status: sprint-locked |
Different system levels are versioned differently because they have different consumers and different compatibility semantics.
| Level | Scheme | Logic |
|---|---|---|
| Domain | vMAJOR.MINOR git tag | MAJOR = ModelChange/BoundaryChange. MINOR = RuleChange/Additive. No PATCH. |
| Use Case / Scenario | Revision r1, r2, r3 | Linear history. The consumer looks at the diff, not "am I compatible." |
| Platform (API) | Honest semver | Consumer is code. Compatibility is technical. Semver works perfectly. |
| Amendment | No version | This is an event, not an artifact. Lives in git as a commit. |
Git is the decision journal. Commit message carries everything not stored in the file: who requested, why, and what it affects.
The same files provide different views for different roles. The key tool is git diff between the relevant tags or branches.
| Role | View | Tool |
|---|---|---|
| Analyst | Current requirements + open questions | main branch + files in _draft/ |
| Developer | Requirements delta in their branch | git diff main feat/... |
| Tester | What changed in release scenarios | git diff release/v1..release/v2 |
| Manager | Full picture + risks | _index.md + grep queries |
1. An atom is not deleted — it becomes deprecated. The file moves to _deprecated/ with deprecated-by and reason specified. A deleted atom breaks history.
2. Leaves are added, branches change minimally. New scenario = new file. Use-case change = diff with changelog in commit. The higher the level, the more conservative.
3. Atom scope is not expanded — a new one is created. Expanding scope = hidden contract change. Everyone referencing the atom silently gets different semantics.
4. Domain Rules — append only, never rewrite. DR changes are recorded with an explicit note: [updated: 2024-03, reason: security policy v3].
5. Open questions block implementation, not documentation. An atom with open OQ exists and is visible. The team knows the question exists, and does not make assumptions.
6. No domain change without an explicit decision. ModelChange and BoundaryChange require § Decision Log with alternatives and rationale.
7. PR boundary = domain risk boundary. Do not mix in one PR: domain changes + new scenarios, high-risk + low-risk, domain change + platform change.
Example: the authentication system went through 4 iterations. Here is how the tree changed and what it meant for the team.
Four complete cases — from file trees to atom examples, amendments, and domain evolution for different product types.
Context: the product integrates multiple payment providers — Stripe (international cards), Tinkoff (RU cards), SBP (QR code). Team: 1 PM, 3 developers, 1 QA. Two-week sprints.
Key challenge: each provider has its own rules, webhook formats, and refund logic. Adding a new provider must not break existing ones. The domain model must be provider-agnostic.
In Sprint-08, SBP returned a QR timeout of 10 minutes, although the NSPK documentation stated 15. After clarification, it turned out to be 10 minutes. The amendment arrived while the developer was already working on the feature.
The first two providers stored card data in Payment. When adding SBP, the model needed to be extended — SBP works differently. Solution: ProviderSession as a separate aggregate.
| Role | Looks At | Sees |
|---|---|---|
| PM | _draft/refund/ | OQ-1 open: SBP refund unknown → do not take into sprint |
| Dev | git diff main feat/sbp | PAY~MODEL-002 added ProviderSession — need a new repository |
| QA | git diff release/v1..release/v2 -- specs/ | New scenarios PAY-INI-030, 031, 032 — all blocks-release: true |
Context: a media platform for authors. Publications, drafts, categories, comments, SEO metadata. Started as a simple blog — grew into an editorial platform with roles over 6 months.
Key insight: the system seems simple, but has non-trivial evolution. Started with "publication = article", then drafts appeared, then revisions, then collaborative editing. Each step broke previous assumptions.
| Version | What Changed | Type | What Broke |
|---|---|---|---|
v1.0 | Post with content: string directly | Initial | — |
v2.0 | Content moved to Revision (edit history) | ModelChange | All use-cases that worked with Post.content |
v2.1 | Added review status to Post | RuleChange | DR-1 in BLOG-PUB-020 updated |
v3.0 | SEOMeta as Value Object | Additive | Nothing — new fields are optional |
Post.content in § Domain Model Touch are listed in the affects-atoms of the ModelChange file. The team knew the scope before development began.
After v3.0, the analyst made SEO-title required for publishing. The developer was already working on the publishing feature.
Context: the product is an AI assistant for customer support. Chats with history, model switching (GPT-4 / Claude / Llama), context window, memory, tools. Team of 4 people. Requirements change every week — this is the main challenge for the methodology.
Key complexity: AI products have vague requirements by default. "The bot should respond smartly" is not a DR. Atomic Spec forces you to formalize what seems obvious: maximum context size, behavior on model error, what counts as a "good" response.
AI products have 2-3 requirement changes per week. Atomic Spec has a special practice for such products:
| Situation | How to Handle |
|---|---|
| Model timeout changed | ~param amendment — one field, one verifier, one PR |
| Added a new model to enum | Additive in domain.spec.md — one line in the model |
| Truncation logic changed | ~rule amendment to CHAT-MSG-013 — product + tech verification |
| New tool type | New atom in tools/ — created in _draft/ while OQs are open |
| LLM provider switch | ModelChange — requires RFC, blocks the sprint |
The team decided to add Llama-3 support as a cheaper alternative. However, Llama has a different API, a different context limit, and no function calling. This is not just "adding a line to an enum".
Context: an e-commerce platform with multiple teams. Product catalog, cart, orders, delivery, returns. Each domain has its own team (2-3 people). This makes cross-team interaction a key challenge.
Main complexity: multiple domains interact through events. A change in one domain can unexpectedly break another. Atomic Spec makes these dependencies explicit through emits / consumes in frontmatter.
After team growth, inventory management was extracted into a separate INVENTORY domain. This is a BoundaryChange — the most expensive type of change, requiring an RFC.
When multiple teams work on the same repository, each team works with its own subtree but sees dependencies through system.spec.md.
| Team | Own Subtree | Watches Events | Risk |
|---|---|---|---|
| Team A (Catalog) | specs/catalog/ | Publishes StockChanged | Changing the event format breaks Team B |
| Team B (Cart + Order) | specs/cart/, specs/order/ | Consumes StockChanged, publishes CartCheckedOut | Depends on two other teams |
| Team C (Delivery) | specs/delivery/ | Consumes OrderConfirmed | Any change to ORD-010 requires verification |
emits in any atom is a Breaking change for all teams that have this event in consumes. Before any event change: find all atoms with this event in consumes and notify their teams.
Four different systems — one approach. See what an atom tree looks like, how a domain evolves, and how a team works with real requirements.
The system accepts payments through multiple providers: Stripe (international cards), YooKassa (Russian cards), SBP (instant transfers). This is a classic case where the atom structure from the OAuth providers example applies to the payment domain — one abstract Provider, multiple concrete implementations.
Key characteristics of this system for documentation:
Idempotency is not a technical detail but a business rule. It lives in domain rules of a use-case, not in the platform section. This allows a tester to verify it independently from the implementation.
| Iteration | What we add | Domain Changes | New atoms |
|---|---|---|---|
| v1.0 — Stripe | Basic payment USD/EUR | domain v1.0 — base model | 7 atoms |
| v2.0 — YooKassa | RUB cards, two-stage confirmation | domain v2.0 — Capture added | +5 atoms |
| v2.1 — SBP | QR code, push notification, 24h timeout | domain v2.1 — Additive, QR flow | +4 atoms |
Seems like a simple system — until you start digging into the details. Drafts, publishing, editing published content, versions, comment moderation, SEO metadata, tags — each of these features contains non-obvious domain decisions. This case shows how to grow from MVP to a full platform without rewriting atoms.
Key questions that will arise:
In the MVP there are no drafts, no versions, no tags. Just write and publish.
Adding comments. The first non-obvious question arises: what happens to comments when a post is deleted?
Tags — a simple feature with a non-obvious edge case: what if you delete a tag that has posts?
This is a Breaking change — the PostRevision aggregate is added. The Post model changes.
| domain v2.0 | domain v3.0 | |
|---|---|---|
| Post.body | string — stores text directly | removed — text in PostRevision |
| Post.title | string | removed — in PostRevision |
| PostRevision | no | new aggregate |
| Editing | mutates Post | creates PostRevision |
BLG~MODEL-001~model_post-revision-aggregate.spec.md must be merged and verified before the developer starts implementing BLG-PST-012 and BLG-PST-015. Otherwise — a conflict mid-sprint.
| Role | Can | Cannot |
|---|---|---|
| Author | create, edit own posts, publish | moderate others' comments, delete tags |
| Editor | everything Author can + edit any posts | delete users, manage tags |
| Admin | everything | — |
| Reader | read, comment | create posts |
Each role boundary is a separate Domain Rule in the corresponding use-case. Not in middleware code, not in a README — in an atom.
The most unconventional case for Atomic Spec: the system behavior is non-deterministic. The same input can produce different output. How to write requirements and tests for such a system?
The answer: we document not the expected exact response, but the expected behavior — intent classification, presence of a tool call, response structure, boundaries of the acceptable. Acceptance Criteria work with response properties, not with its exact content.
Three levels of testing an AI system — each answers its own question:
| Level | What we test | How we capture it in an atom |
|---|---|---|
| Structural | Correct call sequence: save → LLM → save response | Standard Gherkin with Then-steps for action order |
| Behavioral | Presence/absence of tool call, intent type, response structure | Then: response contains/does not contain X, tool was/was not called |
| Qualitative | Tone, accuracy, alignment with system prompt | § Quality Criteria — separate section, not Gherkin |
| Iteration | What we add | Domain Changes |
|---|---|---|
| v1.0 — Simple Q&A | Q&A without memory | Conversation without history |
| v1.1 — History | Previous message context | Additive: Message history |
| v2.0 — Tool calls | Weather lookup, knowledge bases | Breaking: Message.toolCalls |
| v2.1 — Escalation | Handoff to a live operator | Additive: escalated status |
| v3.0 — Agent | Multi-step tasks, planning | Breaking: Task aggregate |
The most complex case in terms of domain count and their interaction. Online Store consists of several independent Bounded Contexts that interact through events, not direct calls. Atomic Spec here solves the most important problem: who owns which requirement and how a change in one domain affects another.
A Saga is a System-level atom that describes cross-service interaction. It is not a use-case of a single domain — it is an orchestration of several.
| Iteration | What we build | Domains | Key decisions |
|---|---|---|---|
| MVP v1.0 | Catalog + Order + Payment (Stripe) | catalog, orders, payments | No cart — direct transition to order |
| v1.1 | Cart | +cart | Price snapshot in CartItem — INV-2 |
| v2.0 | Delivery | +delivery | Breaking: OrderConfirmed now requires delivery |
| v2.1 | Notifications | +notifications | Additive: subscribing to events from other domains |
| v3.0 | Returns | orders expanded | Breaking: new Return aggregate, compensation Saga |
AI agents (Claude Code, Cursor, Copilot Workspace and others) work effectively when context is structured, unambiguous and predictable. Atomic Spec solves three key problems of agent-driven development:
| Agent Problem | How Atomic Spec Solves It |
|---|---|
| "How do I know exactly what to implement?" | The atom contains § Platform Contract — a precise API contract with no room for interpretation |
| "Does my change break anything?" | emits/consumes explicitly show dependencies between domains |
| "Did I understand the business rule correctly?" | § Domain Rules — formalized DR-N, not prose |
| "Are the tests already written?" | § Platform Tests — ready-made test cases, the agent just runs them |
| "How do I update the task status?" | Frontmatter with explicit implementation.status fields |
The agent works with atoms following a strict protocol. The reading order follows the atom sections — from abstract to concrete:
Before the agent starts implementation, it receives a minimal sufficient context. Too much — the agent loses focus; too little — it starts guessing.
When the agent receives a task "add feature X" without an existing atom, it must first create the atom rather than write code. The order is strict:
During implementation the agent may discover that a requirement in the atom contradicts another atom, or that system behavior implies an undocumented rule. The correct algorithm:
The agent can automatically verify code compliance with atoms. This is one of the most valuable scenarios: no need to wait for a human for basic checks.
| Antipattern | Symptom | Correct Approach |
|---|---|---|
| Spec-blind coding | Agent writes code without reading the atom | Protocol: read all related atoms first |
| Silent assumption | Agent fills requirement gaps with its own logic | Create OQ, stop, escalate to human |
| Draft skip | Agent creates atom directly in folder root | Always via _draft/, moving is a separate PR |
| Mega commit | Atom + code + tests in one commit | Three separate commits: spec / implementation / tests |
| Status drift | Agent implemented but did not update implementation.status | Status Update is part of definition of done |
| Context overload | Agent reads all of specs/ before a task | Only target atom + domain + children + see-also |
| Rule invention | Agent adds a DR that is not in the atom | Only DR explicitly described by the Analyst Agent. Everything else is OQ |
A compact prompt for an AI agent working with an Atomic Spec repository. Contains everything necessary — nothing superfluous.
Add your project specifics to the base prompt as one block:
AI agents are a new type of team member. They write code, create tests, suggest refactoring. But they have a fundamental problem: no memory between sessions and no context about team decisions.
Atomic Spec solves this elegantly: the repository of .spec.md files is the agent's external memory. Everything needed about history, decisions, and current state is in files that the agent can read at any time.
.spec.md files before each task. Spec files are the interface between humans and agents.
| Problem | What Happens | How Often |
|---|---|---|
| Agent does not know "why" | Rewrites logic that seems illogical but was accepted for business reasons recorded in Decision Log | Every session |
| Agent does not know current status | Writes code for a requirement that is already deprecated or still in draft | Often |
| Agent does not see dependencies | Changes domain model not knowing it breaks other use-cases | During refactoring |
| Agent invents behavior | With incomplete context, hallucinates "reasonable" behavior instead of following the spec | On edge cases |
| No change versioning | Agent changes spec and code together without explicit classification of what changed | Constantly |
The agent operates in one of four roles depending on the task. The role determines which files to read and what to create.
| Agent Role | Task | Reads | Creates / Modifies |
|---|---|---|---|
| Implementer | Implement feature per spec | § Platform, § Domain Rules | Code, updates implementation.status |
| Spec Writer | Create / supplement atoms | domain.spec.md, neighboring atoms | New .spec.md in _draft/ |
| Test Writer | Write tests | § Acceptance Criteria, § Platform Tests | Test files, updates verification.status |
| Reviewer | Review PR with spec changes | Entire affected subdomain | Comments, OQ in atoms when problems found |
_draft/ and propose closing OQ, but moving the file to root (verification) is done only by a human via PR.
A ready-made prompt for insertion into system prompt or .cursorrules / AGENTS.md. Contains all methodology nuances in compact form.
PAY-REF-012_refund-after-sbp.spec.md in _draft/ with two open questions:PAY-INI-030a~param_sbp-qr-ttl.spec.md: was=15, becomes=10, conflict.status=sprint-locked.| Antipattern | How It Looks | Correct Approach |
|---|---|---|
| Silent expansion | Agent adds fields to API response that are not in the spec "for convenience" | Create OQ or PlatformChange amendment |
| Self-verification | Agent creates atom and moves it from _draft/ to root itself | Only PR + human approval = verification |
| Silent deprecation | Agent sees atom is outdated and deletes it "to clean up" | Move to _deprecated/ with reason |
| Scope creep | Agent adds functionality to atom because "it makes sense here" | New functionality = new atom |
| DR override | Agent changes business rule in atom because "it is better technically" | Create RuleChange amendment with justification |
| Draft bypass | Agent writes code immediately for a feature still in _draft/ | First close OQ → verification → then code |
Atomic Spec is not just documentation. For AI agents it is a machine-readable contract: what to do, what not to do, what is unknown. Agents do not interpret requirements — they execute them. This radically reduces the risk of hallucinations and deviations from team intent.
Key property: the atom explicitly separates knowledge from uncertainty. If information is not in the atom — the agent does not assume, it creates an Open Question and stops. This is the only safe way for agents to work with requirements.
| Without Atomic Spec | With Atomic Spec |
|---|---|
| Agent receives task text in free form → interprets → does something similar to what is needed | Agent reads atom → follows § Domain Rules → implements § Platform Contract → runs § Platform Tests |
| Unclear requirement → agent guesses | Unclear requirement → agent creates OQ → stop |
| Requirement change → agent does not know | Requirement change → amendment file → agent sees when reading |
| Boundary between domains → agent guesses | emits/consumes in frontmatter → boundary is explicit |
The multi-agent system architecture based on Atomic Spec is built from three specialized agents coordinated by the orchestrator:
Works with specification. Creates and updates atoms. Closes Open Questions. Classifies changes.
Reads ready atoms. Implements platform contract. Updates implementation.status. Writes tests with @spec.
Reads diff between releases. Runs tests. Verifies behavior against § Acceptance Criteria. Updates verification.status.
The orchestrator does not write code and does not create atoms directly. Its job is to manage the flow: determine which agent is needed, pass the correct context, receive the result, verify it is safe to proceed.
Each agent knows three states: working / stop-blocker / stop-escalation.
| Situation | Agent | Action | Signal To |
|---|---|---|---|
Atom in _draft/ | Developer | STOP | Orchestrator → Analyst Agent |
| Open OQ found | Analyst | STOP + record OQ | Orchestrator → human |
| Ambiguous contract | Developer | STOP + OQ in atom | Orchestrator → Analyst Agent |
| ModelChange detected | Analyst | STOP + create ~model file | Orchestrator → human (architect) |
| BoundaryChange | Any | STOP immediately | Orchestrator → CTO + architect |
| Verification: failed | Tester | STOP release + report | Orchestrator → Developer Agent |
| DR contradict each other | Developer | STOP + OQ in both atoms | Orchestrator → Analyst Agent |
| Amendment sprint-locked | Orchestrator | Decide: pull or next PR | Human (PM) |
Each task handoff is a structured message. The agent does not receive a "task as text" — it receives a context package:
Copy the content to a SKILL.md file in the repository root or pass it as a system prompt to the orchestrator agent. The file is designed as a self-contained instruction — the agent reads it once and works according to the methodology.
SKILL.md in the repository root. In the agent prompt: "Read SKILL.md and follow this methodology for all tasks with specs/". For Claude Code: add to CLAUDE.md. For Cursor: to .cursorrules. For Copilot: to workspace system prompt.
Atomic Spec gives the agent a structure for managing three sub-agents — Analyst, Developer, and Tester — without losing context and without improvisation.
Orchestrator Agent is the main agent that receives tasks from humans and manages three specialized sub-agents. Each sub-agent works strictly within its area of responsibility. The orchestrator never does the sub-agents' work itself.
| Sub-agent | Reads | Writes | Never Does |
|---|---|---|---|
| Analyst | domain.spec.md, existing atoms, git log | New .spec.md in _draft/, OQ, Decision Log | Code, tests, changing implementation.status |
| Developer | Atom + domain + children + see see-also | Code, implementation.status in frontmatter | Creating/changing atoms, making business decisions |
| Tester | § Acceptance Criteria, § Platform Tests, git diff | Test files, verification.status in frontmatter | Changing requirements, application code |
The orchestrator passes context explicitly as a JSON object. The sub-agent should not independently search for what it needs (except reading files by the provided paths).
| Situation | Orchestrator Decides | Escalates to Human |
|---|---|---|
| OQ with blocking: false | Continues, records for next iteration | — |
| OQ with blocking: true | — | Yes — formulates options clearly |
| Tests failed | Passes exact diff to developer | After 2 iterations without progress |
| ModelChange needed | — | Yes — ModelChange is human-only |
| New domain needed | — | Yes — BoundaryChange RFC |
| Amendment conflicts with sprint | Creates amendment, proposes two options | If sprint-locked — decision is human's |
| Analog already implemented | Points developer to reference file | — |
The orchestrator maintains session state — current status of all tasks in the sprint. This allows resuming work after interruption.
SKILL.md is a file that the agent (Claude Code, Cursor, Copilot Workspace) reads before starting work with the repository. It describes: what methodology is used, how the agent should behave, what roles exist and how to hand off control between them.
The file is written in machine-readable format with explicit sections. Each section addresses a specific agent operating mode.
SKILL.md file in the repository root. Fill in section "9. Project Context" for your stack and team. On each launch the agent will read the file and work per methodology without additional instructions.
| Sign of Correct Work | Sign of a Problem |
|---|---|
Agent creates atom in _draft/ before code | Agent writes code immediately without atom |
| On uncertainty: OQ + stop | Agent "guesses" behavior |
| Three separate commits: spec / impl / tests | Everything in one commit |
Every test has // @spec ATOM-ID | Tests without traceability |
| On conflict: creates amendment + escalation | Silently changes requirement in atom |
| JSON output between sub-agents | Unstructured text |