You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit 2889452
Browse filesBrowse the repository at this point in the historyBrowse files
Copy file name to clipboardExpand all lines: .agents/skills/codebase-design/DEEPENING.md
+10-9Lines changed: 10 additions & 9 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -12,26 +12,27 @@ Pure computation, in-memory state, no I/O. Always deepenable: merge the modules
12
12
13
13
### 2. Local-substitutable
14
14
15
-
Dependencies that have local test stand-ins (PGLite for Postgres, in-memory filesystem). Deepenable if the stand-in exists. The deepened module is tested with the stand-in running in the test suite. The seam is internal; no port at the module's external interface.
15
+
Dependencies you can run for real in a test: Postgres, Redis, the filesystem. Deepenable. The seam is internal; no port at the module's external interface. Verify the deepened module against the real dependency (a `*.integration.ts` suite on real Postgres/Redis) or end to end, never against a hand-built stand-in.
16
16
17
17
### 3. Remote but owned (Ports & Adapters)
18
18
19
-
Your own services across a network boundary (microservices, internal APIs). Define a **port** (interface) at the seam. The deep module owns the logic; the transport is injected as an **adapter**. Tests use an in-memory adapter. Production uses an HTTP/gRPC/queue adapter.
19
+
Your own services across a network boundary (microservices, internal APIs). Define a **port** (interface) at the seam. The deep module owns the logic; the transport is injected as an **adapter**. Production uses an HTTP/gRPC/queue adapter. Prove the module end to end over the real transport (`apps/sim/scripts/test-*-e2e.ts`) rather than through an in-memory adapter written only for tests.
20
20
21
-
Recommendation shape: *"Define a port at the seam, implement an HTTP adapter for production and an in-memory adapter for testing, so the logic sits in one deep module even though it's deployed across a network."*
21
+
Recommendation shape: *"Define a port at the seam and implement the production adapter there, so the logic sits in one deep module even though it's deployed across a network."*
22
22
23
23
### 4. True external (Mock)
24
24
25
-
Third-party services (Stripe, Twilio, etc.) you don't control. The deepened module takes the external dependency as an injected port; tests provide a mock adapter.
25
+
Third-party services (Stripe, Twilio, etc.) you don't control. The deepened module takes the external dependency as an injected port. Where an isolated test is unavoidable, use the shared mocks in `@sim/testing` and `apps/sim/vitest.setup.ts` rather than hand-rolling one.
26
26
27
27
## Seam discipline
28
28
29
-
-**One adapter means a hypothetical seam. Two adapters means a real one.** Don't introduce a port unless at least two adapters are justified (typically production + test). A single-adapter seam is just indirection.
29
+
-**One adapter means a hypothetical seam. Two adapters means a real one.** Don't introduce a port unless at least two adapters are justified. A single-adapter seam is just indirection.
30
30
-**Internal seams vs external seams.** A deep module can have internal seams (private to its implementation, used by its own tests) as well as the external seam at its interface. Don't expose internal seams through the interface just because tests use them.
31
31
32
32
## Testing strategy: replace, don't layer
33
33
34
-
- Old unit tests on shallow modules become waste once tests at the deepened module's interface exist; delete them.
35
-
- Write new tests at the deepened module's interface. The **interface is the test surface**.
36
-
- Tests assert on observable outcomes through the interface, not internal state.
37
-
- Tests should survive internal refactors, since they describe behaviour, not implementation. If a test has to change when the implementation changes, it's testing past the interface.
34
+
Testing follows the repo's rules in `CLAUDE.md` ("Testing") and the `test-audit` skill; this section only says how they apply to deepening.
35
+
36
+
- Old unit tests on shallow modules become waste once the deepened module exists; delete them. Deleting a test that only restated a pass-through is a win, not lost coverage.
37
+
- Don't write new unit tests at the deepened interface after the fact. Prove the change through the real boundary: a `*.integration.ts` suite on real Postgres/Redis, or an end-to-end run.
38
+
- Whatever tests remain assert on observable outcomes through the interface, not internal state. If a test has to change when the implementation changes, it's testing past the interface.
Copy file name to clipboardExpand all lines: .agents/skills/codebase-design/SKILL.md
+5-5Lines changed: 5 additions & 5 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -75,10 +75,10 @@ Good interfaces make testing natural:
75
75
76
76
```typescript
77
77
// Testable
78
-
function processOrder(order, paymentGateway) {}
78
+
function processOrder(order:Order, paymentGateway:PaymentGateway):Promise<Receipt> {}
79
79
80
80
// Hard to test
81
-
function processOrder(order) {
81
+
function processOrder(order:Order):Promise<Receipt> {
82
82
const gateway =newStripeGateway();
83
83
}
84
84
```
@@ -87,10 +87,10 @@ Good interfaces make testing natural:
87
87
88
88
```typescript
89
89
// Testable
90
-
function calculateDiscount(cart):Discount {}
90
+
function calculateDiscount(cart:Cart):Discount {}
91
91
92
92
// Hard to test
93
-
function applyDiscount(cart):void {
93
+
function applyDiscount(cart:Cart):void {
94
94
cart.total-=discount;
95
95
}
96
96
```
@@ -113,5 +113,5 @@ Good interfaces make testing natural:
113
113
114
114
## Going deeper
115
115
116
-
-**Deepening a cluster given its dependencies**, see [DEEPENING.md](DEEPENING.md): dependency categories, seam discipline, and replace-don't-layer testing.
116
+
-**Deepening a cluster given its dependencies**, see [DEEPENING.md](DEEPENING.md): dependency categories, seam discipline, and replace-don't-layer testing (which defers to `CLAUDE.md` "Testing" and the `test-audit` skill).
117
117
-**Exploring alternative interfaces**, see [DESIGN-IT-TWICE.md](DESIGN-IT-TWICE.md): spin up parallel sub-agents to design the interface several radically different ways, then compare on depth, locality, and seam placement.
0 commit comments