Skip to content

Code guidelines ​

What a change to this repository looks like. The lint, format, and check tooling is in Development.

Names ​

A name says what the thing does, so a reader does not open the body: functions are a verb over a domain noun (resolveOrgApiKey, seedOperator, materialiseScripts), types and tables are the domain noun (Repositories, artifact_collections), booleans read as a question (isReadOnlyRemote). Abbreviations are the domain's own (org, id, mcp) and nothing else. A name that needs a comment to be understood is the wrong name.

Functions ​

Functions are short and shallow. One function makes one kind of decision; a nested condition, a loop with a branch inside, or a second switch becomes a named function. Return early. A chain of ifs over a value is a lookup table. A function that takes a flag to do two things is two functions. The cyclomatic complexity of a function is a reason to split it before it is a reason to document it.

Scaffolding ​

One directory per feature, flat inside it. In the orchestrator each domain is a directory under src/ (schedules/, secrets/, recipes/), holding the files for that domain named for what they hold (service.ts, timing.ts, access.ts), and nothing deeper unless the domain has a sub-domain of its own. In the operator app each screen is a directory under src/features/. There is no utils/, helpers/, or common/: code two domains share goes in lib/ and says which two. HTTP stays thin in http/; the domain module owns the logic and the validation. A feature's tests are named for the feature.

Boundaries ​

A module reaches another through what that module exports, and a package through its exports list. Core imports nothing from an edition built on it, and eslint.boundary.js fails the file that tries. An edition attaches through the extension points, and a need it has that core lacks becomes an extension point with a core default, not a branch.

Types and validation ​

TypeScript is strict everywhere. Input is validated at the edge, once: TypeBox schemas on routes, a validation module per domain for what arrives from the operator or the model. Inside the domain the types are trusted and any does not appear.

Comments and documentation ​

A comment says why, not what; the code says what. Every page under docs/ describes what the code does today, in the present tense, with no history, roadmap, or record of a discussion. The one exception is the security register, which keeps the history of each issue. A change to behaviour updates the page that describes it in the same commit.

Commits ​

One change per commit. The message is one sentence in the imperative that states the outcome for the reader of git log, with a short body only when the why is not obvious. The pre-push hook runs the whole check on what is pushed.

Free software under the GNU Affero General Public License, version 3 only.