#!/usr/bin/env nu # reflection/modules/forms.nu — form listing and execution. # # Error handling policy: # forms list — daemon-export-safe; graceful skip on broken form file # form run — daemon-export (fail loud); agent path renders NCL template via tera # render-* — tera-render direct; fail loud on template error use env.nu * use store.nu [daemon-export, daemon-export-safe] export def "forms list" [] { form-files | each { |f| let data = (daemon-export-safe $f) if $data != null { { name: ($f | path basename | str replace ".ncl" ""), description: ($data.description? | default ""), } } else { null } } | compact } export def "form run" [ name: string, --backend: string = "cli", # Backend: cli (default) | tui | web ] { let actor = ($env.ONTOREF_ACTOR? | default "developer") let forms_dir = $"($env.ONTOREF_ROOT)/reflection/forms" let form_file = $"($forms_dir)/($name).ncl" # Guard: form must exist if not ($form_file | path exists) { let available = (form-files | each { |f| $f | path basename | str replace ".ncl" "" }) print $"Form '($name)' not found." print $"Available: ($available | str join ', ')" exit 1 } if $actor == "agent" { agent-render $name $form_file return } # Guard: typedialog must be present for interactive path if (which typedialog | is-empty) { print "" print "typedialog is required for interactive forms." print "Install: cargo install typedialog" print "" print "Agent path (no typedialog needed):" agent-render-hint $name $form_file exit 1 } run-interactive-form $name $form_file $backend } # Render an ADR from a piped record via tera-render. # { id: "adr-005", title: "...", status: "Proposed" } | form render-adr | save adrs/adr-005-title.ncl export def "form render-adr" [ --output: path, ] { let tmpl = $"($env.ONTOREF_ROOT)/reflection/templates/adr.ncl.j2" let rendered = $in | tera-render $tmpl if ($output | is-not-empty) { $rendered | save --force $output print $"Written: ($output)" } else { $rendered } } # Render a new-project script from a piped record via tera-render. # { project_name: "myapp", project_dir: "/tmp/myapp" } | form render-project --output ~/create.nu export def "form render-project" [ --output: path, ] { let tmpl = $"($env.ONTOREF_ROOT)/reflection/templates/create_project.nu.j2" let rendered = $in | tera-render $tmpl if ($output | is-not-empty) { $rendered | save --force $output print $"Written: ($output)" } else { $rendered } } export def "forms help" [] { let actor = ($env.ONTOREF_ACTOR? | default "developer") print "" print "Form commands:" print " forms list list available forms" print " form run run a form (interactive or agent)" print " form render-adr [--output ] render ADR from piped record" print " form render-project [--output] render new-project script from piped record" print "" for f in (forms list) { print $" ($f.name)" print $" ($f.description)" } if $actor == "agent" { print "" print "Agent render pipeline:" print " nickel-export adrs/_template.ncl | form render-adr --output adrs/adr-005-title.ncl" print " { project_name: 'myapp', ... } | form render-project --output ~/create.nu" print "" print "Inspect form fields:" print " nickel-export reflection/forms/.ncl | get elements" print " | where type != 'section_header' | select name prompt required nickel_path" } print "" } # ── Internal ─────────────────────────────────────────────────────────────────── def form-files [] { glob $"($env.ONTOREF_ROOT)/reflection/forms/*.ncl" } def next-adr-id [] { let root = ($env.ONTOREF_PROJECT_ROOT? | default $env.ONTOREF_ROOT) let nums = ( glob $"($root)/adrs/adr-*.ncl" | each { |f| $f | path basename } | parse "adr-{n}-{rest}.ncl" | get n | each { |n| $n | into int } | sort ) let next = if ($nums | is-empty) { 1 } else { ($nums | last) + 1 } $"adr-($next | fill --alignment right --width 3 --character '0')" } def agent-render [name: string, form_file: string] { if $name == "new_adr" { let root = ($env.ONTOREF_PROJECT_ROOT? | default $env.ONTOREF_ROOT) let template = $"($env.ONTOREF_ROOT)/adrs/_template.ncl" let tmpl = $"($env.ONTOREF_ROOT)/reflection/templates/adr.ncl.j2" let next_id = (next-adr-id) let out = $"($root)/adrs/($next_id)-draft.ncl" print $"Rendering ($next_id) from template — output: ($out)" daemon-export $template | to json | tera-render $tmpl | save --force $out print $"Run: nickel-validate ($out)" } else { agent-render-hint $name $form_file } } def agent-render-hint [name: string, form_file: string] { print "" print $"Fields for '($name)':" print $" nickel-export ($form_file) | get elements" print " | where type != \"section_header\" | select name prompt required nickel_path" print "" } def td-roundtrip [backend: string, input: string, form: string, output: string, ncl_template: string] { match $backend { "web" => { ^typedialog web nickel-roundtrip $input $form --output $output --ncl-template $ncl_template --open }, "tui" => { ^typedialog tui nickel-roundtrip $input $form --output $output --ncl-template $ncl_template }, _ => { ^typedialog nickel-roundtrip $input $form --output $output --ncl-template $ncl_template }, } } def td-form [backend: string, form: string, ...extra: string] { match $backend { "web" => { ^typedialog web form $form ...$extra }, "tui" => { ^typedialog tui $form ...$extra }, _ => { ^typedialog form $form ...$extra }, } } def run-interactive-form [name: string, form_file: string, backend: string] { if $name == "new_adr" { let root = ($env.ONTOREF_PROJECT_ROOT? | default $env.ONTOREF_ROOT) let template = $"($env.ONTOREF_ROOT)/adrs/_template.ncl" let tmpl = $"($env.ONTOREF_ROOT)/reflection/templates/adr.ncl.j2" let next_id = (next-adr-id) let out = $"($root)/adrs/($next_id)-draft.ncl" let tmp = $"($env.HOME)/.ontoref-adr-tmp.ncl" open $template | str replace '"adr-000"' $'"($next_id)"' | save --force $tmp print $"Creating ($next_id) — output: ($out)" td-roundtrip $backend $tmp $form_file $out $tmpl rm --force $tmp print $"Run: nickel typecheck ($out)" } else if $name == "new_project" { let tmpl = $"($env.ONTOREF_ROOT)/reflection/templates/create_project.nu.j2" let out = $"($env.HOME)/ontoref-create-project.nu" td-form $backend $form_file "--ncl-template" $tmpl "--output" $out print $"Script generated: ($out)" print $"Review then: nu ($out)" } else if $name == "supersede_adr" { let tmpl = $"($env.ONTOREF_ROOT)/reflection/templates/supersede_adr.nu.j2" let out = $"($env.HOME)/ontoref-supersede.nu" td-form $backend $form_file "--ncl-template" $tmpl "--output" $out print $"Script generated: ($out)" print $"Review then: nu ($out)" } else { td-form $backend $form_file } }