# Form: Create or edit an ADR # Backend: CLI / TUI / Web / Agent # # Roundtrip: # typedialog nickel-roundtrip \ # --input adrs/_template.ncl \ # --form reflection/forms/new_adr.ncl \ # --output adrs/adr-NNN-title.ncl \ # --ncl-template reflection/templates/adr.ncl.j2 # # Agent query (get field structure without running a form): # nickel export reflection/forms/new_adr.ncl \ # | get elements \ # | where type != "section_header" \ # | where type != "section" \ # | select name prompt nickel_path required default { name = "New ADR", description = "Author or edit an Architectural Decision Record. Produces a validated Nickel file at adrs/adr-NNN-title.ncl.", display_mode = "complete", elements = [ # ── Identity ───────────────────────────────────────────────────────────── { type = "section_header", name = "identity_header", title = "ADR Identity", border_top = true, border_bottom = true }, { type = "text", name = "id", prompt = "ADR identifier", required = true, help = "Format: adr-NNN. Run `ls adrs/adr-*.ncl | sort` to find the next number.", nickel_path = ["id"] }, { type = "text", name = "title", prompt = "Title", required = true, placeholder = "Declarative statement of the decision (not a question)", help = "Should complete the sentence: 'We decided that...'", nickel_path = ["title"] }, { type = "select", name = "status", prompt = "Status", default = "Proposed", options = [ { value = "Proposed", label = "Proposed — draft, not yet authoritative" }, { value = "Accepted", label = "Accepted — active, constraints are live" }, { value = "Superseded", label = "Superseded — replaced by another ADR (keep file)" }, { value = "Deprecated", label = "Deprecated — abandoned without replacement" }, ], nickel_path = ["status"] }, { type = "text", name = "date", prompt = "Date (YYYY-MM-DD)", default = "2026-03-09", placeholder = "2026-03-09", nickel_path = ["date"] }, # ── Context & Decision ─────────────────────────────────────────────────── { type = "section_header", name = "context_header", title = "Context & Decision", border_top = true, border_bottom = true }, { type = "editor", name = "context", prompt = "Context", required = true, file_extension = "md", prefix_text = "# What situation led to this decision?\n# What forces are at play?\n\n", help = "Describe the situation without yet mentioning the decision.", nickel_path = ["context"] }, { type = "editor", name = "decision", prompt = "Decision", required = true, file_extension = "md", prefix_text = "# State the decision in one or two sentences.\n# Be declarative, not prescriptive.\n\n", nickel_path = ["decision"] }, # ── Rationale ──────────────────────────────────────────────────────────── { type = "section_header", name = "rationale_header", title = "Rationale", border_top = true, border_bottom = true }, { type = "editor", name = "rationale", prompt = "Rationale entries (Nickel array)", required = true, file_extension = "ncl", prefix_text = "# Each entry: { claim = \"...\", detail = \"...\" }\n# claim: one-line assertion. detail: the supporting argument.\n\n", help = "At least one entry. claim answers 'why'; detail explains the mechanism.", nickel_path = ["rationale"] }, # ── Constraints ────────────────────────────────────────────────────────── { type = "section_header", name = "constraints_header", title = "Constraints (active checks)", border_top = true, border_bottom = true }, { type = "section", name = "constraints_note", content = "Every ADR requires at least one Hard constraint. check_hint must be an executable command — not prose. The constraint is what makes the ADR machine-verifiable." }, { type = "editor", name = "constraints", prompt = "Constraints (Nickel array)", required = true, file_extension = "ncl", prefix_text = "# Required fields per entry:\n# id = \"kebab-case-id\",\n# claim = \"What must be true\",\n# scope = \"Where this applies\",\n# severity = 'Hard, # Hard | Soft\n# check_hint = \"executable command that returns non-zero on violation\",\n# rationale = \"Why this constraint\",\n\n", help = "Hard: non-negotiable, blocks a change. Soft: guideline, requires justification to bypass.", nickel_path = ["constraints"] }, # ── Consequences ───────────────────────────────────────────────────────── { type = "section_header", name = "consequences_header", title = "Consequences", border_top = true, border_bottom = true }, { type = "editor", name = "consequences_positive", prompt = "Positive consequences (Nickel array of strings)", required = true, file_extension = "ncl", prefix_text = "# [ \"One benefit\", \"Another benefit\" ]\n\n", nickel_path = ["consequences", "positive"] }, { type = "editor", name = "consequences_negative", prompt = "Negative consequences / trade-offs (Nickel array of strings)", required = true, file_extension = "ncl", prefix_text = "# [ \"One trade-off\", \"Another trade-off\" ]\n\n", nickel_path = ["consequences", "negative"] }, # ── Alternatives ───────────────────────────────────────────────────────── { type = "section_header", name = "alternatives_header", title = "Alternatives Considered", border_top = true, border_bottom = true }, { type = "editor", name = "alternatives_considered", prompt = "Alternatives (Nickel array)", required = true, file_extension = "ncl", prefix_text = "# Each entry: { option = \"Name\", why_rejected = \"Reason\" }\n\n", nickel_path = ["alternatives_considered"] }, # ── Ontology check ─────────────────────────────────────────────────────── { type = "section_header", name = "ontology_header", title = "Ontology Check", border_top = true, border_bottom = true }, { type = "section", name = "ontology_note", content = "Run before filling: nickel export .ontology/core.ncl | get nodes | where invariant == true | get id" }, { type = "text", name = "ontology_decision_string", prompt = "Decision string (one line, imperative)", required = true, placeholder = "ontoref provides X — each project does Y independently", help = "Concise restatement of the decision for ontology cross-reference.", nickel_path = ["ontology_check", "decision_string"] }, { type = "multiselect", name = "ontology_invariants_at_risk", prompt = "Invariants at risk (select all that apply)", help = "Which core invariants does this decision touch? Query: nickel export .ontology/core.ncl | get nodes | where invariant == true | get id", options = [ { value = "no-runtime-conditioning", label = "no-runtime-conditioning" }, { value = "layer-autonomy", label = "layer-autonomy" }, { value = "project-sovereignty", label = "project-sovereignty" }, { value = "nats-surreal-only-external", label = "nats-surreal-only-external" }, { value = "pattern-not-enforcer", label = "pattern-not-enforcer" }, ], nickel_path = ["ontology_check", "invariants_at_risk"] }, { type = "select", name = "ontology_verdict", prompt = "Verdict", default = "Safe", options = [ { value = "Safe", label = "Safe — no invariant is at risk" }, { value = "RequiresJustification", label = "RequiresJustification — invariant is touched, justification must follow" }, ], nickel_path = ["ontology_check", "verdict"] }, # ── Related ADRs ───────────────────────────────────────────────────────── { type = "section_header", name = "related_header", title = "Related & Supersession", border_top = true, border_bottom = true }, { type = "text", name = "related_adrs", prompt = "Related ADRs (comma-separated, e.g. adr-002,adr-003)", required = false, placeholder = "adr-002,adr-003", help = "ADRs that this decision builds on or responds to.", nickel_path = ["related_adrs"] }, { type = "text", name = "supersedes", prompt = "Supersedes (adr-NNN, if this replaces another ADR)", required = false, placeholder = "adr-002", help = "If set, also edit the old ADR: set status = Superseded and superseded_by = this id.", nickel_path = ["supersedes"] }, # ── Review ─────────────────────────────────────────────────────────────── { type = "section_header", name = "review_header", title = "Review", border_top = true }, { type = "section", name = "review_note", content = "After saving: nickel typecheck adrs/adr-NNN-title.ncl\nOnly set status = Accepted after human review. Proposed ADRs are not authoritative." }, { type = "confirm", name = "ready_to_save", prompt = "All fields complete — generate the ADR file?", default = true }, ], }