Quality Gates
Four gates protect main. Gates 2, 3 and 4 are automated. Gate 1 is you: the manual test you do in your browser at the end of each epic.
Run /quality-check at any time to see the current status of the automated gates.
The four gates
Section titled “The four gates”| Gate | What it checks | Who runs it |
|---|---|---|
| 1. Functional | The epic works the way you described | You, at the manual test |
| 2. Security | No secrets in the code, no serious dependency vulnerabilities, and no unsafe server-side patterns | Automated |
| 3. Code quality | TypeScript compiles, lint rules pass, formatting is consistent, and the production build succeeds | Automated |
| 4. Testing | Every automated test passes, and the tests avoid known bad patterns | Automated |
When the gates run
Section titled “When the gates run”| When | What runs |
|---|---|
| After each story | A quick check: lint rules and test quality. Claude has already run the unit tests and a type check. |
| At the end of each epic | The full automated gates, a code review of the whole epic, and the end-to-end browser tests against a production build |
| On GitHub | Gates 2, 3 and 4, on every pull request to main and on every push to main that changes the app |
Running the full gates once per epic, rather than after every story, keeps the build fast. The quick per-story check still catches most problems while the story is fresh.
Gate 1: Functional
Section titled “Gate 1: Functional”You check that the epic does what you asked for, using the running app the way a user would. There are no automated checks in this gate. Claude gives you a checklist of what to try. See Manual Test Checklists.
Gate 2: Security
Section titled “Gate 2: Security”This gate scans for secrets such as passwords, API keys and tokens committed by mistake. It also checks for unsafe patterns in server-side code and scans the third-party packages your app ships.
A Critical or High dependency vulnerability fails the gate. Medium and Low ones are reported but don’t fail it. The report names the package and the advisory, and Claude can usually fix it by updating the dependency.
Compliance obligations, such as POPIA, are raised with you during Intake rather than scanned for. If your app handles personal data, reviewing it for compliance is part of your manual test.
When a vulnerability has no fix yet
Section titled “When a vulnerability has no fix yet”Sometimes a serious advisory has no fix available from the package’s authors. To stop that one advisory failing every run, add a time-limited exception to web/dependency-audit-exceptions.json. Create the file if it doesn’t exist.
{ "advisories": { "GHSA-1234-abcd-5678": { "reason": "No upstream fix yet. Not reachable in our usage. Tracking: <link>", "expires": "2026-12-01" } }}| Field | What it means |
|---|---|
| Key | The advisory ID from the gate’s report |
reason | Why the advisory is allowed for now. It appears in the report. |
expires | The date the exception ends, as YYYY-MM-DD. After it, the advisory fails the gate again. |
Every other vulnerability still fails the gate. The file is part of your code, so each exception shows up in pull requests for your team to review. Use exceptions only when no fix exists, not to hide an advisory you could fix by updating the package.
Gate 3: Code quality
Section titled “Gate 3: Code quality”This gate checks that the code is valid TypeScript, passes the lint rules, is consistently formatted, and builds for production. It’s fully automated.
A pre-commit check also runs the lint and formatting rules on every commit, so most problems never reach the gate.
Gate 4: Testing
Section titled “Gate 4: Testing”This gate runs the unit and integration tests, and checks the tests themselves for known bad patterns. A test that can never fail, for example, fails this gate.
The end-to-end browser tests run on your machine at the end of each epic, not on GitHub. They also cover accessibility, such as colour contrast and focus order, and anything time-based, such as session timeouts.
Where to see results
Section titled “Where to see results”You don’t need to go looking for gate results. While Claude is shipping an epic, it waits for the GitHub checks and tells you directly if one fails, with the actual error.
To see the results yourself, open the Actions tab of your repository on GitHub and pick a run. Each gate has its own page listing every check it made. Failures also appear on the pull request’s Checks tab.
The gates don’t post comments on your pull requests. If one fails, GitHub emails you once, with a link to the details.