Skip to content

Commit 2889452

Browse files
committed
docs(skills): align codebase-design testing guidance with repo rules and add its license
1 parent c3aceb6 commit 2889452

3 files changed

Lines changed: 36 additions & 14 deletions

File tree

‎.agents/skills/codebase-design/DEEPENING.md‎

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,26 +12,27 @@ Pure computation, in-memory state, no I/O. Always deepenable: merge the modules
1212

1313
### 2. Local-substitutable
1414

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.
1616

1717
### 3. Remote but owned (Ports & Adapters)
1818

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.
2020

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."*
2222

2323
### 4. True external (Mock)
2424

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.
2626

2727
## Seam discipline
2828

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.
3030
- **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.
3131

3232
## Testing strategy: replace, don't layer
3333

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.
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2026 Matt Pocock
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

‎.agents/skills/codebase-design/SKILL.md‎

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -75,10 +75,10 @@ Good interfaces make testing natural:
7575

7676
```typescript
7777
// Testable
78-
function processOrder(order, paymentGateway) {}
78+
function processOrder(order: Order, paymentGateway: PaymentGateway): Promise<Receipt> {}
7979

8080
// Hard to test
81-
function processOrder(order) {
81+
function processOrder(order: Order): Promise<Receipt> {
8282
const gateway = new StripeGateway();
8383
}
8484
```
@@ -87,10 +87,10 @@ Good interfaces make testing natural:
8787

8888
```typescript
8989
// Testable
90-
function calculateDiscount(cart): Discount {}
90+
function calculateDiscount(cart: Cart): Discount {}
9191

9292
// Hard to test
93-
function applyDiscount(cart): void {
93+
function applyDiscount(cart: Cart): void {
9494
cart.total -= discount;
9595
}
9696
```
@@ -113,5 +113,5 @@ Good interfaces make testing natural:
113113

114114
## Going deeper
115115

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).
117117
- **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

Comments
 (0)