Definition of Done
This is the project's authoritative completion contract for a feature, bug fix, refactor, documentation change, or tooling change. Applicable specifications and acceptance criteria define what a particular change must deliver; this document defines the quality and evidence required to call it complete. It does not expand the agreed scope.
A change is done when every mandatory requirement and every applicable context-dependent requirement below is satisfied, with evidence for the version being delivered, and no known unresolved blocking issue remains.
Mandatory requirements for every change
- The agreed implementation or document change is complete across all layers needed to deliver it. All requirements in the applicable specifications are satisfied. Each acceptance criterion has a recorded result and supporting evidence. No required behavior is left as a placeholder or TODO.
- The diff has been reviewed for scope and architectural compliance. The
architecture and technology stack are respected: HTTP
concerns remain in the API layer, application/domain logic remains independent of HTTP and
database clients, persistence stays behind repositories, and frontend components use the
frontend API boundary. Significant architectural decisions are documented in
docs/decisions/. - Test selection follows the applicability guidance below. Behavior changes have appropriate automated tests; existing tests may suffice when they already prove the changed behavior. Bug fixes have a regression test at the lowest level that reliably reproduces the defect. A change without new tests has a recorded reason, such as prose-only edits with no executable behavior.
- Static quality passes:
pnpm qualityverifies formatting, ESLint, all-workspace type checking, locale resources, Markdown links, scoped spelling, architectural imports/API boundaries, tracked-file hygiene, OpenAPI validity, and public TypeScript API documentation, with the database package build prerequisite. AI agents must run this command locally before reporting completion, including for documentation changes; its constituent checks need not be rerun separately. - All required CI validation succeeds for the delivered revision: frozen dependency installation
in each job,
quality,test,build,docs,supply-chain,coverage, andvalidate-docker. The eight checks in CI §4 are represented by seven validation jobs; installation is part of every job. Required jobs must conclude successfully, rather than be missing, pending, cancelled, skipped, or made non-blocking. Branch protection availability does not change this requirement. - Required outputs are produced and persisted successfully under
CI §9:
db-dist,frontend-dist,backend-dist,docs-site,frontend-coverage, andbackend-coverage. Artifact presence alone does not prove a green run. Playwright diagnostics are failure-only and are not required on a successful run; Docker images remain ephemeral. The weeklysupply-chain-diagnosticsartifact is informational and separate from these six mandatory outputs. No additional release artifacts are required by default. - Documentation agrees with the resulting behavior and actual commands. Update affected
source-of-truth documents; if none need changes, record that conclusion. Update
docs/current-state.mdwhen the implementation state changes. AI agents updatedocs/ai-handover.mdwith completed work, changed files, remaining work, validation results, and the next action. Generated builds, coverage, and documentation-site output are not committed; required migration files are committed through the migration workflow. - The final diff contains no unrelated modifications, committed secrets, or undocumented machine-specific prerequisites. Required setup and validation are reproducible from repository sources and documented configuration.
- There are no known unresolved blockers: failed acceptance criteria, regressions, failing required checks, missing required artifacts, or missing required verification. Unrelated non-blocking limitations may remain if documented with their impact and follow-up; labelling a blocker a known issue does not make the change done.
- The completion report records what changed, acceptance evidence, checks actually executed and their outcomes, CI revision/run, applicable artifacts, justified not-applicable items, and any remaining non-blocking limitations. A check not executed is explicitly reported as not verified.
Context-dependent requirements
These requirements become mandatory when their trigger applies. Select tests by changed behavior and dependency impact, rather than by the number of files. Use the lowest practical level, adding higher levels to prove interactions that lower levels cannot. Do not repeat the same assertions at every level.
Unit tests
- When it applies: Isolated application/domain logic, validation, transformations, or error interpretation changes.
- Objective completion evidence: Relevant cases and branches pass in the affected Vitest suite, including meaningful failure and boundary cases.
Component/module tests
- When it applies: UI behavior, loading/error states, routing, or interactions within an application change.
- Objective completion evidence: Tests pass for observable behavior and affected interactions; frontend component tests use React Testing Library. No browser E2E is required solely to test an isolated component.
Integration tests
- When it applies: Persistence, schema, queries, transactions, mapping, or collaboration between real modules changes.
- Objective completion evidence: Tests exercise the affected real components. Database behavior uses real PostgreSQL and deterministic, isolated state initialized through project migrations. A mock database is not evidence of database integration. Frontend integration tests may control the external HTTP boundary while exercising real frontend layers.
API-level tests
- When it applies: Endpoint surface, input validation, HTTP status/headers, response shape, or error contracts change.
- Objective completion evidence: Relevant HTTP-facing tests verify the contract, success, and applicable error cases. Fastify injection suffices for isolated HTTP behavior; real HTTP plus PostgreSQL integration is required when the affected behavior depends on that path. OpenAPI and route-surface contract tests agree with implementation.
E2E tests
- When it applies: A new or changed important user workflow, an integrated feature, or a regression spanning browser/backend/database boundaries requires integrated proof.
- Objective completion evidence: Playwright verifies the affected journey through the real running system and real database where used. Mocked backend/database responses cannot prove the complete workflow. Existing E2E coverage may suffice if it already exercises the affected path.
Production build
- When it applies: Executable sources, dependencies, TypeScript/build configuration, generated assets, or packaging change.
- Objective completion evidence: Affected production builds succeed, including required
workspace dependencies; a running development server is insufficient. The full
pnpm buildremains mandatory in CI for every change.
Docker validation
- When it applies: Container definitions, Compose wiring, runtime configuration, startup, migrations/seed, dependencies, or behavior specific to packaged execution change.
- Objective completion evidence: The canonical
pnpm validate:dockerpasses from clean local Compose state, proving image builds, startup, initialization, integration/API tests, and browser workflow. Add targeted checks if the changed behavior is not exercised by that command, such as configuration overrides or migration rerun behavior. CI runs Docker validation for every change.
Coverage validation
- When it applies: Production code within the documented coverage scope changes.
- Objective completion evidence: The aggregate coverage gate retains 100% statements, lines, functions, and branches globally and per-file, using only the justified exclusions in testing strategy §4.1. Each test layer need not independently reach 100%; E2E has no source coverage threshold. CI coverage is mandatory for every change.
Documentation and contract details
- When it applies: Public HTTP/TypeScript APIs or architecture, tooling, setup, testing, CI, Docker, or milestone conventions change.
- Objective completion evidence: Update OpenAPI with HTTP behavior, meaningful inline documentation for intentional public TypeScript APIs, and the relevant project guide or decision record. Generate and inspect affected documentation pages when content/navigation or generation changes.
Deployment/release acceptance
- When it applies: The agreed task includes deploying, publishing, or changing the staging/release workflow.
- Objective completion evidence: Verify the specific deployed revision and agreed smoke/health
checks in the target environment. Trusted
mainCI runs also requirestaging-migrateto succeed under CI §13; its deliberate PR skip is valid. Publishing changes require the separate Cloudflare workflow's result. Ordinary feature completion does not require provisioning infrastructure or a production deployment.
Applicable specifications may add feature-specific acceptance criteria, required artifacts, environments, or validation beyond this baseline. Record which specifications apply and provide evidence for their requirements. Resolve conflicts between a specification and the current project quality contracts explicitly; outdated or temporary allowances do not silently waive mandatory gates. Future functionality and infrastructure are required only when explicitly in scope for the change.
Proportional local validation
Every change goes through the existing full CI gate. Developers do not need to reproduce that
pipeline manually before each review. Choose local checks that provide useful feedback for the
affected behavior; passing CI can supply the remaining automated evidence. The AI-agent local
pnpm quality requirement still applies.
Prose-only documentation correction
- Expected local validation: Review accuracy and links; static quality. Generate/inspect documentation if rendering or navigation is affected. No new application tests, local application build, Docker reset, or browser E2E is required.
Isolated logic or component fix
- Expected local validation: Static quality, affected unit/component tests, and affected production build. Add a regression test and check relevant coverage; integration/E2E only if the fix affects those boundaries.
Repository/query/schema change
- Expected local validation: Static quality, relevant fast tests, real-database integration tests, affected build, and clean Docker validation when initialization or packaged execution is affected. Schema changes also need evidence that migrations apply to the relevant existing schema, as well as from scratch.
Complete database-backed user feature
- Expected local validation: Static quality, tests at the affected unit/component/integration/API levels, affected builds, and real-browser proof of the important journey through the canonical Docker stack.
CI/artifact or docs-site tooling change
- Expected local validation: Static quality, relevant infrastructure tests (including
pnpm test:cifor artifact/checker changes), affected generation/build commands,pnpm docs:site:checkafter site generation, and inspection of changed outputs. Repeat Docker/E2E locally only if their behavior or orchestration changes.
pnpm validate:docker already runs integration tests and pnpm e2e:docker; do not separately
repeat those suites after it passes without a new change or unresolved concern. Dev-mode pnpm e2e
is optional inner-loop feedback, not an additional completion gate. The coverage run deliberately
reruns instrumented tests to enforce the existing coverage contract; this does not require another
manual repetition. No blanket no-cache rebuild, screenshot collection, artifact download, or
interactive smoke test is required for every change. Add such verification only for acceptance
criteria or behavior not covered automatically.
Docker validation deletes only its own isolated Compose project state and publishes separate ports; the development database is never touched. Run two validation instances serially. Use the documented local/test configuration; never point reset or Docker validation at staging or production. Prerequisites and commands remain owned by the development guide, testing strategy, and Docker guide.
Recording the decision
Use this short record in the PR/change report; an equivalent repository template is sufficient. Record a reason for each context-dependent item marked not applicable, and distinguish that from required checks not yet verified.
Scope and delivered revision:
Applicable specifications and acceptance criteria -> result and evidence:
Architecture/scope review:
Applicable test levels -> tests and results (or N/A with reason):
Local commands -> pass/fail/not executed:
CI -> run/revision and required job conclusions:
Artifacts -> producing run and required outputs:
Documentation/handover updates (or N/A with reason):
Blocking issues: none / details
Non-blocking limitations and follow-up:
Decision: Done / Ready for CI / Blocked
Next action:
Ready for CI means the local work and applicable local validation are finished but required hosted results are pending or unavailable. It is not a claim that the final Definition of Done is satisfied. Blocked means a required criterion or check is failing or cannot be verified. State the missing evidence and next action rather than claiming success. Done requires all mandatory and applicable requirements to pass; an old green run or a green run for a different revision is insufficient. After further edits, rerun affected local checks and obtain CI evidence for the delivered revision.