hatch3r 1.7.1 → 1.8.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 (189) hide show
  1. package/README.md +38 -12
  2. package/agents/hatch3r-a11y-auditor.md +4 -0
  3. package/agents/hatch3r-architect.md +4 -0
  4. package/agents/hatch3r-ci-watcher.md +4 -0
  5. package/agents/hatch3r-context-rules.md +26 -6
  6. package/agents/hatch3r-creator.md +6 -1
  7. package/agents/hatch3r-dependency-auditor.md +4 -0
  8. package/agents/hatch3r-devops.md +4 -0
  9. package/agents/hatch3r-docs-writer.md +4 -0
  10. package/agents/hatch3r-fixer.md +4 -0
  11. package/agents/hatch3r-handoff-loader.md +243 -0
  12. package/agents/hatch3r-handoff-preparer.md +134 -0
  13. package/agents/hatch3r-implementer.md +12 -0
  14. package/agents/hatch3r-learnings-loader.md +5 -1
  15. package/agents/hatch3r-lint-fixer.md +4 -0
  16. package/agents/hatch3r-perf-profiler.md +8 -0
  17. package/agents/hatch3r-researcher.md +4 -0
  18. package/agents/hatch3r-reviewer.md +94 -0
  19. package/agents/hatch3r-security-auditor.md +24 -0
  20. package/agents/hatch3r-test-writer.md +4 -0
  21. package/agents/modes/requirements-elicitation.md +4 -1
  22. package/agents/modes/similar-implementation.md +6 -0
  23. package/agents/modes/user-flows.md +76 -0
  24. package/agents/shared/quality-charter.md +128 -0
  25. package/agents/shared/user-content-templates.md +31 -1
  26. package/commands/hatch3r-agent-customize.md +4 -0
  27. package/commands/hatch3r-api-spec.md +7 -0
  28. package/commands/hatch3r-benchmark.md +7 -0
  29. package/commands/hatch3r-board-fill.md +8 -0
  30. package/commands/hatch3r-board-groom.md +4 -0
  31. package/commands/hatch3r-board-init.md +51 -0
  32. package/commands/hatch3r-board-pickup.md +8 -0
  33. package/commands/hatch3r-board-refresh.md +4 -0
  34. package/commands/hatch3r-board-shared.md +6 -6
  35. package/commands/hatch3r-bug-plan.md +7 -0
  36. package/commands/hatch3r-codebase-map.md +8 -0
  37. package/commands/hatch3r-command-customize.md +4 -0
  38. package/commands/hatch3r-context-health.md +5 -0
  39. package/commands/hatch3r-create.md +59 -4
  40. package/commands/hatch3r-debug.md +7 -0
  41. package/commands/hatch3r-dep-audit.md +4 -0
  42. package/commands/hatch3r-feature-plan.md +7 -0
  43. package/commands/hatch3r-handoff.md +133 -0
  44. package/commands/hatch3r-healthcheck.md +4 -0
  45. package/commands/hatch3r-hooks.md +4 -0
  46. package/commands/hatch3r-learn.md +16 -0
  47. package/commands/hatch3r-migration-plan.md +7 -0
  48. package/commands/hatch3r-onboard.md +7 -0
  49. package/commands/hatch3r-pr-resolve.md +12 -1
  50. package/commands/hatch3r-project-spec.md +8 -0
  51. package/commands/hatch3r-quick-change.md +11 -2
  52. package/commands/hatch3r-recipe.md +4 -0
  53. package/commands/hatch3r-refactor-plan.md +7 -0
  54. package/commands/hatch3r-release.md +5 -0
  55. package/commands/hatch3r-revision.md +7 -0
  56. package/commands/hatch3r-roadmap.md +8 -0
  57. package/commands/hatch3r-rule-customize.md +4 -0
  58. package/commands/hatch3r-security-audit.md +4 -0
  59. package/commands/hatch3r-skill-customize.md +4 -0
  60. package/commands/hatch3r-test-plan.md +7 -0
  61. package/commands/hatch3r-workflow.md +11 -1
  62. package/dist/cli/index.js +4814 -1130
  63. package/dist/cli/index.js.map +1 -1
  64. package/package.json +10 -5
  65. package/rules/hatch3r-accessibility-standards.md +21 -0
  66. package/rules/hatch3r-accessibility-standards.mdc +21 -0
  67. package/rules/hatch3r-agent-orchestration-detail.md +3 -0
  68. package/rules/hatch3r-agent-orchestration-detail.mdc +3 -0
  69. package/rules/hatch3r-agent-orchestration.md +34 -3
  70. package/rules/hatch3r-agent-orchestration.mdc +34 -3
  71. package/rules/hatch3r-ai-evals.md +158 -0
  72. package/rules/hatch3r-ai-evals.mdc +154 -0
  73. package/rules/hatch3r-ai-ux-patterns.md +131 -0
  74. package/rules/hatch3r-ai-ux-patterns.mdc +127 -0
  75. package/rules/hatch3r-api-design.md +67 -9
  76. package/rules/hatch3r-api-design.mdc +67 -9
  77. package/rules/hatch3r-api-versioning.md +119 -0
  78. package/rules/hatch3r-api-versioning.mdc +115 -0
  79. package/rules/hatch3r-auth-patterns.md +170 -0
  80. package/rules/hatch3r-auth-patterns.mdc +166 -0
  81. package/rules/hatch3r-component-conventions.md +30 -0
  82. package/rules/hatch3r-component-conventions.mdc +30 -0
  83. package/rules/hatch3r-container-hardening.md +131 -0
  84. package/rules/hatch3r-container-hardening.mdc +127 -0
  85. package/rules/hatch3r-contract-testing.md +117 -0
  86. package/rules/hatch3r-contract-testing.mdc +113 -0
  87. package/rules/hatch3r-deep-context.md +2 -0
  88. package/rules/hatch3r-deep-context.mdc +2 -0
  89. package/rules/hatch3r-dependency-management.md +73 -1
  90. package/rules/hatch3r-dependency-management.mdc +72 -0
  91. package/rules/hatch3r-design-system-detection.md +142 -0
  92. package/rules/hatch3r-design-system-detection.mdc +138 -0
  93. package/rules/hatch3r-event-schema-evolution.md +90 -0
  94. package/rules/hatch3r-event-schema-evolution.mdc +86 -0
  95. package/rules/hatch3r-handoff-readiness.md +45 -0
  96. package/rules/hatch3r-handoff-readiness.mdc +40 -0
  97. package/rules/hatch3r-i18n.md +13 -0
  98. package/rules/hatch3r-i18n.mdc +13 -0
  99. package/rules/hatch3r-iteration-summary.md +2 -0
  100. package/rules/hatch3r-iteration-summary.mdc +2 -0
  101. package/rules/hatch3r-migrations.md +61 -16
  102. package/rules/hatch3r-migrations.mdc +61 -16
  103. package/rules/hatch3r-observability-logging.md +1 -1
  104. package/rules/hatch3r-observability-logging.mdc +1 -1
  105. package/rules/hatch3r-observability-metrics.md +1 -1
  106. package/rules/hatch3r-observability-metrics.mdc +1 -1
  107. package/rules/hatch3r-observability-tracing-detail.md +8 -149
  108. package/rules/hatch3r-observability-tracing-detail.mdc +7 -149
  109. package/rules/hatch3r-observability-tracing.md +154 -6
  110. package/rules/hatch3r-observability-tracing.mdc +154 -6
  111. package/rules/hatch3r-observability.md +1 -0
  112. package/rules/hatch3r-observability.mdc +1 -0
  113. package/rules/hatch3r-operability.md +149 -0
  114. package/rules/hatch3r-operability.mdc +145 -0
  115. package/rules/hatch3r-passkey-server.md +181 -0
  116. package/rules/hatch3r-passkey-server.mdc +177 -0
  117. package/rules/hatch3r-progressive-delivery.md +120 -0
  118. package/rules/hatch3r-progressive-delivery.mdc +116 -0
  119. package/rules/hatch3r-resilience-patterns.md +154 -0
  120. package/rules/hatch3r-resilience-patterns.mdc +150 -0
  121. package/rules/hatch3r-secrets-management.md +29 -0
  122. package/rules/hatch3r-secrets-management.mdc +29 -0
  123. package/rules/hatch3r-testing.md +139 -43
  124. package/rules/hatch3r-testing.mdc +139 -43
  125. package/rules/hatch3r-ux-states-and-flows.md +149 -0
  126. package/rules/hatch3r-ux-states-and-flows.mdc +145 -0
  127. package/skills/hatch3r-a11y-audit/SKILL.md +14 -0
  128. package/skills/hatch3r-agent-customize/SKILL.md +10 -0
  129. package/skills/hatch3r-ai-feature/SKILL.md +136 -0
  130. package/skills/hatch3r-api-spec/SKILL.md +73 -0
  131. package/skills/hatch3r-architecture-review/SKILL.md +14 -0
  132. package/skills/hatch3r-bug-fix/SKILL.md +5 -0
  133. package/skills/hatch3r-ci-pipeline/SKILL.md +14 -0
  134. package/skills/hatch3r-cli-aichat/SKILL.md +84 -0
  135. package/skills/hatch3r-cli-ast-grep/SKILL.md +85 -0
  136. package/skills/hatch3r-cli-az-devops/SKILL.md +89 -0
  137. package/skills/hatch3r-cli-bat/SKILL.md +85 -0
  138. package/skills/hatch3r-cli-comby/SKILL.md +85 -0
  139. package/skills/hatch3r-cli-csvkit/SKILL.md +84 -0
  140. package/skills/hatch3r-cli-delta/SKILL.md +86 -0
  141. package/skills/hatch3r-cli-difftastic/SKILL.md +84 -0
  142. package/skills/hatch3r-cli-docker/SKILL.md +89 -0
  143. package/skills/hatch3r-cli-duckdb/SKILL.md +84 -0
  144. package/skills/hatch3r-cli-fd/SKILL.md +85 -0
  145. package/skills/hatch3r-cli-fzf/SKILL.md +84 -0
  146. package/skills/hatch3r-cli-gh/SKILL.md +90 -0
  147. package/skills/hatch3r-cli-glab/SKILL.md +89 -0
  148. package/skills/hatch3r-cli-jq/SKILL.md +89 -0
  149. package/skills/hatch3r-cli-lazygit/SKILL.md +78 -0
  150. package/skills/hatch3r-cli-llm/SKILL.md +84 -0
  151. package/skills/hatch3r-cli-miller/SKILL.md +84 -0
  152. package/skills/hatch3r-cli-mods/SKILL.md +84 -0
  153. package/skills/hatch3r-cli-overview/SKILL.md +60 -0
  154. package/skills/hatch3r-cli-playwright/SKILL.md +89 -0
  155. package/skills/hatch3r-cli-podman/SKILL.md +84 -0
  156. package/skills/hatch3r-cli-qsv/SKILL.md +91 -0
  157. package/skills/hatch3r-cli-ripgrep/SKILL.md +85 -0
  158. package/skills/hatch3r-cli-rtk/SKILL.md +91 -0
  159. package/skills/hatch3r-cli-sd/SKILL.md +85 -0
  160. package/skills/hatch3r-cli-stagehand/SKILL.md +111 -0
  161. package/skills/hatch3r-cli-taplo/SKILL.md +84 -0
  162. package/skills/hatch3r-cli-yq/SKILL.md +85 -0
  163. package/skills/hatch3r-cli-zstd/SKILL.md +85 -0
  164. package/skills/hatch3r-command-customize/SKILL.md +10 -0
  165. package/skills/hatch3r-context-health/SKILL.md +14 -0
  166. package/skills/hatch3r-cost-tracking/SKILL.md +14 -0
  167. package/skills/hatch3r-customize/SKILL.md +17 -0
  168. package/skills/hatch3r-dep-audit/SKILL.md +14 -0
  169. package/skills/hatch3r-design-system-detect/SKILL.md +164 -0
  170. package/skills/hatch3r-feature/SKILL.md +2 -0
  171. package/skills/hatch3r-gh-agentic-workflows/SKILL.md +13 -0
  172. package/skills/hatch3r-handoff-prepare/SKILL.md +160 -0
  173. package/skills/hatch3r-handoff-resume/SKILL.md +171 -0
  174. package/skills/hatch3r-incident-response/SKILL.md +14 -0
  175. package/skills/hatch3r-issue-workflow/SKILL.md +5 -0
  176. package/skills/hatch3r-logical-refactor/SKILL.md +14 -0
  177. package/skills/hatch3r-migration/SKILL.md +14 -0
  178. package/skills/hatch3r-observability-verify/SKILL.md +134 -0
  179. package/skills/hatch3r-perf-audit/SKILL.md +14 -0
  180. package/skills/hatch3r-pr-creation/SKILL.md +14 -0
  181. package/skills/hatch3r-qa-validation/SKILL.md +18 -0
  182. package/skills/hatch3r-recipe/SKILL.md +14 -0
  183. package/skills/hatch3r-refactor/SKILL.md +14 -0
  184. package/skills/hatch3r-release/SKILL.md +14 -0
  185. package/skills/hatch3r-reliability-verify/SKILL.md +146 -0
  186. package/skills/hatch3r-rule-customize/SKILL.md +10 -0
  187. package/skills/hatch3r-skill-customize/SKILL.md +10 -0
  188. package/skills/hatch3r-ui-ux-verify/SKILL.md +138 -0
  189. package/skills/hatch3r-visual-refactor/SKILL.md +15 -1
@@ -0,0 +1,150 @@
1
+ ---
2
+ description: Resilience patterns in user code — circuit breakers, retry with decorrelated jitter, timeouts with deadline propagation, idempotency keys, bulkheads, hedged requests
3
+ globs: ["**/services/**", "**/handlers/**", "**/clients/**", "**/integrations/**", "**/api/**", "**/middleware/**", "**/circuit*", "**/retry*", "**/resilience*"]
4
+ alwaysApply: false
5
+ ---
6
+ # Resilience Patterns
7
+
8
+ ## Scope
9
+
10
+ This rule applies to every outbound call (database, cache, queue, external HTTP, external RPC) and every service entry point in user code. The rule governs user application code; hatch3r's own pipeline implementations (`src/pipeline/circuitBreaker.ts`, `src/pipeline/retryWithBackoff.ts`) are the reference implementations — copy their semantics, including the transient-vs-substantive failure classification.
11
+
12
+ ## Circuit Breakers — Per Ecosystem
13
+
14
+ Use the maintained library for the project's runtime. The Hystrix project entered maintenance in 2018; new services use resilience4j or its peers below.
15
+
16
+ - **Node / TypeScript:** `opossum` 9.x or `cockatiel`. `opossum` wraps the operation in a breaker instance with explicit timeout, error threshold, and reset interval.
17
+ - **JVM (Java / Kotlin):** `resilience4j` 2.x — succeeds Hystrix; integrates with Reactor, RxJava 3, Spring Boot 3. Configure per-dependency `CircuitBreakerConfig` and register metrics with Micrometer.
18
+ - **.NET:** `Polly` 8.x — pipeline-style API; chain `AddCircuitBreaker`, `AddRetry`, `AddTimeout` for layered resilience.
19
+ - **Go:** `gobreaker` (sony/gobreaker) — synchronous wrapper around the call; counts consecutive failures and rolls over per `Interval` window.
20
+ - **Python:** `pybreaker` (sync) or `circuitbreaker` (async via decorator); pair with `tenacity` for retry composition.
21
+
22
+ Concrete configuration baseline:
23
+
24
+ - Failure threshold: 50% over a 10-request rolling window.
25
+ - Cooldown: 30s before a half-open trial request.
26
+ - Half-open: 1 trial request; success closes the breaker, failure reopens for the next 30s.
27
+ - Minimum request volume before threshold evaluation: 20 requests within the window — below that the breaker stays closed regardless of failure rate (avoids false trips on cold traffic).
28
+ - Failure classification distinguishes transient (network blip, 5xx, timeout) from substantive (4xx validation, auth failure). Only transient failures trip the breaker. Reference `src/pipeline/circuitBreaker.ts` for the classification taxonomy.
29
+
30
+ Emit a metric on every state transition (closed → open, open → half-open, half-open → closed|open) and alert when a per-dependency breaker stays open for more than 5 minutes — that is a sustained-outage signal, not transient.
31
+
32
+ ## Retry With Decorrelated Jitter
33
+
34
+ The canonical AWS Architecture Blog (2015) pattern, used by AWS SDK retries since:
35
+
36
+ ```
37
+ sleep = min(cap, random_between(base, prev_sleep * 3))
38
+ ```
39
+
40
+ - Base: 100ms.
41
+ - Cap: 30s.
42
+ - Maximum retries: 3 attempts beyond the initial call.
43
+
44
+ Never use `min(cap, base * 2 ** attempt)` (pure exponential backoff) without jitter — synchronized clients produce thundering-herd retry storms on recovery. Never use full random jitter (`random_between(0, cap)`) — it discards the prior delay signal and converges slower.
45
+
46
+ **Retry budget:** cap retry traffic at 10% of base request traffic per service. Exceeding the budget signals a sustained outage; circuit breaker should already be open.
47
+
48
+ Retry only on transient failures (see classification below). Never retry on substantive failures — they will fail again and waste budget. The library should expose a `shouldRetry(error)` predicate that returns `false` for 4xx (except 408 and 429), validation errors, and authentication failures.
49
+
50
+ Respect `Retry-After` headers on 429 and 503 — the server has told the client how long to wait. Ignoring it adds load to a struggling dependency.
51
+
52
+ ## Idempotency-Key on Retries
53
+
54
+ Any retried request that is not naturally idempotent (POST, PATCH, non-idempotent RPC) must carry an `Idempotency-Key` header. Server stores key+response for 24h and replays the stored response on duplicate key. Cross-reference `rules/hatch3r-api-versioning.md` (Slice 4) for the wire-format contract.
55
+
56
+ GET / HEAD / PUT / DELETE are idempotent by HTTP semantics — no key required, but verify handlers honor the contract (no side effects on GET; PUT replaces full resource state; DELETE on already-deleted resource returns 204 not 404).
57
+
58
+ Generate keys as UUIDv4 or ULID at the call site, not at the retry layer — the key must remain stable across all retry attempts of the same logical operation. Reusing a key across logically distinct operations is a correctness bug; the server returns the cached prior response.
59
+
60
+ ## Timeouts + Deadline Propagation
61
+
62
+ Every external call has an explicit timeout. Nested timeout budgets propagate from the parent deadline:
63
+
64
+ - **Go:** `context.WithDeadline` / `context.WithTimeout`.
65
+ - **Web / Node:** chained `AbortSignal` via `AbortSignal.timeout(ms)` and `AbortSignal.any([...])`.
66
+ - **gRPC:** `Deadline` propagated via metadata.
67
+ - **JVM:** `CompletableFuture.orTimeout` or `Resilience4j.TimeLimiter`.
68
+
69
+ Downstream timeout = remaining-budget − propagation-overhead (typically 50ms reserved). Default budgets:
70
+
71
+ - Service-call timeout: 5s.
72
+ - Database call: 2s.
73
+ - Cache call: 200ms.
74
+ - Health-probe call (cross-reference `rules/hatch3r-operability.md`): 1s.
75
+
76
+ A call that exceeds its budget is cancelled, not allowed to complete past the deadline. Caller surfaces the cancellation as a transient failure to the retry layer; if the parent deadline is already exhausted, no retry is attempted (no budget remains).
77
+
78
+ ## Hedged Requests
79
+
80
+ For tail-latency-sensitive reads, send a second request after p99 latency elapses; the first response wins, the second is cancelled. The Google SRE workbook (Reducing Tail Latency chapter) measures p99.9 reduction of approximately 96% at approximately 2% extra request traffic.
81
+
82
+ - **gRPC:** built-in via service-config `hedgingPolicy` (`maxAttempts`, `hedgingDelay`).
83
+ - **Application-level:** issue duplicate request via `Promise.race` (Node) or equivalent; cancel the loser via `AbortController`.
84
+
85
+ Apply only to idempotent reads. Never hedge writes — the duplicate could double-apply. Cap hedge traffic at 5% of total request volume; above that, the dependency is overloaded and hedging compounds the problem.
86
+
87
+ ## Bulkheads + Load Shedding
88
+
89
+ Bound concurrent calls per dependency to prevent one slow downstream from saturating all worker threads:
90
+
91
+ - 50 concurrent DB connections per service instance (per pool).
92
+ - 20 concurrent external HTTP calls per remote dependency.
93
+ - 10 concurrent cache calls per dependency (cache is usually fast — a queue depth above 10 means cache is itself a bottleneck).
94
+ - Reject excess with HTTP 503 + `Retry-After: 1` header at the service entry; do not block the request worker waiting for a slot.
95
+
96
+ - **JVM:** `resilience4j.Bulkhead` (semaphore or fixed thread pool).
97
+ - **Node / TypeScript:** semaphore via `p-limit` or `async-sema`.
98
+ - **Go:** buffered channel as semaphore.
99
+
100
+ Hystrix `commandPoolSize` archived since 2018 — use resilience4j on the JVM.
101
+
102
+ ## Failure Classification
103
+
104
+ Every call result classifies into one of three buckets:
105
+
106
+ - **Transient** — retryable: connection refused, timeout, 502/503/504, ECONNRESET, EAI_AGAIN, gRPC `UNAVAILABLE`/`DEADLINE_EXCEEDED`.
107
+ - **Substantive** — non-retryable: 400/401/403/404/422, validation error, business-rule rejection, gRPC `INVALID_ARGUMENT`/`NOT_FOUND`/`PERMISSION_DENIED`.
108
+ - **Unknown** — treated as transient with reduced retry budget (max 1 attempt). Includes unexpected exceptions and unmapped error codes.
109
+
110
+ Only transient failures trip the breaker and get retried. Substantive failures return immediately to the caller. Reference `src/pipeline/circuitBreaker.ts` for the canonical classification function.
111
+
112
+ 429 Too Many Requests is transient but special — respect `Retry-After`; do not exponential-backoff past it. 408 Request Timeout is transient and retryable. 401 is substantive at the resilience layer (auth refresh is a separate concern handled by the auth client, not the breaker).
113
+
114
+ ## Graceful Degradation / Fallback
115
+
116
+ Every circuit-broken call has a fallback path:
117
+
118
+ - Cached value (from the cache layer, even if stale-while-revalidate is in effect).
119
+ - Static response (sensible default; e.g. empty list, feature-flagged-off behavior).
120
+ - Degraded feature (skip non-critical enrichment; render the page without the personalization block).
121
+
122
+ Never let a non-critical dependency take down the request path. A recommendation service outage must not 500 the product page; the page renders without recommendations. Document the per-feature degradation strategy in `docs/runbooks/<service>.md` so the on-call can verify the fallback actually fires when the upstream breaker is open.
123
+
124
+ ## Composition Order
125
+
126
+ Stack the patterns in the order below — outermost first; reversing the order changes the failure semantics.
127
+
128
+ 1. **Bulkhead** (outermost) — reject if concurrency cap exceeded; protects the worker pool.
129
+ 2. **Circuit breaker** — fail-fast if breaker is open; protects the dependency.
130
+ 3. **Retry** — on transient failure; bounded by retry budget.
131
+ 4. **Timeout** (innermost, per attempt) — cancel the in-flight call.
132
+
133
+ Wrong order example: retry around timeout around breaker would retry on breaker-open exceptions and amplify load against the failing dependency. Right order: retry sits inside breaker, so a tripped breaker short-circuits before any retry attempt fires.
134
+
135
+ ## Cross-References
136
+
137
+ - `rules/hatch3r-operability.md` — probes, graceful shutdown, kill switches.
138
+ - `rules/hatch3r-observability-metrics.md` — RED metrics emit on retries and circuit-state changes; SLO alerts trigger on retry-budget exhaustion.
139
+ - `rules/hatch3r-api-versioning.md` — `Idempotency-Key` header contract.
140
+ - `rules/hatch3r-progressive-delivery.md` — circuit-broken dependency triggers staged-rollout abort.
141
+
142
+ ## References
143
+
144
+ - opossum (Node) — `github.com/nodeshift/opossum`
145
+ - resilience4j 2.x (JVM) — `resilience4j.readme.io`
146
+ - Polly 8.x (.NET) — `pollydocs.org`
147
+ - gobreaker (Go) — `github.com/sony/gobreaker`
148
+ - AWS Architecture Blog, "Exponential Backoff and Jitter" (2015) — `aws.amazon.com/blogs/architecture/exponential-backoff-and-jitter`
149
+ - Google SRE workbook, "Reducing Tail Latency" chapter — `sre.google/workbook`
150
+ - 2024–2026 outage postmortems: CrowdStrike Jul 2024, AWS us-east-1 Oct 2025, Azure East-US2 Sep 2025, Cloudflare Nov 2025.
@@ -53,6 +53,35 @@ cache_friendly: true
53
53
  - **Azure DevOps:** Workload Identity Federation with service connections
54
54
  - **GitLab CI:** OIDC ID tokens via `id_tokens` keyword
55
55
 
56
+ ## OIDC Trust-Policy Conditions (Cloud Auth)
57
+
58
+ Long-lived cloud secrets (`AWS_ACCESS_KEY_ID`, `GOOGLE_APPLICATION_CREDENTIALS` JSON file, Azure SP password) in CI are an anti-pattern in 2026. GitHub OIDC issues a per-run JWT; the cloud provider's trust policy exchanges it for short-lived credentials scoped to the workflow.
59
+
60
+ - **Branch + environment conditions are required.** The `sub` claim must be matched to a specific `(repository, ref, environment)` triple. PR workflows assume a read-only role; main-branch workflows assume the production role.
61
+ - **AWS:** IAM trust policy `Condition.StringEquals` on `token.actions.githubusercontent.com:sub` matching `repo:org/repo:ref:refs/heads/main` (or `:environment:production`). Federate via `aws-actions/configure-aws-credentials`.
62
+ - **GCP:** Workload Identity Federation with attribute condition on `assertion.sub` and `assertion.repository`. The pool is restricted to a single GitHub org.
63
+ - **Azure:** Federated credential `subject` field; create separate federated credentials for `pull_request`, `ref:refs/heads/main`, and per-environment.
64
+ - Remove every long-lived cloud secret after migrating; the leak surface drops from "credential lifetime" to "single workflow run".
65
+
66
+ ## Secret Manager Mandate
67
+
68
+ Every production secret lives in a managed vault — AWS Secrets Manager, GCP Secret Manager, Azure Key Vault, HashiCorp Vault, or a SaaS equivalent (Doppler, 1Password Secrets Automation, Infisical). Direct `.env`-file secret storage is permitted only for local development, and the file is never committed.
69
+
70
+ - Repository ships `.env.example` only — a template with placeholder values and per-variable descriptions. Actual `.env` is in `.gitignore`.
71
+ - Application code fetches secrets at startup via the vault SDK (AWS `GetSecretValue`, GCP `accessSecretVersion`, Vault `kv/data`). Secrets never bake into container images or build artifacts.
72
+ - Automated rotation is configured per-secret (AWS Lambda rotators, GCP rotation schedules, Vault dynamic credentials). See the Secret Rotation Policies table above for cadence.
73
+ - Vault access scoped per service via IAM / IRSA / Workload Identity / AppRole — no shared "master" reader.
74
+
75
+ ## Certificate Automation
76
+
77
+ TLS certificate expiry is a recurring outage class — manual renewal is forbidden in production. Automate via ACME.
78
+
79
+ - **Kubernetes:** `cert-manager` with a `ClusterIssuer` pointing at Let's Encrypt (production) or a private ACME server. Use HTTP-01 or DNS-01 solver per environment.
80
+ - **Reverse proxies:** Caddy auto-issues and renews via ACME by default; nginx pairs with `lego` or `acme.sh`.
81
+ - **Cloud-managed:** AWS ACM, GCP Managed SSL, Azure App Service Managed Certificate — auto-renew built in; pair with deploy-time CertificateNotAfter assertions.
82
+ - Monitoring alerts fire at 30, 14, and 7 days before expiry — paging at 7 days. Track via Prometheus `ssl_expiry_seconds` exporter or cloud-native alarm.
83
+ - Root and intermediate CA certificates pinned by SPKI hash in mTLS clients; rotate on a documented schedule before issuer key rollover.
84
+
56
85
  ## Application-Level Secret Handling
57
86
 
58
87
  - **Never log secrets.** Sanitize log output to redact any field matching known secret patterns (tokens, keys, passwords). Use structured logging with an explicit allowlist of loggable fields.
@@ -49,6 +49,35 @@ alwaysApply: false
49
49
  - **Azure DevOps:** Workload Identity Federation with service connections
50
50
  - **GitLab CI:** OIDC ID tokens via `id_tokens` keyword
51
51
 
52
+ ## OIDC Trust-Policy Conditions (Cloud Auth)
53
+
54
+ Long-lived cloud secrets (`AWS_ACCESS_KEY_ID`, `GOOGLE_APPLICATION_CREDENTIALS` JSON file, Azure SP password) in CI are an anti-pattern in 2026. GitHub OIDC issues a per-run JWT; the cloud provider's trust policy exchanges it for short-lived credentials scoped to the workflow.
55
+
56
+ - **Branch + environment conditions are required.** The `sub` claim must be matched to a specific `(repository, ref, environment)` triple. PR workflows assume a read-only role; main-branch workflows assume the production role.
57
+ - **AWS:** IAM trust policy `Condition.StringEquals` on `token.actions.githubusercontent.com:sub` matching `repo:org/repo:ref:refs/heads/main` (or `:environment:production`). Federate via `aws-actions/configure-aws-credentials`.
58
+ - **GCP:** Workload Identity Federation with attribute condition on `assertion.sub` and `assertion.repository`. The pool is restricted to a single GitHub org.
59
+ - **Azure:** Federated credential `subject` field; create separate federated credentials for `pull_request`, `ref:refs/heads/main`, and per-environment.
60
+ - Remove every long-lived cloud secret after migrating; the leak surface drops from "credential lifetime" to "single workflow run".
61
+
62
+ ## Secret Manager Mandate
63
+
64
+ Every production secret lives in a managed vault — AWS Secrets Manager, GCP Secret Manager, Azure Key Vault, HashiCorp Vault, or a SaaS equivalent (Doppler, 1Password Secrets Automation, Infisical). Direct `.env`-file secret storage is permitted only for local development, and the file is never committed.
65
+
66
+ - Repository ships `.env.example` only — a template with placeholder values and per-variable descriptions. Actual `.env` is in `.gitignore`.
67
+ - Application code fetches secrets at startup via the vault SDK (AWS `GetSecretValue`, GCP `accessSecretVersion`, Vault `kv/data`). Secrets never bake into container images or build artifacts.
68
+ - Automated rotation is configured per-secret (AWS Lambda rotators, GCP rotation schedules, Vault dynamic credentials). See the Secret Rotation Policies table above for cadence.
69
+ - Vault access scoped per service via IAM / IRSA / Workload Identity / AppRole — no shared "master" reader.
70
+
71
+ ## Certificate Automation
72
+
73
+ TLS certificate expiry is a recurring outage class — manual renewal is forbidden in production. Automate via ACME.
74
+
75
+ - **Kubernetes:** `cert-manager` with a `ClusterIssuer` pointing at Let's Encrypt (production) or a private ACME server. Use HTTP-01 or DNS-01 solver per environment.
76
+ - **Reverse proxies:** Caddy auto-issues and renews via ACME by default; nginx pairs with `lego` or `acme.sh`.
77
+ - **Cloud-managed:** AWS ACM, GCP Managed SSL, Azure App Service Managed Certificate — auto-renew built in; pair with deploy-time CertificateNotAfter assertions.
78
+ - Monitoring alerts fire at 30, 14, and 7 days before expiry — paging at 7 days. Track via Prometheus `ssl_expiry_seconds` exporter or cloud-native alarm.
79
+ - Root and intermediate CA certificates pinned by SPKI hash in mTLS clients; rotate on a documented schedule before issuer key rollover.
80
+
52
81
  ## Application-Level Secret Handling
53
82
 
54
83
  - **Never log secrets.** Sanitize log output to redact any field matching known secret patterns (tokens, keys, passwords). Use structured logging with an explicit allowlist of loggable fields.
@@ -12,17 +12,24 @@ cache_friendly: true
12
12
  ## Core Principles
13
13
 
14
14
  - Unit tests: project test runner. Integration: test runner + emulators/mocks. E2E: browser automation (Playwright or equivalent).
15
- - **Deterministic.** Mock time where needed. No wall clock dependency.
16
- - **Isolated.** Each test sets up and tears down its own state.
15
+ - **Deterministic.** Mock time, seed RNG, pin timezone/locale. See Determinism Contract below.
16
+ - **Isolated.** Each test sets up and tears down its own state. Vitest `isolate: true`; Jest `--runInBand` only for serialized DB tests.
17
17
  - **Fast.** Unit tests < 50ms. Integration tests < 2s.
18
18
  - **Named clearly.** Describe behavior: `"should award 15 XP for 25-min focus block"`.
19
19
  - **Regression.** Every bug fix includes a test that fails before the fix and passes after.
20
- - **No network.** Unit tests must not make network calls. Use mocks.
20
+ - **No network.** Unit tests must not make network calls. Use mocks or Testcontainers (pinned by digest).
21
21
  - No type escape hatches in tests. No `.skip` without a linked issue.
22
22
  - Write tests to `tests/unit/`, `tests/integration/`, `tests/e2e/`, or equivalent.
23
23
  - Use test fixtures from `tests/fixtures/` or equivalent.
24
24
  - **Browser verification.** For UI changes, verify visually in the browser via browser automation MCP after automated tests pass. Capture screenshots as evidence.
25
25
 
26
+ ## Test Pyramid / Honeycomb / Trophy — Pick by Architecture
27
+
28
+ Pick exactly one shape and document it in `docs/testing.md` (or equivalent):
29
+ - **Pyramid** (heavy unit, light E2E): monoliths with rich domain logic.
30
+ - **Honeycomb** (heavy integration, light unit + E2E): microservices; ~48% of microservice teams (Spotify model).
31
+ - **Trophy** (unit + integration + E2E in similar ratios, light static): serverless functions; ~42% of serverless teams (Kent C. Dodds shape).
32
+
26
33
  ## Coverage Thresholds
27
34
 
28
35
  - **Statement coverage:** 80% minimum across the project. New code must not decrease overall coverage.
@@ -33,6 +40,10 @@ cache_friendly: true
33
40
  - Generate coverage reports in CI and publish as PR comments or artifacts for visibility.
34
41
  - Exclude generated code, type declarations, and config files from coverage metrics.
35
42
 
43
+ ## Coverage That Matters — Coverage AND Mutation
44
+
45
+ Coverage alone is necessary, not sufficient. A PR that raises line coverage but drops mutation score is a regression. Reviewers verify the right test classes per the Per-Feature Mandate Map below; coverage numbers are a floor, not a finish line.
46
+
36
47
  ## Mocking Strategy
37
48
 
38
49
  - **Prefer fakes over mocks** for stateful dependencies (databases, caches). Fakes implement the real interface with in-memory state, making tests more realistic.
@@ -43,59 +54,144 @@ cache_friendly: true
43
54
  - **Type-safe mocks.** Mock implementations must satisfy the same TypeScript interface as the real dependency. Avoid `as any` in mock setup.
44
55
  - **No mocking the unit under test.** If you need to mock part of the module you are testing, the module has too many responsibilities — refactor first.
45
56
 
46
- ## Property-Based Testing
57
+ ## Contract Testing
58
+
59
+ Every cross-service interaction is covered by both consumer-side (Pact) and provider-side (Schemathesis against the OpenAPI/AsyncAPI schema) contract tests. `pact-broker can-i-deploy` gates production deploys: if the consumer/provider contract pair is incompatible, the deploy is blocked. See `rules/hatch3r-contract-testing.md` for the full pattern (broker setup, provider state handlers, versioning, breakage triage).
60
+
61
+ ## Property-Based Testing — Per Ecosystem
62
+
63
+ Required for any pure function, parser, serializer, state machine, or invariant-bearing function. Default 100 trials per property; raise to 1000 for security-sensitive code. Shrinking must be enabled.
64
+
65
+ - **TypeScript / JavaScript:** `fast-check` (latest 3.x). Use for pure functions, parsers, state machines (`fc.commands`).
66
+ - **Python:** `Hypothesis` 6.151+. Stateful PBT via `RuleBasedStateMachine`.
67
+ - **Rust:** `proptest`. Shrinks to minimal failing case.
68
+ - **Scala:** `ScalaCheck`. Use for case-class invariants.
69
+ - **Java:** `jqwik` (modern) or `junit-quickcheck`.
70
+ - **Go:** `gopter` or stdlib `testing/quick` (limited shrinking).
47
71
 
48
- - Use a property-based testing library (fast-check or equivalent) for functions with wide input domains.
49
- - **Priority targets:** parsers, serializers, validators, encoders/decoders, mathematical functions, and any pure function with complex input types.
50
- - Define invariants as properties: round-trip (encode then decode equals original), idempotency (applying twice equals applying once), monotonicity, commutativity.
51
- - Use `fc.assert` with at least 100 runs per property. Increase to 1000 for critical paths.
52
- - When a property test finds a failure, add the minimal counterexample as a dedicated regression unit test.
53
- - Shrinking must be enabled — it reduces failing inputs to the smallest reproduction case.
54
- - Property tests belong alongside unit tests in `tests/unit/`. Name them clearly: `"property: round-trip serialization for UserProfile"`.
72
+ Invariants to encode: round-trip (encode then decode equals original), idempotency (applying twice equals once), monotonicity, commutativity. When a property test finds a failure, add the minimal counterexample as a dedicated regression unit test.
55
73
 
56
- ## Mutation Testing
74
+ ## Mutation Testing — Per Ecosystem + Thresholds
57
75
 
58
- - Use Stryker (or equivalent mutation testing framework) on critical modules to measure test effectiveness beyond line coverage.
59
- - **Mutation score target:** 70% minimum on critical modules (auth, data layer, business rules). 60% minimum project-wide.
60
- - Run mutation testing in CI on a weekly schedule (not per-PR too slow). Report results as a CI artifact.
61
- - **Surviving mutants** indicate tests that pass regardless of code changes these are false-coverage tests. Fix them by adding assertions that detect the mutation.
62
- - Focus mutation testing effort on modules where a bug would cause data loss, security vulnerability, or financial impact.
63
- - Exclude test files, generated code, and UI presentation logic from mutation analysis.
76
+ Run on a nightly schedule (not per-commit) due to runtime cost. Mutation score is a quality gate alongside coverage. Surviving mutants indicate tests that pass regardless of code changes — fix by adding assertions that detect the mutation.
77
+
78
+ - **TypeScript / JavaScript:** Stryker. Thresholds: break 50 / low 60 / high 80 (Stryker defaults).
79
+ - **Python:** `mutmut` (88.5% score on reference suite, faster) or `Cosmic Ray` (82.7%, thorough).
80
+ - **Java:** PIT 1.22 (November 2025). Business logic target 80–90.
81
+ - **Go:** `go-mutesting` or `gremlins-dev/gremlins`.
82
+ - **.NET:** `Stryker.NET`.
83
+
84
+ **Mutation score target:** 70% minimum on critical modules (auth, data layer, business rules), 60% project-wide, 80%+ on payment/billing logic. Exclude test files, generated code, and UI presentation logic from mutation analysis.
85
+
86
+ ## Fuzz Testing — Per Ecosystem
87
+
88
+ Required for any parser, deserializer, network handler, file-format handler, or untrusted-input boundary. Crash + hang + OOM detection; corpus minimization; persisted crash inputs become regression fixtures.
89
+
90
+ - **Java:** jazzer (OSS-Fuzz integrated).
91
+ - **JavaScript:** jazzer.js OSS was discontinued in 2025 — fall back to property-based testing for JS-only paths, or fuzz the underlying native binding.
92
+ - **Python:** `atheris` (Google).
93
+ - **Rust:** `cargo-fuzz` + libFuzzer.
94
+ - **Go:** native `testing.F` (Go 1.18+); for advanced workflows use `gosentry` (Trail of Bits, 2026-05-12 fork of the discontinued jazzer.js workflow adapted for Go).
95
+ - **C / C++:** AFL++ + OSS-Fuzz.
96
+
97
+ ## Determinism Contract
98
+
99
+ Every test must be deterministic. Mandates:
100
+ - **Clock injection.** Production code never calls `new Date()` / `time.Now()` / `datetime.now()` directly; inject a clock interface. In tests: `vi.useFakeTimers()` / `freezegun` / `mock.patch('time.time')`.
101
+ - **Seeded RNG.** Every random call uses an injected seedable RNG. In tests: fixed seed per test.
102
+ - **Pinned timezone and locale.** `TZ=UTC` and `LC_ALL=C.UTF-8` in the CI environment.
103
+ - **Sorted iteration.** Any test asserting on map / dict iteration order sorts first.
104
+ - **OS-assigned ports.** Never bind to a fixed port in tests — bind to `0` to get an OS-assigned port.
105
+ - **Test isolation.** Vitest `isolate: true` (default); Jest `--runInBand` only when needed for serialized DB tests.
64
106
 
65
107
  ## Flaky Test Handling
66
108
 
67
- - **Zero tolerance policy.** A flaky test erodes trust in the entire suite. Fix or quarantine within 48 hours of detection.
68
- - **Quarantine process:** Move the flaky test to a `tests/quarantine/` directory or tag with `.skip("FLAKY: #issue-number")`. Create a tracking issue immediately.
69
- - **Retry strategy in CI:** Allow a maximum of 1 automatic retry for the full test suite. Never retry individual tests silently — that masks flakiness.
70
- - **Root cause investigation:** Common causes are shared mutable state, timing dependencies (real clocks, `setTimeout`), port conflicts, uncontrolled randomness, and external service calls.
71
- - **Fix patterns:** Replace `setTimeout` with fake timers, replace shared state with per-test setup, replace port binding with dynamic ports, seed random generators deterministically.
72
- - **Flaky test metrics:** Track flaky test rate over time. Target < 0.5% flaky rate (flaky runs / total runs). Alert when rate exceeds 1%.
73
- - **Quarantine review:** Review quarantined tests weekly. Tests quarantined for more than 30 days must be either fixed or deleted with justification.
109
+ - **Detection.** CI retries failed tests once; tests failing on retry but passing on rerun are tagged `flake-suspected`.
110
+ - **Quarantine.** Any test that flakes twice in 7 days moves to `tests/quarantine/` (runs but does not block PRs). Issue auto-filed with the `flake` label.
111
+ - **SLA.** 14 days to root-cause and fix; otherwise the test is deleted. Quarantined tests reviewed weekly.
112
+ - **Retry policy.** Allow at most 1 automatic retry for the full test suite. Never silently retry individual tests that masks flakiness.
113
+ - **Categorization on intake.** Tag each flake by root cause: timing (use fake timers), network (use mocks / Testcontainers), ordering (sort assertions), pollution (test isolation), resource (cleanup).
114
+ - **Fix patterns.** Replace `setTimeout` with fake timers; replace shared state with per-test setup; replace fixed ports with OS-assigned (`0`); seed random generators deterministically.
115
+ - **Metrics.** Track flaky rate over time. Target < 0.5% (flaky runs / total runs). Alert at 1%.
116
+ - **Cost awareness.** Datadog 2026 telemetry reports 6–8 hrs/eng/week lost to flakes when quarantine + SLA is not enforced.
117
+
118
+ ## E2E Strategy
119
+
120
+ - **Playwright is the 2026 default** (95k stars, ~290 ms/action, native sharding via `--shard`). Use for cross-browser, accessibility (`@axe-core/playwright`), and visual regression (`toHaveScreenshot()`).
121
+ - Cypress requires paid Cloud for serious parallelization; WebdriverIO is the niche choice for web + mobile parity.
122
+ - Retry policy: `retries: 2` for transient infra; never `retries: >= 5` (masks bugs).
123
+
124
+ ## Snapshot Testing
125
+
126
+ - **Use sparingly.** 2–4 snapshots per component max. Appropriate for serialized output (JSON API responses, CLI output, rendered HTML structure) where the exact output matters and is stable.
127
+ - **Not appropriate for:** UI component visual appearance (use visual regression tests via `toHaveScreenshot()` or `jest-image-snapshot`), objects with timestamps or random IDs (unstable), large objects (unreadable diffs).
128
+ - **Review discipline.** Snapshot updates (`--update-snapshots`) must be reviewed with the same rigor as code changes. Reviewers verify the new snapshot is intentionally correct, not just "different."
129
+ - **Keep snapshots small.** Files > 100 lines suggest the test is asserting too broadly. Narrow the assertion to the relevant subset.
130
+ - **Inline snapshots** are preferred over external `.snap` files for short outputs (< 20 lines) — keeps the assertion co-located with the test.
131
+ - **Design-system components:** Storybook + Chromatic.
74
132
 
75
133
  ## Test Data Management
76
134
 
77
- - **Factories over fixtures.** Use factory functions (builder pattern) to generate test data with sensible defaults and per-test overrides. Factories produce valid objects by default; tests override only the fields relevant to the scenario.
78
- - **Builder pattern example:** `buildUser({ role: "admin" })` returns a full valid User with admin role and random but valid defaults for all other fields.
79
- - **No shared mutable fixtures.** If multiple tests read the same fixture data, each test must get its own copy. Use `structuredClone()` or factory functions.
80
- - **Realistic data.** Use faker or equivalent for generating realistic names, emails, dates. Avoid magic strings like `"test"`, `"foo"`, `"abc123"`.
81
- - **Deterministic seeding.** When using random data generators, seed them per test file so failures are reproducible.
82
- - **Fixture files** (JSON, YAML) are acceptable for large, complex, or externally-sourced test inputs (API response snapshots, configuration samples). Store in `tests/fixtures/`.
83
- - **Database state:** Integration tests that require database state must set up and tear down within the test using helpers. Never depend on database state from a previous test.
135
+ - **Factories over fixtures.** Use factory functions (factory-bot for Ruby, Fishery for TS, factory-boy for Python) seeded with Faker pinned to a fixed version.
136
+ - **Builder pattern example:** `buildUser({ role: "admin" })` returns a full valid `User` with admin role and valid defaults for all other fields.
137
+ - **No shared mutable fixtures.** If multiple tests read the same fixture data, each test gets its own copy via `structuredClone()` or a factory function.
138
+ - **Realistic data.** Avoid magic strings like `"test"`, `"foo"`, `"abc123"`.
139
+ - **Deterministic seeding.** Seed generators per test file so failures reproduce.
140
+ - **Fixture files** (JSON, YAML) are acceptable for large, complex, or externally-sourced inputs (API response snapshots, configuration samples). Store in `tests/fixtures/`.
141
+ - **Database state:** Integration tests set up and tear down within the test via helpers. Never depend on database state from a previous test. Enforce tenancy isolation via per-test schema or transaction rollback.
142
+ - **Testcontainers** pinned by image digest, not tag.
84
143
 
85
144
  ## Error Path Coverage
86
145
 
87
146
  Error handling code is often under-tested because developers focus on happy paths. Enforce minimum error coverage:
147
+ - **Every exported function that can fail** must have at least one test exercising the error path. "Can fail" includes functions returning `Result<T, E>`, functions with `throw` statements, async functions calling external services, and functions with input validation.
148
+ - **Error message assertions.** Verify that messages, codes, and structured fields contain the expected values. Do not assert only that "an error was thrown" — verify the error content.
149
+ - **Error propagation.** When a function wraps or transforms errors from a dependency, verify the original error context is preserved (cause chain, stack trace, original error code).
150
+ - **Boundary error tests.** For each architectural boundary (API handler, event handler, background processor), verify that errors are caught, logged, and returned as safe responses without leaking internal details.
88
151
 
89
- - **Every exported function that can fail** must have at least one test exercising the error path. "Can fail" includes: functions returning `Result<T, E>`, functions with `throw` statements, async functions calling external services, and functions with input validation.
90
- - **Error message assertions.** Test that error messages, codes, and structured fields contain the expected values. Do not assert only that "an error was thrown" -- verify the error content.
91
- - **Error propagation.** When a function wraps or transforms errors from a dependency, test that the original error context is preserved (cause chain, stack trace, original error code).
92
- - **Boundary error tests.** For each architectural boundary (API handler, event handler, background processor), test that errors are caught, logged, and returned as safe responses without leaking internal details.
152
+ ## Load Testing in CI
93
153
 
94
- ## Snapshot Testing
154
+ - **k6** (k6 Operator v1.0 for Kubernetes-distributed runs), **Vegeta** (constant-rate, no coordinated omission), **Locust** (Python), **Artillery** (TS).
155
+ - Baseline vs current diff in CI; SLO regression detection on p95, p99, and error-rate thresholds. Block the PR when a tracked SLO regresses.
156
+
157
+ ## Security Testing in CI
158
+
159
+ - **SAST:** Semgrep + CodeQL.
160
+ - **SCA / container / IaC / secrets:** Trivy (one-shot multi-scanner).
161
+ - **DAST:** OWASP ZAP or Nuclei against an ephemeral environment.
162
+
163
+ See `rules/hatch3r-container-hardening.md` and `rules/hatch3r-dependency-management.md` for the operational policy around hardening and pinning.
164
+
165
+ ## AI-Assisted Test Generation
166
+
167
+ - **Qodo 2.0** (60.1% F1 on reference benchmark) for TS / JS unit tests + edge cases.
168
+ - **Diffblue Cover** (symbolic, 20× cited productivity uplift on legacy code) for Java.
169
+
170
+ These are accelerators, not substitutes for the Per-Feature Mandate Map. Every generated test still goes through review and must map to a required test class for the code under test.
171
+
172
+ ## Per-Feature Mandate Map
173
+
174
+ Reviewers verify each PR satisfies the required test classes for the code class touched. A PR that adds a parser without a fuzz harness, or a payment path without mutation testing, fails review even if coverage is green.
175
+
176
+ | Code class | Required test classes |
177
+ |------------|----------------------|
178
+ | Parser / deserializer | unit + property + fuzz |
179
+ | Network handler / RPC entry | integration + contract + fuzz |
180
+ | Payment / billing logic | unit + property + mutation (≥ 80 score) |
181
+ | State machine | unit + property (with `RuleBasedStateMachine` analogue) |
182
+ | Pure function | unit + property |
183
+ | Service / RPC client | unit + contract (consumer side) |
184
+ | Service / RPC server | integration + contract (provider side) + Schemathesis |
185
+ | UI component | unit + visual regression + a11y (via `hatch3r-ui-ux-verify`) |
186
+ | LLM feature | eval (via `hatch3r-ai-feature`) + unit on adapter + integration on fallback chain |
187
+ | Background job | unit + integration with poison-message handling |
188
+
189
+ ## References
95
190
 
96
- - **Use sparingly.** Snapshots are appropriate for serialized output (JSON API responses, CLI output, rendered HTML structure) where the exact output matters and is stable.
97
- - **Not appropriate for:** UI component visual appearance (use visual regression tests), objects with timestamps or random IDs (unstable), large objects (unreadable diffs).
98
- - **Review discipline.** Snapshot updates (`--update-snapshots`) must be reviewed with the same rigor as code changes. Reviewers must verify the new snapshot is intentionally correct, not just "different."
99
- - **Keep snapshots small.** Snapshot files > 100 lines suggest the test is asserting too broadly. Narrow the assertion to the relevant subset.
100
- - **Inline snapshots** (where supported) are preferred over external `.snap` files for short outputs (< 20 lines) because they keep the assertion co-located with the test.
101
- - **Name snapshot files** to match their test file: `auth.test.ts` → `auth.test.ts.snap`.
191
+ - Stryker (mutation testing): https://stryker-mutator.io/
192
+ - fast-check (property-based testing, TS): https://fast-check.dev/
193
+ - Hypothesis (property-based testing, Python): https://hypothesis.readthedocs.io/
194
+ - proptest (property-based testing, Rust): https://github.com/proptest-rs/proptest
195
+ - Pact (consumer-driven contract testing): https://docs.pact.io/
196
+ - Schemathesis (OpenAPI provider testing): https://schemathesis.readthedocs.io/
197
+ - OWASP Web Security Testing Guide: https://owasp.org/www-project-web-security-testing-guide/