let d = import "../ontology/defaults/core.ncl" in { nodes = [ # ── Axioms (invariant = true) ───────────────────────────────────────────── d.make_node { id = "protocol-not-runtime", name = "Protocol, Not Runtime", pole = 'Yang, level = 'Axiom, 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.", invariant = true, artifact_paths = [".ontology/core.ncl", ".ontology/state.ncl", "adrs/"], }, d.make_node { id = "no-enforcement", name = "No Enforcement", pole = 'Yang, level = 'Axiom, 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.", invariant = true, artifact_paths = ["ontology/schemas/", "crates/ontoref-ontology/"], }, # ── Tensions ────────────────────────────────────────────────────────────── d.make_node { id = "formalization-vs-adoption", name = "Formalization vs Adoption Friction", pole = 'Spiral, level = 'Tension, 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.", }, # ── Practices ───────────────────────────────────────────────────────────── d.make_node { id = "adr-lifecycle", name = "ADR Lifecycle", pole = 'Yang, level = 'Practice, 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.", artifact_paths = [ "adrs/schema.ncl", "adrs/reflection.ncl", "adrs/_template.ncl", "adrs/adr-001-protocol-as-standalone-project.ncl", "adrs/adr-002-daemon-for-caching-and-notification-barrier.ncl", "adrs/adr-003-qa-and-knowledge-persistence-as-ncl.ncl", "adrs/adr-004-ncl-pipe-bootstrap-pattern.ncl", "adrs/adr-005-unified-auth-session-model.ncl", "adrs/adr-006-nushell-0111-string-interpolation-compat.ncl", "CHANGELOG.md", ], adrs = ["adr-001", "adr-002", "adr-003", "adr-004", "adr-005", "adr-006"], }, d.make_node { id = "reflection-modes", name = "Reflection Modes", pole = 'Yang, level = 'Practice, description = "Operational procedures are first-class artifacts encoded as NCL DAG contracts. Modes declare actors, steps, dependencies, and error strategies — not prose.", artifact_paths = ["reflection/modes/", "reflection/schemas/", "crates/ontoref-reflection/"], }, d.make_node { id = "coder-process-memory", name = "Coder Process Memory", pole = 'Yin, level = 'Practice, description = "Session knowledge is captured as structured JSONL via coder record. Queryable, exportable, and promotable to reflection/knowledge/. The memory layer between sessions.", artifact_paths = ["reflection/modules/coder.nu", "reflection/schemas/coder.ncl"], }, d.make_node { id = "describe-query-layer", name = "Describe Query Layer", pole = 'Yang, level = 'Practice, 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 — surfacing declared ADR constraints alongside source, examples, and connections.", artifact_paths = ["reflection/modules/describe.nu"], }, d.make_node { id = "ontoref-ontology-crate", name = "Ontoref Ontology Crate", pole = 'Yang, level = 'Practice, 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) and adrs (Vec) — both serde(default) for zero-migration backward compatibility.", artifact_paths = ["crates/ontoref-ontology/"], adrs = ["adr-001"], }, d.make_node { id = "ontoref-reflection-crate", name = "Ontoref Reflection Crate", pole = 'Yang, level = 'Practice, description = "Rust implementation for loading, validating, and executing Reflection modes as NCL DAG contracts against project state.", artifact_paths = ["crates/ontoref-reflection/"], }, d.make_node { id = "adopt-ontoref-tooling", name = "Adopt Ontoref Tooling", pole = 'Yang, level = 'Practice, description = "Migration system for onboarding existing projects into the ontoref protocol. Provides .ontology/ stub templates, .ontoref/config.ncl template, scripts/ontoref thin wrapper, and the adopt_ontoref mode+form+script that wire everything up idempotently.", artifact_paths = [ "ontoref", "justfile", "justfiles/ci.just", "templates/ontology/", "templates/ontoref-config.ncl", "templates/scripts-ontoref", "reflection/modes/adopt_ontoref.ncl", "reflection/forms/adopt_ontoref.ncl", "reflection/templates/adopt_ontoref.nu.j2", ], }, d.make_node { id = "ontology-three-file-split", name = "Ontology Three-File Split", pole = 'Yang, level = 'Practice, 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.", invariant = false, artifact_paths = [".ontology/core.ncl", ".ontology/state.ncl", ".ontology/gate.ncl"], }, d.make_node { id = "adr-node-linkage", name = "ADR–Node Declared Linkage", pole = 'Yang, level = 'Practice, 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.", artifact_paths = [ "ontology/schemas/core.ncl", "crates/ontoref-ontology/src/types.rs", "reflection/modules/describe.nu", "crates/ontoref-daemon/templates/pages/graph.html", "crates/ontoref-daemon/src/api.rs", ], }, d.make_node { id = "web-presence", name = "Web Presence", pole = 'Yang, level = 'Practice, description = "Landing page at assets/web/ describing the ontoref protocol to external audiences. Bilingual (EN/ES), covers protocol layers, yin/yang duality, crates, and adoption path. Self-description artifact.", artifact_paths = ["assets/web/src/index.html", "assets/web/index.html", "README.md", "assets/architecture.svg"], }, d.make_node { id = "ontoref-daemon", name = "Ontoref Daemon", pole = 'Yang, level = 'Practice, description = "Runtime support daemon for the ontoref protocol. Provides NCL export caching, file watching, actor registry, notification barrier, HTTP API, MCP server (stdio + streamable-HTTP), Q&A NCL persistence, quick-actions catalog, passive drift observation, and unified auth/session management (key exchange, Bearer tokens, per-project and daemon-level admin, session list/revoke). Launched via ADR-004 NCL pipe bootstrap: nickel export config.ncl | ontoref-daemon.bin --config-stdin. Binary installed as ontoref-daemon.bin; bootstrapper as ontoref-daemon.", invariant = false, artifact_paths = [ "crates/ontoref-daemon/", "install/ontoref-daemon-boot", "install/install.nu", "nats/streams.json", "reflection/modules/services.nu", "crates/ontoref-daemon/src/ui/qa_ncl.rs", "crates/ontoref-daemon/src/ui/drift_watcher.rs", "crates/ontoref-daemon/src/mcp/mod.rs", "crates/ontoref-daemon/src/session.rs", "crates/ontoref-daemon/src/ui/auth.rs", "crates/ontoref-daemon/src/ui/login.rs", "crates/ontoref-daemon/src/ui/search_bookmarks_ncl.rs", "justfiles/ci.just", ], }, d.make_node { id = "unified-auth-model", name = "Unified Auth Model", pole = 'Yang, level = 'Practice, 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.", invariant = false, artifact_paths = [ "install/resources/config.ncl", "install/resources/streams.json", "install/config-setup.nu", "install/check-config-sync.nu", "reflection/forms/config.ncl", "reflection/forms/config.ncl.j2", "reflection/nulib/bootstrap.nu", ], }, d.make_node { id = "qa-knowledge-store", name = "Q&A Knowledge Store", pole = 'Yin, level = 'Practice, 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.", artifact_paths = [ ".ontoref/config.ncl", "crates/ontoref-daemon/templates/pages/actions.html", "reflection/modes/", ], }, d.make_node { id = "personal-ontology-schemas", name = "Personal Ontology Schemas", pole = 'Yin, level = 'Practice, 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). All types carry linked_nodes referencing .ontology/core.ncl node IDs — bridging career artifacts into the DAG.", invariant = false, artifact_paths = [ "ontology/schemas/career.ncl", "ontology/schemas/personal.ncl", "ontology/schemas/project-card.ncl", "ontology/defaults/career.ncl", "ontology/defaults/personal.ncl", "ontology/defaults/project-card.ncl", ], }, d.make_node { id = "content-modes", name = "Content & Career Reflection Modes", pole = 'Yang, level = 'Practice, 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.", invariant = false, artifact_paths = [ "reflection/search_bookmarks.ncl", "reflection/schemas/search_bookmarks.ncl", "crates/ontoref-daemon/src/ui/search_bookmarks_ncl.rs", ], }, d.make_node { id = "drift-observation", name = "Passive Drift Observation", pole = 'Spiral, level = 'Practice, 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.", artifact_paths = [ "crates/ontoref-daemon/src/ui/drift_watcher.rs", "reflection/modes/sync-ontology.ncl", ], }, ], edges = [ { from = "self-describing", to = "dag-formalized", kind = 'ManifestsIn, weight = 'High }, { from = "self-describing", to = "adr-lifecycle", kind = 'ManifestsIn, weight = 'High }, { from = "self-describing", to = "reflection-modes", kind = 'ManifestsIn, weight = 'High }, { from = "ontology-vs-reflection", to = "dag-formalized", kind = 'Resolves, weight = 'High }, { from = "ontology-vs-reflection", to = "coder-process-memory", kind = 'Resolves, weight = 'Medium }, { from = "dag-formalized", to = "ontoref-ontology-crate", kind = 'ManifestsIn, weight = 'High }, { from = "reflection-modes", to = "ontoref-reflection-crate", kind = 'ManifestsIn, weight = 'High }, { from = "no-enforcement", to = "formalization-vs-adoption", kind = 'Resolves, weight = 'Medium }, { from = "protocol-not-runtime", to = "no-enforcement", kind = 'Implies, weight = 'High }, { from = "adr-lifecycle", to = "reflection-modes", kind = 'Complements, weight = 'Medium }, { from = "adr-node-linkage", to = "adr-lifecycle", kind = 'ManifestsIn, weight = 'High }, { from = "adr-node-linkage", to = "describe-query-layer", kind = 'Complements, weight = 'High }, { from = "describe-query-layer", to = "dag-formalized", kind = 'DependsOn, weight = 'High }, { from = "coder-process-memory", to = "describe-query-layer", kind = 'Complements, weight = 'Medium }, { from = "ontoref-daemon", to = "ontoref-ontology-crate", kind = 'Complements, weight = 'High }, { from = "ontoref-daemon", to = "reflection-modes", kind = 'Complements, weight = 'Medium }, { from = "protocol-not-runtime", to = "ontoref-daemon", kind = 'Contradicts, weight = 'Low, note = "Daemon is optional runtime support, not a protocol requirement. Protocol functions without it." }, { from = "no-enforcement", to = "adopt-ontoref-tooling", kind = 'ManifestsIn, weight = 'High, note = "Adoption is voluntary — the tooling makes it easy but never mandatory." }, { from = "adopt-ontoref-tooling", to = "reflection-modes", kind = 'DependsOn, weight = 'High }, { from = "self-describing", to = "web-presence", kind = 'ManifestsIn, weight = 'Medium }, { from = "web-presence", to = "adopt-ontoref-tooling", kind = 'Complements, weight = 'Medium }, # Q&A Knowledge Store edges { from = "qa-knowledge-store", to = "dag-formalized", kind = 'ManifestsIn, weight = 'High, note = "Q&A entries are typed NCL records, git-versioned — knowledge as DAG." }, { from = "qa-knowledge-store", to = "coder-process-memory", kind = 'Complements, weight = 'High, note = "Q&A is the persistent layer; coder.nu is the session capture layer. Together they form the full memory stack." }, { from = "ontoref-daemon", to = "qa-knowledge-store", kind = 'Contains, weight = 'High }, { from = "daemon-config-management", to = "ontoref-daemon", kind = 'DependsOn, weight = 'High }, { from = "daemon-config-management", to = "adopt-ontoref-tooling", kind = 'Complements, weight = 'Medium, note = "Config management is part of the adoption surface — new projects get config.ncl and streams.json during install." }, # Quick Actions edges { 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, note = "Invokes sync-ontology mode steps (scan, diff) as read-only sub-processes." }, # Personal Ontology Schemas edges { 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 }, # Unified Auth Model edges { 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 }, ], }