create-rigel 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +156 -0
- package/cli.js +122 -0
- package/package.json +47 -0
- package/templates/express/.claude/CLAUDE.md +114 -0
- package/templates/express/.claude/agents/arch-validator.md +85 -0
- package/templates/express/.claude/agents/db-optimizer.md +72 -0
- package/templates/express/.claude/agents/doc-gardener.md +67 -0
- package/templates/express/.claude/agents/garbage-collector.md +94 -0
- package/templates/express/.claude/agents/gate-checker.md +176 -0
- package/templates/express/.claude/agents/reviewer.md +84 -0
- package/templates/express/.claude/agents/security-auditor.md +82 -0
- package/templates/express/.claude/hooks/post-write.sh +93 -0
- package/templates/express/.claude/rules/api.md +149 -0
- package/templates/express/.claude/rules/architecture.md +78 -0
- package/templates/express/.claude/rules/database.md +104 -0
- package/templates/express/.claude/rules/jobs.md +81 -0
- package/templates/express/.claude/rules/security.md +92 -0
- package/templates/express/.claude/rules/testing.md +97 -0
- package/templates/express/.claude/settings.json +35 -0
- package/templates/express/.claude/skills/00-infra-setup/SKILL.md +479 -0
- package/templates/express/.claude/skills/01-write-roadmap/SKILL.md +72 -0
- package/templates/express/.claude/skills/02-write-spec/SKILL.md +119 -0
- package/templates/express/.claude/skills/03-write-plan/SKILL.md +124 -0
- package/templates/express/.claude/skills/04-build-layer/SKILL.md +216 -0
- package/templates/express/.claude/skills/05-validate-layer/SKILL.md +43 -0
- package/templates/express/.claude/skills/06-push-layer/SKILL.md +59 -0
- package/templates/express/.claude/skills/07-layer-check/SKILL.md +62 -0
- package/templates/express/.claude/skills/08-garbage-collect/SKILL.md +86 -0
- package/templates/express/.claude/skills/09-doc-garden/SKILL.md +64 -0
- package/templates/express/.claude/skills/10-db-optimize/SKILL.md +96 -0
- package/templates/express/.claude/skills/11-load-test/SKILL.md +77 -0
- package/templates/express/.dockerignore +43 -0
- package/templates/express/.env.example +42 -0
- package/templates/express/.github/CODEOWNERS +22 -0
- package/templates/express/.github/dependabot.yml +48 -0
- package/templates/express/.github/pull_request_template.md +58 -0
- package/templates/express/.github/workflows/ci.yml +278 -0
- package/templates/express/.github/workflows/load-test.yml +41 -0
- package/templates/express/.gitleaks.toml +18 -0
- package/templates/express/.lintstagedrc.json +3 -0
- package/templates/express/.nvmrc +1 -0
- package/templates/express/.prettierrc +8 -0
- package/templates/express/.sequelizerc +8 -0
- package/templates/express/AGENTS.md +94 -0
- package/templates/express/ARCHITECTURE.md +161 -0
- package/templates/express/Dockerfile +40 -0
- package/templates/express/Makefile +79 -0
- package/templates/express/QUICKSTART.md +131 -0
- package/templates/express/docker-compose.yml +114 -0
- package/templates/express/docs/PLANS.md +111 -0
- package/templates/express/docs/QUALITY_SCORE.md +66 -0
- package/templates/express/docs/design-docs/core-beliefs.md +89 -0
- package/templates/express/docs/design-docs/decisions/ADR-000-infrastructure.md +70 -0
- package/templates/express/docs/design-docs/decisions/ADR-001-observability.md +82 -0
- package/templates/express/docs/design-docs/decisions/index.md +23 -0
- package/templates/express/docs/design-docs/index.md +11 -0
- package/templates/express/docs/design-docs/observability.md +194 -0
- package/templates/express/docs/design-docs/team-workflow.md +64 -0
- package/templates/express/docs/exec-plans/active/.gitkeep +0 -0
- package/templates/express/docs/exec-plans/completed/.gitkeep +0 -0
- package/templates/express/docs/exec-plans/tech-debt-tracker.md +31 -0
- package/templates/express/docs/generated/.gitkeep +0 -0
- package/templates/express/docs/product-specs/ROADMAP.md +49 -0
- package/templates/express/docs/product-specs/draft/.gitkeep +0 -0
- package/templates/express/docs/product-specs/index.md +21 -0
- package/templates/express/docs/product-specs/ready/.gitkeep +0 -0
- package/templates/express/eslint.config.mjs +94 -0
- package/templates/express/gitignore +36 -0
- package/templates/express/infra/monitoring/alloy/config.alloy +59 -0
- package/templates/express/jest.config.ts +61 -0
- package/templates/express/package.json +45 -0
- package/templates/express/scripts/openapi.export.ts +77 -0
- package/templates/express/tests/architecture/isolation.test.ts +51 -0
- package/templates/express/tests/architecture/layers.test.ts +83 -0
- package/templates/express/tests/integration/health.test.ts +40 -0
- package/templates/express/tests/integration/isolation.test.template.ts +88 -0
- package/templates/express/tests/load/smoke.js +46 -0
- package/templates/express/tests/load/soak.js +45 -0
- package/templates/express/tests/load/stress.js +44 -0
- package/templates/express/tests/unit/utils/response.util.test.ts +53 -0
- package/templates/express/tsconfig.build.json +8 -0
- package/templates/express/tsconfig.json +20 -0
- package/templates/fastapi/.claude/CLAUDE.md +122 -0
- package/templates/fastapi/.claude/agents/arch-validator.md +64 -0
- package/templates/fastapi/.claude/agents/db-optimizer.md +59 -0
- package/templates/fastapi/.claude/agents/doc-gardener.md +55 -0
- package/templates/fastapi/.claude/agents/garbage-collector.md +74 -0
- package/templates/fastapi/.claude/agents/gate-checker.md +133 -0
- package/templates/fastapi/.claude/agents/reviewer.md +74 -0
- package/templates/fastapi/.claude/agents/security-auditor.md +69 -0
- package/templates/fastapi/.claude/hooks/post-write.sh +65 -0
- package/templates/fastapi/.claude/rules/api.md +119 -0
- package/templates/fastapi/.claude/rules/architecture.md +84 -0
- package/templates/fastapi/.claude/rules/database.md +153 -0
- package/templates/fastapi/.claude/rules/jobs.md +85 -0
- package/templates/fastapi/.claude/rules/security.md +102 -0
- package/templates/fastapi/.claude/rules/testing.md +207 -0
- package/templates/fastapi/.claude/settings.json +50 -0
- package/templates/fastapi/.claude/skills/00-infra-setup/SKILL.md +311 -0
- package/templates/fastapi/.claude/skills/01-write-roadmap/SKILL.md +61 -0
- package/templates/fastapi/.claude/skills/02-write-spec/SKILL.md +82 -0
- package/templates/fastapi/.claude/skills/03-write-plan/SKILL.md +83 -0
- package/templates/fastapi/.claude/skills/04-build-layer/SKILL.md +170 -0
- package/templates/fastapi/.claude/skills/05-validate-layer/SKILL.md +20 -0
- package/templates/fastapi/.claude/skills/06-push-layer/SKILL.md +31 -0
- package/templates/fastapi/.claude/skills/07-layer-check/SKILL.md +51 -0
- package/templates/fastapi/.claude/skills/08-garbage-collect/SKILL.md +47 -0
- package/templates/fastapi/.claude/skills/09-doc-garden/SKILL.md +9 -0
- package/templates/fastapi/.claude/skills/10-db-optimize/SKILL.md +53 -0
- package/templates/fastapi/.claude/skills/11-load-test/SKILL.md +81 -0
- package/templates/fastapi/.dockerignore +30 -0
- package/templates/fastapi/.github/dependabot.yml +24 -0
- package/templates/fastapi/AGENTS.md +87 -0
- package/templates/fastapi/ARCHITECTURE.md +141 -0
- package/templates/fastapi/Makefile +42 -0
- package/templates/fastapi/README.md +179 -0
- package/templates/fastapi/docs/PLANS.md +26 -0
- package/templates/fastapi/docs/QUALITY_SCORE.md +26 -0
- package/templates/fastapi/docs/design-docs/core-beliefs.md +46 -0
- package/templates/fastapi/docs/design-docs/decisions/ADR-000-infrastructure.md +79 -0
- package/templates/fastapi/docs/design-docs/decisions/index.md +7 -0
- package/templates/fastapi/docs/design-docs/index.md +9 -0
- package/templates/fastapi/docs/exec-plans/active/.gitkeep +0 -0
- package/templates/fastapi/docs/exec-plans/completed/.gitkeep +0 -0
- package/templates/fastapi/docs/exec-plans/tech-debt-tracker.md +19 -0
- package/templates/fastapi/docs/generated/.gitkeep +0 -0
- package/templates/fastapi/docs/product-specs/ROADMAP.md +49 -0
- package/templates/fastapi/docs/product-specs/draft/.gitkeep +0 -0
- package/templates/fastapi/docs/product-specs/index.md +18 -0
- package/templates/fastapi/docs/product-specs/ready/.gitkeep +0 -0
- package/templates/fastapi/gitignore +46 -0
- package/templates/fastapi/scripts/gate.sh +68 -0
- package/templates/nestjs/.claude/CLAUDE.md +121 -0
- package/templates/nestjs/.claude/agents/db-optimizer.md +51 -0
- package/templates/nestjs/.claude/agents/doc-gardener.md +45 -0
- package/templates/nestjs/.claude/agents/garbage-collector.md +50 -0
- package/templates/nestjs/.claude/agents/gate-checker.md +127 -0
- package/templates/nestjs/.claude/agents/reviewer.md +68 -0
- package/templates/nestjs/.claude/agents/security-auditor.md +72 -0
- package/templates/nestjs/.claude/hooks/post-write.sh +91 -0
- package/templates/nestjs/.claude/rules/api.md +87 -0
- package/templates/nestjs/.claude/rules/architecture.md +104 -0
- package/templates/nestjs/.claude/rules/database.md +111 -0
- package/templates/nestjs/.claude/rules/security.md +110 -0
- package/templates/nestjs/.claude/rules/testing.md +145 -0
- package/templates/nestjs/.claude/settings.json +33 -0
- package/templates/nestjs/.claude/skills/00-infra-setup/SKILL.md +222 -0
- package/templates/nestjs/.claude/skills/01-write-spec/SKILL.md +25 -0
- package/templates/nestjs/.claude/skills/02-write-plan/SKILL.md +18 -0
- package/templates/nestjs/.claude/skills/03-build-layer/SKILL.md +242 -0
- package/templates/nestjs/.claude/skills/04-validate-layer/SKILL.md +4 -0
- package/templates/nestjs/.claude/skills/05-push-layer/SKILL.md +6 -0
- package/templates/nestjs/.claude/skills/06-layer-check/SKILL.md +12 -0
- package/templates/nestjs/.claude/skills/07-garbage-collect/SKILL.md +2 -0
- package/templates/nestjs/.claude/skills/08-doc-garden/SKILL.md +4 -0
- package/templates/nestjs/.claude/skills/09-api-sync/SKILL.md +36 -0
- package/templates/nestjs/.claude/skills/10-load-test/SKILL.md +29 -0
- package/templates/nestjs/.env.example +11 -0
- package/templates/nestjs/AGENTS.md +88 -0
- package/templates/nestjs/ARCHITECTURE.md +192 -0
- package/templates/nestjs/docs/PLANS.md +22 -0
- package/templates/nestjs/docs/QUALITY_SCORE.md +27 -0
- package/templates/nestjs/docs/design-docs/core-beliefs.md +18 -0
- package/templates/nestjs/docs/design-docs/decisions/ADR-000-infrastructure.md +58 -0
- package/templates/nestjs/docs/design-docs/decisions/index.md +7 -0
- package/templates/nestjs/docs/design-docs/index.md +7 -0
- package/templates/nestjs/docs/exec-plans/active/.gitkeep +0 -0
- package/templates/nestjs/docs/exec-plans/completed/.gitkeep +0 -0
- package/templates/nestjs/docs/exec-plans/tech-debt-tracker.md +16 -0
- package/templates/nestjs/docs/generated/.gitkeep +0 -0
- package/templates/nestjs/docs/product-specs/draft/.gitkeep +0 -0
- package/templates/nestjs/docs/product-specs/index.md +7 -0
- package/templates/nestjs/docs/product-specs/ready/.gitkeep +0 -0
- package/templates/nestjs/gitignore +8 -0
- package/templates/nextjs/.claude/CLAUDE.md +139 -0
- package/templates/nextjs/.claude/agents/arch-validator.md +66 -0
- package/templates/nextjs/.claude/agents/contract-checker.md +78 -0
- package/templates/nextjs/.claude/agents/doc-gardener.md +52 -0
- package/templates/nextjs/.claude/agents/garbage-collector.md +61 -0
- package/templates/nextjs/.claude/agents/gate-checker.md +129 -0
- package/templates/nextjs/.claude/agents/perf-auditor.md +109 -0
- package/templates/nextjs/.claude/agents/reviewer.md +79 -0
- package/templates/nextjs/.claude/agents/security-auditor.md +50 -0
- package/templates/nextjs/.claude/hooks/post-write.sh +121 -0
- package/templates/nextjs/.claude/rules/api-contract.md +166 -0
- package/templates/nextjs/.claude/rules/architecture.md +99 -0
- package/templates/nextjs/.claude/rules/components.md +122 -0
- package/templates/nextjs/.claude/rules/security.md +122 -0
- package/templates/nextjs/.claude/rules/testing.md +187 -0
- package/templates/nextjs/.claude/scripts/infra-setup.sh +550 -0
- package/templates/nextjs/.claude/settings.json +33 -0
- package/templates/nextjs/.claude/skills/00-infra-setup/SKILL.md +471 -0
- package/templates/nextjs/.claude/skills/01-write-roadmap/SKILL.md +77 -0
- package/templates/nextjs/.claude/skills/02-write-spec/SKILL.md +78 -0
- package/templates/nextjs/.claude/skills/03-write-plan/SKILL.md +91 -0
- package/templates/nextjs/.claude/skills/04-build-layer/SKILL.md +141 -0
- package/templates/nextjs/.claude/skills/05-validate-layer/SKILL.md +13 -0
- package/templates/nextjs/.claude/skills/06-push-layer/SKILL.md +20 -0
- package/templates/nextjs/.claude/skills/07-layer-check/SKILL.md +28 -0
- package/templates/nextjs/.claude/skills/08-garbage-collect/SKILL.md +14 -0
- package/templates/nextjs/.claude/skills/09-doc-garden/SKILL.md +12 -0
- package/templates/nextjs/.claude/skills/10-api-sync/SKILL.md +50 -0
- package/templates/nextjs/.claude/skills/11-perf-budget/SKILL.md +51 -0
- package/templates/nextjs/.dockerignore +25 -0
- package/templates/nextjs/.gitattributes +10 -0
- package/templates/nextjs/.github/CODEOWNERS +24 -0
- package/templates/nextjs/.github/dependabot.yml +31 -0
- package/templates/nextjs/.github/pull_request_template.md +59 -0
- package/templates/nextjs/.github/workflows/ci.yml +143 -0
- package/templates/nextjs/.github/workflows/lighthouse.yml +54 -0
- package/templates/nextjs/.github/workflows/load-test.yml +54 -0
- package/templates/nextjs/.husky/pre-commit +1 -0
- package/templates/nextjs/.lintstagedrc.json +4 -0
- package/templates/nextjs/.mcp.json +8 -0
- package/templates/nextjs/.prettierignore +13 -0
- package/templates/nextjs/.prettierrc +9 -0
- package/templates/nextjs/AGENTS.md +88 -0
- package/templates/nextjs/ARCHITECTURE.md +165 -0
- package/templates/nextjs/Dockerfile +38 -0
- package/templates/nextjs/Makefile +50 -0
- package/templates/nextjs/QUICKSTART.md +128 -0
- package/templates/nextjs/docs/PLANS.md +23 -0
- package/templates/nextjs/docs/QUALITY_SCORE.md +27 -0
- package/templates/nextjs/docs/design-docs/core-beliefs.md +43 -0
- package/templates/nextjs/docs/design-docs/decisions/ADR-000-infrastructure.md +72 -0
- package/templates/nextjs/docs/design-docs/decisions/index.md +7 -0
- package/templates/nextjs/docs/design-docs/index.md +7 -0
- package/templates/nextjs/docs/design-docs/team-workflow.md +66 -0
- package/templates/nextjs/docs/exec-plans/active/.gitkeep +0 -0
- package/templates/nextjs/docs/exec-plans/completed/.gitkeep +0 -0
- package/templates/nextjs/docs/exec-plans/tech-debt-tracker.md +19 -0
- package/templates/nextjs/docs/generated/.gitkeep +0 -0
- package/templates/nextjs/docs/product-specs/ROADMAP.md +59 -0
- package/templates/nextjs/docs/product-specs/draft/.gitkeep +0 -0
- package/templates/nextjs/docs/product-specs/index.md +18 -0
- package/templates/nextjs/docs/product-specs/ready/.gitkeep +0 -0
- package/templates/nextjs/eslint.config.mjs +150 -0
- package/templates/nextjs/gitignore +35 -0
- package/templates/nextjs/lighthouserc.js +37 -0
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# Product Roadmap
|
|
2
|
+
|
|
3
|
+
**Product:** *(name)* · **Brief:** *(one-line, or link to the brief)* · **Last updated:** *(YYYY-MM-DD)*
|
|
4
|
+
**Walking skeleton:** *(SPEC-001 — the thinnest end-to-end slice; build this first)*
|
|
5
|
+
|
|
6
|
+
> LIVING document — the altitude ABOVE specs. `/write-roadmap` writes it from a product brief.
|
|
7
|
+
> `/write-spec` reads it to pick the next spec and pre-fill epic + dependency context, and flips
|
|
8
|
+
> a row's **Spec ID** and **Status** as specs are created. Update in place; never delete history.
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## Bounded Contexts (Epics)
|
|
13
|
+
|
|
14
|
+
| Epic | Bounded Context | Responsibility |
|
|
15
|
+
|---|---|---|
|
|
16
|
+
| *(none yet)* | — | — |
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## Spec Roadmap (dependency-ordered)
|
|
21
|
+
|
|
22
|
+
| Order | Spec ID | Name | Epic | Depends On | Skeleton | Status |
|
|
23
|
+
|---|---|---|---|---|---|---|
|
|
24
|
+
| *(none yet)* | — | — | — | — | — | — |
|
|
25
|
+
|
|
26
|
+
> `Spec ID` is `—` until `/write-spec` creates the file and assigns the real number.
|
|
27
|
+
> `Depends On` references other rows by Spec ID (or by Order if not yet numbered).
|
|
28
|
+
> Exactly one row carries `✅ yes` in `Skeleton`. Every spec appears after its dependencies.
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## Build Sequence Rationale
|
|
33
|
+
|
|
34
|
+
1. *(walking skeleton — why this thin slice first: proves auth + one entity + one endpoint end-to-end)*
|
|
35
|
+
2. *(next slice — what it unblocks)*
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## Roadmap Statuses
|
|
40
|
+
|
|
41
|
+
| Status | Meaning |
|
|
42
|
+
|---|---|
|
|
43
|
+
| NOT_STARTED | On the roadmap, no spec file yet |
|
|
44
|
+
| DRAFT | `/write-spec` wrote a SPEC-XXX (in `draft/`) |
|
|
45
|
+
| READY | Spec approved — plannable |
|
|
46
|
+
| PLANNED | `/write-plan` created a plan |
|
|
47
|
+
| IN_PROGRESS | Being built |
|
|
48
|
+
| SHIPPED | Complete and live |
|
|
49
|
+
| CANCELLED | Removed from the roadmap |
|
|
File without changes
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Product Specs Index
|
|
2
|
+
|
|
3
|
+
> Whole-product decomposition (epics → dependency-ordered specs, walking skeleton) lives in
|
|
4
|
+
> [`ROADMAP.md`](ROADMAP.md). `/write-spec` fills this index per spec as each is created.
|
|
5
|
+
|
|
6
|
+
| ID | Name | Status | Plan | Created |
|
|
7
|
+
|---|---|---|---|---|
|
|
8
|
+
| *(no specs yet)* | — | — | — | — |
|
|
9
|
+
|
|
10
|
+
## Spec Statuses
|
|
11
|
+
| Status | Meaning |
|
|
12
|
+
|---|---|
|
|
13
|
+
| DRAFT | Written, not reviewed |
|
|
14
|
+
| READY | Approved — plannable |
|
|
15
|
+
| PLANNED | Plan created |
|
|
16
|
+
| IN_PROGRESS | Being built |
|
|
17
|
+
| SHIPPED | Complete and live |
|
|
18
|
+
| CANCELLED | Not being built |
|
|
File without changes
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*.class
|
|
5
|
+
*.pyc
|
|
6
|
+
.Python
|
|
7
|
+
.venv/
|
|
8
|
+
venv/
|
|
9
|
+
env/
|
|
10
|
+
|
|
11
|
+
# uv
|
|
12
|
+
.uv/
|
|
13
|
+
|
|
14
|
+
# Build
|
|
15
|
+
dist/
|
|
16
|
+
build/
|
|
17
|
+
*.egg-info/
|
|
18
|
+
|
|
19
|
+
# Environment — NEVER commit
|
|
20
|
+
.env
|
|
21
|
+
.env.local
|
|
22
|
+
.env.*.local
|
|
23
|
+
|
|
24
|
+
# Testing
|
|
25
|
+
.coverage
|
|
26
|
+
htmlcov/
|
|
27
|
+
.pytest_cache/
|
|
28
|
+
.mypy_cache/
|
|
29
|
+
.ruff_cache/
|
|
30
|
+
|
|
31
|
+
# Logs
|
|
32
|
+
*.log
|
|
33
|
+
logs/
|
|
34
|
+
|
|
35
|
+
# OS
|
|
36
|
+
.DS_Store
|
|
37
|
+
Thumbs.db
|
|
38
|
+
|
|
39
|
+
# IDE
|
|
40
|
+
.idea/
|
|
41
|
+
.vscode/
|
|
42
|
+
*.swp
|
|
43
|
+
*.swo
|
|
44
|
+
|
|
45
|
+
# Docker
|
|
46
|
+
docker-compose.override.yml
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# scripts/gate.sh — deterministic, runnable mirror of the gate-checker agent's
|
|
3
|
+
# universal checks. Humans run `make gate`; pre-commit runs this; the agent runs
|
|
4
|
+
# the same logic. Exits non-zero on any violation so it can block commits/CI.
|
|
5
|
+
#
|
|
6
|
+
# Layer-specific coverage thresholds (utils 100 / services 90 / repo 80 /
|
|
7
|
+
# runtime 75 / providers 70) are enforced by the gate-checker agent and CI;
|
|
8
|
+
# this script enforces the universal, always-on invariants.
|
|
9
|
+
|
|
10
|
+
set -uo pipefail
|
|
11
|
+
|
|
12
|
+
FAIL=0
|
|
13
|
+
fail() { printf '%b\n' "❌ $1"; FAIL=1; } # %b so embedded \n render as newlines
|
|
14
|
+
pass() { printf '%b\n' "✓ $1"; }
|
|
15
|
+
|
|
16
|
+
if [[ ! -d src ]]; then
|
|
17
|
+
echo "No src/ yet — run /infra-setup first. Nothing to gate."
|
|
18
|
+
exit 0
|
|
19
|
+
fi
|
|
20
|
+
|
|
21
|
+
# 1. File size — no file > 400 lines
|
|
22
|
+
BIG=$(find src/ -name "*.py" -print0 | xargs -0 wc -l 2>/dev/null | awk '$1 > 400 && $2 != "total" { print $2" ("$1" lines)" }')
|
|
23
|
+
[[ -n "$BIG" ]] && fail "files over 400 lines:\n$BIG" || pass "no file > 400 lines"
|
|
24
|
+
|
|
25
|
+
# 2. print() in src/ (except logger.py and config/)
|
|
26
|
+
PRINTS=$(grep -rn "^\s*print(" src/ --include="*.py" 2>/dev/null | grep -v "src/providers/logger" | grep -v "src/config/")
|
|
27
|
+
[[ -n "$PRINTS" ]] && fail "print() in src/:\n$PRINTS" || pass "no print() in src/"
|
|
28
|
+
|
|
29
|
+
# 3. os.environ outside settings.py
|
|
30
|
+
ENVS=$(grep -rn "os\.environ" src/ --include="*.py" 2>/dev/null | grep -v "src/config/settings.py")
|
|
31
|
+
[[ -n "$ENVS" ]] && fail "os.environ outside settings.py:\n$ENVS" || pass "no os.environ outside settings.py"
|
|
32
|
+
|
|
33
|
+
# 4. HTTPException raised in a service
|
|
34
|
+
SVC_HTTP=$(grep -rn "HTTPException" src/services/ --include="*.py" 2>/dev/null)
|
|
35
|
+
[[ -n "$SVC_HTTP" ]] && fail "HTTPException in service layer:\n$SVC_HTTP" || pass "no HTTPException in services"
|
|
36
|
+
|
|
37
|
+
# 5. Services must not import fastapi or ORM models
|
|
38
|
+
SVC_IMP=$(grep -rn "from fastapi\|import fastapi\|from src.models\|import src.models" src/services/ --include="*.py" 2>/dev/null)
|
|
39
|
+
[[ -n "$SVC_IMP" ]] && fail "service imports fastapi/models:\n$SVC_IMP" || pass "services free of fastapi/models imports"
|
|
40
|
+
|
|
41
|
+
# 6. Unvalidated raw dict / ORM returns in repo
|
|
42
|
+
RAW=$(grep -rn "return row\.__dict__\|return dict(row\|return rows\b" src/repo/ --include="*.py" 2>/dev/null)
|
|
43
|
+
[[ -n "$RAW" ]] && fail "unvalidated returns in repo (use Schema.model_validate):\n$RAW" || pass "repo returns validated"
|
|
44
|
+
|
|
45
|
+
# 7. Offset pagination in repo
|
|
46
|
+
OFFSET=$(grep -rn "\.offset(" src/repo/ --include="*.py" 2>/dev/null)
|
|
47
|
+
[[ -n "$OFFSET" ]] && fail "offset pagination in repo (use cursor):\n$OFFSET" || pass "no offset pagination"
|
|
48
|
+
|
|
49
|
+
# 8. ruff
|
|
50
|
+
echo "── ruff ──"; uv run ruff check src/ || FAIL=1
|
|
51
|
+
|
|
52
|
+
# 9. mypy
|
|
53
|
+
echo "── mypy ──"; uv run mypy src/ || FAIL=1
|
|
54
|
+
|
|
55
|
+
# 10. bandit (full security scan)
|
|
56
|
+
echo "── bandit ──"; uv run bandit -r src/ -ll -q || FAIL=1
|
|
57
|
+
|
|
58
|
+
# 11. architecture structural tests
|
|
59
|
+
if [[ -d tests/architecture ]]; then
|
|
60
|
+
echo "── architecture tests ──"; uv run pytest tests/architecture/ -q || FAIL=1
|
|
61
|
+
fi
|
|
62
|
+
|
|
63
|
+
echo "─────────────────────────────"
|
|
64
|
+
if [[ $FAIL -ne 0 ]]; then
|
|
65
|
+
echo "GATE: ❌ FAIL"
|
|
66
|
+
exit 1
|
|
67
|
+
fi
|
|
68
|
+
echo "GATE: ✅ PASS"
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
# CLAUDE.md — Agent Entry Point
|
|
2
|
+
|
|
3
|
+
Stack: NestJS 11 · TypeScript 5 strict · Sequelize 6 + sequelize-typescript · PostgreSQL · Redis · BullMQ
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Cardinal Rules
|
|
8
|
+
|
|
9
|
+
1. **Read the active plan first** — `docs/exec-plans/active/`
|
|
10
|
+
2. **No plan = no code** — run `/write-spec` then `/write-plan` first
|
|
11
|
+
3. **Gate must PASS before commit** — auto-fix, re-run, then commit
|
|
12
|
+
4. **One layer at a time** — complete + gate + commit before next
|
|
13
|
+
5. **No `process.env`** — use `ConfigService` injected via NestJS DI
|
|
14
|
+
6. **No `HttpException` in services** — use `NotFoundException`, `ConflictException` etc.
|
|
15
|
+
7. **No `@InjectModel()` in services** — inject the repository, not the model
|
|
16
|
+
8. **Zod parse every `.toJSON()`** — in repository only, every time
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## Session Start Checklist
|
|
21
|
+
|
|
22
|
+
```
|
|
23
|
+
1. ls docs/exec-plans/active/ → active plan?
|
|
24
|
+
2. If yes → read it → find first [ ] layer → /build-layer
|
|
25
|
+
3. If no → ask human what to build → /write-spec
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## NestJS-Specific Patterns
|
|
31
|
+
|
|
32
|
+
### Config — always ConfigService, never process.env
|
|
33
|
+
```typescript
|
|
34
|
+
// ✅ Inject ConfigService
|
|
35
|
+
constructor(private config: ConfigService) {}
|
|
36
|
+
const secret = this.config.get<string>('JWT_SECRET')
|
|
37
|
+
|
|
38
|
+
// ❌ Never
|
|
39
|
+
const secret = process.env.JWT_SECRET
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### Auth — global guard, opt-out with @Public()
|
|
43
|
+
```typescript
|
|
44
|
+
// ✅ Public route
|
|
45
|
+
@Public()
|
|
46
|
+
@Post('register')
|
|
47
|
+
register(@Body() dto: RegisterDto) { ... }
|
|
48
|
+
|
|
49
|
+
// ✅ Protected (no decoration needed — global guard handles it)
|
|
50
|
+
@Get('me')
|
|
51
|
+
getProfile(@CurrentUser() user: JwtPayload) { ... }
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### Service exceptions — NestJS built-ins only
|
|
55
|
+
```typescript
|
|
56
|
+
// ✅
|
|
57
|
+
throw new NotFoundException(`Application ${id} not found`)
|
|
58
|
+
throw new ConflictException('Invalid stage transition')
|
|
59
|
+
|
|
60
|
+
// ❌
|
|
61
|
+
throw new HttpException('not found', 404)
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Repository — Zod on every output
|
|
65
|
+
```typescript
|
|
66
|
+
// ✅
|
|
67
|
+
const raw = await this.appModel.findOne({ where: { id, userId } })
|
|
68
|
+
if (!raw) throw new NotFoundException(`Application ${id} not found`)
|
|
69
|
+
return ApplicationSchema.parse(raw.toJSON())
|
|
70
|
+
|
|
71
|
+
// ❌
|
|
72
|
+
return raw // raw Sequelize instance
|
|
73
|
+
return raw.toJSON() as App // cast without validation
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### Controller — one-liners only
|
|
77
|
+
```typescript
|
|
78
|
+
// ✅
|
|
79
|
+
@Get(':id')
|
|
80
|
+
@ApiOperation({ summary: 'Get application by ID' })
|
|
81
|
+
@ApiOkResponse({ type: ApplicationResponseDto })
|
|
82
|
+
findOne(@Param('id') id: string, @CurrentUser() user: JwtPayload) {
|
|
83
|
+
return this.applicationService.findOne(user.sub, id)
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// ❌ Business logic in controller
|
|
87
|
+
@Get(':id')
|
|
88
|
+
async findOne(@Param('id') id: string) {
|
|
89
|
+
const app = await this.service.findOne(id)
|
|
90
|
+
if (app.stage === 'CANCELLED') { ... } // logic belongs in service
|
|
91
|
+
}
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### Logging — Logger, not console
|
|
95
|
+
```typescript
|
|
96
|
+
// ✅
|
|
97
|
+
private readonly logger = new Logger(ApplicationService.name)
|
|
98
|
+
this.logger.log({ event: 'application.created', id: app.id })
|
|
99
|
+
|
|
100
|
+
// ❌
|
|
101
|
+
console.log('created', app.id)
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## Stack Reference
|
|
107
|
+
|
|
108
|
+
```
|
|
109
|
+
Framework: NestJS 11, Node 22, TypeScript 5 strict
|
|
110
|
+
ORM: Sequelize 6 + sequelize-typescript + sequelize-cli
|
|
111
|
+
Auth: @nestjs/passport + passport-jwt + @nestjs/jwt
|
|
112
|
+
Password: argon2
|
|
113
|
+
Config: @nestjs/config + joi
|
|
114
|
+
Logging: nestjs-pino + pino
|
|
115
|
+
Queue: @nestjs/bullmq + bullmq + ioredis
|
|
116
|
+
Rate limit: @nestjs/throttler
|
|
117
|
+
API docs: @nestjs/swagger (live at /api/docs)
|
|
118
|
+
Health: @nestjs/terminus (/health + /ready)
|
|
119
|
+
Validation: class-validator + class-transformer (input) + zod (output)
|
|
120
|
+
Testing: Jest + Supertest (NestJS default)
|
|
121
|
+
```
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: db-optimizer
|
|
3
|
+
description: Audits repository layer for N+1, missing indexes, offset pagination. Run before shipping any DB queries.
|
|
4
|
+
model: claude-sonnet-4-5
|
|
5
|
+
tools: [Read, Bash]
|
|
6
|
+
color: orange
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Checks
|
|
10
|
+
|
|
11
|
+
### N+1 Detection
|
|
12
|
+
```bash
|
|
13
|
+
# Flag model calls inside loops
|
|
14
|
+
grep -rn "for\|forEach\|\.map" src/ --include="*.repository.ts" -A5 | grep "await this\."
|
|
15
|
+
```
|
|
16
|
+
For each N+1: provide the `include: [{ model: X }]` fix.
|
|
17
|
+
|
|
18
|
+
### Pagination Audit
|
|
19
|
+
```bash
|
|
20
|
+
grep -rn "findAll\|list\|getAll" src/ --include="*.repository.ts"
|
|
21
|
+
grep -rn "offset:\|\.offset(" src/ --include="*.repository.ts"
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
### Zod Parse Audit
|
|
25
|
+
```bash
|
|
26
|
+
grep -rn "\.toJSON()" src/ --include="*.repository.ts" -A2 | grep -v "Schema\.parse"
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
### Index Audit
|
|
30
|
+
Check every `where:` in repository files — verify matching index in `@Table({ indexes })`.
|
|
31
|
+
|
|
32
|
+
### Soft Delete Audit
|
|
33
|
+
```bash
|
|
34
|
+
grep -rn "findAll\|findOne" src/ --include="*.repository.ts" -A10 | grep -v "userId\|user_id"
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Output
|
|
38
|
+
```
|
|
39
|
+
APPROVED — all repo patterns correct.
|
|
40
|
+
|
|
41
|
+
OR
|
|
42
|
+
|
|
43
|
+
CRITICAL:
|
|
44
|
+
1. N+1 in applications.repository.ts:45
|
|
45
|
+
Fix: add include: [{ model: Note }] to findAll
|
|
46
|
+
|
|
47
|
+
HIGH:
|
|
48
|
+
2. Missing index — applications filtered by (userId, stage) with no composite index
|
|
49
|
+
Fix: add to @Table indexes: [{ fields: ['user_id', 'stage'] }]
|
|
50
|
+
Migration: CREATE INDEX CONCURRENTLY idx_applications_user_stage ON applications(user_id, stage)
|
|
51
|
+
```
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: doc-gardener
|
|
3
|
+
description: Scans documentation for staleness and fixes it. Called by /doc-garden skill.
|
|
4
|
+
model: claude-sonnet-4-5
|
|
5
|
+
tools: [Read, Write, Bash]
|
|
6
|
+
color: green
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Checks
|
|
10
|
+
|
|
11
|
+
### AGENTS.md
|
|
12
|
+
- Agents table matches `.claude/agents/` directory?
|
|
13
|
+
- Slash commands match `.claude/skills/` directory?
|
|
14
|
+
|
|
15
|
+
### ARCHITECTURE.md
|
|
16
|
+
- Module list matches actual `src/` structure?
|
|
17
|
+
- Layer definitions still accurate?
|
|
18
|
+
|
|
19
|
+
### docs/product-specs/index.md
|
|
20
|
+
- Every spec in `draft/` and `ready/` has a row?
|
|
21
|
+
- Status matches `Status:` field inside the file?
|
|
22
|
+
|
|
23
|
+
### .env.example
|
|
24
|
+
```bash
|
|
25
|
+
grep -o "[A-Z_]*:" src/config/configuration.ts | sort
|
|
26
|
+
grep "^[A-Z]" .env.example | cut -d= -f1 | sort
|
|
27
|
+
```
|
|
28
|
+
Every config key documented?
|
|
29
|
+
|
|
30
|
+
### docs/design-docs/decisions/index.md
|
|
31
|
+
Every `.md` file in `decisions/` listed?
|
|
32
|
+
|
|
33
|
+
## Output + Commit
|
|
34
|
+
```
|
|
35
|
+
DOC GARDEN — {timestamp}
|
|
36
|
+
Updated: [file] — [what]
|
|
37
|
+
No changes: [file] ✓
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
If changed:
|
|
41
|
+
```bash
|
|
42
|
+
git add docs/ AGENTS.md ARCHITECTURE.md .env.example
|
|
43
|
+
git commit -m "docs: doc garden — sync stale documentation"
|
|
44
|
+
git push origin main
|
|
45
|
+
```
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: garbage-collector
|
|
3
|
+
description: End-of-feature cleanup. Called by /garbage-collect after all layers complete.
|
|
4
|
+
model: claude-sonnet-4-5
|
|
5
|
+
tools: [Read, Write, Bash]
|
|
6
|
+
color: green
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Steps (auto-fix everything)
|
|
10
|
+
|
|
11
|
+
### 1. File Size
|
|
12
|
+
```bash
|
|
13
|
+
find src/ -name "*.ts" | xargs wc -l | awk '$1 > 400 { print $2, $1 }' | sort -rn
|
|
14
|
+
```
|
|
15
|
+
Split any file over 400 lines.
|
|
16
|
+
|
|
17
|
+
### 2. TypeScript + ESLint
|
|
18
|
+
```bash
|
|
19
|
+
npx tsc --noEmit
|
|
20
|
+
npx eslint src/ --fix --max-warnings=0
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
### 3. Stale Docs
|
|
24
|
+
- `AGENTS.md` — matches current modules?
|
|
25
|
+
- `ARCHITECTURE.md` — matches current `src/` structure?
|
|
26
|
+
- `docs/design-docs/decisions/index.md` — all ADRs listed?
|
|
27
|
+
- `.env.example` — all vars from `src/config/configuration.ts` documented?
|
|
28
|
+
|
|
29
|
+
### 4. Update QUALITY_SCORE.md
|
|
30
|
+
```bash
|
|
31
|
+
npx jest --coverage 2>&1 | grep -A5 "Coverage summary"
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### 5. Log Tech Debt → `docs/exec-plans/tech-debt-tracker.md`
|
|
35
|
+
|
|
36
|
+
### 6. Close Plan
|
|
37
|
+
- All `[x]` confirmed
|
|
38
|
+
- `Status: COMPLETE`, `Completed: YYYY-MM-DD`
|
|
39
|
+
- Move: `docs/exec-plans/active/PLAN-XXX.md` → `docs/exec-plans/completed/`
|
|
40
|
+
|
|
41
|
+
### 7. Mark Spec SHIPPED
|
|
42
|
+
- `docs/product-specs/ready/SPEC-XXX.md` → `Status: SHIPPED`
|
|
43
|
+
- Update `docs/product-specs/index.md`
|
|
44
|
+
|
|
45
|
+
### 8. Final Commit
|
|
46
|
+
```bash
|
|
47
|
+
git add -A
|
|
48
|
+
git commit -m "chore: garbage collect — close PLAN-XXX"
|
|
49
|
+
git push origin main
|
|
50
|
+
```
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: gate-checker
|
|
3
|
+
description: Runs the layer gate after every /build-layer. Outputs PASS or FAIL with exact items. Called automatically — not by human.
|
|
4
|
+
model: claude-sonnet-4-5
|
|
5
|
+
tools: [Bash, Read]
|
|
6
|
+
color: red
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
You are the gate enforcement agent. Check current layer against all harness standards.
|
|
10
|
+
Output precise PASS or FAIL verdict. Never build code — only check it.
|
|
11
|
+
|
|
12
|
+
## Universal Checks (every layer)
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
# 1. TypeScript
|
|
16
|
+
npx tsc --noEmit 2>&1
|
|
17
|
+
|
|
18
|
+
# 2. ESLint
|
|
19
|
+
npx eslint src/ --max-warnings=0 2>&1
|
|
20
|
+
|
|
21
|
+
# 3. File size
|
|
22
|
+
find src/ -name "*.ts" | xargs wc -l | sort -rn | awk '$1 > 400 { print "FAIL:", $2, $1, "lines" }'
|
|
23
|
+
|
|
24
|
+
# 4. console.log
|
|
25
|
+
grep -rn "console\.\(log\|error\|warn\|info\)" src/ --include="*.ts"
|
|
26
|
+
|
|
27
|
+
# 5. process.env outside config/
|
|
28
|
+
grep -rn "process\.env" src/ --include="*.ts" | grep -v "src/config/"
|
|
29
|
+
|
|
30
|
+
# 6. HttpException in services
|
|
31
|
+
grep -rn "HttpException" src/ --include="*.service.ts"
|
|
32
|
+
|
|
33
|
+
# 7. @InjectModel in services
|
|
34
|
+
grep -rn "@InjectModel" src/ --include="*.service.ts"
|
|
35
|
+
|
|
36
|
+
# 8. Architecture tests
|
|
37
|
+
npx jest src/ --testPathPattern="spec" --no-coverage 2>&1 | tail -5
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Layer-Specific Checks
|
|
41
|
+
|
|
42
|
+
### Model layer
|
|
43
|
+
```bash
|
|
44
|
+
# paranoid: true on all models
|
|
45
|
+
grep -rL "paranoid.*true" src/**/*.model.ts 2>/dev/null
|
|
46
|
+
|
|
47
|
+
# UUIDv7 default on id
|
|
48
|
+
grep -rn "@Column.*primaryKey" src/ --include="*.model.ts" -A2 | grep -v "newId"
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### DTO layer
|
|
52
|
+
```bash
|
|
53
|
+
# @ApiProperty on all properties
|
|
54
|
+
grep -rn "^\s*readonly\s\+" src/ --include="*.dto.ts" | while read line; do
|
|
55
|
+
file=$(echo $line | cut -d: -f1)
|
|
56
|
+
grep -c "@ApiProperty" $file 2>/dev/null || echo "MISSING @ApiProperty in $file"
|
|
57
|
+
done
|
|
58
|
+
|
|
59
|
+
# class-validator on all input fields
|
|
60
|
+
grep -rn "^\s*readonly\s\+" src/ --include="*create*.dto.ts" -c
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### Repository layer
|
|
64
|
+
```bash
|
|
65
|
+
# Zod parse on all returns
|
|
66
|
+
grep -rn "\.toJSON()" src/ --include="*.repository.ts" -A2 | grep -v "Schema\.parse\|\.parse("
|
|
67
|
+
# No offset pagination
|
|
68
|
+
grep -rn "offset:\|\.offset(" src/ --include="*.repository.ts"
|
|
69
|
+
# Ownership check (userId in WHERE)
|
|
70
|
+
grep -rn "findByPk\|findOne\|findAll" src/ --include="*.repository.ts" | grep -v "userId\|user_id"
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### Service layer
|
|
74
|
+
```bash
|
|
75
|
+
# No @InjectModel (should use repository)
|
|
76
|
+
grep -rn "@InjectModel" src/ --include="*.service.ts"
|
|
77
|
+
# No HTTP imports
|
|
78
|
+
grep -rn "from 'express'\|HttpException\b" src/ --include="*.service.ts"
|
|
79
|
+
# Coverage
|
|
80
|
+
npx jest --testPathPattern="service.spec" --coverage --coverageThreshold='{"global":{"lines":90}}' 2>&1 | tail -3
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### Controller layer
|
|
84
|
+
```bash
|
|
85
|
+
# @ApiTags on every controller
|
|
86
|
+
grep -rn "@Controller" src/ --include="*.controller.ts" -B5 | grep -v "@ApiTags"
|
|
87
|
+
# @ApiOperation on every route
|
|
88
|
+
grep -rn "@Get\|@Post\|@Put\|@Patch\|@Delete" src/ --include="*.controller.ts" -B3 | grep -v "@ApiOperation"
|
|
89
|
+
# No business logic
|
|
90
|
+
grep -rn "^\s\+if\|^\s\+else\|^\s\+switch" src/ --include="*.controller.ts"
|
|
91
|
+
# E2E coverage
|
|
92
|
+
npx jest --testPathPattern="e2e" --no-coverage 2>&1 | tail -5
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### Module layer
|
|
96
|
+
```bash
|
|
97
|
+
# SequelizeModule.forFeature in imports
|
|
98
|
+
grep -rn "SequelizeModule.forFeature" src/ --include="*.module.ts"
|
|
99
|
+
# Repository in providers
|
|
100
|
+
grep -rn "Repository\b" src/ --include="*.module.ts"
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## Output Format
|
|
104
|
+
```
|
|
105
|
+
─────────────────────────────────────────
|
|
106
|
+
GATE CHECK — Layer: [name] [Attempt N]
|
|
107
|
+
─────────────────────────────────────────
|
|
108
|
+
Universal
|
|
109
|
+
✓/✗ TypeScript: 0 errors
|
|
110
|
+
✓/✗ ESLint: 0 errors
|
|
111
|
+
✓/✗ No file > 400 lines
|
|
112
|
+
✓/✗ No console.log
|
|
113
|
+
✓/✗ No process.env outside config/
|
|
114
|
+
✓/✗ No HttpException in services
|
|
115
|
+
✓/✗ No @InjectModel in services
|
|
116
|
+
|
|
117
|
+
Layer-Specific ([name])
|
|
118
|
+
✓/✗ [check]
|
|
119
|
+
|
|
120
|
+
Tests
|
|
121
|
+
✓/✗ Coverage: XX% (threshold: YY%)
|
|
122
|
+
─────────────────────────────────────────
|
|
123
|
+
STATUS: ✅ PASS / ❌ FAIL — N items
|
|
124
|
+
|
|
125
|
+
ITEM 1: [file:line] [problem] → [exact fix]
|
|
126
|
+
─────────────────────────────────────────
|
|
127
|
+
```
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: reviewer
|
|
3
|
+
description: Full harness review before opening a PR. Run with "Use the reviewer agent to review current changes."
|
|
4
|
+
model: claude-sonnet-4-5
|
|
5
|
+
tools: [Read, Bash]
|
|
6
|
+
color: blue
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
Run `git diff main --name-only` then read all changed files.
|
|
10
|
+
|
|
11
|
+
## Checklist
|
|
12
|
+
|
|
13
|
+
### Architecture
|
|
14
|
+
- [ ] No cross-layer violations (service doesn't touch HTTP, controller has no logic)
|
|
15
|
+
- [ ] No file > 400 lines
|
|
16
|
+
- [ ] TypeScript: 0 errors
|
|
17
|
+
- [ ] ESLint: 0 errors
|
|
18
|
+
|
|
19
|
+
### Code Quality
|
|
20
|
+
- [ ] No `console.log` (use `Logger`)
|
|
21
|
+
- [ ] No `process.env` (use `ConfigService`)
|
|
22
|
+
- [ ] No `HttpException` in services
|
|
23
|
+
- [ ] No `@InjectModel` in services (inject repository)
|
|
24
|
+
|
|
25
|
+
### Database (if repository/model changed)
|
|
26
|
+
- [ ] All `.toJSON()` results: `ZodSchema.parse()`
|
|
27
|
+
- [ ] All list methods: cursor pagination (no offset)
|
|
28
|
+
- [ ] No N+1 (no model calls in loops — use `include`)
|
|
29
|
+
- [ ] Multi-table writes: `sequelize.transaction()`
|
|
30
|
+
- [ ] New models: `paranoid: true`, `newId()`, indexes in `@Table`
|
|
31
|
+
- [ ] Ownership: `userId` in every WHERE clause
|
|
32
|
+
|
|
33
|
+
### API (if controller changed)
|
|
34
|
+
- [ ] `@ApiTags()` on controller class
|
|
35
|
+
- [ ] `@ApiOperation()` on every route
|
|
36
|
+
- [ ] `@ApiBearerAuth()` on class (if protected)
|
|
37
|
+
- [ ] `@ApiResponse()` on every route
|
|
38
|
+
- [ ] All routes under `/v1/` prefix
|
|
39
|
+
- [ ] Rate limiting tier applied
|
|
40
|
+
|
|
41
|
+
### Security
|
|
42
|
+
- [ ] Public routes have `@Public()`
|
|
43
|
+
- [ ] No `@UseGuards(JwtAuthGuard)` manually (it's global)
|
|
44
|
+
- [ ] Admin routes have `@Roles('ADMIN')`
|
|
45
|
+
- [ ] Input validation via DTO + `@ApiProperty()`
|
|
46
|
+
|
|
47
|
+
### Tests
|
|
48
|
+
- [ ] Service: 90%+ coverage, error paths tested
|
|
49
|
+
- [ ] E2E: 201, 401, 422, 404 all covered
|
|
50
|
+
- [ ] Mock uses `Test.createTestingModule` pattern
|
|
51
|
+
|
|
52
|
+
### Docs
|
|
53
|
+
- [ ] ADR for non-obvious decisions
|
|
54
|
+
- [ ] `QUALITY_SCORE.md` updated
|
|
55
|
+
|
|
56
|
+
## Verdict
|
|
57
|
+
```
|
|
58
|
+
APPROVED — ready to merge.
|
|
59
|
+
|
|
60
|
+
OR
|
|
61
|
+
|
|
62
|
+
CHANGES REQUIRED:
|
|
63
|
+
BLOCKING:
|
|
64
|
+
1. [file:line] [problem] → [fix]
|
|
65
|
+
|
|
66
|
+
NON-BLOCKING:
|
|
67
|
+
2. [description]
|
|
68
|
+
```
|