#!/usr/bin/env nu # domains/provisioning/commands.nu — Provisioning domain CLI for ontoref. # Dispatched by the ontoref bash wrapper when repo_kind in {DevWorkspace, Mixed}: # ore provisioning [args] # # Works for both DevWorkspace (workspace-level) and Mixed (platform-level) projects. # Commands that require project-specific files (card.ncl, reflection/backlog.ncl) # degrade gracefully when those files are absent. def project-root [] { $env.ONTOREF_PROJECT_ROOT? | default (pwd | path expand) } # ─── Loaders ────────────────────────────────────────────────────────────────── def load-state [] { ^nickel export $"(project-root)/.ontology/state.ncl" | from json } def load-core [] { ^nickel export $"(project-root)/.ontology/core.ncl" | from json } def load-gate [] { ^nickel export $"(project-root)/.ontology/gate.ncl" | from json } def load-connections [] { ^nickel export $"(project-root)/.ontology/connections.ncl" | from json } def load-manifest [] { ^nickel export $"(project-root)/.ontology/manifest.ncl" | from json } def load-card [] { let path = $"(project-root)/card.ncl" if ($path | path exists) { ^nickel export $path | from json } else { null } } def load-backlog [] { let path = $"(project-root)/reflection/backlog.ncl" if ($path | path exists) { ^nickel export $path | from json } else { { items: [] } } } # ─── state / next / validate ────────────────────────────────────────────────── export def "state" [] { load-state | get dimensions | each { |dim| { dimension: $dim.id, current: $dim.current_state, desired: $dim.desired_state, horizon: $dim.horizon } } } export def "next" [] { load-state | get dimensions | each { |dim| let active = $dim.transitions | where from == $dim.current_state if ($active | is-empty) { { dimension: $dim.id, from: $dim.current_state, to: "–", condition: "no active transition", blocker: "–", catalyst: "–" } } else { let tr = $active | first { dimension: $dim.id, from: $tr.from, to: $tr.to, condition: $tr.condition, blocker: $tr.blocker, catalyst: $tr.catalyst } } } } export def "validate" [decision: string] { let core = load-core let words = ($decision | str downcase | split row " " | where { |w| ($w | str length) > 3 }) let affected = ($core.nodes | each { |n| let text = $"($n.id) ($n.name) ($n.description)" | str downcase if ($words | any { |w| $text =~ $w }) { $n } else { null } } | compact) { decision: $decision, invariants_at_risk: ($affected | where invariant == true | select id level name), tensions_touched: ($affected | where level == "Tension" | select id name), practices_touched: ($affected | where level == "Practice" | select id name), verdict: "manual review required — if any invariant is contradicted, justification is required", } } # ─── connections / gates ────────────────────────────────────────────────────── export def "connections" [] { let c = load-connections if ($c.upstream? | default [] | is-not-empty) { print "" print "UPSTREAM" $c.upstream | each { |u| print $" ($u.project) kind=($u.kind) via=($u.via)" if ($u.node? | default "" | is-not-empty) { print $" node: ($u.node)" } print $" ($u.note)" } } if ($c.downstream? | default [] | is-not-empty) { print "" print "DOWNSTREAM" $c.downstream | each { |d| print $" ($d.project) kind=($d.kind) via=($d.via)" if ($d.node? | default "" | is-not-empty) { print $" node: ($d.node)" } print $" ($d.note)" } } if ($c.peers? | default [] | is-not-empty) { print "" print "PEERS" $c.peers | each { |p| print $" ($p.project) kind=($p.kind) via=($p.via)" } } } export def "gates" [] { load-gate | get membranes | each { |m| { membrane: $m.id, name: $m.name, active: $m.active, permeability: $m.permeability, condition: ($m.opening_condition.description? | default ""), } } } # ─── card (DevWorkspace only) ───────────────────────────────────────────────── export def "card" [] { let c = load-card if ($c | is-empty) { print "No card.ncl found — this command is only available for DevWorkspace projects." return } print $"id: ($c.id)" print $"name: ($c.name)" print $"tagline: ($c.tagline)" print $"status: ($c.status)" print $"version: ($c.version)" print $"started: ($c.started_at)" if ($c.tags? | default [] | is-not-empty) { print $"tags: ($c.tags | str join ', ')" } if ($c.tools? | default [] | is-not-empty) { print $"tools: ($c.tools | str join ', ')" } if ($c.features? | default [] | is-not-empty) { print "" print "features:" $c.features | each { |f| print $" - ($f)" } } } # ─── capabilities (manifest.capabilities) ──────────────────────────────────── export def "capabilities" [] { let caps = load-manifest | get capabilities? | default [] if ($caps | is-empty) { print "No capabilities declared in manifest."; return } $caps | select id name summary } # ─── backlog (platform only) ────────────────────────────────────────────────── export def "backlog" [--priority: string = ""] { let items = load-backlog | get items if ($items | is-empty) { print "No backlog.ncl found — this command is only available for platform projects." return } let filtered = if ($priority | is-empty) { $items } else { $items | where priority == $priority } $filtered | each { |i| { id: $i.id, priority: $i.priority, blocked_by: ($i.blocked_by | str join ", "), } } } export def "backlog show" [id: string] { let items = load-backlog | get items if ($items | is-empty) { error make { msg: "No backlog.ncl found for this project." } } let item = $items | where id == $id if ($item | is-empty) { error make { msg: $"Backlog item not found: ($id)" } } let r = $item | first print $"id: ($r.id)" print $"priority: ($r.priority)" print "" print "description:" print $" ($r.description)" if ($r.blocked_by? | default [] | is-not-empty) { print "" print $"blocked_by: ($r.blocked_by | str join ', ')" } if ($r.related_nodes? | default [] | is-not-empty) { print $"nodes: ($r.related_nodes | str join ', ')" } } # ─── help + main ────────────────────────────────────────────────────────────── def show-help [] { print "Provisioning — ontoref domain extension" print "" print "USAGE" print " ore provisioning [args]" print "" print "COMMANDS (all repo_kinds)" print " state Current FSM position across all dimensions" print " next Next valid transitions with blockers/catalysts" print " validate Check against ontological invariants" print " connections Upstream/downstream project dependency graph" print " gates Membrane status and opening conditions" print " capabilities Platform capabilities from manifest" print "" print "COMMANDS (DevWorkspace only)" print " card Workspace card: identity, clusters, status" print "" print "COMMANDS (Mixed/platform only)" print " backlog [--priority] Backlog items filtered by High|Medium|Low" print " backlog show Full detail of a backlog item" } def main [ ...args: string --priority: string = "" ] { if ($args | is-empty) or ($args | first) == "help" { show-help; return } let sub = ($args | str join " ") match $sub { "state" => { state } "next" => { next } "connections" => { connections } "gates" => { gates } "card" => { card } "capabilities" => { capabilities } "backlog" => { backlog --priority $priority } _ if ($sub | str starts-with "backlog show ") => { backlog show ($args | get 2) } _ if ($sub | str starts-with "validate ") => { validate ($args | skip 1 | str join " ") } _ => { print $"Unknown command: ($sub)"; show-help } } }