Skip to content
DocumentationDomains & traits
On this page

Page resources

Open Markdownllms.txtView source

Last updated

Domains and traits

A semantic domain is a complete bounded language over One's fixed structural source format. It owns its vocabulary, rules, defaults, compatibility, normalization, and contributions to downstream owners. One-owned and organization-owned domains use the same contracts and lifecycle.

Foundation, inheritance, and composition

Every domain has exactly one compatibility lineage rooted at one.semantic@1. extends inherits one complete language; use composes any number of additional packages without making them compatibility parents.

one 1

semantic acme.process.language
    domain one.semantic.domain@1

    domain Process@1
        extends one.semantic@1
        use one.identity@1 only Principal, TenantId
        use one.data@1 only Key, Scope
        use acme.audit.Audited@1

        kind Entity
            exposes StableIdentity

        kind Transition
            exposes StateChange

Use extends one.product@1 when the domain intentionally inherits the full product language. Extend one.semantic@1 and import narrow packages when it does not. There is no multiple inheritance or source-order conflict winner.

one.standard@1 is an optional explicit aggregation package, not an ambient prelude. A domain export preserves the original owner of every imported type, trait, unit, capability, and declaration kind.

Define a trait

Trait packages use the one.trait@1 meta-domain. A trait definition owns:

  • its owner-qualified identity and compatibility lane;
  • the broad application-site category it may refine;
  • typed arguments, defaults, bounds, conflicts, and repetition rules;
  • semantic laws, normalization, and compatibility effects;
  • required capabilities or prerequisite traits;
  • possible owner contribution contracts; and
  • documentation, diagnostics, formatting, and conformance obligations.

A broad category is only an upper bound. Declaring Key as a field trait does not make it applicable to every field.

Implement applicability coherently

Inside a domain definition, impl associates an already defined trait with an exact bounded subject pattern:

impl Key
    for Entity@1.field<T>
    where T implements StableKeyValue
    normalize_with: ProcessTraitNormalizer

This is distinct from a top-level executable impl: the leading for marks a semantic trait implementation, while an executable claim uses realizes and using.

A package may publish a globally coherent implementation only when it owns the trait or the target nominal type/declaration kind. A package owning neither side publishes an explicit directional mapping that remains inert until one root selects it. Overlapping implementations fail unless their subject sets are provably disjoint; import order and “most specific” guesses never choose a winner.

Apply traits after the subject exists

Postfix traits refine a completed type, field, member, declaration, operation, environment, or evidence subject:

type UserName@1 = Text @Length(1..=128)
type Percentage@1 = Decimal @Value(0..=100)

record Upload@1
    tenant: TenantId @Scope
    id: Text @Length(1..=64) @Key
    chunks: List<Bytes> @Cardinality(1..=10_000)
    total_size: DataSize @Value(1B..=5GiB)
    @Invariant(total_size == sum(chunks[*].length))

A field trait follows the field type. A declaration-wide invariant appears after every member it references. Trait applications form a canonical set, not an order-sensitive decorator pipeline.

Use precise traits: numeric value, text length, and collection cardinality are different meanings. @Value, @Length, and @Cardinality are not aliases for one generic range annotation.

Every bare @Key field contributes to one logical primary key. Multiple key fields form a canonical composite identity without choosing physical index order. @Unique(name) represents an independent candidate key. @Scope identifies logical subject scope; it does not create a partition or grant.

Resolution and normalization

Strict checking:

  1. resolves the trait through the primary domain or prior import;
  2. constructs the exact completed subject descriptor;
  3. finds matching implementations in the selected package closure;
  4. rejects zero matches or non-identical multiple matches;
  5. validates arguments, prerequisites, conflicts, and repetition;
  6. runs the exact declarative rule or capability-empty normalizer;
  7. asks every destination owner to validate proposed contributions; and
  8. retains a receipt naming every definition, implementation, input, proof, contribution, and revision.

A custom normalizer receives only the bounded subject, arguments, exact package dependencies, and deterministic budget. It has no filesystem, network, clock, entropy, credentials, source-write access, provider selection, or authority, and it cannot mint trusted IR.

Unknown traits, unsupported subjects, ambiguity, invalid arguments, normalizer failure, and rejected owner contributions are semantic errors. Tooling retains and explains the source; it never discards a trait as metadata.

Publish and consume a domain

The domain follows the ordinary lifecycle: check its schema and closure, build or select its normalizer, run domain and trait conformance, publish the exact package and evidence, lock it in a consumer, then select it as that semantic item's primary domain.

Publishing proves no application behavior and activates no consumer. The lock selects exact package, export, trait implementation, normalizer, definition, and compatibility revisions.

Next: author a product or follow define a semantic domain.