# M — Modeled > **Rule:** tests live next to source. Types and parse-functions live in `c31_*`. The shape comes before the logic. The third letter of SAMA. Where *Sorted* and *Architecture* tell the agent *where files go*, *Modeled* tells it *what those files contain*. Two concrete commitments: 1. Every behaviour has a test file as its sibling — `c32_session.ts` next to `c32_session.test.ts`. 2. Every external input has a parser in a `c31_*` model — types and parse-functions colocated, not scattered. The shape of the data and the proof of the behaviour are first-class artefacts, never afterthoughts. ## Tests next to source Not in a separate `tests/` tree. Not in a parallel `__tests__` folder. The test for `c32_session.ts` is `c32_session.test.ts` in the same directory. ``` src/ ├── c32_session.ts ← impl ├── c32_session.test.ts ← its sibling test ├── c32_judge.ts └── c32_judge.test.ts ``` Why this matters for an agent: - When you `ls src/c32_session.*`, you see *both* the impl and its proof. - When you delete the impl, the test goes too — no orphan test files to chase. - When you start a TDD red commit, the test file is already next to where the impl will land — no path-juggling. - Coverage is a glance, not a tool: any `cXX_*.ts` without a sibling `*.test.ts` is unproven. The tooling agrees: `bun test` discovers `*.test.ts` automatically with no path config. ## Parsers live in c31 Anything that comes in from outside the process — JSON files, request bodies, environment variables, third-party API responses — gets a parser in `c31_*` *before* any logic touches it. The parser: - Defines the type (the shape). - Validates the input. - Throws a clear error on bad input. ```ts // src/c31_project_config.ts export interface ProjectConfig { test_runner: TestRunner; tracked_branches: string[]; // ... } export const parseProjectConfig = (raw: unknown): ProjectConfig => { // explicit shape check, then return a typed value }; ``` The rest of the codebase consumes `ProjectConfig`, never `unknown` and never `any`. By the time data leaves `c31_*`, it has a name and a shape that the type system can carry the rest of the way. ## "The shape comes before the logic" The order in which an agent should approach a feature: 1. What's the input shape? → `c31_*` type + parser. 2. What's the behaviour? → red test in the test file. 3. What's the impl? → just enough to pass the test. Not the other way around. Writing the impl first lets you smuggle assumptions about the input ("oh, this field is always a number") into code that should have refused to start without an explicit type. The discipline lines up with TDD's iron law: *no code without a failing test first*. SAMA adds: *no test without a typed input first*. Together they force you to write down what the world looks like before you write down what to do with it. ## Examples **Good** — type + parser + sibling test: ``` src/ ├── c31_project_config.ts type + parseProjectConfig ├── c31_project_config.test.ts parser-edge-case tests ├── c32_judge.ts logic that consumes ProjectConfig └── c32_judge.test.ts judge-behaviour tests ``` **Bad** — type defined inline at point of use: ```ts // src/c21_handlers_projects.ts const config = await req.json() as { test_runner: string; ... }; // ↑ no parser, no validation, type lies ``` The fix: move the type to `c31_project_config.ts`, write a `parseProjectConfig` that validates, call it in the handler. The shape and its proof are now in one place; every consumer benefits. ## Common mistakes - **Tests in a parallel tree.** Breaks the "delete the impl, test goes too" property. Move them next to source. - **`as` casts at I/O boundaries.** A cast is a lie the type system promises not to question. Replace casts with parsers in `c31_*`. - **Inline `interface` in handlers / logic.** If two files use the same shape, it belongs in `c31_*`, not duplicated at each consumer. - **A test file with no sibling impl.** The test is for something that no longer exists, or the impl drifted to another file. Either reattach it or delete it. ## What this gives you - An agent given the path `c32_session.ts` can find the contract (sibling test) and the input shape (`c31_*` type) without searching. - The boundary between the typed inside and the untyped outside is one file (`c31_*`) per concern, not a scatter of `as` casts. - "What does this code do?" is answered by the test next to it, every time. --- [← A — Architecture](/sama/discipline/architecture) · [/sama](/sama) · [next: A — Atomic →](/sama/discipline/atomic)