Skip to main content
This page is the operating form of ADR 0006 (naming, exports, imports) and ADR 0007 (documentation). Formatting is not a style question: oxfmt formats and oxlint lints, and both run in pnpm verify.

Naming

No speculative directories: utils/, helpers/ and services/ exist because something real lives in them. A helper used by a second file moves to utils/<name>.util.ts; a single-use private helper stays where it is used.

One declaration per file

Every exported declaration lives in its own file, named for it. Where the kind is not a plain function, the file carries a kind suffix:
  • index.ts is the only barrel name. A barrel declares nothing and names each symbol (export type { Token } from "./token.class"), never export *.
  • A folder is created for one artifact only when it has two or more non-test files.
  • Scaffolded templates are the reference: tools/scaffold/templates/packages/package/src.
  • A reviewer treats a file with two exported declarations, or a barrel that declares, as a finding. Changes to these conventions go through an ADR; there are no package-local exceptions.

Imports

The decorators preset turns consistent-type-imports off because decorator metadata needs value imports (ADR 0005).

File contract

Every source and configuration file opens with a header before its imports. Plain JSON has no comments and is documented by its nearest README. Source files (.ts, .tsx), per ADR 0007:
Configuration and tooling files (pnpm-workspace.yaml, turbo.jsonc, lefthook.yml, preset configs) use the header the repository already carries, in their own comment syntax (#, //):

TSDoc

Types carry the weight first: no any, generics have meaningful names, an exported type is its own documentation. Every exported symbol then gets TSDoc that says something the type does not.
Interfaces and types say what they represent and who produces and consumes them; each property says its meaning, unit or format, and who sets it. Boilerplate is a finding: a comment that restates the signature teaches readers to skip comments.

Comments in code

Explain why, not what the next line says. Required before a workaround, a security-relevant check, a deliberate deviation and a non-obvious ordering. Forbidden: restating comments, commented-out code, and a TODO without an owner and a tracking reference.

Tests

A test file’s header says what the suite proves. Each it() title is a full sentence stating behaviour, not the function name.

Typed errors

A package never lets a raw Error escape a public function. Every error it throws is a class under errors/ with:
  • a stable, unique code (a string literal in the class);
  • a message that names the offending thing (the token, driver or id involved);
  • an optional hint saying what to do;
  • structural fields, never embedded secrets or values.
A rejected promise or listener failure is reported through the package’s logger port, never swallowed. At an HTTP boundary a typed error maps to a framework error with a stable message; see HTTP and events.

What enforces this

The planned code-standards-steward splits, renames and moves files to meet the naming and barrel rules without changing behaviour; see the agent roster.