Layout Consolidation Under .ontoref/ Root — Single Hidden Hierarchy for the Protocol's Consumer Footprint
Accepted
Context
Every project that adopts ontoref currently inherits a sprawl of root directories: `.ontoref/` (hidden — config and runtime state), `.ontology/` (hidden — declarative ontology), `adrs/` (visible — Architecture Decision Records), `reflection/` (visible — qa, backlog, modes, schemas, modules, migrations, nulib), and most recently `catalog/` (visible — operations and validators per ADR-024, ADR-026). For consumer projects this means:
- Five root directories owned by ontoref alone, consuming 33-40% of the `L-ROOT-LIMIT` (target 12-15 total root dirs) defined in `.claude/layout_conventions.md`. - Inconsistent hidden/visible split: `.ontoref/` and `.ontology/` are dot-prefixed (following `L-NAMING-HIDDEN` for infrastructure dirs), while `adrs/`, `reflection/`, `catalog/` are visible without architectural justification for the inconsistency. - Mixed identity signal: the visible directories present as "first-class project content" alongside `crates/`, `src/`, `docs/`, when in fact they are infrastructure of the protocol supporting the project — not the project's substantive content. - Operational friction: copying ontoref state across projects requires enumerating five paths; deleting cleanly requires five `rm -rf` invocations; CI exclusion requires five glob patterns; backup/restore means five tar entries; auditing "is ontoref clean here?" means five independent checks.
The current layout grew organically across ontoref's evolution. Each section (`.ontology/` from the earliest ondaod pass; `adrs/` from adr-001's adoption of ADR-as-data; `reflection/` from the adopt-ontoref-tooling onboarding template; `catalog/` from ADR-024's operations layer) arrived as a section of the protocol's design and was placed where it made narrative sense AT THAT MOMENT. Nothing ever collected them under a common root because the protocol grew as a tree, not as a module. The session 2026-05-26 (ADR-029 tier coexistence articulation, then ADR-030 catalog discovery, then ADR-031 on+re duality elevation) produced both more sub-directories AND increased visibility of the cost of the layout sprawl. The user's observation:
"ontoref debería aparecer en los proyectos como una estructura en un sólo folder ... esto convierte al layout de proyectos en un lío además de no cumplir con `.claude/layout_conventions.md`. Facilitaría mucho que todo estuviera dentro de una misma jerarquía."
This ADR records that observation as architectural decision and consolidates ontoref's consumer footprint into a single hidden hierarchy under `.ontoref/`, propagated per-project via migration 0023 (opt-in, consistent with `voluntary-adoption`). The change is a protocol version increment to **0.1.1** — breaking layout change with migration assistance and dual-path resolver back-compat during the transition window.
Decision
All ontoref consumer-facing artefacts MUST consolidate under a single hidden root directory `.ontoref/` per consumer project. The canonical layout becomes:
my-project/ └── .ontoref/ ← single hidden ontoref subsystem root ├── config.ncl ← daemon config (unchanged location) ├── project.ncl ← project identity (unchanged location) ├── actors.ncl ← actor keypairs (unchanged location) ├── ontology/ ← MOVED FROM .ontology/ │ ├── core.ncl │ ├── state.ncl │ ├── gate.ncl │ ├── manifest.ncl │ └── _refs.ncl ← was _ontology_refs.ncl ├── adrs/ ← MOVED FROM adrs/ │ ├── adr-*.ncl │ └── _template.ncl ├── reflection/ ← MOVED FROM reflection/ │ ├── qa.ncl │ ├── backlog.ncl │ ├── search_bookmarks.ncl │ ├── modes/ │ ├── forms/ │ ├── schemas/ │ ├── modules/ │ ├── migrations/ │ └── nulib/ ├── catalog/ ← MOVED FROM catalog/ │ ├── schema.ncl │ ├── operations/ │ └── validators/ ├── store/ ← runtime state (oplogs, witness chain) │ └── ontologies/ ← was .ontoref/ontologies/ (content-addressed oplogs) └── locks/ ← runtime advisory locks (unchanged)
The consumer project's own content (`crates/`, `src/`, `docs/`, `assets/`, etc.) retains its existing layout. Only ontoref's footprint moves.
DUAL-PATH RESOLVER (transition period)
During the version 0.1.0 → 0.1.1 transition, the daemon implements a dual-path resolver in `crates/ontoref-daemon/src/registry.rs` and `crates/ontoref-ontology/src/ontology.rs` that:
1. Prefers the new path (`.ontoref/<section>/`) when it exists. 2. Falls back to the legacy path (root-level `.ontology/`, `adrs/`, `reflection/`, `catalog/`) when the new path is absent. 3. Emits an `info`-level log when the legacy path is used, noting the project has not yet applied migration 0023.
The dual-path resolver remains in the codebase until ontoref version 0.2.0; at that point a future ADR may declare the legacy paths removed (advisory, not forced).
ONTOREF-EL-PROYECTO MIGRATES FIRST (canonical demonstration)
Per the `self-describing` axiom (invariant=true), ontoref-el-proyecto applies migration 0023 before any consumer project. This produces:
- The canonical layout demonstration that other projects can follow - First-class evidence that the migration script works on real content (ontoref's own ontology has 40 nodes, 91+ edges, 32 ADRs) - The reference state for the dual-path resolver tests
Consumer projects (mirador, libre-{daoshi,wuji,forge}, lian-build, the other 14 currently onboarded) apply migration 0023 voluntarily on their own schedules. Until they do, the daemon serves them via the legacy paths through the dual-path resolver.
SCOPE — WHAT MOVES, WHAT DOES NOT
MOVES into .ontoref/: .ontology/ → .ontoref/ontology/ adrs/ → .ontoref/adrs/ reflection/ → .ontoref/reflection/ catalog/ → .ontoref/catalog/
STAYS at root (for ontoref-el-proyecto only, not for consumers): crates/ (Rust implementation crates — not consumer-relevant) install/ (install scripts — not in consumer projects) justfiles/ (build automation) scripts/ (support scripts — co-existing with the consumer's own) templates/ (consumer onboarding templates) ontology/ (defaults + schemas installed to consumer data dir) assets/ (web + presentation)
REMAINS unchanged (already under .ontoref/): .ontoref/config.ncl .ontoref/project.ncl .ontoref/actors.ncl .ontoref/locks/
NCL IMPORT PATH UPDATES
Inside the moved files, relative `import "..."` paths are updated to reflect the new depth:
OLD: `.ontology/core.ncl` with `import "../ontology/defaults/core.ncl"` NEW: `.ontoref/ontology/core.ncl` with `import "../../ontology/defaults/core.ncl"`
The daemon's `NICKEL_IMPORT_PATH` (managed by `global_schema_dirs()`) continues to include the data-dir schemas at `$data_dir/ontology/schemas/` and `$data_dir/ontology/`. Absolute schema imports (`import "manifest"`, `import "core"`) keep working unchanged.
Constraints
- Hard All ontoref consumer-facing artefacts (ontology declarations, ADRs, reflection store, catalog declarations, runtime state, locks) MUST live under `.ontoref/` in a consumer project. The legacy root-level directories `.ontology/`, `adrs/`, `reflection/`, `catalog/` are deprecated by migration 0023 and removed by the migration's mv operations.
- Hard The daemon's `registry.rs` and `ontology.rs` MUST implement a dual-path resolver that prefers the new path (`.ontoref/<section>/`) and falls back to the legacy path (root-level `.ontology/`, `adrs/`, `reflection/`, `catalog/`) when the new path is absent. The fallback MUST emit an info-level log noting the project has not yet applied migration 0023.
- Hard Migration 0023 MUST be applied per-project via the standard `ontoref migrate` workflow. No automatic / silent / boot-time migration of consumer projects is permitted. The daemon detects un-migrated consumers via the legacy-path fallback and surfaces the recommendation via `ontoref migrate pending`, but does not act on it.
- Hard ontoref-el-proyecto (this repository) MUST apply migration 0023 to its own consumer-facing artefacts before any consumer project is recommended to apply it. The canonical layout under `.ontoref/` is demonstrated in ontoref's own repo first; consumer documentation references the ontoref repo as the worked example.
- Hard The project beacon `card.ncl` and the generated `artifacts/api-catalog-*.ncl` files MUST live under `.ontoref/` after migration 0023, NOT at project root. `card.ncl` is pure ontoref metadata (not an OS-level discovery convention like `Cargo.toml` or `package.json`) and `artifacts/` is generated ontoref output — both belong under the consolidated root.
- Hard Section paths (ontology_dir, adrs_dir, reflection_dir, catalog_dir, artifacts_dir, card_path) MUST be addressable through `LayoutConfig` rather than hard-coded literals in production code. Defaults match the consolidated layout (`.ontoref/<section>/`), but projects MAY override any field via their `.ontoref/config.ncl` `[layout]` section. All call sites that read or write ontoref artefacts MUST route through `ontoref_ontology::layout::resolve_section` (reads, with legacy fallback) or `canonical_section` (writes, no fallback) or an explicit `LayoutConfig::resolve` / `canonical` method.
Alternatives considered
- Keep the current layout — accept the L-ROOT-LIMIT violation as a cost of organic growth — rejected: The user's observation made the cost concrete and named the protocol's own convention (`.claude/layout_conventions.md`) as the rule being violated. The protocol cannot ignore its own conventions without losing credibility as a self-describing system. Five root directories for one subsystem is not organic growth; it is unsynchronised growth that the consolidation corrects.
- Move ALL of ontoref under a visible `ontoref/` directory (not hidden) — rejected: Visible directories signal 'first-class project content' alongside crates/, src/, docs/. ontoref is infrastructure-of-the-project, not the project's value content. L-NAMING-HIDDEN explicitly prescribes dot-prefix for process and configuration directories. Visible `ontoref/` would re-introduce the same identity-signal confusion the consolidation is meant to eliminate.
- Hybrid layout — runtime state hidden, declarative content visible (`.ontoref/store/` + `ontoref/ontology/`, etc.) — rejected: Re-introduces the inconsistency this ADR was opened to resolve. Two root dirs instead of five is an improvement but stops short of the single-point operational manipulation that the configuration-cube of ADR-029 requires. Half-measures cost the same migration effort as the full move with less of the benefit.
- Per-tier layouts (tier-0 → minimal under .ontoref/; tier-2 → richer hierarchy) — rejected: Multiplies the support matrix without qualitative gain. ADR-029 / `tier-coexistence-permanent-design` says tiers are about authoritative-state regimes, not about disk layout. Having one canonical layout that scales to all tiers (some directories empty at tier-0, populated at tier-2) is cleaner than three layouts.
- Move incrementally — only `catalog/` to `.ontoref/catalog/` first (it is the newest, with no legacy users), defer `adrs/` / `reflection/` / `.ontology/` for later versions — rejected: Three partial migrations cost more than one comprehensive migration. Consumer maintainers would face N rounds of layout disruption instead of one. The dual-path resolver pattern works equally well for one or four moved directories. Doing it all at version 0.1.1 lets the protocol stabilise at the new layout sooner.
Related ADRs
ADR-001 · ADR-010 · ADR-020 · ADR-024 · ADR-025 · ADR-026 · ADR-028 · ADR-029 · ADR-030 · ADR-031