From 96e79184e095d7d8f7f13f9b5f0aafca1dfc163c Mon Sep 17 00:00:00 2001 From: claude Date: Thu, 23 Jul 2026 20:58:19 +0200 Subject: [PATCH] fix(docs, registry): fieldtest follow-ups -- guide sync, doc-op documentation, surface-neutral refusal Three of the four immediate fieldtest findings for the self-description cycle: - authoring-guide S0: the worked Scale literal gains the required NodeSchema.doc line (+ the C29 comment) -- the shipped example was a hard E0063 for anyone pasting it (the exact #314 teaching-failure class, caught from the consumer seat). - The op table becomes "The nine ops": the C29 doc op is documented with its JSON shape, the register requirement, the at-most-once rule and the gate; the README op-kinds list names it too. The fieldtester had to guess the shape from commit bodies -- now it is on the public surface. - The store-gate refusal's fix hint is surface-neutral: builder .doc(...), blueprint "doc" member, or op-script {"op":"doc"} -- previously it prescribed the Rust builder to a JSON author. Gates: registry, graph_construct (63) and project_load (14) suites green; refusal-prose pins unchanged (pinned substrings untouched). refs #316 --- README.md | 5 +++-- crates/aura-registry/src/lib.rs | 4 +++- docs/authoring-guide.md | 6 +++++- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 8944670..35a385e 100644 --- a/README.md +++ b/README.md @@ -119,8 +119,9 @@ aura sweep crossover.bp.json --list-axes ``` The op kinds are `source`, `input`, `add`, `feed`, `connect`, `expose`, `tap`, -and `gang` (`tap` declares a recorded measurement point on an interior wire — -see the authoring guide). See +`gang`, and `doc` (`tap` declares a recorded measurement point on an interior +wire; `doc` declares the composite's one-line meaning, required at register — +C29; see the authoring guide). See `aura graph introspect --node ` for a type's exact ports and the op-script grammar in the design ledger for the full semantics. diff --git a/crates/aura-registry/src/lib.rs b/crates/aura-registry/src/lib.rs index 76d38e8..6fa1562 100644 --- a/crates/aura-registry/src/lib.rs +++ b/crates/aura-registry/src/lib.rs @@ -968,7 +968,9 @@ impl fmt::Display for RegistryError { aura_core::DocGateFault::Empty => write!( f, "blueprint: composite `{name}` carries no doc — a registered \ - composite describes itself (C29); set .doc(\"...\") before register" + composite describes itself (C29); add a doc line (builder \ + .doc(\"...\"), blueprint \"doc\" member, or op-script \ + {{\"op\":\"doc\"}}) before register" ), aura_core::DocGateFault::RestatesName => write!( f, diff --git a/docs/authoring-guide.md b/docs/authoring-guide.md index 28705d9..4ae9f26 100644 --- a/docs/authoring-guide.md +++ b/docs/authoring-guide.md @@ -134,6 +134,9 @@ impl Scale { }], output: vec![FieldSpec { name: "value".into(), kind: ScalarKind::F64 }], params: vec![ParamSpec { name: "factor".into(), kind: ScalarKind::F64 }], + // C29: every vocabulary entry ships a one-line meaning — the + // doc field is required (E0063 without it) and gated at load. + doc: "scalar gain: emits the input times the factor param", }, |p| Box::new(Scale::new(p[0].f64())), ) @@ -217,10 +220,11 @@ $ aura graph build < smacross.json > blueprint.json Nodes are referenced by an **identifier** (given by `add`, see below); ports are dotted `.` on both sides of a wire. -### The eight ops +### The nine ops | op | JSON shape | does | |---|---|---| +| `doc` | `{"op":"doc","text":}` | declare the composite's one-line meaning (C29) — the op-script twin of the Rust builder's `.doc(...)`. Required before `aura graph register` accepts the product (the store refuses a doc-less composite); at most one per script (a second refuses: `a doc op may appear at most once`). The text is gated: empty or merely restating the composite's name refuses at register. | | `source` | `{"op":"source","role":,"kind":}` | reserve a bound root **source** role of `kind` — a real input the harness feeds (e.g. `"price"`). | | `input` | `{"op":"input","role":}` | reserve an open root **input** role (kind inferred from the slots it feeds) — for a fragment meant to be wired by an *enclosing* graph. A standalone document built with `aura graph build` finalizes as a closed root, so an `input` role that is never bound refuses at the end: `finalize: root input role is unbound`. | | `add` | `{"op":"add","type":,"name":?,"bind":{:}?}` | instantiate a node of a type in the closed vocabulary (`aura graph introspect --vocabulary`) — see §0 below for how a type gets into that vocabulary in the first place. `name` becomes the node's identifier for later ops (default: the type's own lowercase label — two unnamed nodes of the same type then collide). `bind` sets zero or more of its params. |