# Fieldtest — cycle 0106 — research-artifact document surface — 2026-07-03

**Role:** downstream consumer (methodology designer / campaign designer), public
interface only (ledger C18/C20/C22/C25, glossary, CLI help + introspection, the
fieldtests corpus shape). No `crates/` source read. Binary built from HEAD;
referential tier exercised after `cargo build` in the scaffolded `demo_project/`.

## Fixtures (this directory)

- `c0106_1_attempt1..3.json`, `c0106_1_partial.json`, `c0106_1_reformatted.json`
  — process doc: 3-round envelope discovery + canonicalization + empty-gate probe
- `c0106_2_strategy.json` — SMA-cross op-script (content id `573262…`)
- `c0106_2_campaign_attempt1..2.json`, `c0106_2_campaign_valid.json`,
  `c0106_2_campaign_partial.json`, `c0106_2_probe_{barestring,refnull,noref,prefixed}.json`
- `c0106_4_{emptyaxis,floatinint,noinstr,backwardwin,badmetric,badcmp,process_identity}.json`
- `demo_project/` — `aura new` scaffold + campaign/process docs + in-project store
- `runs/{processes,campaigns}/…` — content-addressed store written by `register`

## Findings

### F2 [bug] `introspect --block std::process_ref` advertises `identity_id`, which the validator refuses
The slot line prints `ref  required, one of { content_id } | { identity_id }`
while validation refuses an identity_id process ref (`process.ref: a process is
referenced by content id in this version`, exit 1); the block header itself says
"(content id)". The 0106 audit fixed the parallel `--unwired` hint but not this
`--block` describe. Repro: `aura campaign introspect --block std::process_ref`.
→ debug (RED-pin content-id-only).

### F1 [friction] Document envelope not derivable from the introspection contract
Process doc took 3 blind rounds (`stages` → wrong-kind refusal that does not
name the `kind` key → `unknown field stages, expected one of … pipeline`).
Campaign worse: block ids `std::data/std::strategy/std::process_ref/std::presentation`
map to fields `data`/`strategies` (plural)/`process`/`presentation`, and the
required `seed` appears in NO block (`missing field seed`). Introspection
describes block slots but never the envelope composing them.
→ plan (envelope/skeleton introspection; reconcile block ids with field names).

### F3 [friction] content-id printed `content:`-prefixed, refs need the bare hash — silent referential break
`process|campaign introspect --content-id` print `content:<hash>`; `graph
introspect --content-id` prints bare. Pasting the prefixed form into a ref
PASSES intrinsic validation (different id!) then fails referential resolution
without the error naming the prefix as the cause.
→ plan (one display form across verbs; accept/strip the prefix in refs).

### F4 [friction] `--unwired` open-slot hints fire only when a ref is omitted, which `validate` fails
The ref open-slot hints appear only with the `ref` key removed (then validate
says `missing field ref`); placeholders `{}` / `null` give cryptic serde errors
(`expected map with a single key`; `invalid type: null, expected string or map`)
and `--unwired` reports `no open slots`. One draft file cannot both
validate-so-far and report its open slots.
→ plan (treat `ref: {}`/`null` as the reported open slot).

### F5 [friction] A campaign's strategy ref cannot be driven to resolve from the public surface
No verb computes a blueprint FILE's content id (`graph introspect --content-id`
is op-list-only), no verb registers a standalone blueprint into the store (only
sweep/mc/walkforward populate it), no verb lists a strategy's `param_space`
(axis names/kinds undiscoverable). The ref stays unresolved unless a sweep
already ran — but the sweep is what the campaign describes (see F7).
→ planner (blueprint register + file content-id + param-space listing; scope
with the executor).

### F6 [doc-gap] No worked document example anywhere; `metric_vocabulary` unlisted by any verb
Zero process/campaign JSON examples in docs/ or the corpus at test time. Block
hints say "metric name (see metric_vocabulary)" but no verb lists it, and
`unknown metric` does not enumerate valid names.
→ tighten docs (worked example per type; metric enumeration via introspect or
in the refusal).

### F7 [spec_gap] No executor — a valid campaign has no run path (the pending executor decision)
After registering a campaign whose process declares sweep → gate → walk_forward
over a strategy + 9-point axis, the expected `aura campaign run <id>` does not
exist; `aura run`/`sweep` take no campaign. The campaign+process pair is a
complete declarative spec of machinery the engine already runs
(sweep_family / optimize_deflated / walkforward_family); what exists is
persisted, content-addressed, legible intent that nothing consumes. The trail
ends at `runs/campaigns/<hash>.json`.
→ this run IS the intent-persistence re-test the executor decision waited on;
scope the executor.

### F8 [working] Content-id canonicalization is exact and stable
Reordered keys + reflowed whitespace + `0` vs `0.0` yield the identical content
id; stored form is compact, declared-key-order, no trailing newline, and
re-derives its id. → carry-on.

### F9 [working] Intrinsic validation is thorough, path-addressed, house-style
Empty gate, unknown metric/cmp, empty axis, float-in-I64, empty instruments,
backwards window, invalid-doc content-id refusal — all precise prose, exit
codes usage=2 / invalid=1 / ok=0. Minor: the kind-mismatch error omits the axis
path its siblings carry. → carry-on.

### F10 [working] Referential tier correct across the project boundary
Outside: skip line names the search root. Inside without dylib: actionable
build hint. Inside built: per-store diagnostics, progressive resolution as
documents get registered. → carry-on.

## Verdict

The shipped surface delivers standalone value: methodology and experiment
intent are nameable, diffable (byte-exact content id surviving reformatting),
and auditable (content-addressed, referentially checkable, honest
diagnostics) — with no compile and no run. The shortfall concentrates in the
authoring on-ramp (envelope invisible to introspection, no worked example, the
`content:`-vs-bare id trap) and the terminal wall: the campaign+process pair
fully specifies a sweep→gate→walk-forward the engine already runs, yet nothing
consumes it. The single most valuable next capability is an executor
(`aura campaign run <id>` driving the existing family machinery) — the one
addition that turns persisted intent into a result and retroactively gives
every id, store, axis, and gate its reason to exist.

Counts: bug 1 (F2), friction 4 (F1/F3/F4/F5), doc-gap 1 (F6), spec-gap 1 (F7),
working 3 (F8/F9/F10).
