e25ca15be486ab60ca25eadaff36ee4720a2a957
529 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
e25ca15be4 |
plan: 0092 run-from-blueprint
Five-task decomposition of #165 (run a serialized signal blueprint): 1. behaviour-preserving restructure of stage1_r_graph into stage1_signal() + wrap_stage1r() (the serializable signal boundary + the shared wrapping), gated by the stage1-r + bit-identical-e2e tests staying green; 2. RunManifest.topology_hash (Tier-1 optional) + thread None into the ~24 workspace literal sites (one compile-gate); 3. the shared run_signal_stage1r seam + the sha256_hex helper (sha2 in aura-cli, off the frozen engine, invariant 8) + run_stage1_r gains its topology_hash; 4. the `aura run <blueprint.json>` CLI arm (.json discriminator, --params cells), leaving the existing harness-kind dispatch intact (#159 stays); 5. demo signal blueprint + the bit-identical / determinism / E2E tests. Tasks 1-2 (restructure + field-add) run and verify first. Derived grounding decisions (the restructure target, param_space-derived manifest.params, the Q4 behaviour-preserving semantics) recorded on #165. refs #165 |
||
|
|
29a519dbf6 |
spec: 0092 run-from-blueprint (boss-signed)
Cycle 1 of the World/C21 milestone (#165): `aura run <blueprint.json>` loads a serialized C24 signal blueprint, wraps it in the existing Stage-1-R run scaffolding via a shared seam extracted from run_stage1_r, compiles + bootstraps + runs, and emits a RunReport whose RunManifest carries a new Tier-1-optional topology_hash (SHA256 of the canonical blueprint form, #158 anchor). A serialized blueprint is a SIGNAL (sinks/brokers/data/clock out of the round-trippable set, C24), so aura run WRAPS the loaded signal in a runnable harness — the same wrap the Rust path does, shared as one function so "bit-identical to the Rust path" is the same seam over the same signal. The round-trip bit-identity is already proven (blueprint_serde_e2e.rs); cycle 1 lifts it to the CLI + adds topology_hash. Boss-signed on a grounding-check PASS: all six load-bearing current-behaviour assumptions ratified by named green tests (blueprint_from_json, the bit-identical round-trip, the run_stage1_r compile/bootstrap/run path, RunManifest's Tier-1 optional-field pattern, canonical blueprint_to_json, window_of). Derived wrapping decision recorded on #165. sha2 enters under the C16 per-case dependency review (SHA256 user-settled). refs #165 |
||
|
|
df228986c4 |
docs(ledger): C24 enforcement shift — invariant 9 moves from structural to resolver-seam
A cycle-0091 design analysis (adversarially verified) of "does invariant 9 survive lifting blueprints onto the data plane?" records a load-bearing finding in the C24 entry. Pre-C24 a blueprint referencing another project's node was a compile error (topology was in-process Rust — structurally impossible). Post-C24 it is a type-id string refused only by the injected resolver's closed set (UnknownNodeType). The anti-NIH rationale survives (logic stays cargo+Gitea-only; the format distributes topology-as-content, never logic, C17) and std_vocabulary stays a compiled-in dispatch table, not a registry — but enforcement of the engine/project boundary degrades from compiler-guaranteed to resolver-seam discipline. Two consequences recorded: #160 becomes the data-plane face of that boundary (no longer droppable; its own drift still fails safe), and the injected per-project resolver is the genuinely new, deferred invariant-9 surface (a project can express a marketplace one layer above the engine contract) — a World/C21-layer charter point. Invariant 8 (frozen) is reframed alongside: runtime topology generation (research plane) + frozen deploy artifact + deterministic-once-instantiated (C1). refs #160 |
||
|
|
4a3ae05db2 |
test(graph_model): cover a producer backing >1 re-exported output field
#47 — close a coverage gap in the graph model serializer: a single interior producer node backing more than one re-exported output field was never exercised by a fixture (every existing one maps each output to a distinct producer or a single field). The issue was filed at cycle 0022 against `aura-cli/src/graph.rs`'s `render_definition` / `output_binding` helper, which rendered a textual `(n1, n2) := <producer>` tuple binding. That file and helper no longer exist — the textual definition renderer was replaced by the JSON model emission now in `aura-engine/src/graph_model.rs`, where the multi-OutField case is plain flat iteration over `c.output()` (one `[name,kind]` entry + one `#N` boundary binding per `OutField`, by `(node, field)`), not a special tuple-binding arm. So the original branch is gone; this guards the flat emission that replaced it. New test `multi_outfield_producer_emits_one_binding_per_field` (+ two fixtures): a two-field producer (`hi`:f64, `lo`:i64 — distinct kinds, so the per-field `field_kind` lookup is exercised) re-exported as both composite outputs, nested in a root so it renders through `composite_def_json`. Asserts both fields surface with their own kind (`"outputs":[["hi","f64"],["lo","i64"]]`) and both bindings reference the same producer at distinct ordinals (`0.o0`/`#0`, `0.o1`/`#1`). Test-only; no production code touched (the behaviour was already correct). Verified: cargo test -p aura-engine green (237 in the lib suite); clippy clean. closes #47 |
||
|
|
b8b83cf1c9 |
feat(0091): byte-canonical blueprint emit; record the equality-surface decision
#164 — tighten the C24 "canonical, versioned" blueprint contract on two corners the milestone fieldtest surfaced. Both forks were derivable; resolved with rationale (recorded on #164). Fork 1 — canonical artifact carries no trailing newline. `blueprint_to_json` returns the JSON value with no trailing newline (647 bytes for the SMA-cross fixture); `aura graph build` had framed it with a `println!` (648). The library serializer is the single canonical source — the form content-addressed topology identity (#158) hashes — so the CLI is a transport that must not mutate the bytes: `build_cmd` now `print!`s the canonical bytes verbatim, making the CLI and library emit paths byte-identical. RED-first: the new E2E `graph_build_emit_is_byte_canonical_no_trailing_newline` pinned the trailing newline (FAIL), green after the one-line change. The two cycle-0088 `.out.json` goldens are re-recorded at 647 bytes. The loader stays lenient (a trailing newline on input still parses, Tier-1 robustness; the milestone fieldtest's `mt_4` tolerance check is unaffected). Fork 2 — the canonical JSON is the blueprint equality/identity surface; no second in-memory PartialEq/Debug is added. `Composite`/`BlueprintNode` cannot derive them: `PrimitiveBuilder` (aura-core node.rs) holds a `build: Box<dyn Fn(&[Cell]) -> Box<dyn Node>>` closure, neither comparable nor printable. Equality could only be defined over the serialized data, of which `blueprint_to_json` is already the single source; a separate in-memory equality notion would be a redundant second source of truth and a drift hazard against the form #158 hashes. Recorded the decision (discharges acceptance box 2's "or JSON-string is the intended equality surface" arm) in the C24 ledger; no code added for it. Verified: cargo test --workspace green (51 suites, incl. the new RED->green E2E); cargo clippy --workspace --all-targets -D warnings clean. closes #164 |
||
|
|
8bb21b1c16 |
docs(0088): document op-script grammar; refresh stale cycle-0088 example corpus
#163 — the construction op-script (`aura graph build`) had no durable public
schema doc, and the only worked-example corpus had drifted out of sync with the
current binary, so a consumer copying the visible example was misled.
Grammar reference (durable): a compact op-script grammar — the six verbs
(source/input/add/feed/connect/expose), their keys, the typed-Scalar bind form
({"I64":2}) and the capitalized ScalarKind, the by-identifier / dotted-port
model, and the add-`name` vs expose-`as` distinction — added to the C24 ledger
entry, with a correct worked-example pointer. Surfacing the same grammar in
`aura graph build --help` is left to ride with the CLI-discoverability work
(#159), keeping this change decoupled from the deferred World/project-as-crate
layer.
Corpus refresh: the cycle-0088 fixture corpus replayed against the current
binary failed on two accumulated drifts. (1) `add`'s naming key was renamed
`as` -> `name` (3c4b667; `expose` keeps `as` as a real alias) — the inputs now
use `name` for `add` ops only. (2) The dataflow-cycle bug the 0088 fieldtest
found was fixed (
|
||
|
|
3f75d59598 |
audit(0090): cycle + C24 milestone close — fieldtest green; ledger + rm ephemeral spec/plan
Closes the cycle-0090 (#156) work and delivers the "Topology-as-data: blueprint serialization & loader (C24)" milestone. Cycle-0090 audit (architect drift review, range 7ad7f58..HEAD): drift-clean on substance. Tier-1 forward-tolerance is genuinely serde-default (deny_unknown_fields = 0 in every production struct), pinned at envelope + primitive across both the in-crate and public-seam tests; Tier-2 refusals real and green; no struct/signature/runtime change; the invariant-5 acyclicity lockstep (construction gate <-> bootstrap Kahn sort) undisturbed; invariant-9 resolver stays injected, no registry. The one medium item the architect flagged — the C24 Remaining block carried no deferral signal for #158/#159 — is fixed in this commit's ledger update. Milestone fieldtest (fieldtests/milestone-topology-as-data/, the close-gate evidence): GREEN, 0 behavioural bugs. A downstream consumer ran the full author -> serialize -> load -> construct -> introspect -> reproduce story from the public surface alone — round-trip bit-exact on both authoring surfaces (Rust builder + op-script CLI), build-free introspection, Tier-1/Tier-2 forward-compat by name, fail-fast diagnostics by identifier. Verified the headline claims myself (the two Rust binaries + the CLI build/diff + the fail-fast exits), not just the agent's report. Findings triaged to the forward queue (none blocking): op-script grammar undocumented + a stale cycle-0088 example (#163); canonical trailing-newline divergence + Composite Debug/PartialEq ergonomics (#164); CLI discoverability of build/introspect + no `graph run` (commented on #159); the newline as a content-addressing prerequisite (commented on #158). #158 (content-address topology in the manifest) and #159 (retire the hard-wired harnesses) were moved OUT of this milestone: both are premature until the World generates runs from blueprint-data (commit still fully identifies every hard-wired topology), so they belong to the project-as-crate / World cycle. The C24 ledger Status records the delivery and the deferral. Ephemeral cycle-0090 spec + plan removed per the lifecycle convention. The Gitea milestone container is closed on user ratification (this run tees up the close, does not click it). |
||
|
|
cdd2da6337 |
feat(0090): blueprint format forward-compat — Tier-1 tolerance pinned, two-tier discipline codified (closes #156)
The blueprint data format (C24) extends additively under one codified two-tier discipline: - Tier-1 (additive-optional): a new optional field/section is tolerated by an older reader (serde ignores unknown fields — no deny_unknown_fields), with no format_version bump; by C1 a new optional field defaults to prior behaviour, so an old blueprint reproduces the same graph. - Tier-2 (must-understand: a new node type, edge semantics, or structural-axis kind): bumps format_version, so an old reader refuses cleanly (LoadError::UnsupportedVersion / UnknownNodeType) rather than silently building a different graph. Most of #156 already shipped with #155 (cycle 0087): the envelope, omit-defaults canonical form, and both Tier-2 load-path refusals were present and green. This cycle pins the one previously-unproven property — Tier-1 forward-tolerance of an unknown optional field on the current loader — and codifies the discipline. Changes: - New characterization pin (in-crate, blueprint_serde.rs): unknown_optional_field_is_tolerated_byte_identically — an unknown optional key at doc and primitive level loads byte-identically and runs bit-identically. - Two public-seam E2E pins (blueprint_serde_e2e.rs, added by the E2E phase): unknown_envelope_field_tolerated_through_public_api and unknown_primitive_field_tolerated_through_public_api — split the two distinct tolerance surfaces (envelope vs primitive) across the World/cdylib crate boundary, where a deny_unknown_fields added to one would break forward-compat while leaving the in-crate test green. - LoadError::UnsupportedVersion doc reworded from the deferred "is #156" note to the settled two-tier discipline statement. - C24 ledger (docs/design/INDEX.md): Status codification sentence added; #156 dropped from Remaining (#158/#159 stay). Derived fork (recorded on #156): the per-section required-flag mechanism (PNG critical-vs-ancillary) is NOT built — the version envelope already gives the must-understand refusal at version granularity, no current Tier-2 section validates a finer scheme, and C1 holds either way. The pin is a characterization test (GREEN on first run) — it documents existing serde silent-ignore behaviour, no production code changed. Verified: cargo test -p aura-engine green (all targets, three new tests confirmed by name); cargo clippy --workspace --all-targets -- -D warnings clean. |
||
|
|
ead064df50 |
plan: 0090 blueprint forward-compat
Single-task iteration for #156: append the Tier-1 forward-tolerance characterization test (unknown_optional_field_is_tolerated_byte_identically), reword the LoadError::UnsupportedVersion doc to the settled two-tier discipline, and codify it in the C24 ledger (Status sentence + drop #156 from Remaining). No struct/signature/runtime change. refs #156 |
||
|
|
cb558519b0 |
spec: 0090 blueprint forward-compat two-tier discipline (boss-signed)
Iteration within the C24 topology-as-data milestone (#156). Codifies the blueprint format's additive forward-compatibility under one discipline: Tier-1 (additive-optional) = serde-default silent-ignore, no version bump, C1 default-equals-prior-behaviour; Tier-2 (must-understand: new node type, edge semantics, structural-axis kind) = bump format_version so an old reader refuses cleanly rather than building a different graph. Most of #156 already shipped with #155 (cycle 0087): the format_version envelope, omit-defaults canonical form, and both Tier-2 load-path refusals (LoadError::UnsupportedVersion / UnknownNodeType) are present and green. The genuine remainder is one unproven property — forward-tolerance of an unknown optional field on the current loader — plus codifying the discipline in the LoadError doc and the C24 ledger entry. Not a new mechanism. Derived fork recorded on #156: the per-section required-flag mechanism (PNG critical-vs-ancillary) is NOT built — the version envelope already gives the must-understand refusal at version granularity, there is no current Tier-2 section to validate a finer scheme against, and C1 holds either way. Boss-signed on a grounding-check PASS (all current-behaviour claims ratified by named green tests; the new Tier-1 pin correctly absent — this cycle's deliverable). refs #156 |
||
|
|
3c4b667955 |
feat: construction add names a node via name, mirroring the builder (#157)
The op-script authoring form is meant to be the Rust builder lifted into data —
every op is a 1:1 image of a GraphBuilder method. The one un-builder-ish key was
`add`'s `"as"`: the builder names a node with `.named("fast")`, so the data echo
is `"name"`, not the SQL-ish aliasing word `as`. Renamed the `add` wire key
`as -> name`.
`expose` keeps `as` — there it is a genuine alias (`expose bias.bias as bias`,
mirroring the builder's positional name arg). `source`/`input` keep their terse
verbs: those are plain shortenings of `source_role`/`input_role`, not a foreign
concept the way `as`-for-naming was.
CLI-side only: a one-attribute serde rename on the `OpDoc` Add DTO
(`#[serde(rename = "name")]`), since the engine `Op` is serde-free (the engine
field stays `as_name`, untouched). Updated the op-list test documents to the
`name` key (add ops only; expose's `as` left intact) and added an explicit pin
(`add_names_node_via_name_key`). The cycle-0088 fieldtest corpus
(fieldtests/cycle-0088-construction-op-script/*.json) is left on the old `as`
form as historical cycle-0088 evidence (it is not run by the suite).
Verified: full workspace suite + clippy green; `aura graph build` on a `name`-keyed
doc names the node and emits it in the #155 blueprint.
|
||
|
|
7ad7f58798 |
audit(0089): cycle close — record acyclicity lockstep + C24 ledger refresh; rm ephemeral spec/plan
Cycle-close audit for the /boss run that followed up the cycle-0088 construction fieldtest (#161 cycle-reject + #162 diagnostics-by-identifier). Regression gate: full workspace suite green (0 failed). Architect drift review (range 86841b0..HEAD): drift_found, two items, both documentation-side — the code is correct and green. - What holds: invariant 5 / C9 acyclicity (closes_cycle is a correct eager reachability gate, no false positive on a valid DAG); C24 no-second-validator (blueprint.rs untouched, finish() only translates the gates' returned CompileError); fieldtest corpus handled per convention. - Resolved (fix path, ledger): the C24 Status now enumerates the #161 eager acyclicity gate and captures the LOCKSTEP the architect flagged — closes_cycle (construction-time) and the bootstrap Kahn sort (harness.rs, BootstrapError::Cycle) are now two homes of invariant-5 that must co-evolve when the explicit delay/register node lands; plus a note that the holistic finalize faults now read by-identifier (#162) while still calling the unchanged gates. Ephemeral 0089 spec + plan git-rm'd per the active-cycle artefact lifecycle; the durable rationale is lifted to the ledger above. No code change in this commit. |
||
|
|
f1ab81d1b8 |
feat(0089): construction diagnostics read by-identifier (closes #162)
The cycle-0088 fieldtest found three presentation defects on the construction
op-script surface, all where the surface dropped out of its by-identifier register.
Presentation only — every fault still fires identically (same exit code, same
op/finalize attribution); only the rendered cause changes.
- Item 1 (finalize by-identifier). The holistic finalize fault leaked the raw
index Debug form (`UnconnectedPort { node: 2, slot: 1 }`). `GraphSession::finish()`
now translates the three reachable index-carrying CompileErrors into new
by-identifier OpError variants (UnconnectedPort{node,slot} / RoleKindMismatch{role}
/ UnboundRootRole{role}) using the session's `ids`/`schemas` and the composite's
`input_roles()` — the holistic gate calls (validate_wiring,
check_param_namespace_injective, check_root_roles_bound) stay byte-for-byte
unchanged (C24: no second validator; only the `.map_err` closures changed).
`aura graph build` now prints `finalize: slot sub.rhs is unconnected`.
- Item 2 (bind mismatch prose). `format_op_error`'s BadParam arm matches the
BindOpError variants instead of `{:?}`: `op 1 (add): param fast.length expects I64
but got F64`, matching the connect mismatch register.
- Item 3 (discoverable bind form). `introspect --node` shows the typed-Scalar bind
form: `param length:I64 (bind {"I64": <v>})`.
Item 1 spans both crates atomically (adding OpError variants forces the exhaustive
format_op_error match; the finish() translation flips behavioural test pins in both
crates). Five test touches: the two in-file unit tests, the two E2E twins plan-recon
found that the spec's testing strategy under-enumerated
(construction_e2e.rs, tests/graph_construct.rs), and a new unbound-root-role test;
the implementer added RoleKindMismatch / Ambiguous/UnknownParam coverage too. The
CLI finalize test was tightened (orchestrator) to pin `sub.rhs` and the absence of a
raw `node:` index.
Spec boss-signed on a grounding-check PASS (docs/specs+plans/0089). Verified: full
workspace suite + clippy green; the three messages reproduce exactly against the
built binary on the fieldtest fixtures.
|
||
|
|
c6c181f715 |
plan: 0089 construction diagnostics polish (refs #162)
Two tasks: item 1 (by-identifier finalize) lands atomically across both crates — three OpError variants + finish() translation + the CLI presenter arms + five test touches (two of them E2E twins plan-recon found that the spec's testing strategy under-enumerated: construction_e2e.rs and tests/graph_construct.rs); items 2 & 3 (bind-mismatch prose + discoverable bind form) are additive CLI changes. |
||
|
|
365f112451 |
spec: 0089 construction diagnostics polish (boss-signed) (refs #162)
Three presentation-only defects the cycle-0088 fieldtest found on the
construction op-script surface: the holistic finalize fault leaks raw machine
indices (UnconnectedPort { node: 2, slot: 1 }) where the by-identifier mapping
demonstrably exists; the bind-kind mismatch leaks a Debug struct; the typed-Scalar
bind form is invisible from introspect --node. Boss-signed on a grounding-check
PASS (every load-bearing assumption ratified by a currently-green test or the
defining code).
|
||
|
|
16520429be |
fix(0088): reject dataflow cycles in construction build (closes #161)
The construction op-script service accepted a dataflow cycle and exited 0,
emitting a non-DAG blueprint — violating domain invariant 5 / C9 (the graph is a
DAG; the only feedback path is an explicit delay/state node). The cycle-0088
fieldtest surfaced it (fieldtests/cycle-0088-construction-op-script/FINDINGS.md).
The construction gate set had no acyclicity check: a cyclic interior-edge set
passed both the eager per-op gates and the holistic finish, so replay() returned
Ok. Fix: an eager reachability check at the connect op that closes the cycle —
GraphSession::closes_cycle(from, to) asks "does the `to` node already reach the
`from` node through the edges added so far?" and rejects with a new by-identifier
OpError::WouldCycle { from, to } ("connecting from -> to would close a cycle"),
threaded through the CLI's exhaustive format_op_error. The fault is attributed to
the offending connect op, consistent with the surface's eager per-op diagnostics.
Eager rather than a holistic topological check at finish: a cycle is closed by
one specific connect, and naming that connect is the sharpest by-identifier error.
RED-first: two tests pin the symptom (a 2-cycle a<->b and a self-loop), both red
before the fix and green after; the 19 existing construction tests, the full
workspace suite, and clippy stay green.
Scope is the cycle only. The validity-floor cases the fieldtest also noted (an
unfed declared source role, an output-less graph) are degenerate-but-well-formed,
not invariant violations, and are deferred (refs #161) pending the build->consume
edge (#28) that defines what a valid emitted blueprint must guarantee.
|
||
|
|
985e129129 |
test(fieldtest): cycle 0088 construction op-script — downstream consumer pass
Exercise the construction op-script service (#157) purely as a downstream consumer authoring topology as data: discover-then-author an SMA-crossover bias, author-with-`--unwired`, and 15 error-ergonomics fixtures. Public interface only (the C24 ledger + the CLI's own output); no implementation source read. Confirmed working: discover→author round-trip, the `--unwired` by-identifier authoring aid, eager per-op diagnostics. Surfaced one bug + frictions, all reproduced and filed forward: - #161 (bug): `graph build` accepts a dataflow cycle — DAG invariant 5 unenforced; reproduced directly before filing. - #162: construction error/bind ergonomics (raw-index finalize, Debug-struct bind-mismatch, undiscoverable typed-Scalar bind). - #28: no CLI consumer for the emitted #155 blueprint (round-trip dead-ends). - #159: construction surface undiscoverable from the CLI usage/help. FINDINGS.md carries the full report + the triage table. The two 1.4 MB self-contained viewer HTML dumps from the round-trip check are dropped as bloat (the byte-identical result is recorded in FINDINGS). |
||
|
|
86841b0740 |
audit(0088): cycle close — drift fixes + C24 ledger refresh; close construction service
Architect drift review of cycle 0088 (#157, the introspectable fail-fast construction service: §A shared gate predicates, §B the GraphSession/Op/replay per-op surface + introspection, §C the aura graph build/introspect CLI). What holds (confirmed against the diff): no-second-validator (C24) — edge_kind_check is the single kind-check site called by both validate_wiring and GraphSession::connect, and validate_wiring / check_param_namespace_injective are reused verbatim in finish(); engine domain-free (invariant 9) — construction takes an injected Fn(&str)->Option<PrimitiveBuilder>, no registry, the closed match + std_vocabulary_types live in aura-std; topology-as-data / no DSL (C24/C17/inv 10) — the engine Op is serde-free, the OpDoc wire DTO is CLI-side, ops are static and non-Turing-complete; replay-equals-builder byte-identity (construction_e2e.rs) protects C9/C19/C23. Resolution: - fix (drift-med): the root-role-boundness gate was the one holistic check finish() re-implemented instead of sharing — extracted check_root_roles_bound (blueprint.rs) and called from BOTH compile_with_cells and finish(), so finish() now reuses ALL the holistic gates and the no-second-validator claim is literally true. Behaviour- preserving (same UnboundRootRole variant; unbound_root_role_is_rejected stays green). - fix (drift-med): removed the #![allow(dead_code)] on construction.rs — empirically unnecessary (the pub re-exported surface is reachable; clippy -D warnings green without it) — and its now-inaccurate comment (it claimed removal "when the consumer lands", but the consumer is a separate crate). Also tidied a stale graph_construct.rs module-doc line. - fix (ledger): C24 Status refreshed — #157 moved out of "Remaining" with a cycle-0088 realization note (the construction service: eager/holistic gate split, build-free introspection, emits the #155 blueprint); #159 reframed as paired with #157. - carry-on (debt-med, forward-noted): the std_vocabulary roster is now a third hand-kept copy (match + test list + std_vocabulary_types) and introspect --vocabulary escalates #160's gap to user-facing — noted on #160; still fails safe. - carry-on (scaling-low, forward-noted): the engine Op -> wire OpDoc direction is unguarded for future Op variants — noted on #156 (the format-extension track). No architect-sweep / regression script is declared in the project facts, so the suite is the gate: cargo test --workspace 51 suites green; clippy --all-targets -D warnings clean. Cycle drift-clean. Ephemeral cycle artifacts removed (lifecycle convention): docs/specs/0088-*, docs/plans/0088-*. closes #157 |
||
|
|
25e452aaf7 |
feat(0088): §C construction op-script CLI — aura graph build/introspect
Iteration-2 §C of the construction service (#157), the CLI shell over the iteration-1 engine core ( |
||
|
|
f271e40d17 |
plan: 0088 construction op-script — iteration 2 (§C CLI shell)
Iteration-2 tasks (9-12) appended to the cycle-0088 plan: the JSON op-list serde DTO (CLI-side, engine Op stays serde-free), `aura graph build` (replay -> emit #155 / fail fast at op N), `aura graph introspect` (--vocabulary / --node / --unwired), and an E2E suite driving the aura binary. All changes in aura-cli; the engine core ( |
||
|
|
27ac4dc537 |
feat(0088): §B construction op-script surface — GraphSession/Op/replay + introspection
Iteration-1 §B of the construction service (#157), on the §A shared predicates
(
|
||
|
|
ea1ca32dbd |
feat(0088): §A shared gate predicates — edge_kind_check, resolution helpers, try_bind
Iteration-1 §A of the construction service (#157): the surface-agnostic shared predicates the eager op-script path and the holistic finalize gates both call — no second validator (C24). - edge_kind_check (blueprint.rs): the per-edge producer/consumer kind check, lifted verbatim out of validate_wiring's edge loop into a pub(crate) fn that validate_wiring now calls — behaviour-preserving (same Bootstrap(KindMismatch) variant; the existing compile-time gate test stays green). - resolve_input_slot / resolve_output_field (builder.rs): the exactly-one-match name→index resolution extracted as pub(crate) fns over (&NodeSchema, &str), so the runtime-String op-script names share GraphBuilder's resolution; GraphBuilder delegates and maps to the unchanged BuildError variants. - try_bind + BindOpError (aura-core node.rs): the fallible Result twin of bind (bind keeps its panic contract and pinned messages verbatim; try_bind is a separate method reporting the same three conditions as values). - check_param_namespace_injective + validate_wiring widened to pub(crate) for the finalize-stage reuse by the upcoming GraphSession::finish (§B). Partial iteration: §B (the GraphSession/Op/replay surface + introspection) and the §A→§B integration land next (plan Tasks 4-8). compile_with_params / check_ports_connected are behaviourally unchanged. Full suite green; clippy clean. Plan correction folded in: Task 3's test originally referenced aura_std::Sma — infeasible inside aura-core (aura-std depends on aura-core; the reverse edge is a dependency cycle). Adapted to a local PrimitiveBuilder probe with identical assertions. refs #157 |
||
|
|
a5b887a955 |
plan: 0088 construction op-script — iteration 1 (engine core)
Iteration-1 plan for #157 §A+§B: the eager/holistic gate split (extract edge_kind_check + shared name-resolution helpers + try_bind, all reusing the engine's gates — no second validator), the GraphSession/Op/replay per-op surface, build-free unwired/vocabulary introspection, and the acceptance-1 replay-equals-GraphBuilder compile-identity test. The JSON op-list + CLI are iteration 2. Eight RED-first tasks; struct literals + filter strings verified against the current tree. refs #157 |
||
|
|
114fa3d718 |
spec: 0088 construction op-script (boss-signed)
The introspectable, fail-fast construction service (#157): a declarative, replayable by-identifier op-script that builds a runnable blueprint through validated ops and emits the #155 value, reusing the engine's existing gates (no second validator, C24). Surface-agnostic core = an eager/holistic gate split: the per-op-decidable checks (name resolution, edge kind-match, the >1-cover DoubleWiredPort arm, param bind) fire eagerly at the offending op; the only-at-end-decidable checks (0-cover UnconnectedPort totality, DuplicateParamPath injectivity, root-role boundness) stay holistic at finalize. Both cadences call the SAME extracted predicates. Plus build-free introspection over the closed std_vocabulary (enumerable companion) and a partial document's unwired slots. The JSON op-list + `aura graph build`/`introspect` CLI is a thin shell (iteration 2). Spec auto-signed under /boss on a grounding-check PASS (11/11 load-bearing current-behaviour assumptions ratified by named green tests). Derived sub-forks logged on the issue. refs #157 |
||
|
|
468fbae62b |
audit(0087): cycle close — drift-clean after C24/C9 realization note; rm ephemeral spec/plan
Architect drift review of cycle 0087 (#155, the C24 blueprint-serialization-and- loader first cut). What holds (confirmed against the diff): C17 / no-RustAst (the format carries only type identity + name + bound params + topology; the build closure is dropped and re-derived, no node logic in the data); invariant 9 / domain-free engine (injected resolver, the closed match in aura-std, engine lib deps aura-core + aura-analysis only — a compiled-in closed set, not a dynamic registry); C9 round-trip / C23 bootstrap untouched (loader's terminal step is the unchanged Composite::new -> bootstrap_with_params; validation deferred to the existing gate, not bypassed). Resolution: - fix (ledger): C24 Status refreshed from "unbuilt" to "first cut shipped" with a cycle-0087 realization note; C9's round-trips-both-ways refinement marked realised. The ledger no longer contradicts the code. - backlog (debt-med): the hand-written std_vocabulary match has no guard test that fails when a new zero-arg aura-std node lacks an arm — fails safe today (clean UnknownNodeType, never silent-wrong). Filed as #160. - carry-on (scaling): construction-arg builders + sinks excluded, so no real harness round-trips yet; harness retirement blocks on the construction + project-as-crate layers — already tracked #156/#157/#159. No architect-sweep / regression script is declared in the project facts, so the suite is the gate: cargo test --workspace 748 passed (737 -> 748 = the 11 new tests); clippy --all-targets -D warnings clean. Ephemeral cycle artifacts removed (lifecycle convention): docs/specs/0087-*, docs/plans/0087-*. |
||
|
|
d5602ec5ad |
feat(0087): blueprint serialization & loader — close the graph-as-data loop
C24 first cut (#155): a blueprint — the param-generic, named graph-as-data a Rust builder produces — is now a first-class serializable data value with a canonical, versioned format, and the engine has the missing load path (data -> blueprint -> FlatGraph), not only the Rust-builder construction path. What ships: - `blueprint_to_json` / `blueprint_from_json` in a new `aura-engine` blueprint_serde module: a faithful serde DTO projection (the build closures dropped; re-derived on load), top-level `format_version` envelope, canonical compact JSON (struct field order, defaults omitted via skip_serializing_if). - A resolver seam: the loader is generic over an injected `Fn(&str) -> Option<PrimitiveBuilder>`; the concrete closed `match` over the aura-std vocabulary lives in aura-std (`std_vocabulary`), never in the engine (the engine stays domain-free: lib deps aura-core + aura-analysis only, never the node-vocabulary crate). This is C24's compiled-in closed-set referenced by type identity, NOT a dynamic/marketplace node registry (domain invariant 9). - serde derives on the serialized plain types (Edge, Target, OutField, Role, BoundParam, ScalarKind); BoundParam additionally re-exported from aura-core's root (an additive fix the plan's file list missed). Load-bearing scope decisions (derived, logged on #155): - Sinks are excluded from the serialized blueprint — a recording sink captures an mpsc::Sender (runtime identity, not param/topology, C19 value-empty); sink addressing is the C18-registry / #101 concern. The round-trip test attaches identical sinks post-load to both twins. - Construction-arg builders (LinComb(arity), CostSum(n), SimBroker(pip), Session(..)) are out of the round-trippable set: their structural args are a C20 structural-axis concern the param-generic format does not yet encode; an absent type_id fails the load cleanly (UnknownNodeType), never a silent wrong graph. #155's vocabulary is the 22 zero-arg aura-std builders. Additively extensible later (#156). Orchestrator hardening on review: the serializer now emits bound params in ascending original-slot order (mirroring the loader), so the canonical form is bind-order-independent — a precondition for content-addressing (#158). Identity today (every #155 node has <=1 param); holds by construction for future multi-param nodes. Acceptance (all green): a serialized blueprint runs bit-identical (C1) to its Rust-built twin; serializer/loader are inverse (canonical idempotence, incl. a recursive nested composite); unknown-type and unsupported-version fail named, never panicking. cargo test --workspace 748 passed; clippy --all-targets -D warnings clean. closes #155 |
||
|
|
b2278538ab |
plan: 0087 blueprint serialization & loader
Five tasks for #155: serde derives on the serialized plain types; the closed aura-std std_vocabulary resolver (22 zero-arg builders); the DTO layer + canonical serializer + format_version envelope; the resolver-injected loader + typed LoadError; and the round-trip tests (canonical golden, named failures, bit-identical run vs Rust twin, idempotence, recursion). refs #155 |
||
|
|
ce86b4ec30 |
spec: 0087 blueprint serialization & loader (boss-signed)
The C24 first cut (#155): a stable, versioned, canonical serialization of a param-generic Composite blueprint plus the data -> blueprint -> FlatGraph loader, closing the graph-as-data loop. Format references nodes by compiled-in type identity over a closed vocabulary (no logic, non-Turing); the loader is generic over an injected resolver with the concrete aura-std vocabulary match living outside the engine (engine stays domain-free). Acceptance: a serialized blueprint runs bit-identical (C1) to its Rust-built twin. Signed under /boss on the Step-5 grounding-check PASS (all load-bearing assumptions ratified by currently-green tests). refs #155 |
||
|
|
f80571a46a |
docs(ledger): C24 — blueprint as serializable World-owned data; resolve #109
Settle the #109 fork as topology-as-data (game-engine principle, C16): node logic stays Rust (C17), topology becomes a serializable value the World owns, generates, structurally searches, and reproduces. New contract C24 + refinements to C9/C17/C18/C20/C21/C22; threads: #109 resolved -> C24. Format itself unbuilt (next brainstorm/milestone). refs #109 |
||
|
|
893698a1e6 |
audit(0086): cycle close — drift-clean; rm ephemeral spec/plan
Architect drift review (8d04a84..HEAD): clean, no drift/debt. What holds (verified against code, not asserted): - C10 cost contract preserved: the non-R-harness guard reads the *resolved* harness, so a `run` cost flag on sma/macd (incl. the implicit default) is exit-2 fail-loud, never a silent no-op; parse_nonneg_rate names the flag; the eight stage1-r cost goldens are byte-unchanged. - The three edited realization notes are grounded: C12 Arc-sharing → aura-ingest/src/lib.rs:316; aura-std "~30 modules" → 30 node files; C15 Session emits only bars_since_open, matching the quoted source wording. - project-layout.md rewrite complete: no residual exposure/realistic-broker. Non-actionable scaling note (architect): the guard hardcodes Stage1R as the sole R-harness, coupled to the "stage1-r only" note text — three sites move together if a second R-harness ever lands; not in plausible next scope. Regression gate: cargo test --workspace exit 0 (48 binaries, 737 passed, 0 failed); cargo clippy --workspace --all-targets -- -D warnings exit 0. No baseline moved → no ratify needed. cycle 0086 tidy (clean). Ephemeral spec/plan (docs/specs/0086, docs/plans/0086) removed per the ephemeral-artifact convention. |
||
|
|
d925a747cb |
feat(0086): cost-flag CLI ergonomics — units note, named diagnostics, non-R-harness guard
#153 (friction surfaced by the milestone-#148 close fieldtest). Three cost-flag fixes on `aura run`, all on the pure parse_run_args grammar: - Units discoverable: a COST_FLAGS_NOTE appended to the run usage + --help (price units, charged in R as cost/|entry-stop|, per-ENGINE-cycle carry, >= 0, stage1-r only). - A negative rate names the cause + flag ("<flag> must be non-negative, got <v>") via a factored parse_nonneg_rate helper, not a bare usage dump. - A cost flag on a non-R harness (sma/macd) is refused (exit 2, "cost flags require an R-evaluator harness (stage1-r)") instead of silently ignored — the named spec_gap, decided reject/fail-loud (refuse-don't-guess, recorded on #153), pinned by a new C10 ledger note. Internal RunArgs/RunData/HarnessKind gain #[derive(Debug)] (behaviour-neutral) so the pure parse_run_args unit tests can use expect_err. Verified independently: cargo test -p aura-cli green, the eight stage1-r cost goldens byte-unchanged; clippy -p aura-cli --all-targets -D warnings clean. Only the grammar/usage strings and the previously-unguarded sma-cost path changed; the cost-model graph and R math are untouched. closes #153 |
||
|
|
dfc01bf837 |
plan: 0086 cost-flag CLI ergonomics
Four tasks from spec 0086: (1) named non-negativity diagnostic via a parse_nonneg_rate helper + perturbed-test fix; (2) non-R-harness guard (the spec_gap, reject/exit-2); (3) COST_FLAGS_NOTE appended to the usage + --help surfaces; (4) the C10 ledger note + full-suite/clippy gate. Confined to crates/aura-cli; the eight stage1-r cost goldens stay byte-green. refs #153 |
||
|
|
f26b33f345 |
spec: 0086 cost-flag CLI ergonomics (boss-signed)
Settled design from #153 (fieldtest friction of milestone #148): make the `aura run` cost-flag surface honest — a units/constraints note in the usage, a named non-negativity diagnostic, and a refuse-don't-guess rejection of cost flags on a non-R harness (the spec_gap; decided reject/exit-2, recorded on #153). CLI-ergonomics + one C10 ledger note only; no cost-model/R-math change. Boss-signed: grounding-check PASS (independent fresh-context agent; 6/6 load-bearing assumptions ratified by currently-green tests). refs #153 |
||
|
|
dcf58c5d26 |
docs(project-layout): retire exposure/realistic-broker framing → bias/R/cost-model
The "day in the life" worked example was stale on the #117 (exposure→bias) and #116 (realistic broker retired → cost-model graph in R) reframes. Rewrite steps 3/4/7 to the live model: unsized bias stream → in-R risk-executor + R-evaluator (E[R]/SQN) → optional cost-model graph (net R = gross R − cost-in-R); money/real-broker pushed to the live deploy edge; the matrix axis swapped from the retired {sim-optimal, pepperstone} broker pair to a {fixed-stop, vol-stop} risk-executor axis. closes #151 |
||
|
|
d8946b1d7b |
docs(ledger): correct stale realization notes — C12 sharing, aura-std, C15 SessionNode
Three drift items surfaced by the 2026-06-29 design-goal audit, all recording shipped reality into the ledger (no contract change): - C12: cross-sim `Arc<[T]>` sharing is no longer "still open" — the sweep/MC/walk-forward families build members over one shared `Arc<DataServer>`/`FileCache`, so a window is parsed once and shared zero-copy across the disjoint sims (aura-ingest/src/lib.rs:316). - open-threads: `aura-std` is no longer "doc-only" — ~30 node modules. - C15: record that `Session` deliberately ships only `bars_since_open` (the node's own contract), the other two streams deferred (refs #154). |
||
|
|
8d04a845ee |
docs(glossary): align terminology with industry standard
Reconcile 68 terms against algotrading frameworks (LEAN, NautilusTrader, backtrader, VectorBT, Zipline), quant-validation literature (Van Tharp, Bailey & Lopez de Prado, White), and stream/dataflow vocabulary. Conservative pass: extend Avoid lists with industry synonyms/homonyms and fold short disambiguation notes into definitions; no canonical headings renamed. Touched 18 entries. Avoid additions: overfit probability (PBO/CSCV), signal (entry/exit signal, trade signal), position table (transactions, trade blotter), conviction-based risk allocation (risk budgeting/parity/ contribution), run registry (model registry), session node (session window), sign-agreement (market breadth). Disambiguation notes: broker vs fill/account simulator, edge (wiring/trading/deploy senses), cycle (clock step vs DAG loop), manifest vs Cargo.toml config, experiment vs MLflow container, run-count (version counter), bias vs statistical bias, bootstrap vs statistical bootstrap, deflated score anchored on the Deflated Sharpe Ratio, Monte-Carlo (input not trade sequence), World vs Unreal UWorld. Deferred (out of scope this pass): heading renames, a new `record` entry + composite sense-split, the playground egui->web wording, the SoA Avoid line. |
||
|
|
dff99c93e4 |
fieldtest(milestone): cost-model graph (#148) — capability delivered green
Milestone-close gate for "Cost-model graph (in R)" (#148). The fieldtester exercised the milestone capability end-to-end from the public CLI only (no implementation source), on the stage1-r harness, against ledger C10 + the glossary. Roll-up: friction_found — 0 capability bugs; the milestone promise is empirically delivered: - bare gross-R run is clean (net == gross, no cost forced); - per-trade cost: gross pinned, net drops strictly/monotonically, net_r_equity tap persists; - the capstone per-held-cycle carry BLEEDS the net-R curve continuously over a hold (the gross-net gap grows 0.367 -> 0.734 -> 1.101 -> 1.468 across one hold, vs the per-trade run's flat 0.367) — the holding-cost shape change, observable end-to-end; - composition is exact-additive (the composed drag equals the sum of the single-cost drags to the last ULP) and `aura chart` renders the real net_r_equity series. Evidence under fieldtests/milestone-cost-model-graph/ (run_scenarios.sh + captured_outputs.txt + traces/ + the charted bleed + FINDINGS.md). Non-blocking findings filed forward (none gates the close): - cost-flag CLI ergonomics — units hint, negative-rate diagnostic, non-R-harness no-op + a C10 spec_gap -> #153; - docs/project-layout.md describes the retired `aura backtest --broker` path and omits the cost flags -> folded into #151. refs #148 |
||
|
|
84ec2ab5d1 |
audit(0085): cycle close — drift-clean; C10 cycle-0085 realization note
Cycle 5 of milestone #148 (per-cycle-held accrual + CarryCost). Architect drift review over 39f9387..f5e00a9: status clean, no code drift. What holds (architect, evidence-of-review): - C11 byte-identity: the AtClose eval arm is the pre-cycle-5 tokens verbatim (if closed { per } / if open { per }, the per + cum lines unchanged), so the cycle-0083/0084 net_expectancy_r goldens (-614.3134020253314, -615.0304388396047) stay byte-identical and the AtClose unit regressions are untouched. - Accrual sound, no double-count: aura-analysis (summarize_r) is genuinely unchanged. During a hold the carry lives only in open_cost_in_r (cum=0); at close it moves to cum while open_cost->0 (open/closed mutually exclusive per cycle), so net_r_equity subtracts cum+open singly. summarize_r reads the close-row dumped total + the window-end accrued-so-far — one charge per trade, acc reset proven. The 3-field cost record's semantics generalize cleanly to accrual. - C9/C16/C23: the diff touches only aura-std + aura-cli; aura-engine stays domain-free. CarryCost is a CostNode factor, CostRunner a plain Node, composed via cost_graph/CostSum. label() carries its param. All three run_stage1_r call sites threaded; the negative-rate guard is symmetric with the sibling cost flags. Resolved this commit (the cycle-close ledger sync): - C10 realization note (cycle 0085) added under docs/design/INDEX.md — C10's "per-cycle-held factors accrue over the hold" clause is now first realized (the prior 0084 note covered the cost-graph composite-builder). Regression gate: cargo test --workspace (0 failures), cargo build --workspace, cargo clippy --workspace --all-targets -- -D warnings clean — the architect is the primary gate (no dedicated regression script). Ephemera (spec 0085 + plan 0085) git rm'd. Milestone "Cost-model graph (in R)" remains OPEN. refs #148 |
||
|
|
f5e00a9c72 |
feat(0085): per-cycle-held accrual — CarryCost + ChargeMode (approach B)
Cycle 5 of milestone #148 (cost-model graph in R): the per-cycle-held accrual mechanism — C10's "per-cycle-held factors accrue over the hold". A carry/funding cost is charged for every cycle a position is held, so the net_r_equity equity curve bleeds continuously over the hold (approach B, "ja, mach B") rather than stepping at close. Mechanism (logged on #148): ChargeMode { AtClose, PerHeldCycle } is a property of the cost factor, read by the one shared CostRunner (no second runner type). The AtClose arm is the pre-cycle-5 eval tokens VERBATIM (IEEE-754 byte-identity). The PerHeldCycle arm accrues `per` into `acc` each held cycle, dumps the accrued total into `cum` at close (resetting acc), and marks the open position via a growing open_cost_in_r. The bleed lives in open_cost_in_r, which the net_r_equity tap already subtracts — so summarize_r and the CLI net_eq wiring are UNCHANGED, and the cycle-0083/0084 net_expectancy_r goldens (-614.3134020253314 flat, -615.0304388396047 composed) + the C18 no-cost golden stay byte-identical. CarryCost is a ConstantCost twin differing only in charge_mode() -> PerHeldCycle (a labelled stress parameter, the flat base of the accrual family). Wired through the existing cost_graph/CostSum aggregation; a per-trade ConstantCost and a per-held-cycle CarryCost compose in one run (the costs sum per-field — the composed golden is exactly the sum of the two single-cost charges). New run-path --carry-per-cycle flag (sweep/walkforward/mc pass None, as the existing cost flags do). Tests: 2 RED-first unit B-proofs (open_cost grows over the hold, dumps the total at close, acc resets between trades — the discriminator a scalar net_expectancy_r cannot see); the CarryCost twin's 5 unit tests; 2 captured net_expectancy_r goldens (-768.2095026600887 carry, -1383.7939051991182 composed); a net_r_equity-bleeds-over- the-hold integration test (the terminal open hold's r_equity-net_r_equity gap strictly grows); plus negative-rate-refused-exit-2, monotone-in-rate, and zero-rate-exactly-free guards. Verified: cargo test --workspace (0 failures), cargo build --workspace, cargo clippy --workspace --all-targets -- -D warnings clean. summarize_r / aura-analysis untouched. Deferred to later #148 cycles (logged there): notional-based carry, the calendar-aware overnight swap, sweep-path cost. refs #148 |
||
|
|
2a8ee86489 |
plan: 0085 per-cycle-held accrual + CarryCost
Parent spec docs/specs/0085 (
|
||
|
|
19ba1ec978 |
spec: 0085 per-cycle-held accrual + CarryCost (boss-signed)
Cycle 5 of milestone #148 (cost-model graph in R): the per-cycle-held accrual mechanism — C10's "per-cycle-held factors accrue over the hold" — exercised by a constant per-held-cycle CarryCost node and a --carry-per-cycle CLI flag. Approach B (user-decided, "ja, mach B"): the headline net_r_equity curve bleeds continuously over each hold, not stepping at close. Mechanism (derived, logged on #148): the bleed lives in open_cost_in_r (grown each held cycle = accrued-so-far mark-to-market); cost_in_r dumps the accrued total into cum at close. The net_r_equity tap already subtracts both cum_cost_in_r and open_cost_in_r, so the curve bleeds with NO change to summarize_r or the CLI net_eq wiring — and the AtClose runner branch is kept verbatim, so every cycle-0083/0084 net_expectancy_r golden stays byte-identical. ChargeMode is a property of the factor read by the one shared CostRunner (no second runner type); CarryCost is a ConstantCost twin differing only in charge_mode() -> PerHeldCycle. Auto-signed under /boss on a grounding-check PASS (all 6 current-behaviour assumptions ratified against named green tests). Reference issue #148 carries the A/B fork (user decision), the minimal-scope decision (derived), and the mechanism refinement (derived). refs #148 |
||
|
|
39f9387c57 |
docs(glossary): add 'tap' — named recorded sink stream
Record-reality add: 'tap' is in consistent use across the code (ColumnarTrace.tap, the --tap flag, the equity/exposure/net_r_equity/ r_equity taps) and the design ledger, but had no glossary entry. The entry also draws the line the 'tap/sink' shorthand blurs: a sink is the recording-role node, a tap is the named stream it records. |
||
|
|
face1879a6 |
audit(0084): cycle close — drift-clean (code); C10 cycle-0084 note + doc fixes
Cycle 4 of milestone #148 (cost-graph composite-builder). Architect drift review over fc52b4f..d5c44dd: drift_found, every item dispositioned. What holds (architect, evidence-of-review): C16/C9 — cost_graph lives in aura-composites, the factors in aura-std, aura-engine stays domain-free; the composite is ordinary downstream nodes. C11 behaviour-preservation is structural, not just asserted — the composite inlines to the same flat fan-in as the deleted CLI block (identical node set/order, cost[k].field slot map, geometry fan, net_eq terms/signs, cost_rec cols), so the cycle-0083 net_expectancy_r goldens stay byte-identical. C23 — role/port names non-load-bearing; 4 fixtures pin the role-set + output triple. Resolved this commit: - [high] ledger C10: the cycle-0083 note's "Still deferred (decision E)" is removed (E shipped this cycle) and a cycle-0084 realization note added. - [medium] cost_graph .leak() provenance (aura-composites/src/lib.rs): the "risk_executor precedent" was imprecise — that .leak() lives in risk_executor's TEST (one-shot, leak-safe), not its production builder. Doc corrected: the leak is fine for one-shot run-path construction but must be interned (the COL_PORTS production pattern) before cost reaches the sweep path. - [low] cli_run.rs golden docstring cited the deleted `slot * COST_WIDTH + f` CLI wiring; updated to the cost_graph composite's per-node cost[k].<port> wiring. Deferred (tracked, not pending) -> #152: - [medium] the cost[k].<port> index-namespacing restated across CostSum / cost_graph / the CLI (a build-validated lockstep — a divergent name fails loudly at g.build(), NOT the silent positional kind 0083 collapsed), AND the per-build .leak() that becomes an allocation regression on the per-member sweep path. Both are harmless on the current run-only cost path; the proper fix is one sweep-safe single-source cost-port-name contract (interned), best built with the deferred sweep-cost cycle. Regression gate: cargo test --workspace (0 failures), clippy --workspace --all-targets -- -D warnings clean, cargo doc clean — the architect is the primary gate (no dedicated regression script). Ephemera (spec 0084 + plan 0084) git rm'd. Milestone "Cost-model graph (in R)" remains OPEN. refs #148 |
||
|
|
d5c44dd1ea |
feat(0084): cost-graph composite-builder
Cycle 4 of milestone #148 (Cost-model graph in R), decision E. New `cost_graph(Vec<PrimitiveBuilder>) -> Composite` in aura-composites: it fans the 4 PM-geometry inputs to N cost nodes, surfaces each node's extra inputs (discovered via schema introspection past GEOMETRY_WIDTH) as `cost[k].<port>` roles, sums them through CostSum, and exposes the 3-field aggregate. Replaces the CLI's manual slot-indexed cost-wiring + the hardcoded MAX_RUN_COST_NODES=2 cap with one principled composite of arbitrary arity. GEOMETRY_WIDTH re-exported from aura-std (first cross-crate consumer). Runtime port names .leak()'d (the risk_executor precedent), a bounded one-time cost at blueprint construction. Behaviour-preserving at the value level: the composite inlines at bootstrap (C11) to the same flat fan-in, so the two cycle-3 net_expectancy_r goldens (-614.3134020253314 flat, -615.0304388396047 composed), the C18 no-cost golden, and the full suite stay green verbatim. Honours C9 (a composite of cost nodes is ordinary downstream nodes), C16 (wiring lives in aura-composites, not aura-engine), C23 (label drift under cost_graph nesting is permitted; no with-cost graph label/shape golden exists). Four aura-composites unit tests pin the exposed contract: the two planned (n=2 heterogeneous role set; n=1 no-extra shape) plus two the implementer added that strengthen the headline — arbitrary-arity per-node namespacing (n=3, two VolSlippageCost -> distinct cost[1]/cost[2].volatility, the property that retires the 2-node cap) and geometry fan-once (n=2 extra-free -> only the 4 geometry roles). Accepted nit (held, non-gating): the CLI reconstructs the `cost[k].volatility` role name to feed the vol node's extra input — a string coupling to the composite's public role-naming convention. Kept: role-based composite wiring addresses roles by name (as the CLI already does for "closed"/"bias"/"price"); the convention is tested + build-validated; a decoupling accessor would widen this cycle's scope. Verified: cargo test --workspace (0 failures), clippy --workspace --all-targets -D warnings clean, cargo doc -p aura-composites clean. refs #148 |
||
|
|
550d5ce947 |
plan: 0084 cost-graph composite-builder
Two tasks: (1) the cost_graph(Vec<PrimitiveBuilder>) -> Composite builder in aura-composites + the GEOMETRY_WIDTH re-export from aura-std + two unit tests pinning the exposed input-role set and the 3-field output; (2) the aura-cli stage1_r_graph rewire onto cost_graph, deleting MAX_RUN_COST_NODES and COST_SUM_PORTS. Runtime port names .leak()'d (the risk_executor precedent). Behaviour-preserving: the cycle-3 net_expectancy_r goldens are the regression net. refs #148 |
||
|
|
9fb3d8b8ee |
spec: 0084 cost-graph composite-builder (boss-signed)
Cycle 4 of milestone #148 (Cost-model graph in R), decision E — the cost-graph composite-builder, recorded across cycles 2-3 as the natural next. Adds a `cost_graph(Vec<PrimitiveBuilder>) -> Composite` builder in aura-composites that fans the 4 PM-geometry inputs to N cost nodes, surfaces each node's extra inputs as `cost[k].<port>` roles (schema introspection past GEOMETRY_WIDTH), sums them via CostSum, and exposes the 3-field aggregate. Replaces the CLI's manual slot-indexed cost-wiring + the hardcoded MAX_RUN_COST_NODES=2 cap with one principled composite of arbitrary arity. Re-exports GEOMETRY_WIDTH from aura-std (first cross-crate consumer). Behaviour-preserving at the value level: the composite inlines at bootstrap (C11) to the same flat computation, so the two cycle-3 net_expectancy_r goldens, the C18 no-cost golden, and the full suite stay green verbatim. Routed spec-driven (specify direct-entry): settled in #148's scope + the mature aura-composites idiom + the CostNode contract. All four forks (composite API shape, extra-input namespacing, GEOMETRY_WIDTH visibility, CLI consumption) are derived decisions logged on #148; none hangs on pure user preference. Auto-signed under /boss on the Step-5 grounding-check PASS (every load-bearing current-behaviour assumption tied to a named green test or current source; no with-cost graph label/shape pin contradicts the C23-permitted label drift). refs #148 |
||
|
|
fc52b4fced |
audit(0083): cycle close — drift-clean (code); C10 cycle-0083 note + lib.rs doc
Architect drift review over 6c7f5dd..HEAD. No regression scripts in this project → the architect is the sole gate; verdict: shipped code byte-clean. What holds (verified against the diff): - C9 — a CostRunner<F> is a plain downstream Node; the two cost nodes are thin factors wired through the same cost_node_builder. No runtime sub-object. - C18 / byte-identity — the numerator/latched token form is preserved verbatim; the two new CLI goldens pin exact net_expectancy_r and pass; the no-cost golden is untouched. - C10 co-temporality + C23 + invariant-4 — the gate-on-PM-geometry-only rule (cold factor input → 0 cost, row still emits) is now centralized once in the runner; name() dropped cleanly (label() remains the non-load-bearing symbol); the 3-field triple is a single source (COST_FIELD_NAMES) read by both producers + CostSum + the CLI — the cycle-0082 by-convention lockstep is structurally gone. Resolution: - [fix] docs/design/INDEX.md C10 — added the cycle-0083 realization note (each prior cost cycle got one; the deferred general CostNode trait is now shipped and the lockstep eliminated). Ledger deferred-work tracking re-synced. - [fix] crates/aura-std/src/lib.rs:5 — module doc now names the CostNode/CostRunner authoring surface. - [carry-on, low debt] vol_slippage_cost.rs still declares its extra-input port twice (the cost_node_builder arg and the trait extra_inputs()); a clean unifier needs design thought (builder() is static, no factor instance) and is not worth forcing at cycle close. Documented here; agreement rests on the helper + a test + the harness debug-assert. Cycle 0083 ephemera removed (docs/specs/0083 + docs/plans/0083). Verified: cargo build/test --workspace clean (0 failures), clippy -D warnings clean, cargo doc -p aura-std clean (CostNode/CostRunner intra-doc links resolve). refs #148 |
||
|
|
6b53c239dd |
feat(0083): CostNode trait + shared cost-record contract
Lift the duplicated cost-node skeleton — shared verbatim by ConstantCost and VolSlippageCost and locked by convention against CostSum — into one abstraction: - A new aura-std/src/cost.rs owns the cost-record contract (COST_WIDTH, COST_FIELD_NAMES, GEOMETRY_WIDTH), the CostNode factor trait (one hook: cost_numerator, in price units), the generic CostRunner<F> adapter that holds the shared state (cum, out) and the co-temporality skeleton (geometry gating, numerator/latched R-normalization, closed/open charge, 3-field emit), and a cost_node_builder schema assembler. - ConstantCost and VolSlippageCost become thin CostNode factors; their new() returns CostRunner<Self>, so every existing call site and unit test binds transparently and stays green verbatim. - CostSum and main.rs drop their local triple consts for the shared COST_FIELD_NAMES — the cycle-2 audit-flagged by-convention 3-field lockstep is now a structural single-source contract (the four copies of the triple collapse to one). main.rs also reads COST_WIDTH in place of the literal slot stride. Behaviour-preserving: the builders emit unchanged schemas (same port names), so the wiring, the net_r_equity seam, and summarize_r are untouched; the numerator/latched token form is preserved verbatim (IEEE-754 byte-identity). The existing suite is the regression net — all green: the per-node unit tests pass verbatim (0.5/1.5, 0.375/1.375), the composition E2E exact, the C18 no-cost golden byte-identical. Two new CLI characterization goldens pin the exact net_expectancy_r of the flat and composed cost paths (the prior tests only asserted net < gross, which a numerator drift would pass silently). New cost.rs runner/contract tests + the HalfSpreadCost author doctest cover the new surface. Deviation from the plan: CostNode::name() was dropped (the plan over-specified it) — it is dead surface, nothing consumes it (CostRunner forwards label(); cost_node_builder takes the name as an explicit arg). Removed from the trait, both impls, the doctest, and the test stubs; build + suite + clippy green. Verified: cargo build --workspace --all-targets clean; cargo test --workspace 0 failures; cargo clippy --workspace --all-targets -- -D warnings clean; doctest green. refs #148 |
||
|
|
c787488e64 |
plan: 0083 cost-node trait + shared cost-record contract
6 tasks: (1) new cost.rs — CostNode trait + CostRunner<F> + cost_node_builder + shared COST_FIELD_NAMES/COST_WIDTH/GEOMETRY_WIDTH + runner tests + author doctest; (2-3) migrate ConstantCost/VolSlippageCost to thin factors; (4) CostSum reads the shared contract; (5) main.rs reads aura_std::COST_FIELD_NAMES; (6) workspace gate. Behaviour-preserving — the existing suite is the regression net. refs #148 |
||
|
|
16f4cbb548 |
spec: 0083 cost-node trait + shared cost-record contract (boss-signed)
Cycle 3 of the cost-model-graph milestone: lift the duplicated cost-node skeleton (shared verbatim by ConstantCost/VolSlippageCost, locked by convention against CostSum) into a CostNode factor trait + a generic CostRunner<F> adapter, with one source of truth for the 3-field cost record. Behaviour-preserving: same schemas, same wiring, byte-identical output; the existing suite is the regression net. Cost-graph composite-builder deferred (decision E). Grounding-check PASS (7/7 assumption groups against named green tests). Fork decisions logged on the reference issue. refs #148 |