ontoref-code/domains/framework/commands.nu
2026-07-10 01:44:59 +01:00

167 lines
7.2 KiB
Text
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env nu
# domains/framework/commands.nu — Framework protocol CLI for ontoref.
# Dispatched by the ontoref bash wrapper when repo_kind in {Library, Service, Tool}:
# ore framework <command> [args] or ore fw <command> [args]
#
# Provides protocol connectivity commands (state, connections, gates, capabilities)
# for projects that are frameworks, libraries, or services — no workspace-specific ops.
def project-root [] {
$env.ONTOREF_PROJECT_ROOT? | default (pwd | path expand)
}
# Resolves an ontoref section path against ADR-032 layout (canonical
# `.ontoref/<rel>`) falling back to legacy root-level layout for projects that
# have not yet applied migration 0023. Pass logical paths like
# `ontology/state.ncl`, `card.ncl`, etc.
def resolve-onto-path [logical: string] {
let root = (project-root)
let canonical = $"($root)/.ontoref/($logical)"
if ($canonical | path exists) { return $canonical }
let legacy_rel = if ($logical | str starts-with "ontology/") {
$logical | str replace "ontology/" ".ontology/"
} else { $logical }
let legacy = $"($root)/($legacy_rel)"
if ($legacy | path exists) { return $legacy }
$canonical
}
# ─── Loaders ──────────────────────────────────────────────────────────────────
def load-state [] { ^nickel export (resolve-onto-path "ontology/state.ncl") | from json }
def load-core [] { ^nickel export (resolve-onto-path "ontology/core.ncl") | from json }
def load-manifest [] { ^nickel export (resolve-onto-path "ontology/manifest.ncl") | from json }
def load-optional [path: string] {
if ($path | path exists) { ^nickel export $path | from json } else { null }
}
# ─── 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 path = (resolve-onto-path "ontology/connections.ncl")
let c = load-optional $path
if ($c | is-empty) {
print --stderr "No connections.ncl found for this project."
exit 1
}
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)" }
}
if ($c.upstream? | default [] | is-empty) and ($c.downstream? | default [] | is-empty) and ($c.peers? | default [] | is-empty) {
print "No connections declared."
}
}
export def "gates" [] {
let path = (resolve-onto-path "ontology/gate.ncl")
let g = load-optional $path
if ($g | is-empty) {
print "No gate.ncl found for this project."
return
}
$g | get membranes | each { |m|
{
membrane: $m.id,
name: $m.name,
active: $m.active,
permeability: $m.permeability,
condition: ($m.opening_condition.description? | default ""),
}
}
}
# ─── 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
}
# ─── help + main ──────────────────────────────────────────────────────────────
def show-help [] {
print "Framework — ontoref domain extension"
print ""
print "USAGE"
print " ore framework <command> [args] (alias: ore fw)"
print ""
print "COMMANDS"
print " state Current FSM position across all dimensions"
print " next Next valid transitions with blockers/catalysts"
print " connections Upstream/downstream project dependency graph"
print " gates Gate membrane status and opening conditions"
print " capabilities Project capabilities from manifest"
print " validate <decision> Check decision against ontological invariants"
}
def main [...args: 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 }
"capabilities" => { capabilities }
_ if ($sub | str starts-with "validate ") => { validate ($args | skip 1 | str join " ") }
_ => { print --stderr $"Unknown command: ($sub)"; show-help; exit 1 }
}
}