← Back to Skills

Definition of Done — the user completes the job in a screen

On 2026-09-26 an audit of iec-ledger found months of work reported "done" that an accountant could not use: 48 vendor fields in the API schema and 11 in the…

Ruleplatform

About

On 2026-09-26 an audit of iec-ledger found months of work reported "done" that an accountant could not use: 48 vendor fields in the API schema and 11 in the form; bills with no vendor invoice number; reports with an export and no page; a Pay Bills screen that looped payments client-side. Every one of those PRs had green tests and merged. Nothing in the pipeline had asked whether the person the feature was for could do the job. This convention makes that the question, and a merge-gate hook asks…

Skill Content

This is the raw markdown that gets installed as a Claude Code rule.

# Definition of Done — the user completes the job in a screen

## Why this exists

On 2026-09-26 an audit of iec-ledger found months of work reported "done" that an
accountant could not use: 48 vendor fields in the API schema and 11 in the form; bills
with no vendor invoice number; reports with an export and no page; a Pay Bills screen
that looped payments client-side. Every one of those PRs had green tests and merged.
Nothing in the pipeline had asked whether the person the feature was for could do the
job. This convention makes that the question, and a merge-gate hook asks it
mechanically.

## The rule

A change is done only when **all** of these hold:

1. **The user can complete the story in a screen.** The issue's story
   ("As a <role>, I need to <do> so that <outcome>") was driven end to end in a
   browser against a running build of this change, by the agent or dev who built it.
   "API only, UI to follow" is a status, not done.
2. **Field parity.** Every field the API accepts on a record is in the form, or is
   listed as intentionally hidden with a reason. Repos with forms carry a parity lint
   (iec-ledger: `npm run lint:parity`, a ratchet that fails only on new gaps).
3. **Reference behaviour cited.** The PR names what the reference system does (for
   accounting: QuickBooks Online, Sage Intacct, NetSuite, Applied Epic/AMS360,
   Vertafore AIM, the accounting bible) and where this matches or deliberately differs.
4. **Evidence in the PR body** under `## Walkthrough`: the story, the screen steps
   driven, a `Reference:` line, and proof. Preferred proof is a
   [`tawa walkthrough`](/reference/walkthroughs) page (asserted screenshots, public
   link); a screenshot/GIF or a `docs/qa/issue-N-*.md` execution log also counts.
5. **QA execution log** for changes to routes, models, services, pages or components:
   a `## QA Execution` section with real, dated output, or a changed
   `docs/qa/issue-N-*.md`. Mocked unit tests alone do not satisfy this.
6. **Vertical slice.** One issue spans API and UI. A backend-only PR must link the UI
   issue opened in the same PR and say so.
7. **Honest completion.** The final message names what was not done and why. A parent
   agent never reports a fan-out complete when a child failed or was rate-limited.

## Escape hatch

`DoD-exempt: <reason, 20+ characters>` in the PR body. The gate allows the merge and
surfaces the reason. For infrastructure, docs, and platform plumbing, not for "UI later".
Docs-only PRs (only `.md`, `docs/`, `.forgejo/`) are exempt automatically.

## The merge-gate hook

`scripts/pr-merge-gate.sh` in this repo is a Claude Code `PreToolUse` hook on any MCP
tool named `*git_pr_merge`. It fetches the PR from Forgejo with the machine's stored git
credential and denies the merge when the body lacks the sections above. Install on every
machine that merges:

```bash
mkdir -p ~/.claude/hooks && cp scripts/pr-merge-gate.sh ~/.claude/hooks/ && chmod +x ~/.claude/hooks/pr-merge-gate.sh
```

Then add to `~/.claude/settings.json`:

```json
{ "hooks": { "PreToolUse": [ { "matcher": "mcp__.*git_pr_merge",
  "hooks": [ { "type": "command", "command": "~/.claude/hooks/pr-merge-gate.sh", "timeout": 45 } ] } ] } }
```

Decisions are appended to `~/.claude/hooks/pr-merge-gate.log`. Test without merging:

```bash
echo '{"tool_input":{"repo":"iec-ledger","index":<pr>}}' | ~/.claude/hooks/pr-merge-gate.sh
DOD_GATE_TEST_BODY='## Walkthrough ...' bash -c 'echo ... | ~/.claude/hooks/pr-merge-gate.sh'
```

The strict QA-log requirement applies to `insureco/iec-ledger`, `iec-ledger-ui` and
`icap-portal`; edit `ledger_repos` in the script to add a repo.

## Issue and PR templates

Repos adopting this carry `.forgejo/issue_template/{feature,bug}.md` (story,
screen-step acceptance criteria, Reference, API + UI checkboxes, out-of-scope) and
`.forgejo/pull_request_template.md` (Walkthrough, QA Execution, Not done in this PR).
Copy them from iec-ledger.

## What this does not replace

- The [Agile workflow](/reference/agile-workflow): issues first, PR-only main,
  self-merge when green. This convention defines what "green" must include.
- The [QA & regression](/reference/qa-regression) discipline: dossiers, risk tiers,
  live E2E. This convention is the gate that makes the dossier non-optional for code
  that touches the user.
- [Walkthroughs](/reference/walkthroughs): the preferred way to produce the evidence.

## Common mistakes

- Closing an issue when the schema landed and the form did not.
- Reporting a report "built" when it has no page.
- Modelling a business document as a bare GL transaction because the posting engine
  already existed.
- Writing the Walkthrough from memory instead of from the browser.
- Using `DoD-exempt` for "UI in a later PR".
- Widening the parity baseline to make the lint pass.

Install

Copy the skill content and save it to:

~/.claude/rules/tawa-definition-of-done.md
Download .md

Coming soon via CLI:

tawa chaac install tawa-definition-of-done

Details

Format
Rule
Category
platform
Version
1.0.69770
Tokens
~1,207
Updated
2026-10-13
platformprocessqualitymerge-gatewalkthroughqaagents