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]
8.8 KiB
Ontoref Protocol Update — Ontology Enrichment Prompt
Purpose: Bring {project_name} up to the current ontoref protocol version and enrich its
ontology to reflect the project's actual state. Run this prompt in the project's Claude Code
session with ontoref available.
Substitutions required before use:
{project_name}— kebab-case project identifier{project_dir}— absolute path to project root{ontoref_dir}— absolute path to the ontoref checkout
Context for the agent
You are enriching the ontoref ontology for project {project_name}. The ontology lives in
.ontology/ and the reflection layer in reflection/. Your goal is to make the ontology
reflect current architectural reality — not aspirational state, not stale state.
Read the project's .claude/CLAUDE.md and any CLAUDE.md at root before starting. Understand
what the project actually does. All changes must pass nickel export cleanly.
Phase 1 — Infrastructure: add missing v2 files
Run the infrastructure detection and update steps. These are additive — nothing is overwritten.
cd {project_dir}
# Step 1a: detect missing files
test -f .ontology/manifest.ncl && echo "manifest: present" || echo "manifest: MISSING"
test -f .ontology/connections.ncl && echo "connections: present" || echo "connections: MISSING"
# Step 1b: add manifest.ncl if missing
test -f .ontology/manifest.ncl || \
sed 's/{{ project_name }}/{project_name}/g' \
{ontoref_dir}/templates/ontology/manifest.ncl > .ontology/manifest.ncl
# Step 1c: add connections.ncl if missing
test -f .ontology/connections.ncl || \
sed 's/{{ project_name }}/{project_name}/g' \
{ontoref_dir}/templates/ontology/connections.ncl > .ontology/connections.ncl
# Step 1d: validate both files parse
nickel export --import-path {ontoref_dir}/ontology:{ontoref_dir}/ontology/schemas:{ontoref_dir}/ontology/defaults:{ontoref_dir} \
.ontology/manifest.ncl > /dev/null && echo "manifest: ok"
nickel export --import-path {ontoref_dir}/reflection/schemas:{ontoref_dir} \
.ontology/connections.ncl > /dev/null && echo "connections: ok"
If either validation fails, read the file, fix the import path or schema mismatch, and revalidate before continuing.
Phase 2 — Audit: understand current state
Run these commands and read the output before making any changes to core.ncl or state.ncl.
# Full project self-description (identity, axioms, practices, gate)
./scripts/ontoref describe project
# Semantic diff vs HEAD — shows what changed since last commit
./scripts/ontoref describe diff
# What modes are available, what gates allow
./scripts/ontoref describe guides
# Current gate state and dimension health
./scripts/ontoref describe gate
# API surface available (requires daemon running)
./scripts/ontoref describe api
Read the output of each command. Note:
- Which dimensions are in non-ideal states and why
- Which practices have no corresponding nodes in core.ncl
- What the diff reports as added/removed/changed since HEAD
- Whether the gate is aligned with what the project actually does today
Phase 3 — Enrich core.ncl
Open .ontology/core.ncl. For each of the following, apply only what is actually true:
3a. Nodes — add missing, update stale descriptions
For any practice or capability the project has implemented since the last ontology update, add a node with:
id— kebab-case, stable identifierlevel—'Protocol | 'Integration | 'Application | 'Toolingpole—'Positive | 'Negative | 'Tensiondescription— one sentence, present tense, what it IS (not what it should be)adrs— list any ADR IDs that govern this nodepractices— list practice slugs if declared in.ontology/state.ncl
Do NOT add aspirational nodes. If a feature is not yet implemented, do not add it.
3b. Edges — declare real dependencies
For any new nodes, declare edges to the nodes they depend on or implement:
{ from = "new-node-id", to = "existing-node-id", kind = 'Implements }
Valid edge kinds: 'Implements | 'Depends | 'Extends | 'Supersedes | 'Tensions
3c. Tensions — update descriptions
For tension nodes (pole = 'Tension), update the description to reflect the current root cause if it has changed. Tensions describe real trade-offs the project has made, not theoretical ones.
After editing, validate:
nickel export --import-path {ontoref_dir}/ontology:{ontoref_dir} .ontology/core.ncl > /dev/null
Phase 4 — Update state.ncl
Open .ontology/state.ncl. For each dimension:
- Read
current_stateandtransitionconditions - Check whether a transition condition has been met based on recent work
- If the project has advanced: update
current_stateto the new state - Update
blockerandcatalystto reflect current reality (not stale reasoning)
Do NOT advance a dimension optimistically. Only advance if the transition condition is demonstrably met (code exists, tests pass, ADR written — not "in progress").
After editing:
nickel export --import-path {ontoref_dir}/ontology:{ontoref_dir}/ontology/defaults:{ontoref_dir} \
.ontology/state.ncl > /dev/null
Phase 5 — Fill manifest.ncl
Open .ontology/manifest.ncl. Declare any content assets the project has:
- Branding assets (logos, icons) in
assets/branding/or equivalent - Architecture diagrams in
docs/,assets/, orarchitecture/ - Screenshots or demo recordings
- Agent prompt templates in
reflection/templates/ - Mode step templates in
reflection/templates/
For each asset, use m.make_asset with accurate source_path (relative to project root),
correct kind, and a one-sentence description. Only declare assets that actually exist on disk.
Check:
ls assets/ 2>/dev/null; ls docs/ 2>/dev/null; ls reflection/templates/ 2>/dev/null
After editing:
nickel export \
--import-path {ontoref_dir}/ontology:{ontoref_dir}/ontology/schemas:{ontoref_dir}/ontology/defaults:{ontoref_dir} \
.ontology/manifest.ncl > /dev/null
Phase 6 — Declare connections.ncl
Open .ontology/connections.ncl. Declare cross-project relationships if they exist:
upstream— projects this one depends on or consumes APIs fromdownstream— projects that consume this one's APIs or outputspeers— symmetric sibling services with shared concerns
For each connection: project must be a slug registered in the shared daemon, node is an
ontology node id in that project, via is "http" | "local" | "nats".
If no cross-project relationships exist, leave all arrays empty — that is valid and correct. Do NOT invent connections.
After editing:
nickel export --import-path {ontoref_dir}/reflection/schemas:{ontoref_dir} \
.ontology/connections.ncl > /dev/null
Phase 7 — Migrate ADR check_hint (if present)
Check for deprecated check_hint fields:
grep -rl 'check_hint' {project_dir}/adrs/ 2>/dev/null
If any files are found, for each ADR:
- Read the
check_hintstring — it describes what to verify - Map it to the closest typed
checkvariant:- Shell command →
'NuCmd { cmd = "...", expect_exit = 0 } - File search (grep/rg) →
'Grep { pattern = "...", paths = ["..."], must_be_empty = true } - Cargo.toml dep check →
'Cargo { crate = "...", forbidden_deps = ["..."] } - File presence →
'FileExists { path = "...", present = true } - API response →
'ApiCall { endpoint = "...", json_path = "...", expected = ... }
- Shell command →
- Replace
check_hintwithcheckusing the typed variant - Validate:
nickel export --import-path {ontoref_dir}/adrs:{ontoref_dir} adrs/adr-NNN-*.ncl > /dev/null
Phase 8 — Final validation
Run all validations in sequence:
# All .ontology/ files
for f in .ontology/core.ncl .ontology/state.ncl .ontology/gate.ncl \
.ontology/manifest.ncl .ontology/connections.ncl; do
nickel export \
--import-path {ontoref_dir}/ontology:{ontoref_dir}/ontology/schemas:\
{ontoref_dir}/ontology/defaults:{ontoref_dir}/reflection/schemas:{ontoref_dir} \
"$f" > /dev/null && echo "ok: $f" || echo "FAIL: $f"
done
# All ADRs
for f in adrs/adr-*.ncl; do
nickel export --import-path {ontoref_dir}/adrs:{ontoref_dir} $f > /dev/null && echo "ok: $f" || echo "FAIL: $f"
done
# Re-run describe diff to confirm changes are coherent
./scripts/ontoref describe diff
After all files pass, run the protocol update report:
./scripts/ontoref describe project
Delivery
Report:
- Files changed and what was changed in each
- Nodes added / updated / removed in core.ncl
- Dimension state transitions applied in state.ncl
- Assets declared in manifest.ncl
- Connections declared in connections.ncl
- ADRs migrated from check_hint to typed check
- Any validation errors that could not be resolved (with reason)
Do NOT commit. The developer reviews the diff before committing.