The Increment and the Definition of Done: What "Done" Really Means
The Definition of Done is the Increment's commitment: an item that does not meet it can neither be released nor shown at the Sprint Review, and returns to the Product Backlog. The post writes a concrete Definition of Done for a .NET and Angular team and turns it into a GitHub Actions workflow: in a local run of its steps a vulnerable transitive package broke the build with NU1903, and an uncommitted OpenAPI document made git diff exit with code 1.
Version note: This post is based on the Scrum Guide 2020 (November 2020, Ken Schwaber and Jeff Sutherland). The code in this post was built and run with .NET 10 SDK (Software Development Kit) 10.0.402, Entity Framework Core (EF Core) 10.0.14, Microsoft.AspNetCore.OpenApi 10.0.14 and xUnit v3 4.0.2; every command in the workflow was run locally in the same order.
Guess First
Two days before Bookstore's Sprint 9 Review, there are seven items in the "Done" column. Deniz notices that three of them were never deployed to staging, one has an integration test skipped "temporarily", and one added a new endpoint while the OpenAPI document stayed old. The team thinks "the code is written and reviewed, so it's done".
According to the Guide, how many of these seven items can be shown at the Sprint Review? And where do the others go: do they move to the next Sprint automatically, or somewhere else? Write down your guess; the answer is one sentence in the Guide.
The Increment: A Concrete Stepping Stone Toward the Product Goal
The Guide defines an Increment as a concrete stepping stone toward the Product Goal. Each Increment is additive to all prior Increments and thoroughly verified, ensuring that all Increments work together. To provide value, the Increment must be usable. Underline three words: additive (not a side branch, the product itself), verified (by checks, not by someone saying "it works"), usable (a stakeholder can pick it up and try it).
The 2020 version also explicitly corrects two wrong assumptions. First, a Sprint does not have to have a single Increment; multiple Increments may be created within a Sprint, and their sum is presented at the Sprint Review. Second, an Increment may be delivered to stakeholders before the end of the Sprint; the Guide says the Sprint Review should never be considered a gate to releasing value. At Bookstore, the time zone bug fix met the Definition of Done on day three of the Sprint and went to production the same day; the Review only discussed the result.
And the rule itself: work cannot be considered part of an Increment unless it meets the Definition of Done.
The Definition of Done: The Increment's Commitment
Every artifact has a commitment; the Increment's is the Definition of Done. The Guide defines it as a formal description of the state of the Increment when it meets the quality measures required for the product. The moment a Product Backlog item meets the Definition of Done, an Increment is born.
The answer to the opening question is here as well. If an item does not meet the Definition of Done, it cannot be released or even presented at the Sprint Review. Instead, it returns to the Product Backlog for future consideration. There is no rule that it "moves to the next Sprint automatically"; the Product Owner orders it again, and it may or may not be at the top in the next Sprint. Four of Bookstore's seven items could have been shown at the Review; three went back to the backlog.
The Guide is clear about ownership too. If the Definition of Done is part of the organization's standards, all Scrum Teams follow it as a minimum; if not, the Scrum Team must create a Definition of Done appropriate for the product. The Developers are required to conform to it. If several Scrum Teams work on the same product, they mutually define and comply with the same Definition of Done. One of the things the Retrospective inspects is the Definition of Done itself; so it is not fixed either, and it tightens as the team matures.
Bookstore's Definition of Done
The Bookstore team wrote the Definition of Done for its product, a .NET 10 backend and an Angular frontend, as follows. An item is Done when all of these are true:
- The change was merged into main through a pull request and reviewed by at least one Developer.
- The build passed in CI (Continuous Integration) without warnings; unit and integration tests are green, with no skipped tests.
- There is no NuGet or npm package with a known vulnerability.
- If the API (Application Programming Interface) changed, the OpenAPI document is up to date and committed.
- If the schema changed, an idempotent SQL (Structured Query Language) script was generated for the EF Core migration and reviewed.
- It was deployed to staging and the smoke test passed.
- The new screen is usable with the keyboard and its form fields have labels (a basic accessibility check).
- The new endpoint has structured logging and at least one metric.
Every line on this list came from one of Bookstore's scars. The OpenAPI line was added after a Sprint in which the mobile app team wrote code against the old document for three days. The logging and metric line came after a weekend when nobody could see why the return endpoint was slow in production.

Checking the Definition of Done in Code
Scrum does not impose engineering practices; but leaving the meaning of "done" to someone's memory weakens transparency. Bookstore's approach: move the checkable items into CI and keep a checklist in the pull request template for the rest. The first step is making packages with known vulnerabilities break the build. NuGet audit reports these as warnings NU1902 (moderate), NU1903 (high) and NU1904 (critical); turning them into errors is enough:
<Project>
<PropertyGroup>
<!-- break the build on known vulnerable packages -->
<WarningsAsErrors>$(WarningsAsErrors);NU1902;NU1903;NU1904</WarningsAsErrors>
</PropertyGroup>
</Project>
This file is Directory.Build.props at the repository root; it applies to every project. On the first run the build really did break, and the cause was a package the team had not added directly:
src/Bookstore.Api/Bookstore.Api.csproj : error NU1902: Warning As Error: Package 'System.Security.Cryptography.Pkcs' 9.0.11 has a known moderate severity vulnerability, https://github.com/advisories/GHSA-2fmv-rv2c-59x7
src/Bookstore.Api/Bookstore.Api.csproj : error NU1903: Warning As Error: Package 'System.Security.Cryptography.Pkcs' 9.0.11 has a known high severity vulnerability, https://github.com/advisories/GHSA-846f-f764-76mx
dotnet nuget why shows where the package comes from:
$ dotnet nuget why src/Bookstore.Api System.Security.Cryptography.Pkcs
Project 'Bookstore.Api' has the following dependency graph(s) for
'System.Security.Cryptography.Pkcs':
[net10.0]
└── Microsoft.EntityFrameworkCore.SqlServer (v10.0.14)
└── Microsoft.Data.SqlClient (v6.1.7)
└── System.Security.Cryptography.Pkcs (v9.0.11)
The team raised the transitive package System.Security.Cryptography.Pkcs to 10.0.14 with a direct reference, and the build went green again. Without this line in the Definition of Done, the warning would have been lost among hundreds of build log lines, and the Sprint's "done" work would have gone to production with a known vulnerability.
The second step is the workflow itself. Each item is a separate step; which item broke is visible by name on the pull request:
name: definition-of-done
on:
pull_request:
branches: [main]
jobs:
dod:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: actions/setup-dotnet@v6
with:
global-json-file: global.json
- run: dotnet tool restore
# NU1902-NU1904 are errors: no known vulnerable packages
- run: dotnet build -c Release
- run: dotnet test -c Release --no-build
# OpenAPI document regenerated on build must match the committed one
- run: git diff --exit-code -- src/Bookstore.Api/Bookstore.Api.json
# migration script generated and attached to the release
- run: dotnet ef migrations script --idempotent -p src/Bookstore.Api -o artifacts/migrate.sql
- uses: actions/upload-artifact@v7
with:
name: migrate-sql
path: artifacts/migrate.sql
The idea behind the OpenAPI check is simple. The project references the Microsoft.Extensions.ApiDescription.Server package and its OpenApiDocumentsDirectory property points to the project folder, so every build regenerates the OpenAPI document and writes it to Bookstore.Api.json. If a Developer adds an endpoint and forgets to commit the new document, the build in CI changes the file and git diff --exit-code returns a non-zero code. The local run on the branch where Emre added an endpoint that looks up books by ISBN (International Standard Book Number):
$ dotnet build -c Release
0 Warning(s)
0 Error(s)
$ git diff --exit-code --stat -- src/Bookstore.Api/Bookstore.Api.json
src/Bookstore.Api/Bookstore.Api.json | 22 ++++++++++++++++++++++
1 file changed, 22 insertions(+)
exit code: 1
Build and tests are green, but the Definition of Done is not met: the API contract changed and nobody consuming it can see that. When Emre committed the updated document, the same step passed with exit code: 0. The endpoint itself and OpenAPI generation are covered in the ASP.NET Core Web API series post "What's New in .NET 10: AddValidation, OpenAPI 3.1 and Server-Sent Events in ASP.NET Core"; designing tests and quality gates in a pipeline in the CI/CD Fundamentals series post "Testing in the Pipeline: Fast Feedback, Quality Gates and Flaky Tests"; and where the migration script fits in a deploy in the Deployment Strategies series post "Where Migrations Fit in a Deploy: Expand-Contract, EF Core Migration Bundles and Backward-Compatible Schemas".
The items that are not automated (accessibility, logging and metrics, the staging smoke test) live as a checklist in the pull request template. The point of automation is not to remove people; it is to spend their attention on the items that cannot be automated.
Definition of Done vs Acceptance Criteria
The two are often confused. Acceptance criteria are specific to a single item: "A return request can only be opened within 14 days of delivery", for example. The Definition of Done is the quality standard for the whole Increment: the same for every item, independent of the item's content. For an item to be Done, both must hold: the item meets its own criteria, and the Increment meets the team's quality standard.
A practical test: if a line repeats verbatim for every item, it belongs in the Definition of Done; if it only describes this item, it is an acceptance criterion. The technique of writing acceptance criteria belongs to the upcoming Requirements Analysis series.
Undone Work and the Hardening Sprint
The 2010 Guide had a concept called "undone work"; the 2011 revision removed that reference. Today's Guide has no in-between state: an item either meets the Definition of Done and is part of the Increment, or returns to the Product Backlog. "90 percent done" does not enter an Increment.
What happens if the Definition of Done stays at "code written and reviewed"? Testing, integration, performance and release preparation pile up every Sprint, and at some point before a release the team declares a "hardening sprint" that produces no features and only clears that pile. This openly violates the principle that every Sprint produces a usable Increment; it violates transparency too: the work that looked "done" at the Review was not actually done. The cure for a hardening sprint is not a longer hardening sprint, but tightening the Definition of Done and selecting less work in the Sprint that really gets finished.
In Production: What to Watch
Bookstore looks at two numbers for the health of its Definition of Done. The first is escaped defects, bugs found in production in work counted as Done. If that number rises, the Definition of Done is missing a line, or has it on paper but does not apply it. The second is the time from Done to production. If an item is Done but not released for weeks, either release is a heavy step left outside the Definition of Done, or "Done" does not mean "releasable". What the Guide expects is that Done work is releasable.
As the number of checks in CI grows, the pipeline slows down; automating the Definition of Done has a cost. Bookstore's rule: if the pull request pipeline takes more than ten minutes, the team discusses in the Retrospective which check should move where. Measuring and speeding up a pipeline, together with the DORA (DevOps Research and Assessment) metrics, is covered in the CI/CD Fundamentals series post "Measuring and Speeding Up a Pipeline: DORA Metrics, Caching and Parallelism".
At scale the rule is fixed: all teams on the same product share the same Definition of Done. When two teams have different definitions of "done", the quality of the integrated Increment is only as good as the weakest definition.
Common Pitfalls
Keeping the Definition of Done at "code written" and breeding hardening sprints. As described above, that pushes quality outside the Sprint.
A Definition of Done written on a wiki page and never checked. If the team bends the lines every Sprint with "let's skip it this time", a written Definition of Done adds nothing to transparency; it is actually misleading.
Showing an item that is not Done at the Review as "almost done". The Guide explicitly forbids this; everything shown to stakeholders must meet the Definition of Done so that inspection is based on real data.
Trying to write the perfect Definition of Done in one go. In the first Sprint, Bookstore's list had four lines; each line since came from a Retrospective. A Definition of Done the team cannot meet today becomes a document that is violated every Sprint.
A Small Experiment
★☆☆ Write down your team's Definition of Done; if it is not written, take three items called "done" in the last Sprint and list what was actually done for each. The intersection of the three lists is your team's de facto Definition of Done.
★★☆ Split the lines of your Definition of Done into "automatically checkable in CI" and "needs a human check". Turn one line from the first group into a pipeline step like the ones in this post, and watch it stop with a non-zero exit code on a branch you break on purpose.
★★★ List the escaped defects of the last three months and write, for each, which Definition of Done line would have caught it. Bring the most frequent one to the next Retrospective as a proposal to add to the Definition of Done.
The Increment is ready and really done. In the next post we move to the last two events of the Sprint: how we inspect this Increment with stakeholders in the Sprint Review, and how we improve our own way of working, Definition of Done included, in the Sprint Retrospective.