diff --git a/README.md b/README.md index 273909d..014ca7d 100644 --- a/README.md +++ b/README.md @@ -122,7 +122,9 @@ The op kinds are `source`, `input`, `add`, `feed`, `connect`, `expose`, `tap`, `gang`, `doc`, and `use` (`tap` declares a recorded measurement point on an interior wire; `doc` declares the composite's one-line meaning, required at register — C29; `use` splices a registered blueprint in as a nested composite, -by content id or label; see the authoring guide). See +by content id or label; `add` additionally takes an `args` object for +**arg-bearing** types (`Session`, `LinComb`, `CostSum`) — structural, +non-scalar construction consumed before `bind`; 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/docs/authoring-guide.md b/docs/authoring-guide.md index 384f262..d3f486d 100644 --- a/docs/authoring-guide.md +++ b/docs/authoring-guide.md @@ -49,8 +49,9 @@ the same shape every node in `aura-std` already follows. `src/lib.rs`, registered under the project's own `::` prefix) and appends its path to the project's `Aura.toml [nodes]` section. - **A block promoted to universal** — reused across projects and folded into - the engine itself — lives in `crates/aura-std/src/`, unprefixed, and is - rostered in `crates/aura-std/src/vocabulary.rs` instead of a node crate's + the engine itself — lives in `crates/aura-std/` (or its sibling domain + crates: `aura-market`, `aura-strategy`), unprefixed, and is rostered in + `crates/aura-vocabulary/src/lib.rs` instead of a node crate's `vocabulary()` function. The pattern below is identical either way; only the rostering call site differs (see "Rostering the type" below). @@ -89,11 +90,16 @@ Every node type — std or project-local — is three things: `aura_core::aura_project!` macro wires up (every `aura new` scaffold emits a starter pair — see the worked example below). Add one match arm to `vocabulary()` and one entry to `type_ids()`'s slice. - - **Std-side** (only when promoting a node into `aura-std` itself): one - line in the `std_vocabulary_roster!` macro invocation in - [`crates/aura-std/src/vocabulary.rs`](../crates/aura-std/src/vocabulary.rs) + - **Std-side** (only when promoting a node into the shipped std + vocabulary): one line in the `std_vocabulary_roster!` macro invocation in + [`crates/aura-vocabulary/src/lib.rs`](../crates/aura-vocabulary/src/lib.rs) — `"TypeId" => Type,` — which expands into both the resolver `match` and - the enumerable type-id list, so the two surfaces cannot drift apart. + the enumerable type-id list, so the two surfaces cannot drift apart. A + zero-arg `Type::builder()` rosters directly; an **arg-bearing** type + (structural, non-scalar construction — see "Session anchoring" below and + `docs/glossary.md`'s `construction arg` entry, #271) rosters the exact + same way — its `builder()` is itself zero-arg, returning a *pending* + recipe the `add` op's `args` configures before any `bind`. An unrostered type fails safe either way: the loader refuses with a clean `LoadError::UnknownNodeType` naming the missing id, and the type is simply absent from `aura graph introspect --vocabulary` — never a silent partial @@ -228,7 +234,7 @@ are dotted `.` on both sides of a wire. | `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) — the formal parameter of an **open pattern**, a fragment meant to be wired by an *enclosing* graph. An open pattern builds and registers like any blueprint. Running it standalone is governed by the ordinary run gates: the harness binds input roles to archive columns **by name** (C26), so a pattern whose roles match the data runs as-is; what refuses, by name, is a role the harness cannot bind — or the run surface's other gates (a signal without a bias output or tap; free knobs). | -| `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. | +| `add` | `{"op":"add","type":,"name":?,"args":{:}?,"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). `args` (#271) configures an **arg-bearing** type's structural, non-scalar construction (`Session`'s timezone/open, `LinComb`/`CostSum`'s arity) — a closed table of string values, applied BEFORE `bind`; `aura graph introspect --node ` lists a type's declared `arg` rows. `bind` sets zero or more of the (now real) params. | | `use` | `{"op":"use","ref":{"content_id":}\|{"name":