azcodr 1.5.0 → 1.5.1
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/.agents/hooks.json +42 -0
- package/.agents/hooks.json.example +42 -42
- package/.agents/mcp_config.json.example +6 -1
- package/.agents/scripts/safety_guard.sh +34 -16
- package/.agents/scripts/verify_completion.sh +27 -13
- package/.agents/skills/agentic-architect/SKILL.md +125 -125
- package/.agents/skills/agentic-architect/references/agents_md_template.md +62 -62
- package/.agents/skills/agentic-architect/references/refinement_workflow.md +32 -32
- package/.agents/skills/agentic-architect/references/skill_architecture_inquiry.md +63 -63
- package/.agents/skills/agentic-architect/references/skill_template.md +56 -56
- package/.agents/skills/agentic-architect/scripts/validate_agentic_configs.sh +401 -362
- package/.agents/skills/clean-code-refactor/SKILL.md +91 -91
- package/.agents/skills/clean-code-refactor/references/clean_code_smells.md +27 -27
- package/.agents/skills/clean-code-refactor/references/design_patterns_ts.md +65 -65
- package/.agents/skills/compliance-audit/SKILL.md +120 -120
- package/.agents/skills/compliance-audit/references/owasp_top10_controls.md +16 -16
- package/.agents/skills/compliance-audit/references/soc2_iso_controls.md +28 -28
- package/.agents/skills/lets-build/SKILL.md +173 -172
- package/.agents/skills/lets-build/references/architecture_interview_matrix.md +115 -115
- package/.agents/skills/lets-build/references/hexagonal_bootstrap_scaffolds.md +160 -160
- package/.agents/skills/lets-build/references/project_readme_template.md +79 -79
- package/.agents/skills/lets-build/scripts/bootstrap_workspace.sh +255 -253
- package/.agents/skills/product-analyst/SKILL.md +154 -154
- package/.agents/skills/product-analyst/references/backlog_ordering_techniques.md +107 -107
- package/.agents/skills/product-analyst/references/gherkin_patterns.md +46 -46
- package/.agents/skills/product-analyst/references/invest_checklist.md +38 -38
- package/.agents/skills/product-analyst/references/okr_alignment_guide.md +76 -76
- package/.agents/skills/product-analyst/references/smart_tasks.md +59 -59
- package/.agents/skills/relentless-questioner/SKILL.md +128 -128
- package/.agents/skills/relentless-questioner/references/adaptive_question_trees.md +102 -102
- package/.editorconfig +19 -19
- package/.github/copilot-instructions.md +1 -0
- package/.github/workflows/ci.yml +56 -0
- package/.gitignore +25 -25
- package/AGENTS.md +102 -102
- package/LICENSE +21 -21
- package/README.md +154 -154
- package/bin/azcodr.js +228 -228
- package/data/.gitkeep +0 -0
- package/docs/knowledge/ubiquitous_language.md +18 -18
- package/docs/rules/agentic_configuration.md +259 -259
- package/docs/rules/api_architecture.md +179 -179
- package/docs/rules/authentication.md +76 -76
- package/docs/rules/authorization.md +75 -75
- package/docs/rules/caching.md +69 -69
- package/docs/rules/clean_code.md +62 -62
- package/docs/rules/cloud_native.md +41 -41
- package/docs/rules/cqrs.md +203 -203
- package/docs/rules/database_design.md +125 -125
- package/docs/rules/database_operations.md +69 -69
- package/docs/rules/design_patterns.md +98 -98
- package/docs/rules/devops_ci_cd.md +76 -76
- package/docs/rules/domain_driven_design.md +122 -122
- package/docs/rules/error_handling.md +52 -52
- package/docs/rules/feature_flags.md +59 -59
- package/docs/rules/frontend_architecture.md +157 -157
- package/docs/rules/multitenancy_architecture.md +98 -98
- package/docs/rules/product_ownership.md +127 -127
- package/docs/rules/project_management.md +49 -49
- package/docs/rules/relentless_questioning.md +52 -52
- package/docs/rules/requirements_engineering.md +98 -98
- package/docs/rules/security_compliance.md +53 -53
- package/docs/rules/server_driven_ui.md +88 -88
- package/docs/rules/test_driven_development.md +185 -185
- package/docs/rules/transactional_email.md +27 -27
- package/docs/rules/type_safety.md +65 -65
- package/docs/rules/ui_ux_architecture.md +150 -150
- package/docs/rules/workflow_state_machines.md +117 -117
- package/lib/index.d.ts +134 -123
- package/lib/index.js +5 -5
- package/lib/scaffold.js +399 -351
- package/memory.md +36 -36
- package/package.json +62 -59
- package/scripts/test_coverage.js +38 -0
- package/scripts/validate.js +246 -0
|
@@ -1,185 +1,185 @@
|
|
|
1
|
-
# Test-Driven Development (London School TDD) & Test Isolation Standards
|
|
2
|
-
|
|
3
|
-
> **Core Mandate:** Drive all features through the non-negotiable 5-Phase Agile Domain Lifecycle (Outside-In Double-Loop TDD, Uncle Bob's 3 Laws), enforcing transactional database rollback per test, zero-sleep determinism, and non-negotiable 100.00% statement, branch, and function coverage gates.
|
|
4
|
-
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
## 1. The Immutable 5-Phase Agile Domain Lifecycle
|
|
8
|
-
|
|
9
|
-
Every functional increment, feature, or architectural modification must traverse this unbroken sequence. Writing code out of order (e.g. coding before tests, or testing before domain analysis) is strictly prohibited.
|
|
10
|
-
|
|
11
|
-
```mermaid
|
|
12
|
-
flowchart TD
|
|
13
|
-
P1["Phase 1: Requirements Engineering<br/>• INVEST stories & Gherkin criteria<br/>• Out-of-scope non-goals & status matrix"]
|
|
14
|
-
P2["Phase 2: Tactical Domain Analysis<br/>• Ubiquitous Language & Bounded Contexts<br/>• Aggregate Roots & Business Invariants"]
|
|
15
|
-
P3["Phase 3: Outer Acceptance Test (RED)<br/>• Failing UI component or API route test<br/>• Verifies failure for expected reason"]
|
|
16
|
-
P4["Phase 4: Inner TDD & Collaborator Discovery (RED-GREEN-REFACTOR)<br/>• Discovers Use Cases & Ports<br/>• Nano-cycles with Uncle Bob's 3 Laws"]
|
|
17
|
-
P5["Phase 5: Outer Verification & Proof (GREEN)<br/>• Outer test passes with zero regressions<br/>• 100.00% coverage & boundary smoke verification"]
|
|
18
|
-
|
|
19
|
-
P1 --> P2 --> P3 --> P4 --> P5
|
|
20
|
-
```
|
|
21
|
-
|
|
22
|
-
---
|
|
23
|
-
|
|
24
|
-
## 2. The London School Double-Loop TDD Workflow
|
|
25
|
-
|
|
26
|
-
Drive all user-facing features from the outermost interface inward:
|
|
27
|
-
|
|
28
|
-
```mermaid
|
|
29
|
-
flowchart TD
|
|
30
|
-
subgraph OuterLoop ["Outer Loop (Acceptance / Contract Test)"]
|
|
31
|
-
O_RED["Outer Acceptance Test (RED)"]
|
|
32
|
-
O_GREEN["Outer Acceptance Test (GREEN)"]
|
|
33
|
-
O_REF["Outer Refactor & Proof"]
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
subgraph InnerLoop ["Inner Loop (Unit Test & Collaborator TDD)"]
|
|
37
|
-
I_RED["Unit Test Collaborator (RED)"]
|
|
38
|
-
I_GREEN["Implement Minimal Code (GREEN)"]
|
|
39
|
-
I_REF["Refactor under Green (REFACTOR)"]
|
|
40
|
-
|
|
41
|
-
I_RED --> I_GREEN --> I_REF
|
|
42
|
-
I_REF -.->|"Next Micro-Assertion"| I_RED
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
O_RED --> I_RED
|
|
46
|
-
I_REF --> O_GREEN --> O_REF
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
1. **Outer Acceptance / Contract Test First**: Every feature begins with a failing outer acceptance test:
|
|
50
|
-
- **Frontend (UI)**: Component or page tests asserting user interactions, form submissions, accessibility, and visual states.
|
|
51
|
-
- **Backend (API)**: Black-box REST route tests asserting HTTP verbs, request schemas, RFC 7807 problem details, and status codes.
|
|
52
|
-
2. **Collaborator Discovery**: Outer tests do not implement business logic directly; they discover and shape the contracts of their immediate collaborators (Use Cases, Domain Services, Repositories).
|
|
53
|
-
3. **Inner Unit Tests with Test Doubles**: Unit test collaborators in isolation using test doubles and mocks (`Controllers/Handlers` ➔ `Use Cases` ➔ `Ports/Adapters`).
|
|
54
|
-
4. **Mock Ownership Principle**: **Only mock types you own**. Always wrap third-party libraries, database drivers, and external network clients in application-owned port adapters before mocking.
|
|
55
|
-
5. **Atomic Double Loop**: Follow the strict rhythm: **RED (Fail) ➔ GREEN (Pass) ➔ REFACTOR (Clean/De-duplicate)**. Never skip the Refactor phase.
|
|
56
|
-
6. **Cross-Package Boundary Verification**: In monorepos with frontend dev servers or API gateways (Vite, NGINX), outer-loop verification must explicitly test reverse-proxy forwarding and real network serialization (`scripts/smoke_test.sh`), ensuring client-side SPA fallbacks do not mask unmapped backend routes.
|
|
57
|
-
|
|
58
|
-
---
|
|
59
|
-
|
|
60
|
-
## 3. The Zero-Deviation Invariant (Why We NEVER Deviate)
|
|
61
|
-
|
|
62
|
-
Deviating from this lifecycle introduces catastrophic defects and architectural rot:
|
|
63
|
-
|
|
64
|
-
| Deviation Shortcut | Immediate Consequence | Systemic Impact |
|
|
65
|
-
|---|---|---|
|
|
66
|
-
| **Skipping Domain Analysis** | Hallucinated entities, missing business invariants, wrong data models. | "The Toy Prototype Blunder": Foreign key string inputs, unvalidated states, costly migrations. |
|
|
67
|
-
| **Writing Code Before Tests** | Untested edge cases, unfalsifiable code, confirmation bias in test design. | Hidden bugs in production, regressions during refactoring, brittle codebases. |
|
|
68
|
-
| **Skipping Outer Acceptance Tests** | In-memory unit tests pass, but user interactions and network routing fail. | "The In-Memory Supertest Illusion": App says "Offline/Connecting" while 100% unit tests pass. |
|
|
69
|
-
| **Dropping the UI in Fullstack TDD** | Developer plunges into internal domain units, leaving the application headless with no web UI. | "The Headless Fallacy": User requests a fullstack web app but receives pure headless backend libraries. |
|
|
70
|
-
| **Skipping the Refactor Phase** | Technical debt accumulates immediately behind green tests. | Code rot, duplicated logic, bloated monolithic functions (> 30 lines), violated DRY/SLAP. |
|
|
71
|
-
|
|
72
|
-
---
|
|
73
|
-
|
|
74
|
-
## 4. The Batch-Test Anti-Pattern & The Incremental Nano-Cycle
|
|
75
|
-
|
|
76
|
-
### The "Test-First Waterfall" Anti-Pattern (BANNED)
|
|
77
|
-
A rampant anti-pattern in AI coding is dumping 10–20 test cases in a single test file, and then writing a 300-line implementation file in one shot so all tests pass simultaneously. **This is strictly prohibited.**
|
|
78
|
-
- **Why It Fails:** Writing all tests upfront is Waterfall in disguise. It forces the AI to hallucinate and lock in speculative method signatures and class structures before any code runs. If test #3 reveals a design flaw, tests #4–20 are broken legacy code before running.
|
|
79
|
-
- **Falsifiability Failure:** When 20 tests fail at once, you never prove that each individual assertion would catch its specific regression. Many batch tests are tautologies that pass by coincidence.
|
|
80
|
-
|
|
81
|
-
### The Mandatory Incremental Nano-Cycle
|
|
82
|
-
Every collaborator discovered in Phase 4 must progress through micro-cycles of one behavior at a time:
|
|
83
|
-
1. **RED (Micro-Assertion):** Write **ONE** test asserting a single micro-behavior (e.g. `expect(cart.total()).toBe(0)`).
|
|
84
|
-
2. **VERIFY RED:** Run the test suite (`npm test`). **Inspect and verify the specific failure message** (e.g. "method not defined" or "expected 0, got undefined"). Never skip running the test while RED.
|
|
85
|
-
3. **GREEN (Minimal Implementation):** Write the **absolute minimum production code** required to pass the single failing assertion (even hardcoding `return 0` if appropriate).
|
|
86
|
-
4. **VERIFY GREEN:** Run the test suite. Confirm the test turns green with zero side effects.
|
|
87
|
-
5. **REFACTOR (Under Green):** Clean up names, eliminate duplication (DRY), enforce SLAP and Clean Code standards while tests remain 100% green.
|
|
88
|
-
6. **REPEAT:** Move to the next micro-behavior (e.g. `cart with 1 item returns item price`).
|
|
89
|
-
|
|
90
|
-
---
|
|
91
|
-
|
|
92
|
-
## 5. Ping-Pong Pair Programming Protocol with AI
|
|
93
|
-
|
|
94
|
-
When pairing with the human developer, operate in true **Ping-Pong TDD**:
|
|
95
|
-
|
|
96
|
-
```mermaid
|
|
97
|
-
sequenceDiagram
|
|
98
|
-
autonumber
|
|
99
|
-
actor A as Partner A (Driver/Human)
|
|
100
|
-
participant S as Test Runner
|
|
101
|
-
actor B as Partner B (Navigator/AI)
|
|
102
|
-
|
|
103
|
-
A->>S: Writes 1 micro-test assertion (RED)
|
|
104
|
-
S-->>A: Displays verified failure output
|
|
105
|
-
B->>S: Writes minimal code to pass (GREEN)
|
|
106
|
-
S-->>B: Displays verified pass
|
|
107
|
-
Note over A,B: Both refactor under green (REFACTOR)
|
|
108
|
-
Note over A,B: Roles swap; repeat for next behavior
|
|
109
|
-
```
|
|
110
|
-
|
|
111
|
-
- **Collaborative Steering**: The human developer can write the test while the AI writes the minimal pass, or the AI can present each micro-test and await confirmation before implementing.
|
|
112
|
-
- **Continuous Alignment**: Design and data structures emerge organically through mutual feedback rather than monolithic code dumps.
|
|
113
|
-
|
|
114
|
-
---
|
|
115
|
-
|
|
116
|
-
## 6. Test Isolation & Determinism
|
|
117
|
-
|
|
118
|
-
- **Transactional Rollback per Integration Test**:
|
|
119
|
-
- Every integration test that interacts with persistence must execute within a scoped transaction that is rolled back upon test completion (`afterEach` rollback) or use ephemeral, disposable database isolates. Never leave mutated rows that pollute subsequent tests.
|
|
120
|
-
- **Deterministic Test Data Factories**:
|
|
121
|
-
- Utilize strongly-typed test data factories (`buildUser()`, `buildOrder()`) with randomized unique identifiers rather than hardcoded magic strings or fixed database IDs.
|
|
122
|
-
- **Zero Sleep / Flakiness Elimination**:
|
|
123
|
-
- Strictly forbid arbitrary `sleep()` or timeout pauses in tests.
|
|
124
|
-
- Rely exclusively on deterministic condition polling (`waitFor(condition)`) or reactive event promises to eliminate test flakiness.
|
|
125
|
-
|
|
126
|
-
---
|
|
127
|
-
|
|
128
|
-
## 7. Mandatory 100.00% Test Coverage Thresholds
|
|
129
|
-
|
|
130
|
-
- **Strict Coverage Thresholds**: Maintain line, function, branch, and statement test coverage at **100.00%** across all backend domain logic, adapters, contracts, and frontend suites. Strictly enforce 100% threshold failure gates in CI pipelines (`scripts/test_coverage.js`).
|
|
131
|
-
- **Exhaustive Status Codes & Error Branches**: Explicitly test all HTTP/gRPC response codes:
|
|
132
|
-
- Success: `200 OK`, `201 Created`, `204 No Content`
|
|
133
|
-
- Client Errors: `400 Bad Request`, `401 Unauthorized`, `403 Forbidden`, `404 Not Found`, `409 Conflict`, `422 Unprocessable Entity`, `429 Too Many Requests`
|
|
134
|
-
- Server Failures: `500 Internal Server Error`, `503 Service Unavailable`
|
|
135
|
-
- **UI Interaction States & Edge Cases**: Fully assert all presentation states (loading spinners, disabled controls, error banners, success feedback, empty states) across suites.
|
|
136
|
-
|
|
137
|
-
---
|
|
138
|
-
|
|
139
|
-
## 8. Headless UI Testing Architecture for Autonomous Agents
|
|
140
|
-
|
|
141
|
-
Autonomous AI coding agents operate without human eyesight. To verify user interfaces deterministically without manual browser clicking, projects with UI interfaces must enforce the **4-Tier Headless UI Testing Pyramid**:
|
|
142
|
-
|
|
143
|
-
```mermaid
|
|
144
|
-
flowchart TD
|
|
145
|
-
T4["Tier 4: Headless Playwright E2E<br/>(Full multi-page browser journeys, Chromium CLI)"]
|
|
146
|
-
T3["Tier 3: Automated A11y Gates (axe-core)<br/>(WCAG 2.2 AA audits with zero human eyesight)"]
|
|
147
|
-
T2["Tier 2: Network Isolation via MSW<br/>(Deterministic HTTP mocking: loading, error, empty, success)"]
|
|
148
|
-
T1["Tier 1: Behavioral Component Testing (@testing-library)<br/>(Accessible role queries, user-event keyboard/mouse)"]
|
|
149
|
-
|
|
150
|
-
T4 --> T3 --> T2 --> T1
|
|
151
|
-
```
|
|
152
|
-
|
|
153
|
-
### 8.1. Behavioral Component Testing (@testing-library + jsdom/happy-dom)
|
|
154
|
-
- **Test Behavior, Not Implementation**: Never assert component internal state, hook variables, or private methods. Assert what the user experiences.
|
|
155
|
-
- **Strict Accessible Role-Based Queries**:
|
|
156
|
-
- *Mandatory:* `screen.getByRole('button', { name: /submit/i })`, `screen.getByRole('heading', { level: 1 })`, `screen.getByLabelText(/email/i)`.
|
|
157
|
-
- *Prohibited:* `container.querySelector('.btn-primary')`, `getByTestId('submit-btn')` (data-testid is a banned crutch for poor semantic accessibility).
|
|
158
|
-
- **Realistic User Events**: Always use `@testing-library/user-event` rather than synthetic `fireEvent` to accurately simulate browser focus, keypress, typing, and click sequences.
|
|
159
|
-
|
|
160
|
-
### 8.2. Network Isolation via Mock Service Worker (MSW)
|
|
161
|
-
- Never mock client fetch/HTTP clients with ad-hoc mock objects (`vi.fn()`).
|
|
162
|
-
- Intercept requests at the network layer using **MSW**:
|
|
163
|
-
```typescript
|
|
164
|
-
// Deterministic network boundary simulation
|
|
165
|
-
http.get('/api/v1/orders', () => HttpResponse.json(mockOrders))
|
|
166
|
-
```
|
|
167
|
-
- **The 4 Universal UI Presentation States**: Component tests must explicitly assert:
|
|
168
|
-
1. *Loading State:* Accessible spinner / skeleton is rendered while request is in flight.
|
|
169
|
-
2. *Success State:* Data grid / list renders items with correct semantic markup.
|
|
170
|
-
3. *Error State:* RFC 7807 error banner renders with retry button when API returns `500` or `422`.
|
|
171
|
-
4. *Empty State:* Meaningful empty-state message and CTA when API returns `[]`.
|
|
172
|
-
|
|
173
|
-
### 8.3. Automated Headless Accessibility Gates (axe-core)
|
|
174
|
-
- Every component test suite must execute automated accessibility checks using `axe-core` (`vitest-axe` or `@axe-core/playwright`):
|
|
175
|
-
```typescript
|
|
176
|
-
const { container } = render(<OrderDetailsModal orderId="ord_123" />);
|
|
177
|
-
const results = await axe(container);
|
|
178
|
-
expect(results).toHaveNoViolations();
|
|
179
|
-
```
|
|
180
|
-
- Fails the test automatically on missing ARIA labels, invalid heading hierarchies, contrast defects, or unlinked form labels without requiring human eyesight.
|
|
181
|
-
|
|
182
|
-
### 8.4. End-to-End Headless Browser Automation (Playwright)
|
|
183
|
-
- For critical user journeys (authentication, checkout, resource creation):
|
|
184
|
-
- Run headless Chromium in CLI/CI: `npx playwright test`.
|
|
185
|
-
- Configure automated forensic captures on failure: screenshots, trace files, and videos saved to `test-results/` for immediate agent inspection.
|
|
1
|
+
# Test-Driven Development (London School TDD) & Test Isolation Standards
|
|
2
|
+
|
|
3
|
+
> **Core Mandate:** Drive all features through the non-negotiable 5-Phase Agile Domain Lifecycle (Outside-In Double-Loop TDD, Uncle Bob's 3 Laws), enforcing transactional database rollback per test, zero-sleep determinism, and non-negotiable 100.00% statement, branch, and function coverage gates.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 1. The Immutable 5-Phase Agile Domain Lifecycle
|
|
8
|
+
|
|
9
|
+
Every functional increment, feature, or architectural modification must traverse this unbroken sequence. Writing code out of order (e.g. coding before tests, or testing before domain analysis) is strictly prohibited.
|
|
10
|
+
|
|
11
|
+
```mermaid
|
|
12
|
+
flowchart TD
|
|
13
|
+
P1["Phase 1: Requirements Engineering<br/>• INVEST stories & Gherkin criteria<br/>• Out-of-scope non-goals & status matrix"]
|
|
14
|
+
P2["Phase 2: Tactical Domain Analysis<br/>• Ubiquitous Language & Bounded Contexts<br/>• Aggregate Roots & Business Invariants"]
|
|
15
|
+
P3["Phase 3: Outer Acceptance Test (RED)<br/>• Failing UI component or API route test<br/>• Verifies failure for expected reason"]
|
|
16
|
+
P4["Phase 4: Inner TDD & Collaborator Discovery (RED-GREEN-REFACTOR)<br/>• Discovers Use Cases & Ports<br/>• Nano-cycles with Uncle Bob's 3 Laws"]
|
|
17
|
+
P5["Phase 5: Outer Verification & Proof (GREEN)<br/>• Outer test passes with zero regressions<br/>• 100.00% coverage & boundary smoke verification"]
|
|
18
|
+
|
|
19
|
+
P1 --> P2 --> P3 --> P4 --> P5
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## 2. The London School Double-Loop TDD Workflow
|
|
25
|
+
|
|
26
|
+
Drive all user-facing features from the outermost interface inward:
|
|
27
|
+
|
|
28
|
+
```mermaid
|
|
29
|
+
flowchart TD
|
|
30
|
+
subgraph OuterLoop ["Outer Loop (Acceptance / Contract Test)"]
|
|
31
|
+
O_RED["Outer Acceptance Test (RED)"]
|
|
32
|
+
O_GREEN["Outer Acceptance Test (GREEN)"]
|
|
33
|
+
O_REF["Outer Refactor & Proof"]
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
subgraph InnerLoop ["Inner Loop (Unit Test & Collaborator TDD)"]
|
|
37
|
+
I_RED["Unit Test Collaborator (RED)"]
|
|
38
|
+
I_GREEN["Implement Minimal Code (GREEN)"]
|
|
39
|
+
I_REF["Refactor under Green (REFACTOR)"]
|
|
40
|
+
|
|
41
|
+
I_RED --> I_GREEN --> I_REF
|
|
42
|
+
I_REF -.->|"Next Micro-Assertion"| I_RED
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
O_RED --> I_RED
|
|
46
|
+
I_REF --> O_GREEN --> O_REF
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
1. **Outer Acceptance / Contract Test First**: Every feature begins with a failing outer acceptance test:
|
|
50
|
+
- **Frontend (UI)**: Component or page tests asserting user interactions, form submissions, accessibility, and visual states.
|
|
51
|
+
- **Backend (API)**: Black-box REST route tests asserting HTTP verbs, request schemas, RFC 7807 problem details, and status codes.
|
|
52
|
+
2. **Collaborator Discovery**: Outer tests do not implement business logic directly; they discover and shape the contracts of their immediate collaborators (Use Cases, Domain Services, Repositories).
|
|
53
|
+
3. **Inner Unit Tests with Test Doubles**: Unit test collaborators in isolation using test doubles and mocks (`Controllers/Handlers` ➔ `Use Cases` ➔ `Ports/Adapters`).
|
|
54
|
+
4. **Mock Ownership Principle**: **Only mock types you own**. Always wrap third-party libraries, database drivers, and external network clients in application-owned port adapters before mocking.
|
|
55
|
+
5. **Atomic Double Loop**: Follow the strict rhythm: **RED (Fail) ➔ GREEN (Pass) ➔ REFACTOR (Clean/De-duplicate)**. Never skip the Refactor phase.
|
|
56
|
+
6. **Cross-Package Boundary Verification**: In monorepos with frontend dev servers or API gateways (Vite, NGINX), outer-loop verification must explicitly test reverse-proxy forwarding and real network serialization (`scripts/smoke_test.sh`), ensuring client-side SPA fallbacks do not mask unmapped backend routes.
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
## 3. The Zero-Deviation Invariant (Why We NEVER Deviate)
|
|
61
|
+
|
|
62
|
+
Deviating from this lifecycle introduces catastrophic defects and architectural rot:
|
|
63
|
+
|
|
64
|
+
| Deviation Shortcut | Immediate Consequence | Systemic Impact |
|
|
65
|
+
|---|---|---|
|
|
66
|
+
| **Skipping Domain Analysis** | Hallucinated entities, missing business invariants, wrong data models. | "The Toy Prototype Blunder": Foreign key string inputs, unvalidated states, costly migrations. |
|
|
67
|
+
| **Writing Code Before Tests** | Untested edge cases, unfalsifiable code, confirmation bias in test design. | Hidden bugs in production, regressions during refactoring, brittle codebases. |
|
|
68
|
+
| **Skipping Outer Acceptance Tests** | In-memory unit tests pass, but user interactions and network routing fail. | "The In-Memory Supertest Illusion": App says "Offline/Connecting" while 100% unit tests pass. |
|
|
69
|
+
| **Dropping the UI in Fullstack TDD** | Developer plunges into internal domain units, leaving the application headless with no web UI. | "The Headless Fallacy": User requests a fullstack web app but receives pure headless backend libraries. |
|
|
70
|
+
| **Skipping the Refactor Phase** | Technical debt accumulates immediately behind green tests. | Code rot, duplicated logic, bloated monolithic functions (> 30 lines), violated DRY/SLAP. |
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
## 4. The Batch-Test Anti-Pattern & The Incremental Nano-Cycle
|
|
75
|
+
|
|
76
|
+
### The "Test-First Waterfall" Anti-Pattern (BANNED)
|
|
77
|
+
A rampant anti-pattern in AI coding is dumping 10–20 test cases in a single test file, and then writing a 300-line implementation file in one shot so all tests pass simultaneously. **This is strictly prohibited.**
|
|
78
|
+
- **Why It Fails:** Writing all tests upfront is Waterfall in disguise. It forces the AI to hallucinate and lock in speculative method signatures and class structures before any code runs. If test #3 reveals a design flaw, tests #4–20 are broken legacy code before running.
|
|
79
|
+
- **Falsifiability Failure:** When 20 tests fail at once, you never prove that each individual assertion would catch its specific regression. Many batch tests are tautologies that pass by coincidence.
|
|
80
|
+
|
|
81
|
+
### The Mandatory Incremental Nano-Cycle
|
|
82
|
+
Every collaborator discovered in Phase 4 must progress through micro-cycles of one behavior at a time:
|
|
83
|
+
1. **RED (Micro-Assertion):** Write **ONE** test asserting a single micro-behavior (e.g. `expect(cart.total()).toBe(0)`).
|
|
84
|
+
2. **VERIFY RED:** Run the test suite (`npm test`). **Inspect and verify the specific failure message** (e.g. "method not defined" or "expected 0, got undefined"). Never skip running the test while RED.
|
|
85
|
+
3. **GREEN (Minimal Implementation):** Write the **absolute minimum production code** required to pass the single failing assertion (even hardcoding `return 0` if appropriate).
|
|
86
|
+
4. **VERIFY GREEN:** Run the test suite. Confirm the test turns green with zero side effects.
|
|
87
|
+
5. **REFACTOR (Under Green):** Clean up names, eliminate duplication (DRY), enforce SLAP and Clean Code standards while tests remain 100% green.
|
|
88
|
+
6. **REPEAT:** Move to the next micro-behavior (e.g. `cart with 1 item returns item price`).
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
## 5. Ping-Pong Pair Programming Protocol with AI
|
|
93
|
+
|
|
94
|
+
When pairing with the human developer, operate in true **Ping-Pong TDD**:
|
|
95
|
+
|
|
96
|
+
```mermaid
|
|
97
|
+
sequenceDiagram
|
|
98
|
+
autonumber
|
|
99
|
+
actor A as Partner A (Driver/Human)
|
|
100
|
+
participant S as Test Runner
|
|
101
|
+
actor B as Partner B (Navigator/AI)
|
|
102
|
+
|
|
103
|
+
A->>S: Writes 1 micro-test assertion (RED)
|
|
104
|
+
S-->>A: Displays verified failure output
|
|
105
|
+
B->>S: Writes minimal code to pass (GREEN)
|
|
106
|
+
S-->>B: Displays verified pass
|
|
107
|
+
Note over A,B: Both refactor under green (REFACTOR)
|
|
108
|
+
Note over A,B: Roles swap; repeat for next behavior
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
- **Collaborative Steering**: The human developer can write the test while the AI writes the minimal pass, or the AI can present each micro-test and await confirmation before implementing.
|
|
112
|
+
- **Continuous Alignment**: Design and data structures emerge organically through mutual feedback rather than monolithic code dumps.
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
## 6. Test Isolation & Determinism
|
|
117
|
+
|
|
118
|
+
- **Transactional Rollback per Integration Test**:
|
|
119
|
+
- Every integration test that interacts with persistence must execute within a scoped transaction that is rolled back upon test completion (`afterEach` rollback) or use ephemeral, disposable database isolates. Never leave mutated rows that pollute subsequent tests.
|
|
120
|
+
- **Deterministic Test Data Factories**:
|
|
121
|
+
- Utilize strongly-typed test data factories (`buildUser()`, `buildOrder()`) with randomized unique identifiers rather than hardcoded magic strings or fixed database IDs.
|
|
122
|
+
- **Zero Sleep / Flakiness Elimination**:
|
|
123
|
+
- Strictly forbid arbitrary `sleep()` or timeout pauses in tests.
|
|
124
|
+
- Rely exclusively on deterministic condition polling (`waitFor(condition)`) or reactive event promises to eliminate test flakiness.
|
|
125
|
+
|
|
126
|
+
---
|
|
127
|
+
|
|
128
|
+
## 7. Mandatory 100.00% Test Coverage Thresholds
|
|
129
|
+
|
|
130
|
+
- **Strict Coverage Thresholds**: Maintain line, function, branch, and statement test coverage at **100.00%** across all backend domain logic, adapters, contracts, and frontend suites. Strictly enforce 100% threshold failure gates in CI pipelines (`scripts/test_coverage.js`).
|
|
131
|
+
- **Exhaustive Status Codes & Error Branches**: Explicitly test all HTTP/gRPC response codes:
|
|
132
|
+
- Success: `200 OK`, `201 Created`, `204 No Content`
|
|
133
|
+
- Client Errors: `400 Bad Request`, `401 Unauthorized`, `403 Forbidden`, `404 Not Found`, `409 Conflict`, `422 Unprocessable Entity`, `429 Too Many Requests`
|
|
134
|
+
- Server Failures: `500 Internal Server Error`, `503 Service Unavailable`
|
|
135
|
+
- **UI Interaction States & Edge Cases**: Fully assert all presentation states (loading spinners, disabled controls, error banners, success feedback, empty states) across suites.
|
|
136
|
+
|
|
137
|
+
---
|
|
138
|
+
|
|
139
|
+
## 8. Headless UI Testing Architecture for Autonomous Agents
|
|
140
|
+
|
|
141
|
+
Autonomous AI coding agents operate without human eyesight. To verify user interfaces deterministically without manual browser clicking, projects with UI interfaces must enforce the **4-Tier Headless UI Testing Pyramid**:
|
|
142
|
+
|
|
143
|
+
```mermaid
|
|
144
|
+
flowchart TD
|
|
145
|
+
T4["Tier 4: Headless Playwright E2E<br/>(Full multi-page browser journeys, Chromium CLI)"]
|
|
146
|
+
T3["Tier 3: Automated A11y Gates (axe-core)<br/>(WCAG 2.2 AA audits with zero human eyesight)"]
|
|
147
|
+
T2["Tier 2: Network Isolation via MSW<br/>(Deterministic HTTP mocking: loading, error, empty, success)"]
|
|
148
|
+
T1["Tier 1: Behavioral Component Testing (@testing-library)<br/>(Accessible role queries, user-event keyboard/mouse)"]
|
|
149
|
+
|
|
150
|
+
T4 --> T3 --> T2 --> T1
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
### 8.1. Behavioral Component Testing (@testing-library + jsdom/happy-dom)
|
|
154
|
+
- **Test Behavior, Not Implementation**: Never assert component internal state, hook variables, or private methods. Assert what the user experiences.
|
|
155
|
+
- **Strict Accessible Role-Based Queries**:
|
|
156
|
+
- *Mandatory:* `screen.getByRole('button', { name: /submit/i })`, `screen.getByRole('heading', { level: 1 })`, `screen.getByLabelText(/email/i)`.
|
|
157
|
+
- *Prohibited:* `container.querySelector('.btn-primary')`, `getByTestId('submit-btn')` (data-testid is a banned crutch for poor semantic accessibility).
|
|
158
|
+
- **Realistic User Events**: Always use `@testing-library/user-event` rather than synthetic `fireEvent` to accurately simulate browser focus, keypress, typing, and click sequences.
|
|
159
|
+
|
|
160
|
+
### 8.2. Network Isolation via Mock Service Worker (MSW)
|
|
161
|
+
- Never mock client fetch/HTTP clients with ad-hoc mock objects (`vi.fn()`).
|
|
162
|
+
- Intercept requests at the network layer using **MSW**:
|
|
163
|
+
```typescript
|
|
164
|
+
// Deterministic network boundary simulation
|
|
165
|
+
http.get('/api/v1/orders', () => HttpResponse.json(mockOrders))
|
|
166
|
+
```
|
|
167
|
+
- **The 4 Universal UI Presentation States**: Component tests must explicitly assert:
|
|
168
|
+
1. *Loading State:* Accessible spinner / skeleton is rendered while request is in flight.
|
|
169
|
+
2. *Success State:* Data grid / list renders items with correct semantic markup.
|
|
170
|
+
3. *Error State:* RFC 7807 error banner renders with retry button when API returns `500` or `422`.
|
|
171
|
+
4. *Empty State:* Meaningful empty-state message and CTA when API returns `[]`.
|
|
172
|
+
|
|
173
|
+
### 8.3. Automated Headless Accessibility Gates (axe-core)
|
|
174
|
+
- Every component test suite must execute automated accessibility checks using `axe-core` (`vitest-axe` or `@axe-core/playwright`):
|
|
175
|
+
```typescript
|
|
176
|
+
const { container } = render(<OrderDetailsModal orderId="ord_123" />);
|
|
177
|
+
const results = await axe(container);
|
|
178
|
+
expect(results).toHaveNoViolations();
|
|
179
|
+
```
|
|
180
|
+
- Fails the test automatically on missing ARIA labels, invalid heading hierarchies, contrast defects, or unlinked form labels without requiring human eyesight.
|
|
181
|
+
|
|
182
|
+
### 8.4. End-to-End Headless Browser Automation (Playwright)
|
|
183
|
+
- For critical user journeys (authentication, checkout, resource creation):
|
|
184
|
+
- Run headless Chromium in CLI/CI: `npx playwright test`.
|
|
185
|
+
- Configure automated forensic captures on failure: screenshots, trace files, and videos saved to `test-results/` for immediate agent inspection.
|
|
@@ -1,27 +1,27 @@
|
|
|
1
|
-
# Transactional Email Subsystem
|
|
2
|
-
|
|
3
|
-
> **Core Mandate:** Enforce declarative email templates, strict HTML sanitization, decoupled asynchronous dispatch, and deterministic local test delivery through Mailpit SMTP routing.
|
|
4
|
-
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
## 1. Declarative & Typed Email Templates
|
|
8
|
-
|
|
9
|
-
- **Declarative Template Definition**: Author transactional email templates using language-agnostic markup formats (such as **MJML - Mailjet Markup Language**) or typed component schemas to ensure cross-client rendering consistency across Outlook, Gmail, and Apple Mail.
|
|
10
|
-
- **Strict HTML Sanitization & Injection Defense**: Strictly prohibit unescaped raw HTML string concatenation. Centralize variable interpolation through a strict escaping utility neutralizing `&`, `<`, `>`, `"`, and `'` to prevent Cross-Site Scripting (XSS) and template injection vulnerabilities.
|
|
11
|
-
|
|
12
|
-
---
|
|
13
|
-
|
|
14
|
-
## 2. Decoupled Transport & Background Queues
|
|
15
|
-
|
|
16
|
-
- **Async Queue Decoupling**: Decouple notification delivery from synchronous HTTP request-response cycles via an asynchronous job queue (e.g. BullMQ, Celery, or Transactional Outbox workers). API responses must never block on external network SMTP socket round-trips.
|
|
17
|
-
- **Zero-Dependency Native Sockets**: Prefer socket-based SMTP adapters adhering to RFC 5321 commands over heavy third-party mailer libraries to eliminate supply chain risks and transitive dependencies.
|
|
18
|
-
|
|
19
|
-
---
|
|
20
|
-
|
|
21
|
-
## 3. Local Mail Transport & Integration Verification
|
|
22
|
-
|
|
23
|
-
- **Local SMTP via Mailpit**:
|
|
24
|
-
- Route local and CI SMTP traffic to **Mailpit** (SMTP port 1025 / Web UI port 8025).
|
|
25
|
-
- Never route emails to public mail transfer agents (MTAs) or external API gateways during automated test runs or local development.
|
|
26
|
-
- **Deterministic API Assertion Protocol**:
|
|
27
|
-
- Assert email delivery in integration tests by querying Mailpit's REST API (`GET /api/v1/messages`) or testing against in-memory notification sinks to inspect recipient headers, delivery status, HTML body content, and verification links without timing dependencies.
|
|
1
|
+
# Transactional Email Subsystem
|
|
2
|
+
|
|
3
|
+
> **Core Mandate:** Enforce declarative email templates, strict HTML sanitization, decoupled asynchronous dispatch, and deterministic local test delivery through Mailpit SMTP routing.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 1. Declarative & Typed Email Templates
|
|
8
|
+
|
|
9
|
+
- **Declarative Template Definition**: Author transactional email templates using language-agnostic markup formats (such as **MJML - Mailjet Markup Language**) or typed component schemas to ensure cross-client rendering consistency across Outlook, Gmail, and Apple Mail.
|
|
10
|
+
- **Strict HTML Sanitization & Injection Defense**: Strictly prohibit unescaped raw HTML string concatenation. Centralize variable interpolation through a strict escaping utility neutralizing `&`, `<`, `>`, `"`, and `'` to prevent Cross-Site Scripting (XSS) and template injection vulnerabilities.
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## 2. Decoupled Transport & Background Queues
|
|
15
|
+
|
|
16
|
+
- **Async Queue Decoupling**: Decouple notification delivery from synchronous HTTP request-response cycles via an asynchronous job queue (e.g. BullMQ, Celery, or Transactional Outbox workers). API responses must never block on external network SMTP socket round-trips.
|
|
17
|
+
- **Zero-Dependency Native Sockets**: Prefer socket-based SMTP adapters adhering to RFC 5321 commands over heavy third-party mailer libraries to eliminate supply chain risks and transitive dependencies.
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## 3. Local Mail Transport & Integration Verification
|
|
22
|
+
|
|
23
|
+
- **Local SMTP via Mailpit**:
|
|
24
|
+
- Route local and CI SMTP traffic to **Mailpit** (SMTP port 1025 / Web UI port 8025).
|
|
25
|
+
- Never route emails to public mail transfer agents (MTAs) or external API gateways during automated test runs or local development.
|
|
26
|
+
- **Deterministic API Assertion Protocol**:
|
|
27
|
+
- Assert email delivery in integration tests by querying Mailpit's REST API (`GET /api/v1/messages`) or testing against in-memory notification sinks to inspect recipient headers, delivery status, HTML body content, and verification links without timing dependencies.
|
|
@@ -1,65 +1,65 @@
|
|
|
1
|
-
# Static Type Safety & Sound Type Systems
|
|
2
|
-
|
|
3
|
-
> **Core Mandate:** Enforce maximum compiler strictness, branded nominal typing for domain identifiers, strict prohibition of untyped escape hatches, and automated pre-commit quality guardrails across polyglot implementations.
|
|
4
|
-
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
## 1. The YAGNI Gate: Sound Types vs. Type-Level Acrobatics
|
|
8
|
-
|
|
9
|
-
Type systems exist to prove program correctness and eliminate entire classes of runtime errors. **Never compromise static type safety with `any` escape hatches, but avoid premature type-level metaprogramming acrobatics that obscure domain intent.**
|
|
10
|
-
|
|
11
|
-
```mermaid
|
|
12
|
-
flowchart TD
|
|
13
|
-
subgraph TypeSafetyGate["Type Safety YAGNI Gate"]
|
|
14
|
-
B1["1. Simple Baseline (Day 1)<br/>• Strict compiler flags enabled with zero compilation warnings<br/>• Concrete interfaces, records, dataclasses, and structs<br/>• Zero any, Any, or raw Object escape hatches"]
|
|
15
|
-
B2["2. Anti-Triggers (Forbidden)<br/>• Bypassing the compiler via any, as unknown as T, or casts<br/>• Deep recursive type-gymnastics where a simple interface solves it<br/>• Primitive Obsession: passing raw string for all domain IDs"]
|
|
16
|
-
B3["3. The Tipping Point (Graduation)<br/>• Domain Identifiers: Use Branded/Nominal types when multiple entity IDs risk mix-ups<br/>• System Boundaries: Use fail-fast schema validation (Zod, Serde, Pydantic) on untrusted inputs"]
|
|
17
|
-
B1 -->|Forbidden if compiler bypassed| B2
|
|
18
|
-
B1 -->|Triggered by domain safety & boundary parsing| B3
|
|
19
|
-
end
|
|
20
|
-
```
|
|
21
|
-
|
|
22
|
-
---
|
|
23
|
-
|
|
24
|
-
## 2. Maximum Compiler Strictness Across Polyglot Stacks
|
|
25
|
-
|
|
26
|
-
Regardless of the execution language chosen for an adapter, service, or CLI, enforce maximum compiler rigor to eliminate runtime null pointer exceptions, unhandled type cases, and memory errors at compile time:
|
|
27
|
-
|
|
28
|
-
- **TypeScript**: Enable all strict compiler flags (`strict: true`, `noImplicitAny: true`, `strictNullChecks: true`, `noUncheckedIndexedAccess: true`).
|
|
29
|
-
- **Python**: Enforce strict type checking (`mypy --strict` or `pyright` in strict mode).
|
|
30
|
-
- **Rust**: Enable `#![deny(clippy::all)]` and `#![deny(missing_docs)]` with zero `unsafe` blocks.
|
|
31
|
-
- **Go**: Enable comprehensive static analysis (`golangci-lint` with `errcheck`, `govet`, `staticcheck`).
|
|
32
|
-
- **Java**: Enable `-Werror -Xlint:all`, enforce `@NonNull` contracts or the Checker Framework.
|
|
33
|
-
- **C#**: Enable `<Nullable>enable</Nullable>` and `<TreatWarningsAsErrors>true</TreatWarningsAsErrors>`.
|
|
34
|
-
|
|
35
|
-
---
|
|
36
|
-
|
|
37
|
-
## 3. Branded Nominal Typing & Primitive Obsession Elimination
|
|
38
|
-
|
|
39
|
-
Prevent accidental mixing of raw primitive identifiers (e.g. passing an arbitrary `string` representing a `TenantId` where a `UserId` is expected) by enforcing nominal types across all supported languages:
|
|
40
|
-
|
|
41
|
-
```mermaid
|
|
42
|
-
classDiagram
|
|
43
|
-
class NominalIdentifierPattern {
|
|
44
|
-
<<Polyglot Implementations>>
|
|
45
|
-
}
|
|
46
|
-
note for NominalIdentifierPattern "Rust: struct TenantId(String); struct UserId(String);<br/>Go: type TenantId string; type UserId string<br/>TypeScript: type TenantId = Brand<string, 'TenantId'>;<br/>Python: TenantId = NewType('TenantId', str)<br/>Java: record TenantId(String value) {}<br/>C#: readonly record struct TenantId(string Value);"
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
Domain functions must accept and return branded types rather than raw primitive strings or integers.
|
|
50
|
-
|
|
51
|
-
---
|
|
52
|
-
|
|
53
|
-
## 4. Strict Prohibition of Untyped Escape Hatches
|
|
54
|
-
|
|
55
|
-
- **Zero Tolerance for Unsound Types**: Strictly prohibit `any` in TypeScript, raw `interface{}` / `any` without type assertion checks in Go, raw `Any` in Python, or unchecked casts in Java/Rust/C#.
|
|
56
|
-
- **Runtime Validation at Boundaries**: External payloads (network requests, message queues, disk files) must be parsed and narrowed into strongly-typed domain structures before passing to application services (e.g. via Zod in TS, Pydantic in Python, Serde in Rust, Jackson/Record validation in Java).
|
|
57
|
-
- **Commit Guardrails**: Enforce Conventional Commits via commit linters. Never bypass pre-commit hooks running static type checking, formatting, and linters.
|
|
58
|
-
|
|
59
|
-
---
|
|
60
|
-
|
|
61
|
-
## 5. Clean Import Hygiene & Relative Traversal Elimination
|
|
62
|
-
|
|
63
|
-
- **Path Alias Mandate**: In languages supporting path aliases (TypeScript, Python packages, Go modules), configure root module resolution (e.g. `@/*` mapped to `./src/*`) to prevent brittle relative coupling.
|
|
64
|
-
- **Strict Prohibition of Deep Relative Traversal**: Never use deep relative traversals (`../../../..`, `../../..`, `../..`) across layers or contexts. Deep relative paths create fragile coupling, impair refactoring, and obscure domain layer boundaries.
|
|
65
|
-
- **Scope of Sibling Imports**: Local relative imports (`./file`) are permitted only for immediate siblings within the identical directory. Any import traversing up a directory hierarchy or crossing architectural boundaries (domain, ports, adapters, components, context) MUST resolve via root package paths or aliases.
|
|
1
|
+
# Static Type Safety & Sound Type Systems
|
|
2
|
+
|
|
3
|
+
> **Core Mandate:** Enforce maximum compiler strictness, branded nominal typing for domain identifiers, strict prohibition of untyped escape hatches, and automated pre-commit quality guardrails across polyglot implementations.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 1. The YAGNI Gate: Sound Types vs. Type-Level Acrobatics
|
|
8
|
+
|
|
9
|
+
Type systems exist to prove program correctness and eliminate entire classes of runtime errors. **Never compromise static type safety with `any` escape hatches, but avoid premature type-level metaprogramming acrobatics that obscure domain intent.**
|
|
10
|
+
|
|
11
|
+
```mermaid
|
|
12
|
+
flowchart TD
|
|
13
|
+
subgraph TypeSafetyGate["Type Safety YAGNI Gate"]
|
|
14
|
+
B1["1. Simple Baseline (Day 1)<br/>• Strict compiler flags enabled with zero compilation warnings<br/>• Concrete interfaces, records, dataclasses, and structs<br/>• Zero any, Any, or raw Object escape hatches"]
|
|
15
|
+
B2["2. Anti-Triggers (Forbidden)<br/>• Bypassing the compiler via any, as unknown as T, or casts<br/>• Deep recursive type-gymnastics where a simple interface solves it<br/>• Primitive Obsession: passing raw string for all domain IDs"]
|
|
16
|
+
B3["3. The Tipping Point (Graduation)<br/>• Domain Identifiers: Use Branded/Nominal types when multiple entity IDs risk mix-ups<br/>• System Boundaries: Use fail-fast schema validation (Zod, Serde, Pydantic) on untrusted inputs"]
|
|
17
|
+
B1 -->|Forbidden if compiler bypassed| B2
|
|
18
|
+
B1 -->|Triggered by domain safety & boundary parsing| B3
|
|
19
|
+
end
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## 2. Maximum Compiler Strictness Across Polyglot Stacks
|
|
25
|
+
|
|
26
|
+
Regardless of the execution language chosen for an adapter, service, or CLI, enforce maximum compiler rigor to eliminate runtime null pointer exceptions, unhandled type cases, and memory errors at compile time:
|
|
27
|
+
|
|
28
|
+
- **TypeScript**: Enable all strict compiler flags (`strict: true`, `noImplicitAny: true`, `strictNullChecks: true`, `noUncheckedIndexedAccess: true`).
|
|
29
|
+
- **Python**: Enforce strict type checking (`mypy --strict` or `pyright` in strict mode).
|
|
30
|
+
- **Rust**: Enable `#![deny(clippy::all)]` and `#![deny(missing_docs)]` with zero `unsafe` blocks.
|
|
31
|
+
- **Go**: Enable comprehensive static analysis (`golangci-lint` with `errcheck`, `govet`, `staticcheck`).
|
|
32
|
+
- **Java**: Enable `-Werror -Xlint:all`, enforce `@NonNull` contracts or the Checker Framework.
|
|
33
|
+
- **C#**: Enable `<Nullable>enable</Nullable>` and `<TreatWarningsAsErrors>true</TreatWarningsAsErrors>`.
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## 3. Branded Nominal Typing & Primitive Obsession Elimination
|
|
38
|
+
|
|
39
|
+
Prevent accidental mixing of raw primitive identifiers (e.g. passing an arbitrary `string` representing a `TenantId` where a `UserId` is expected) by enforcing nominal types across all supported languages:
|
|
40
|
+
|
|
41
|
+
```mermaid
|
|
42
|
+
classDiagram
|
|
43
|
+
class NominalIdentifierPattern {
|
|
44
|
+
<<Polyglot Implementations>>
|
|
45
|
+
}
|
|
46
|
+
note for NominalIdentifierPattern "Rust: struct TenantId(String); struct UserId(String);<br/>Go: type TenantId string; type UserId string<br/>TypeScript: type TenantId = Brand<string, 'TenantId'>;<br/>Python: TenantId = NewType('TenantId', str)<br/>Java: record TenantId(String value) {}<br/>C#: readonly record struct TenantId(string Value);"
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Domain functions must accept and return branded types rather than raw primitive strings or integers.
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## 4. Strict Prohibition of Untyped Escape Hatches
|
|
54
|
+
|
|
55
|
+
- **Zero Tolerance for Unsound Types**: Strictly prohibit `any` in TypeScript, raw `interface{}` / `any` without type assertion checks in Go, raw `Any` in Python, or unchecked casts in Java/Rust/C#.
|
|
56
|
+
- **Runtime Validation at Boundaries**: External payloads (network requests, message queues, disk files) must be parsed and narrowed into strongly-typed domain structures before passing to application services (e.g. via Zod in TS, Pydantic in Python, Serde in Rust, Jackson/Record validation in Java).
|
|
57
|
+
- **Commit Guardrails**: Enforce Conventional Commits via commit linters. Never bypass pre-commit hooks running static type checking, formatting, and linters.
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
## 5. Clean Import Hygiene & Relative Traversal Elimination
|
|
62
|
+
|
|
63
|
+
- **Path Alias Mandate**: In languages supporting path aliases (TypeScript, Python packages, Go modules), configure root module resolution (e.g. `@/*` mapped to `./src/*`) to prevent brittle relative coupling.
|
|
64
|
+
- **Strict Prohibition of Deep Relative Traversal**: Never use deep relative traversals (`../../../..`, `../../..`, `../..`) across layers or contexts. Deep relative paths create fragile coupling, impair refactoring, and obscure domain layer boundaries.
|
|
65
|
+
- **Scope of Sibling Imports**: Local relative imports (`./file`) are permitted only for immediate siblings within the identical directory. Any import traversing up a directory hierarchy or crossing architectural boundaries (domain, ports, adapters, components, context) MUST resolve via root package paths or aliases.
|