codebase-design

A preserved method from https://github.com/mattpocock/skills at 3cca18b368ae, path skills/engineering/codebase-design, MIT. 13 of 198 source lines differ (7%), every difference claimed by an entry of the ledger with its reason. Entries: baseline-copies-2026-09-11, pull-2026-09-11, fold-2026-09-11, series-s7-roster-2026-09-11.

  • harness 2
  • lifecycle 1
  • method 1
  • scope 1

Files

Every difference, as it stands

DEEPENING.md

# Deepening
# Deepening
 
 
How to deepen a cluster of shallow modules safely, given its dependencies. Assumes the vocabulary in [SKILL.md](SKILL.md): **module**, **interface**, **seam**, **adapter**.
How to deepen a cluster of shallow modules safely, given its dependencies. Assumes the vocabulary in [SKILL.md](SKILL.md): **module**, **interface**, **seam**, **adapter**.
27 unchanged lines
 
 
## Dependency categories
## Dependency categories
 
 
When assessing a candidate for deepening, classify its dependencies. The category determines how the deepened module is tested across its seam.
When assessing a candidate for deepening, classify its dependencies. The category determines how the deepened module is tested across its seam.
 
 
### 1. In-process
### 1. In-process
 
 
Pure computation, in-memory state, no I/O. Always deepenable: merge the modules and test through the new interface directly. No adapter needed.
Pure computation, in-memory state, no I/O. Always deepenable: merge the modules and test through the new interface directly. No adapter needed.
 
 
### 2. Local-substitutable
### 2. Local-substitutable
 
 
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.
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.
 
 
### 3. Remote but owned (Ports & Adapters)
### 3. Remote but owned (Ports & Adapters)
 
 
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.
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.
 
 
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."*
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."*
 
 
### 4. True external (Mock)
### 4. True external (Mock)
 
 
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.
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.
 
 
## Seam discipline
## Seam discipline
 
 
- **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.
- **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.
- **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.
- **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.
 
 
## Testing strategy: replace, don't layer
## Testing strategy: replace, don't layer
 
 
methodchangedseries-s7-roster-2026-09-11

upstream tells the deepener to delete old shallow-module tests once interface tests exist; greenline retains them through the deepening and routes deletion to sweep-tests with mutation proof, which changes the criterion (the D3 consumer finding of 2026-09-10, carried as a bookend override until this fold); the operator is asked to confirm this method edit in the S3 report Confirmed by the operator on 2026-09-11 (method-rulings.md).

- Old unit tests on shallow modules become waste once tests at the deepened module's interface exist; delete them.
- Old unit tests on shallow modules become candidates for examination once tests at the deepened module's interface exist, not proven waste: retain them through the deepening, and route their deletion, with the removal of any seam only they use, to sweep-tests in a dedicated ticket with its green baseline and before/after mutation proof. A deepening that cannot retain the existing protection reports that constraint before removing it; no unproven test deletion is part of this method. Carry this rule into any delegated deepening brief.
- Write new tests at the deepened module's interface. The **interface is the test surface**.
- Write new tests at the deepened module's interface. The **interface is the test surface**.
- Tests assert on observable outcomes through the interface, not internal state.
- Tests assert on observable outcomes through the interface, not internal state.
- 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.
- 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.

SKILL.md

---
---
harnesschangedbaseline-copies-2026-09-11

greenline renders its own frontmatter: quoted name and description, the description from the manifest override where one existed, no upstream activation flag

name: codebase-design
name: "codebase-design"
description: Shared vocabulary for designing deep modules. Use when the user wants to design or improve a module's interface, find deepening opportunities, decide where a seam goes, make code more testable or AI-navigable, or when another skill needs the deep-module vocabulary.
description: "Shared vocabulary for designing deep modules: a reference to consult mid-build, not a session to run. Use when designing or improving one module's interface, placing a seam, or making code testable; repo-wide surveys belong to improve-codebase-architecture."
---
---
 
 
# Codebase Design
# Codebase Design
 
 
scopechangedfold-2026-09-11

one opening paragraph in the skill's voice: a reference consulted mid-build on the agent's own judgment for one module's interface, a seam or testability, which tdd consults for its seam vocabulary; repo-wide surveys are improve-codebase-architecture's, test deletion is sweep-tests' dedicated ticket with mutation proof; never deletes a test, never announced or offered, not a session to run

This discipline is a reference to consult mid-build, on your own judgment, whenever one module's interface is being designed or improved, a seam placed, or code made testable; tdd consults it for the vocabulary of the seam it tests at. A repo-wide survey belongs to improve-codebase-architecture. Existing tests are retained through a deepening, and their deletion, with any seam only they use, belongs to sweep-tests in a dedicated ticket with its green baseline and before/after mutation proof; this skill never deletes a test, is never announced or offered, and is not a session to run.
 
Design **deep modules**: a lot of behaviour behind a small interface, placed at a clean seam, testable through that interface. Use this language and these principles wherever code is being designed or restructured. The aim is leverage for callers, locality for maintainers, and testability for everyone.
Design **deep modules**: a lot of behaviour behind a small interface, placed at a clean seam, testable through that interface. Use this language and these principles wherever code is being designed or restructured. The aim is leverage for callers, locality for maintainers, and testability for everyone.
 
 
## Glossary
## Glossary
99 unchanged lines
 
 
Use these terms exactly: don't substitute "component," "service," "API," or "boundary." Consistent language is the whole point.
Use these terms exactly: don't substitute "component," "service," "API," or "boundary." Consistent language is the whole point.
 
 
**Module**: anything with an interface and an implementation. Deliberately scale-agnostic: a function, class, package, or tier-spanning slice. _Avoid_: unit, component, service.
**Module**: anything with an interface and an implementation. Deliberately scale-agnostic: a function, class, package, or tier-spanning slice. _Avoid_: unit, component, service.
 
 
**Interface**: everything a caller must know to use the module correctly: the type signature, but also invariants, ordering constraints, error modes, required configuration, and performance characteristics. _Avoid_: API, signature (too narrow, they refer only to the type-level surface).
**Interface**: everything a caller must know to use the module correctly: the type signature, but also invariants, ordering constraints, error modes, required configuration, and performance characteristics. _Avoid_: API, signature (too narrow, they refer only to the type-level surface).
 
 
**Implementation**: what's inside a module, its body of code. Distinct from **Adapter**: a thing can be a small adapter with a large implementation (a Postgres repo) or a large adapter with a small implementation (an in-memory fake). Reach for "adapter" when the seam is the topic; "implementation" otherwise.
**Implementation**: what's inside a module, its body of code. Distinct from **Adapter**: a thing can be a small adapter with a large implementation (a Postgres repo) or a large adapter with a small implementation (an in-memory fake). Reach for "adapter" when the seam is the topic; "implementation" otherwise.
 
 
**Depth**: leverage at the interface. The amount of behaviour a caller (or test) can exercise per unit of interface they have to learn. A module is **deep** when a large amount of behaviour sits behind a small interface, **shallow** when the interface is nearly as complex as the implementation.
**Depth**: leverage at the interface. The amount of behaviour a caller (or test) can exercise per unit of interface they have to learn. A module is **deep** when a large amount of behaviour sits behind a small interface, **shallow** when the interface is nearly as complex as the implementation.
 
 
**Seam** _(Michael Feathers)_: a place where you can alter behaviour without editing in that place; the *location* at which a module's interface lives. Where to put the seam is its own design decision, distinct from what goes behind it. _Avoid_: boundary (overloaded with DDD's bounded context).
**Seam** _(Michael Feathers)_: a place where you can alter behaviour without editing in that place; the *location* at which a module's interface lives. Where to put the seam is its own design decision, distinct from what goes behind it. _Avoid_: boundary (overloaded with DDD's bounded context).
 
 
**Adapter**: a concrete thing that satisfies an interface at a seam. Describes *role* (what slot it fills), not substance (what's inside).
**Adapter**: a concrete thing that satisfies an interface at a seam. Describes *role* (what slot it fills), not substance (what's inside).
 
 
**Leverage**: what callers get from depth. More capability per unit of interface they learn. One implementation pays back across N call sites and M tests.
**Leverage**: what callers get from depth. More capability per unit of interface they learn. One implementation pays back across N call sites and M tests.
 
 
**Locality**: what maintainers get from depth. Change, bugs, knowledge, and verification concentrate in one place rather than spreading across callers. Fix once, fixed everywhere.
**Locality**: what maintainers get from depth. Change, bugs, knowledge, and verification concentrate in one place rather than spreading across callers. Fix once, fixed everywhere.
 
 
## Deep vs shallow
## Deep vs shallow
 
 
**Deep module** = small interface + lots of implementation:
**Deep module** = small interface + lots of implementation:
 
 
```
```
┌─────────────────────┐
┌─────────────────────┐
│ Small Interface │ ← Few methods, simple params
│ Small Interface │ ← Few methods, simple params
├─────────────────────┤
├─────────────────────┤
│ │
│ │
│ Deep Implementation│ ← Complex logic hidden
│ Deep Implementation│ ← Complex logic hidden
│ │
│ │
└─────────────────────┘
└─────────────────────┘
```
```
 
 
**Shallow module** = large interface + little implementation (avoid):
**Shallow module** = large interface + little implementation (avoid):
 
 
```
```
┌─────────────────────────────────┐
┌─────────────────────────────────┐
│ Large Interface │ ← Many methods, complex params
│ Large Interface │ ← Many methods, complex params
├─────────────────────────────────┤
├─────────────────────────────────┤
│ Thin Implementation │ ← Just passes through
│ Thin Implementation │ ← Just passes through
└─────────────────────────────────┘
└─────────────────────────────────┘
```
```
 
 
When designing an interface, ask:
When designing an interface, ask:
 
 
- Can I reduce the number of methods?
- Can I reduce the number of methods?
- Can I simplify the parameters?
- Can I simplify the parameters?
- Can I hide more complexity inside?
- Can I hide more complexity inside?
 
 
## Principles
## Principles
 
 
- **Depth is a property of the interface, not the implementation.** A deep module can be internally composed of small, mockable, swappable parts; they just aren't part of the interface. A module can have **internal seams** (private to its implementation, used by its own tests) as well as the **external seam** at its interface.
- **Depth is a property of the interface, not the implementation.** A deep module can be internally composed of small, mockable, swappable parts; they just aren't part of the interface. A module can have **internal seams** (private to its implementation, used by its own tests) as well as the **external seam** at its interface.
- **The deletion test.** Imagine deleting the module. If complexity vanishes, it was a pass-through. If complexity reappears across N callers, it was earning its keep.
- **The deletion test.** Imagine deleting the module. If complexity vanishes, it was a pass-through. If complexity reappears across N callers, it was earning its keep.
- **The interface is the test surface.** Callers and tests cross the same seam. If you want to test *past* the interface, the module is probably the wrong shape.
- **The interface is the test surface.** Callers and tests cross the same seam. If you want to test *past* the interface, the module is probably the wrong shape.
- **One adapter means a hypothetical seam. Two adapters means a real one.** Don't introduce a seam unless something actually varies across it.
- **One adapter means a hypothetical seam. Two adapters means a real one.** Don't introduce a seam unless something actually varies across it.
 
 
## Designing for testability
## Designing for testability
 
 
Good interfaces make testing natural:
Good interfaces make testing natural:
 
 
1. **Accept dependencies, don't create them.**
1. **Accept dependencies, don't create them.**
 
 
```typescript
```typescript
// Testable
// Testable
function processOrder(order, paymentGateway) {}
function processOrder(order, paymentGateway) {}
 
 
// Hard to test
// Hard to test
function processOrder(order) {
function processOrder(order) {
const gateway = new StripeGateway();
const gateway = new StripeGateway();
}
}
```
```
 
 
2. **Return results, don't produce side effects.**
2. **Return results, don't produce side effects.**
 
 
```typescript
```typescript
// Testable
// Testable
function calculateDiscount(cart): Discount {}
function calculateDiscount(cart): Discount {}
 
 
// Hard to test
// Hard to test
function applyDiscount(cart): void {
function applyDiscount(cart): void {
cart.total -= discount;
cart.total -= discount;
}
}
```
```
 
 
3. **Small surface area.** Fewer methods = fewer tests needed. Fewer params = simpler test setup.
3. **Small surface area.** Fewer methods = fewer tests needed. Fewer params = simpler test setup.
 
 
## Relationships
## Relationships
 
 
- A **Module** has exactly one **Interface** (the surface it presents to callers and tests).
- A **Module** has exactly one **Interface** (the surface it presents to callers and tests).
- **Depth** is a property of a **Module**, measured against its **Interface**.
- **Depth** is a property of a **Module**, measured against its **Interface**.
- A **Seam** is where a **Module**'s **Interface** lives.
- A **Seam** is where a **Module**'s **Interface** lives.
- An **Adapter** sits at a **Seam** and satisfies the **Interface**.
- An **Adapter** sits at a **Seam** and satisfies the **Interface**.
- **Depth** produces **Leverage** for callers and **Locality** for maintainers.
- **Depth** produces **Leverage** for callers and **Locality** for maintainers.
 
 
## Rejected framings
## Rejected framings
 
 
- **Depth as ratio of implementation-lines to interface-lines** (Ousterhout): rewards padding the implementation. We use depth-as-leverage instead.
- **Depth as ratio of implementation-lines to interface-lines** (Ousterhout): rewards padding the implementation. We use depth-as-leverage instead.
- **"Interface" as the TypeScript `interface` keyword or a class's public methods**: too narrow: interface here includes every fact a caller must know.
- **"Interface" as the TypeScript `interface` keyword or a class's public methods**: too narrow: interface here includes every fact a caller must know.
- **"Boundary"**: overloaded with DDD's bounded context. Say **seam** or **interface**.
- **"Boundary"**: overloaded with DDD's bounded context. Say **seam** or **interface**.
 
 
## Going deeper
## Going deeper
 
 
lifecyclechangedfold-2026-09-11

the SKILL.md pointer to DEEPENING.md names the retained tests and the sweep-tests route, matching the edited bullet

- **Deepening a cluster given its dependencies**, see [DEEPENING.md](DEEPENING.md): dependency categories, seam discipline, and replace-don't-layer testing.
- **Deepening a cluster given its dependencies**, see [DEEPENING.md](DEEPENING.md): dependency categories, seam discipline, and replace-don't-layer testing, with the old tests retained until sweep-tests proves their deletion.
- **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.
- **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.

agents/openai.yaml

harnessremoved filebaseline-copies-2026-09-11

the renderer generates agents/openai.yaml from the manifest; the vendored copy is not projected

interface:
display_name: "Codebase Design"
short_description: "Vocabulary for deep-module design"

The timeline

Each entry that touched this method, with the differences it claimed as they stood at its commit, read from the repository's history.

2026-09-11 baseline-copies-2026-09-11

the cutover to an edited copy (ADR 0039): the composed output written as the copy, every difference from upstream claimed with the reason of the overlay that produced it

SKILL.md

harnesschangedbaseline-copies-2026-09-11

greenline renders its own frontmatter: quoted name and description, the description from the manifest override where one existed, no upstream activation flag

name: codebase-design
name: "codebase-design"
description: Shared vocabulary for designing deep modules. Use when the user wants to design or improve a module's interface, find deepening opportunities, decide where a seam goes, make code more testable or AI-navigable, or when another skill needs the deep-module vocabulary.
description: "Shared vocabulary for designing deep modules: a reference to consult mid-build, not a session to run. Use when designing or improving one module's interface, placing a seam, or making code testable; repo-wide surveys belong to improve-codebase-architecture."
lifecyclechangedbaseline-copies-2026-09-11

greenline prelude, to fold: retain existing tests during a deepening; route deletions to sweep-tests in a dedicated ticket with mutation proof

**greenline prelude: deepening preserves test protection.** The first bullet
under DEEPENING.md's “Testing strategy: replace, don't layer” is superseded:
new interface tests make old tests candidates for examination, not proven waste.
Retain them during the deepening. Route proposed deletions and test-only seam
removal to sweep-tests in a dedicated ticket, with its green baseline and
before/after mutation proof. A deepening that cannot retain the existing
protection reports that constraint before removing it; no unproven test deletion
is part of this method. Carry this rule into any delegated deepening brief.
The interface, dependency categories, and design vocabulary below still govern.
 

agents/openai.yaml

harnessremoved filebaseline-copies-2026-09-11

the renderer generates agents/openai.yaml from the manifest; the vendored copy is not projected

interface:
display_name: "Codebase Design"
short_description: "Vocabulary for deep-module design"

2026-09-11 pull-2026-09-11

pin advance to 3cca18b: upstream moved with no change under the vendored paths

2026-09-11 fold-2026-09-11

the fold (ADR 0039, S3): the prelude is gone; the retention of existing tests through a deepening and the routing of their deletion to sweep-tests are stated in DEEPENING.md's own testing bullet and in the pointer to it; a discipline, so no Handoff section

DEEPENING.md

methodchangedfold-2026-09-11

upstream tells the deepener to delete old shallow-module tests once interface tests exist; greenline retains them through the deepening and routes deletion to sweep-tests with mutation proof, which changes the criterion (the D3 consumer finding of 2026-09-10, carried as a bookend override until this fold); the operator is asked to confirm this method edit in the S3 report

- Old unit tests on shallow modules become waste once tests at the deepened module's interface exist; delete them.
- Old unit tests on shallow modules become candidates for examination once tests at the deepened module's interface exist, not proven waste: retain them through the deepening, and route their deletion, with the removal of any seam only they use, to sweep-tests in a dedicated ticket with its green baseline and before/after mutation proof. A deepening that cannot retain the existing protection reports that constraint before removing it; no unproven test deletion is part of this method. Carry this rule into any delegated deepening brief.

SKILL.md

scopechangedfold-2026-09-11

one opening paragraph in the skill's voice: a reference consulted mid-build on the agent's own judgment for one module's interface, a seam or testability, which tdd consults for its seam vocabulary; repo-wide surveys are improve-codebase-architecture's, test deletion is sweep-tests' dedicated ticket with mutation proof; never deletes a test, never announced or offered, not a session to run

This discipline is a reference to consult mid-build, on your own judgment, whenever one module's interface is being designed or improved, a seam placed, or code made testable; tdd consults it for the vocabulary of the seam it tests at. A repo-wide survey belongs to improve-codebase-architecture. Existing tests are retained through a deepening, and their deletion, with any seam only they use, belongs to sweep-tests in a dedicated ticket with its green baseline and before/after mutation proof; this skill never deletes a test, is never announced or offered, and is not a session to run.
 
lifecyclechangedfold-2026-09-11

the SKILL.md pointer to DEEPENING.md names the retained tests and the sweep-tests route, matching the edited bullet

- **Deepening a cluster given its dependencies**, see [DEEPENING.md](DEEPENING.md): dependency categories, seam discipline, and replace-don't-layer testing.
- **Deepening a cluster given its dependencies**, see [DEEPENING.md](DEEPENING.md): dependency categories, seam discipline, and replace-don't-layer testing, with the old tests retained until sweep-tests proves their deletion.

2026-09-11 series-s7-roster-2026-09-11

The operator's ruling on the method-class edits put to them by the S3 fold: the edit is kept and re-recorded with the ruling as its authority.

DEEPENING.md

methodchangedseries-s7-roster-2026-09-11

upstream tells the deepener to delete old shallow-module tests once interface tests exist; greenline retains them through the deepening and routes deletion to sweep-tests with mutation proof, which changes the criterion (the D3 consumer finding of 2026-09-10, carried as a bookend override until this fold); the operator is asked to confirm this method edit in the S3 report Confirmed by the operator on 2026-09-11 (method-rulings.md).

- Old unit tests on shallow modules become waste once tests at the deepened module's interface exist; delete them.
- Old unit tests on shallow modules become candidates for examination once tests at the deepened module's interface exist, not proven waste: retain them through the deepening, and route their deletion, with the removal of any seam only they use, to sweep-tests in a dedicated ticket with its green baseline and before/after mutation proof. A deepening that cannot retain the existing protection reports that constraint before removing it; no unproven test deletion is part of this method. Carry this rule into any delegated deepening brief.