199 lines
10 KiB
Plaintext
199 lines
10 KiB
Plaintext
# 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 },
|
|
],
|
|
}
|