rototo 0.1.0-alpha.2

Control plane for runtime configuration in application code.
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
# Variable File Reference

A variable is the application-facing configuration contract. Application code
resolves a variable id in an environment with runtime context, and rototo
returns the selected value key and value.

This page specifies the variable file format and the related external value
file format.

## Location and ID

Variable files live under the workspace `variables/` directory:

```text
variables/<variable-id>.toml
```

The file stem is the variable id. For example:

```text
variables/llm-agent-config.toml -> llm-agent-config
variables/max-output-tokens.toml -> max-output-tokens
```

Variable ids are the names applications resolve. Keep them stable once
application code depends on them.

## Minimal Shape

Every variable file uses `schema_version = 1` and a `[variable]` table:

```toml
schema_version = 1

[variable]
description = "Maximum number of tokens the summarizer can emit"
type = "int"

[variable.values]
small = 500
standard = 1000
large = 2000

[variable.env._]
value = "standard"

[variable.env.dev]
value = "small"

[variable.env.prod]
value = "large"
```

The `_` environment is required. It is the fallback used when a variable does
not define a block for the requested environment.

## `schema_version`

Required. Must be:

```toml
schema_version = 1
```

Files without a supported schema version fail lint.

## `[variable]`

Required. Contains the variable metadata and contract.

### `description`

Optional but recommended. Use it to explain what application-facing behavior the
variable controls.

```toml
[variable]
description = "LLM settings for the incident summary agent"
type = "string"
```

### `type`

Declares a primitive value type. A variable must declare exactly one of `type`
or `schema`.

Supported primitive types:

```text
bool
int
number
string
list
```

Primitive values are checked during lint. A variable with `type = "int"` fails
lint if any configured value is not an integer.

### `schema`

Declares a JSON Schema file for structured values. A variable must declare
exactly one of `type` or `schema`.

```toml
[variable]
description = "LLM settings for the incident summary agent"
schema = "../schemas/llm-config.schema.json"
```

The schema path is resolved relative to the variable file. Each configured value
is validated against the schema during lint.

### `[variable.lint]`

Optional. Declares variable-scoped custom Lua lint.

```toml
[variable.lint]
path = "../lint/llm-agent-config.lua"
```

The path is resolved relative to the variable file. The Lua script can define
`lint(variable)`, `lint_value(value)`, or both.

`lint(variable)` receives the expanded variable, including inline and external
values:

```lua
function lint(variable)
  return {}
end
```

`lint_value(value)` runs once for each expanded value:

```lua
function lint_value(value)
  if value.value.max_output_tokens > 5000 then
    return {
      {
        message = "value " .. value.name .. " exceeds the token budget",
        help = "Use 5000 or fewer output tokens."
      }
    }
  end
  return {}
end
```

Each function must return a list of diagnostics. A diagnostic must contain
`message` and may contain `help`.

Custom lint is declared on variables today. Workspace-level and qualifier-level
custom lint are not separate extension points.

## Values

A variable must define at least one value. Values can be inline in the variable
file, external in a sibling `*-values/` directory, or both.

Value keys are names used by environment mappings and rules. They are also
returned in resolution output as `value_key`.

### Inline Primitive Values

Use `[variable.values]` for primitive values:

```toml
[variable.values]
small = 500
standard = 1000
large = 2000
```

### Inline Object Values

Use nested tables for object values:

```toml
[variable.values.standard]
model = "gpt-5-mini"
gateway = "openai"
max_output_tokens = 2400
temperature = 0.3

[variable.values.enterprise]
model = "gpt-5"
gateway = "openai"
max_output_tokens = 5000
temperature = 0.2
```

## External Value Files

External value files keep large or structured values separate from the variable
selection logic.

For this variable:

```text
variables/llm-agent-config.toml
```

rototo also loads TOML files from:

```text
variables/llm-agent-config-values/*.toml
```

Each external value file stem is the value key:

```text
variables/
  llm-agent-config.toml
  llm-agent-config-values/
    standard.toml     -> standard
    enterprise.toml   -> enterprise
```

External values are merged into `[variable.values]` before lint, custom lint,
and resolution. If the same value key is declared inline and externally, loading
fails.

### Scalar External Values

If an external value file contains a single top-level `value` key, rototo uses
the contents of that key as the value:

```toml
value = "Welcome back, premium member."
```

The selected value is the string:

```json
"Welcome back, premium member."
```

### Object External Values

Use `[value]` for object values:

```toml
[value]
model = "gpt-5"
gateway = "openai"
prompt = "Summarize the incident for an enterprise support workflow."
max_output_tokens = 5000
temperature = 0.2
```

The selected value is the object under `value`.

If an external value TOML file does not consist of a single top-level `value`
key, rototo uses the whole TOML document as the value.

## Environment Mappings

Variable environment blocks live under `[variable.env]`.

The fallback block is required:

```toml
[variable.env._]
value = "standard"
```

Named environment blocks are optional:

```toml
[variable.env.dev]
value = "small"

[variable.env.prod]
value = "large"
```

Environment names other than `_` must be declared in the workspace manifest
under `[environments].values`.

When resolving a variable, rototo first looks for a block matching the requested
environment. If there is no matching block, it uses `[variable.env._]`.

Each environment block must contain:

```toml
value = "<value-key>"
```

The value key must exist in the expanded values table.

## Rules

Rules let an environment block select a value by qualifier.

```toml
[variable.env.prod]
value = "standard"

[[variable.env.prod.rule]]
description = "Enterprise accounts get the larger agent configuration"
qualifier = "enterprise-accounts"
value = "enterprise"
```

Each rule contains:

- `description`: optional but recommended.
- `qualifier`: required. Must reference an existing qualifier id.
- `value`: required. Must reference an existing value key.

Rules are evaluated in the order they appear. The first matching rule selects
its value. If no rule matches, rototo uses the environment block's `value`.

Rules are only evaluated for the selected environment block. If the requested
environment has no block and rototo falls back to `_`, only rules in `_` are
considered.

## Resolution Output

Variable resolution returns:

```json
{
  "id": "llm-agent-config",
  "environment": "prod",
  "value_key": "enterprise",
  "value": {
    "model": "gpt-5",
    "gateway": "openai",
    "max_output_tokens": 5000,
    "temperature": 0.2
  }
}
```

The `environment` field is the environment requested by the caller. The
`value_key` field is the selected branch. The `value` field is the configured
value after inline and external value files have been expanded.

CLI JSON output also includes the workspace source/path.

## Validation

Variable lint checks:

- `schema_version = 1` exists.
- `[variable]` exists.
- Exactly one of `type` or `schema` is declared.
- `[variable.lint]`, when present, is a table with `path`.
- Values exist after external value files are loaded.
- Primitive values match `type`.
- Schema-backed values match the referenced JSON Schema.
- `[variable.env._]` exists.
- Environment blocks are tables with `value`.
- Named environments are declared in the workspace manifest.
- Environment `value` references point at known value keys.
- Rule `qualifier` references point at known qualifier ids.
- Rule `value` references point at known value keys.
- Custom lint returns no diagnostics.

Context schema validation happens during resolution, before qualifiers and rules
are evaluated. Value type and value schema checks happen during lint, before the
workspace is used.

## Complete Examples

### Primitive Inline Variable

```toml
schema_version = 1

[variable]
description = "Maximum number of tokens the summarizer can emit"
type = "int"

[variable.values]
small = 500
standard = 1000
large = 2000

[variable.env._]
value = "standard"

[variable.env.dev]
value = "small"

[variable.env.prod]
value = "large"
```

### Schema-Backed Variable With External Values

```toml
schema_version = 1

[variable]
description = "LLM settings for the incident summary agent"
schema = "../schemas/llm-config.schema.json"

[variable.lint]
path = "../lint/llm-agent-config.lua"

[variable.env._]
value = "standard"

[variable.env.prod]
value = "standard"

[[variable.env.prod.rule]]
description = "Enterprise accounts get the larger agent configuration"
qualifier = "enterprise-accounts"
value = "enterprise"
```

With value files:

```text
variables/
  llm-agent-config.toml
  llm-agent-config-values/
    standard.toml
    enterprise.toml
```

`variables/llm-agent-config-values/enterprise.toml`:

```toml
[value]
model = "gpt-5"
gateway = "openai"
prompt = "Summarize the incident for an enterprise support workflow."
max_output_tokens = 5000
temperature = 0.2
```