128 lines
7.1 KiB
Text
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,
|
|
}
|