Query surfaces derive their visible set from the declared level chain and bonds — no flat union, no hand-list

Accepted

ontoref
The everyday query surfaces do a flat union and ignore the hierarchy the manifest already declares

Context

The everyday query surfaces do a flat union and ignore the hierarchy the manifest already declares (level = { index, parent }, ADR-018/045) and the bond graph (ADR-073). Verified 2026-07-19, queried from rustelo (repo_kind = Library, level = { index = 'Domain, parent = "ontoref-base" }):

- `mode list` should show 5 own modes plus inherited-applicable ones; it shows 34. Twenty-nine foreign modes leak in — personal/provisioning/ecosystem modes that belong to SIBLING domains with a different repo_kind (draft-email, write-cfp, update-cv, and the provisioning set). - `qa show bond-carrier-layout-howto` should be reachable — it is a protocol fundamental authored at ontoref-base — but reports "No QA entry", because nothing inherits upward along parent = "ontoref-base".

Opposite-direction scope bugs in one CLI: QA under-scopes (no vertical inheritance), modes over-scope (no horizontal filter). The chain is declared and not routed. ADR-045 already computes a traversal path in `mode resolve`, but the list/show/describe surfaces never adopted it. This is the enforcement-vs-emergence self-drift on the query plane: a declared hierarchy nothing applies. Fixing it realizes declared formalization at near-zero adoption cost — no new fields, only existing declarations consumed. It is the observability prerequisite for adr-076 (adaptive role-scopes): a scope gradient nobody can see is a gradient nobody can manage.

Decision

Query resolvers (`qa`, `mode list`, `describe`, and any surface that enumerates inheritable artifacts) compute a VISIBLE SET DERIVED FROM DECLARED DATA — never a flat union, never a hand-listed set.

VERTICAL INHERITANCE (fixes under-scope). Walk level.parent from the querying project up to the base. Surface each ancestor's inheritable artifacts (the protocol floor: base QA, base/framework modes). This is why bond-carrier-layout-howto — authored at ontoref-base — must reach a 'Domain-level consumer like rustelo.

HORIZONTAL APPLICABILITY (fixes over-scope). Include a domain's artifacts only when the project relates to that domain: (a) BOND signal — the project declares a bond to the domain (.domains-ontoref/<id>/bonds.ncl, ADR-073); the refined signal, present once the bond layer is materialized. (b) REPO_KIND signal — the project's repo_kind matches the domain's repo_kinds.txt; the available floor today, working before any bond exists. Exclude sibling projects' local artifacts and domains the project neither bonds to nor repo_kind-matches.

DERIVATION, NOT ENUMERATION. The visible set is a pure function of chain(project) + bonds(project) + repo_kind(project) over the artifact population. It is never hand-listed — that is the coverage-superset-of-extent anti-pattern (ADR-072). A `--all` / `--scope <s>` widen flag exists for debugging and cross-domain inspection; the default is the derived set. The derivation is uniform across surfaces, so a project's self-knowledge is consistent regardless of which surface asks.

USES ONLY EXISTING DECLARATIONS. No new taxonomy. adr-076 layers the adaptive role-scope tags on top; this ADR is functional on the chain + repo_kind + bond data that already exist, and degrades gracefully to chain + repo_kind before any bond is materialized.

Constraints

  • Hard The visible set of any query surface is a pure function of the project's level chain, its declared bonds, and its repo_kind — never a flat union and never a hand-maintained list.
  • Hard An artifact authored at an ancestor level (up to the base) is reachable from a descendant project that repo_kind-matches or bonds to it; base protocol fundamentals are never invisible from a conformant descendant.
  • Soft A project's query surfaces exclude sibling projects' local artifacts and the artifacts of domains it neither bonds to nor repo_kind-matches; exclusion is reported directionally (inherited-count, filtered-count), never as a Hard exact-membership assertion.
  • Hard A `--all` / `--scope <s>` widen flag exists and is discoverable, so the derived default is never a silent, total filter a caller cannot see past.

Alternatives considered

  • Keep the flat union and let callers filter mentally.rejected: That is the current state: 34 modes where 5 apply, and a protocol fundamental invisible from a consumer. The union pushes the routing cost onto every reader, forever, and silently mixes scopes the manifest already distinguishes.
  • Hand-maintain a per-project allow-list of which artifacts each project sees.rejected: coverage-superset-of-extent (ADR-072): a hand list drifts from the artifact population the moment either changes, and it duplicates information the level chain + bonds + repo_kind already carry as data.
  • Fold routing into adr-076 (the adaptive role-scope ADR).rejected: adr-076's gradient is unobservable without routing; bundling them makes the prerequisite depend on the thing it must precede. Routing stands alone on existing declarations and is the cheaper, verifiable-first half.

Anti-patterns

  • Mode horizontal routing on existing declarations alone — Discovered 2026-07-19 while wiring the resolvers (adr-075 TASK 2). This ADR claims routing "uses only existing declarations". That HOLDS for QA — an ancestor's qa.ncl is inherited by walking the chain, no per-entry tag needed — but NOT for modes: the reflection mode schema carries no domain / scope / repo_kind / applies_to field. Within the installed set (`$ONTOREF_ROOT/reflection/ modes/`) there is therefore no signal to separate a universal-base mode from ontoref's OWN project mode. Measured: rustelo's `mode list` returns 34, of which the 30 installed are ontoref's own difusion / positioning / personal workflow modes (draft-email, write-cfp, update-cv, …) shipped as "base". This IS the adr-076 self-separation problem made concrete — ontoref's project modes install as universal because nothing tags them otherwise. The VERTICAL axis (own vs installed, by path) is available today; the HORIZONTAL filter (drop foreign / provider-own modes) is not, until each mode carries an origin scope.

Related ADRs

ADR-018 · ADR-045 · ADR-073 · ADR-012 · 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.