ADR 0010 - Runtime user inputs
- Status: accepted
- Date: 2026-05-07
- Spec target: XTL 0.1 draft
- Affects: evaluation.md, language.md
- Superseded-By (partial): ADR-0011 — renames the reserved sheet to
__inputs__and replaces{{ _<name> }}with{{ __inputs__[name] }}. Semantics, the type system, host API, and error catalog from this ADR remain authoritative.
Note (2026-05-07): ADR-0011 renamed the reserved sheet
_inputs→__inputs__and replaced the{{ _<name> }}cell-reference syntax with{{ __inputs__[name] }}. The decision text below reflects the original 0010 wording; the current spec is inevaluation.mdand the impl uses the renamed forms.
Context
A common pattern in operator workflows is "the same template every month, with one or two values that change per run": the report month, a region selector, an approval code, an exchange-rate threshold.
XTL 0.1 already supports _<name> user variables declared in the
_config sheet. Those values are static — they live inside the
template file and require an author to edit the workbook for each run.
For values that legitimately change per run, this forces operators to
either (a) keep editing _config, which defeats the "templates are
the handover artifact" property, or (b) maintain N copies of the
template, one per month.
There is no spec support today for a template to declare "I need
this value at runtime" so a host UI can ask the operator. The reference
implementation's convert() and preview() accept only the template
buffer and the source buffer.
This ADR closes that gap.
Considered Options
A. Status quo. Authors edit _config for every run, or maintain
template copies. Cost: contradicts the "approved template, file-based
handoff" identity.
B. Free-form runtime variables, no declaration. convert() accepts
an arbitrary inputs: Record<string, unknown> that is merged into the
expression context; the template references them via {{ _name }} and
missing values become empty per ADR-0007. Cost: no introspection — a
host UI cannot know what to ask for, what type to render, or whether a
value is required.
C. Declare in _config rows. Reuse the _config key/value sheet
with extended columns: column A is the key, column B the type, column
C the default, column D the label. Cost: _config is conventionally a
key/value table; adding parallel columns conflates two record shapes.
Verbose to declare more than two attributes.
D. Dedicated _inputs sheet. A reserved sheet name with a header
row and one row per input. Columns: name, type, default, label,
description. Cost: one more reserved sheet name, but consistent with
the existing reserved-sheet pattern (_config, list sheets).
E. Implicit inputs. Auto-detect any {{ _name }} reference that
does not resolve in _config as a runtime input. Cost: cannot carry
type, label, default, or required information; reduces every input to
free-form text.