32eb5a6a9e
Source-blind consumer run over the four cycle axes on the release
binary at 4ff85b9: the authoring loop lands the name in bytes, store
document, and traces/<name>/ (with the documented default collision
observable on the unnamed twin); the refusal battery is uniform and
op-indexed across the op route and the file intakes; a named blueprint
defaults its use-splice instance identifier as documented, two unnamed
splices collide, two named ones coexist; help/guide/glossary agree on
eleven ops and the render-name vs registry-label split. Finding B1
(sweep --list-axes ungated, mangled listing at exit 0) is fixed
RED-first in the preceding commit; SG1 (prefix variance in the refusal
prose) is ratified there in C24.
refs #331
185 lines
8.2 KiB
Markdown
185 lines
8.2 KiB
Markdown
# Fieldtest transcript — cycle #331 (blueprint name op)
|
|
|
|
Source-blind consumer field test of the eleventh op-script op
|
|
`{"op":"name","name":"<name>"}` — the composite render name that flows to store
|
|
documents, `traces/<name>/`, and `use`-splice instance defaults, gated by a
|
|
deterministic shape check at every authored intake.
|
|
|
|
Binary: `target/release/aura`, built from HEAD `4ff85b9` via
|
|
`cargo build --release -p aura-cli` (Finished in 5.48s — HEAD builds clean).
|
|
Scratch project `aura new nm_lab` in `/tmp/ftwork/nm_lab`; real data from the
|
|
built-in archive (US500). Public interface only (README, authoring-guide,
|
|
glossary, design ledger C23/C24/C29, `aura … --help`) — no crate source read.
|
|
|
|
---
|
|
|
|
## Example 1 — authoring loop end to end (`c331_1_named_crossover.ops.json`)
|
|
|
|
A named SMA-crossover with a `spread` tap, all knobs bound (closed → runnable).
|
|
|
|
```
|
|
$ aura graph build < c331_1_named_crossover.ops.json > c331_1_named_crossover.bp.json # exit 0
|
|
# blueprint.name == "ny_momentum", taps == [{"name":"spread",...}]
|
|
$ aura graph register c331_1_named_crossover.bp.json
|
|
registered blueprint 347a361997e8a65d4122b5ab50367031f78df24a1ff6ad14477ed2c04ec3b603 (…)
|
|
# store doc runs/blueprints/347a…json -> name: ny_momentum
|
|
$ aura run c331_1_named_crossover.bp.json --real US500 --tap spread=mean # exit 0
|
|
$ find runs/traces
|
|
runs/traces/ny_momentum
|
|
runs/traces/ny_momentum/index.json
|
|
runs/traces/ny_momentum/spread.json
|
|
```
|
|
|
|
The authored name `ny_momentum` shows up in all three documented places — the
|
|
blueprint bytes, the store document's `name`, and the run's trace directory
|
|
`traces/ny_momentum/`. (Finding W1.)
|
|
|
|
### Default collision story (omitting the name)
|
|
|
|
Two *different* unnamed crossovers (A: fast=3/slow=8, B: fast=5/slow=20), both
|
|
build to `name: "graph"`, both `--tap spread=record` over US500:
|
|
|
|
```
|
|
$ aura run c331_1b_unnamed_A.bp.json --real US500 --tap spread=record # exit 0
|
|
sha256(runs/traces/graph/spread.json) = 5bb5dcfc…
|
|
$ aura run c331_1c_unnamed_B.bp.json --real US500 --tap spread=record # exit 0
|
|
sha256(runs/traces/graph/spread.json) = 3be8025b… ← overwritten, silently
|
|
$ ls runs/traces/ → graph ny_momentum
|
|
```
|
|
|
|
Both unnamed strategies share `traces/graph/`; B silently overwrote A's
|
|
`spread.json` (differing sha). This is exactly the documented "later runs
|
|
overwrite earlier ones" consequence — observable, no warning (as documented).
|
|
(Finding W1.)
|
|
|
|
---
|
|
|
|
## Example 2 — refusal battery (`c331_2*`)
|
|
|
|
### Op route (op-indexed prose)
|
|
|
|
```
|
|
$ aura graph build < c331_2a_dup_name.ops.json # exit 1
|
|
aura: op 1 (name): a script names its blueprint at most once
|
|
$ aura graph build < c331_2b_slash_name.ops.json # exit 1
|
|
aura: op 0 (name): blueprint name "traces/evil" is invalid: must not contain '/' or '\' (a single path segment)
|
|
$ aura graph build < c331_2c_empty_name.ops.json # exit 1
|
|
aura: op 0 (name): blueprint name "" is invalid: must be non-empty (a single path segment)
|
|
$ aura graph build < c331_2d_dotdot_name.ops.json # exit 1
|
|
aura: op 0 (name): blueprint name ".." is invalid: must not be "." or ".." (a single path segment)
|
|
```
|
|
|
|
Each refusal is op-indexed, quotes the offending name, and states the exact
|
|
rule. Copy-paste fixable. (Finding W2.)
|
|
|
|
### Hand-edited envelope with a bad root name (`../escape`)
|
|
|
|
`c331_2e_open_named.bp.json` (clean name `clean_name`, `fast.length` open),
|
|
root `name` hand-edited to `../escape` → `c331_2e_badroot.bp.json`, fed to
|
|
every file intake:
|
|
|
|
```
|
|
$ aura graph register c331_2e_badroot.bp.json # exit 1 GATED
|
|
aura: blueprint name "../escape" is invalid: must not contain '/' or '\' (a single path segment)
|
|
$ aura run c331_2e_badroot.bp.json --real US500 # exit 2 GATED
|
|
aura: …/c331_2e_badroot.bp.json: blueprint name "../escape" is invalid: …
|
|
$ aura sweep c331_2e_badroot.bp.json --axis fast.length=2,4 # exit 2 GATED
|
|
aura: blueprint name "../escape" is invalid: …
|
|
$ aura graph introspect --content-id c331_2e_badroot.bp.json # exit 1 GATED
|
|
$ aura graph introspect --params c331_2e_badroot.bp.json # exit 1 GATED
|
|
$ aura graph c331_2e_badroot.bp.json # exit 2 GATED
|
|
aura: …/c331_2e_badroot.bp.json: blueprint name "../escape" is invalid: …
|
|
|
|
$ aura sweep c331_2e_badroot.bp.json --list-axes # exit 0 *** NOT GATED ***
|
|
./escape.fast.length:I64
|
|
slow.length:I64 default=8
|
|
bias.scale:F64 default=0.5
|
|
```
|
|
|
|
Six of seven file intakes gate uniformly (Finding W2). **`sweep --list-axes`
|
|
does not** — it exits 0 and prints a mangled, retired *wrapped* axis form
|
|
`./escape.fast.length` for the open param only. The same on a `.` root:
|
|
`sweep --list-axes` → `.fast.length:I64` (exit 0) while `register`/`--params`
|
|
refuse. Pasting the leaked `./escape.fast.length` back as `--axis` refuses —
|
|
so discovery emits a name the bind surface rejects. (Finding B1.)
|
|
|
|
Prose note: `run` and `graph` prepend the full file path; `register`,
|
|
`sweep --axis`, `introspect` do not — the core sentence is uniform, the prefix
|
|
is not. (Finding SG1.)
|
|
|
|
---
|
|
|
|
## Example 3 — use-splice interplay (`c331_3*`)
|
|
|
|
Registered patterns: `agree` (input `x`, SMA length open), `refute` (input `y`),
|
|
`unnamedsm` (unnamed → `graph`, input `z`).
|
|
|
|
```
|
|
# A — splice agree, NO instance name:
|
|
$ aura graph build < c331_3A_splice_named.ops.json # exit 0
|
|
aura: note: use "agree": agree -> 4f78a9f6e1f3…
|
|
$ aura graph introspect --params c331_3A.bp.json
|
|
agree.sma.length:I64 ← instance defaulted to authored name
|
|
|
|
# B — splice unnamedsm TWICE, no instance names:
|
|
$ aura graph build < c331_3B_two_unnamed.ops.json # exit 1
|
|
aura: note: use "graph": unnamedsm -> 25cdd4942f21…
|
|
aura: note: use "graph": unnamedsm -> 25cdd4942f21…
|
|
aura: op 3 (use): duplicate identifier "graph" ← collide, op-indexed
|
|
|
|
# C — splice agree + refute, no instance names:
|
|
$ aura graph build < c331_3C_two_named.ops.json # exit 0
|
|
$ aura graph introspect --params c331_3C.bp.json
|
|
agree.sma.length:I64
|
|
refute.sma.length:I64 ← distinct names, no collision
|
|
```
|
|
|
|
Instance identifier defaults to the authored render name; two unnamed
|
|
(`graph`) splices collide with an op-indexed `duplicate identifier "graph"`;
|
|
distinct authored names dissolve the collision. Matches guide + glossary
|
|
`blueprint label` entry exactly. (Finding W3.)
|
|
|
|
---
|
|
|
|
## Example 4 — discovery / docs parity (`c331_4_*`)
|
|
|
|
`aura graph build --help` lists the name op last of the eleven:
|
|
|
|
```
|
|
{"op":"name","name":"ny_momentum"}
|
|
set the composite's render name, at most once per script (default
|
|
"graph" if omitted)
|
|
```
|
|
|
|
Consistent with the authoring guide's eleven-ops table (§1). Three distinct
|
|
`--name`-ish concepts, each with distinct help phrasing:
|
|
|
|
- op `name` → **render name** (keys `traces/<name>/`, use-splice instance default)
|
|
- `aura graph register --name` → **registry label** ("Label the registered
|
|
content id for `use` by name (#317)")
|
|
- `aura sweep --name` → **family name** ("Family name (records to the registry…)")
|
|
|
|
The glossary `blueprint label` entry separates render name from registry label
|
|
explicitly. Distinction is learnable from the public docs alone, though a
|
|
consumer must consult the glossary to fully disambiguate the three. (Finding W4.)
|
|
|
|
---
|
|
|
|
## Findings summary
|
|
|
|
- W1 (working, axis 1): authored name → blueprint bytes + store doc +
|
|
`traces/<name>/`; default `graph` collision observable (silent overwrite).
|
|
- W2 (working, axis 2): op-route refusals op-indexed + specific; hand-edited
|
|
bad root name gated uniformly on 6 of 7 file intakes.
|
|
- W3 (working, axis 3): use-splice instance defaults to authored name; unnamed
|
|
splices collide (op-indexed); named splices coexist.
|
|
- W4 (working, axis 4): `graph build --help` lists the name op consistently
|
|
with the guide; render-name vs registry-label distinction learnable.
|
|
- B1 (BUG, axis 2): `sweep --list-axes` does not gate a bad root name (exit 0)
|
|
and leaks a retired, non-bindable wrapped axis form (`./escape.fast.length`),
|
|
breaking #328's `--params`/`--list-axes` line-identity and the
|
|
every-discovered-name-is-verbatim-legal promise.
|
|
- SG1 (spec_gap, axis 2): "uniform refusal prose" — `run`/`graph` prepend the
|
|
file path, other seams don't; unclear whether "uniform" means the core
|
|
sentence or byte-identical.
|