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.
Files changed (240) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +156 -0
  3. package/cli.js +122 -0
  4. package/package.json +47 -0
  5. package/templates/express/.claude/CLAUDE.md +114 -0
  6. package/templates/express/.claude/agents/arch-validator.md +85 -0
  7. package/templates/express/.claude/agents/db-optimizer.md +72 -0
  8. package/templates/express/.claude/agents/doc-gardener.md +67 -0
  9. package/templates/express/.claude/agents/garbage-collector.md +94 -0
  10. package/templates/express/.claude/agents/gate-checker.md +176 -0
  11. package/templates/express/.claude/agents/reviewer.md +84 -0
  12. package/templates/express/.claude/agents/security-auditor.md +82 -0
  13. package/templates/express/.claude/hooks/post-write.sh +93 -0
  14. package/templates/express/.claude/rules/api.md +149 -0
  15. package/templates/express/.claude/rules/architecture.md +78 -0
  16. package/templates/express/.claude/rules/database.md +104 -0
  17. package/templates/express/.claude/rules/jobs.md +81 -0
  18. package/templates/express/.claude/rules/security.md +92 -0
  19. package/templates/express/.claude/rules/testing.md +97 -0
  20. package/templates/express/.claude/settings.json +35 -0
  21. package/templates/express/.claude/skills/00-infra-setup/SKILL.md +479 -0
  22. package/templates/express/.claude/skills/01-write-roadmap/SKILL.md +72 -0
  23. package/templates/express/.claude/skills/02-write-spec/SKILL.md +119 -0
  24. package/templates/express/.claude/skills/03-write-plan/SKILL.md +124 -0
  25. package/templates/express/.claude/skills/04-build-layer/SKILL.md +216 -0
  26. package/templates/express/.claude/skills/05-validate-layer/SKILL.md +43 -0
  27. package/templates/express/.claude/skills/06-push-layer/SKILL.md +59 -0
  28. package/templates/express/.claude/skills/07-layer-check/SKILL.md +62 -0
  29. package/templates/express/.claude/skills/08-garbage-collect/SKILL.md +86 -0
  30. package/templates/express/.claude/skills/09-doc-garden/SKILL.md +64 -0
  31. package/templates/express/.claude/skills/10-db-optimize/SKILL.md +96 -0
  32. package/templates/express/.claude/skills/11-load-test/SKILL.md +77 -0
  33. package/templates/express/.dockerignore +43 -0
  34. package/templates/express/.env.example +42 -0
  35. package/templates/express/.github/CODEOWNERS +22 -0
  36. package/templates/express/.github/dependabot.yml +48 -0
  37. package/templates/express/.github/pull_request_template.md +58 -0
  38. package/templates/express/.github/workflows/ci.yml +278 -0
  39. package/templates/express/.github/workflows/load-test.yml +41 -0
  40. package/templates/express/.gitleaks.toml +18 -0
  41. package/templates/express/.lintstagedrc.json +3 -0
  42. package/templates/express/.nvmrc +1 -0
  43. package/templates/express/.prettierrc +8 -0
  44. package/templates/express/.sequelizerc +8 -0
  45. package/templates/express/AGENTS.md +94 -0
  46. package/templates/express/ARCHITECTURE.md +161 -0
  47. package/templates/express/Dockerfile +40 -0
  48. package/templates/express/Makefile +79 -0
  49. package/templates/express/QUICKSTART.md +131 -0
  50. package/templates/express/docker-compose.yml +114 -0
  51. package/templates/express/docs/PLANS.md +111 -0
  52. package/templates/express/docs/QUALITY_SCORE.md +66 -0
  53. package/templates/express/docs/design-docs/core-beliefs.md +89 -0
  54. package/templates/express/docs/design-docs/decisions/ADR-000-infrastructure.md +70 -0
  55. package/templates/express/docs/design-docs/decisions/ADR-001-observability.md +82 -0
  56. package/templates/express/docs/design-docs/decisions/index.md +23 -0
  57. package/templates/express/docs/design-docs/index.md +11 -0
  58. package/templates/express/docs/design-docs/observability.md +194 -0
  59. package/templates/express/docs/design-docs/team-workflow.md +64 -0
  60. package/templates/express/docs/exec-plans/active/.gitkeep +0 -0
  61. package/templates/express/docs/exec-plans/completed/.gitkeep +0 -0
  62. package/templates/express/docs/exec-plans/tech-debt-tracker.md +31 -0
  63. package/templates/express/docs/generated/.gitkeep +0 -0
  64. package/templates/express/docs/product-specs/ROADMAP.md +49 -0
  65. package/templates/express/docs/product-specs/draft/.gitkeep +0 -0
  66. package/templates/express/docs/product-specs/index.md +21 -0
  67. package/templates/express/docs/product-specs/ready/.gitkeep +0 -0
  68. package/templates/express/eslint.config.mjs +94 -0
  69. package/templates/express/gitignore +36 -0
  70. package/templates/express/infra/monitoring/alloy/config.alloy +59 -0
  71. package/templates/express/jest.config.ts +61 -0
  72. package/templates/express/package.json +45 -0
  73. package/templates/express/scripts/openapi.export.ts +77 -0
  74. package/templates/express/tests/architecture/isolation.test.ts +51 -0
  75. package/templates/express/tests/architecture/layers.test.ts +83 -0
  76. package/templates/express/tests/integration/health.test.ts +40 -0
  77. package/templates/express/tests/integration/isolation.test.template.ts +88 -0
  78. package/templates/express/tests/load/smoke.js +46 -0
  79. package/templates/express/tests/load/soak.js +45 -0
  80. package/templates/express/tests/load/stress.js +44 -0
  81. package/templates/express/tests/unit/utils/response.util.test.ts +53 -0
  82. package/templates/express/tsconfig.build.json +8 -0
  83. package/templates/express/tsconfig.json +20 -0
  84. package/templates/fastapi/.claude/CLAUDE.md +122 -0
  85. package/templates/fastapi/.claude/agents/arch-validator.md +64 -0
  86. package/templates/fastapi/.claude/agents/db-optimizer.md +59 -0
  87. package/templates/fastapi/.claude/agents/doc-gardener.md +55 -0
  88. package/templates/fastapi/.claude/agents/garbage-collector.md +74 -0
  89. package/templates/fastapi/.claude/agents/gate-checker.md +133 -0
  90. package/templates/fastapi/.claude/agents/reviewer.md +74 -0
  91. package/templates/fastapi/.claude/agents/security-auditor.md +69 -0
  92. package/templates/fastapi/.claude/hooks/post-write.sh +65 -0
  93. package/templates/fastapi/.claude/rules/api.md +119 -0
  94. package/templates/fastapi/.claude/rules/architecture.md +84 -0
  95. package/templates/fastapi/.claude/rules/database.md +153 -0
  96. package/templates/fastapi/.claude/rules/jobs.md +85 -0
  97. package/templates/fastapi/.claude/rules/security.md +102 -0
  98. package/templates/fastapi/.claude/rules/testing.md +207 -0
  99. package/templates/fastapi/.claude/settings.json +50 -0
  100. package/templates/fastapi/.claude/skills/00-infra-setup/SKILL.md +311 -0
  101. package/templates/fastapi/.claude/skills/01-write-roadmap/SKILL.md +61 -0
  102. package/templates/fastapi/.claude/skills/02-write-spec/SKILL.md +82 -0
  103. package/templates/fastapi/.claude/skills/03-write-plan/SKILL.md +83 -0
  104. package/templates/fastapi/.claude/skills/04-build-layer/SKILL.md +170 -0
  105. package/templates/fastapi/.claude/skills/05-validate-layer/SKILL.md +20 -0
  106. package/templates/fastapi/.claude/skills/06-push-layer/SKILL.md +31 -0
  107. package/templates/fastapi/.claude/skills/07-layer-check/SKILL.md +51 -0
  108. package/templates/fastapi/.claude/skills/08-garbage-collect/SKILL.md +47 -0
  109. package/templates/fastapi/.claude/skills/09-doc-garden/SKILL.md +9 -0
  110. package/templates/fastapi/.claude/skills/10-db-optimize/SKILL.md +53 -0
  111. package/templates/fastapi/.claude/skills/11-load-test/SKILL.md +81 -0
  112. package/templates/fastapi/.dockerignore +30 -0
  113. package/templates/fastapi/.github/dependabot.yml +24 -0
  114. package/templates/fastapi/AGENTS.md +87 -0
  115. package/templates/fastapi/ARCHITECTURE.md +141 -0
  116. package/templates/fastapi/Makefile +42 -0
  117. package/templates/fastapi/README.md +179 -0
  118. package/templates/fastapi/docs/PLANS.md +26 -0
  119. package/templates/fastapi/docs/QUALITY_SCORE.md +26 -0
  120. package/templates/fastapi/docs/design-docs/core-beliefs.md +46 -0
  121. package/templates/fastapi/docs/design-docs/decisions/ADR-000-infrastructure.md +79 -0
  122. package/templates/fastapi/docs/design-docs/decisions/index.md +7 -0
  123. package/templates/fastapi/docs/design-docs/index.md +9 -0
  124. package/templates/fastapi/docs/exec-plans/active/.gitkeep +0 -0
  125. package/templates/fastapi/docs/exec-plans/completed/.gitkeep +0 -0
  126. package/templates/fastapi/docs/exec-plans/tech-debt-tracker.md +19 -0
  127. package/templates/fastapi/docs/generated/.gitkeep +0 -0
  128. package/templates/fastapi/docs/product-specs/ROADMAP.md +49 -0
  129. package/templates/fastapi/docs/product-specs/draft/.gitkeep +0 -0
  130. package/templates/fastapi/docs/product-specs/index.md +18 -0
  131. package/templates/fastapi/docs/product-specs/ready/.gitkeep +0 -0
  132. package/templates/fastapi/gitignore +46 -0
  133. package/templates/fastapi/scripts/gate.sh +68 -0
  134. package/templates/nestjs/.claude/CLAUDE.md +121 -0
  135. package/templates/nestjs/.claude/agents/db-optimizer.md +51 -0
  136. package/templates/nestjs/.claude/agents/doc-gardener.md +45 -0
  137. package/templates/nestjs/.claude/agents/garbage-collector.md +50 -0
  138. package/templates/nestjs/.claude/agents/gate-checker.md +127 -0
  139. package/templates/nestjs/.claude/agents/reviewer.md +68 -0
  140. package/templates/nestjs/.claude/agents/security-auditor.md +72 -0
  141. package/templates/nestjs/.claude/hooks/post-write.sh +91 -0
  142. package/templates/nestjs/.claude/rules/api.md +87 -0
  143. package/templates/nestjs/.claude/rules/architecture.md +104 -0
  144. package/templates/nestjs/.claude/rules/database.md +111 -0
  145. package/templates/nestjs/.claude/rules/security.md +110 -0
  146. package/templates/nestjs/.claude/rules/testing.md +145 -0
  147. package/templates/nestjs/.claude/settings.json +33 -0
  148. package/templates/nestjs/.claude/skills/00-infra-setup/SKILL.md +222 -0
  149. package/templates/nestjs/.claude/skills/01-write-spec/SKILL.md +25 -0
  150. package/templates/nestjs/.claude/skills/02-write-plan/SKILL.md +18 -0
  151. package/templates/nestjs/.claude/skills/03-build-layer/SKILL.md +242 -0
  152. package/templates/nestjs/.claude/skills/04-validate-layer/SKILL.md +4 -0
  153. package/templates/nestjs/.claude/skills/05-push-layer/SKILL.md +6 -0
  154. package/templates/nestjs/.claude/skills/06-layer-check/SKILL.md +12 -0
  155. package/templates/nestjs/.claude/skills/07-garbage-collect/SKILL.md +2 -0
  156. package/templates/nestjs/.claude/skills/08-doc-garden/SKILL.md +4 -0
  157. package/templates/nestjs/.claude/skills/09-api-sync/SKILL.md +36 -0
  158. package/templates/nestjs/.claude/skills/10-load-test/SKILL.md +29 -0
  159. package/templates/nestjs/.env.example +11 -0
  160. package/templates/nestjs/AGENTS.md +88 -0
  161. package/templates/nestjs/ARCHITECTURE.md +192 -0
  162. package/templates/nestjs/docs/PLANS.md +22 -0
  163. package/templates/nestjs/docs/QUALITY_SCORE.md +27 -0
  164. package/templates/nestjs/docs/design-docs/core-beliefs.md +18 -0
  165. package/templates/nestjs/docs/design-docs/decisions/ADR-000-infrastructure.md +58 -0
  166. package/templates/nestjs/docs/design-docs/decisions/index.md +7 -0
  167. package/templates/nestjs/docs/design-docs/index.md +7 -0
  168. package/templates/nestjs/docs/exec-plans/active/.gitkeep +0 -0
  169. package/templates/nestjs/docs/exec-plans/completed/.gitkeep +0 -0
  170. package/templates/nestjs/docs/exec-plans/tech-debt-tracker.md +16 -0
  171. package/templates/nestjs/docs/generated/.gitkeep +0 -0
  172. package/templates/nestjs/docs/product-specs/draft/.gitkeep +0 -0
  173. package/templates/nestjs/docs/product-specs/index.md +7 -0
  174. package/templates/nestjs/docs/product-specs/ready/.gitkeep +0 -0
  175. package/templates/nestjs/gitignore +8 -0
  176. package/templates/nextjs/.claude/CLAUDE.md +139 -0
  177. package/templates/nextjs/.claude/agents/arch-validator.md +66 -0
  178. package/templates/nextjs/.claude/agents/contract-checker.md +78 -0
  179. package/templates/nextjs/.claude/agents/doc-gardener.md +52 -0
  180. package/templates/nextjs/.claude/agents/garbage-collector.md +61 -0
  181. package/templates/nextjs/.claude/agents/gate-checker.md +129 -0
  182. package/templates/nextjs/.claude/agents/perf-auditor.md +109 -0
  183. package/templates/nextjs/.claude/agents/reviewer.md +79 -0
  184. package/templates/nextjs/.claude/agents/security-auditor.md +50 -0
  185. package/templates/nextjs/.claude/hooks/post-write.sh +121 -0
  186. package/templates/nextjs/.claude/rules/api-contract.md +166 -0
  187. package/templates/nextjs/.claude/rules/architecture.md +99 -0
  188. package/templates/nextjs/.claude/rules/components.md +122 -0
  189. package/templates/nextjs/.claude/rules/security.md +122 -0
  190. package/templates/nextjs/.claude/rules/testing.md +187 -0
  191. package/templates/nextjs/.claude/scripts/infra-setup.sh +550 -0
  192. package/templates/nextjs/.claude/settings.json +33 -0
  193. package/templates/nextjs/.claude/skills/00-infra-setup/SKILL.md +471 -0
  194. package/templates/nextjs/.claude/skills/01-write-roadmap/SKILL.md +77 -0
  195. package/templates/nextjs/.claude/skills/02-write-spec/SKILL.md +78 -0
  196. package/templates/nextjs/.claude/skills/03-write-plan/SKILL.md +91 -0
  197. package/templates/nextjs/.claude/skills/04-build-layer/SKILL.md +141 -0
  198. package/templates/nextjs/.claude/skills/05-validate-layer/SKILL.md +13 -0
  199. package/templates/nextjs/.claude/skills/06-push-layer/SKILL.md +20 -0
  200. package/templates/nextjs/.claude/skills/07-layer-check/SKILL.md +28 -0
  201. package/templates/nextjs/.claude/skills/08-garbage-collect/SKILL.md +14 -0
  202. package/templates/nextjs/.claude/skills/09-doc-garden/SKILL.md +12 -0
  203. package/templates/nextjs/.claude/skills/10-api-sync/SKILL.md +50 -0
  204. package/templates/nextjs/.claude/skills/11-perf-budget/SKILL.md +51 -0
  205. package/templates/nextjs/.dockerignore +25 -0
  206. package/templates/nextjs/.gitattributes +10 -0
  207. package/templates/nextjs/.github/CODEOWNERS +24 -0
  208. package/templates/nextjs/.github/dependabot.yml +31 -0
  209. package/templates/nextjs/.github/pull_request_template.md +59 -0
  210. package/templates/nextjs/.github/workflows/ci.yml +143 -0
  211. package/templates/nextjs/.github/workflows/lighthouse.yml +54 -0
  212. package/templates/nextjs/.github/workflows/load-test.yml +54 -0
  213. package/templates/nextjs/.husky/pre-commit +1 -0
  214. package/templates/nextjs/.lintstagedrc.json +4 -0
  215. package/templates/nextjs/.mcp.json +8 -0
  216. package/templates/nextjs/.prettierignore +13 -0
  217. package/templates/nextjs/.prettierrc +9 -0
  218. package/templates/nextjs/AGENTS.md +88 -0
  219. package/templates/nextjs/ARCHITECTURE.md +165 -0
  220. package/templates/nextjs/Dockerfile +38 -0
  221. package/templates/nextjs/Makefile +50 -0
  222. package/templates/nextjs/QUICKSTART.md +128 -0
  223. package/templates/nextjs/docs/PLANS.md +23 -0
  224. package/templates/nextjs/docs/QUALITY_SCORE.md +27 -0
  225. package/templates/nextjs/docs/design-docs/core-beliefs.md +43 -0
  226. package/templates/nextjs/docs/design-docs/decisions/ADR-000-infrastructure.md +72 -0
  227. package/templates/nextjs/docs/design-docs/decisions/index.md +7 -0
  228. package/templates/nextjs/docs/design-docs/index.md +7 -0
  229. package/templates/nextjs/docs/design-docs/team-workflow.md +66 -0
  230. package/templates/nextjs/docs/exec-plans/active/.gitkeep +0 -0
  231. package/templates/nextjs/docs/exec-plans/completed/.gitkeep +0 -0
  232. package/templates/nextjs/docs/exec-plans/tech-debt-tracker.md +19 -0
  233. package/templates/nextjs/docs/generated/.gitkeep +0 -0
  234. package/templates/nextjs/docs/product-specs/ROADMAP.md +59 -0
  235. package/templates/nextjs/docs/product-specs/draft/.gitkeep +0 -0
  236. package/templates/nextjs/docs/product-specs/index.md +18 -0
  237. package/templates/nextjs/docs/product-specs/ready/.gitkeep +0 -0
  238. package/templates/nextjs/eslint.config.mjs +150 -0
  239. package/templates/nextjs/gitignore +35 -0
  240. package/templates/nextjs/lighthouserc.js +37 -0
@@ -0,0 +1,94 @@
1
+ ---
2
+ name: garbage-collector
3
+ description: End-of-feature cleanup. Called by /garbage-collect. Scans for violations, updates quality scores, closes the plan.
4
+ model: claude-opus-4-8
5
+ tools: [Read, Write, Bash]
6
+ color: green
7
+ ---
8
+
9
+ You are the cleanup agent. Run after every feature is complete.
10
+
11
+ ## Steps (run in order)
12
+
13
+ ### 1. File Size Scan
14
+
15
+ ```bash
16
+ find src/ -name "*.ts" | xargs wc -l | awk '$1 > 400 { print $2, $1, "lines — SPLIT REQUIRED" }' | sort -rn
17
+ ```
18
+
19
+ For each file over 400 lines: identify a logical split point, create sub-modules, update imports.
20
+
21
+ ### 2. Layer Violation Scan
22
+
23
+ ```bash
24
+ npx madge --circular src/ --extensions ts
25
+ # Layer-boundary enforcement lives in eslint.config.mjs (boundaries/dependencies) — a plain
26
+ # lint run covers it. Or just run `npm run gate` (typecheck + lint + circular + arch tests).
27
+ npx eslint src/ --max-warnings=0
28
+ ```
29
+
30
+ Fix any violations found.
31
+
32
+ ### 3. Stale Docs Scan
33
+
34
+ - Read `AGENTS.md` — does it match current skills and agents?
35
+ - Read `ARCHITECTURE.md` — does it match current layers?
36
+ - Read `docs/design-docs/decisions/` — are ADRs current?
37
+ - Update any stale content.
38
+
39
+ ### 4. Update QUALITY_SCORE.md
40
+
41
+ Run coverage: `npm test -- --coverage`
42
+ For each domain touched in this feature, update the grade table.
43
+
44
+ Grade rubric (coverage is judged per layer against `jest.config.ts`, not a single global number):
45
+
46
+ - A: all invariants met, every per-layer coverage threshold met, zero known debt
47
+ - B: minor issues, per-layer thresholds met with little margin, low-priority debt logged
48
+ - C: layer violation OR any per-layer threshold breached OR unresolved medium debt
49
+ - D: multiple violations, coverage well under thresholds, active bugs
50
+
51
+ ### 5. Log New Tech Debt
52
+
53
+ Any shortcut taken during this feature → add to `docs/exec-plans/tech-debt-tracker.md`
54
+ Format: `| DEBT-XXX | P3 | [area] | [description] | PLAN-XXX | [date] |`
55
+
56
+ ### 6. Close the Plan
57
+
58
+ - Open `docs/exec-plans/active/PLAN-XXX.md`
59
+ - Set `Status: COMPLETE`, set `Completed:` date
60
+ - Verify all layer checkboxes are ticked
61
+ - Move file: `docs/exec-plans/active/` → `docs/exec-plans/completed/`
62
+
63
+ ### 7. Mark Spec Shipped
64
+
65
+ - Open `docs/product-specs/ready/SPEC-XXX.md`
66
+ - Update `Status: SHIPPED`
67
+ - Update `docs/product-specs/index.md` table
68
+
69
+ ### 8. Final Commit
70
+
71
+ ```bash
72
+ git add -A
73
+ git commit -m "chore: garbage collect — close PLAN-XXX
74
+
75
+ - QUALITY_SCORE.md updated
76
+ - [N] debt items logged
77
+ - PLAN-XXX moved to completed
78
+ - SPEC-XXX marked SHIPPED"
79
+ git push origin main
80
+ ```
81
+
82
+ ### 9. Report
83
+
84
+ ```
85
+ GARBAGE COLLECT COMPLETE
86
+
87
+ Files split: N
88
+ Violations fixed: N
89
+ Stale docs updated: N
90
+ Quality scores: [domain: grade, ...]
91
+ Debt logged: N items
92
+ Plan closed: PLAN-XXX
93
+ Spec shipped: SPEC-XXX
94
+ ```
@@ -0,0 +1,176 @@
1
+ ---
2
+ name: gate-checker
3
+ description: Runs the layer gate check. Called automatically by /build-layer after every layer build. Outputs PASS or FAIL with specific actionable items. Never called directly by the human.
4
+ model: claude-opus-4-8
5
+ tools: [Bash, Read]
6
+ color: red
7
+ ---
8
+
9
+ You are the gate enforcement agent. Your only job is to check the current layer against all harness standards and output a precise PASS or FAIL verdict.
10
+
11
+ You are called after a layer is built. You do NOT build code — you check it.
12
+
13
+ ---
14
+
15
+ ## How to Run
16
+
17
+ 1. Read `ARCHITECTURE.md` to know the layer rules
18
+ 2. Identify which layer was just built from the active plan
19
+ 3. Run every check below that applies to that layer
20
+ 4. Output the full gate report
21
+
22
+ ---
23
+
24
+ ## Universal Checks (every layer)
25
+
26
+ ```bash
27
+ # 1. File size — no file > 400 lines
28
+ find src/ -name "*.ts" -exec wc -l {} + | sort -rn | awk '$1 > 400 { print "FAIL:", $2, "has", $1, "lines" }'
29
+
30
+ # 2. console.log in src/ (config/ is exempt — it hosts logger.ts)
31
+ find src/ -name "*.ts" \
32
+ -not -path "src/config/*" \
33
+ -exec grep -Hn "console\.\(log\|error\|warn\|info\)" {} +
34
+
35
+ # 3. process.env outside config/env.ts
36
+ find src/ -name "*.ts" -not -path "src/config/env.ts" \
37
+ -exec grep -Hn "process\.env" {} +
38
+
39
+ # 4. TypeScript compilation
40
+ npx tsc --noEmit 2>&1
41
+
42
+ # 5. ESLint
43
+ npx eslint src/ --max-warnings=0 2>&1
44
+
45
+ # 6. Circular imports (madge)
46
+ npx madge --circular src/ --extensions ts 2>&1
47
+
48
+ # 7. Architecture structural tests
49
+ npx jest tests/architecture/ --no-coverage 2>&1
50
+ ```
51
+
52
+ ## Layer-Specific Checks
53
+
54
+ ### Types layer
55
+
56
+ ```bash
57
+ # Zero imports from other layers (types may only self-reference)
58
+ find src/types/ -name "*.ts" -exec grep -Hn "from '\.\." {} + | grep -v "from '.*types"
59
+ # Zero logic (no function implementations)
60
+ find src/types/ -name "*.ts" -exec grep -Hn "^export function\|^export const.*=.*=>" {} +
61
+ ```
62
+
63
+ ### Config layer
64
+
65
+ ```bash
66
+ # Only imports from types/zod/path
67
+ find src/config/ -name "*.ts" -exec grep -Hn "from '\.\." {} + | grep -Ev "types|zod|path"
68
+ # Zod validation present in env.ts
69
+ grep -n "safeParse\|process.exit" src/config/env.ts
70
+ ```
71
+
72
+ ### Models layer
73
+
74
+ ```bash
75
+ # paranoid: true on all model @Table decorators — list models missing it
76
+ find src/models/ -name "*.ts" | while read -r f; do
77
+ if grep -q "@Table" "$f" && ! grep -q "paranoid: true" "$f"; then
78
+ echo "FAIL: $f has @Table without paranoid: true"
79
+ fi
80
+ done
81
+ # UUIDv7 default on all id columns — @Default present but not newId
82
+ find src/models/ -name "*.ts" -exec grep -Hn "@Default" {} + | grep -v "newId"
83
+ ```
84
+
85
+ ### Repo layer
86
+
87
+ ```bash
88
+ # Zod parse on all returns — no bare raw or as-cast
89
+ find src/repo/ -name "*.ts" -exec grep -Hn "return raw as\|\.toJSON() as\|return await.*\.findAll\|return await.*\.findByPk\|return await.*\.findOne\|return await.*\.create" {} +
90
+ # Ownership: findByIdAndUser pattern (no findByPk without userId)
91
+ find src/repo/ -name "*.ts" -exec grep -Hn "findByPk\|findOne" {} + | grep -v "userId\|user_id"
92
+
93
+ # Cursor pagination check — look for offset/skip (should be empty)
94
+ find src/repo/ -name "*.ts" -exec grep -Hn "offset:\|\.skip(" {} +
95
+
96
+ # N+1 check — manual review: look for Model.find* inside for/forEach loops
97
+ find src/repo/ -name "*.ts" -exec grep -Hn "for \|forEach\|\.map(async" {} + \
98
+ && echo "Manually verify: no await Model.find* calls inside the above loops"
99
+ ```
100
+
101
+ ### Service layer
102
+
103
+ ```bash
104
+ # No express imports (services are HTTP-agnostic)
105
+ find src/services/ -name "*.ts" -exec grep -Hn "from 'express'\|require('express')" {} +
106
+
107
+ # Coverage check
108
+ npx jest tests/unit/services/ --coverage --coverageThreshold='{"global":{"lines":90}}' 2>&1 | tail -5
109
+ ```
110
+
111
+ ### Runtime layer
112
+
113
+ ```bash
114
+ # Auth first — requireAuth before body parsing in all POST/PATCH/DELETE
115
+ find src/runtime/routes/ -name "*.ts" -exec grep -Hn "requireAuth" {} + | wc -l # should match protected route count
116
+
117
+ # Response envelope — ok() helper used (raw res.json should be empty)
118
+ find src/runtime/routes/ -name "*.ts" -exec grep -Hn "res\.json({" {} +
119
+
120
+ # Rate limit applied
121
+ find src/runtime/routes/ -name "*.ts" -exec grep -Hn "RateLimit\|rateLimiter" {} +
122
+
123
+ # Coverage
124
+ npx jest tests/integration/ --coverage 2>&1 | tail -5
125
+ ```
126
+
127
+ ### Utils layer
128
+
129
+ ```bash
130
+ # Zero domain imports except type-only Types (node:, path, crypto, ../types allowed)
131
+ find src/utils/ -name "*.ts" -exec grep -Hn "from '\.\." {} + | grep -Ev "node:|path|crypto|/types"
132
+
133
+ # 100% coverage required
134
+ npx jest tests/unit/utils/ --coverage --coverageThreshold='{"global":{"lines":100,"branches":100}}' 2>&1 | tail -5
135
+ ```
136
+
137
+ ---
138
+
139
+ ## Output Format
140
+
141
+ ```
142
+ ─────────────────────────────────────────
143
+ GATE CHECK — Layer: [name] [Attempt N]
144
+ ─────────────────────────────────────────
145
+ Universal
146
+ ✓/✗ No file > 400 lines
147
+ ✓/✗ No console.log in src/
148
+ ✓/✗ No process.env outside config
149
+ ✓/✗ TypeScript compiles clean
150
+ ✓/✗ ESLint: 0 errors
151
+ ✓/✗ No circular imports
152
+ ✓/✗ Architecture tests pass
153
+
154
+ Layer-Specific ([layer name])
155
+ ✓/✗ [check description]
156
+ ✓/✗ [check description]
157
+
158
+ Tests
159
+ ✓/✗ Coverage: XX% (threshold: YY%)
160
+ ✓/✗ All tests pass
161
+
162
+ Decision Doc
163
+ ✓/✗ ADR written for [decision] / No non-obvious decisions
164
+ ─────────────────────────────────────────
165
+ STATUS: ✅ PASS / ❌ FAIL — N items
166
+
167
+ [If FAIL, list each item:]
168
+ ITEM 1: [file:line] [problem] → [exact fix]
169
+ ITEM 2: ...
170
+ ─────────────────────────────────────────
171
+ ```
172
+
173
+ ## After FAIL Output
174
+
175
+ Do NOT ask the human what to do.
176
+ Return the FAIL report to the `/build-layer` skill, which will auto-fix each item and re-call you.
@@ -0,0 +1,84 @@
1
+ ---
2
+ name: reviewer
3
+ description: Full harness review before opening a PR. Checks all layers against harness standards. Use with "Use the reviewer agent to review current changes."
4
+ model: claude-opus-4-8
5
+ tools: [Read, Bash]
6
+ color: blue
7
+ ---
8
+
9
+ You are a senior engineer reviewing a PR against the harness engineering standards.
10
+ Run `git diff main --name-only` then `git diff main` to see all changes.
11
+
12
+ ## Review Checklist
13
+
14
+ ### Architecture
15
+
16
+ - [ ] No cross-layer imports (ESLint + madge)
17
+ - [ ] No file > 400 lines
18
+ - [ ] No circular imports
19
+ - [ ] TypeScript compiles clean
20
+
21
+ ### Code Quality
22
+
23
+ - [ ] No `console.log` (use logger)
24
+ - [ ] No `process.env` outside `src/config/env.ts`
25
+ - [ ] No `as SomeType` on external/DB data
26
+
27
+ ### Security
28
+
29
+ - [ ] Auth check first on every protected route
30
+ - [ ] Zod validation before any business logic
31
+ - [ ] Ownership enforced in repo layer
32
+ - [ ] Error responses sanitised (no stack traces)
33
+ - [ ] SQL: Sequelize ORM only (no interpolated raw queries)
34
+
35
+ ### Database (if repo/model changed)
36
+
37
+ - [ ] All query results: `Schema.parse(raw.toJSON())`
38
+ - [ ] All list methods: cursor-based pagination (no offset)
39
+ - [ ] No N+1 (no Model calls inside loops)
40
+ - [ ] Multi-table writes: `sequelize.transaction()`
41
+ - [ ] New models: `paranoid: true`, `newId()` for UUIDs
42
+ - [ ] New queries: indexes defined and migrated
43
+
44
+ ### API (if routes changed)
45
+
46
+ - [ ] Routes under `/api/v1/` prefix
47
+ - [ ] Rate limiting applied
48
+ - [ ] Response envelope: `ok()` / `err()` helpers
49
+ - [ ] `X-Request-ID` attached to response
50
+
51
+ ### Jobs (if workers changed)
52
+
53
+ - [ ] Payload validated with Zod
54
+ - [ ] Retry config on queue definition
55
+ - [ ] start/complete/failed logs emitted
56
+ - [ ] Circuit breaker on external calls
57
+
58
+ ### Tests
59
+
60
+ - [ ] Utils: 100% coverage
61
+ - [ ] Services: ≥ 90%
62
+ - [ ] Error paths tested (not just happy path)
63
+ - [ ] Invalid Zod inputs tested
64
+
65
+ ### Docs
66
+
67
+ - [ ] ADR written for non-obvious decisions
68
+ - [ ] QUALITY_SCORE.md updated for affected domains
69
+
70
+ ## Verdict
71
+
72
+ ```
73
+ APPROVED — ready to merge.
74
+
75
+ OR
76
+
77
+ CHANGES REQUIRED:
78
+
79
+ BLOCKING:
80
+ 1. [description + file:line + fix]
81
+
82
+ NON-BLOCKING (fix before next feature):
83
+ 2. [description]
84
+ ```
@@ -0,0 +1,82 @@
1
+ ---
2
+ name: security-auditor
3
+ description: OWASP Top 10 security review. Run before any PR touching auth, payments, file uploads, or external data. Use with "Use the security-auditor agent to review current changes."
4
+ model: claude-opus-4-8
5
+ tools: [Read, Bash]
6
+ color: red
7
+ ---
8
+
9
+ You are a senior application security engineer. Review all recent changes against OWASP Top 10.
10
+ Be specific. A missed vulnerability is a production incident.
11
+
12
+ ## Pre-Review Steps
13
+
14
+ 1. `git diff main --name-only` → list changed files
15
+ 2. Read each changed file carefully
16
+ 3. Run the checklist
17
+
18
+ ## OWASP Checklist
19
+
20
+ ### A01 — Broken Access Control
21
+
22
+ - [ ] Every protected route: `requireAuth()` is the FIRST call
23
+ - [ ] Ownership check: `findByIdAndUser(id, auth.userId)` not `findById(id)`
24
+ - [ ] RBAC: `requirePermission()` on role-restricted actions
25
+ - [ ] No horizontal escalation: user A cannot access user B's data
26
+
27
+ ### A02 — Cryptographic Failures
28
+
29
+ - [ ] Passwords: argon2 hash (not bcrypt, not MD5/SHA1)
30
+ - [ ] JWT secret: min 32 chars, from env (not hardcoded)
31
+ - [ ] Sensitive fields: `[REDACTED]` in logs
32
+ - [ ] HSTS header: present in helmet config
33
+
34
+ ### A03 — Injection
35
+
36
+ - [ ] All SQL via Sequelize ORM — no string-interpolated raw queries
37
+ - [ ] All inputs validated with Zod before use
38
+ - [ ] `sequelize.query()` uses named replacements only
39
+
40
+ ### A04 — Insecure Design
41
+
42
+ - [ ] Auth endpoints rate limited (10/min)
43
+ - [ ] Idempotency keys on mutation endpoints
44
+ - [ ] UUIDs (not sequential ints) on user-facing IDs
45
+
46
+ ### A05 — Security Misconfiguration
47
+
48
+ - [ ] Helmet applied globally (7 headers on every response)
49
+ - [ ] CORS configured once centrally (no `*` on authenticated endpoints)
50
+ - [ ] No stack traces in error responses
51
+ - [ ] No debug mode in production
52
+
53
+ ### A07 — Auth Failures
54
+
55
+ - [ ] Access token: max 15 min lifetime
56
+ - [ ] Refresh token: httpOnly cookie, 7 days, single-use (rotate on use)
57
+ - [ ] Token revocation: Redis revocation list checked on every verify
58
+ - [ ] Login error: same message for bad user vs bad password (no enumeration)
59
+
60
+ ### A09 — Logging Failures
61
+
62
+ - [ ] Auth events logged: login, logout, failed auth, token refresh
63
+ - [ ] 401/403 logged with requestId and userId
64
+ - [ ] No PII in log values
65
+
66
+ ## Verdict Format
67
+
68
+ ```
69
+ APPROVED — all checks pass.
70
+
71
+ OR
72
+
73
+ CHANGES REQUIRED:
74
+
75
+ CRITICAL (block merge):
76
+ 1. [file:line] [problem]
77
+ Fix: [exact code change]
78
+
79
+ HIGH (fix before production):
80
+ 2. [file:line] [problem]
81
+ Fix: [exact code change]
82
+ ```
@@ -0,0 +1,93 @@
1
+ #!/usr/bin/env bash
2
+ # .claude/hooks/post-write.sh
3
+ # Fires after every Write/Edit/MultiEdit tool call.
4
+ # Claude Code passes the tool invocation as JSON on stdin; the edited file
5
+ # path lives at .tool_input.file_path.
6
+ # Checks: console.log, process.env outside config, file size, unsafe casts.
7
+ # Prints warnings directly — gate-checker does the hard blocking.
8
+
9
+ set -euo pipefail
10
+
11
+ # Read all of stdin once (the JSON tool payload).
12
+ PAYLOAD=$(cat)
13
+
14
+ # Resolve the file path. Prefer the env var Claude Code may expose, else parse
15
+ # the JSON payload with node (always present in this project). We check the
16
+ # documented nested path first (.tool_input.file_path), then top-level fallbacks.
17
+ FILE="${CLAUDE_FILE_PATH:-}"
18
+
19
+ if [[ -z "$FILE" ]]; then
20
+ FILE=$(printf '%s' "$PAYLOAD" | node -e "
21
+ let raw = '';
22
+ process.stdin.on('data', (c) => (raw += c));
23
+ process.stdin.on('end', () => {
24
+ try {
25
+ const d = JSON.parse(raw);
26
+ const p =
27
+ (d.tool_input && (d.tool_input.file_path || d.tool_input.path)) ||
28
+ d.file_path ||
29
+ d.path ||
30
+ '';
31
+ process.stdout.write(String(p));
32
+ } catch {
33
+ process.stdout.write('');
34
+ }
35
+ });
36
+ " 2>/dev/null || echo "")
37
+ fi
38
+
39
+ # Nothing to check
40
+ [[ -z "$FILE" ]] && exit 0
41
+ [[ ! -f "$FILE" ]] && exit 0
42
+
43
+ # Only check TypeScript source files
44
+ if [[ ! "$FILE" =~ \.ts$ ]]; then
45
+ exit 0
46
+ fi
47
+
48
+ # Normalise to a path relative to the repo root so matching works whether the
49
+ # payload gives an absolute or relative path (strip everything before src/).
50
+ REL="$FILE"
51
+ if [[ "$REL" == *"/src/"* ]]; then
52
+ REL="src/${REL##*/src/}"
53
+ fi
54
+
55
+ WARNINGS=()
56
+
57
+ # 1. console.log check in src/ (config/ is exempt — it hosts logger.ts)
58
+ if [[ "$REL" =~ ^src/ ]] && [[ ! "$REL" =~ src/config/ ]]; then
59
+ if grep -qn "console\.\(log\|error\|warn\|info\)" "$FILE" 2>/dev/null; then
60
+ LINE=$(grep -n "console\.\(log\|error\|warn\|info\)" "$FILE" | head -1 | cut -d: -f1)
61
+ WARNINGS+=("⚠ [HOOK] console.log found at $REL:$LINE — use logger from src/config/logger.ts")
62
+ fi
63
+ fi
64
+
65
+ # 2. process.env check — only allowed in src/config/env.ts
66
+ if [[ "$REL" =~ ^src/ ]] && [[ ! "$REL" =~ src/config/env\.ts ]]; then
67
+ if grep -qn "process\.env" "$FILE" 2>/dev/null; then
68
+ LINE=$(grep -n "process\.env" "$FILE" | head -1 | cut -d: -f1)
69
+ WARNINGS+=("⚠ [HOOK] process.env found at $REL:$LINE — import from src/config/env.ts instead")
70
+ fi
71
+ fi
72
+
73
+ # 3. File size check
74
+ LINE_COUNT=$(wc -l < "$FILE" 2>/dev/null || echo 0)
75
+ if [[ $LINE_COUNT -gt 400 ]]; then
76
+ WARNINGS+=("⚠ [HOOK] $REL has $LINE_COUNT lines — exceeds 400 line limit. Split into focused modules.")
77
+ fi
78
+
79
+ # 4. `as SomeType` on external data check in repo files
80
+ if [[ "$REL" =~ \.repo\.ts$ ]]; then
81
+ if grep -qn "return raw as " "$FILE" 2>/dev/null; then
82
+ LINE=$(grep -n "return raw as " "$FILE" | head -1 | cut -d: -f1)
83
+ WARNINGS+=("⚠ [HOOK] Unsafe cast at $REL:$LINE — use Schema.parse(raw.toJSON()) instead")
84
+ fi
85
+ fi
86
+
87
+ # Print all warnings
88
+ for w in "${WARNINGS[@]}"; do
89
+ echo "$w"
90
+ done
91
+
92
+ # Exit 0 always — hooks warn, gate-checker blocks
93
+ exit 0
@@ -0,0 +1,149 @@
1
+ ---
2
+ paths:
3
+ - "src/runtime/routes/**/*.ts"
4
+ ---
5
+
6
+ # API Rules — Auto-injected on route file edits
7
+
8
+ ## Route File Checklist (verify before every route)
9
+
10
+ ### Versioning
11
+ ```typescript
12
+ // ✅ All routes under version prefix
13
+ // File: src/runtime/routes/v1/applications.route.ts
14
+ router.get('/applications', ...) // mounted at /api/v1/applications
15
+
16
+ // ❌ Never create unversioned routes
17
+ app.get('/applications', ...) // no version = breaking changes are impossible to manage
18
+ ```
19
+
20
+ ### Required Handler Structure (every protected route)
21
+ ```typescript
22
+ router.post('/', async (req: Request, res: Response, next: NextFunction) => {
23
+ try {
24
+ const auth = await requireAuth(req) // 1. Auth
25
+ const body = CreateApplicationSchema.parse(req.body) // 2. Validate
26
+ const result = await applicationService.create(auth.userId, body) // 3. Service
27
+ return res.status(201).json(ok(result, req.requestId)) // 4. Respond
28
+ } catch (err) { next(err) } // 5. Error handler
29
+ })
30
+ ```
31
+
32
+ ### Rate Limits (pick correct tier per route)
33
+ ```typescript
34
+ // Auth endpoints — strict (10/min — brute force protection)
35
+ router.post('/login', authRateLimit, handler)
36
+ router.post('/register', authRateLimit, handler)
37
+
38
+ // Public read endpoints — moderate (60/min)
39
+ router.get('/public-data', publicRateLimit, handler)
40
+
41
+ // Authenticated user endpoints — generous (300/min)
42
+ router.use(userRateLimit) // apply at router level for all user routes
43
+ ```
44
+
45
+ ### Response Envelope — Canonical Shape (always)
46
+
47
+ Every response carries a top-level `ok` discriminator so the frontend can branch
48
+ on one field. This shape is identical across all backends in the harness family.
49
+
50
+ ```jsonc
51
+ // ✅ Success
52
+ {
53
+ "ok": true,
54
+ "data": { /* ... */ },
55
+ "meta": { "requestId": "01932b3e-4f5a-7b8c-9d0e-1f2a3b4c5d6e", "timestamp": "..." }
56
+ }
57
+
58
+ // ✅ Error
59
+ {
60
+ "ok": false,
61
+ "error": {
62
+ "code": "VALIDATION_ERROR", // | NOT_FOUND | UNAUTHORIZED | FORBIDDEN | CONFLICT | RATE_LIMITED | INTERNAL_ERROR
63
+ "message": "Human-readable error message"
64
+ },
65
+ "meta": { "requestId": "01932b3e-4f5a-7b8c-9d0e-1f2a3b4c5d6e" }
66
+ }
67
+ ```
68
+
69
+ ```typescript
70
+ // ✅ Success: use ok() helper — sets ok: true + data + meta
71
+ res.status(200).json(ok(data, req.requestId))
72
+
73
+ // ✅ Error: use next(err) — errorHandler maps it to the canonical error shape
74
+ next(new NotFoundError('Application not found'))
75
+
76
+ // ❌ Never raw JSON
77
+ res.json({ data: result }) // missing ok + meta
78
+ res.json({ error: err.message }) // wrong format
79
+ ```
80
+
81
+ **Error code enum** (the only allowed `error.code` values):
82
+ `VALIDATION_ERROR`, `NOT_FOUND`, `UNAUTHORIZED`, `FORBIDDEN`, `CONFLICT`, `RATE_LIMITED`, `INTERNAL_ERROR`.
83
+
84
+ **`meta` shape** (pinned by `tests/unit/utils/response.util.test.ts`): success carries
85
+ `{ requestId, timestamp }`; errors carry `{ requestId }` only. The timestamp asymmetry is intentional —
86
+ error responses stay minimal. This is identical across the harness family; do not add fields ad-hoc.
87
+
88
+ ### Required Response Headers (applied by middleware — verify they're mounted)
89
+ ```typescript
90
+ // In src/runtime/app.ts — these must be present
91
+ app.use(helmetMiddleware) // 7 security headers
92
+ app.use(requestIdMiddleware) // X-Request-ID propagation
93
+ app.use(corsMiddleware) // CORS configured centrally
94
+ ```
95
+
96
+ ### Pagination (all list endpoints)
97
+
98
+ Cursors are encoded with **base64url** (URL-safe, no padding) — standardised
99
+ across the harness so cursors are portable between services and safe in query strings.
100
+
101
+ ```typescript
102
+ // ✅ Accept cursor from query params (base64url)
103
+ const cursor = req.query.cursor
104
+ ? (JSON.parse(Buffer.from(req.query.cursor as string, 'base64url').toString()) as PageCursor)
105
+ : undefined
106
+ const limit = Math.min(Number(req.query.limit) || 20, 100) // cap at 100
107
+
108
+ const result = await applicationService.list(auth.userId, { cursor, limit })
109
+ return res.json(ok(result, req.requestId))
110
+ // → { ok: true, data: { items: [...], nextCursor: 'base64url...', hasMore: true }, meta: {...} }
111
+
112
+ // ❌ Never accept raw offset/page params on user-facing endpoints
113
+ // ❌ Never use plain base64 — use base64url for URL safety
114
+ ```
115
+
116
+ ### Idempotency (mutation endpoints)
117
+
118
+ Mutating routes (POST/PUT/PATCH/DELETE) accept an optional `Idempotency-Key` header, handled by
119
+ `src/runtime/middleware/idempotency.ts` (Redis-backed). Wire it in front of the handler:
120
+
121
+ ```typescript
122
+ router.post('/', idempotency, userRateLimit, async (req, res, next) => { ... })
123
+ ```
124
+
125
+ - **First call** with a given key → handler runs; response is cached under `{userId}:{method}:{path}:{key}`.
126
+ - **Replay** (same key) → cached response returned with header `Idempotent-Replay: true`.
127
+ - **In-flight** (key still processing) → `409 CONFLICT` (`error.code: "CONFLICT"`).
128
+ - No key, or non-mutating method → middleware is a pass-through.
129
+
130
+ This is what the `security-auditor` A04 check ("idempotency keys on mutation endpoints") verifies.
131
+
132
+ ### OpenAPI registration (every route)
133
+
134
+ The harness publishes one machine-readable contract for the frontend's `openapi-fetch` client.
135
+ Every route registers its Zod request/response schemas + path into the registry in
136
+ `src/runtime/openapi.ts`, then `npm run openapi:export` regenerates `docs/generated/openapi.{json,yaml}`.
137
+
138
+ ```typescript
139
+ import { registry } from '../../openapi.js'
140
+ registry.registerPath({
141
+ method: 'post',
142
+ path: '/applications',
143
+ request: { body: { content: { 'application/json': { schema: CreateApplicationSchema } } } },
144
+ responses: { 201: { description: 'Created' /* ...envelope... */ } },
145
+ })
146
+ ```
147
+
148
+ CI fails if the committed contract drifts from the code (the `quality` job runs `openapi:export`
149
+ and `git diff`). Regenerate and commit `docs/generated/openapi.*` whenever a route or schema changes.