2026-03-13 00:15:49 +00:00
# Changelog
All notable changes to ontoref are documented here.
ADRs referenced below live in `adrs/` as typed Nickel records.
---
## [Unreleased]
feat: mode guards, convergence, manifest coverage, doc authoring pattern
## Mode guards and convergence loops (ADR-011)
- `Guard` and `Converge` types added to `reflection/schema.ncl` and
`reflection/defaults.ncl`. Guards run pre-flight checks (Block/Warn);
converge loops iterate until a condition is met (RetryFailed/RetryAll).
- `sync-ontology.ncl`: 3 guards + converge (zero-drift condition, max 2 iter).
- `coder-workflow.ncl`: guard (coder-dir-exists) + `novelty-check` step.
- Rust types in `ontoref-reflection/src/mode.rs`; executor in `executor.rs`
evaluates guards before steps and convergence loop after.
- `adrs/adr-011-mode-guards-and-convergence.ncl` added.
## Manifest capability completeness
- `.ontology/manifest.ncl`: 3 → 19 declared capabilities covering the full
action surface (daemon API, modes, Task Composer, QA, bookmarks, etc.).
- `sync.nu`: `audit-manifest-coverage` + `sync manifest-check` command.
- `validate-project.ncl`: 6th category `manifest-cov`.
- Pre-commit hook `manifest-coverage` added.
- Migrations `0010-manifest-capability-completeness`,
`0011-manifest-coverage-hooks`.
## Rust doc authoring pattern — canonical `///` convention
- `#[onto_api]`: `description = "..."` optional when `///` doc comment exists
above handler — first line used as fallback. `#[derive(OntologyNode)]` same.
- `ontoref-daemon/src/api.rs`: 42 handlers migrated to `///` doc comments;
`description = "..."` removed from all `#[onto_api]` blocks.
- `sync diff --docs --fail-on-drift`: exits 1 on crate `//!` drift; used by
new `docs-drift` pre-commit hook. `docs-links` hook checks rustdoc broken links.
- `generator.nu`: mdBook `crates/` chapter — per-crate page from `//!` doc,
coverage badge, feature flags, implementing practice nodes.
- `.claude/CLAUDE.md`: `### Documentation Authoring (Rust)` section added.
- Migration `0012-rust-doc-authoring-pattern`.
## OntologyNode derive fixes
- `#[derive(OntologyNode)]`: `name` and `paths` attributes supported; `///`
doc fallback for `description`; `artifact_paths` correctly populated.
- `Core::from_value` calls `merge_contributors()` behind `#[cfg(feature = "derive")]`.
## Bug fixes
- `sync.nu` drift check: exact crate path match (not `str starts-with`);
first-path-only rule; split on `. ` not `.` to avoid `.ontology/` truncation.
- `find-unclaimed-artifacts`: fixed absolute vs relative path comparison.
- Rustdoc broken intra-doc links fixed across all three crates.
- `ci-docs` recipe now sets `RUSTDOCFLAGS` and actually fails on errors.
mode guards/converge, manifest coverage validation, 19 capabilities (ADR-011)
Extend the mode schema with Guard (pre-flight Block/Warn checks) and Converge
(RetryFailed/RetryAll post-execution loops) — protocol pushes back on invalid
state and iterates until convergence. ADR-011 records the decision to extend
modes rather than create a separate action subsystem.
Manifest expanded from 3 to 19 capabilities covering the full action surface
(compose, plans, backlog graduation, notifications, coder pipeline, forms,
templates, drift, quick actions, migrations, config, onboarding). New
audit-manifest-coverage validator + pre-commit hook + SessionStart hook
ensure agents always see complete project self-description.
Bug fix: find-unclaimed-artifacts absolute vs relative path comparison —
19 phantom MISSING items resolved. Health 43% → 100%.
Anti-slop: coder novelty-check step (Jaccard overlap against published+QA)
inserted between triage and publish in coder-workflow.
Justfile restructured into 5 modules (build/test/dev/ci/assets).
Migrations 0010-0011 propagate requirements to consumer projects.
2026-03-30 19:08:25 +01:00
### Rust doc authoring pattern — canonical `///` convention
#### `#[onto_api]` — `description` now optional
- `description = "..."` parameter is no longer required when a `///` doc comment exists
above the handler. The proc-macro reads the first `///` line as the fallback description.
- Same fallback applied to `#[derive(OntologyNode)]` — `///` first line used when
`description` attribute is absent.
- `ontoref-daemon/src/api.rs` : 42 handlers migrated — `description = "..."` removed from
all `#[onto_api]` blocks, canonical `///` first line added above each handler.
#### `sync diff --docs --fail-on-drift`
- New `--fail-on-drift` flag on `sync diff` : exits 1 when any crate `//!` has drifted
from its ontology node description. Intended for pre-commit enforcement; without the
flag, the command remains non-destructive and returns the table as before.
#### mdBook `crates/` chapter
- `generator.nu` : two helpers added — `read-crate-module-doc` (parses `//!` from
`lib.rs` /`main.rs` ) and `count-pub-coverage` (ratio of documented pub items).
- `render-mdbook` generates `docs/src/crates/<name>.md` per workspace member: `//!`
content, pub item coverage badge, feature flags from `Cargo.toml` , and which practice
nodes list the crate as primary `artifact_paths` . Missing `//!` renders a warning block.
- `SUMMARY.md` gains a `# Crates` section with links to all generated pages.
#### Pre-commit hooks
- `.pre-commit-config.yaml` : `docs-links` hook runs rustdoc broken-link check
(`RUSTDOCFLAGS` with `-D rustdoc::broken-intra-doc-links` ) on `.rs` changes.
- `.pre-commit-config.yaml` : `docs-drift` hook runs
`sync diff --docs --fail-on-drift` on `.rs` changes.
#### Agent and developer directives
- `.claude/CLAUDE.md` : `### Documentation Authoring (Rust)` section added — three-layer
table, four authoring rules, agent discovery commands (`describe workspace` ,
`describe features` , `sync diff --docs` ), crate registration procedure.
#### Migration
- `0012-rust-doc-authoring-pattern` : consumer projects receive the
`### Documentation Authoring (Rust)` section for their `CLAUDE.md` and optional
pre-commit hooks (`docs-links` , `docs-drift` ).
---
### Mode guards, convergence loops, and manifest coverage enforcement
#### Mode schema extension (ADR-011)
- **Guard type** added to `reflection/schema.ncl` : pre-flight executable checks with
`Block` (abort) or `Warn` (continue) severity. Guards run before any step — the
protocol pushes back on invalid state instead of failing silently mid-execution.
- **Converge type** added to `reflection/schema.ncl` : post-execution convergence loop
with `condition` command, `max_iterations` cap, and `RetryFailed` /`RetryAll` strategy.
Modes iterate until a condition is met rather than running once blindly.
- Both types exposed in `reflection/defaults.ncl` as `Guard` and `Converge` .
- Reference implementation: `sync-ontology.ncl` gains 3 guards (ontology-exists,
nickel-available, manifest-capabilities) and converge (iterate until zero drift,
max 2 iterations).
- `coder-workflow.ncl` gains guard (coder-dir-exists) and new `novelty-check` step
(anti-slop Jaccard overlap detection between pending entries and published+QA).
- Nushell executor (`reflection/nulib/modes.nu` ): guard execution before steps,
convergence loop after steps.
- Rust types: `Guard` , `GuardSeverity` , `Converge` , `ConvergeStrategy` in
`ontoref-reflection/src/mode.rs` .
- Rust executor: guards evaluated pre-execution (Block returns error, Warn logs),
convergence loop post-execution.
- Backward compatible: `guards` defaults to `[]` , `converge` is optional.
All 19 existing modes export unchanged.
#### Manifest capability completeness (19 capabilities)
- `.ontology/manifest.ncl` expanded from 3 to 19 declared capabilities covering the
full action surface: protocol spec, daemon API, reflection modes, run/step tracking,
Agent Task Composer, backlog graduation, notifications, coder process memory, QA store,
form system, template generation, describe query layer, drift detection, quick actions,
protocol migration, config surface, search bookmarks, project onboarding, web presence.
- `audit-manifest-coverage` function in `reflection/modules/sync.nu` : cross-references
Practice nodes, reflection modes, and daemon UI pages against declared capabilities.
- `sync manifest-check` exported command for pre-commit hooks and CI.
- `validate-project.ncl` gains 6th validation category: `manifest-cov` .
- Pre-commit hook `manifest-coverage` : fires on `.ontology/` , `reflection/modes/` ,
`reflection/forms/` changes.
- SessionStart hook (`session-context.sh` ): shows manifest coverage status at session start.
- Agent consumption mode description updated in manifest.
#### Bug fixes
- `find-unclaimed-artifacts` in `sync.nu` : fixed absolute vs relative path comparison
for modes and forms. `path relative-to $root` applied before `starts-with` check.
19 phantom MISSING items resolved.
- `audit-claude` session-hook check: accepts both `.claude/hooks/session-context.sh`
and legacy `.claude/ontoref-session-start.sh` .
- `describe mode` now shows guards and converge sections.
- `scan-reflection-mode-dags` JSON output for agents now includes guards, converge,
preconditions, postconditions, and step-level cmd/on_error/verify.
#### Infrastructure
- Justfile restructured: `justfiles/build.just` , `justfiles/test.just` ,
`justfiles/dev.just` added. CI recipes delegated to canonical modules.
Manifest justfile convention updated to `Import` system with 5 modules.
- Manifest `claude` baseline declared: `["rust", "nushell", "nickel"]` guidelines, session_hook enabled.
- `.ontology/core.ncl` : `ci-pipelines` Practice node added. `reflection/forms/` added to `reflection-modes` artifact_paths.
#### Migrations
- `0010-manifest-capability-completeness` : consumer projects must declare ≥3 capabilities.
- `0011-manifest-coverage-hooks` : consumer projects must add pre-commit and SessionStart
hooks for manifest coverage.
#### on+re update
| Artifact | Change |
|----------|--------|
| `.ontology/manifest.ncl` | 3 → 19 capabilities; justfile/claude baselines declared; agent consumption mode updated |
| `.ontology/core.ncl` | `ci-pipelines` node; `reflection/forms/` in reflection-modes; adr-011 in adr-lifecycle |
| `.ontology/state.ncl` | protocol-maturity catalyst updated (ADR-011, 19 caps, migrations 0010-0012); self-description-coverage catalyst updated (session 2026-03-30) |
| `adrs/adr-011-mode-guards-and-convergence.ncl` | New ADR: guards and converge extend mode schema rather than separate action subsystem |
| Health | 43.2% → 100.0% (31 OK / 0 MISSING / 0 STALE) |
---
2026-03-29 08:32:50 +01:00
### Browser-style panel navigation + repo file routing
Graph, search, and api_catalog pages now share a uniform browser-style navigation model:
back/forward history stack with cursor-into-array semantics. File artifact paths open in
external browser tabs rather than being loaded inline.
#### `crates/ontoref-daemon/templates/pages/graph.html`
- `.artifact-link` click handler changed from removed `openFile()` to `srcOpen()` .
- `panelNav._replay` `type: "file"` case changed to `srcOpen(e.id)` .
#### `crates/ontoref-daemon/templates/pages/search.html`
- `openFileInPanel` async function removed entirely (was loading file content inline via `/api/file` ).
- `srcOpen(path)` function added: opens `{card_repo}/src/branch/main/{path}` for most files;
opens `card_docs` for `.rs` files when configured.
- `CARD_REPO` / `CARD_DOCS` JS constants injected via Tera (`| safe` filter required — Tera
auto-escapes all `{{ }}` interpolations regardless of `<script>` context).
- `.s-file-link` click delegation updated to call `srcOpen` .
- `dpNav._replay` `type: "file"` case calls `srcOpen` .
#### `crates/ontoref-daemon/templates/pages/api_catalog.html`
- `ensureFileModal` and `openFile` removed.
- `srcOpen` added with same logic as graph and search pages.
- `CARD_REPO` / `CARD_DOCS` constants injected.
- `#detail-source-btn` click delegation calls `srcOpen` .
#### `crates/ontoref-daemon/src/ui/handlers.rs`
- `insert_brand_ctx` reads `card.repo` and `card.docs` from config NCL and injects
`card_repo` / `card_docs` into the Tera context for all pages.
#### `card.ncl`
- `repo = "https://repo.jesusperez.pro/jesus/ontoref"` added.
#### `reflection/migrations/0007-card-repo-field.ncl` — new migration
- Check: `card.ncl` absent → pass (not applicable); present + `repo =` found → pass; present
without `repo =` → pending.
- Instructions: add `repo` and optionally `docs` fields; explains how `srcOpen` uses both.
#### on+re update
| Artifact | Change |
|----------|--------|
| `.ontology/core.ncl` | `ontoref-daemon` description updated — browser-style panel nav, file routing via `card.repo` /`card.docs` |
| `.ontology/state.ncl` | `self-description-coverage` catalyst updated with session 2026-03-29 |
---
2026-03-29 00:19:56 +00:00
### Protocol Migration System — progressive NCL checks for consumer project upgrades (ADR-010)
Replaces the template-prompt approach with an ordered, idempotent migration system. Applied state
determined by check result alone — no state file. 6 migrations shipped; runtime ships
`migrate list/pending/show` with interactive group dispatch.
#### `reflection/migrations/` — 6 ordered migrations
- `0001-ontology-infrastructure` — `.ontology/manifest.ncl` and `connections.ncl` present.
- `0002-adr-typed-checks` — no `check_hint` in ADR instance files (`adr-[0-9][0-9][0-9]-*.ncl` );
check narrowed from `adrs/` broad scan to exclude schema/template infrastructure files.
- `0003-manifest-self-interrogation` — `capabilities[]` and `requirements[]` non-empty in manifest.ncl.
- `0004-just-convention` — justfile validates against canonical module convention (pending in this repo — documented gap).
- `0005-mode-step-schema` — all reflection mode steps declare `actor` , `on_error` , `depends_on` .
- `0006-claude-agent-entrypoint` — `Agent Entry-Point Protocol` section present in `.claude/CLAUDE.md` .
All NuCmd checks rewritten from bash to valid Nushell: `&&` removed, `$env.VAR` replacing `$VAR` ,
no bash-style redirects. Grep checks on ADR files use `adr-[0-9][0-9][0-9]-*.ncl` glob.
#### `reflection/modules/migrate.nu` — new module
- `migrate list [--fmt] [--actor]` — all migrations with applied/pending status; JSON for agents.
- `migrate pending [--fmt] [--actor]` — pending only.
- `migrate show <id> [--fmt]` — runtime-interpolated instructions; accepts short ids (`002` → `0002` ).
- Applied state: `run-migration-check` dispatches over `FileExists | Grep | NuCmd` .
- No state file — idempotent by construction.
#### `reflection/nulib/interactive.nu` + `help.nu` — `migrate` group wired
- `group-command-info` — `migrate` case added (list, pending, show).
- `run-group-command` — `migrate` dispatch added.
- `help-group` — `migrate` help section added; fallback "Available groups" updated.
#### `reflection/bin/ontoref.nu` — shims + aliases
- `main migrate` , `main migrate list/pending/show` added.
- Short aliases: `mg` , `mg l` , `mg p` .
#### `reflection/schemas/justfile-convention.ncl` — export fix
- Removed `Module` and `ModuleSystem` from the exported record (open contract fields with no default
value caused `nickel export` to fail). Both remain as `let` bindings for internal NCL use.
#### on+re update
| Artifact | Change |
|----------|--------|
| `adrs/adr-010-...ncl` | Created — protocol migration system, progressive NCL checks |
| `.ontology/core.ncl` | `protocol-migration-system` node added; `adopt-ontoref-tooling` artifacts updated; `adr-lifecycle` updated with ADR-010; 4 new edges |
| `.ontology/state.ncl` | `protocol-maturity` catalyst updated (10 consumers, all features complete); blocker narrowed to `ontoref.dev not yet published` |
---
2026-03-26 21:01:39 +00:00
### Manifest Self-Interrogation Layer — capabilities, requirements, critical deps (ADR-009)
Three new typed arrays in `manifest_type` answering operational self-knowledge queries distinct from
ontology Practice nodes. `describe requirements` new subcommand; `describe guides` extended.
#### `ontology/schemas/manifest.ncl` — three new types
- `capability_type` — `id` , `name` , `summary` , `rationale` , `how` , `artifacts[]` , `adrs[]` , `nodes[]` .
`nodes[]` cross-references ontology node IDs; `adrs[]` cross-references ADR IDs.
- `env_target_type` — `'Production | 'Development | 'Both` classification axis for requirements.
- `requirement_kind_type` — `'Tool | 'Service | 'EnvVar | 'Infrastructure` .
- `requirement_type` — `id` , `name` , `env` , `kind` , `version` , `required` , `impact` , `provision` .
- `critical_dep_type` — `id` , `name` , `ref` , `used_for` , `failure_impact` (required), `mitigation` .
- `manifest_type` gains `description | String | default = ""` (bug fix — `collect-identity` was reading
a field that didn't exist), `capabilities[]` , `requirements[]` , `critical_deps[]` (all `default = []` ).
- New exports: `EnvTarget` , `RequirementKind` , `Capability` , `Requirement` , `CriticalDep` .
#### `ontology/defaults/manifest.ncl` — three new builders
- `make_capability` , `make_requirement` , `make_critical_dep` added alongside existing builders.
- New type re-exports: `EnvTarget` , `RequirementKind` , `Capability` , `Requirement` , `CriticalDep` .
#### `reflection/modules/describe.nu` — new subcommand + extended outputs
- `describe requirements` — renders requirements grouped by env (Production / Development / Both) and
critical deps table (name, ref, used_for, failure_impact, mitigation). `--environment` flag filters.
- `describe capabilities` extended — loads `manifest.capabilities?` and renders a `PROJECT CAPABILITIES
(manifest)` section with name, summary, artifacts per entry.
- `describe guides` output gains `capabilities` , `requirements` , `critical_deps` keys — agents on cold
start via `ontoref_guides` MCP tool receive full self-interrogation context without extra tool calls.
- Bug fix: `collect-identity` was reading `manifest.kind?` (field absent from schema, always returned
`""` ) — changed to `manifest.repo_kind?` . Same fix for `manifest.description?` (now exists).
#### `.ontology/manifest.ncl` — ontoref self-described
- `description` field populated.
- 3 capabilities: `protocol-spec` , `daemon-api` , `reflection-modes` — each with rationale, how,
artifacts, adrs, nodes cross-references.
- 5 requirements: `nushell` (both), `nickel` (both), `rust-nightly` (dev), `surrealdb` (prod optional),
`stratumiops` (dev optional) — each with impact and provision.
- 3 critical deps: `nickel-lang` , `inventory` , `axum` — each with failure_impact and mitigation.
#### on+re update
| Artifact | Change |
|----------|--------|
| `adrs/adr-009-...ncl` | Created — manifest self-interrogation layer, three semantic axes |
| `.ontology/core.ncl` | `manifest-self-description` node added (29 nodes, 59 edges); `adr-lifecycle` updated with ADR-009 |
| `.ontology/state.ncl` | `protocol-maturity` blocker + `self-description-coverage` catalyst updated |
---
feat: config surface, NCL contracts, override-layer mutation, on+re update
Config surface — per-project config introspection, coherence verification, and
audited mutation without destroying NCL structure (ADR-008):
- crates/ontoref-daemon/src/config.rs — typed DaemonNclConfig (parse-at-boundary
pattern); all section structs derive ConfigFields + config_section(id, ncl_file)
emitting inventory::submit!(ConfigFieldsEntry{...}) at link time
- crates/ontoref-derive/src/lib.rs — #[derive(ConfigFields)] proc-macro; serde
rename support; serde_rename_of() helper extracted to fix excessive_nesting
- crates/ontoref-daemon/src/main.rs — 3-tuple bootstrap block (nickel_import_path,
loaded_ncl_config: Option<DaemonNclConfig>, stdin_raw); apply_ui_config takes
&UiConfig; NATS call site typed; resolve_asset_dir cfg(feature = "ui")
- crates/ontoref-daemon/src/api.rs — config GET/PUT endpoints, quickref, coherence,
cross-project comparison; index_section_fields() extracted (excessive_nesting)
- crates/ontoref-daemon/src/config_coherence.rs — multi-consumer coherence;
merge_meta_into_section() extracted; and() replaces unnecessary and_then
NCL contracts for ontoref's own config:
- .ontoref/contracts.ncl — LogConfig (LogLevel, LogRotation, PositiveInt) and
DaemonConfig (Port, optional overrides); std.contract.from_validator throughout
- .ontoref/config.ncl — log | C.LogConfig applied
- .ontology/manifest.ncl — contracts_path, log/daemon contract refs, daemon section
with DaemonRuntimeConfig consumer and 7 declared fields
Protocol:
- adrs/adr-008-ncl-first-config-validation-and-override-layer.ncl — NCL contracts
as single validation gate; Rust structs are contract-trusted; override-layer
mutation writes {section}.overrides.ncl + _overrides_meta, never touches source
on+re update:
- .ontology/core.ncl — config-surface node (28 practices); adr-lifecycle extended
to adr-007 + adr-008; 6 new edges (ManifestsIn daemon, DependsOn ontology-crate,
Complements api-catalog-surface/dag-formalized/self-describing/adopt-ontoref)
- .ontology/state.ncl — protocol-maturity blocker and self-description-coverage
catalyst updated for session 2026-03-26
- README.md / CHANGELOG.md updated
2026-03-26 20:20:22 +00:00
### Config Surface — typed config, NCL contracts, override-layer mutation
Per-project config introspection, coherence verification, and audited mutation. NCL contracts are the single
validation gate; config mutation never modifies source NCL files.
#### `crates/ontoref-daemon/src/config.rs` — typed `DaemonNclConfig` (parse-at-boundary)
- `DaemonNclConfig` — top-level deserialize target for `nickel export .ontoref/config.ncl | daemon --config-stdin` ;
fields: `nickel_import_paths` , `ui: UiConfig` , `log: LogConfig` , `mode_run: ModeRunConfig` ,
`nats_events: NatsEventsConfig` , `actor_init: Vec<ActorInit>` , `quick_actions: Vec<QuickAction>` ,
`daemon: DaemonRuntimeConfig` . `#[cfg(feature = "db")] db: DbConfig` . All `#[serde(default)]` .
- Each section struct derives `#[derive(Deserialize, ConfigFields)]` + `#[config_section(id, ncl_file)]`
— emits `inventory::submit!(ConfigFieldsEntry{...})` at link time.
- `DaemonRuntimeConfig` — optional port, timeouts, sweep intervals, `notification_ack_required: Vec<String>` .
#### `crates/ontoref-daemon/src/main.rs` — 3-tuple bootstrap block
- Bootstrap block changed to `(nickel_import_path, loaded_ncl_config, stdin_raw)` — `loaded_ncl_config: Option<DaemonNclConfig>`
replaces raw `Option<serde_json::Value>` . `stdin_raw: Option<serde_json::Value>` retained only
for service-mode `projects` extraction.
- `apply_stdin_config` now deserializes JSON to `DaemonNclConfig` before applying CLI overrides;
`apply_ui_config` signature changed from `&serde_json::Value` to `&UiConfig` .
- `load_config_overrides` returns `(Option<String>, Option<DaemonNclConfig>)` — all `.get("daemon").and_then(...)` chains
replaced with typed field access (`ncl.daemon.port` , etc.).
- NATS call site updated to `loaded_ncl_config.as_ref().map(|c| &c.nats_events)` .
- `resolve_asset_dir` gated with `#[cfg(feature = "ui")]` ; `#[allow(unused_variables)]` on bootstrap tuple for `--no-default-features` .
#### `crates/ontoref-derive/src/lib.rs` — `#[derive(ConfigFields)]` macro
- New `proc_macro_derive` `ConfigFields` with helper attribute `config_section(id, ncl_file)` .
Extracts serde-renamed field names; emits `inventory::submit!(ConfigFieldsEntry{section_id, ncl_file, struct_name, fields})` .
- Extracted `serde_rename_of(field)` helper to fix `clippy::excessive_nesting` (depth was 6).
Field names collected via `.iter().map(|f| serde_rename_of(f).unwrap_or_else(|| f.ident...)).filter(|s| !s.is_empty())` .
#### `crates/ontoref-daemon/src/config_coherence.rs` — clippy fixes
- `and_then(|_| full_export.as_ref())` → `.and(full_export.as_ref())` (unnecessary lazy evaluation).
- Extracted `merge_meta_into_section` helper to reduce nesting depth for `_meta_*` record merging.
#### `crates/ontoref-daemon/src/api.rs` — `index_section_fields` helper
- Extracted `index_section_fields` to fix `clippy::excessive_nesting` at the cross-project field indexing loop.
Skips `_meta_*` and `_overrides_meta` keys; indexes `(section_id, field) → Vec<(slug, value)>` .
#### `.ontoref/contracts.ncl` — new file
NCL contracts for ontoref's own config sections using `std.contract.from_validator` (not the deprecated `fun label value =>` pattern):
- `LogLevel` — enum validator: `error | warn | info | debug | trace`
- `LogRotation` — enum validator: `daily | hourly | never`
- `PositiveInt` — `value > 0 && is_number`
- `Port` — `value >= 1 && value <= 65535`
- `LogConfig` — applies per-field contracts + defaults (`level = "info"` , `rotation = "daily"` , `max_files = 7` )
- `DaemonConfig` — all fields optional (override-only); port, timeouts, intervals, `notification_ack_required`
#### `.ontoref/config.ncl` — contracts applied
- `let C = import "contracts.ncl"` added at top.
- `log | C.LogConfig = { ... }` — contract enforced before JSON reaches Rust.
#### `.ontology/manifest.ncl` — config surface enriched
- `contracts_path = ".ontoref"` added to `config_surface` .
- `log` section: `contract = "contracts.ncl → LogConfig"` added.
- New `daemon` section: `contract = "contracts.ncl → DaemonConfig"` , consumer `daemon-config` pointing to
`crates/ontoref-daemon/src/config.rs → DaemonRuntimeConfig` with 7 declared fields.
### Protocol
- ADR-007 extended: `#[derive(ConfigFields)]` is a second application of the `inventory::submit!` / `inventory::collect!`
linker registration pattern first established by `#[onto_api]` . Both are now referenced from the `config-surface` node.
- ADR-008 accepted: NCL-first config validation and override-layer mutation. NCL contracts are the single validation gate;
Rust structs are contract-trusted with `#[serde(default)]` . Config mutation writes `{section}.overrides.ncl` with
`_overrides_meta` audit record; original NCL source files are never modified. nickel export validates the merged
result before commit; contract violations revert the override file.
([adr-008 ](adrs/adr-008-ncl-first-config-validation-and-override-layer.ncl ))
### Self-Description — on+re Update
`.ontology/core.ncl` — new Practice node, updated nodes, 6 new edges:
| Change | Detail |
| --- | --- |
| New node `config-surface` | Yang — typed DaemonNclConfig, ConfigFields inventory registry, override-layer mutation API, NCL contracts, multi-consumer manifest schema; `adrs = ["adr-007", "adr-008"]` |
| Updated `adr-lifecycle` | ADR-007 + ADR-008 added to `artifact_paths` and `adrs` list (now 8 ADRs) |
New edges: `config-surface → ontoref-daemon` (ManifestsIn/High),
`config-surface → ontoref-ontology-crate` (DependsOn/High — ConfigFieldsEntry lives in zero-dep crate),
`config-surface → api-catalog-surface` (Complements/High — shared inventory pattern),
`config-surface → dag-formalized` (ManifestsIn/High),
`config-surface → self-describing` (Complements/High — ontoref validates its own config with its own contracts),
`config-surface → adopt-ontoref-tooling` (Complements/Medium).
`.ontology/state.ncl` — `protocol-maturity` blocker updated to record config surface completion.
`self-description-coverage` catalyst updated with session 2026-03-26 additions.
Previous: 4 axioms, 2 tensions, 27 practices. Current: 4 axioms, 2 tensions, 28 practices.
---
---
feat: API catalog surface, protocol v2 tooling, MCP expansion, on+re update
## Summary
Session 2026-03-23. Closes the loop between handler code and discoverability
across all three surfaces (browser, CLI, MCP agent) via compile-time inventory
registration. Adds protocol v2 update tooling, extends MCP from 21 to 29 tools,
and brings the self-description up to date.
## API Catalog Surface (#[onto_api] proc-macro)
- crates/ontoref-derive: new proc-macro crate; `#[onto_api(method, path,
description, auth, actors, params, tags)]` emits `inventory::submit!(ApiRouteEntry{...})`
at link time
- crates/ontoref-daemon/src/api_catalog.rs: `catalog()` — pure fn over
`inventory::iter::<ApiRouteEntry>()`, zero runtime allocation
- GET /api/catalog: returns full annotated HTTP surface as JSON
- templates/pages/api_catalog.html: new page with client-side filtering by
method, auth, path/description; detail panel per route (params table,
feature flag); linked from dashboard card and nav
- UI nav: "API" link (</> icon) added to mobile dropdown and desktop bar
- inventory = "0.3" added to workspace.dependencies (MIT, zero transitive deps)
## Protocol Update Mode
- reflection/modes/update_ontoref.ncl: 9-step DAG (5 detect parallel, 2 update
idempotent, 2 validate, 1 report) — brings any project from protocol v1 to v2
by adding manifest.ncl and connections.ncl if absent, scanning ADRs for
deprecated check_hint, validating with nickel export
- reflection/templates/update-ontology-prompt.md: 8-phase reusable prompt for
agent-driven ontology enrichment (infrastructure → audit → core.ncl →
state.ncl → manifest.ncl → connections.ncl → ADR migration → validation)
## CLI — describe group extensions
- reflection/bin/ontoref.nu: `describe diff [--fmt] [--file]` and
`describe api [--actor] [--tag] [--auth] [--fmt]` registered as canonical
subcommands with log-action; aliases `df` and `da` added; QUICK REFERENCE
and ALIASES sections updated
## MCP — two new tools (21 → 29 total)
- ontoref_api_catalog: filters catalog() output by actor/tag/auth; returns
{ routes, total } — no HTTP roundtrip, calls inventory directly
- ontoref_file_versions: reads ProjectContext.file_versions DashMap per slug;
returns BTreeMap<filename, u64> reload counters
- insert_mcp_ctx: audited and updated from 15 to 28 entries in 6 groups
- HelpTool JSON: 8 new entries (validate_adrs, validate, impact, guides,
bookmark_list, bookmark_add, api_catalog, file_versions)
- ServerHandler::get_info instructions updated to mention new tools
## Web UI — dashboard additions
- Dashboard: "API Catalog" card (9th); "Ontology File Versions" section showing
per-file reload counters from file_versions DashMap
- dashboard_mp: builds BTreeMap<String, u64> from ctx.file_versions and injects
into Tera context
## on+re update
- .ontology/core.ncl: describe-query-layer and adopt-ontoref-tooling descriptions
updated; ontoref-daemon updated ("11 pages", "29 tools", API catalog,
per-file versioning, #[onto_api]); new node api-catalog-surface (Yang/Practice)
with 3 edges; artifact_paths extended across 3 nodes
- .ontology/state.ncl: protocol-maturity blocker updated (protocol v2 complete);
self-description-coverage catalyst updated with session 2026-03-23 additions
- ADR-007: "API Surface Discoverability via #[onto_api] Proc-Macro" — Accepted
## Documentation
- README.md: crates table updated (11 pages, 29 MCP tools, ontoref-derive row);
MCP representative table expanded; API Catalog, Semantic Diff, Per-File
Versioning paragraphs added; update_ontoref onboarding section added
- CHANGELOG.md: [Unreleased] section with 4 change groups
- assets/web/src/index.html: tool counts 19→29 (EN+ES), page counts 12→11
(EN+ES), daemon description paragraph updated with API catalog + #[onto_api]
2026-03-23 00:58:27 +01:00
### API Catalog Surface — `#[onto_api]` proc-macro
Annotated HTTP surface discoverable at compile time via `inventory` .
- `crates/ontoref-derive/src/lib.rs` — `#[proc_macro_attribute] onto_api(method, path, description, auth, actors,
params, tags)` emits ` inventory::submit!(ApiRouteEntry{...})` for each handler; auth validated at compile time
(`none | viewer | admin` ); param entries parsed as `name:type:constraint:description` semicolon-delimited
- `crates/ontoref-daemon/src/api_catalog.rs` — `ApiRouteEntry` + `ApiParam` structs (`&'static str` fields for
process lifetime); `inventory::collect!(ApiRouteEntry)` ; `catalog()` returns sorted `Vec<&'static ApiRouteEntry>`
- `GET /api/catalog` — annotated with `#[onto_api]` ; returns all registered routes as JSON sorted by path+method;
no auth required
- `GET /projects/{slug}/ontology/versions` — per-file reload counters as `BTreeMap<filename, u64>` ;
counter bumped on every watcher-triggered NCL cache invalidation
- `describe api [--actor] [--tag] [--auth] [--fmt json|text]` — queries `/api/catalog` , groups by first tag,
renders auth badges, param detail per route; available as `onref da` alias
- `describe diff [--file <ncl>] [--fmt json|text]` — semantic diff of `.ontology/` files vs HEAD via
`git show HEAD:<rel> | mktemp | nickel export` ; diffs nodes by id, edges by `from→to[kind]` key;
available as `onref df` alias
- `ontoref_api_catalog` MCP tool — calls `api_catalog::catalog()` directly; filters by actor/tag/auth; returns `{ routes, total }`
- `ontoref_file_versions` MCP tool — reads `ProjectContext.file_versions` DashMap; returns per-filename counters
- Web UI: `/{slug}/api` page — table with client-side filtering (path, auth, method) + expandable detail panel; linked from nav and dashboard
- Dashboard: "Ontology File Versions" section showing per-file counters; "API Catalog" card
- `insert_mcp_ctx` in `handlers.rs` updated: 15 → 28 tools (previously stale for qa, bookmark, action, ontology extensions, validate, impact, guides)
- `HelpTool` JSON updated: 8 entries added (validate_adrs, validate, impact, guides, bookmark_list, bookmark_add, api_catalog, file_versions)
- `MCP ServerHandler::get_info()` instructions updated to mention `ontoref_guides` , `ontoref_api_catalog` , `ontoref_file_versions` , `ontoref_validate`
### Protocol Update Mode
- `reflection/modes/update_ontoref.ncl` — new mode bringing existing ontoref-adopted projects to protocol v2;
9-step DAG: 5 parallel detect steps (manifest, connections, ADR check_hint scan, ADRs missing check, daemon
/api/catalog probe), 2 parallel update steps (add-manifest, add-connections — both idempotent via
`test -f || sed` ), 2 validate steps (nickel export with explicit import paths), 1 aggregate report step
- `templates/ontology/manifest.ncl` — consumer-project stub; imports `ontology/defaults/manifest.ncl` via import-path-relative resolution
- `templates/ontology/connections.ncl` — consumer-project stub; imports `connections` schema; empty upstream/downstream/peers with format docs
- `reflection/modes/adopt_ontoref.ncl` — updated: adds `copy_ontology_manifest` and `copy_ontology_connections`
steps (parallel, `'Continue` , idempotent); `validate_ontology` depends on both with `'Always`
- `reflection/templates/update-ontology-prompt.md` — 8-phase reusable prompt for full ontology enrichment:
infrastructure update, audit, core.ncl nodes/edges, state.ncl dimensions, manifest.ncl assets,
connections.ncl cross-project, ADR migration, final validation
### CLI — `describe` group extensions and aliases
- `main describe diff` and `main describe api` wrappers in `reflection/bin/ontoref.nu`
- `main d diff` , `main d api` — short aliases within `d` group
- `main df` , `main da` — toplevel aliases (consistent with `d` , `ad` , `bkl` pattern)
- QUICK REFERENCE: `describe diff` , `describe api` , `run update_ontoref` entries added
- `help describe` description updated to include `diff, api surface`
### Self-Description — on+re Update
`.ontology/core.ncl` — 1 new Practice node, 3 updated nodes, 3 new edges:
| Change | Detail |
| --- | --- |
| New node `api-catalog-surface` | Yang — #[onto_api] proc-macro + inventory catalog; GET /api/catalog; describe api; ApiCatalogTool; /ui/{slug}/api page |
| Updated `describe-query-layer` | Description extended: describe diff (semantic vs HEAD) and describe api (annotated surface) |
| Updated `adopt-ontoref-tooling` | Description extended: update_ontoref mode, manifest/connections templates, enrichment prompt; artifact_paths updated |
| Updated `ontoref-daemon` | 11 pages, 29 MCP tools, per-file versioning, API catalog endpoint; artifact_paths: api_catalog.rs, api_catalog.html, crates/ontoref-derive/ |
| New edge `api-catalog-surface → ontoref-daemon` | ManifestsIn/High |
| New edge `api-catalog-surface → describe-query-layer` | Complements/High |
| New edge `api-catalog-surface → protocol-not-runtime` | Complements/Medium — catalog is link-time, no runtime |
`.ontology/state.ncl` — `self-description-coverage` catalyst updated (session 2026-03-23).
`protocol-maturity` blocker updated to reflect protocol v2 completeness.
Previous: 4 axioms, 2 tensions, 20 practices. Current: 4 axioms, 2 tensions, 21 practices.
---
2026-03-16 01:48:17 +00:00
### Personal Ontology Schemas & Content Modes
Three new typed NCL schema families added to `ontology/schemas/` and `ontology/defaults/` :
| Schema | Types exported |
| --- | --- |
| `career.ncl` | `Skill` , `WorkExperience` , `Talk` , `Positioning` , `CompanyTarget` , `PublicationCard` , `CareerConfig` |
| `personal.ncl` | `Content` (BlogPost / ConferenceProposal / CV / Application / Email / Thread), `Opportunity` (Job / Conference / Grant / Collaboration / Podcast), `PersonalConfig` |
| `project-card.ncl` | `ProjectCard` — canonical display metadata (name, tagline, status, tags, tools, features, sort_order) for portfolio and cv_repo publication |
All types carry `linked_nodes | Array String` referencing `.ontology/core.ncl` node IDs.
`PublicationCard` is a career overlay referencing a canonical `project_node` from the portfolio repo.
Five NCL DAG reflection modes added to `reflection/modes/` :
| Mode | Purpose |
| --- | --- |
| `draft-application` | Job/grant/collaboration application anchored in personal ontology — gate alignment check, node selection, career trajectory render, status update |
| `draft-email` | Context-grounded email composition using ontology nodes as evidence |
| `generate-article` | Blog post / thread generation from project nodes and tensions |
| `update-cv` | CV refresh loop querying current career.ncl and core.ncl state |
| `write-cfp` | Conference proposal from Practice/Project nodes with gate alignment check |
### Search Bookmarks
Bookmark persistence for search results over the ontology graph. Mirrors Q& A NCL pattern (ADR-003).
- `reflection/schemas/search_bookmarks.ncl` — `BookmarkEntry` (id, node_id, kind, title, level, term, actor, created_at, tags) and `BookmarkStore` contracts
- `reflection/search_bookmarks.ncl` — typed store file; conforms to `BookmarkStore` contract
- `crates/ontoref-daemon/src/ui/search_bookmarks_ncl.rs` — `add_entry` / `remove_entry` via
line-level NCL surgery; auto-incremented `sb-NNN` ids; concurrency-safe via `NclWriteLock`
Tests: `next_id_empty` , `next_id_increments` , `insert_into_empty_store` , `delete_first_entry` ,
`delete_second_entry` , `delete_missing_id_errors` , `escape_quotes_and_backslashes` ,
`concurrent_add_produces_unique_ids` (tokio, 6 concurrent tasks, asserts unique ids).
### Protocol
- ADR-006 accepted: Nushell 0.111 string interpolation compatibility fix. Four print statements in
`reflection/bin/ontoref.nu` used `(identifier: expr)` patterns inside `$"..."` — parsed as
command calls by Nu 0.111 parser. Fix: bare `identifier: (expr)` for label-value pairs; plain
strings (no `$` ) for zero-interpolation prints. Hard constraint: no `(label: expr)` inside
`$"..."` in any `.nu` file. Soft constraint: zero-interpolation strings must not use `$"..."` .
([adr-006 ](adrs/adr-006-nushell-0111-string-interpolation-compat.ncl ))
### Self-Description — on+re Update
`.ontology/core.ncl` — 3 new Practice nodes, updated `adr-lifecycle` and `ontoref-daemon` nodes:
| Change | Detail |
| --- | --- |
| New node `personal-ontology-schemas` | Yin — career/personal/project-card typed NCL schemas with linked_nodes DAG bridges |
| New node `content-modes` | Yang — 5 NCL DAG modes for personal content and career operations |
| New node `search-bookmarks` | Yin — bookmark persistence layer; NCL surgery via search_bookmarks_ncl.rs |
| `adr-lifecycle` | ADR-006 added to `artifact_paths` and `adrs` list |
| `ontoref-daemon` | `search_bookmarks_ncl.rs` added to `artifact_paths` |
New edges: `personal-ontology-schemas → dag-formalized` (ManifestsIn/High),
`personal-ontology-schemas → self-describing` (Complements/Medium),
`content-modes → reflection-modes` (ManifestsIn/High),
`content-modes → personal-ontology-schemas` (DependsOn/High),
`search-bookmarks → qa-knowledge-store` (Complements/High),
`search-bookmarks → ontoref-daemon` (ManifestsIn/High),
`ontoref-daemon → search-bookmarks` (Contains/High).
`.ontology/state.ncl` — `self-description-coverage` catalyst updated to include 2026-03-15 session
additions. `protocol-maturity` blocker updated to reflect Nu 0.111 fix and personal schema layer
completion.
Previous: 4 axioms, 2 tensions, 17 practices. Current: 4 axioms, 2 tensions, 20 practices.
---
### ADR– Node Declared Linkage
- `Node` schema extended with `adrs | Array String | default = []` (Nickel `ontology/schemas/core.ncl`
and inline `CoreConfig` type).
- Rust `Node` struct gains `artifact_paths: Vec<String>` and `adrs: Vec<String>` , both
`#[serde(default)]` — zero migration cost for existing nodes that omit the fields.
- `describe.nu` `build-howto` populates `adrs` from the node record; `render-howto` (ANSI),
`render-howto-md` , and `howto-to-md-string` (clipboard) all emit a **Validated by** section
when `adrs` is non-empty.
- New `GET /api/adr/{id}?slug=<slug>` endpoint — reads `adrs/<stem>.ncl` , exports via NCL
cache, returns JSON. No auth required (read-only, loopback boundary).
- Graph UI (`graph.html` ): `adrs` field passed into Cytoscape node data. Detail panel renders
"Validated by" section with clickable `◆ <adr-id>` buttons that open a DaisyUI modal
fetching full ADR content via the new endpoint.
- Fixed glob pattern error in `describe.nu:build-howto` : `glob $"($full)/*.rs"` replaced with
`glob ($full | path join "*.rs")` — eliminates `//` in pattern when path has trailing separator.
### Self-Description — on+re Update
`.ontology/core.ncl` — new node, updated nodes, new edges:
| Change | Detail |
| --- | --- |
| New node `adr-node-linkage` | Practice: declares `adrs` field pattern, lists all 5 modified artifacts |
| `adr-lifecycle` | Description updated; `adrs = ["adr-001"…"adr-005"]` declared |
| `describe-query-layer` | Description updated to mention Validated by rendering |
| `ontoref-ontology-crate` | Description updated to mention `artifact_paths` + `adrs` fields; `adrs = ["adr-001"]` |
| New edge `adr-node-linkage → adr-lifecycle` | ManifestsIn/High |
| New edge `adr-node-linkage → describe-query-layer` | Complements/High |
Previous: 4 axioms, 2 tensions, 16 practices. Current: 4 axioms, 2 tensions, 17 practices.
### Ontology Three-File Split
- New Practice node `ontology-three-file-split` in `.ontology/core.ncl` : documents the
`core.ncl` (what IS) / `state.ncl` (where we ARE vs want to BE) / `gate.ncl` (when READY
to cross a boundary) separation and the role of `reflection/` in answering self-knowledge
queries without reading code.
- `assets/presentation/slides.md` speaker note updated to English with reflection mention.
- `assets/web/src/index.html` "Scattered Project Knowledge" solution bullets updated (bilingual)
to express the three-file split and `reflection/` self-knowledge layer.
feat: unified auth model, project onboarding, install pipeline, config management
The full scope across this batch: POST /sessions key→token exchange, SessionStore dual-index with revoke_by_id, CLI Bearer injection (ONTOREF_TOKEN), ontoref setup
--gen-keys, install scripts, daemon config form roundtrip, ADR-004/005, on+re self-description update (fully-self-described), and landing page refresh.
2026-03-13 20:56:31 +00:00
### Auth & Session Model (ADR-005)
Unified key-to-session token exchange across all surfaces. All work gated on `#[cfg(feature = "ui")]` .
- `KeyEntry` gains `label: String` (`#[serde(default)]` ) — audit trail for key-based sessions.
NCL schema `install/resources/schemas/ontoref-project.ncl` updated accordingly.
- `verify_keys_list` returns `Option<KeyMatch { role, label }>` instead of `Option<Role>` .
- `SessionEntry` gains `id: String` — stable public identifier distinct from the bearer token,
safe to expose in list responses. Prevents session enumeration by admins.
- `SessionStore` gains secondary `id_index: DashMap<id, token>` for O(1) `revoke_by_id` .
- New `SessionStore` methods: `list_for_slug` , `list_all` , `revoke_all_for_slug` ,
`revoke_by_id(id, acting_slug, acting_role) -> RevokeResult` .
- `POST /sessions` — key → UUID v4 token exchange. Accepts project keys or daemon admin password
(`project: "_daemon"` ). Rate-limited. No authentication required (it is the credential exchange endpoint).
- `GET /sessions?project=slug` — list active sessions for a project (viewer+). Without `?project=`
param requires daemon admin and returns all sessions.
- `DELETE /sessions/{id}` — revoke by public id. Project admin: own project only. Daemon admin: any.
- `require_session()` helper: validates UUID v4 Bearer → `SessionEntry` , error boxed (`Box<Response>` )
to satisfy `clippy::result_large_err` .
- `check_primary_auth` fast-path: UUID v4 bearer → session lookup (O(1)) before argon2 fallback (~100ms).
- `project_update_keys` (`PUT /projects/{slug}/keys` ) now calls `sessions.revoke_all_for_slug` in
addition to actor deregistration. All in-flight UI sessions for the rotated project are immediately
invalidated.
- Daemon admin: `ONTOREF_ADMIN_TOKEN_FILE` (preferred — hash not visible in `ps aux` ) or
`ONTOREF_ADMIN_TOKEN` . Sessions use virtual slug `"_daemon"` .
- `manage_login_page` / `manage_login_submit` / `manage_logout` handlers for `/ui/manage/login`
and `/ui/manage/logout` .
- `AdminGuard` redirects to `/ui/manage/login` when `daemon_admin_hash` is set.
### CLI Bearer Token
- `bearer-args` exported from `reflection/modules/store.nu` : returns `["-H" "Authorization: Bearer $token"]`
when `ONTOREF_TOKEN` is set, `[]` otherwise.
- `http-get` , `http-post-json` , `http-delete` (new) in `store.nu` use `...$auth` — Bearer injected
transparently, no behavior change when `ONTOREF_TOKEN` is unset.
- `notify-daemon-project-add` and `notify-daemon-project-remove` in `reflection/bin/ontoref.nu`
use `bearer-args` .
### Project Setup & Onboarding
- `ontoref setup` is now the primary onboarding command (replaces manual `cp templates/` pattern).
- `--kind <K>` flag: `Service` (default) | `Library` | `DevWorkspace` | `PublishedCrate` |
`AgentResource` | `Mixed` .
- `--parent <path>` flag: generates manifest with `implementation` layer + `<slug>-framework` layer
and `<slug>-browse` op mode for implementation children.
- Logo auto-detection: `setup` scans `assets/` for `<slug>-logo.svg` , `<slug>.svg` , `logo.svg`
(and `.png` variants); inserts `ui.logo` into generated `config.ncl` when found.
- `--gen-keys ["admin:label" "viewer:label"]` flag: idempotent bootstrap — skips if `role =` already
present in `project.ncl` . Hashes via `ontoref-daemon.bin --hash-password` ; prints passwords once
to stdout.
- All `mkdir` calls in setup guarded by `if not (path | path exists)` .
### Self-Description — on+re Update
`.ontology/core.ncl` — 3 new Practice nodes, updated `ontoref-daemon` description and `artifact_paths` :
| Node | Pole | Description |
| --- | --- | --- |
| `unified-auth-model` | Yang | Key→session token exchange; session.id ≠ bearer; revoke on key rotation |
| `project-onboarding` | Yang | `ontoref setup` — idempotent scaffold, `--kind` , `--parent` , `--gen-keys` |
`ontoref-daemon` node updated: auth/session management added to description and `artifact_paths`
(`session.rs` , `auth.rs` , `login.rs` ).
New edges: `unified-auth-model → ontoref-daemon` , `unified-auth-model → no-enforcement`
(Contradicts/Low — auth is opt-in), `ontoref-daemon → unified-auth-model` (Contains),
`project-onboarding → unified-auth-model` (DependsOn),
`project-onboarding → adopt-ontoref-tooling` (Complements),
`project-onboarding → daemon-config-management` (DependsOn).
`.ontology/state.ncl` — `self-description-coverage` transitions to `current_state = "fully-self-described"` .
Blocker resolved: `reflection/backlog.ncl` created, ADR-005 recorded.
`reflection/backlog.ncl` — created with 6 items: bl-001 (ontoref.dev), bl-002 (first external project),
bl-003 (`ontoref keys` CLI), bl-004 (session UI views), bl-005 (Syntaxis migration),
bl-006 (ADR-001 acceptance).
Previous state: 4 axioms, 2 tensions, 13 practices. Current: 4 axioms, 2 tensions, 15 practices.
### Protocol
- ADR-004 accepted: NCL pipe bootstrap pattern —
`nickel export config.ncl | ontoref-daemon.bin --config-stdin` .
Stages: Nickel evaluation → optional SOPS/Vault merge → binary via stdin.
([adr-004 ](adrs/adr-004-ncl-pipe-bootstrap-pattern.ncl ))
- ADR-005 accepted: unified key-to-session auth model across CLI, UI, and MCP. Opaque UUID v4 tokens,
`session.id ≠ bearer` , revocation on key rotation, daemon admin via `_daemon` slug.
([adr-005 ](adrs/adr-005-unified-auth-session-model.ncl ))
---
### Install Infrastructure
- `install/` directory reorganized: binaries, bootstrapper, global CLI, resources, and validation
scripts co-located.
- Binary installed as `ontoref-daemon.bin` ; public entrypoint bootstrapper installed as `ontoref-daemon` .
Users never call `.bin` directly.
- `install/ontoref-daemon-boot` (renamed from `ontoref-daemon-start` ) — NCL pipe bootstrapper
implementing ADR-004. Stages: `nickel export config.ncl` → optional SOPS/Vault secret merge →
`ontoref-daemon.bin --config-stdin` . Supports `--dry-run` , `--sops` , `--vault` .
- `install/ontoref-daemon-boot` sets `NICKEL_IMPORT_PATH` (config dir + platform data dir schemas)
and `NATS_STREAMS_CONFIG` (default `~/.config/ontoref/streams.json` ) before launching the binary.
- `install/install.nu` — installs binary, bootstrapper, global `ontoref` CLI (ONTOREF_ROOT baked in
at install time), UI assets, config skeleton, and global NATS topology.
Hash-checked — unchanged files are not overwritten.
- `install/config-setup.nu` — standalone validation script: `nickel typecheck` + `nickel export` ,
path existence checks, DB and NATS liveness probes (`nc -z -w2` ).
- `install/check-config-sync.nu` — CI guard asserting that every `nickel_path` -bearing field in
`reflection/forms/config.ncl` has a matching `{{ name }}` reference in `reflection/forms/config.ncl.j2` ,
and vice versa. Wired into `just ci-lint` and `just ci-full` .
### Config Management
- `install/resources/config.ncl` — default global config skeleton with full Nickel contracts
(`Port` , `LogLevel` , `Rotation` , `Actor` , `Severity` ). Covers: daemon, db, nats_events, log,
cache, ui, mode_run, actor_init, quick_actions, nickel_import_paths.
- `install/resources/streams.json` — global default NATS JetStream topology: ECOSYSTEM stream
(`ecosystem.>` , 30-day retention), no project-specific consumers.
Installed to `~/.config/ontoref/streams.json` .
- `nats/streams.json` — ontoref project-local topology with `daemon-ontoref` and `cli-notifications`
consumers on ECOSYSTEM stream.
- `reflection/forms/config.ncl` + `reflection/forms/config.ncl.j2` — typedialog roundtrip for
browser-based config editing (`ontoref config-edit` ). Form populates fields from existing config
via `nickel_path` ; Tera template reconstructs full NCL with all contracts on save.
- `reflection/nulib/bootstrap.nu` — Nu bootstrapper helper updated: `nats-streams-config` function
resolves `NATS_STREAMS_CONFIG` default; env var passed to daemon process via `with-env` .
- Daemon `nats.rs` : empty `streams_config` string → `None` , activating `TopologyConfig::load` fallback
to `NATS_STREAMS_CONFIG` env var. Projects with a local `nats/streams.json` set `streams_config`
explicitly in their config.
### Daemon Fixes
- `--config-stdin` now exclusively skips `.ontoref/config.ncl` — project config is never loaded when
stdin config is active. Previously both paths could run.
- DB connection (`stratum-db` ) only established when `db.enabled = true` in config. Previously
connected regardless of `enabled` flag.
- NATS connection (`platform-nats` ) only established when `nats_events.enabled = true` .
"Connecting to NATS..." log moved after the enabled check.
- `NatsPublisher::connect` signature changed from `config_path: &PathBuf` (re-read file) to
`config: Option<&serde_json::Value>` (already-loaded JSON). Eliminates double file read and ensures
NATS uses the same config source as the rest of the daemon.
- `load_config_overrides` returns `(Option<String>, Option<serde_json::Value>)` — nickel import path
and parsed config JSON returned together. `apply_stdin_config` returns `serde_json::Value` directly.
### Self-Description — on+re Update
`.ontology/core.ncl` — 1 new Practice node, updated `ontoref-daemon` description and artifact_paths:
| Node | Pole | Description |
| --- | --- | --- |
| `daemon-config-management` | Yang | Install + config form/template roundtrip, CI guard, global NATS topology, config-setup validation |
New edges: `daemon-config-management → ontoref-daemon` (DependsOn),
`daemon-config-management → adopt-ontoref-tooling` (Complements).
`.ontology/state.ncl` — `operational-mode` dimension description updated to reference ADR-004 bootstrap
and `NATS_STREAMS_CONFIG` mechanism. `protocol-maturity` blocker updated to reflect install pipeline
completion.
`.ontology/manifest.ncl` — `tooling` layer paths updated to include `install/` and `nats/` .
Previous state: 4 axioms, 2 tensions, 12 practices. Current: 4 axioms, 2 tensions, 13 practices.
2026-03-13 00:15:49 +00:00
### Protocol
- ADR-001 accepted: ontoref extracted as a standalone protocol project, independent of
stratumiops versioning and release cycle. Consumer projects adopt via `scripts/ontoref`
wrapper + `.ontoref/config.ncl` .
([adr-001 ](adrs/adr-001-protocol-as-standalone-project.ncl ))
- ADR-002 accepted: `ontoref-daemon` introduced as optional persistent daemon for NCL export
caching (keyed by path+mtime), actor registry (developer/agent/CI), and notification barrier
(pre-commit hook, fail-open). Supersedes stratumiops ADR-007.
([adr-002 ](adrs/adr-002-daemon-for-caching-and-notification-barrier.ncl ))
- ADR-003 accepted: Q& A and accumulated operational knowledge persist to `reflection/qa.ncl`
— typed NCL, git-versioned, accessible via MCP tools and HTTP endpoints. localStorage
eliminated. Q& A entries survive session boundaries and are queryable by any actor.
([adr-003 ](adrs/adr-003-qa-and-knowledge-persistence-as-ncl.ncl ))
### Crates
feat: unified auth model, project onboarding, install pipeline, config management
The full scope across this batch: POST /sessions key→token exchange, SessionStore dual-index with revoke_by_id, CLI Bearer injection (ONTOREF_TOKEN), ontoref setup
--gen-keys, install scripts, daemon config form roundtrip, ADR-004/005, on+re self-description update (fully-self-described), and landing page refresh.
2026-03-13 20:56:31 +00:00
- `ontoref-ontology` : Rust crate for loading `.ontology/*.ncl` as typed structs (`Core` , `Gate` ,
`State` ). Zero stratumiops dependencies.
- `ontoref-reflection` : Rust crate for loading, validating, and executing Reflection modes as NCL
DAG contracts. Optional `nats` feature (path dep: `platform-nats` ).
2026-03-13 00:15:49 +00:00
- `ontoref-daemon` : Rust crate providing HTTP API (axum), DashMap-backed NCL export cache,
notify-based file watcher, and actor registry. Optional `db` feature (path dep: `stratum-db` )
and `nats` feature (path dep: `platform-nats` ).
### Daemon — Q&A NCL Persistence (`crates/ontoref-daemon/src/ui/qa_ncl.rs`)
feat: unified auth model, project onboarding, install pipeline, config management
The full scope across this batch: POST /sessions key→token exchange, SessionStore dual-index with revoke_by_id, CLI Bearer injection (ONTOREF_TOKEN), ontoref setup
--gen-keys, install scripts, daemon config form roundtrip, ADR-004/005, on+re self-description update (fully-self-described), and landing page refresh.
2026-03-13 20:56:31 +00:00
Line-level NCL surgery for `reflection/qa.ncl` — same pattern as `backlog_ncl.rs` . No AST parsing,
no nickel-lang-core dependency.
2026-03-13 00:15:49 +00:00
- `add_entry` — appends a typed `QaEntry` block before `],` array close; generates sequential `qa-NNN` ids
- `update_entry` — in-place field mutation via bidirectional scan (question + answer fields)
- `remove_entry` — removes the full block by id using backward scan for `{` and forward scan for `},`
HTTP endpoints (all under `#[cfg(feature = "ui")]` except read-only GET):
feat: unified auth model, project onboarding, install pipeline, config management
The full scope across this batch: POST /sessions key→token exchange, SessionStore dual-index with revoke_by_id, CLI Bearer injection (ONTOREF_TOKEN), ontoref setup
--gen-keys, install scripts, daemon config form roundtrip, ADR-004/005, on+re self-description update (fully-self-described), and landing page refresh.
2026-03-13 20:56:31 +00:00
2026-03-13 00:15:49 +00:00
- `GET /qa-json` — export all Q& A entries as JSON (read-only, always enabled)
- `POST /qa/add` — append new entry; returns generated id
- `POST /qa/delete` — remove entry by id; invalidates NCL cache
- `POST /qa/update` — mutate question + answer fields by id; invalidates NCL cache
- `GET /actions/run` / `POST /actions/run` — execute a quick action by id; spawns `./ontoref <mode>`
Server-side hydration: `qa.html` receives `entries` as Tera context variable, embeds
`SERVER_ENTRIES` JSON literal in the page `<script>` — no fetch round-trip on load.
### Daemon — MCP Tools (`crates/ontoref-daemon/src/mcp/mod.rs`)
Four new MCP tools exposed to AI agents:
| Tool | Description |
| --- | --- |
| `ontoref_qa_list` | List Q& A entries with optional `filter` substring match. Never triggers ontology sync. |
| `ontoref_qa_add` | Append a new Q& A entry to `reflection/qa.ncl` ; invalidates NCL cache. |
| `ontoref_action_list` | List all quick actions from `.ontoref/config.ncl` export. |
| `ontoref_action_add` | Create a new reflection mode at `reflection/modes/<id>.ncl` and register it as a quick action. |
feat: unified auth model, project onboarding, install pipeline, config management
The full scope across this batch: POST /sessions key→token exchange, SessionStore dual-index with revoke_by_id, CLI Bearer injection (ONTOREF_TOKEN), ontoref setup
--gen-keys, install scripts, daemon config form roundtrip, ADR-004/005, on+re self-description update (fully-self-described), and landing page refresh.
2026-03-13 20:56:31 +00:00
Constraint: `ontoref_qa_list` and `ontoref_qa_add` never trigger `apply` steps or modify `.ontology/`
files (enforced by ADR-003).
2026-03-13 00:15:49 +00:00
### Daemon — Passive Drift Observation (`crates/ontoref-daemon/src/ui/drift_watcher.rs`)
Background observer bridging Yang code artifacts with Yin ontology declarations:
- Watches `crates/` , `.ontology/` , `adrs/` , `reflection/modes/` via `notify` file watcher
- 15-second debounce window before triggering scan
- Spawns `./ontoref sync scan && ./ontoref sync diff` as read-only subprocesses
- Parses stdout for MISSING / STALE / DRIFT / BROKEN markers
- Emits `ontology_drift` notification via `push_custom` when any drift is found
- Never applies changes automatically — `apply` remains a deliberate human or agent act
Started from `main.rs` under `#[cfg(feature = "ui")]` ; failure to start is non-fatal (logged as warning).
### Tooling
feat: unified auth model, project onboarding, install pipeline, config management
The full scope across this batch: POST /sessions key→token exchange, SessionStore dual-index with revoke_by_id, CLI Bearer injection (ONTOREF_TOKEN), ontoref setup
--gen-keys, install scripts, daemon config form roundtrip, ADR-004/005, on+re self-description update (fully-self-described), and landing page refresh.
2026-03-13 20:56:31 +00:00
- `reflection/modules/` : 16 Nushell operational modules (`adr.nu` , `backlog.nu` , `coder.nu` ,
`describe.nu` , `sync.nu` , etc.)
- `reflection/modes/` : 10 NCL DAG operational modes including `adopt_ontoref` , `sync-ontology` ,
`coder-workflow` , `create-pr`
2026-03-13 00:15:49 +00:00
- `reflection/forms/` : 7 interactive NCL forms for ADR lifecycle, backlog, and adoption
- `templates/` : Consumer-facing adoption templates (`ontoref-config.ncl` , `ontology/` , `scripts-ontoref` )
feat: unified auth model, project onboarding, install pipeline, config management
The full scope across this batch: POST /sessions key→token exchange, SessionStore dual-index with revoke_by_id, CLI Bearer injection (ONTOREF_TOKEN), ontoref setup
--gen-keys, install scripts, daemon config form roundtrip, ADR-004/005, on+re self-description update (fully-self-described), and landing page refresh.
2026-03-13 20:56:31 +00:00
- `./ontoref` : Bash entry point with actor auto-detection, advisory file locking, and Nushell version
guard (>= 0.110.0)
2026-03-13 00:15:49 +00:00
### Self-Description — on+re Update
`.ontology/core.ncl` updated with 3 new Practice nodes and 9 new edges:
| Node | Pole | Description |
| --- | --- | --- |
| `qa-knowledge-store` | Yin | Q& A entries as typed NCL — accumulated knowledge queryable by any actor |
| `quick-actions` | Yang | Runnable shortcuts over reflection modes; configured in `.ontoref/config.ncl` |
| `drift-observation` | Spiral | Passive bridge between Yang code artifacts and Yin ontology declarations |
New edges: `qa-knowledge-store → dag-formalized` , `qa-knowledge-store → coder-process-memory` ,
`ontoref-daemon → qa-knowledge-store` , `quick-actions → reflection-modes` ,
`quick-actions → ontoref-daemon` , `describe-query-layer → quick-actions` ,
`drift-observation → ontoref-daemon` , `drift-observation → ontology-vs-reflection` ,
`drift-observation → reflection-modes` .
Previous state: 4 axioms, 2 tensions, 9 practices. Current: 4 axioms, 2 tensions, 12 practices.
feat: unified auth model, project onboarding, install pipeline, config management
The full scope across this batch: POST /sessions key→token exchange, SessionStore dual-index with revoke_by_id, CLI Bearer injection (ONTOREF_TOKEN), ontoref setup
--gen-keys, install scripts, daemon config form roundtrip, ADR-004/005, on+re self-description update (fully-self-described), and landing page refresh.
2026-03-13 20:56:31 +00:00
`reflection/schemas/qa.ncl` — `QaStore` and `QaEntry` types (id, question, answer, actor, created_at,
tags, related, verified).
2026-03-13 00:15:49 +00:00
`reflection/qa.ncl` — typed store file, conforms to `QaStore` contract, Nickel typecheck must pass.
---
*ontoref uses its own ADR system to track decisions. Architectural rationale lives in `adrs/` , not in this file.*