# Sharing and promotion

A type, failure or helper used by one file lives in that file. When a
second file needs it, it moves to a file of its own, a step called
promotion:

- When a second file in the same domain uses it, it moves to the domain's
  `types/`, `failures/` or `libraries/`.
- When a second domain uses it, it moves to `shared/`. Only pure types,
  failures, libraries and messages go there; a message moves to
  `shared/translations/`.

Moving to the right folder isn't enough: the file must be named after the
declaration. `DiscountCode` in `types/basket.jadpo`, used by another file,
must move to `types/discount_code.jadpo`.

Tests never count as users. A route counts only when nothing else uses the
type, and a failure counts where it is raised.

A constant ([Constants](constants.md)) is placed as a helper
function is. Used by one file, it sits at the top of that file, never as a
primary declaration. Used by a second, it moves into a library and is read
through it, as in `pricing.vat_rate`, so a library holds functions and
constants.

## What `shared/` holds besides

- `shared/emails/` holds only the app's optional email layout,
  `layout.html` and `layout.txt`, and the email partials every domain's
  emails may include, each a `type X = EmailPartial` with its templates
  beside it ([Email](email.md)).
- `shared/documents/` holds only the app's optional document layout,
  `layout.html`.
- `shared/providers/` holds the app's own integrations, each in
  `shared/providers/<name>/<version>/`, in exactly the package format
  ([The package format](the-package-format.md)). They
  aren't promoted there: they are written there from the start.

## How a promotion happens

Promotion is required. The compiler reports it as
`layout.promotion_required` with a one-step fix, applied through the
editor or `jadpo fmt --layout`, never silently on save.

Demotion is never forced. A promoted declaration stays where it is until
nothing uses it, when it becomes a dead-code error. So code doesn't move
back and forth, `git blame` keeps working and moves don't cause merge
conflicts.

Promotion is a move, not a rewrite. The library keeps its name, so calls
such as `rounding.half_even(x)` and the function's text stay identical,
and behaviour can't change.

Promoting a private function or type to `shared/` makes its name unique
across the project, so a private one of the same name in another domain
then clashes, as `semantic.duplicate_declaration`.

The move is also recorded in the identity registry,
`database/identities.jadpo_record`: the committed file that gives every
table, column and declaration a lasting identity, so a rename reads as a
rename ([Stable identity](stable-identity.md)). The
identity key of a function or type declared in a domain includes the
domain, so the move writes one line there, and it reads as a move, not as
a removal and an addition. `layout.promotion_required`'s edits for a type
moving to `shared/types/` add that line, so `jadpo fmt --layout` writes it.
A failure raised by a second domain gets no edit, so moving it by hand
writes no line. A library keeps its name in `shared/`, so its functions'
keys need none.

## Helpers that depend on a domain

A helper that depends on one domain's types (`order_math.total(order)`)
stays in that domain, and becomes public when another domain calls it. A
helper that depends on two domains' types is an error that needs a design
decision. Making a helper generic, for example extracting
`pricing.sum(amounts)` for `ordering` and `payments` to share, is a
deliberate refactor.

## Finding the helper that already exists

Two constants of the same type holding the same value are the declinable
`constant.similar_exists`, so parallel agents each inventing `vat_rate`
find each other's ([Constants](constants.md)).

Duplicate helpers are caught as they are written. When a new helper looks
like an existing one, `jadpo check` says so and names it ("a similar
library exists: `rounding.half_even` in
`shared/libraries/rounding.jadpo`"). The compiler also generates a
catalogue of every library function, with its signature, documentation
comment and callers, and the Jadpo agent skill tells agents to consult it
before writing a helper. Agents look things up in the compiler's project
map, the language server, rather than browsing folders.

Placement alone can't prevent two copies: two domains may each hold a
private helper with the same name.

A function's description is written once, as a `///` comment above it. The
catalogue, the list of callers and the domains that use it are computed
and shown in the editor, never written into source files.

## Seeing a change's reach

Before shared or public code changes, its reach shows in three ways:
find-references in the editor; a `jadpo impact <name>` command listing the
calling domains, the entry points and the tests that cover it; and
`jadpo check` itself, which reports the domains a change affects and runs
their tests.

Not built yet: `jadpo impact`.
