feat(domains): two-path activation gate + both-faces slots (adr-077)

_dispatch_domain now activates a domain by EITHER a managed project's repo_kind
(adr-012) OR the presence of a bond carrier .domains-ontoref/<id>/bonds.ncl
(adr-073), with no manifest required on the bond path. The repo_kind path is
unchanged; the bond path is purely additive. domains/schema.ncl gains adrs/modes
reference-id slots so a domain carries both faces (adr-076 the-domain-scope-
carries-both-faces).
This commit is contained in:
Jesús Pérez 2026-07-21 11:45:25 +01:00
parent 234432856c
commit b3e3a62f91
Signed by: jesus
GPG key ID: 9F243E355E0BC939
2 changed files with 39 additions and 18 deletions

View file

@ -29,8 +29,19 @@ let domain_type = {
description | String | default = "",
commands | Array domain_command_type | default = [],
pages | Array domain_page_type | default = [],
# .ontoref/ontology/*.ncl stems that must exist for commands to work
# .ontoref/ontology/*.ncl stems that must exist for commands to work.
# Enforced ONLY on the Layer-1 activation path (a managed project, repo_kind
# match); a bond-only consumer ('Linked/'Node, no .ontoref/ spine) is exempt
# (ADR-073, ADR-076 G-1=A). The dispatch gate lives in install/ontoref-global.
required_extensions | Array String | default = [],
# Both faces of the domain scope (ADR-076 the-domain-scope-carries-both-faces).
# Reference ids only — the actual .ncl content lives in the provider's spine
# (.ontoref/adrs, .ontoref/reflection/modes) or, for a bonded implementing
# consumer, in .domains-ontoref/<id>/{ontology,reflection} (bond-carrier-layout).
# A domain declaring commands/schemas but neither face collapses ontology-vs-
# reflection (schema-only = Yin capture, commands-only = Yang capture).
adrs | Array String | default = [],
modes | Array String | default = [],
commands_script | String | default = "commands.nu",
short_alias | String | default = "",
# For domains whose NCL schemas live in an external project (not ontoref itself).

View file

@ -489,37 +489,47 @@ _dispatch_domain() {
exit 1
fi
# Two activation paths coexist (ADR-012 repo_kind ⊕ ADR-073 bond; ADR-076 G-1=A).
# Layer-1 path — a MANAGED project: manifest present + repo_kind in repo_kinds.txt.
# Bond path — a BOND-ONLY consumer: carrier .domains-ontoref/<id>/bonds.ncl
# present, NO project manifest required (linkage_state 'Linked/'Node;
# adr-073 "a bond needs no .ontoref/ management spine"). The carrier's
# PRESENCE is detection pattern (d) (domain.nu). Fast file test only —
# consistent with the no-nickel-export dispatch philosophy above.
# Neither path collapses the other: a managed project still activates by repo_kind
# exactly as before; the bond path is purely additive.
local bond_carrier="${ONTOREF_PROJECT_ROOT}/.domains-ontoref/${first_arg}/bonds.ncl"
local manifest="${ONTOREF_PROJECT_ROOT}/.ontoref/ontology/manifest.ncl"
[[ -f "$manifest" ]] || manifest="${ONTOREF_PROJECT_ROOT}/.ontology/manifest.ncl"
if [[ ! -f "$manifest" ]]; then
echo "" >&2
echo " ontoref: domain '${first_arg}' requires a project with .ontoref/ontology/manifest.ncl (or legacy .ontology/manifest.ncl)" >&2
echo " current project: ${ONTOREF_PROJECT_ROOT}" >&2
echo "" >&2
exit 1
fi
# Extract repo_kind directly from the NCL source — no nickel export needed.
# The field is always a literal enum tag: repo_kind = 'SomeName,
# This avoids import-path resolution failures for manifests that import schemas.
local repo_kind=""
repo_kind="$(grep -oE "repo_kind\s*=\s*'[A-Za-z_]+" "$manifest" 2>/dev/null | grep -oE "'[A-Za-z_]+$" | tr -d "'")" || true
[[ -f "$manifest" ]] && repo_kind="$(grep -oE "repo_kind\s*=\s*'[A-Za-z_]+" "$manifest" 2>/dev/null | grep -oE "'[A-Za-z_]+$" | tr -d "'")" || true
if [[ -z "$repo_kind" ]]; then
echo "" >&2
echo " ontoref: domain '${first_arg}' is not available for this project" >&2
echo " reason: repo_kind is not set in ${manifest}" >&2
echo "" >&2
exit 1
local activated=0
if [[ -n "$repo_kind" ]] && grep -qx "$repo_kind" "$repo_kinds_file" 2>/dev/null; then
activated=1 # Layer-1 / ADR-012 path
elif [[ -f "$bond_carrier" ]]; then
activated=1 # Bond / ADR-073 path — no manifest or repo_kind demanded
fi
if ! grep -qx "$repo_kind" "$repo_kinds_file" 2>/dev/null; then
if [[ "$activated" -eq 0 ]]; then
local required
required="$(tr '\n' ' ' < "$repo_kinds_file" | sed 's/ $//')"
echo "" >&2
echo " ontoref: domain '${first_arg}' is not available for this project" >&2
echo " requires repo_kind: ${required}" >&2
echo " current repo_kind: ${repo_kind}" >&2
echo " current project: ${ONTOREF_PROJECT_ROOT}" >&2
echo " activate it either by:" >&2
echo " • a project manifest with repo_kind in: ${required} (managed project, ADR-012)" >&2
echo " • a bond carrier at .domains-ontoref/${first_arg}/bonds.ncl (bonded consumer, ADR-073)" >&2
if [[ -f "$manifest" && -z "$repo_kind" ]]; then
echo " note: manifest found but repo_kind is unset in ${manifest}" >&2
elif [[ -f "$manifest" ]]; then
echo " note: current repo_kind is '${repo_kind}', not in the list above" >&2
fi
echo "" >&2
exit 1
fi