sorted.md
raw
· source
S — Sorted
Rule: alphabetical sort = dependency direction. UI sits at the edge — foundation, data and logic layers (
c1*,c3*) never depend on UI (c5*+). Handlers (c21) are the orchestration layer and may import anything.
The first property of SAMA. Run ls src/ and you have the architecture diagram. There is no separate "where does the data flow?" document because the file system answers it.
Why
Two reasons:
- An agent can navigate by
ls. No need to read aREADMEto know thatc14_github.tsis lower thanc21_app.ts. The prefix is the layer; the layer is the import contract. - The rule is mechanically verifiable. A grep proves it or refutes it in one second. There is no judgement call about "is this dependency OK?" — the only question is whether the prefix on the left is lower than the prefix on the right.
The verification command
Run this from the repo root:
grep -rE 'from "\./c[5-9]' src/c1*.ts src/c3*.ts
If the output is empty, the rule holds. If anything appears, you have a UI dependency leaking into a foundation, data or logic layer — fix the import or move the file. (Note: c2* files are intentionally excluded — handlers compose UI calls, so c21 → c51 is the normal pattern.)
This is the single load-bearing test for the Sorted property. Wire it into CI and forget about it.
Examples
Allowed — lower importing higher? Never. Higher importing lower? Always:
// src/c21_app.ts (handler layer — c21)
import { fetchUser } from "./c14_github.ts"; // c14 < c21 ✓
import { parseCommit } from "./c31_commits.ts"; // c31 > c21 — wrong direction!
Wait — c31 is higher than c21, so this would be backwards. Let me restate the example correctly:
// src/c21_app.ts
import { fetchUser } from "./c14_github.ts"; // c14 < c21 ✓ (handler uses I/O)
import { parseCommit } from "./c31_commits.ts"; // c31 > c21 — this is fine,
// c21 (handler) consumes c31 (model)
The rule is lower numbers never import higher numbers. So c14 (I/O) cannot import c21 (handler) — that would be a leaf importing the trunk. c21 importing c31 is fine because c21 (handler) is meant to compose models from c31.
Forbidden:
// src/c14_github.ts (I/O layer — c14)
import { renderPage } from "./c51_render_layout.ts"; // c51 < c14? NO — c51 > c14, but
// wait, the rule is
// "lower never imports higher",
// and c14 < c51, so importing
// c51 from c14 is forbidden.
Plain reading of the rule: a file at level n may only import from levels < n. The grep above checks the most common violation (1- and 2- and 3-prefixed files reaching into 5+).
Common mistakes
- Putting "shared utilities" in a top-level file with no prefix. The prefix isn't optional. If a helper is used across layers, it belongs in the lowest layer that all callers can reach — usually
c31_*(pure models) or a layer-appropriate_layout/_helpersfile (e.g.c51_render_layout.ts). - Re-exporting from a "barrel" file. Defeats the grep. Every module imports directly from the source file.
- Treating tests as "outside the rule". Tests are part of the layer they test.
c32_session.test.tsis itselfc32and follows the same import constraints.
What this gives you
A file tree where:
ls src/is the dependency graph, sorted top-to-bottom.- The agent can answer "where does X live?" in one prefix-letter.
- Layer violations are caught by
grep, not by reviewers' memory.