Enforcement mechanism for two 2026-07-16 monorepo-architecture-audit findings that could not be closed by a one-shot migration:
- R-11 (DRY / shared-lib adoption): the canonical platform layer exists
(
@oshun/logging,@oshun/database,@oshun/cache,@oshun/config), but hundreds of files predate it and re-implement or bypass it. Migrating them is per-domain feature work; what must not happen is the debt growing. - F-1 (test-file suffix): the workspace convention is colocated
*.spec.ts(the plurality at audit time). ~12.6k*.test.tsfiles are grandfathered; renaming them wholesale would churn thousands of vitest configs and diffs for no behavioral gain.
Mechanism#
tools/conventions/check-conventions-ratchet.mjs runs in the ci.yml quality
job. It compares the current tree against the committed baseline
(tools/conventions/conventions-ratchet-baseline.json):
| Rule | Kind | Fails when | Fix |
|---|---|---|---|
raw-pino-import |
file set | a file not in the baseline imports pino directly (outside libs/shared) |
import from @oshun/logging |
raw-pg-pool |
file set | a new file constructs new Pool( from pg |
use @oshun/database |
raw-ioredis-client |
file set | a new file constructs new Redis( from ioredis |
use @oshun/cache |
direct-process-env |
file set | a new production file reads process.env directly |
use @oshun/config (typed schema) |
local-circuit-breaker-class |
file set | a new file defines its own CircuitBreaker class |
use @oshun/resilience |
local-sleep-def |
file set | a new file defines its own sleep/delay |
use @oshun/resilience |
test-dot-test-suffix |
count | the tracked *.test.ts(x) count under libs/+apps/ grows |
name new test files *.spec.ts |
File-set rules are strict set-ratchets: a new file entering the set fails CI even if another file left it. Existing (grandfathered) files pass; migrating one off the raw dependency is always welcome.
Tightening#
When a change removes grandfathered occurrences, tighten the baseline in the same PR:
bash
node tools/conventions/check-conventions-ratchet.mjs --update-baseline
git add tools/conventions/conventions-ratchet-baseline.json
The checker prints a reminder whenever counts drop below the baseline.
Scope notes#
- Tests (
*.spec.ts,*.test.ts,__tests__/),*.config.ts, and e2e trees are excluded from the shared-lib rules — test doubles and config loaders at dependency boundaries are legitimate. libs/shared/**is excluded: the shared layer is where the raw dependencies are supposed to live.- Related policy:
docs/conventions/server-frameworks-and-deps.md(sanctioned frameworks and overlapping-dependency policy, audit R-17).