quality-gate · git:20261016.d4dd77b · 2026-10-16 · sha256 dda97db352dcf38d
quality-gate git:20261016.d4dd77bA
Immutable. This exact content never changes and is served at /api/v1/blob/dda97db352dcf38d.
--- name: quality-gate description: >- Runs the checks of a ddd-ts-kit project at the right scope (the changed files while iterating, the whole gate before a slice is closed or merged) and fixes what fails at the root cause. Use before closing a slice or opening a pull or merge request, when the user asks whether the work is clean, done or ready, or when a check, the guard or the pipeline reports a violation. For the size and message of the commit use commit-discipline. allowed-tools: - Read - Edit - Bash(npm run verify) - Bash(npm run typecheck) - Bash(npm run lint *) - Bash(npm test *) - Bash(npm run test:coverage) - Bash(npm run test:e2e *) - Bash(npm run docs:check) - Bash(npm run regenerate) - Bash(npm run docs:generate) - Bash(npm run depcruise) - Bash(npm run deadcode) - Bash(npx ddd-ts-kit check *) - Bash(npx ddd-ts-kit verify-slice *) - Bash(npx ddd-ts-kit check) - Bash(npx ddd-ts-kit todo *) - Bash(npx ddd-ts-kit todo) - Bash(npx ddd-ts-kit status) - Bash(npx ddd-ts-kit docs) - Bash(npx ddd-ts-kit explain *) --- # Quality gate ## Scope the run | When | Run | Cost | |---|---|---| | after each write | nothing: the guard runs `check-file` and returns the violations | none | | while iterating | `npx ddd-ts-kit verify-slice <context> --since <base>`: regenerate, the rules on the changed files, the specs of the context, the files near the size limit and the paths to stage, in one run | seconds | | before the commit that closes a slice | the two above, `npm run typecheck`, `npm run lint`, `npm run format:check` (`npm run format` settles it), `npx ddd-ts-kit todo <context>` (nothing left but `TODO(review)`), `npx ddd-ts-kit check --commit-size` | under a minute | | before a merge or a pull request | `npm run verify`, on the branch with the trunk merged in; each non-blocking remark of the review written as a `TODO(review)` or settled | everything | | before a story or a milestone is closed | `npx ddd-ts-kit todo`: no `TODO(review)` left | seconds | `check --changed-since` judges the changed files only: a cycle, an unused export or a rule broken by the combination with the trunk escapes it, which is why the last run is `verify`, on the whole tree, after merging the trunk. `npm run verify` chains types, lint, format, every spec with the coverage thresholds (`npm run test:coverage`), end-to-end tests, the architecture rules, the import graph (dependency-cruiser), dead code (knip) and documentation drift. Use `npm run typecheck`, never `npx tsc`: the project compiles with the native compiler. `npx ddd-ts-kit status` counts the `TODO(domain)`, `TODO(platform)`, `it.todo` and `TODO(review)` left in each context: a gate is not passed while the slice still has one of the first three. ## Review remarks A review sorts its findings: a blocking one is fixed before the merge; a non-blocking one is settled at once, or written before the merge as `TODO(review): <remark>` at the line it is about, by whoever fixes the branch (the `architecture-reviewer` agent gives the line and its `file:line`, and never writes it). A slice may merge with `TODO(review)` markers; a story or a milestone is closed only when `todo` lists none, each one handled, or dismissed by a decision record (`npx ddd-ts-kit generate adr "<title>"`, quoting the remark without its marker) with the marker deleted in the same commit. ## Coverage `npm run test:coverage` fails with `Coverage for <rate> (<measured>%) does not meet "<contexts>/<context>/<layer>/**/*.ts" threshold (<floor>%)`: that layer of that context holds code no spec runs. The thresholds are the `coverage` key of `ddd-ts-kit.config.json` (the reference when absent: domain 90/85/90/90, application 85/80/85/85, presentation 80/70/80/80, infrastructure 70/60/70/70, as statements/branches/functions/lines). - Read the uncovered lines in the report, write the spec of the behaviour that reaches them (`/ddd-ts-kit:testing`), or delete the code when nothing can reach it. - Never add `exclude`, `include` or `thresholds` to the runner config, a `--coverage.*` flag to a script, or a `v8 ignore` / `istanbul ignore` comment: `test/coverage-governed` reports them. - Lowering a threshold is a decision of the team: change the rate in the config and record it with `npx ddd-ts-kit generate adr "<title>" --deviation coverage.<layer>.<rate> --reason "<why>"`. Raising one is free. ## Read a violation Each carries a rule id, a `file:line`, a message and a `fix` sentence. Open that file at that line only. `npx ddd-ts-kit explain <rule-id>` gives the reason and a good and a bad example. | Rule family | Usual root cause | Fix | |---|---|---| | `layer/*` | logic or a type in the wrong layer | move it, or a port in `application/ports/` and an adapter | | `context/*` | a context reaching into another | a contract in the upstream's `published-language/`, an integration event, a declared relationship (skill `ddd-ts-kit:context-map`) | | `tree/*`, `naming/*` | a file made by hand | `ddd-ts-kit generate`, then move the logic | | `language/*` | a name outside the glossary | the business word, or the term added first (skill `ddd-ts-kit:glossary`) | | `ports/*`, `declarations/*`, `composition/*` | wiring by hand | skill `ddd-ts-kit:wiring`; a stale barrel is `npx ddd-ts-kit docs` | | `domain-events/*` | a handler or an adapter dispatching events itself; a `before-commit` handler depending on a gateway, an external port, `Cache`, `Lock`, `RateLimiter`, `JobScheduler` or `EventBus` | `await repository.save(aggregate)` and nothing else: the unit of work dispatches at its end; `phase: 'after-commit'` when the effect may be lost, an integration event when it must not | | `authz/*` | a use case without a permission, a right decided in the wrong layer | skill `ddd-ts-kit:access-control` | | `events/*`, `scheduling/*` | a contract outside the published language, a consumer without a name, a job doing work | skill `ddd-ts-kit:integration-event`; a job only sends a command | | `purity/*`, `clean/*` | a hidden dependency, unclear code | skill `ddd-ts-kit:clean-code` | | `aspects/*`, `tracing/*`, `standard/*` | a technical concern inside business code | skill `ddd-ts-kit:cross-cutting` | | `governance/*`, `config/*` | a suppression or a config entry without its reason or record | skill `ddd-ts-kit:deviation` | | `test/*` | behaviour without a test, or a mock | skill `ddd-ts-kit:testing` | | documentation drift | generated files not regenerated | `npm run regenerate`, commit them with the code | | `event-sourcing/*`, `unrecorded ... in stored-events.lock.json` from `docs:check` | a state change outside an apply method, a stored shape changed in place, a stored version not recorded | skill `ddd-ts-kit:persistence`; a changed stored shape is a new version with its upcaster, and an unrecorded one is recorded by `npx ddd-ts-kit docs --stored-events` once final, never by hand | Five ids are held by ESLint (`domain/*`, `application/*`): `npm run lint` reports them. ## Not without the owner's explicit agreement A suppression, a lowered severity, a wider allow-list, an extra directory, a relaxed pipeline, `any`, a non-null assertion, a skipped or deleted test: skill `ddd-ts-kit:deviation`. Getting to green is never the reason. ## Report The commands run and their real result, in a few lines. A failing gate is reported as failing, with what remains and why.