ontoref-code/ontology/schemas/bond.ncl
2026-07-18 00:57:58 +01:00

128 lines
7.1 KiB
Text

# bond.ncl — contract for the ontoref BOND: a typed relation between projects
# (and their domains), distinct from a `link` (the generic `ln`/Link node
# reference). Frozen semantics live in .ontoref/ontology/glossary.ncl
# (terms: bond, ontoref-node, ontoref-plane); this file types them.
#
# Session 2026-07-17 (rustelo instantiation map + domain-model brief).
# Frame is native ontoref (nodes/edges/axes/planes). DDD Context-Map is borrowed
# ONLY as the dependency-edge type enum; Hexagonal only intra-domain.
#
# ondaod:
# - formalization-vs-adoption — the type is formal; membership cardinality is
# UNCAPPED and a bond is declarable WITHOUT ontoref managing the project (the
# carrier BondSet lives in .domains-ontoref/<domain>/, orthogonal to the
# manifest's scalar repo_kind).
# - enforcement-vs-emergence — `dep_kind` seeds the 6 DDD kinds already witnessed;
# the protocol supplies the mechanism, never the number. No cardinality cap.
# - ontology-vs-reflection — the TYPES live here (ontology); the `bond` verb,
# forms and FSM execution live in reflection. `linkage_transitions` is the
# canonical data the verb consults, not behaviour.
# - plane-habitability — the mutual/Partnership dependency bond IS a habitable
# plane (a 2-cycle), never a hierarchy. The `mutual` flag marks it.
# ── Axis ─────────────────────────────────────────────────────────────────────
# Governance = the project is an ontoref-node in a domain's DAG (acyclic).
# Dependency = the project inhabits an ontoref-plane with peer nodes (cycles OK).
let bond_axis_type = [| 'Governance, 'Dependency |] in
# ── Dependency edge kind — DDD Context-Map (applies when axis = 'Dependency) ──
# Seeded with the 6 kinds witnessed in the constellation; the enum grows by
# evidence (enforcement-vs-emergence), never by speculation.
let dep_kind_type = [|
'CustomerSupplier,
'Partnership,
'OpenHostService,
'Conformist,
'SharedKernel,
'AnticorruptionLayer,
|] in
# ── Governance resolution (applies when axis = 'Governance) ───────────────────
# How a domain (level N) resolves against its governed nodes (level N+1).
# ADR-018 (level hierarchy + mode resolution), ADR-045 (recursive level chains).
let resolution_type = [| 'Delegate, 'Override, 'Compose |] in
# ── Linkage state — the FSM a bonded project moves through ────────────────────
# 'None — not bonded (default).
# 'Linked — bonded on the DEPENDENCY axis (inhabits a plane; see `plane`).
# 'Node — bonded on the GOVERNANCE axis (a governed node in a domain's DAG).
# 'Managed — ontoref governs the project's development (full project management).
# The `linked(plane)` case of the brief = state 'Linked + a populated `plane`
# field (bare-tag enums carry no payload — matches core.ncl style).
let linkage_state_type = [| 'None, 'Linked, 'Node, 'Managed |] in
let linkage_transition_type = [| 'Onboard, 'Offboard, 'Update |] in
let linkage_transition = {
from | linkage_state_type,
via | linkage_transition_type,
to | linkage_state_type,
note | String | default = "",
} in
# Canonical FSM the `bond init|update|drop` verb consults (data, not behaviour).
# Onboard climbs (None→Linked/Node→Managed); Update is a self-loop (retype the
# same-tier bond); Offboard descends (Managed→Node, then →None).
let default_linkage_transitions | Array linkage_transition = [
{ from = 'None, via = 'Onboard, to = 'Linked, note = "declare a dependency bond — inhabit a plane" },
{ from = 'None, via = 'Onboard, to = 'Node, note = "declare a governance bond — become a governed node" },
{ from = 'Linked, via = 'Onboard, to = 'Managed, note = "escalate to full ontoref management" },
{ from = 'Node, via = 'Onboard, to = 'Managed, note = "escalate to full ontoref management" },
{ from = 'Linked, via = 'Update, to = 'Linked, note = "retype dep_kind / mutual / capabilities" },
{ from = 'Node, via = 'Update, to = 'Node, note = "retype resolution / capabilities" },
{ from = 'Managed, via = 'Update, to = 'Managed, note = "retune the managed bond" },
{ from = 'Managed, via = 'Offboard, to = 'Node, note = "demote from management to a governance node" },
{ from = 'Node, via = 'Offboard, to = 'None, note = "drop the governance bond" },
{ from = 'Linked, via = 'Offboard, to = 'None, note = "drop the dependency bond" },
] in
# ── The bond record ───────────────────────────────────────────────────────────
# `from`/`to` name the DOMAIN ROOTS of the two endpoints — a bond resolves
# against their definitions/attributes/states/capabilities, NEVER on the edge
# (glossary::bond). The edge is thin: `capabilities` are reference ids into a
# domain root's catalog, not inline definitions (ontology-vs-reflection).
#
# Field applicability by axis (not enforceable in bare Nickel — stated, and the
# `bond validate` verb checks it):
# axis = 'Governance → `resolution` meaningful; `dep_kind`/`mutual`/`plane` unused.
# axis = 'Dependency → `dep_kind`/`mutual`/`plane` meaningful; `resolution` unused.
let bond_type = {
id | String, # stable slug, e.g. "rustelo-app-to-rustelo"
from | String, # this project's domain root (the bonding endpoint)
to | String, # the target domain root
axis | bond_axis_type,
state | linkage_state_type | default = 'None,
# Dependency-axis fields
dep_kind | dep_kind_type | default = 'CustomerSupplier,
mutual | Bool | default = false,
plane | String | default = "", # which ontoref-plane (when 'Linked)
# Governance-axis field
resolution | resolution_type | default = 'Delegate,
# Reference ids into the endpoints' domain-root catalogs (never inline defs).
capabilities | Array String | default = [],
note | String | default = "",
} in
# ── Carrier — what a bonded project declares on disk ──────────────────────────
# One file per domain folder: .domains-ontoref/<domain>/bond.ncl : BondSet.
# Multi-domain membership = multiple <domain>/ subfolders, each a BondSet — never
# derived from the manifest's single `repo_kind` (formalization-vs-adoption: the
# cardinality is uncapped and lives outside project management).
let bond_set_type = {
domain | String, # the domain these bonds target (matches folder name)
bonds | Array bond_type,
} in
{
BondAxis = bond_axis_type,
DepKind = dep_kind_type,
Resolution = resolution_type,
LinkageState = linkage_state_type,
LinkageTransition = linkage_transition,
LinkageTransitionKind = linkage_transition_type,
Bond = bond_type,
BondSet = bond_set_type,
# Canonical FSM, exported for the `bond` verb and forms to consult.
linkage_transitions = default_linkage_transitions,
}