| name | codebase-design |
| description | Shared vocabulary for designing deep modules and for naming factory concepts consistently. Load before writing a spec, decomposing issues, freezing checks, or reviewing a diff - anywhere "module," "interface," "issue," or "frozen check" need to mean the same thing to every skill, builder, and reviewer. Also covers dependency categories for deepening and the parallel design-it-twice pattern for exploring interfaces before committing to one.
|
Codebase Design
Design deep modules: a lot of behavior behind a small interface, placed
at a clean seam, testable through that interface. Use this language wherever
code or a factory issue is being designed. The aim is leverage for callers,
locality for maintainers, and testability for everyone.
Glossary
Use these terms exactly — don't substitute component, service, boundary, or API
when you mean module or interface; don't say task or ticket for issue, or test
file for frozen check. Consistent language is the whole point.
Design (Pocock, adapted):
- Module - anything with an interface and an implementation, at any scale: a function, a package, or a whole vertical slice.
- Interface - everything a caller must know to use a module correctly: types, invariants, ordering, error modes, config, performance - not just a signature.
- Implementation - the body of code behind the interface; distinct from adapter, which names role at a seam, not substance.
- Depth - leverage at the interface: behavior reached per unit of interface learned. Deep means a small interface over a big implementation; shallow is the opposite, and to avoid.
- Seam (Feathers) - the place a module's interface lives; where behavior can change without editing there.
- Adapter - a concrete thing satisfying an interface at a seam. One adapter is a hypothetical seam; two make it real.
- Leverage - what callers get from depth: one implementation pays off across many call sites and tests.
- Locality - what maintainers get from depth: change and bugs concentrate in one place instead of spreading.
Factory (one line each; matches docs/spec/skill-library.md Target flow):
- Run - one factory build from intake to the closing PR, on its own factory branch.
- Tracking issue - the run's parent issue: dashboard, digest, preflight record.
- Issue - one vertical-slice unit of work: one builder job, one disjoint file set, one change-skeleton.
- Slice - the vertical cut an issue implements; slice names the cut, issue names its tracker record - same unit, two angles.
- Frozen check - the committed, read-only acceptance check a builder's work is graded against.
- Check-runner - the deterministic script that grades a frozen check's RUN items and exits typed (0/2/5).
- Strategist - the fresh high-judgment subagent that drafts specs, cuts issues, stress-tests plans, and runs full-lane reviews.
- Builder - the fresh, worktree-isolated agent that implements one issue and never commits.
- Orchestrator - the one session that grounds, dispatches strategist and builder work, freezes, and integrates; never writes implementation code; in the fast lane (/architect-fast) it also runs the closing test pass whose output feeds the builder review - a recorded relaxation.
- Factory branch - the run's integration branch (
factory/<run>) that job branches merge into.
- Worktree - the isolated git checkout a builder or reviewer works in, verified against the freeze commit.
- Job report - a builder's raw-evidence artifact, ending in one STATUS line.
- Verdict - the grading record posted on an issue at close: checkrun summary plus typed exit, postflight result, slice call, decisive reason; the closing review's run-level verdict goes on the tracking issue.
- Ruling - an orchestrator decision recorded post-freeze: a PHASE-0 execution conflict, boundary amendment, or respawn answer.
- Digest - the shipped-issues, diffstat, rulings, and domain-language summary handed to the integrate subagent's docs pass.
- Hard stop - an irreversible or destructive action the loop refuses without a human ruling.
Deep vs. shallow
A deep module hides a lot of implementation behind a small interface: few
methods, simple params, most of the complexity out of sight. A shallow
module is the opposite - an interface almost as complex as what it wraps,
often a near-passthrough. When shaping an interface, ask whether the
method count and params can shrink, and whether more logic can move inside.
Principles
- Depth is a property of the interface, not the implementation - a deep
module can be built from small internal seams its own tests use, without
exposing them at the external interface.
- The deletion test: imagine deleting the module. If complexity vanishes,
it was a pass-through; if it 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.
- 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
- Accept dependencies, don't create them - a function that takes its
gateway is testable; one that builds a
StripeGateway() internally is not.
- Return results, don't produce side effects - a function that returns a
computed discount is testable; one that mutates a cart in place is not.
- Small surface area: fewer methods = fewer tests needed; fewer params =
simpler test setup.
Going deeper
- Deepening a cluster given its dependencies - see
DEEPENING.md:
dependency categories, seam discipline, and replace-don't-layer testing.
- Exploring alternative interfaces - see
DESIGN-IT-TWICE.md: dispatch
parallel subagents to design the interface several radically different
ways, then compare on depth, locality, and seam placement.