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:
@@ -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
|
||||
eagerly at the closing op, `GraphSession::closes_cycle`, #161) — and **holistic**
|
||||
finalize checks — wiring totality (`validate_wiring`), param-namespace injectivity
|
||||
(`check_param_namespace_injective`), root-role boundness (`check_root_roles_bound`).
|
||||
Both cadences call the **same extracted predicates** — no second validator. The
|
||||
holistic faults read **by-identifier** (#162): `finish()` translates the
|
||||
index-carrying `CompileError`s (`UnconnectedPort` / `RoleKindMismatch` /
|
||||
`UnboundRootRole`) into by-identifier `OpError` variants while still *calling* the
|
||||
unchanged holistic gates. Build-free introspection answers over the closed vocabulary:
|
||||
`graph introspect --vocabulary | --node <T> | --unwired`. The 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.
|
||||
(`check_param_namespace_injective`). Both cadences call the **same extracted
|
||||
predicates** — no second validator. The holistic faults read **by-identifier**
|
||||
(#162): `finish()` translates the index-carrying `CompileError`s (`UnconnectedPort` /
|
||||
`RoleKindMismatch`) into by-identifier `OpError` variants while still *calling* the
|
||||
unchanged holistic gates. **Root-role boundness moved off this list (#317, open
|
||||
patterns):** `check_root_roles_bound` no longer runs in `finish()` — a `finish()`ed
|
||||
op-script may still carry an open (unbound) root role, declaring a reusable
|
||||
pattern's formal parameter; only `compile`/bootstrap (the runnability gate, not a
|
||||
construction gate) still call it, unchanged. Build-free introspection answers over
|
||||
the closed vocabulary: `graph introspect --vocabulary | --node <T> | --unwired`. The
|
||||
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
|
||||
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"`,
|
||||
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 role producing a base column of `kind`.
|
||||
- `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 a node of compiled-in type identity `type`; **`name` is its identifier**
|
||||
(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
|
||||
value fans out to every member at bootstrap. Members must share one scalar
|
||||
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
|
||||
form `{"I64":2}` / `{"F64":0.5}` / `{"Bool":true}` / `{"Timestamp":<i64>}`, and `kind`
|
||||
|
||||
@@ -27,13 +27,23 @@ cannot pass its short-name alibi
|
||||
restatement.
|
||||
3. **Register seam (data plane).** The registry's public `put_blueprint`
|
||||
parses the canonical bytes and requires a gate-passing doc on the root
|
||||
composite and on every named nested composite — the gate guards the
|
||||
store boundary itself, so the register verb, every register-then-run
|
||||
composite and on **every** nested composite (the walk recurses
|
||||
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
|
||||
op-script vocabulary carries the `doc` op as the builder `.doc(...)`'s
|
||||
twin ([C25](c25-role-model.md): a closed, typed metadata construct).
|
||||
Process/campaign documents take an additive-optional top-level
|
||||
`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
|
||||
vocabularies — process/campaign blocks, metrics, tap slots, tap folds, and
|
||||
|
||||
Reference in New Issue
Block a user