CI and Local Gates
Required local and CI verification gates for projects that follow these standards. Agents MUST run every applicable gate before marking work complete.
Agent Quick Rules {#agent-quick-rules}
- MUST run backend build and test before marking backend work complete.
- MUST run
pnpm lint,type-check,test, andbuildfor every changed frontend app. - MUST use
pnpm install --frozen-lockfilein CI. - MUST verify OpenAPI freshness when generated API types are committed.
- SHOULD run
node scripts/validate-domain-docs.mjswhen domain docs change.
Full convention: docs/conventions/shared/ci.md
0. pnpm Workspace Setup
All frontend apps and packages share a single pnpm workspace. The pnpm-lock.yaml and pnpm-workspace.yaml files live at the repository root. Individual app directories have their own package.json but no separate lockfile.
Install from the root to populate the shared node_modules:
pnpm installRunning pnpm install from an app subdirectory also works: pnpm walks up to find the workspace root automatically.
In CI, use --frozen-lockfile to fail if the lockfile is out of sync:
pnpm install --frozen-lockfileWhen running the Aspire AppHost, run pnpm install from the workspace root before starting the AppHost. The WithPnpm() call in the AppHost triggers pnpm install in each app’s subdirectory, which resolves back to the workspace root.
0.1 Recommended Root Scripts
Monorepos SHOULD expose common workflows from root package.json:
| Script | Command purpose |
|---|---|
dev:aspire | Start AppHost |
dev:api | Run WebApi standalone (manual path) |
dev:web / dev:admin | Run individual Next.js apps |
db:migrate | dotnet ef database update with standard project paths |
db:migrate:add | Wrapper for dotnet ef migrations add |
Document which path (Aspire vs manual) each script targets in the project development guide.
See also docs/conventions/shared/local-ide-setup.md for VS Code / Cursor debug configs.
1. Required CI Gates
Every pull request MUST run:
| Gate | Command |
|---|---|
| Backend build | dotnet build apps/api/{ProjectName}.slnx --configuration Release |
| Backend tests | dotnet test apps/api/{ProjectName}.slnx --configuration Release --no-build |
| Vulnerable NuGet packages | dotnet list apps/api/src/{ProjectName}.slnx package --vulnerable |
| Frontend install | pnpm install --frozen-lockfile |
| Frontend lint | pnpm lint |
| Frontend type check | pnpm type-check |
| Frontend unit tests | pnpm test |
| Frontend build | pnpm build |
| Frontend audit | pnpm audit |
| Playwright E2E | pnpm exec playwright test --config apps/web/playwright.config.ts |
| OpenAPI freshness | Regenerate spec and types, then git diff --exit-code on artifacts |
Skip frontend gates when the project has no frontend. Skip Playwright when no apps/web/e2e/ exists yet (document in project ADR). Skip OpenAPI freshness when no generated frontend API types are committed.
2. OpenAPI Freshness Gate
# 1. Build (generates openapi.json into the WebApi build output via Microsoft.Extensions.ApiDescription.Server)dotnet build apps/api/{ProjectName}.slnx --configuration Release
# 2. Copy the generated speccp apps/api/src/{ProjectName}.WebApi/bin/Release/net10.0/openapi.json packages/api-types/openapi.json
# 3. Regenerate TypeScript typespnpm --filter @myproject/api-types generate:api-types
# 4. Fail if the generated files differ from what was committedgit diff --exit-code packages/api-types/openapi.json packages/api-types/src/api.d.tsBuild-time generation requires Microsoft.Extensions.ApiDescription.Server in the WebApi project. See docs/conventions/backend/api-layer.md for the MSBuild configuration.
If the diff is non-empty, the PR forgot to commit regenerated API artifacts.
3. Example GitHub Actions Workflow
Use docs/templates/config/ci-workflow.yml as the canonical workflow template. It includes backend gates, frontend gates, OpenAPI freshness, Playwright, and optional standards submodule tag verification.
4. Pre-Commit Hooks
Pre-commit hooks are OPTIONAL. When used, they MUST be fast and local.
Local hooks MAY include:
dotnet format --verify-no-changespnpm lintpnpm type-checkDo not run containerized integration tests or Playwright in pre-commit hooks. Keep slower checks in CI.
4. Domain Documentation Validation
When the project has docs/domain/, run structural completeness checks before merge:
node scripts/validate-domain-docs.mjsCopy the script from the standards repository (standards/scripts/validate-domain-docs.mjs) or symlink it in consumer projects. The script checks:
- YAML frontmatter on Feature Specs and Use Case Docs
- Presence of Use Case Test Specs for each operation doc
docs/domain/agent-index.jsonexists and parses as JSON- Warnings for invariant coverage gaps, state transition coverage, and write/read asymmetry
Warnings do not fail CI by default; errors (missing test specs, invalid frontmatter keys) fail CI. Projects MAY treat warnings as errors in release branches.
See docs/guides/agentic-domain-driven-design.md §12 for the full check catalog.
5. Acceptance Test Stages
When a project has {ProjectName}.AcceptanceTests:
| Stage | Scope |
|---|---|
| Every PR | dotnet test on Architecture, Domain, Application, Integration smoke, and acceptance tests filtered to @critical |
| Domain/API PRs | Full acceptance test project when docs/domain/**, Application/**, WebApi/**, Infrastructure/**, migrations, or OpenAPI changed |
| Release candidate / nightly | All acceptance tests including @slow and @external-dependency |
Filter Reqnroll scenarios by tag in CI, for example:
dotnet test apps/api/tests/{ProjectName}.AcceptanceTests \ --filter "Category=critical"Projects SHOULD copy standards/scripts/validate-feature-files.ps1 and run it in CI when Reqnroll feature files exist. Tag rules: docs/conventions/backend/api-acceptance-tests.md section 5.