Repository navigation
The variables family: --variable NAME=value, <PREFIX>_VARIABLE_<NAME> and <program>.variable, read only by the variable resolver #1023
Description
The runtime variable space has no surface of its own. Variables are declared by reference (plan.variable(...)),
gathered from a graph's nodes, and bound when a run starts by pkg/op's VariableResolver, but nothing lets a user
introduce one. The resolver makes up for it by reading settings: the flag map, the configuration map, and the
environment under the program's prefix plus the bare name. Two bugs are this gap seen from either end: writ's template
variables come only from the configuration file (#975), and a template's Env reads the process environment (#683).
Ruled 2026-10-02
The owner, planning lane 8 of #916 (#927):
- "settings are different than variables in the context of a RuntimeEnvironment. variables are declared by reference
and bound at execution time. settings are orthogonal." - "Until we have specific use cases with a syntax for introducing settings (as i've now defined settings) they will
not be entered into the runtime variable space. Bindings are entered into the runtime variable space using a syntax
similar to what make uses." - "this seems like a big hole that was meant to be filled exclusively by the VariableResolver. It is the logical
place. the VariableResolver needs access to settings. it's domain is the variable space. It should not need to do
more than resolve the set of variables defined by the current application. ... I propose --variable NAME=value. And
we must be sensitive to the fact that these things may represent complex types; any types that can be serialized:
primitives and structs. anything that might be passed to a provider method." - The family is named as segments are (
--segment,WRIT_SEGMENT_<NAME>,writ.segments):--variable NAME=value,
<PREFIX>_VARIABLE_<NAME>and<program>.variables. Ruled "yes". - No file form for a long value until a use case asks for one: a string on the command line and in the environment,
JSON for a structure, YAML in the file. Ruled "(a)". - "our shipping apps (lore, star, and writ) and devlore-test are the apps that should carry variables. none other."
- The work splits, ruled "(c)": lane 8 (The environment prefix is doubled: WRIT_WRIT_VERBOSE works and WRIT_VERBOSE does not; the variable is the prefix plus the bare key, for every program #927, PR C) moves the resolver's environment lookup to
<PREFIX>_VARIABLE_<NAME>and drops its lookups of settings; this feature adds the surfaces.
Amended 2026-10-02: the file key is singular,
<program>.variable. Asked whether scopes, segments and variables should take singular or plural keys, the owner: "yes, singular for all three":writ.scope,writ.segment(#1024) and<program>.variable. Under #927's rule,writ.variable.<NAME>readsWRIT_VARIABLE_<NAME>: the file key and the environment variable are one setting chain.
Acceptance
-
--variable NAME=value, repeatable, on lore, star, writ and devlore-test, the programs on the shared root, and
on no other program. - The variable resolver is the family's only reader. It binds the variables a graph references from the family's
three layers (the flag, then<PREFIX>_VARIABLE_<NAME>, then<program>.variablein the configuration file),
beneath values the run's caller supplies and above declared defaults. It reads no other setting. - A value reaches its slot as anything a provider method takes. A string from the command line or the environment
decodes throughenvValue(primitives, durations, file modes,TextUnmarshaler, then JSON), and every value then
projects throughop.Convert(structs by theirjsonoryamltags, slices, maps, registered resources). -
<program>.variablereplaceswrit.vars; writ's templates read their variables from the variable space, and
names keep their case (writ's template variables come only from the configuration file: writ.vars is read as a whole map, which the environment never reaches, and no flag sets one #975). - A template's
Envreads the variable space, not the process environment, and its name is settled (template.render_text reads the ambient environment instead of declared runtime variables #683). - devlore-test's fixtures set variables through the family.
-
configuration.md§ Variables,10-command-line-interface.md,2.1-typed-slots.md,
2.5-lifecycle-pipeline-construction.mdand the templates guide describe the family.
Schedule
#916 lane 38, PR C′, after lane 22 (#1009, the one configuration file), lane 24 (#1010, the shared root's flags as
global settings, from which --variable is the exception), and lane 8's part in PR C. #975 and #683 are lanes 39 and
40, done in lane 38, and #1024 (writ.scope and writ.segment) is lane 41, done in lane 38 too.
Plan and design documents
| Kind | Document |
|---|---|
| Plan | Not yet opened: written when lane 38 opens, in PR C′'s worktree |
| Design | docs/architecture/configuration.md § Variables — supplemental |
Epic: #441
Activity
fix(cli): a setting's variable is the prefix plus the bare key; lane …
test(cli): no two settings share an environment variable, and none li…
[-]The variables family: --variable NAME=value, <PREFIX>_VARIABLE_<NAME> and <program>.variables, read only by the variable resolver[/-][+]The variables family: --variable NAME=value, <PREFIX>_VARIABLE_<NAME> and <program>.variable, read only by the variable resolver[/+]docs: settings and variables are orthogonal, and the name-keyed famil…