docs(ledger, glossary, guide): construction args across the surfaces
C24 gains the add-op args clause and the data-driven format-version paragraph (tier-2 discipline with id-stability); C15's current state records Session as args-authorable; the glossary defines construction arg and arg kind (and de-stales the session-node entry to aura-market); the authoring guide fixes the moved roster path, extends the Session-anchoring section with the args path, and teaches the add-op args row; the README op-list sentence notes args on arg-bearing types. refs #271
This commit is contained in:
@@ -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 <T>` for a type's exact ports and the op-script
|
||||
grammar in the design ledger for the full semantics.
|
||||
|
||||
|
||||
+33
-7
@@ -49,8 +49,9 @@ the same shape every node in `aura-std` already follows.
|
||||
`src/lib.rs`, registered under the project's own `<namespace>::` 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 `<identifier>.<port>` on both sides of a wire.
|
||||
| `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"`). |
|
||||
| `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. 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":<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>?,"args":{<arg>:<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). `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 <T>` lists a type's declared `arg` rows. `bind` sets zero or more of the (now real) 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). |
|
||||
| `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). |
|
||||
@@ -342,6 +348,26 @@ Wire it like any node —
|
||||
`{"op":"add","type":"SessionFrankfurt","bind":{"period_minutes":{"I64":15}}}`,
|
||||
feed its `trigger` from a once-per-bar stream, and read `bars_since_open`.
|
||||
|
||||
**Any other timezone/open: `Session` + `args` (#271).** `SessionFrankfurt`
|
||||
stays baked sugar for the one Frankfurt open; the canonical path for ANY IANA
|
||||
timezone and local open time is the base `Session` type through the typed
|
||||
construction-args channel — `args` configures it BEFORE `bind`:
|
||||
|
||||
```json
|
||||
{"op":"add","type":"Session","name":"ny",
|
||||
"args":{"tz":"America/New_York","open":"09:30"},
|
||||
"bind":{"period_minutes":{"I64":15}}}
|
||||
```
|
||||
|
||||
`tz` is `chrono_tz`'s own exact, case-sensitive IANA name (`"berlin"` refuses;
|
||||
`"Europe/Berlin"` accepts); `open` is strict zero-padded local `HH:MM`
|
||||
(`"9:30"` refuses; `"09:30"` accepts) — the accepted string IS the canonical
|
||||
form, no normalization. Giving `Session` no `args` at all refuses the `add`
|
||||
op (`node <name> is missing required arg "tz"`) — an arg-bearing type never
|
||||
silently enters the graph half-configured. `aura graph introspect --node
|
||||
Session` lists both declared `arg` rows with their kind and hint text before
|
||||
you write the JSON.
|
||||
|
||||
### Commands
|
||||
|
||||
```
|
||||
|
||||
@@ -17,10 +17,14 @@ stream; reference data feeds source/session nodes from beside the hot path.
|
||||
|
||||
**Session context — `bars_since_open` is the shipped contract (#154).** The
|
||||
session-context node `Session` (`crates/aura-market/src/session.rs`) emits
|
||||
**one** scalar stream, `bars_since_open: i64` (tz-aware, DST-correct, over a
|
||||
baked Frankfurt open), and takes no scalar params; the zero-arg
|
||||
`SessionFrankfurt` roster preset (#261) exposes it with a single
|
||||
`period_minutes` knob. This is a deliberate narrowing pinned in the node's own
|
||||
**one** scalar stream, `bars_since_open: i64` (tz-aware, DST-correct), over a
|
||||
timezone/open time that is now data-authorable via the typed construction-args
|
||||
channel (`Session` roster-reaches `std_vocabulary` as an arg-bearing type,
|
||||
#271: `args: {"tz": <IANA name>, "open": "HH:MM"}`, applied before its one
|
||||
scalar param, `period_minutes`). The zero-arg `SessionFrankfurt` roster preset
|
||||
(#261) stays as baked sugar over the 09:00 `Europe/Berlin` open — the
|
||||
canonical path for any OTHER open/timezone is `Session` + `args`, not a new
|
||||
preset per market. This is a deliberate narrowing pinned in the node's own
|
||||
contract: `bars_since_open` alone is the gate — a downstream `EqConst(== N)`
|
||||
subsumes an `in_session: bool` stream (pre-open instants read `<= 0`, which
|
||||
never match), and nothing consumes a `session_open_ts: timestamp`. The two
|
||||
|
||||
@@ -197,10 +197,17 @@ replayed in order; nodes are referenced **by identifier**, ports as dotted
|
||||
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>?,"args":{<arg>:<str>}?,"bind":{<param>:<Scalar>}?}` —
|
||||
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
|
||||
two unnamed nodes of one type collide); `bind` sets params.
|
||||
two unnamed nodes of one type collide); `args` (#271) configures an **arg-bearing**
|
||||
type's structural, non-scalar construction (`Session`'s IANA timezone/open,
|
||||
`LinComb`/`CostSum`'s arity) through the closed, load-time-validated `ArgKind`
|
||||
table (`Tz`/`TimeOfDay`/`Count`) — applied BEFORE `bind`, so a bound param
|
||||
`args` unlocks (e.g. `LinComb`'s `weights[i]`) is only bindable once `arity` is
|
||||
consumed; an arg-bearing type given no `args` refuses (`BadArg(MissingArg)`), a
|
||||
`Plain` type given `args` it does not declare also refuses
|
||||
(`BadArg(NotArgBearing)`); `bind` sets the (now real) params.
|
||||
- `feed` — `{"op":"feed","role":<str>,"into":[<port>,…]}` — fan a root role into
|
||||
interior input slots.
|
||||
- `connect` — `{"op":"connect","from":<port>,"to":<port>}` — wire an interior output
|
||||
@@ -269,6 +276,14 @@ additive-optional fields of v1; the first ship consciously freezes v1, gangs inc
|
||||
and activates the bump discipline. The per-section required-flag scheme is deferred (no
|
||||
current Tier-2 section to validate it; recorded on #156).
|
||||
|
||||
**First data-driven bump (#271):** construction args are the first Tier-2 case whose
|
||||
version is decided PER DOCUMENT, not a single global bump. The writer emits
|
||||
`format_version: 1` for an args-free document (byte-identical to every pre-#271
|
||||
document — content ids stable) and `2` the moment any primitive, at any composite
|
||||
nesting depth, carries `args` — the must-understand signal an old (pre-#271) reader
|
||||
needs, since it cannot construct a pending arg-bearing type at all. The loader accepts
|
||||
the closed range `1..=2`.
|
||||
|
||||
### Enforcement shift — invariant 9 on the data plane
|
||||
|
||||
Lifting topology onto the data plane relocates *where* the engine/project boundary
|
||||
|
||||
+9
-1
@@ -11,6 +11,10 @@ Entries are alphabetical.
|
||||
|
||||
---
|
||||
|
||||
### arg kind
|
||||
**Avoid:** ArgKind, construction-arg type
|
||||
The closed vocabulary of construction-arg value shapes (`Tz`/`TimeOfDay`/`Count`, #271) — deliberately NOT a `scalar base type`: args are bootstrap metadata, never streamed, so the two closedness axes stay separate. Each kind's accepted strict form IS its canonical form (an exact IANA name, zero-padded `HH:MM`, a plain positive decimal count) — there is no normalization layer, so a near-miss string refuses rather than being rewritten.
|
||||
|
||||
### atomic sim unit
|
||||
**Avoid:** atomic unit, sim unit
|
||||
The primitive `(frozen topology + param-set + data-window + RNG-seed) → deterministic run → metrics` over which the four orchestration axes operate. One frozen-topology unit equals one harness instance.
|
||||
@@ -67,6 +71,10 @@ The type-erased 64-bit word holding one scalar-base-type value with its kind str
|
||||
**Avoid:** —
|
||||
A node that wires a sub-graph and exposes one output (a combined signal, or a strategy) — composition is fractal and acyclic. May carry an optional authored rationale (`doc`, #125) — a non-load-bearing debug symbol shown in the graph tooltip, identity-blind like the name. Also names the multi-column stream a node emits: the **record** a producer's `eval` returns, bundling 1..K base scalar columns (e.g. OHLCV), each bound field-wise by a consumer (C7/C8).
|
||||
|
||||
### construction arg
|
||||
**Avoid:** construction-time param, arg
|
||||
A typed, closed, non-scalar construction input (`args`, #271) that configures an **arg-bearing** vocabulary type's structural shape — `Session`'s IANA timezone/open, `LinComb`/`CostSum`'s arity — through a second channel beside `bind`, consumed once at construction (`PrimitiveBuilder::try_args`) before any param binds, never streamed, never swept, never bound. Values are closed, load-time-validated strings (see `arg kind`); the accepted pairs are id-bearing (they enter the blueprint's content id, like `bind` values) and survive the identity projection.
|
||||
|
||||
### content id
|
||||
**Avoid:** —
|
||||
The SHA-256 (hex) of an artifact's byte-canonical form — for a blueprint, `blueprint_to_json` (the byte-exact identity that keys the reproduction store and anchors `aura reproduce`, stamped into a run manifest as the `topology hash`); for a `process document` / `campaign document`, its canonical JSON (keying the sibling registry stores). One primitive, library-hosted in `aura-research` (`content_id_of`; the CLI delegates). Surfaced as `aura graph|process|campaign introspect --content-id`; two artifacts share a content id only when their canonical bytes agree, debug names included — contrast `identity id`.
|
||||
@@ -263,7 +271,7 @@ The four streamed scalar kinds — `i64`, `f64`, `bool`, `timestamp` (a newtype
|
||||
|
||||
### session node
|
||||
**Avoid:** session window
|
||||
A node that exposes session context as a scalar stream so session logic stays inside the stream model. The shipped `Session` / `SessionFrankfurt` node (`aura-std`) emits ONE `i64` field, `bars_since_open` — the count of completed bar-periods since the local (tz-aware, DST-correct) session open, indexed off the just-closed bar's close instant (in-session closes read exact positive multiples: 09:15→1, 09:45→3; pre-open ≤0). `SessionFrankfurt` bakes the Frankfurt 09:00 `Europe/Berlin` open with a single `period_minutes` knob; its `trigger` input only clocks it once per completed bar (the value is ignored). Calendars and instrument specs remain metadata beside the hot path.
|
||||
A node that exposes session context as a scalar stream so session logic stays inside the stream model. The shipped `Session` / `SessionFrankfurt` node (`aura-market`) emits ONE `i64` field, `bars_since_open` — the count of completed bar-periods since the local (tz-aware, DST-correct) session open, indexed off the just-closed bar's close instant (in-session closes read exact positive multiples: 09:15→1, 09:45→3; pre-open ≤0). `Session` is roster-reachable for ANY IANA timezone/open through the typed **construction arg** channel (#271: `args: {"tz": <IANA name>, "open": "HH:MM"}`, applied before its one scalar param, `period_minutes`); `SessionFrankfurt` stays as baked sugar over the Frankfurt 09:00 `Europe/Berlin` open. Its `trigger` input only clocks it once per completed bar (the value is ignored). Calendars and instrument specs remain metadata beside the hot path.
|
||||
|
||||
### sign-agreement
|
||||
**Avoid:** sign consistency, market breadth
|
||||
|
||||
Reference in New Issue
Block a user