Sharing and promotion
On this page
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/orlibraries/. - When a second domain uses it, it moves to
shared/. Only pure types, failures, libraries and messages go there; a message moves toshared/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) 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.htmlandlayout.txt, and the email partials every domain's emails may include, each atype X = EmailPartialwith its templates beside it (Email).shared/documents/holds only the app's optional document layout,layout.html.shared/providers/holds the app's own integrations, each inshared/providers/<name>/<version>/, in exactly the package format (The package format). 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). 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).
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.
Markdown for agents: /docs/sharing-and-promotion.md.Built from Jadpo main at a707efb.