ontoref/domains/provisioning/commands.nu

679 lines
30 KiB
Text
Raw Permalink Normal View History

feat: domain extension system, VCS abstraction, personal/provisioning domains, web subpages Domain extension system (ADR-012): bash-layer dispatch activates repo_kind-conditional CLI domains. install.nu copies domains/ tree; short_alias wrappers generated (personal, prov). ore help and describe capabilities domain-aware. personal domain (PersonalOntology): career skills/talks/publications/positioning, CFP pipeline (Watching→Delivered), opportunities lifecycle, content pipeline, Sessionize integration. Daemon pages: /career, /personal. provisioning domain (DevWorkspace/Mixed): FSM state, next transitions, connections graph, gates, workspace card, capabilities, backlog. Daemon page: /provisioning. VCS abstraction layer (ADR-013): reflection/modules/vcs.nu — uniform jj/git API via filesystem detection (.jj/ vs .git/). opmode.nu and git-event.nu migrated off ^git. reflection/bin/jjw.nu — jj + ontoref + Radicle agent workspace lifecycle. jjw-ncl-merge.nu registered as jj merge tool for .ontology/ NCL conflicts. init-repo.nu for new_project mode. jj/rad not in ontoref requirements — belong in orchestration project manifests. 'Framework RepoKind: ontology/schemas/manifest.ncl gains 'Framework variant; ontoref self-identifies as framework — no domain activates for the protocol itself. Web presence: personal.html and provisioning.html domain subpages. index.html gains "Project Types — Domain Extensions" section with type cards and subpage links. Nav compacted (Arch/Prov labels, solid backdrop-filter background). on+re: vcs-abstraction (adrs: adr-013) and agent-workspace-orchestration Practice nodes; 21 manifest capabilities; state.ncl catalysts updated.
2026-04-07 23:08:29 +01:00
#!/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 <command> [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 ', ')"
}
}
feat: #[onto_mcp_tool] catalog, OCI credential vault layer, validate ADR-018 mode hierarchy ontoref-derive: #[onto_mcp_tool] attribute macro registers MCP tool unit-structs in the catalog at link time via inventory::submit!; annotated item is emitted unchanged, ToolBase/AsyncTool impls stay on the struct. All 34 tools migrated from manual wiring (net +5: ontoref_list_projects, ontoref_search, ontoref_describe, ontoref_list_ontology_extensions, ontoref_get_ontology_extension). validate modes (ADR-018): reads level_hierarchy from workflow.ncl and checks every .ncl mode for level declared, strategy declared, delegate chain coherent, compose extends valid. mode resolve <id> shows which hierarchy level handles a mode and why. --self-test generates synthetic fixtures in a temp dir for CI smoke-testing. validate run-cargo: two-step Cargo.toml resolution — workspace layout first (crates/<check.crate>/Cargo.toml), single-crate fallback by package name or repo basename. Lets the same ADR constraint shape apply to workspace and single-crate repos. ontology/schemas/manifest.ncl: registry_topology_type contract — multi-registry coordination, push targets, participant scopes, per-namespace capability. reflection/requirements/base.ncl: oras ≥1.2.0, cosign ≥2.0.0, sops ≥3.9.0, age ≥1.1.0, restic declared as Hard/Soft requirements with version_min, check_cmd, and install_hint (ADR-017 toolchain surface). ADR-019: per-file recipient routing for tenant isolation without multi-vault. Schema additions: sops.recipient_groups + sops.recipient_rules in ontoref-project.ncl. secrets-bootstrap generates .sops.yaml from project.ncl in declarative mode. Three new secrets-audit checks: recipient-routing-coherent, recipient-routing-coverage, no-multi-vault. Adoption templates: single-team/, multi-tenant/, agent-first/. Integration templates: domain-producer/, mode-producer/, mode-consumer/. UI: project_picker surfaces registry badge (⟳ participant) and vault badge (⛁ vault_id · N, green=declarative / amber=legacy) per project card. Expanded panel adds collapsible Registry section with namespace, endpoint, and push/pull capability. manage.html gains Runtime Services card — MCP and GraphQL toggleable without restart via HTMX POST /ui/manage/services/{service}/toggle. describe.nu: capabilities JSON includes registry_topology and vault_state per project. sync.nu: drift check extended to detect //! absence on newly registered crates. qa.ncl: six entries — credential-vault-best-practice (layered data-flow diagram), credential-vault-templates (paths A/B/C), credential-vault-troubleshooting (15 named errors), integration-what-and-why (ADR-042 OCI federation), integration-how-to-implement, integration-troubleshooting. on+re: core.ncl + manifest.ncl updated to reflect OCI, MCP, and mode-hierarchy nodes. Deleted stale presentation assets (2026-02 slides + voice notes).
2026-05-12 04:46:15 +01:00
# ─── install (Mixed/platform only) ───────────────────────────────────────────
def detect-platform []: nothing -> string {
if (do { ^which docker } | complete | get exit_code) == 0 { "docker" }
else if (do { ^which podman } | complete | get exit_code) == 0 { "podman" }
else if (do { ^which kubectl } | complete | get exit_code) == 0 { "kubernetes" }
else { "" }
}
export def "install" [
--mode: string = "solo" # Deployment mode: solo|multi-user|cicd|enterprise
--platform: string = "" # Container platform: docker|podman|kubernetes (auto-detected)
--dry-run # Print what would be run without executing
]: nothing -> nothing {
let root = (project-root)
let installer_bin = [$root, "platform", "target", "release", "provisioning-installer"] | path join
let installer_src = [$root, "platform", "installer"] | path join
let just_available = (do { ^which just } | complete | get exit_code) == 0
let resolved_platform = if ($platform | is-not-empty) { $platform } else { detect-platform }
print $"Platform install mode=($mode) platform=(if ($resolved_platform | is-empty) { '?' } else { $resolved_platform })"
print ""
if ($resolved_platform | is-empty) {
print "No supported container platform found (docker, podman, kubectl)."
print "Install one and retry."
return
}
if ($installer_bin | path exists) {
print $"installer binary: ($installer_bin)"
if $dry_run {
print $"[dry-run] would run: ($installer_bin) --headless --mode ($mode) --platform ($resolved_platform) --yes"
return
}
do { ^$installer_bin --headless --mode $mode --platform $resolved_platform --yes } | complete | ignore
return
}
if ($installer_src | path exists) {
print "installer binary not built — building from source..."
if $dry_run {
print $"[dry-run] would run: cargo build --release --manifest-path ($installer_src)/Cargo.toml"
return
}
let r = do { ^cargo build --release --manifest-path $"($installer_src)/Cargo.toml" } | complete
if $r.exit_code != 0 {
error make { msg: $"installer build failed:\n($r.stderr)" }
}
do { ^$installer_bin --headless --mode $mode --platform $resolved_platform --yes } | complete | ignore
return
}
if $just_available {
print "No installer binary or source found — delegating to: just install"
if $dry_run {
print $"[dry-run] would run: just install mode=($mode)"
return
}
let r = do { ^just install $"mode=($mode)" } | complete
if $r.exit_code != 0 {
error make { msg: $"just install failed:\n($r.stderr)" }
}
return
}
print "installer not found and 'just' is not available."
print $"Build the installer first: cargo build --release --manifest-path ($installer_src)/Cargo.toml"
}
# ─── ops (ADR-037: NATS ops contract) ────────────────────────────────────────
def workspace-id []: nothing -> string {
let card = load-card
if ($card | is-empty) { "unknown" } else { $card.id }
}
def nats-available []: nothing -> bool {
(do { ^which nats } | complete | get exit_code) == 0
}
def keeper-cli-available []: nothing -> bool {
(do { ^which keeper-cli } | complete | get exit_code) == 0
}
def rad-available []: nothing -> bool {
(do { ^which rad } | complete | get exit_code) == 0
}
export def "ops list" []: nothing -> nothing {
let ws = workspace-id
if not (nats-available) {
print "nats CLI not found — install nats-io/natscli"
return
}
let stream = $"OPS_PENDING_(($ws | str upcase))"
let r = do { ^nats stream info $stream --json } | complete
if $r.exit_code != 0 {
print $"Stream ($stream) not found or NATS unreachable: ($r.stderr | str trim)"
return
}
let info = $r.stdout | from json
print $"stream: ($stream)"
print $"messages: ($info.state.messages)"
print $"first_seq: ($info.state.first_seq)"
print $"last_seq: ($info.state.last_seq)"
}
export def "ops describe" [id: string]: nothing -> nothing {
let ws = workspace-id
if not (nats-available) { print "nats CLI not found"; return }
let subject = $"ops.pending.($ws).>"
let r = do { ^nats req $subject "" --count 50 --json } | complete
if $r.exit_code != 0 { print $"NATS request failed: ($r.stderr | str trim)"; return }
let msgs = $r.stdout | lines | each { |l| $l | from json | get data? | default {} }
let found = $msgs | where { |m| ($m.jti? | default "") == $id }
if ($found | is-empty) { print $"Op not found: ($id)"; return }
let op = $found | first
print $"jti: ($op.jti)"
print $"op_type: ($op.op_type? | default 'unknown')"
print $"target: ($op.target? | default 'unknown')"
print $"expected_version: ($op.expected_state_version? | default 'none')"
print $"scopes: ($op.scopes? | default [] | str join ', ')"
print $"issued_at: ($op.iat? | default 'unknown')"
}
export def "ops sign" [id: string]: nothing -> nothing {
if not (keeper-cli-available) { print "keeper-cli not found — build from platform/crates/ops-keeper"; return }
let ws = workspace-id
let r = do { ^keeper-cli --workspace $ws sign $id } | complete
if $r.exit_code != 0 {
error make { msg: $"keeper-cli sign failed: ($r.stderr | str trim)" }
}
print $r.stdout
}
export def "ops history" [--workspace: string = ""]: nothing -> nothing {
let ws = if ($workspace | is-empty) { workspace-id } else { $workspace }
let repo_path = $env.HOME | path join ".local/share/radicle/repos" $"state-($ws)"
if not ($repo_path | path exists) {
print $"Radicle state repo not found at ($repo_path)"
print "Run: rad clone rad:<rid> state-($ws)"
return
}
let r = do { ^git -C $repo_path log --oneline --no-decorate -20 } | complete
if $r.exit_code != 0 { print $"git log failed: ($r.stderr | str trim)"; return }
$r.stdout | lines | each { |l|
let parts = $l | split row " " | enumerate
let hash = $parts | where index == 0 | get item.0
let msg = $parts | skip 1 | get item | str join " "
{ commit: $hash, message: $msg }
}
}
# ─── playbook (extensions/playbooks/) ────────────────────────────────────────
def playbooks-root []: nothing -> string {
let root = project-root
[$root, "..", "..", "provisioning", "extensions", "playbooks"] | path join | path expand
}
export def "playbook list" []: nothing -> nothing {
let root = playbooks-root
if not ($root | path exists) { print "No extensions/playbooks/ directory found."; return }
^ls $root | where type == dir | get name | each { |d|
let playbook_path = [$d, "playbook.ncl"] | path join
let has_run = ([$d, "run.nu"] | path join | path exists)
{ name: ($d | path basename), has_run: $has_run, has_playbook: ($playbook_path | path exists) }
}
}
export def "playbook describe" [name: string]: nothing -> nothing {
let root = playbooks-root
let playbook_path = [$root, $name, "playbook.ncl"] | path join
if not ($playbook_path | path exists) {
print $"Playbook not found: ($name)"
print $"Expected at: ($playbook_path)"
return
}
let r = do { ^nickel export $playbook_path } | complete
if $r.exit_code != 0 { print $"Failed to load playbook: ($r.stderr | str trim)"; return }
let p = $r.stdout | from json
print $"name: ($p.name)"
print $"description: ($p.description)"
print $"version: ($p.version)"
print ""
print "preconditions:"
$p.preconditions? | default [] | each { |c| print $" - ($c)" }
print ""
print "steps:"
$p.steps? | default [] | enumerate | each { |s|
print $" ($s.index + 1). ($s.item.id): ($s.item.description)"
}
if ($p.rollback_strategy? | default "none") != "none" {
print $"\nrollback: ($p.rollback_strategy)"
}
}
export def "playbook run" [name: string, --dry-run]: nothing -> nothing {
let root = playbooks-root
let run_path = [$root, $name, "run.nu"] | path join
if not ($run_path | path exists) {
print $"run.nu not found for playbook: ($name)"
return
}
let ws = workspace-id
if $dry_run {
let dry_path = [$root, $name, "tests", "dry_run.nu"] | path join
if ($dry_path | path exists) {
let r = do { ^nu $dry_path --workspace $ws } | complete
if $r.exit_code != 0 { error make { msg: $"dry-run failed: ($r.stderr | str trim)" } }
print $r.stdout
} else {
print $"[dry-run] would execute: nu ($run_path) --workspace ($ws)"
print "No dry_run.nu found — simulating step listing only."
playbook describe $name
}
return
}
let r = do { ^nu $run_path --workspace $ws } | complete
if $r.exit_code != 0 {
error make { msg: $"playbook run failed: ($r.stderr | str trim)" }
}
print $r.stdout
}
export def "playbook history" []: nothing -> nothing {
let ws = workspace-id
let repo_path = $env.HOME | path join ".local/share/radicle/repos" $"state-($ws)"
if not ($repo_path | path exists) {
print $"Radicle state repo not found at ($repo_path)"
return
}
let r = do { ^git -C $repo_path log --oneline --no-decorate --grep="playbook:" -20 } | complete
if $r.exit_code != 0 { print $"git log failed: ($r.stderr | str trim)"; return }
if ($r.stdout | is-empty) { print "No playbook audit entries found."; return }
$r.stdout | lines | each { |l|
let parts = $l | split row " " | enumerate
let hash = $parts | where index == 0 | get item.0
let msg = $parts | skip 1 | get item | str join " "
{ commit: $hash, message: $msg }
}
}
# ─── keeper (ADR-037 dual-mode signing) ──────────────────────────────────────
export def "keeper status" []: nothing -> nothing {
let ws = workspace-id
if not (keeper-cli-available) { print "keeper-cli not found"; return }
let r = do { ^keeper-cli --workspace $ws status } | complete
if $r.exit_code != 0 {
print $"keeper-cli unavailable: ($r.stderr | str trim)"
return
}
print $r.stdout
}
export def "keeper policy" []: nothing -> nothing {
let ws = workspace-id
let policy_repo = $env.HOME | path join ".local/share/radicle/repos" $"policy-($ws)"
if not ($policy_repo | path exists) {
print $"Policy repo not cloned locally: policy-($ws)"
print "Run: rad clone rad:<rid> policy-($ws)"
return
}
let policy_path = [$policy_repo, "policy.ncl"] | path join
if not ($policy_path | path exists) { print "policy.ncl not found in policy repo"; return }
let r = do { ^nickel export $policy_path } | complete
if $r.exit_code != 0 { print $"Failed to load policy: ($r.stderr | str trim)"; return }
let p = $r.stdout | from json
print $"workspace: ($p.workspace)"
print $"version: ($p.version)"
print ""
print "auto_sign rules:"
$p.auto_sign? | default [] | each { |rule|
print $" op_type=($rule.op_type) target=($rule.target? | default '*') scope=($rule.scope? | default 'any')"
}
print ""
print "require_manual rules:"
$p.require_manual? | default [] | each { |rule|
print $" op_type=($rule.op_type) target=($rule.target? | default '*')"
}
}
export def "keeper switch" [mode: string]: nothing -> nothing {
let valid_modes = ["auto", "operator-only"]
if not ($valid_modes | any { |m| $m == $mode }) {
error make { msg: $"Invalid mode '($mode)'. Valid modes: ($valid_modes | str join ', ')" }
}
let playbook = if $mode == "auto" { "switch_to_vm_ops" } else { "switch_to_operator_only" }
print $"Delegating to playbook: ($playbook)"
playbook run $playbook
}
# ─── governance (ADR-038 Radicle delegation) ─────────────────────────────────
export def "governance delegations" []: nothing -> nothing {
let ws = workspace-id
let repos = ["policy", "desired", "state"] | each { |r| $"($r)-($ws)" }
$repos | each { |repo_name|
let r = do { ^rad id --repo $repo_name --json } | complete
if $r.exit_code != 0 {
{ repo: $repo_name, error: ($r.stderr | str trim), delegates: [] }
} else {
let info = $r.stdout | from json
{ repo: $repo_name, threshold: ($info.threshold? | default 1), delegates: ($info.delegates? | default []) }
}
}
}
export def "governance signers" []: nothing -> nothing {
let ws = workspace-id
if not (nats-available) { print "nats CLI not found"; return }
let r = do { ^nats auth account ls --json } | complete
if $r.exit_code != 0 {
print $"NATS auth query failed: ($r.stderr | str trim)"
return
}
let accounts = $r.stdout | from json
let ops_accounts = $accounts | where { |a| ($a.name? | default "") | str contains $ws }
if ($ops_accounts | is-empty) { print $"No NATS accounts found for workspace: ($ws)"; return }
$ops_accounts | each { |a|
{ account: $a.name, subject: ($a.subject? | default ""), signers: ($a.signing_keys? | default []) }
}
}
feat: domain extension system, VCS abstraction, personal/provisioning domains, web subpages Domain extension system (ADR-012): bash-layer dispatch activates repo_kind-conditional CLI domains. install.nu copies domains/ tree; short_alias wrappers generated (personal, prov). ore help and describe capabilities domain-aware. personal domain (PersonalOntology): career skills/talks/publications/positioning, CFP pipeline (Watching→Delivered), opportunities lifecycle, content pipeline, Sessionize integration. Daemon pages: /career, /personal. provisioning domain (DevWorkspace/Mixed): FSM state, next transitions, connections graph, gates, workspace card, capabilities, backlog. Daemon page: /provisioning. VCS abstraction layer (ADR-013): reflection/modules/vcs.nu — uniform jj/git API via filesystem detection (.jj/ vs .git/). opmode.nu and git-event.nu migrated off ^git. reflection/bin/jjw.nu — jj + ontoref + Radicle agent workspace lifecycle. jjw-ncl-merge.nu registered as jj merge tool for .ontology/ NCL conflicts. init-repo.nu for new_project mode. jj/rad not in ontoref requirements — belong in orchestration project manifests. 'Framework RepoKind: ontology/schemas/manifest.ncl gains 'Framework variant; ontoref self-identifies as framework — no domain activates for the protocol itself. Web presence: personal.html and provisioning.html domain subpages. index.html gains "Project Types — Domain Extensions" section with type cards and subpage links. Nav compacted (Arch/Prov labels, solid backdrop-filter background). on+re: vcs-abstraction (adrs: adr-013) and agent-workspace-orchestration Practice nodes; 21 manifest capabilities; state.ncl catalysts updated.
2026-04-07 23:08:29 +01:00
# ─── help + main ──────────────────────────────────────────────────────────────
feat: #[onto_mcp_tool] catalog, OCI credential vault layer, validate ADR-018 mode hierarchy ontoref-derive: #[onto_mcp_tool] attribute macro registers MCP tool unit-structs in the catalog at link time via inventory::submit!; annotated item is emitted unchanged, ToolBase/AsyncTool impls stay on the struct. All 34 tools migrated from manual wiring (net +5: ontoref_list_projects, ontoref_search, ontoref_describe, ontoref_list_ontology_extensions, ontoref_get_ontology_extension). validate modes (ADR-018): reads level_hierarchy from workflow.ncl and checks every .ncl mode for level declared, strategy declared, delegate chain coherent, compose extends valid. mode resolve <id> shows which hierarchy level handles a mode and why. --self-test generates synthetic fixtures in a temp dir for CI smoke-testing. validate run-cargo: two-step Cargo.toml resolution — workspace layout first (crates/<check.crate>/Cargo.toml), single-crate fallback by package name or repo basename. Lets the same ADR constraint shape apply to workspace and single-crate repos. ontology/schemas/manifest.ncl: registry_topology_type contract — multi-registry coordination, push targets, participant scopes, per-namespace capability. reflection/requirements/base.ncl: oras ≥1.2.0, cosign ≥2.0.0, sops ≥3.9.0, age ≥1.1.0, restic declared as Hard/Soft requirements with version_min, check_cmd, and install_hint (ADR-017 toolchain surface). ADR-019: per-file recipient routing for tenant isolation without multi-vault. Schema additions: sops.recipient_groups + sops.recipient_rules in ontoref-project.ncl. secrets-bootstrap generates .sops.yaml from project.ncl in declarative mode. Three new secrets-audit checks: recipient-routing-coherent, recipient-routing-coverage, no-multi-vault. Adoption templates: single-team/, multi-tenant/, agent-first/. Integration templates: domain-producer/, mode-producer/, mode-consumer/. UI: project_picker surfaces registry badge (⟳ participant) and vault badge (⛁ vault_id · N, green=declarative / amber=legacy) per project card. Expanded panel adds collapsible Registry section with namespace, endpoint, and push/pull capability. manage.html gains Runtime Services card — MCP and GraphQL toggleable without restart via HTMX POST /ui/manage/services/{service}/toggle. describe.nu: capabilities JSON includes registry_topology and vault_state per project. sync.nu: drift check extended to detect //! absence on newly registered crates. qa.ncl: six entries — credential-vault-best-practice (layered data-flow diagram), credential-vault-templates (paths A/B/C), credential-vault-troubleshooting (15 named errors), integration-what-and-why (ADR-042 OCI federation), integration-how-to-implement, integration-troubleshooting. on+re: core.ncl + manifest.ncl updated to reflect OCI, MCP, and mode-hierarchy nodes. Deleted stale presentation assets (2026-02 slides + voice notes).
2026-05-12 04:46:15 +01:00
# ─── registry (i sub-domain) ──────────────────────────────────────────────────
const DEFAULT_REGISTRY = "reg.librecloud.online"
def _find-capabilities-ncl []: nothing -> string {
let ws_path = ($env | get -o PROVISIONING_WORKSPACE_PATH | default "")
if ($ws_path | is-not-empty) {
let candidates = (do { glob $"($ws_path)/infra/*/capabilities.ncl" } | default [])
if ($candidates | is-not-empty) { return ($candidates | first) }
}
mut dir = $env.PWD
for _ in 0..6 {
let cur = $dir # immutable copy for closure capture in glob
let candidates = (do { glob $"($cur)/infra/*/capabilities.ncl" } | default [])
if ($candidates | is-not-empty) { return ($candidates | first) }
let parent = ($dir | path dirname)
if $parent == $dir { break }
$dir = $parent
}
""
}
export def "i resolve-registry" []: nothing -> string {
let from_env = ($env | get -o PROVISIONING_REGISTRY | default "")
if ($from_env | is-not-empty) { return $from_env }
let caps = (_find-capabilities-ncl)
if ($caps | is-not-empty) {
let ip = ($env.NICKEL_IMPORT_PATH? | default ($env.PROVISIONING? | default ""))
let ncl = (do { ^nickel export --import-path $ip $caps } | complete)
if $ncl.exit_code == 0 {
let data = ($ncl.stdout | from json)
let reg_default = ($data | get -o provides.registries.default | default "")
let registries = ($data | get -o provides.registries.registries | default [])
if ($reg_default | is-not-empty) and ($registries | is-not-empty) {
let entry = ($registries | where { |e| $e.id == $reg_default } | first | default null)
if ($entry != null) and ($entry.endpoint? | default "" | is-not-empty) {
return $entry.endpoint
}
}
}
}
$DEFAULT_REGISTRY
}
export def "i list" [--live]: nothing -> nothing {
let reg = (i resolve-registry)
if not $live {
print $"registry : ($reg)"
print "Use --live to query the live catalog."
return
}
let url = $"https://($reg)/v2/_catalog"
let body = try { http get $url } catch {
print $"Registry catalog unavailable at ($url)"
return
}
let repos = ($body | get -o repositories | default [])
let domains = ($repos | where { |r| $r | str starts-with "domains/" } | each { |r|
let parts = ($r | str replace "domains/" "" | split row "/")
{ kind: "domain", participant: ($parts | first), id: ($parts | skip 1 | str join "/"), ref: $"($reg)/($r)" }
})
let modes = ($repos | where { |r| $r | str starts-with "modes/" } | each { |r|
let parts = ($r | str replace "modes/" "" | split row "/")
{ kind: "mode", participant: ($parts | first), id: ($parts | skip 1 | str join "/"), ref: $"($reg)/($r)" }
})
let all = ($domains | append $modes)
if ($all | is-empty) {
print $"No domains/ or modes/ artifacts found in ($reg)"
return
}
print $"registry: ($reg) artifacts: ($all | length)"
print ""
$all | each { |a|
print $" ($a.kind) ($a.participant)/($a.id) → ($a.ref)"
}
null
}
feat: domain extension system, VCS abstraction, personal/provisioning domains, web subpages Domain extension system (ADR-012): bash-layer dispatch activates repo_kind-conditional CLI domains. install.nu copies domains/ tree; short_alias wrappers generated (personal, prov). ore help and describe capabilities domain-aware. personal domain (PersonalOntology): career skills/talks/publications/positioning, CFP pipeline (Watching→Delivered), opportunities lifecycle, content pipeline, Sessionize integration. Daemon pages: /career, /personal. provisioning domain (DevWorkspace/Mixed): FSM state, next transitions, connections graph, gates, workspace card, capabilities, backlog. Daemon page: /provisioning. VCS abstraction layer (ADR-013): reflection/modules/vcs.nu — uniform jj/git API via filesystem detection (.jj/ vs .git/). opmode.nu and git-event.nu migrated off ^git. reflection/bin/jjw.nu — jj + ontoref + Radicle agent workspace lifecycle. jjw-ncl-merge.nu registered as jj merge tool for .ontology/ NCL conflicts. init-repo.nu for new_project mode. jj/rad not in ontoref requirements — belong in orchestration project manifests. 'Framework RepoKind: ontology/schemas/manifest.ncl gains 'Framework variant; ontoref self-identifies as framework — no domain activates for the protocol itself. Web presence: personal.html and provisioning.html domain subpages. index.html gains "Project Types — Domain Extensions" section with type cards and subpage links. Nav compacted (Arch/Prov labels, solid backdrop-filter background). on+re: vcs-abstraction (adrs: adr-013) and agent-workspace-orchestration Practice nodes; 21 manifest capabilities; state.ncl catalysts updated.
2026-04-07 23:08:29 +01:00
def show-help [] {
print "Provisioning — ontoref domain extension"
print ""
print "USAGE"
print " ore provisioning <command> [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 <decision> 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 <id> Full detail of a backlog item"
feat: #[onto_mcp_tool] catalog, OCI credential vault layer, validate ADR-018 mode hierarchy ontoref-derive: #[onto_mcp_tool] attribute macro registers MCP tool unit-structs in the catalog at link time via inventory::submit!; annotated item is emitted unchanged, ToolBase/AsyncTool impls stay on the struct. All 34 tools migrated from manual wiring (net +5: ontoref_list_projects, ontoref_search, ontoref_describe, ontoref_list_ontology_extensions, ontoref_get_ontology_extension). validate modes (ADR-018): reads level_hierarchy from workflow.ncl and checks every .ncl mode for level declared, strategy declared, delegate chain coherent, compose extends valid. mode resolve <id> shows which hierarchy level handles a mode and why. --self-test generates synthetic fixtures in a temp dir for CI smoke-testing. validate run-cargo: two-step Cargo.toml resolution — workspace layout first (crates/<check.crate>/Cargo.toml), single-crate fallback by package name or repo basename. Lets the same ADR constraint shape apply to workspace and single-crate repos. ontology/schemas/manifest.ncl: registry_topology_type contract — multi-registry coordination, push targets, participant scopes, per-namespace capability. reflection/requirements/base.ncl: oras ≥1.2.0, cosign ≥2.0.0, sops ≥3.9.0, age ≥1.1.0, restic declared as Hard/Soft requirements with version_min, check_cmd, and install_hint (ADR-017 toolchain surface). ADR-019: per-file recipient routing for tenant isolation without multi-vault. Schema additions: sops.recipient_groups + sops.recipient_rules in ontoref-project.ncl. secrets-bootstrap generates .sops.yaml from project.ncl in declarative mode. Three new secrets-audit checks: recipient-routing-coherent, recipient-routing-coverage, no-multi-vault. Adoption templates: single-team/, multi-tenant/, agent-first/. Integration templates: domain-producer/, mode-producer/, mode-consumer/. UI: project_picker surfaces registry badge (⟳ participant) and vault badge (⛁ vault_id · N, green=declarative / amber=legacy) per project card. Expanded panel adds collapsible Registry section with namespace, endpoint, and push/pull capability. manage.html gains Runtime Services card — MCP and GraphQL toggleable without restart via HTMX POST /ui/manage/services/{service}/toggle. describe.nu: capabilities JSON includes registry_topology and vault_state per project. sync.nu: drift check extended to detect //! absence on newly registered crates. qa.ncl: six entries — credential-vault-best-practice (layered data-flow diagram), credential-vault-templates (paths A/B/C), credential-vault-troubleshooting (15 named errors), integration-what-and-why (ADR-042 OCI federation), integration-how-to-implement, integration-troubleshooting. on+re: core.ncl + manifest.ncl updated to reflect OCI, MCP, and mode-hierarchy nodes. Deleted stale presentation assets (2026-02 slides + voice notes).
2026-05-12 04:46:15 +01:00
print " install [--mode] [--platform] Install provisioning platform services"
print ""
print "COMMANDS (DevWorkspace — ops contract, ADR-037)"
print " ops list Pending ops queue depth for this workspace"
print " ops describe <id> Full op detail: JWT claims, scopes, expected_version"
print " ops sign <id> Operator signs a pending op via keeper-cli"
print " ops history [<workspace>] Applied ops from <workspace>-state Radicle ledger"
print ""
print "COMMANDS (DevWorkspace — playbooks)"
print " playbook list Available playbooks for this workspace"
print " playbook describe <name> Steps, params, preconditions of a playbook"
print " playbook run <name> Execute a playbook (use --dry-run first)"
print " playbook history Past playbook executions from audit ledger"
print ""
print "COMMANDS (DevWorkspace — keeper daemon, ADR-037)"
print " keeper status Keeper mode (auto|operator-only|down) + policy version"
print " keeper policy Active keeper policy from policy-<workspace> Radicle repo"
print " keeper switch <mode> Switch keeper mode (delegates to switch_to_<mode> playbook)"
print ""
print "COMMANDS (DevWorkspace — governance, ADR-038)"
print " governance delegations Radicle delegation sets for policy/desired/state repos"
print " governance signers Active NATS JWT signers and M-of-N quorum status"
print ""
print "COMMANDS (all repo_kinds — registry)"
print " i resolve-registry Resolved OCI registry endpoint (env → capabilities.ncl → default)"
print " i list Show resolved registry endpoint"
print " i list --live Query _catalog and list live domains/ and modes/ artifacts"
feat: domain extension system, VCS abstraction, personal/provisioning domains, web subpages Domain extension system (ADR-012): bash-layer dispatch activates repo_kind-conditional CLI domains. install.nu copies domains/ tree; short_alias wrappers generated (personal, prov). ore help and describe capabilities domain-aware. personal domain (PersonalOntology): career skills/talks/publications/positioning, CFP pipeline (Watching→Delivered), opportunities lifecycle, content pipeline, Sessionize integration. Daemon pages: /career, /personal. provisioning domain (DevWorkspace/Mixed): FSM state, next transitions, connections graph, gates, workspace card, capabilities, backlog. Daemon page: /provisioning. VCS abstraction layer (ADR-013): reflection/modules/vcs.nu — uniform jj/git API via filesystem detection (.jj/ vs .git/). opmode.nu and git-event.nu migrated off ^git. reflection/bin/jjw.nu — jj + ontoref + Radicle agent workspace lifecycle. jjw-ncl-merge.nu registered as jj merge tool for .ontology/ NCL conflicts. init-repo.nu for new_project mode. jj/rad not in ontoref requirements — belong in orchestration project manifests. 'Framework RepoKind: ontology/schemas/manifest.ncl gains 'Framework variant; ontoref self-identifies as framework — no domain activates for the protocol itself. Web presence: personal.html and provisioning.html domain subpages. index.html gains "Project Types — Domain Extensions" section with type cards and subpage links. Nav compacted (Arch/Prov labels, solid backdrop-filter background). on+re: vcs-abstraction (adrs: adr-013) and agent-workspace-orchestration Practice nodes; 21 manifest capabilities; state.ncl catalysts updated.
2026-04-07 23:08:29 +01:00
}
def main [
...args: string
--priority: string = ""
feat: #[onto_mcp_tool] catalog, OCI credential vault layer, validate ADR-018 mode hierarchy ontoref-derive: #[onto_mcp_tool] attribute macro registers MCP tool unit-structs in the catalog at link time via inventory::submit!; annotated item is emitted unchanged, ToolBase/AsyncTool impls stay on the struct. All 34 tools migrated from manual wiring (net +5: ontoref_list_projects, ontoref_search, ontoref_describe, ontoref_list_ontology_extensions, ontoref_get_ontology_extension). validate modes (ADR-018): reads level_hierarchy from workflow.ncl and checks every .ncl mode for level declared, strategy declared, delegate chain coherent, compose extends valid. mode resolve <id> shows which hierarchy level handles a mode and why. --self-test generates synthetic fixtures in a temp dir for CI smoke-testing. validate run-cargo: two-step Cargo.toml resolution — workspace layout first (crates/<check.crate>/Cargo.toml), single-crate fallback by package name or repo basename. Lets the same ADR constraint shape apply to workspace and single-crate repos. ontology/schemas/manifest.ncl: registry_topology_type contract — multi-registry coordination, push targets, participant scopes, per-namespace capability. reflection/requirements/base.ncl: oras ≥1.2.0, cosign ≥2.0.0, sops ≥3.9.0, age ≥1.1.0, restic declared as Hard/Soft requirements with version_min, check_cmd, and install_hint (ADR-017 toolchain surface). ADR-019: per-file recipient routing for tenant isolation without multi-vault. Schema additions: sops.recipient_groups + sops.recipient_rules in ontoref-project.ncl. secrets-bootstrap generates .sops.yaml from project.ncl in declarative mode. Three new secrets-audit checks: recipient-routing-coherent, recipient-routing-coverage, no-multi-vault. Adoption templates: single-team/, multi-tenant/, agent-first/. Integration templates: domain-producer/, mode-producer/, mode-consumer/. UI: project_picker surfaces registry badge (⟳ participant) and vault badge (⛁ vault_id · N, green=declarative / amber=legacy) per project card. Expanded panel adds collapsible Registry section with namespace, endpoint, and push/pull capability. manage.html gains Runtime Services card — MCP and GraphQL toggleable without restart via HTMX POST /ui/manage/services/{service}/toggle. describe.nu: capabilities JSON includes registry_topology and vault_state per project. sync.nu: drift check extended to detect //! absence on newly registered crates. qa.ncl: six entries — credential-vault-best-practice (layered data-flow diagram), credential-vault-templates (paths A/B/C), credential-vault-troubleshooting (15 named errors), integration-what-and-why (ADR-042 OCI federation), integration-how-to-implement, integration-troubleshooting. on+re: core.ncl + manifest.ncl updated to reflect OCI, MCP, and mode-hierarchy nodes. Deleted stale presentation assets (2026-02 slides + voice notes).
2026-05-12 04:46:15 +01:00
--mode: string = "solo"
--platform: string = ""
--dry-run
--live
feat: domain extension system, VCS abstraction, personal/provisioning domains, web subpages Domain extension system (ADR-012): bash-layer dispatch activates repo_kind-conditional CLI domains. install.nu copies domains/ tree; short_alias wrappers generated (personal, prov). ore help and describe capabilities domain-aware. personal domain (PersonalOntology): career skills/talks/publications/positioning, CFP pipeline (Watching→Delivered), opportunities lifecycle, content pipeline, Sessionize integration. Daemon pages: /career, /personal. provisioning domain (DevWorkspace/Mixed): FSM state, next transitions, connections graph, gates, workspace card, capabilities, backlog. Daemon page: /provisioning. VCS abstraction layer (ADR-013): reflection/modules/vcs.nu — uniform jj/git API via filesystem detection (.jj/ vs .git/). opmode.nu and git-event.nu migrated off ^git. reflection/bin/jjw.nu — jj + ontoref + Radicle agent workspace lifecycle. jjw-ncl-merge.nu registered as jj merge tool for .ontology/ NCL conflicts. init-repo.nu for new_project mode. jj/rad not in ontoref requirements — belong in orchestration project manifests. 'Framework RepoKind: ontology/schemas/manifest.ncl gains 'Framework variant; ontoref self-identifies as framework — no domain activates for the protocol itself. Web presence: personal.html and provisioning.html domain subpages. index.html gains "Project Types — Domain Extensions" section with type cards and subpage links. Nav compacted (Arch/Prov labels, solid backdrop-filter background). on+re: vcs-abstraction (adrs: adr-013) and agent-workspace-orchestration Practice nodes; 21 manifest capabilities; state.ncl catalysts updated.
2026-04-07 23:08:29 +01:00
] {
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 }
feat: #[onto_mcp_tool] catalog, OCI credential vault layer, validate ADR-018 mode hierarchy ontoref-derive: #[onto_mcp_tool] attribute macro registers MCP tool unit-structs in the catalog at link time via inventory::submit!; annotated item is emitted unchanged, ToolBase/AsyncTool impls stay on the struct. All 34 tools migrated from manual wiring (net +5: ontoref_list_projects, ontoref_search, ontoref_describe, ontoref_list_ontology_extensions, ontoref_get_ontology_extension). validate modes (ADR-018): reads level_hierarchy from workflow.ncl and checks every .ncl mode for level declared, strategy declared, delegate chain coherent, compose extends valid. mode resolve <id> shows which hierarchy level handles a mode and why. --self-test generates synthetic fixtures in a temp dir for CI smoke-testing. validate run-cargo: two-step Cargo.toml resolution — workspace layout first (crates/<check.crate>/Cargo.toml), single-crate fallback by package name or repo basename. Lets the same ADR constraint shape apply to workspace and single-crate repos. ontology/schemas/manifest.ncl: registry_topology_type contract — multi-registry coordination, push targets, participant scopes, per-namespace capability. reflection/requirements/base.ncl: oras ≥1.2.0, cosign ≥2.0.0, sops ≥3.9.0, age ≥1.1.0, restic declared as Hard/Soft requirements with version_min, check_cmd, and install_hint (ADR-017 toolchain surface). ADR-019: per-file recipient routing for tenant isolation without multi-vault. Schema additions: sops.recipient_groups + sops.recipient_rules in ontoref-project.ncl. secrets-bootstrap generates .sops.yaml from project.ncl in declarative mode. Three new secrets-audit checks: recipient-routing-coherent, recipient-routing-coverage, no-multi-vault. Adoption templates: single-team/, multi-tenant/, agent-first/. Integration templates: domain-producer/, mode-producer/, mode-consumer/. UI: project_picker surfaces registry badge (⟳ participant) and vault badge (⛁ vault_id · N, green=declarative / amber=legacy) per project card. Expanded panel adds collapsible Registry section with namespace, endpoint, and push/pull capability. manage.html gains Runtime Services card — MCP and GraphQL toggleable without restart via HTMX POST /ui/manage/services/{service}/toggle. describe.nu: capabilities JSON includes registry_topology and vault_state per project. sync.nu: drift check extended to detect //! absence on newly registered crates. qa.ncl: six entries — credential-vault-best-practice (layered data-flow diagram), credential-vault-templates (paths A/B/C), credential-vault-troubleshooting (15 named errors), integration-what-and-why (ADR-042 OCI federation), integration-how-to-implement, integration-troubleshooting. on+re: core.ncl + manifest.ncl updated to reflect OCI, MCP, and mode-hierarchy nodes. Deleted stale presentation assets (2026-02 slides + voice notes).
2026-05-12 04:46:15 +01:00
"install" => { if $dry_run { install --mode $mode --platform $platform --dry-run } else { install --mode $mode --platform $platform } }
feat: domain extension system, VCS abstraction, personal/provisioning domains, web subpages Domain extension system (ADR-012): bash-layer dispatch activates repo_kind-conditional CLI domains. install.nu copies domains/ tree; short_alias wrappers generated (personal, prov). ore help and describe capabilities domain-aware. personal domain (PersonalOntology): career skills/talks/publications/positioning, CFP pipeline (Watching→Delivered), opportunities lifecycle, content pipeline, Sessionize integration. Daemon pages: /career, /personal. provisioning domain (DevWorkspace/Mixed): FSM state, next transitions, connections graph, gates, workspace card, capabilities, backlog. Daemon page: /provisioning. VCS abstraction layer (ADR-013): reflection/modules/vcs.nu — uniform jj/git API via filesystem detection (.jj/ vs .git/). opmode.nu and git-event.nu migrated off ^git. reflection/bin/jjw.nu — jj + ontoref + Radicle agent workspace lifecycle. jjw-ncl-merge.nu registered as jj merge tool for .ontology/ NCL conflicts. init-repo.nu for new_project mode. jj/rad not in ontoref requirements — belong in orchestration project manifests. 'Framework RepoKind: ontology/schemas/manifest.ncl gains 'Framework variant; ontoref self-identifies as framework — no domain activates for the protocol itself. Web presence: personal.html and provisioning.html domain subpages. index.html gains "Project Types — Domain Extensions" section with type cards and subpage links. Nav compacted (Arch/Prov labels, solid backdrop-filter background). on+re: vcs-abstraction (adrs: adr-013) and agent-workspace-orchestration Practice nodes; 21 manifest capabilities; state.ncl catalysts updated.
2026-04-07 23:08:29 +01:00
"backlog" => { backlog --priority $priority }
feat: #[onto_mcp_tool] catalog, OCI credential vault layer, validate ADR-018 mode hierarchy ontoref-derive: #[onto_mcp_tool] attribute macro registers MCP tool unit-structs in the catalog at link time via inventory::submit!; annotated item is emitted unchanged, ToolBase/AsyncTool impls stay on the struct. All 34 tools migrated from manual wiring (net +5: ontoref_list_projects, ontoref_search, ontoref_describe, ontoref_list_ontology_extensions, ontoref_get_ontology_extension). validate modes (ADR-018): reads level_hierarchy from workflow.ncl and checks every .ncl mode for level declared, strategy declared, delegate chain coherent, compose extends valid. mode resolve <id> shows which hierarchy level handles a mode and why. --self-test generates synthetic fixtures in a temp dir for CI smoke-testing. validate run-cargo: two-step Cargo.toml resolution — workspace layout first (crates/<check.crate>/Cargo.toml), single-crate fallback by package name or repo basename. Lets the same ADR constraint shape apply to workspace and single-crate repos. ontology/schemas/manifest.ncl: registry_topology_type contract — multi-registry coordination, push targets, participant scopes, per-namespace capability. reflection/requirements/base.ncl: oras ≥1.2.0, cosign ≥2.0.0, sops ≥3.9.0, age ≥1.1.0, restic declared as Hard/Soft requirements with version_min, check_cmd, and install_hint (ADR-017 toolchain surface). ADR-019: per-file recipient routing for tenant isolation without multi-vault. Schema additions: sops.recipient_groups + sops.recipient_rules in ontoref-project.ncl. secrets-bootstrap generates .sops.yaml from project.ncl in declarative mode. Three new secrets-audit checks: recipient-routing-coherent, recipient-routing-coverage, no-multi-vault. Adoption templates: single-team/, multi-tenant/, agent-first/. Integration templates: domain-producer/, mode-producer/, mode-consumer/. UI: project_picker surfaces registry badge (⟳ participant) and vault badge (⛁ vault_id · N, green=declarative / amber=legacy) per project card. Expanded panel adds collapsible Registry section with namespace, endpoint, and push/pull capability. manage.html gains Runtime Services card — MCP and GraphQL toggleable without restart via HTMX POST /ui/manage/services/{service}/toggle. describe.nu: capabilities JSON includes registry_topology and vault_state per project. sync.nu: drift check extended to detect //! absence on newly registered crates. qa.ncl: six entries — credential-vault-best-practice (layered data-flow diagram), credential-vault-templates (paths A/B/C), credential-vault-troubleshooting (15 named errors), integration-what-and-why (ADR-042 OCI federation), integration-how-to-implement, integration-troubleshooting. on+re: core.ncl + manifest.ncl updated to reflect OCI, MCP, and mode-hierarchy nodes. Deleted stale presentation assets (2026-02 slides + voice notes).
2026-05-12 04:46:15 +01:00
"ops list" => { ops list }
"ops history" => { ops history }
"keeper status" => { keeper status }
"keeper policy" => { keeper policy }
"governance delegations" => { governance delegations }
"governance signers" => { governance signers }
"playbook list" => { playbook list }
"playbook history" => { playbook history }
_ if ($sub | str starts-with "backlog show ") => { backlog show ($args | get 2) }
_ if ($sub | str starts-with "validate ") => { validate ($args | skip 1 | str join " ") }
_ if ($sub | str starts-with "ops describe ") => { ops describe ($args | get 2) }
_ if ($sub | str starts-with "ops sign ") => { ops sign ($args | get 2) }
_ if ($sub | str starts-with "playbook describe ") => { playbook describe ($args | get 2) }
_ if ($sub | str starts-with "playbook run ") => {
if $dry_run { playbook run ($args | get 2) --dry-run } else { playbook run ($args | get 2) }
}
_ if ($sub | str starts-with "keeper switch ") => { keeper switch ($args | get 2) }
_ if ($sub | str starts-with "ops history ") => { ops history --workspace ($args | get 2) }
"i resolve-registry" => { i resolve-registry | print }
"i list" => { if $live { i list --live } else { i list } }
feat: domain extension system, VCS abstraction, personal/provisioning domains, web subpages Domain extension system (ADR-012): bash-layer dispatch activates repo_kind-conditional CLI domains. install.nu copies domains/ tree; short_alias wrappers generated (personal, prov). ore help and describe capabilities domain-aware. personal domain (PersonalOntology): career skills/talks/publications/positioning, CFP pipeline (Watching→Delivered), opportunities lifecycle, content pipeline, Sessionize integration. Daemon pages: /career, /personal. provisioning domain (DevWorkspace/Mixed): FSM state, next transitions, connections graph, gates, workspace card, capabilities, backlog. Daemon page: /provisioning. VCS abstraction layer (ADR-013): reflection/modules/vcs.nu — uniform jj/git API via filesystem detection (.jj/ vs .git/). opmode.nu and git-event.nu migrated off ^git. reflection/bin/jjw.nu — jj + ontoref + Radicle agent workspace lifecycle. jjw-ncl-merge.nu registered as jj merge tool for .ontology/ NCL conflicts. init-repo.nu for new_project mode. jj/rad not in ontoref requirements — belong in orchestration project manifests. 'Framework RepoKind: ontology/schemas/manifest.ncl gains 'Framework variant; ontoref self-identifies as framework — no domain activates for the protocol itself. Web presence: personal.html and provisioning.html domain subpages. index.html gains "Project Types — Domain Extensions" section with type cards and subpage links. Nav compacted (Arch/Prov labels, solid backdrop-filter background). on+re: vcs-abstraction (adrs: adr-013) and agent-workspace-orchestration Practice nodes; 21 manifest capabilities; state.ncl catalysts updated.
2026-04-07 23:08:29 +01:00
_ => { print $"Unknown command: ($sub)"; show-help }
}
}