ef24f06547
Harvest sweep, whole-diff review fix block. The review refuted the #343 ratification's factual premise: the campaign leg does NOT mint a reopened member's hash — runner.rs passes the stored strategy_id as topo even for reopened members (reference semantics). Decision revised on the issue (fix, not ratify): exec's override run now stamps the LOADED base document's content id (computed before reopen_all; RED-first — the inverted pin failed on the old reopened-hash behaviour), keeping topology_hash store-resolvable and identical in meaning across both legs; the variation lives in manifest.params. C24/C12/C18 rewritten to the corrected reading. Also per review: C24's retired build-free-introspection sentence updated (old wording archived in the history sidecar, #339 item 4); C14's partition key precisely scoped to the routing seam, naming the legs' differing content-validation exits honestly; measure.rs's false unreachability comment corrected; --taps added to the guide's introspect cheat-sheet and pinned on the content-id path; the zero-trade-cell note routed through the diag macro; doc-comment, issue-ref, and gate-name corrections; the Fixed-regime NaN branch pinned. refs #339 refs #342 refs #343
152 lines
9.3 KiB
Markdown
152 lines
9.3 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.
|
|
|
|
**`exec`'s target-classification exit partition is pinned, precisely scoped
|
|
(#342 item 5).** The partition below governs exec's TARGET-CLASSIFICATION
|
|
refusals at the routing seam — the shape-peek (`classify_exec_document_file`)
|
|
that decides which leg, if any, a target reaches, strictly before either
|
|
leg's own document-shape validation ever runs. A target fault at this seam
|
|
splits along the same usage/runtime line the exit-code partition above
|
|
already draws, keyed on whether a *real, existing document's content* is
|
|
being judged (usage, exit 2 — the content of an argv-named file is itself
|
|
part of the argument) or the target simply fails to resolve to any recorded
|
|
state at all (runtime, exit 1 — the needed environment/recorded state is
|
|
missing). Missing-state faults (exit 1): a target naming no readable file and
|
|
no plausible content id (`'{target}' is neither a readable .json file nor a
|
|
64-hex content id`), and a well-formed-but-unregistered 64-hex content id
|
|
(`no campaign {id} in the project store`) — no file or store entry exists to
|
|
have content in either case. File-content faults at the routing seam (exit
|
|
2): a file that does not parse as JSON at all, a valid-JSON op-script array
|
|
(not a document exec can execute at all — it names the `graph build`
|
|
escalation instead), and a kind-bearing document whose `"kind"` is not
|
|
`"campaign"` (e.g. a process document handed to `exec`) — all three are a
|
|
real, readable file whose content the ROUTING seam itself cannot classify
|
|
into a leg. The wrong-kind case is the one realignment this pin made (#342
|
|
item 5): it shipped at exit 1 (mirroring the campaign leg's own missing-state
|
|
refusals) until this pass, despite being a routing-seam content fault like
|
|
its op-script and not-valid-JSON siblings, not a missing-state fault like the
|
|
file-vs-id cases — realigned to exit 2 to match its true class, the one
|
|
sanctioned behaviour change of this pin.
|
|
|
|
Once a target classifies as campaign or blueprint, it falls under that leg's
|
|
**own** established validation partition, not this one — and the two legs'
|
|
content-validation exits differ today, named honestly rather than harmonized:
|
|
a `kind:"campaign"` document whose *content* then fails the campaign
|
|
doc-tier gate (e.g. an empty axis) exits 1, runtime-class, per the
|
|
established campaign contract (pinned by
|
|
`campaign_run_invalid_file_refuses_before_touching_store`), while the
|
|
blueprint leg's own content faults (a blueprint envelope that fails to parse
|
|
or build) exit 2, usage-class. No behaviour changes here — only this pin's
|
|
scope is named precisely: it is the routing seam's partition, not a
|
|
uniform content-validation rule across both legs.
|
|
|
|
**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)
|