Purpose: define the gates a work item must pass before its
Statuscan be set todone. Prevents “done in name only” — items that look complete on a board but are buggy, untested, undocumented, or broken in the actual product.
The Definition of Done (DoD) is the hardest discipline in this methodology. Skipping it is the most common way the system fails. Read it carefully and apply it without negotiation.
Without an enforced DoD, items drift to done while still imperfect:
done while its test status still reads not-tested.Each of these creates downstream cost: the next contributor builds on a foundation they believe is solid and is not. The bug returns. The user finds the breakage. Trust in the backlog erodes.
The DoD prevents this by being a hard barrier. An item that has not passed every gate is not done. There is no partial credit. There is no “mostly done.”
If a gate cannot be ticked, the item stays at to-be-tested, under-review, or blocked. It does not move to done.
Every item must pass all of these before its status flips to done.
Review every file you changed. Check for:
If you find an issue, fix it. Then review again. Continue until you complete a full pass with zero issues found. One clean pass is the bar, not “I think it’s fine.”
This is a loop, not a single review.
Run the review as two questions in order, not one blurred pass:
**Done means:** acceptance criteria (and nothing it shouldn’t)? This is findings-verification — see 10_testing_and_verification.md “Three modes”.Where possible, the two stages get different eyes. The author is the worst-placed reviewer for stage 1 — they will tend to confirm the interpretation they already built. A fresh session or a second contributor (a human, or a different model — see cross-AI validation) catches “built the wrong thing, correctly,” the failure a same-author quality pass sails straight past.
The two stages order the review; this routes each finding. A defect enters the work at some layer — classify which one, and fix at that layer, not below it.
Note what this asks of stage 1. Checking “does the change satisfy the criteria?” can only ever produce Code- and Plan-layer findings; the reviewer must also ask “are the criteria themselves right?” — because a faithful build of a wrong goal still fails the user. That second question is the only thing that produces an Intent-layer finding, and it is the one an author reviewing their own work almost never asks.
| Layer the defect entered | Finding looks like | Route |
|---|---|---|
| Architecture — an external requirement changed and the shape the items were built on no longer fits it | “Every item here is fine and the thing they add up to is wrong.” | Surface as a strategy or pillar-level re-evaluation, never as a bug. Wedging new requirements into an architecture they invalidated is the plan-layer anti-pattern at larger scale, and it produces the codebase that “works” while every future item pays interest on it. |
| Intent — the approved goal itself is mistaken | “This does what the item says, and what the item says is wrong.” | Halt. Back to the human who approved it — this is a frozen-intent renegotiation, not a code fix. |
| Plan — goal fine; the approach or Code Map led the code astray | “The code faithfully implements a wrong approach.” | Fix the item body first, then re-derive the code from it. Never patch code to compensate for a wrong plan — the patch encodes the confusion permanently. |
| Code — goal and plan fine; implementation wrong | The ordinary bug. | Patch. This is the normal review-loop case. |
| Out of scope — real, but not this item | “While reviewing, I noticed X elsewhere.” | File it — FUTURE.md or a new item per scope-creep recovery. Don’t fix inline. |
| Invalid — the finding is wrong | A misread, a false positive. | Reject with a one-line reason (findings from cross-AI validation are candidates, not ground truth). |
Process top-down — a finding at any layer cancels the findings below it, because everything beneath will be re-derived anyway. Triage the layer first, then spend effort. The ladder does not stop at the item: the top rung is above every item in the epic, which is why it routes to a re-evaluation rather than to a fix.
The escape hatch: if the same item bounces at the architecture, intent or plan layer more than twice, stop looping and surface it to the human — repeated upper-layer findings mean the item wasn’t ready to work. This is the definition-side sibling of the attempt cap: that cap bounds how many times you retry a fix that keeps failing; this bounds how many times you re-derive from a definition that keeps proving wrong. Both end the same way — a human picks a disposition per handle / postpone / mark — never force, rather than the loop grinding on.
Run the project’s full test suite locally. Not just the new tests. Not just the file you changed. The full suite.
Before ticking this gate, ask once per behavior the change adds or alters: “if this behavior broke, would any test fail?” The output is not a list of bugs — it is a list of untested behavior changes. Each one needs a test; where a behavior genuinely can’t be automated, it takes the sanctioned route — manual-verified plus a regression-needed follow-up item (the hard rule) — never a skipped test left sitting in the suite. Two rules sharpen it:
For details on testing approach, see 10_testing_and_verification.md.
This is the gate that “tests pass” does not replace.
For any change visible in the user-facing product, perform end-to-end verification in the actual running application:
This is the most-skipped gate. It is also the most expensive to skip.
Before the loop is complete, verify:
| Dimension | What to check |
|---|---|
| Theme | Both light and dark themes if the product supports both. Many changes break one and not the other. |
| Viewport | The product’s primary target viewport FIRST (e.g., mobile-first products: verify at mobile width before desktop). Then secondary viewports. |
| Auth state | The relevant auth states for the change: logged-in, logged-out, gated, ungated. |
| Empty state | A user with no data — does the change still render and make sense? |
| Error state | When the API fails or the network is down, does the UI handle it? |
| Offline state | If the product supports offline use, does the change still work without network? |
Only the dimensions that can be affected by your change are required. A pure backend-tool change does not need viewport verification. But err on the side of checking — the cost of one extra check is small; the cost of shipping a broken state is large.
If the change is user-facing or alters behavior an operator or developer needs to know about, update the relevant docs in the same change:
CLAUDE.md) — if the change introduces a new convention, command, or hard rule that future contributors need to know.Documentation is part of the change, not a follow-up. If you defer it, you are deferring the work that lets the next person understand what you did.
After the per-gate work is done, do one more full pass:
You are looking for: anything the per-gate work missed because of fatigue or tunnel vision. Late-stage bugs often hide in this pass — typos in copy, broken imports introduced by an unrelated fix, a regression test that was supposed to be added and was forgotten.
Zero issues at the end of this pass is the bar.
The item’s metadata must match reality:
Status: doneTest: pass — or one of the two narrow exceptions in the hard rule below. Gate 6 does not restate the rule; the hard rule is the only definition.Lock: — (lock released)BACKLOG.md to ARCHIVE.md (see 04_backlog_items.md “Lifecycle of an item” for the archive mechanics).done count up by one, open count down by one — see 03_epics.md “Epic rollup (EPICS.md)” for the rollup format).The backlog is a source of truth. If the file says done but the work is half-finished, the backlog has lied — and every future decision based on that state is poisoned. Update metadata accurately or do not flip the status.
Status: done requires Test: pass, manual-verified (with a regression-needed follow-up item), or n/a (with a body-documented reason).
The canonical path is pass. The two narrow extensions exist to handle real-world cases automated testing can’t cover honestly:
manual-verified — verified by a human (UI walkthrough, manual reproduction) but no automated test exists. Acceptable when automation is impractical for the change AND a regression-needed follow-up item exists to backfill automation when feasible. Manual-verified without a follow-up is the cheating-agent anti-pattern.n/a — the item has no testable behavior (folder creation, README edit, repo-state chore). Acceptable with a body-documented reason; “I didn’t feel like writing tests” is not a valid reason.There is no path from not-tested, pending, partial, fail: <detail>, or regression-needed (without a backing pass) directly to done. The Test field must read pass, manual-verified, or n/a first. If it reads anything else, the item is not done — regardless of how close the work feels.
This is not bureaucracy. It is the single most important enforcement point in the methodology. Every other gate can be checked by good intent. This one requires the test to have actually run and actually passed (or the manual-verification + follow-up trail to exist, or the n/a reasoning to be documented). It is the gate that catches all the others when they slip.
See 04_backlog_items.md "The hard rule" for the canonical statement of the rule and the Test enum.
If you cannot tick the Test field to pass, the item stays at:
to-be-tested — code complete, awaiting verification.under-review — code awaiting review.blocked — cannot proceed; record why in a Blocker: body line.Not done.
A clean pnpm test, a successful TypeScript compile, a green CI run, a dev server that started without errors — none of these prove the application works for the user.
What they prove:
What they do not prove:
The Actual UI Verification gate exists because of this gap. Tests are necessary; they are not sufficient.
“Run the test once. If it passes, ship.” — wrong.
“Run the test. Fix any issues. Run again. Fix any issues. Run again until clean.” — right.
The same applies to UI verification, to the review loop, and to the final verification loop. A loop with a stopping condition is the gate. A single run is not.
The stopping condition for every loop is the same: complete a full pass with zero issues. One clean pass after possibly many imperfect passes. Not “tests pass with one known flaky failure.” Not “UI works except for that one thing I’ll file separately.” Zero.
If you find yourself excluding issues to claim a clean pass, the pass is not clean.
Different projects have different non-negotiables. The six gates above are the base set — the minimum any project needs.
Some projects need additional gates. Layer them on top of the base set; do not replace gates.
Common additions:
| Gate | When to add |
|---|---|
| Schema migration applied | Any project with a database where migrations are tracked separately. The change does not pass DoD until the migration runs cleanly against a representative dataset. |
| Security scan run | Any project with sensitive data, authentication, or payment flows. The change does not pass DoD until the project’s security tooling clears the diff. |
| Accessibility check | Any user-facing product. The change does not pass DoD until a11y rules pass at the project’s target level (e.g., WCAG 2.1 AA). |
| Visual regression check | Any project with a strict design system or pixel-level expectations. The change does not pass DoD until visual regression snapshots pass or are knowingly updated. |
| Performance budget | Any project where load time, bundle size, or query latency is a hard constraint. The change does not pass DoD until the budget is met. |
| Type coverage threshold | Any project enforcing typed coverage. The change does not pass DoD until coverage stays above the floor. |
| Compliance review | Any project under regulatory constraints (privacy, finance, healthcare). The change does not pass DoD until the relevant review signs off. |
| Cross-browser smoke | Any user-facing product targeting more than one browser engine. The change is verified in each target engine. |
The pattern is the same in every case: the additional gate has a binary pass/fail criterion, runs as part of the change (not after), and blocks done if it fails.
Document the project-specific additions in the project’s instruction file so every contributor knows the full set.
Acceptance is defined before implementation by observable criteria, the assurance profile, and the accountable human. The author does not decide what is “good enough” after seeing the result. This applies to software-delivery work across engineering, UX, and customer-facing responsibilities.
| Profile | Consequences and typical work | Required assurance in addition to applicable base gates |
|---|---|---|
| A0 — Exploratory | Bounded spike, disposable mock-up, learning prototype explicitly marked non-production | Record the learning objective, limits, and evidence; author self-check may suffice where existing gates allow it. No production use under this profile. |
| A1 — Standard | Ordinary reversible product work and internal tools | Existing review, tests, DoD, and actual-product verification, with the project’s accountable human identified. |
| A2 — Material | Authentication/authorization, payments, sensitive data, consequential public API changes, significant architecture | Named human acceptance; independent verification against approved criteria and reproducible evidence; relevant security checks. |
| A3 — Critical | Safety-critical or regulated consequences, including software decisions whose failure could materially harm people | A2 controls plus a named human domain owner, qualified human specialist verification/sign-off, and applicable compliance evidence. AI is never the sole verifier. |
Classify the consequences of the work, not the contributor’s job title or the industry label alone. A payment implementation is at least A2; a regulated financial decision may require A3. Existing human-only decisions and operations still apply at every profile.
Selection and inheritance: record a project baseline and accountable human in the instruction file. A1 is the default for ordinary reversible work, never a fallback for unidentified risk. An epic may raise that baseline; an item inherits it and must rise further when its consequences demand it. Explicit A0 applies only to bounded non-production exploration. Reassess before reusing a prototype for delivery; its earlier checks are not production acceptance.
Before ready, identify the effective profile, required evidence/reviewers, and accountable human. A human-held role is sufficient only when its current holder is discoverable in the repository. Missing assignments or uncertain classification block readiness. Escalate uncertainty or new material consequences to that human; update the requirements before affected work continues. An author cannot silently lower a profile or remove a required check. Any proposed reduction needs explicit human agreement with a recorded rationale, still meeting the consequence-based minimum and base gates. Approved acceptance criteria remain frozen intent.
One verification system: L0–L4 still describe verification methods/depth and the existing change-class requirements. A0–A3 add responsibility and assurance requirements, not alternative Test values or replacement levels. Meet both the applicable L requirements and this profile; neither can waive the other. The six gates and the two narrow Test exceptions remain unchanged. A0 is not permission to skip tests on testable behavior.
Use the conditional item fields to record A2/A3, with reviewer assignments, evidence references, acceptance decision, date, and residual risks in the body. Author, verifier, and acceptor are distinct responsibilities. Required independent review or acceptance still pending means Test: partial (or pending before checks), never pass with a prose caveat. An unavailable required specialist blocks completion; use blocked and the human-needed protocol when human action is the blocker. n/a for untestable documentation does not waive required review or acceptance.
Release readiness for A2/A3: before accepting release-bound work, link documented rollback or recovery arrangements, monitoring checks and escalation, and a named human operational owner. A legitimate non-release artifact records why these arrangements are not applicable; its profile still governs acceptance. Risk acceptance cannot excuse failed mandatory gates. Production deploy execution remains human-only, regardless of profile or approval.
Beyond the per-item DoD gates, certain project documents are living artifacts that drift if not maintained. Each has its own maintenance trigger, cadence, and owner. Letting them drift turns the project’s narrative into a lie — and trust in the artifacts erodes fast once that happens.
This section is the practical playbook for keeping them honest. It expands Gate 4 (documentation updated) with concrete patterns.
| Document | Lives at | What it answers | Update trigger |
|---|---|---|---|
| Changelog | CHANGELOG.md |
What changed and when | Every behavior change or release |
| README | README.md |
How to set up and run | When setup commands or top-level architecture change |
| Project status / readiness | STATUS.md or docs/STATUS.md |
What’s shipped, what’s open | When a phase milestone moves |
| Project instruction file | CLAUDE.md / AGENTS.md |
How contributors (human + AI) work here | When a hard rule or convention changes |
| Epic rollup | backlog/EPICS.md |
Active epics + open/done counts | When any item changes state |
| Backlog README | backlog/README.md |
Workflow and item-format conventions | When the workflow changes |
| Strategy master plan | docs/strategy/00_master_plan.md |
Vision + phases + supporting-doc index | On re-evaluation (quarterly or trigger-driven) |
| Memory index | memory/MEMORY.md |
The lessons-learned index | Same commit as the memory entry’s add / remove / rename (per 08_lessons_and_memory.md “Index update discipline”) |
Each row is enforced by either the per-item DoD (CHANGELOG, README, STATUS, EPICS) or by its own re-evaluation protocol (strategy, memory).
The changelog is the project’s behavior diary. Most projects skip it, over-engineer it, or let it rot. The shape below is what works.
One source of truth. Exactly one CHANGELOG.md at the repo root. Not split across docs/CHANGELOG.md, the root, and per-package files. If you find duplicates, consolidate immediately and note the consolidation date at the top: “Previously maintained in both root and docs/CHANGELOG.md — consolidated here on YYYY-MM-DD.”
Reverse-chronological with an [Unreleased] section. Newest at the top. [Unreleased] holds entries that have landed on the trunk but not yet been released (versioned + tagged). When you cut a release, rename [Unreleased] to the version number, then create a fresh [Unreleased] above it.
Categorized entries. Use a small fixed set of categories matching your commit conventions:
Feat — new user-visible behavior.Fix — bug fix.Chore — tooling, dependencies, infrastructure (no user-visible change).Refactor — restructuring without behavior change (usually omitted; some projects include).Release — version bump entries.Entry header format:
### <Category> — <short description> (<date> or <BL-###> or both)
Examples:
### Feat — Add CSV export to the activity report (BL-0428, 2026-05-22)
### Fix — Off-by-one in date parser overflow (BL-0517, 2026-05-21)
### Chore — Upgrade typescript to 5.4 (2026-05-20)
### Release — v0.8.0: versioning regime starts here (2026-05-17)
Entry body — detailed paragraphs. What changed, why, where (with file links), what’s out of scope on this commit, and verification notes (especially when verification went beyond the test suite). Bullet lists are welcome. The entry should be readable cold by someone who didn’t write it.
Link to source files. Use markdown links to the actual changed files. [apps/api/src/routes/auth.ts](apps/api/src/routes/auth.ts) rewards readers who want to dig in.
Tie to backlog items. Reference BL-### in the header or body. The changelog and the backlog stay cross-linked.
Don’t over-summarize. A changelog entry that says “Various fixes” is useless. An entry that names what was wrong and how it was fixed teaches future contributors (including future-you).
Update timing — in the same PR as the change. DoD Gate 4 enforces this. A PR that lands behavior without updating the changelog is incomplete.
The README is the front door. It rots faster than any other document because everyone reads it on day 1 and nobody re-reads it after.
Must always be current:
Can be brief or external:
docs/).Update trigger — any time the setup commands change, the repo structure changes, or a feature the README explicitly mentions is added or removed.
Test the README literally. Once a quarter, follow the README setup commands on a fresh clone and see if they actually work. They often don’t. Fix.
A short doc that answers “what state is this project in right now?” Useful for stakeholders who don’t read the changelog and for your future self.
Suggested sections:
Update trigger — when a phase milestone moves or a major risk materializes / resolves. Monthly minimum.
See 08_lessons_and_memory.md for the full discipline. Maintenance triggers:
The “explained twice” rule. Whenever you find yourself explaining the same project-specific rule to a contributor (human or AI) more than once, that’s the signal to write it down in the instruction file.
The fastest way to make documentation lie is to write it at implementation level. A paragraph describing how a function does its job is false the first time someone rewrites the function — and nothing fails when it goes stale, so it rots silently while still being read as authority.
Document interactions and contracts, not implementations: what talks to what, what each part guarantees, what the invariants are, why a non-obvious boundary exists. Those change on the order of quarters. Implementation details change on the order of afternoons.
The test — one question: if I rewrote this implementation tomorrow, would this paragraph become false? If yes, it is at the wrong altitude. Either lift it to the contract it is really describing, move it into a code comment where it sits next to the thing that would change it, or delete it.
This is the same principle as the memory admission test — derivable from source is never stored — applied to system documentation instead of memory entries. Both exist because a confidently wrong document costs more than an absent one: the absent one sends you to the code, and the code is never out of date.
The biggest failure mode for living documents is partial maintenance. The CHANGELOG mentions a feature; the README still says “coming soon”; the STATUS says “in alpha”; the project instruction file describes the old auth flow. Three readers, four docs, four contradictory impressions, and nobody knows which one to trust.
Defense:
S. The quarterly pass covers the project’s living docs (CHANGELOG, README, STATUS, instruction files, backlog). The methodology docs themselves are out of scope for the quarterly pass — they get the deeper semi-annual evaluation described in “Methodology self-evaluation (semi-annual)” below.Beyond doc audits, a quarterly repo health audit catches imbalances and decay that no individual change reveals. File it as a recurring backlog item with effort S–M:
backlog status for more than 6 months; items blocked with no recent activity; epics active for more than 12 weeks. All signals to triage.done with non-empty Lock: fields (forgotten releases); expired locks that have been sitting for days.A small scripted repo-stats utility that emits these numbers as a markdown summary is worth writing once. The methodology doesn’t ship one — your stack determines the right implementation — but the practice of measuring is what matters.
The audit above checks the codebase. A complementary practice checks the methodology docs themselves — do they still describe how the team actually works?
Methodology and practice naturally drift. The team learns shortcuts that aren’t in the docs. New patterns emerge that the docs don’t acknowledge. Old rules survive in the docs after their reason for existing has gone. Without a deliberate self-evaluation pass, the methodology becomes a fossil: technically correct as of when it was written, less and less descriptive of what’s actually happening.
Cadence: semi-annual (every six months). More often is overhead; less often lets drift compound. The cadence is half that of the quarterly repo health audit because methodology docs change more slowly than code — and they should change slowly, since stability is part of their value.
What to do:
chore(methodology): semi-annual self-evaluation — close drift around <area>.The reverse case. Sometimes a methodology doc gets ahead of practice — a section was written but the team hasn’t yet needed it. That’s fine; the methodology is aspirational on those edges. But if a year passes and the section was never needed, consider whether it should be pruned or marked as optional. Aspirational forever becomes clutter.
What this is NOT:
Connection to the existing patterns:
The healthy state: docs and practice inform each other continuously. Each self-evaluation pass moves the docs ~5% closer to current reality; the cumulative effect across years is what keeps the methodology alive instead of stale.
- [ ] CHANGELOG.md updated (entry under [Unreleased] with category +
date + BL ref + body).
- [ ] README.md updated if setup commands, repo structure, or top-
level architecture changed.
- [ ] STATUS / project-readiness doc updated if a milestone moved or
a known limitation changed.
- [ ] Project instruction file (CLAUDE.md / AGENTS.md) updated if a
convention or hard rule was added.
- [ ] Memory index (MEMORY.md) updated if a memory entry was added.
- [ ] EPICS.md rollup counts updated if items changed state.
This checklist is the operational reality of Gate 4. If you can tick every relevant row for your change, you’ve met the documentation gate.
The short form. Paste into the project’s contributor instructions verbatim.
Definition of Done (every item, no exceptions):
[ ] Code review loop: every changed file reviewed; logic/type/edge-case
issues found and fixed; one clean pass at the end.
[ ] Automated tests pass: full suite run locally; new behavior covered;
bug fixes include a regression test.
[ ] Actual UI verification: ran the change in the actual app, navigated
every affected surface, fixed issues, looped until clean. Verified in
both themes, primary viewport first.
[ ] Documentation updated: changelog, README, status doc, and project
instruction file updated where relevant.
[ ] Final verification loop: one more clean pass of review + tests + UI
after all per-gate work.
[ ] Backlog state correct: Status: done, Test: pass, Lock: —, item moved
to ARCHIVE.md, epic rollup counts updated.
Hard rule: Status: done REQUIRES Test: pass -- or one of exactly two narrow
exceptions: manual-verified (with a regression-needed follow-up item), or
n/a (with a body-documented reason). Nothing else closes an item. Never flip
to done from not-tested / pending / partial / fail: / regression-needed; the
item stays at to-be-tested or under-review until it earns one of the three.
"Servers up" / "tests pass" is not proof. The UI gate is required.
Append project-specific gates as needed. Template:
Project-specific gates (in addition to the base DoD):
[ ] Schema migration applied to local DB; smoke-tested an endpoint that
uses the new column.
[ ] Security scan passes (<tool name>).
[ ] Accessibility check passes (WCAG 2.1 AA; <tool name>).
[ ] Performance budget met (<target>; <tool name>).
[ ] Compliance reviewer signed off (if change touches <regulated area>).
The list should be short and concrete. Each gate names what must be checked and how to check it. Vague gates (“looks good”) are not gates.
| Failure mode | What it looks like | What was skipped |
|---|---|---|
| “All tests pass” but the page is white. | Item flipped to done. User reports a blank screen on the next deploy. |
Gate 3 (UI verification). |
| Dark theme broken after a UI change. | Item is done; users on dark theme see unreadable text. |
Gate 3 dimensions (theme). |
| Bug returns three weeks later. | Same item is filed again. | Gate 2 (regression test required for bug fixes). |
Item is done but README still says “coming soon.” |
Doc drift; future contributors are confused about what’s shipped. | Gate 4 (documentation). |
Item is done with Test: not-tested. |
Backlog claims complete; in reality untested. Trust in backlog erodes. | Gate 6 + hard rule. |
| Migration applied locally but not run against staging. | Endpoint 500s after deploy because the column is missing. | Project-specific overlay (schema migration applied to the right environment). |
| Reviewer asks “did you check X?” and the answer is no. | Item gets bounced back. Loop restarts. Time lost. | Gate 5 (final verification loop should catch this before review). |
Each row is a real failure pattern. Each one is fully prevented by following the gate it skipped.
Every contributor will, at some point, be tempted to skip a gate for “just this one item.” A common pretext:
Resist the temptation. The DoD exists because every one of these has been wrong before. Tiny changes break things. Hurried work creates the most rework. Manual testing before refactoring does not cover post-refactor behavior. CI does not catch UI-only issues. “Just a doc change” can mislead users.
The DoD is the floor for every item. If a project wants to allow some items to skip some gates (e.g., trivial typo fixes), it can define that explicitly in its project-specific overlay — but the rule is named, not improvised.
done.The DoD outranks deadlines. The DoD outranks “we’ll fix it later.” The DoD outranks “the user is waiting.”
The DoD does not outrank explicit user direction. If a user, knowing the rules, explicitly says “ship this without UI verification because the dev environment is down and I need it on staging in the next hour,” that overrides the gate — and the consequence (untested ship) is now the user’s accepted risk, recorded in the item’s notes.
Implicit pressure (“the user seems impatient”) does not override the gate. The contributor’s job is to follow the gate or surface that it cannot be followed, never to silently skip it.