description = "Onref is a protocol specification and tooling layer. It is never a runtime dependency. Projects implement the protocol; onref provides the schemas and modules to do so.",
invariant = true,
},
d.make_node {
id = "self-describing",
name = "Self-Describing",
pole = 'Yang,
level = 'Axiom,
description = "Onref describes itself using its own protocol. The .ontology/, adrs/, and reflection/ directories in this repository are onref consuming ontoref.",
description = "Onref defines contracts and patterns. There is no enforcement mechanism. Coherence is voluntary and emerges from justified adoption.",
invariant = true,
},
d.make_node {
id = "dag-formalized",
name = "DAG-Formalized Knowledge",
pole = 'Yin,
level = 'Axiom,
description = "All project knowledge — concepts, tensions, decisions, state — is formalized as directed acyclic graphs. This enables transversal queries, impact analysis, and ecosystem-level visibility.",
description = "Richer formalization produces better ecosystem visibility but increases the cost of adoption. The balance: schemas are optional layers, not mandatory gates.",
},
d.make_node {
id = "ontology-vs-reflection",
name = "Ontology vs Reflection",
pole = 'Spiral,
level = 'Tension,
description = "Ontology captures what IS (invariants, structure, being). Reflection captures what BECOMES (operations, drift, memory). Both must coexist without one dominating. This tension is onref's core identity.",
description = "Architectural decisions follow: Proposed → Accepted → Superseded. Superseded ADRs retain constraints for historical reconstruction. Active Hard constraints drive the constraint set. Nodes declare which ADRs validate them via the adrs field — surfaced by describe and the daemon graph UI.",
description = "Operational procedures are first-class artifacts encoded as NCL DAG contracts. Modes declare actors, steps, dependencies, and error strategies — not prose. Forms (reflection/forms/) provide structured input schemas that feed into modes and the compose pipeline.",
description = "Session knowledge is captured as structured JSONL via coder record. Queryable, exportable, and promotable to reflection/knowledge/. The memory layer between sessions.",
description = "describe.nu aggregates all project sources and answers self-knowledge queries: what IS this, what can I DO, what can I NOT do, what tools exist, what is the impact of changing X. Renders Validated by section when a node declares adrs. describe diff computes a semantic diff of .ontology/ files vs HEAD — nodes/edges added/removed/changed without text diffing. describe api queries GET /api/catalog and renders the annotated HTTP surface grouped by tag, filterable by actor/auth.",
description = "Rust implementation for loading and querying .ontology/ NCL files as typed structs. Provides Core, Gate, and State types for ecosystem-level introspection. Node carries artifact_paths (Vec<String>) and adrs (Vec<String>) — both serde(default) for zero-migration backward compatibility.",
description = "Migration system for onboarding existing projects into the ontoref protocol. adopt_ontoref mode installs .ontoref/, .ontology/ stubs (core, state, gate, manifest, connections), config.ncl template, and scripts/ontoref wrapper — all idempotent. update_ontoref mode brings already-adopted projects to the current protocol version: adds manifest.ncl (content assets) and connections.ncl (cross-project federation) if missing, scans ADR migration status, validates both files, and prints a protocol update report. The 8-phase update-ontology-prompt.md guides an agent through full ontology enrichment on any project.",
description = "Progressive, ordered protocol migrations for consumer projects. Each migration is an NCL file in reflection/migrations/NNN-slug.ncl declaring id, slug, description, a typed check (FileExists | Grep | NuCmd), and instructions interpolated at runtime with project_root and project_name. Applied state is determined solely by whether the check passes — no state file, fully idempotent. NuCmd checks must be valid Nushell (no bash &&, $env.VAR not $VAR). Accessible via `ontoref migrate list/pending/show` and the interactive group dispatch. Narrows ADR instance checks to `adr-[0-9][0-9][0-9]-*.ncl` to exclude schema/template infrastructure files from pattern matching.",
description = "The .ontology/ directory separates three orthogonal concerns into three files. core.ncl captures what the project IS — invariant axioms and structural tensions; touching invariant=true nodes requires a new ADR. state.ncl captures where it IS vs where it wants to BE — current and desired state per dimension. gate.ncl defines when it is READY to cross a boundary — active membranes protecting key conditions. reflection/ reads all three and answers self-knowledge queries. This separation lets an agent understand a project without reading code — only by consulting the declarative graph.",
description = "Nodes declare which ADRs validate them via the adrs field (Array String). This makes the ADR→Node relationship explicit in the graph rather than implicit in prose. describe surfaces a Validated by section per node. The daemon graph UI renders each ADR as a clickable link opening the full ADR via GET /api/adr/{id}. Field is serde(default) and Nickel default=[] — zero migration cost for existing nodes.",
description = "HTTP daemon for NCL export caching, file watching, actor registry, MCP surface, and GraphQL API. Provides notification barrier, HTTP API, MCP server (stdio + streamable-HTTP), GraphQL endpoint (async-graphql 8, Apollo Federation v2, WebSocket subscriptions), Q&A NCL persistence, quick-actions catalog, passive drift observation, unified auth/session model (ADR-005), runtime service toggles (ADR-014), and annotated API catalog (GET /api/catalog). API catalog populated at link time via #[onto_api] proc-macro + inventory — zero runtime overhead. Launched via ADR-004 NCL pipe bootstrap: nickel export config.ncl | ontoref-daemon.bin --config-stdin. Optional services (MCP, GraphQL) are feature-gated and runtime-toggleable via PUT /api/services/:service or UI manage page — changes take effect immediately without restart.",
description = "Every HTTP handler is annotated with #[onto_api(method, path, description, auth, actors, params, tags)] — a proc-macro attribute that emits an inventory::submit!(ApiRouteEntry{...}) at link time. inventory::collect!(ApiRouteEntry) aggregates all entries into a zero-cost static catalog. GET /api/catalog serves the full annotated surface as JSON, sorted by path+method. describe api queries the catalog and renders it grouped by tag, filterable by actor/auth in the CLI. ApiCatalogTool exposes the catalog to MCP agents. The /ui/{slug}/api web page renders it with client-side filtering and a parameter detail panel.",
description = "All surfaces (CLI, UI, MCP) exchange a raw key for a UUID v4 session token via POST /sessions (30-day lifetime, O(1) lookup vs O(~100ms) argon2 per request). Project keys carry role (admin|viewer) and label for audit trail. Daemon admin sessions use virtual slug '_daemon'. ONTOREF_TOKEN injected as Bearer by CLI automatically. Sessions have a stable public id (distinct from bearer token) for safe list/revoke operations. Key rotation revokes all sessions for the rotated project.",
invariant = false,
artifact_paths = [
"crates/ontoref-daemon/src/session.rs",
"crates/ontoref-daemon/src/api.rs",
"crates/ontoref-daemon/src/registry.rs",
"crates/ontoref-daemon/src/ui/login.rs",
"crates/ontoref-daemon/src/ui/auth.rs",
"reflection/modules/store.nu",
"install/resources/schemas/ontoref-project.ncl",
],
},
d.make_node {
id = "project-onboarding",
name = "Project Onboarding",
pole = 'Yang,
level = 'Practice,
description = "Idempotent onboarding via `ontoref setup`. Creates .ontoref/project.ncl, .ontoref/config.ncl (with logo auto-detection in assets/), .ontology/ scaffold, adrs/, reflection/modes/, backlog.ncl, qa.ncl, git hooks, and registers in projects.ncl. Supports --kind (repo_kind) and --parent (framework layers + browse modes for implementation children). Bootstrap key generation via --gen-keys ['admin:label' 'viewer:label']: idempotent (no-op if keys exist), hashes via daemon binary, prints passwords once.",
invariant = false,
artifact_paths = [
"reflection/bin/ontoref.nu",
"templates/project.ncl",
"templates/ontoref-config.ncl",
"templates/ontology/",
"install/gen-projects.nu",
"install/resources/schemas/ontoref-project.ncl",
],
},
d.make_node {
id = "daemon-config-management",
name = "Daemon Config Management",
pole = 'Yang,
level = 'Practice,
description = "Install and configuration infrastructure for ontoref-daemon. Global config at ~/.config/ontoref/config.ncl (Nickel, type-checked). Browser-based editing via typedialog roundtrip: form (config.ncl) → browser → Tera template (config.ncl.j2) → updated config.ncl. CI guard (check-config-sync.nu) enforces form/template parity on every commit. Global NATS topology at ~/.config/ontoref/streams.json; project-local override via nats/streams.json and NATS_STREAMS_CONFIG env var. Config validation + liveness probes via config-setup.nu.",
description = "Accumulated Q&A entries persisted as NCL — questions and answers captured during development sessions, AI interactions, and architectural reviews. Git-versioned, typed by QaEntry schema, queryable via MCP (ontoref_qa_list/add) and HTTP (/qa-json). Bridges session boundaries: knowledge is never lost between actor sessions.",
artifact_paths = [
"reflection/qa.ncl",
"reflection/schemas/qa.ncl",
"crates/ontoref-daemon/src/ui/qa_ncl.rs",
],
},
d.make_node {
id = "quick-actions",
name = "Quick Actions Catalog",
pole = 'Yang,
level = 'Practice,
description = "Runnable shortcuts over existing reflection modes. Configured as quick_actions in .ontoref/config.ncl (id, label, icon, category, mode, actors). Accessible from UI (/actions), CLI (./ontoref), and MCP (ontoref_action_list/add). New modes created via ontoref_action_add are immediately available as actions. Reduces friction between knowing a mode exists and executing it.",
description = "Typed NCL schema layer for personal and career artifacts: career.ncl (Skills, WorkExperience, Talks, Positioning, CompanyTargets, PublicationCards), personal.ncl (Content and Opportunity lifecycle — BlogPost to CV to Application, Job to Conference to Grant), project-card.ncl (canonical display metadata for portfolio and cv_repo publication), links.ncl (typed Link record with LinkKind enum — replaces raw urls/docs/emails/slides_url/video_url/repository string arrays across all personal+career+core schemas). All types carry linked_nodes referencing .ontology/core.ncl node IDs — bridging career artifacts into the DAG.",
description = "NCL DAG modes for personal content and career operations: draft-application (job/grant/collaboration application anchored in personal ontology — gate alignment check, node selection, career trajectory render), draft-email, generate-article, update-cv, write-cfp. Each mode queries personal.ncl and core.ncl nodes to ground output in declared project artifacts rather than free-form prose.",
invariant = false,
artifact_paths = [
"reflection/modes/draft-application.ncl",
"reflection/modes/draft-email.ncl",
"reflection/modes/generate-article.ncl",
"reflection/modes/update-cv.ncl",
"reflection/modes/write-cfp.ncl",
],
},
d.make_node {
id = "search-bookmarks",
name = "Search Bookmarks",
pole = 'Yin,
level = 'Practice,
description = "Persistent bookmark store for search results over the ontology graph. Entries typed as BookmarkEntry (id, node_id, kind, title, level, term, actor, created_at, tags) and persisted to reflection/search_bookmarks.ncl via line-level NCL surgery — same atomic-write pattern as qa_ncl.rs. IDs are sequential sb-NNN, zero-padded. Concurrency-safe via NclWriteLock. Supports add and remove; accessible from the daemon search UI.",
description = "Background observer that bridges Yang code artifacts with Yin ontology declarations. Watches crates/, .ontology/, adrs/, reflection/modes/ for changes; after a debounce window runs sync scan + sync diff; if MISSING/STALE/DRIFT/BROKEN items are found emits an ontology_drift notification. Never applies changes automatically — apply remains a deliberate human or agent act.",
description = "Three typed arrays added to manifest_type: capabilities[] (what the project does, why, how — with explicit ontology node and ADR cross-references), requirements[] (prerequisites classified by env_target_type: Production/Development/Both and requirement_kind_type: Tool/Service/EnvVar/Infrastructure), and critical_deps[] (external dependencies with documented blast radius distinct from startup prerequisites). describe requirements new subcommand surfaces these. describe guides gains capabilities/requirements/critical_deps keys — agents on cold start receive full self-interrogation context without extra tool calls. Also fixes the collect-identity bug where manifest.kind? was read (field did not exist) instead of manifest.repo_kind?, and adds description | String | default = '' to manifest_type.",
description = "Per-project config introspection, coherence verification, and documented mutation. Rust structs annotated with #[derive(ConfigFields)] + #[config_section(id, ncl_file)] emit inventory::submit!(ConfigFieldsEntry{...}) at link time — the same inventory pattern as API catalog. The daemon queries inventory::iter::<ConfigFieldsEntry>() at startup to build a zero-maintenance registry of which Rust fields each struct reads from each NCL section. Multi-consumer coherence compares this registry against the NCL export, Nu script accessors, and CI pipeline fields declared in manifest.ncl's config_surface — any NCL field claimed by no consumer is flagged unclaimed. API endpoints: GET /projects/{slug}/config (full export), /config/{section} (single section), /config/schema (sections with contracts and consumers), /config/coherence (multi-consumer diff), /config/quickref (generated documentation with rationales, override history, coherence status). PUT /projects/{slug}/config/{section} mutates via an override layer: writes {section}.overrides.ncl with audit metadata (actor, reason, timestamp, previous value), appends a single import to the entry point (idempotent), validates with nickel export, reverts on contract violation. NCL contracts (std.contract.from_validator) enforce field constraints (enums, positive numbers, port ranges) before any Rust struct is populated — Nickel is the single validation layer. Ontoref describes its own config via .ontoref/contracts.ncl applying LogConfig and DaemonConfig contracts.",
description = "Bash-layer dispatch for repo_kind-conditional CLI domains. Consumer projects with specific repo_kinds get project-type-aware CLI commands via ore <domain-id> <command>. Each domain ships three files under $ONTOREF_ROOT/domains/{id}/: domain.ncl (NCL contract: commands, pages, repo_kinds, short_alias), commands.nu (Nu script with def main entry point), repo_kinds.txt (grep-readable list of matching repo_kind values). install.nu copies all domains/ to $data_dir and generates aliases.txt + standalone bin wrappers from short_alias. help.nu and describe.nu read domain.ncl at runtime for dynamic help and capabilities output. repo_kind extracted from project manifest via grep (not nickel export) to avoid import-path failures. Session 2026-04-05: personal domain (PersonalOntology — state, next, validate, audit, career, cfp, opportunities, content) and provisioning domain (DevWorkspace/Mixed — state, next, connections, gates, card, capabilities, backlog) implemented. Session 2026-04-06: framework domain (Library/Service/Tool — state, next, connections, gates, capabilities, validate) added to cover Library and Service projects (librosys, DD7pasos, rustelo, website-impl) that have connections.ncl and gate.ncl but no workspace-specific commands.",
invariant = false,
artifact_paths = [
"domains/",
"domains/schema.ncl",
"domains/personal/domain.ncl",
"domains/personal/commands.nu",
"domains/personal/repo_kinds.txt",
"domains/provisioning/domain.ncl",
"domains/provisioning/commands.nu",
"domains/provisioning/repo_kinds.txt",
"domains/framework/domain.ncl",
"domains/framework/commands.nu",
"domains/framework/repo_kinds.txt",
"install/ontoref-global",
"install/install.nu",
"reflection/nulib/help.nu",
"reflection/modules/describe.nu",
],
adrs = ["adr-012"],
},
d.make_node {
id = "vcs-abstraction",
name = "VCS Abstraction Layer",
pole = 'Yang,
level = 'Practice,
description = "Uniform VCS API over jj and git. Filesystem-based detection (.jj/ vs .git/) — no config, no env var. Exposes show-committed, restore-file, remote-url, current-branch, uncommitted-files, and commit-count with identical semantics regardless of VCS backend. All ontoref modules consume vcs.nu instead of hardcoding git commands.",
artifact_paths = [
"reflection/modules/vcs.nu",
],
adrs = ["adr-013"],
},
d.make_node {
id = "agent-workspace-orchestration",
name = "Agent Workspace Orchestration",
pole = 'Yang,
level = 'Practice,
description = "jj + ontoref + Radicle lifecycle wrapper for agent workspaces. jjw agent create spawns a jj workspace and starts an ontoref run; jjw agent step reports progress; jjw agent publish validates, pushes, and opens a Radicle patch (or git push fallback); jjw agent merge commits and cleans the workspace. NCL conflict resolution via jjw-ncl-merge.nu registered as a jj merge tool — enables automated .ontology/ conflict resolution during workspace merge.",
description = "Model Context Protocol server exposing ontology state, reflection modes, ADRs, backlog, config, Q&A, and search bookmarks as structured tools. Two transports: stdio (for AI assistants that launch daemon as subprocess) and streamable-HTTP at POST /mcp (for remote MCP clients). Authentication uses the same unified session model as the REST API (ADR-005) — Bearer token from POST /sessions. Runtime-toggleable without restart (ADR-014). Connect: (1) stdio — run `ontoref-daemon --mcp-stdio`; tool list auto-discovered by the AI client. (2) streamable-HTTP — configure MCP client with url=http://127.0.0.1:7891/mcp, auth=Bearer <session-token>. Session token obtained via POST /sessions with project key. ONTOREF_TOKEN env var injected automatically by CLI. Available tools include: ontoref_help, ontoref_list_projects, ontoref_set_project, ontoref_search, ontoref_get, ontoref_get_node, ontoref_get_adr, ontoref_get_mode, ontoref_status, ontoref_describe, ontoref_guides, ontoref_list_adrs, ontoref_list_modes, ontoref_constraints, ontoref_backlog_list, ontoref_backlog, ontoref_action_list, ontoref_action_add, ontoref_validate_adrs, ontoref_validate, ontoref_impact, ontoref_qa_list, ontoref_qa_add, ontoref_bookmark_list, ontoref_bookmark_add, ontoref_api_catalog, ontoref_notify.",
artifact_paths = [
"crates/ontoref-daemon/src/mcp/mod.rs",
"crates/ontoref-daemon/src/api.rs",
],
},
d.make_node {
id = "graphql-surface",
name = "GraphQL API Surface",
pole = 'Yang,
level = 'Practice,
description = "GraphQL endpoint over the ontology graph, impact traversal, project state, backlog, ADRs, cross-project config comparison, and notification stream. Built with async-graphql 8 (Apollo Federation v2 entity resolution built-in). Endpoints: GET /graphql (GraphiQL IDE), POST /graphql (queries/mutations), GET /graphql/ws (WebSocket subscriptions). Auth: if graphql.read_token_hash is set in config.ncl, all endpoints require Authorization: Bearer <token>. Generate token: `just generate-graphql-token` — prints TOKEN and the Argon2id HASH to add to config.ncl. Pre-auth GraphiQL: GET /graphql?token=<token> — pre-injects the Bearer header and WebSocket connectionParam so the IDE works without manual header setup. Runtime-toggleable without restart (ADR-014). Key queries: ontologyNode(slug, id), impactGraph(slug, nodeId), project(slug), backlog(slug), adrs(slug), crossProjectSummaries, crossProjectConflicts. Key mutations: emitNotification, proposeBacklogStatus, ackNotifications, ackAllNotifications. Subscription: notifications(project, eventType) — streams live notifications over WebSocket.",
artifact_paths = [
"crates/ontoref-daemon/src/graphql/mod.rs",
"crates/ontoref-daemon/Cargo.toml",
"adrs/adr-014-runtime-service-toggles.ncl",
],
},
d.make_node {
id = "registry-credential-vault",
name = "Registry Credential Vault",
pole = 'Yang,
level = 'Practice,
description = "Per-project sops multi-recipient credential vault stored as OCI artifact in ZOT (ADR-017). Each actor role has its own age keypair — the sops DEK is encrypted separately per recipient, enabling revocation without key rotation. vault_key is decrypted into RESTIC_PASSWORD or KOPIA_PASSWORD for the operation duration only; never written to disk. The daemon is structurally excluded: it holds no .kage, cannot decrypt sops files even if it reads them, and cannot be used as a credential amplifier. DOCKER_CONFIG is isolated to a per-call tmpdir; no ambient ~/.docker/config.json is ever consulted. src-vault OCI artifact is cosign-signed on every push and verified before any pull — tamper-evident and substitution-resistant. Access logs are co-located in the vault artifact as an append-only jsonl layer. Two-level authorization gate: assert-actor-authorized validates ONTOREF_ACTOR→role binding + scope.bound_actor + scope.ops; assert-target-in-scope validates the OCI ref against scope.namespaces glob — both fire before any oras call, no cache hit bypasses. Vault lock OCI artifact (src-vault/<id>:lock) coordinates concurrent edits with TTL 60min and admin-only force-unlock auditable. Impact analysis on secrets-close diffs sops files since last snapshot and maps changes to RegistryEntry IDs before push. Per-file recipient routing via project.ncl::sops.recipient_groups + recipient_rules enables tenant/agent isolation in a single vault using sops creation_rules — admin operates as super-role, clientA/clientB/agents decrypt only their own files. cosign 2+ compatibility via vault.cosign.signing_config_path (Rekor-less) when tlog=false. cosign_password 4th field in access.sops.yaml enables non-interactive CI signing. 14/14 named-error tests cover the helper contract. 3 sops adoption templates (single-team, multi-tenant, agent-first) and 3 integration templates (domain-producer, mode-producer, mode-consumer) provide copy-paste starting points. FAQ entries with data-flow diagrams in reflection/qa.ncl.",
description = "Three-level specialization hierarchy with per-mode resolution strategy (ADR-018). Level 1 = ontoref base (generic protocol), Level 2 = project domain (e.g. provisioning-domain), Level 3 = domain instance (e.g. libre-daoshi, libre-wuji). Level identity is declared in manifest.ncl (level.index: Base|Domain|Instance, level.name, level.parent). Each mode at Level 2+ declares strategy: Override (complete implementation, traversal stops), Delegate (no implementation here, traverse to parent), Merge (accumulate bottom-up, lower wins conflicts), Compose (partial inheritance via extends field). Implicit absence at Level 2+ is treated as Delegate with a Soft validation warning from ore validate modes. Strategy transitions are FSM events in state.ncl — moving from Delegate to Override is an observable, git-tracked architectural decision, not a silent refactor. ore mode resolve makes traversal observable: reports which level answered a mode invocation, the strategy applied, the source file, and the reason.",
description = "Before architectural analysis or recommendation, read .ontology/core.ncl tensions; identify which the question engages; describe the synthesis state and direction of motion rather than collapse the Spiral by picking one pole. Default reasoning (human or agent) is Yang — choose, decide, recommend. This Practice surfaces that bias and asks the analyst to characterize the continuous flow first. Operationalizes the ontology-vs-reflection tension; balances against formalization-vs-adoption by choosing minimal structural enforcement (one Practice node, qa entry as canonical content, terse CLAUDE.md addendum) over heavier ADR schema constraints that would impose ceremony before adoption matures. Full procedure and forbidden patterns: reflection/qa.ncl::ontoref-dao-discipline.",
{ from = "quick-actions", to = "reflection-modes", kind = 'DependsOn, weight = 'High,
note = "Each quick action invokes a reflection mode by id." },
{ from = "quick-actions", to = "ontoref-daemon", kind = 'ManifestsIn, weight = 'Medium },
{ from = "describe-query-layer", to = "quick-actions", kind = 'Complements, weight = 'Medium,
note = "describe capabilities lists available modes; quick-actions makes them executable." },
# Drift Observation edges
{ from = "drift-observation", to = "ontoref-daemon", kind = 'ManifestsIn, weight = 'High },
{ from = "drift-observation", to = "ontology-vs-reflection", kind = 'Resolves, weight = 'Medium,
note = "Drift observer continuously monitors the gap between Yin (ontology) and Yang (code). Passive resolution — it signals drift without forcing resolution." },
{ from = "drift-observation", to = "reflection-modes", kind = 'DependsOn, weight = 'High,
{ from = "personal-ontology-schemas", to = "dag-formalized", kind = 'ManifestsIn, weight = 'High,
note = "Career and personal artifacts are typed NCL records with linked_nodes — DAG connections into the core ontology." },
{ from = "personal-ontology-schemas", to = "self-describing", kind = 'Complements, weight = 'Medium,
note = "Personal/career schemas let projects describe not just what they ARE but who built them and for what trajectory." },
{ from = "content-modes", to = "reflection-modes", kind = 'ManifestsIn, weight = 'High },
{ from = "content-modes", to = "personal-ontology-schemas", kind = 'DependsOn, weight = 'High,
note = "Content and career modes query personal.ncl and core.ncl to ground output in declared artifacts." },
{ from = "search-bookmarks", to = "qa-knowledge-store", kind = 'Complements, weight = 'High,
note = "Both are NCL persistence layers using the same atomic-write surgery pattern. Q&A is for accumulated knowledge; bookmarks are for search navigation state." },
{ from = "search-bookmarks", to = "ontoref-daemon", kind = 'ManifestsIn, weight = 'High },
{ from = "ontoref-daemon", to = "search-bookmarks", kind = 'Contains, weight = 'High },
{ from = "unified-auth-model", to = "ontoref-daemon", kind = 'ManifestsIn, weight = 'High },
{ from = "unified-auth-model", to = "no-enforcement", kind = 'Contradicts, weight = 'Low,
note = "Auth is opt-in per project (no keys = open deployment). When keys are configured enforcement is real, but the protocol itself never mandates it." },
{ from = "ontoref-daemon", to = "unified-auth-model", kind = 'Contains, weight = 'High },
# Project Onboarding edges
{ from = "project-onboarding", to = "adopt-ontoref-tooling", kind = 'Complements, weight = 'High,
note = "adopt-ontoref-tooling is the migration surface for existing projects; project-onboarding is the first-class setup for new projects." },
{ from = "project-onboarding", to = "unified-auth-model", kind = 'DependsOn, weight = 'Medium,
note = "--gen-keys bootstraps the first keys into project.ncl during setup." },
{ from = "project-onboarding", to = "daemon-config-management", kind = 'DependsOn, weight = 'Medium },
{ from = "manifest-self-description", to = "self-describing", kind = 'Complements, weight = 'High,
note = "capabilities/requirements/critical_deps in the manifest are the typed operational answer to 'what IS this project' — complementing the architectural answer in core.ncl Practice nodes." },
{ from = "manifest-self-description", to = "adopt-ontoref-tooling", kind = 'Complements, weight = 'High,
note = "Consumer projects declare their own capabilities, requirements, and critical deps — the self-interrogation layer is part of the adoption surface." },
{ from = "manifest-self-description", to = "describe-query-layer", kind = 'ManifestsIn, weight = 'High,
note = "describe capabilities renders manifest_capabilities; describe requirements surfaces requirements + critical_deps; describe guides extends its output with all three arrays." },
{ from = "manifest-self-description", to = "dag-formalized", kind = 'Complements, weight = 'Medium,
note = "capabilities.nodes[] cross-references ontology node IDs; capabilities.adrs[] cross-references ADR IDs — bridging the manifest into the queryable DAG." },
{ from = "manifest-self-description", to = "adr-lifecycle", kind = 'Complements, weight = 'Medium,
note = "capabilities.adrs[] creates explicit typed links from capabilities to the ADRs that formalize them — the ADR→Node linkage pattern extended to the manifest layer." },
{ from = "protocol-migration-system", to = "adopt-ontoref-tooling", kind = 'ManifestsIn, weight = 'High,
note = "Migration system is the versioned upgrade surface for adopt-ontoref-tooling — new protocol features arrive as numbered migrations, not template rewrites." },
{ from = "protocol-migration-system", to = "adr-lifecycle", kind = 'Complements, weight = 'High,
note = "Each migration check can verify ADR-level constraints are met in consumer repos — migrations and ADRs are complementary protocol enforcement layers." },
{ from = "protocol-migration-system", to = "no-enforcement", kind = 'Complements, weight = 'Medium,
note = "Migrations are advisory: `migrate pending` reports state, never applies automatically. The actor decides when to apply." },
{ from = "self-describing", to = "protocol-migration-system", kind = 'ManifestsIn, weight = 'Medium,
note = "Ontoref runs its own migration checks against itself — the migration system is self-applied." },
{ from = "domain-extension-system", to = "formalization-vs-adoption", kind = 'Resolves, weight = 'High,
note = "Domain commands remove the adoption friction of project-type-specific CLI — PersonalOntology and DevWorkspace get discoverable commands without local scripts." },
{ from = "domain-extension-system", to = "personal-ontology-schemas", kind = 'DependsOn, weight = 'High,
note = "The personal domain reads career.ncl, personal.ncl, and backlog.ncl — it is the CLI surface for the personal ontology schema layer." },
{ from = "domain-extension-system", to = "describe-query-layer", kind = 'Complements, weight = 'High,
note = "describe capabilities runs resolve-domain-extension and renders DOMAIN EXTENSION section; ore help <domain-id> reads domain.ncl commands[] dynamically." },
{ from = "domain-extension-system", to = "adopt-ontoref-tooling", kind = 'Complements, weight = 'High,
note = "Domain extensions are part of the adoption surface — new repo_kinds get project-type-aware CLI by shipping a domain directory." },
{ from = "domain-extension-system", to = "protocol-not-runtime", kind = 'Complements, weight = 'Medium,
note = "Domain dispatch is bash+grep — no runtime dependency on nickel for the dispatch path itself. commands.nu is an isolated Nu process." },
# VCS Abstraction edges
{ from = "vcs-abstraction", to = "reflection-modes", kind = 'DependsOn, weight = 'Medium,
note = "opmode.nu and git-event.nu consume vcs.nu — mode execution is VCS-aware." },
{ from = "vcs-abstraction", to = "project-onboarding", kind = 'DependsOn, weight = 'Medium,
note = "init-repo.nu uses vcs detection to choose jj colocated vs git init during onboarding." },
# Agent Workspace Orchestration edges
{ from = "agent-workspace-orchestration", to = "vcs-abstraction", kind = 'DependsOn, weight = 'High,
note = "jjw delegates VCS detection and operations to vcs.nu." },
{ from = "agent-workspace-orchestration", to = "reflection-modes", kind = 'DependsOn, weight = 'High,
{ from = "config-surface", to = "ontoref-daemon", kind = 'ManifestsIn, weight = 'High },
{ from = "config-surface", to = "ontoref-ontology-crate", kind = 'DependsOn, weight = 'High,
note = "ConfigFieldsEntry struct and inventory::collect!(ConfigFieldsEntry) live in ontoref-ontology — the zero-dep adoption surface." },
{ from = "config-surface", to = "api-catalog-surface", kind = 'Complements, weight = 'High,
note = "#[derive(ConfigFields)] extends the same inventory::submit! pattern as #[onto_api]. Both emit link-time registration entries collected by the daemon at startup." },
{ from = "config-surface", to = "dag-formalized", kind = 'ManifestsIn, weight = 'High,
note = "Config sections, consumers, and coherence reports are typed NCL/Rust records — the config tree is a queryable subgraph." },
{ from = "config-surface", to = "self-describing", kind = 'Complements, weight = 'High,
note = "Ontoref applies its own LogConfig and DaemonConfig contracts in .ontoref/contracts.ncl — the config surface is self-demonstrated, not just specified." },
{ from = "config-surface", to = "adopt-ontoref-tooling", kind = 'Complements, weight = 'Medium,
note = "Consumer projects adopting ontoref can annotate their config structs with #[derive(ConfigFields)] to participate in the coherence registry." },
{ from = "registry-credential-vault", to = "domain-extension-system", kind = 'DependsOn, weight = 'High,
note = "Provisioning domain uses registry credentials for OCI artifact push/pull — the vault is what makes ontoref OCI discovery possible in domain projects." },
{ from = "registry-credential-vault", to = "adopt-ontoref-tooling", kind = 'Complements, weight = 'High,
note = "Migration 0016 propagates the credential vault pattern to consumer projects — adding sops config to project.ncl and credential_sops to registry entries." },
{ from = "registry-credential-vault", to = "protocol-not-runtime", kind = 'Complements, weight = 'Medium,
note = "Vault belongs to the reflection layer, not the protocol. Protocol declares the credential_sops pattern; vault.nu and secrets.nu implement it operationally." },
{ from = "registry-credential-vault", to = "unified-auth-model", kind = 'Complements, weight = 'Medium,
note = "Both use age encryption. Auth model secures the daemon API; credential vault secures OCI registry access. Independent mechanisms with the same cryptographic foundation." },
# Level Hierarchy and Mode Resolution edges
{ from = "level-hierarchy-resolution", to = "domain-extension-system", kind = 'Complements, weight = 'High,
note = "Domain extensions (Level 2) now formally declare their hierarchy position via level.index=Domain and mode strategy fields — making the implicit traversal explicit." },
{ from = "level-hierarchy-resolution", to = "manifest-self-description", kind = 'ManifestsIn, weight = 'High,
note = "level field in manifest_type is the ADR-018 mechanism for level identity — manifest.ncl is the source of truth for hierarchy position, queryable via ore describe project." },
{ from = "level-hierarchy-resolution", to = "reflection-modes", kind = 'Complements, weight = 'High,
note = "Mode strategy (Override/Delegate/Merge/Compose) is declared on _ModeBase — every mode file now carries its resolution contract alongside its DAG steps." },
{ from = "level-hierarchy-resolution", to = "protocol-migration-system", kind = 'Complements, weight = 'High,
note = "Migration 0017 propagates level identity and strategy declarations to all consumer projects — applied this session to provisioning, libre-daoshi, libre-wuji." },
{ from = "level-hierarchy-resolution", to = "dag-formalized", kind = 'ManifestsIn, weight = 'Medium,
note = "Level hierarchy is a DAG of specialization: each instance knows its domain parent, each domain knows the base. Traversal is graph traversal, not implicit lookup." },
# MCP and GraphQL surface edges
{ from = "mcp-surface", to = "ontoref-daemon", kind = 'DependsOn, weight = 'High,
note = "MCP server is compiled into ontoref-daemon; runtime-toggleable via ServiceFlags (ADR-014)." },
{ from = "mcp-surface", to = "unified-auth-model", kind = 'DependsOn, weight = 'High,
note = "MCP Bearer auth uses the same POST /sessions session token as the REST API." },
{ from = "graphql-surface", to = "ontoref-daemon", kind = 'DependsOn, weight = 'High,
note = "GraphQL endpoint compiled into ontoref-daemon; runtime-toggleable via ServiceFlags (ADR-014)." },
{ from = "graphql-surface", to = "unified-auth-model", kind = 'DependsOn, weight = 'High,
note = "GraphQL auth uses Argon2id token from config.graphql.read_token_hash — separate from project keys." },
{ from = "graphql-surface", to = "mcp-surface", kind = 'Complements, weight = 'Medium,
note = "GraphQL and MCP are complementary surfaces: MCP for structured tool invocation, GraphQL for ad-hoc graph queries and subscriptions." },
# Dao discipline — surface the read-tensions-first Practice from the named tensions it operationalizes
{ from = "ontology-vs-reflection", to = "read-tensions-first", kind = 'ManifestsIn, weight = 'High,
note = "The named Spiral between contract definition and operational mechanism is the primary tension this Practice asks analysts to engage. Yang reasoning (pick a side) collapses it; this Practice asks for synthesis-state characterization." },
{ from = "formalization-vs-adoption", to = "read-tensions-first", kind = 'ManifestsIn, weight = 'Medium,
note = "This Practice is itself in tension with adoption friction — minimal structural enforcement is chosen so the discipline doesn't become ceremony. Heavier mechanisms (ADR schema constraints, schema pole field) deferred until adoption proves the discipline lands." },
{ from = "read-tensions-first", to = "dag-formalized", kind = 'Complements, weight = 'Medium,
note = "If protocol knowledge is DAG-formalized then analyses ABOUT the protocol must reference the DAG nodes — specifically the named Tension nodes — rather than reason from outside it. read-tensions-first extends DAG formalization from project state to project reasoning." },