The capability registry resolves through the declared bond resolution, not by shadowing: a chain with the node winning per id

Accepted

ontoref
`capabilities-file` in reflection/modules/checks.nu resolved the capability registry per FILE — the project overlay if present, else the shipped one — and its own comment warned about the neighbour

Context

`capabilities-file` in reflection/modules/checks.nu resolved the capability registry per FILE — the project overlay if present, else the shipped one — and its own comment warned about the neighbouring form of the defect it carried: 'resolving per DIRECTORY is what let a project carrying one local schema shadow the entire shipped set and turn a validator into a blanket reject'. Per-file resolution reproduces exactly that for capabilities, and it was measured rather than reasoned. On 2026-08-11 provisioning (a Level-2 domain) declared reflection/capabilities.ncl with three domain reaches (node_reach, registry_reach, sops_reach) plus the five shipped ones re-declared, because omitting them would have removed them. Evaluated from workspaces/libre-wuji, a Level-3 instance of that domain, a nucleus declaring needs = ['node_reach'] returned verdict 'unknown with cause 'Inferred and BLOCKED — 'I DID NOT LOOK — nucleus needs capability node_reach, which no registry declares'. The reach is declared by the instance's DOMAIN and nothing consulted the domain, because the resolver knows only two locations and neither is Level-2. The consequence is not a missing feature but an inverted verdict: a cell that should report 'unknown / 'Declared / non-blocking (out of its tissue, the circuit decides) instead reports a blocking harness failure, and the message sends the reader to fix a harness that is not broken. The vocabulary for the fix already exists and was not being read: bond.ncl's `resolution` on a 'Governance bond states 'Delegate (the node takes the domain's version), 'Override (the node's own is complete, traversal stops), 'Compose (explicit partial inheritance) and 'Merge (the node accumulates the domain's contributions AND adds its own — per item the NODE's version wins, and any item the node does not carry is inherited). Registry resolution was hardcoded to 'Override while the project could declare otherwise, so the declaration was inert.

Decision

Capability-registry resolution READS the project's declared 'Governance bond resolution instead of hardcoding one. `capabilities-file` becomes `capability-registries`, returning an ordered CHAIN merged first-wins per id: 'Override (or no governance bond at all) keeps the historical behaviour exactly — the overlay alone when it exists, else the shipped set; 'Merge yields overlay → bonded domain roots → shipped; 'Delegate yields bonded domain roots → shipped, skipping the node's own overlay. 'Compose is REFUSED with a message rather than guessed: it means the node names what it inherits, and the only field that could name it is `bond.capabilities`, which holds domain-catalog ids (cascade-resolver, shared-gates) and not cell reaches — guessing there would make a domain feature list read as a reach declaration. A bonded domain whose project root does not resolve is REPORTED, NOT FATAL: it is recorded and surfaced in the unregistered-id message ('inheritance incomplete: bonded domain(s) X declared 'Merge/'Delegate but their project root did not resolve'), which is the only place it can be relevant. A registry file that exists but does not export is a hard error naming the file, never a silently skipped link. Domain roots are resolved by invoking `domain-root`, extracted for this purpose from `domain show` in reflection/modules/domain.nu, so its ONTOREF_RESOLVING_DOMAIN re-entry guard is invoked and not reproduced.

Constraints

  • Hard Capability-registry resolution must consult the project's declared 'Governance bond resolution. No call site may hardcode a precedence that ignores it.
  • Hard Every caller resolving a domain project root invokes `domain-root` from reflection/modules/domain.nu. No second site may reproduce the schema_cmd invocation, with or without the re-entry guard.
  • Hard A 'Compose governance bond must produce an explicit refusal from capability resolution. It must not be silently treated as 'Merge, and `bond.capabilities` must not be read as a list of cell reaches.
  • Hard A bonded domain whose project root does not resolve must not block cells that do not depend on it. Its ids are carried out and named only in the unregistered-id message.
  • Hard reflection/modules/bond.nu and reflection/modules/domain.nu must not import checks.nu. checks.nu imports both, so either import would close a cycle.
  • Hard A nucleus in a bonded instance declaring a reach its domain registers must return cause 'Declared when the probe reports absent, never 'Inferred. The blocking/non-blocking distinction is the observable consequence.

Alternatives considered

  • Have each instance declare its own full capability registryrejected: It duplicates per instance a declaration the level hierarchy (adr-018, adr-030 mechanism #6) says converges at the domain, and the duplicate drifts from the domain on the first probe anyone updates. It is also the shape the tissue fence refuses for the analogous case.
  • Union every registry found, ignoring bond resolutionrejected: It would make 'Override unexpressible — a node whose registry is deliberately complete could no longer stop inheritance — and it would reintroduce the shadowing question from the other side, with no declaration to appeal to.
  • Derive the domain from the manifest's `repo_kind` instead of from a bondrejected: adr-073 forbids it explicitly: domain membership is carrier-declared, uncapped, and never derived from the scalar repo_kind. The bond is the only legitimate statement that this project belongs to that domain.
  • Keep the resolver and let instances pass a registry path explicitlyrejected: A path is a location true on one machine (the defect bl-048 already recorded), and it moves a governed relation into an invocation flag where nothing validates it.

Related ADRs

ADR-073 · ADR-074 · ADR-018 · ADR-072

Was this useful? Rate it
Got something to add? Tell me what you think, what you'd suggest, or whether we should keep exploring this topic.
· reads

We use cookies to help this site function, understand service usage, and support marketing efforts. Cookie Policy for more info.