# Files and names

## One primary declaration per file

Each file holds one primary declaration, named after it:
`ServiceCredential` lives in `service_credential.jadpo`. Route groups and
libraries are named declarations, so the same rule covers them.

Supporting types, failures and helpers that only that file uses live in it
too. A declaration any other file uses, apart from the file's own tests,
has a file of its own named after it. So every name a `use` line brings in
is in `<folder>/<name>.jadpo` (see [Imports](imports.md)).

Everything in a file besides its primary declaration is used by the
primary declaration, directly or through one another. A declaration that
only the file's tests use, or that nothing uses, is dead code, reported as
`layout.unused_declaration`, as an unused shared declaration is. So a file
never collects helpers for something else. A declaration another file uses
is reported by `layout.promotion_required`, which moves it, not as unused.

The primary declaration is the one of the folder's kind named after the
file, or the first of that kind when the file is misnamed. In
`database/seeds/` it is the seed. Test files, root files and loose files
have no primary declaration, and a library's functions keep their own
rule: a function nothing calls is unused.

While the primary declaration, or one it uses, writes a name that names
nothing, perhaps a misspelling of the one it meant, nothing beside it is
called unused, as with imports.

## Order within a file

Definitions come before their use. After any opening comment and the `use`
lines, every declaration in a file comes before the first one that uses
it. So the primary declaration comes last, and you read it with the
constants and types it needs already in view.

When two declarations could go in either order:

- They go by kind: constants, then types, then failures, then helpers.
- Within a kind, they go in the order the primary declaration first
  reaches them. Reaching follows the primary's names in the order it first
  writes them, into each declaration before the next.
- Declarations that refer to each other keep their written order among
  themselves, and constants written together stay together.
- A declaration nothing reaches (reported as `layout.unused_declaration`)
  goes after the reached ones of its kind, in written order.
- A declaration still waits for what it uses, whatever its kind, so a
  constant of type `Stock` comes after `Stock`.

`jadpo fmt` writes this order, and `jadpo fmt --check` fails on a file out
of it. A file with no primary declaration (a test file, a root file, a
loose file) keeps its written order.

## Names are unique

A name must convert to its file name and back unchanged, so a name can't
have two capitals in a row: `VatRate`, not `VATRate`.

Names are unique across the whole project and across kinds, with one
exception. A private `function` or `type` needs a name unique only within
its domain, whether it has a file of its own or sits beside the
declaration that uses it. A private `constant` follows the same rule
([Constants](constants.md)). A failure or an email
(`type X = Failure` or `EmailMessage`) doesn't get the exception.

Everything else stays unique across the project:

- anything `public`, and anything in `shared/` or the root files;
- every other kind of declaration, whatever its visibility, since most
  have a name outside the code: entities (tables), failures (public error
  codes), events, actions, queries, routes, schedules, subscribers (stored
  deliveries and schedule state name them), services, fixtures and emails;
- a type an API's record names, private or not: a route's input or output,
  or a type reached through their fields, is an OpenAPI schema name;
- library names, which also qualify their functions (`rounding.half_even`).

A name unique across the project is unique against the per-domain ones
too. A private `Address` in `billing` clashes with a public or shared
`Address`, while two private `Address` types in `billing` and `shipping`
don't. Two names folding to one file name (`naming.folded_collision`)
follow the same scope. So a search for a name finds one file, or one file
per domain for a private function or type.

Domain, library and standard-library names are unique among themselves,
and local variables can't reuse them. Standard-library names are fixed per
language version, so a new standard namespace never breaks an existing
library.

A private name can be imported only inside its own domain, where it is
unique, and anything importable across domains is unique across the
project. So `import.missing` can always name the exact `use` line.

A domain is not a namespace: `Customer` means the same thing whichever
folder it appears in.

There is one exception to file names being unique. A type declared in the
same file as an action, query or function may fold to that callable's
name, as an input does: `type CreateTodo = Input` beside
`action create_todo` in `actions/create_todo.jadpo`. Only one file carries
the name. If the type is promoted to its own file, the rule applies again.

## When two names clash

A clash is `semantic.duplicate_declaration`. It says whether the two are a
copy (use the existing one, or move it to `shared/`) or two things with
one name (rename one). It never invents a name, and it lists the names in
use that contain the same word. `jadpo rename` refuses a new name already
in use before editing anything.

An agent working in parallel with others merges `main` before pushing,
runs `jadpo check` (it builds nothing, so it is quick), fixes any clash,
then pushes. Generated CI runs `jadpo check` first, so a clash fails in
seconds ([Tools for agents](tools-for-agents.md)).

## Tests and other files

Tests sit beside their subject as `<name>.test.jadpo`. Scenarios that span
several domains go in the root `tests/`. The kind of test (pure, action,
route, schedule) is known from what it calls, so it isn't a folder;
`jadpo test --kind route` runs one kind.

Files that aren't Jadpo (provider contracts, email templates, search
mappings) sit beside the file that uses them, and that file must refer to
them.

Not built yet: `jadpo rename`.
