# 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//, 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//bond.ncl : BondSet. # Multi-domain membership = multiple / 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, }