ontoref/CHANGELOG.md
Jesús Pérez 75892a8eea
Some checks failed
Rust CI / Security Audit (push) Has been cancelled
Rust CI / Check + Test + Lint (nightly) (push) Has been cancelled
Rust CI / Check + Test + Lint (stable) (push) Has been cancelled
Nickel Type Check / Nickel Type Checking (push) Has been cancelled
feat: browser-style panel nav, repo file routing, migration 0007
graph, search, api_catalog pages: back/forward history stack (PanelNav/dpNav).
  File artifact paths open in external tabs via card.repo (Gitea source URL) or
  card.docs (cargo docs for .rs) — openFile/openFileInPanel removed from all pages.
  Tera | safe required for URL values inside <script> blocks (auto-escape of slashes).

  card.ncl: repo field added.
  insert_brand_ctx: injects card_repo/card_docs into Tera context.
  #[onto_api] proc-macro: source_file = file!() emitted; ApiRouteEntry.source_file
  populated in primary catalog handler.

  migration 0007-card-repo-field: check card.ncl for repo field; skip if absent.
2026-03-29 08:32:50 +01:00

42 KiB
Raw Blame History

Changelog

All notable changes to ontoref are documented here. ADRs referenced below live in adrs/ as typed Nickel records.


[Unreleased]

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

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-interrogationcapabilities[] 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-entrypointAgent 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 (0020002).
  • Applied state: run-migration-check dispatches over FileExists | Grep | NuCmd.
  • No state file — idempotent by construction.

reflection/nulib/interactive.nu + help.numigrate group wired

  • group-command-infomigrate case added (list, pending, show).
  • run-group-commandmigrate dispatch added.
  • help-groupmigrate 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

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_typeid, 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_typeid, name, env, kind, version, required, impact, provision.
  • critical_dep_typeid, 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

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.rsindex_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
  • PositiveIntvalue > 0 && is_number
  • Portvalue >= 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)

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.nclprotocol-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.


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.rsApiRouteEntry + 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.nclself-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.


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.nclBookmarkEntry (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.rsadd_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)

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.nclself-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.


ADRNode 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.

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.nclself-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)
  • 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)

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.ncloperational-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.ncltooling layer paths updated to include install/ and nats/.

Previous state: 4 axioms, 2 tensions, 12 practices. Current: 4 axioms, 2 tensions, 13 practices.

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)
  • 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)
  • 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)

Crates

  • 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).
  • 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)

Line-level NCL surgery for reflection/qa.ncl — same pattern as backlog_ncl.rs. No AST parsing, no nickel-lang-core dependency.

  • 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):

  • 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.

Constraint: ontoref_qa_list and ontoref_qa_add never trigger apply steps or modify .ontology/ files (enforced by ADR-003).

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

  • 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
  • reflection/forms/: 7 interactive NCL forms for ADR lifecycle, backlog, and adoption
  • templates/: Consumer-facing adoption templates (ontoref-config.ncl, ontology/, scripts-ontoref)
  • ./ontoref: Bash entry point with actor auto-detection, advisory file locking, and Nushell version guard (>= 0.110.0)

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.

reflection/schemas/qa.nclQaStore and QaEntry types (id, question, answer, actor, created_at, tags, related, verified). 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.