docs(ledger, glossary, guide): the ten-verb grammar, the use seam, open patterns
C24: the op-script grammar section is rewritten to the ten verbs — repairing a pre-existing drift on the way (it read "The eight verbs" and omitted the doc op shipped with #316) — with the new use row and the open-pattern reading of input roles; a "Registered-blueprint splice" paragraph records the resolution split (all store I/O CLI-side at DTO conversion; the engine's second injected closure mirrors vocab, the §"Enforcement shift" permission extended to registered-blueprint references); the construction-gates paragraph moves root-role boundness from the holistic finalize list to compile/bootstrap only (#317 comment 4627). C29: the register-seam wording drops "named" — the code gates EVERY nested composite, recon-confirmed pre-existing prose/code mismatch — and the use seam joins the seam list (build-time gate on fetched store content; no retroactive invalidation of existing reads). Glossary: use (op) and blueprint label entries. Authoring guide: ten ops (the stale "nine ops" heading + the input row's obsolete finalize-refusal claim corrected), the use row, and the register --name / discovery paragraph. Prose truth per review: instance params are sweepable, NOT gangable (the gang op refuses a composite instance's member path) — stated as such everywhere; the gangability of spliced instances is recorded residue, not a claim. refs #317
This commit is contained in:
+10
-2
@@ -221,14 +221,15 @@ $ aura graph build < smacross.json > blueprint.json
|
|||||||
Nodes are referenced by an **identifier** (given by `add`, see below); ports
|
Nodes are referenced by an **identifier** (given by `add`, see below); ports
|
||||||
are dotted `<identifier>.<port>` on both sides of a wire.
|
are dotted `<identifier>.<port>` on both sides of a wire.
|
||||||
|
|
||||||
### The nine ops
|
### The ten ops
|
||||||
|
|
||||||
| op | JSON shape | does |
|
| op | JSON shape | does |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| `doc` | `{"op":"doc","text":<str>}` | 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. |
|
| `doc` | `{"op":"doc","text":<str>}` | 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":<str>,"kind":<ScalarKind>}` | reserve a bound root **source** role of `kind` — a real input the harness feeds (e.g. `"price"`). |
|
| `source` | `{"op":"source","role":<str>,"kind":<ScalarKind>}` | reserve a bound root **source** role of `kind` — a real input the harness feeds (e.g. `"price"`). |
|
||||||
| `input` | `{"op":"input","role":<str>}` | 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 <name> is unbound`. |
|
| `input` | `{"op":"input","role":<str>}` | 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; only *running* it standalone refuses (bootstrap's unbound-root-role gate — there is no enclosing graph to wire it). |
|
||||||
| `add` | `{"op":"add","type":<TypeId>,"name":<str>?,"bind":{<param>:<Scalar>}?}` | 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":<TypeId>,"name":<str>?,"bind":{<param>:<Scalar>}?}` | 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. |
|
||||||
|
| `use` | `{"op":"use","ref":{"content_id":<id-or-prefix>}\|{"name":<label>},"name":<str>?,"bind":{<path>:<Scalar>}?}` | splice a **registered blueprint** into the graph as a nested composite under an instance identifier (`name`; default: the stored composite's own name). The ref resolves by content id (full or unique prefix) or by a register-time label; `graph build` echoes every resolution (`aura: note: use "…": … -> <id>`) so the exact id can be pinned. The instance's open input roles wire as `<instance>.<role>`, its outputs as `<instance>.<field>`; its open params surface path-qualified (`<instance>.<node>.<param>`), sweepable (ganging an instance's params is not yet supported — the `gang` op refuses a composite instance's member path). A doc-less stored source refuses at the op (C29). The emitted blueprint contains the subgraph *inline* — no reference survives into the artifact. |
|
||||||
| `feed` | `{"op":"feed","role":<str>,"into":[<port>, …]}` | fan a previously-declared role into one or more interior input slots, all-or-nothing (a failing target leaves none of the batch wired). |
|
| `feed` | `{"op":"feed","role":<str>,"into":[<port>, …]}` | fan a previously-declared role into one or more interior input slots, all-or-nothing (a failing target leaves none of the batch wired). |
|
||||||
| `connect` | `{"op":"connect","from":<port>,"to":<port>}` | wire one interior output field to one interior input slot. A `connect` that would close a dataflow cycle is rejected immediately — the only legal feedback path is an explicit delay/state node (domain invariant 5). |
|
| `connect` | `{"op":"connect","from":<port>,"to":<port>}` | wire one interior output field to one interior input slot. A `connect` that would close a dataflow cycle is rejected immediately — the only legal feedback path is an explicit delay/state node (domain invariant 5). |
|
||||||
| `expose` | `{"op":"expose","from":<port>,"as":<str>}` | promote an interior output field to a boundary output under the alias `as` — a real *alias* (a terminal boundary name, not a referenceable identifier like `add`'s `name`). Together with `tap`, one of the two ops whose `as` key is a terminal name rather than an identifier. |
|
| `expose` | `{"op":"expose","from":<port>,"as":<str>}` | promote an interior output field to a boundary output under the alias `as` — a real *alias* (a terminal boundary name, not a referenceable identifier like `add`'s `name`). Together with `tap`, one of the two ops whose `as` key is a terminal name rather than an identifier. |
|
||||||
@@ -405,6 +406,13 @@ registered blueprint 597d719b7ac607158cda3e68cd497387620397a5e93087e23da512876da
|
|||||||
The printed content id is the address a campaign document's `strategies[].ref`
|
The printed content id is the address a campaign document's `strategies[].ref`
|
||||||
points at (§3).
|
points at (§3).
|
||||||
|
|
||||||
|
`graph register <file> --name <label>` additionally records a **blueprint
|
||||||
|
label** — a legible, re-pointable handle for the `use` op's `{"name":…}`
|
||||||
|
ref form (re-registering under the same label repoints it; the echo names
|
||||||
|
the previous target). `aura graph introspect --registered` lists the
|
||||||
|
labels with their id prefix and root doc line — the discovery surface for
|
||||||
|
what `use` can reference.
|
||||||
|
|
||||||
## 2. Process documents — a validation methodology (role 5)
|
## 2. Process documents — a validation methodology (role 5)
|
||||||
|
|
||||||
A process document is a named, versionable pipeline of **std stage blocks**
|
A process document is a named, versionable pipeline of **std stage blocks**
|
||||||
|
|||||||
@@ -144,17 +144,38 @@ per-op checks — name resolution, edge kind-match (`edge_kind_check`), the doub
|
|||||||
arm, param bind, and acyclicity (a `connect` that would close a cycle is rejected
|
arm, param bind, and acyclicity (a `connect` that would close a cycle is rejected
|
||||||
eagerly at the closing op, `GraphSession::closes_cycle`, #161) — and **holistic**
|
eagerly at the closing op, `GraphSession::closes_cycle`, #161) — and **holistic**
|
||||||
finalize checks — wiring totality (`validate_wiring`), param-namespace injectivity
|
finalize checks — wiring totality (`validate_wiring`), param-namespace injectivity
|
||||||
(`check_param_namespace_injective`), root-role boundness (`check_root_roles_bound`).
|
(`check_param_namespace_injective`). Both cadences call the **same extracted
|
||||||
Both cadences call the **same extracted predicates** — no second validator. The
|
predicates** — no second validator. The holistic faults read **by-identifier**
|
||||||
holistic faults read **by-identifier** (#162): `finish()` translates the
|
(#162): `finish()` translates the index-carrying `CompileError`s (`UnconnectedPort` /
|
||||||
index-carrying `CompileError`s (`UnconnectedPort` / `RoleKindMismatch` /
|
`RoleKindMismatch`) into by-identifier `OpError` variants while still *calling* the
|
||||||
`UnboundRootRole`) into by-identifier `OpError` variants while still *calling* the
|
unchanged holistic gates. **Root-role boundness moved off this list (#317, open
|
||||||
unchanged holistic gates. Build-free introspection answers over the closed vocabulary:
|
patterns):** `check_root_roles_bound` no longer runs in `finish()` — a `finish()`ed
|
||||||
`graph introspect --vocabulary | --node <T> | --unwired`. The engine `Op` stays
|
op-script may still carry an open (unbound) root role, declaring a reusable
|
||||||
serde-free; the wire DTO (`OpDoc`) is CLI-side (`aura-cli::graph_construct`).
|
pattern's formal parameter; only `compile`/bootstrap (the runnability gate, not a
|
||||||
Acceptance: a graph built purely through the ops compiles identical (C1) to its
|
construction gate) still call it, unchanged. Build-free introspection answers over
|
||||||
Rust-built twin, an invalid op is rejected at the op naming the cause, introspection
|
the closed vocabulary: `graph introspect --vocabulary | --node <T> | --unwired`. The
|
||||||
answers without a build.
|
engine `Op` stays serde-free; the wire DTO (`OpDoc`) is CLI-side
|
||||||
|
(`aura-cli::graph_construct`). Acceptance: a graph built purely through the ops
|
||||||
|
compiles identical (C1) to its Rust-built twin, an invalid op is rejected at the op
|
||||||
|
naming the cause, introspection answers without a build.
|
||||||
|
|
||||||
|
**Registered-blueprint splice (#317).** The `use` op resolves a reference — a store
|
||||||
|
content id, a unique content-id prefix (#302 semantics), or a registry **name
|
||||||
|
label** (`graph register --name`, latest-wins, `aura-registry`'s
|
||||||
|
`blueprint_names.jsonl` sidecar) — to a previously registered blueprint and
|
||||||
|
splices it into the building graph as a nested `BlueprintNode::Composite` under an
|
||||||
|
instance identifier. The **engine never resolves**: `GraphSession`/`replay` take a
|
||||||
|
second injected closure, `subgraph: &dyn Fn(&str) -> Option<Composite>`, mirroring
|
||||||
|
`vocab`'s closed-lookup posture exactly — this is the same enforcement-shift
|
||||||
|
permission §"Enforcement shift" above already grants the node vocabulary, extended
|
||||||
|
to registered-blueprint references. All store I/O — label/prefix resolution, the
|
||||||
|
`get_blueprint` fetch, the C29 doc-gate re-walk over the fetched composite (before
|
||||||
|
it ever reaches the session, so a doc-less fetched entry cannot enter a NEW
|
||||||
|
composition), and the resolution echo — happens CLI-side, at DTO conversion, before
|
||||||
|
replay; build-free introspection paths pass `&|_| None`. The echo
|
||||||
|
(`aura: note: use "<instance>": <label-or-prefix> -> <full id>`) is the existing
|
||||||
|
`aura: note:` benign-diagnostic marker (C14) — a new instance of the existing
|
||||||
|
class, not a new one, so the exit-code/marker taxonomy is unchanged.
|
||||||
|
|
||||||
**Invariant-5 lockstep.** The eager acyclicity gate is a *second* home of invariant 5
|
**Invariant-5 lockstep.** The eager acyclicity gate is a *second* home of invariant 5
|
||||||
alongside the bootstrap Kahn sort (`harness.rs`, `BootstrapError::Cycle`); the two
|
alongside the bootstrap Kahn sort (`harness.rs`, `BootstrapError::Cycle`); the two
|
||||||
@@ -166,12 +187,14 @@ rejected at construction.
|
|||||||
|
|
||||||
The op-script is a JSON **array of ops**, each object internally tagged by `"op"`,
|
The op-script is a JSON **array of ops**, each object internally tagged by `"op"`,
|
||||||
replayed in order; nodes are referenced **by identifier**, ports as dotted
|
replayed in order; nodes are referenced **by identifier**, ports as dotted
|
||||||
`<identifier>.<port>`. The eight verbs:
|
`<identifier>.<port>`. The ten verbs:
|
||||||
|
|
||||||
- `source` — `{"op":"source","role":<str>,"kind":<ScalarKind>}` — declare a root
|
- `source` — `{"op":"source","role":<str>,"kind":<ScalarKind>}` — declare a root
|
||||||
source role producing a base column of `kind`.
|
source role producing a base column of `kind`.
|
||||||
- `input` — `{"op":"input","role":<str>}` — declare a root input role (kind inferred
|
- `input` — `{"op":"input","role":<str>}` — declare a root input role (kind inferred
|
||||||
from the slots it feeds).
|
from the slots it feeds) — a reusable **pattern**'s formal parameter, left open
|
||||||
|
until an enclosing graph wires it (#317's open patterns): `finish()` accepts an
|
||||||
|
op-script that never binds it, only `compile`/bootstrap require it bound.
|
||||||
- `add` — `{"op":"add","type":<TypeId>,"name":<str>?,"bind":{<param>:<Scalar>}?}` —
|
- `add` — `{"op":"add","type":<TypeId>,"name":<str>?,"bind":{<param>:<Scalar>}?}` —
|
||||||
add a node of compiled-in type identity `type`; **`name` is its identifier**
|
add a node of compiled-in type identity `type`; **`name` is its identifier**
|
||||||
(mirrors the builder's `.named(...)`; defaults to the lowercased type label, so
|
(mirrors the builder's `.named(...)`; defaults to the lowercased type label, so
|
||||||
@@ -196,6 +219,19 @@ replayed in order; nodes are referenced **by identifier**, ports as dotted
|
|||||||
leave the sweepable param space and `as` replaces them; the bound or swept
|
leave the sweepable param space and `as` replaces them; the bound or swept
|
||||||
value fans out to every member at bootstrap. Members must share one scalar
|
value fans out to every member at bootstrap. Members must share one scalar
|
||||||
kind and stay open (un-bound).
|
kind and stay open (un-bound).
|
||||||
|
- `doc` — `{"op":"doc","text":<str>}` — declare the composite's one-line meaning
|
||||||
|
(C29, #316) — the op-script twin of the builder's `.doc(...)`; at most one per
|
||||||
|
script, a second is a fault (a declarative script carries no last-wins
|
||||||
|
ambiguity).
|
||||||
|
- `use` — `{"op":"use","ref":{"content_id":<str>}|{"name":<str>},"name":<str>?,"bind":{<path>:<Scalar>}?}`
|
||||||
|
— splice a **registered** blueprint into the building graph as a nested
|
||||||
|
composite under an instance identifier (`name`, defaulting to the fetched
|
||||||
|
composite's own name); `bind` path-qualifies the spliced instance's params
|
||||||
|
(e.g. `"sma.length"`), applied after the splice (#317). An instance's open
|
||||||
|
input roles become its `<instance>.<role>` in-ports, its output boundary
|
||||||
|
aliases its `<instance>.<field>` out-fields — the same `Composite` arm every
|
||||||
|
other add/wiring path walks, not a new mechanism. See §"The construction
|
||||||
|
service" below for the resolution split.
|
||||||
|
|
||||||
Value forms are the serialized representations: a `Scalar` bind value is the typed tag
|
Value forms are the serialized representations: a `Scalar` bind value is the typed tag
|
||||||
form `{"I64":2}` / `{"F64":0.5}` / `{"Bool":true}` / `{"Timestamp":<i64>}`, and `kind`
|
form `{"I64":2}` / `{"F64":0.5}` / `{"Bool":true}` / `{"Timestamp":<i64>}`, and `kind`
|
||||||
|
|||||||
@@ -27,13 +27,23 @@ cannot pass its short-name alibi
|
|||||||
restatement.
|
restatement.
|
||||||
3. **Register seam (data plane).** The registry's public `put_blueprint`
|
3. **Register seam (data plane).** The registry's public `put_blueprint`
|
||||||
parses the canonical bytes and requires a gate-passing doc on the root
|
parses the canonical bytes and requires a gate-passing doc on the root
|
||||||
composite and on every named nested composite — the gate guards the
|
composite and on **every** nested composite (the walk recurses
|
||||||
store boundary itself, so the register verb, every register-then-run
|
unconditionally — it does not stop at an unnamed one) — the gate guards
|
||||||
|
the store boundary itself, so the register verb, every register-then-run
|
||||||
sugar path, and any future caller are gated by construction. The
|
sugar path, and any future caller are gated by construction. The
|
||||||
op-script vocabulary carries the `doc` op as the builder `.doc(...)`'s
|
op-script vocabulary carries the `doc` op as the builder `.doc(...)`'s
|
||||||
twin ([C25](c25-role-model.md): a closed, typed metadata construct).
|
twin ([C25](c25-role-model.md): a closed, typed metadata construct).
|
||||||
Process/campaign documents take an additive-optional top-level
|
Process/campaign documents take an additive-optional top-level
|
||||||
`description`, gated only when present (`DocFault::BadDescription`).
|
`description`, gated only when present (`DocFault::BadDescription`).
|
||||||
|
4. **Use seam (data plane, construction-time, #317).** The `use`
|
||||||
|
construction op re-runs the SAME `gate_composite_docs` walk over a
|
||||||
|
blueprint FETCHED from the store, before it ever splices into a new
|
||||||
|
composition — a build-time gate on already-registered content, not a
|
||||||
|
second write-path check. A doc-less entry (reachable only through the
|
||||||
|
raw in-crate write survivor class, since `put_blueprint`'s own gate keeps
|
||||||
|
the store clean going forward) cannot enter a NEW composition this way,
|
||||||
|
but stays readable and runnable on its own — no retroactive invalidation,
|
||||||
|
the same discipline the Forbids clause states for the register seam.
|
||||||
|
|
||||||
**Scope at this record's writing (#321).** The gate walks five
|
**Scope at this record's writing (#321).** The gate walks five
|
||||||
vocabularies — process/campaign blocks, metrics, tap slots, tap folds, and
|
vocabularies — process/campaign blocks, metrics, tap slots, tap folds, and
|
||||||
|
|||||||
@@ -31,6 +31,10 @@ A strategy's primary, backtestable DAG output: one signed, bounded `f64 ∈ [-1,
|
|||||||
**Avoid:** —
|
**Avoid:** —
|
||||||
The param-generic, input-role-generic graph-as-data produced by running a Rust builder; it carries free numeric params and free input roles before bootstrap. Bootstrapped into a frozen instance by binding params + data + seed. Registered and inspected headless (`aura graph register`, `aura graph introspect --params` — the raw `param_space` namespace campaign axes bind against; cycle 0107/#196); a *bound* param is an overridable **default** — a sweep axis naming it re-opens it per family (#246), while `run` uses it as-is.
|
The param-generic, input-role-generic graph-as-data produced by running a Rust builder; it carries free numeric params and free input roles before bootstrap. Bootstrapped into a frozen instance by binding params + data + seed. Registered and inspected headless (`aura graph register`, `aura graph introspect --params` — the raw `param_space` namespace campaign axes bind against; cycle 0107/#196); a *bound* param is an overridable **default** — a sweep axis naming it re-opens it per family (#246), while `run` uses it as-is.
|
||||||
|
|
||||||
|
### blueprint label
|
||||||
|
**Avoid:** —
|
||||||
|
A registry-level name pointing at a registered blueprint's content id (`graph register --name <label>`, #317) — a mutable, latest-wins pointer over the immutable content-addressed store, not a second identity: re-registering under an existing label *repoints* it (the earlier content id stays reachable by its own id, never invalidated). `graph introspect --registered` lists every label with its content-id prefix and root `doc` line — the discovery surface a `use (op)` reference by name resolves against.
|
||||||
|
|
||||||
### bootstrap
|
### bootstrap
|
||||||
**Avoid:** —
|
**Avoid:** —
|
||||||
The distinct, recursive construction phase that binds `(blueprint + param-set + data bindings + seed)` into a frozen instance — buffers sized, topology fixed. The explicit name for the "wiring / graph build" that C7/C12 reference — the construction/compilation sense. Disambiguation: the *statistical* moving-block bootstrap of a trade-R series (`r_bootstrap`, `RBootstrap`) is a different thing that keeps its statistics name — it appears as the deflation null, the `aura mc` R path, and since 0108 the `std::monte_carlo` stage's `stage bootstrap` annotation; context (construction vs annotation) disambiguates.
|
The distinct, recursive construction phase that binds `(blueprint + param-set + data bindings + seed)` into a frozen instance — buffers sized, topology fixed. The explicit name for the "wiring / graph build" that C7/C12 reference — the construction/compilation sense. Disambiguation: the *statistical* moving-block bootstrap of a trade-R series (`r_bootstrap`, `RBootstrap`) is a different thing that keeps its statistics name — it appears as the deflation null, the `aura mc` R path, and since 0108 the `std::monte_carlo` stage's `stage bootstrap` annotation; context (construction vs annotation) disambiguates.
|
||||||
@@ -333,6 +337,10 @@ Since #283 what CONSUMES a declared tap is itself declared per run by a **tap pl
|
|||||||
**Avoid:** —
|
**Avoid:** —
|
||||||
The `content id` of a run's signal blueprint in its run-record role: stamped into the manifest as `topology_hash`, keying the reproduction store and anchoring `aura reproduce` — the same SHA-256 over the same canonical bytes. Distinct from the debug-name-blind `identity id`.
|
The `content id` of a run's signal blueprint in its run-record role: stamped into the manifest as `topology_hash`, keying the reproduction store and anchoring `aura reproduce` — the same SHA-256 over the same canonical bytes. Distinct from the debug-name-blind `identity id`.
|
||||||
|
|
||||||
|
### use (op)
|
||||||
|
**Avoid:** —
|
||||||
|
The construction op that splices a **registered** blueprint into the building graph as a nested `composite` under a chosen instance name (`{"op":"use","ref":{"content_id"|"name":…},"name":…,"bind":{…}}`, #317): the reference — a content id, a unique content-id prefix, or a `blueprint label` — resolves CLI-side, before the engine ever sees it; the fetched composite is C29-gated, spliced, and its resolution echoed on stderr (`aura: note:`, the existing benign marker). The emitted blueprint carries the splice inline as an ordinary nested composite — no reference or registry dependency survives into the artifact. An instance's open input roles become its `<instance>.<role>` in-ports, its output boundary fields its `<instance>.<field>` out-fields — the existing nested-composite param-prefix discipline extends unchanged (`graph.<instance>.<node>.<param>` on `sweep --list-axes`). Pairs with the `input` op: a pattern meant to be `use`d declares its formal parameters as open `input` roles, left unbound at `finish()` (#317's open-pattern amendment) — only running it standalone requires them bound.
|
||||||
|
|
||||||
### veto
|
### veto
|
||||||
**Avoid:** risk-manager
|
**Avoid:** risk-manager
|
||||||
The **optional** documented pre-trade-gate seam in the execution chain (`stop-rule → [Veto] → position-management`): position / exposure / notional caps that may reject or scale a trade. A pass-through identity DCE'd away when absent (C19/C23); kept as a named seam — it is what LEAN calls "Risk Management" and nautilus the RiskEngine.
|
The **optional** documented pre-trade-gate seam in the execution chain (`stop-rule → [Veto] → position-management`): position / exposure / notional caps that may reject or scale a trade. A pass-through identity DCE'd away when absent (C19/C23); kept as a named seam — it is what LEAN calls "Risk Management" and nautilus the RiskEngine.
|
||||||
|
|||||||
Reference in New Issue
Block a user