Files
Aura/docs/design/contracts/c14-headless-two-faces.md
T
claude dc5f1742f4 fix(aura-cli, aura-runner): review findings — duplicate --override refusal, live discovery prose, neutral JSON refusal
In-cycle fixes for the independent review of the #319 package, RED-first
for both Importants. A repeated --override path now refuses at the shared
lexer (exit 2, path named) instead of panicking exit 101 through
reopen_all — which also un-misattributes the campaign leg's collision
prose for duplicates. override_paths' refusal points at aura graph
introspect --params (the retired --list-axes reference swept from every
live comment, one explicitly-historical mention remains). exec classifies
file targets through a Result-bearing peek: unparseable JSON refuses
neutrally before any leg is chosen. RunPresentation (single-variant)
removed; run_campaign_returning's contract note names its one deliberate
usage-class exit; C14's routing sentence and C20's family-builder
paragraph amended to current truth (superseded text to the history
sidecars); bench error strings and deletion blank-line runs tidied.

refs #319
2026-07-25 23:21:07 +02:00

113 lines
6.7 KiB
Markdown

# C14 — Headless core, two faces
**Guarantee.** The engine is a UI-agnostic library. Two faces sit on it: a
**programmatic/CLI** face (the primary surface for the LLM and automation —
author a node, run a sim/sweep, emit structured metrics) and a **visual** face
for human exploration. Visualization is only a downstream consumer node
([C8](c08-node-contract.md)) on the streams.
**Forbids.** Any UI/pixel knowledge inside the engine.
**Why.** The LLM drives programmatically, the human visually; a headless core
serves both. The visual face is the **playground** ([C22](c22-playground-traces.md)) —
a **web frontend served from disk-persisted traces** (#101, ratified 2026-06):
the engine writes recorded traces to disk and a browser charts them. It is
staged after the runnable substrate but is core to aura's identity, not
optional. Reading a serialized trace file is a stricter form of "no UI knowledge
in the engine" than an in-process native UI reaching zero-copy into the live SoA
columns — the pivot to the disk-trace frontend keeps this contract's core intact
and arguably tightens it.
## Current state
**The CLI conventions.** The programmatic/CLI face is a `clap` derive parser
(`aura-cli`, `crates/aura-cli/src/main.rs`) that meets GNU / clig.dev
conventions: one declarative source yields scoped `aura <sub> --help`,
`--version`/`-V`, per-flag Options sections, and GNU `--flag=value` / `--` /
long-option abbreviation. `clap` is admitted under the
[C16](c16-engine-project-split.md) per-case dependency policy — a
research-side, dev-loop/compile tax confined to `aura-cli`, a leaf binary the
frozen deploy artifact ([invariant 8](c13-hot-reload-frozen-deploy.md)) cannot
pick up. Usage lines follow the clap house style (`Usage: aura <verb> …`);
refusal diagnostics stay unprefixed, since a diagnostic is not a usage line.
**The stderr class markers (#278/#313).** Diagnostics on a *continuing* run
carry a stable class marker the exit code cannot supply: `aura: note: <text>`
for a benign, expected diagnostic — a gate-emptied cell, a skipped tap, an
all-zero-trade walk-forward — where the run stays valid and the exit code is
unaffected (a null result is a valid research result, #198); and
`aura: warning: <text>` for a recorded fault or suspect condition the run
survives — a failed cell feeding exit 3, a failed scaffold git step, a stale
hot-reload dylib. Error lines that accompany a non-zero exit — and plain
info lines such as the run-record summary — keep the bare `aura: ` prefix;
for errors, the exit-code partition below is the machine contract.
The markers are grep-stable: `grep '^aura: warning: '` isolates faults,
`grep '^aura: note: '` benign notices. The grammar's single source is
`aura-cli/src/diag.rs`; the few runner-side literals repeat it verbatim.
**The exit-code partition** is a durable part of the automation contract: a
caller branches on the failure class without parsing stderr.
- **0 — success.**
- **2 — usage error:** a command-line fault (clap parse errors + aura's
post-parse argument-structure validations, *including* the content of an
argv-named blueprint file, which is itself an argument).
- **1 — runtime failure:** a well-formed command whose needed environment /
recorded state is missing, or bad piped stdin data.
- **3 — campaign completed with failed cells:** a well-formed campaign that ran
to completion but with at least one failed cell (#272; `exit_on_campaign_result`
in `crates/aura-cli/src/main.rs`, threaded from the run registry —
[C18](c18-registry.md)).
**Single document grammar (#319, 2026-07-25).** The five dual-grammar
subcommands (run/sweep/walkforward/mc/generalize) that used to keep two
grammars under one token are retired; one verb, `exec <target>`, dispatches
on `is_blueprint_file` layered with a "kind"-field peek
(`classify_exec_document_file`): a first-positional naming an existing
`.json` file that parses as JSON and carries no top-level `"kind"` selects
the loaded-blueprint leg; a file carrying `"kind"`, or a target that is not a
readable `.json` file at all (a registered content id), selects the campaign
leg. A file that does not parse as JSON at all refuses neutrally (exit 2)
before either leg's own document-shape validation runs, rather than
silently choosing a leg (review Minor-3, 2026-07-25). The execution layer
this collapses onto is unchanged in kind (arg-plumbing via thin adapters).
The machine-first help surface (JSON/manifest help, stdin op-scripts) is
deferred to the #157 / [C21](c21-world.md) track, distinct from this
human/GNU-convention compliance.
**Two artifact classes, two redundancy budgets** (#249, ratified 2026-07-13).
The data layer the programmatic face emits is a public interface read raw (by
humans and LLMs), and its records split into two classes with opposite
redundancy budgets. **Generated outcome records** (manifests, metrics, family
reports) have a single writer at run time — redundancy there cannot drift and is
deliberately spent on direct readability. **Authored intent artifacts**
(blueprints, op-scripts, campaign documents) are author-maintained — every
redundancy is a drift site and stays out. Consequence in the run manifest
(`RunManifest`, `crates/aura-engine/src/report.rs`): the untouched bound
`defaults` are stamped one-directionally beside `params` (which keeps its "what
varied" reproduce semantics, disjoint by construction from `defaults`, "what was
held"), so a raw reader of a fully-bound run no longer sees a misleading
`"params": []`; the blueprint itself carries no such duplication.
**The programmatic face is an executor** (#295, ratified 2026-07-20). The
member-run recipe — the definition of what a standard aura backtest is — is
library content (`aura-runner` / `aura-backtest` / `aura-measurement`,
[C28](c28-stratification.md) assembly position), not CLI content: the binary is
argv → document → executor → presentation, and a downstream World program
reaches the same recipe with no binary involved. See
[C25](c25-role-model.md)'s control-surface amendment for the projection rule.
## See also
- [C8](c08-node-contract.md) — visualization is a downstream sink/consumer node
- [C16](c16-engine-project-split.md) — the per-case dependency policy under
which `clap` is admitted
- [C18](c18-registry.md) — the run registry that yields the exit-3
completed-with-failures class
- [C21](c21-world.md) — the #157 machine-first help track (deferred)
- [C22](c22-playground-traces.md) — the visual face / playground
- [C25](c25-role-model.md) — the control-surface amendment (executor projection)
- [C28](c28-stratification.md) — the assembly position of the member-run recipe
> History: [c14-headless-two-faces.history.md](c14-headless-two-faces.history.md)