Carry or content-address a generated run's topology in its manifest #158

Closed
opened 2026-06-29 12:59:09 +02:00 by Brummel · 5 comments
Owner

C18 reproducibility under C24 (docs/design/INDEX.md): RunManifest (crates/aura-engine/src/report.rs) identifies a run's topology today only via commit (this engine + a hand-coded harness). That suffices while harnesses are a finite hand-coded menu. Once the World generates or structurally searches topologies (C21/C24), commit no longer identifies the graph, so a generated run is not reproducible from its manifest — a C18 violation.

Goal: the manifest carries or content-addresses the topology-data, keeping the manifest the full re-derivation recipe (C18, "reproducible from a recorded manifest"). This pulls the previously-deferred content-addressed-identity non-goal forward (named in docs/design/INDEX.md under C18 Non-goals).

Requires the canonical, omit-defaults serialization from #155, so a logically-identical blueprint hashes stably across Tier-1 format additions (an absent optional must not change the content id) — the canonical form is shared with the forward-compat work #156.

Acceptance (validated property):

  • Two command paths that build the same topology produce the same content id.
  • A serialized manifest re-derives the same FlatGraph and a bit-identical run (C1).
  • A Tier-1 format addition the blueprint does not use leaves its content id unchanged.

Depends on #155; adjacent to #156.

C18 reproducibility under C24 (docs/design/INDEX.md): RunManifest (crates/aura-engine/src/report.rs) identifies a run's topology today only via commit (this engine + a hand-coded harness). That suffices while harnesses are a finite hand-coded menu. Once the World generates or structurally searches topologies (C21/C24), commit no longer identifies the graph, so a generated run is not reproducible from its manifest — a C18 violation. Goal: the manifest carries or content-addresses the topology-data, keeping the manifest the full re-derivation recipe (C18, "reproducible from a recorded manifest"). This pulls the previously-deferred content-addressed-identity non-goal forward (named in docs/design/INDEX.md under C18 Non-goals). Requires the canonical, omit-defaults serialization from #155, so a logically-identical blueprint hashes stably across Tier-1 format additions (an absent optional must not change the content id) — the canonical form is shared with the forward-compat work #156. Acceptance (validated property): - [ ] Two command paths that build the same topology produce the same content id. - [ ] A serialized manifest re-derives the same FlatGraph and a bit-identical run (C1). - [ ] A Tier-1 format addition the blueprint does not use leaves its content id unchanged. Depends on #155; adjacent to #156.
Brummel added this to the Topology-as-data: blueprint serialization & loader (C24) milestone 2026-06-29 12:59:09 +02:00
Brummel added the feature label 2026-06-29 12:59:09 +02:00
Author
Owner

Grounding finding (specify, #158) — deferred to the World / project-as-crate cycle

A /boss run on the C24 milestone grounded this issue against the current code before producing a spec. The grounding changes #158's readiness: it is premature now, coupled to the same missing substrate as #159, and is deferred rather than specced this cycle. Recording the finding so the forward queue stays honest.

The problem #158 solves does not arise yet. Acceptance (2) — "a serialized manifest re-derives the same FlatGraph and a bit-identical run" — matters only once a run's topology is a generated data value. Today every topology is hard-wired: the CLI harnesses build a FlatGraph imperatively (crates/aura-cli/src/main.rs:119-156) and sim_optimal_manifest (:164-181) constructs the manifest with no blueprint in hand. So commit still fully identifies a run's topology (re-derivation today = check out the commit, run the same hard-wired harness). #158's own premise is that this breaks once the World generates or structurally searches topologies (C21/C24) — which does not exist yet. Building manifest-reproducibility for generated topologies before any run is generated from a blueprint is solving a not-yet-existing problem.

Coupling. #158 (in full) therefore depends on a blueprint-based run path — a run built from a serializable Composite blueprint, which the project-as-crate / World layer introduces. That is the same substrate #159 waits on (retiring the imperative harnesses, paired with #157's data-authoring surface). #158 and #159 are one deferred tail of the milestone, not two independent items.

The buildable slice was weighed and declined. The one part not coupled to the missing substrate is a content-addressing primitive — blueprint_content_id(&Composite) = sha256 of the canonical blueprint_to_json form (research-side, aura-registry, sha2; off the frozen engine, invariant 8). It satisfies acceptance (1) (same topology → same id) and (3) (Tier-1-stable, composing with #156). It is not built this cycle: it fails the project's feature-acceptance criterion's "measurably improves correctness / removes redundancy" arm — its consumers (manifest reproducibility here; sweep-invariant-subgraph dedup, C11/C12) are all in the next cycle, so it would be a consumer-less primitive (the speculative abstraction the project avoids, cf. main.rs:104). The sha256-of-canonical-form design is recorded here so the next cycle can lift it directly.

Net. The milestone's buildable, criterion-meeting work is complete: the round-trippable format (#155), the construction service (#157), and the forward-compat two-tier discipline (#156, cycle 0090). The reproducibility/cleanup tail (#158, #159) is correctly deferred to the World / project-as-crate cycle. Suggest #158 and #159 move to that milestone when it is seeded.

## Grounding finding (specify, #158) — deferred to the World / project-as-crate cycle A `/boss` run on the C24 milestone grounded this issue against the current code before producing a spec. The grounding changes #158's readiness: it is **premature now**, coupled to the same missing substrate as #159, and is deferred rather than specced this cycle. Recording the finding so the forward queue stays honest. **The problem #158 solves does not arise yet.** Acceptance (2) — "a serialized manifest re-derives the same `FlatGraph` and a bit-identical run" — matters only once a run's topology is a *generated* data value. Today every topology is hard-wired: the CLI harnesses build a `FlatGraph` imperatively (`crates/aura-cli/src/main.rs:119-156`) and `sim_optimal_manifest` (`:164-181`) constructs the manifest with no blueprint in hand. So `commit` still fully identifies a run's topology (re-derivation today = check out the commit, run the same hard-wired harness). #158's own premise is that this breaks **once the World generates or structurally searches topologies (C21/C24)** — which does not exist yet. Building manifest-reproducibility for generated topologies before any run is generated from a blueprint is solving a not-yet-existing problem. **Coupling.** #158 (in full) therefore depends on a blueprint-based run path — a run built *from* a serializable `Composite` blueprint, which the project-as-crate / World layer introduces. That is the same substrate #159 waits on (retiring the imperative harnesses, paired with #157's data-authoring surface). #158 and #159 are one deferred tail of the milestone, not two independent items. **The buildable slice was weighed and declined.** The one part not coupled to the missing substrate is a content-addressing primitive — `blueprint_content_id(&Composite)` = sha256 of the canonical `blueprint_to_json` form (research-side, `aura-registry`, `sha2`; off the frozen engine, invariant 8). It satisfies acceptance (1) (same topology → same id) and (3) (Tier-1-stable, composing with #156). It is **not** built this cycle: it fails the project's feature-acceptance criterion's "measurably improves correctness / removes redundancy" arm — its consumers (manifest reproducibility here; sweep-invariant-subgraph dedup, C11/C12) are all in the next cycle, so it would be a consumer-less primitive (the speculative abstraction the project avoids, cf. `main.rs:104`). The sha256-of-canonical-form design is recorded here so the next cycle can lift it directly. **Net.** The milestone's buildable, criterion-meeting work is complete: the round-trippable format (#155), the construction service (#157), and the forward-compat two-tier discipline (#156, cycle 0090). The reproducibility/cleanup tail (#158, #159) is correctly deferred to the World / project-as-crate cycle. Suggest #158 and #159 move to that milestone when it is seeded.
Brummel removed this from the Topology-as-data: blueprint serialization & loader (C24) milestone 2026-06-30 14:14:02 +02:00
Author
Owner

Canonical-form prerequisite flagged by the 2026-06-30 milestone fieldtest (fieldtests/milestone-topology-as-data/): aura graph build appends a trailing newline that the library blueprint_to_json omits (648 vs 647 bytes, content character-identical). A content hash of the same blueprint would therefore differ by which surface emitted it — so the two emit paths must be made byte-identical and the trailing-newline rule stated before topology content-addressing lands here. Tracked in #164.

Canonical-form prerequisite flagged by the 2026-06-30 milestone fieldtest (`fieldtests/milestone-topology-as-data/`): `aura graph build` appends a trailing newline that the library `blueprint_to_json` omits (648 vs 647 bytes, content character-identical). A content hash of the same blueprint would therefore differ by which surface emitted it — so the two emit paths must be made byte-identical and the trailing-newline rule stated before topology content-addressing lands here. Tracked in #164.
Brummel added this to the World/C21: run + orchestrate harness families from blueprint-data milestone 2026-06-30 18:02:08 +02:00
Author
Owner

Scope note from cycle 0092: topology_hash currently covers the SIGNAL only

The cycle-0092 run-from-blueprint work (#165, shipped) landed RunManifest.topology_hash
= SHA256 of the canonical blueprint_to_json of the run's signal blueprint. The fixed
Stage-1-R scaffolding (broker / sinks / RiskExecutor / cost-graph) is NOT in the hash — it
is identified by commit. So two runs differing only in scaffolding / stop / cost share a
topology_hash today. This is correct for cycle 1 (the scaffolding is fixed).

For this issue's full content-addressed reproduction — and once #166 (families) varies
harness-structural axes — the content-id must cover the scaffolding / structural-axis
variants, not just the signal, or a generated run's topology will not be uniquely
identified by its manifest (the C18 property this issue exists to restore). Recorded so the
#158 cycle scopes the hash domain deliberately (signal-only vs. whole-harness vs.
structural-axis-aware). Surfaced by the cycle-0092 architect drift review.

## Scope note from cycle 0092: topology_hash currently covers the SIGNAL only The cycle-0092 run-from-blueprint work (#165, shipped) landed `RunManifest.topology_hash` = SHA256 of the canonical `blueprint_to_json` of the run's **signal** blueprint. The fixed Stage-1-R scaffolding (broker / sinks / RiskExecutor / cost-graph) is NOT in the hash — it is identified by `commit`. So two runs differing only in scaffolding / stop / cost share a `topology_hash` today. This is correct for cycle 1 (the scaffolding is fixed). For this issue's **full** content-addressed reproduction — and once #166 (families) varies harness-structural axes — the content-id must cover the scaffolding / structural-axis variants, not just the signal, or a generated run's topology will not be uniquely identified by its manifest (the C18 property this issue exists to restore). Recorded so the #158 cycle scopes the hash domain deliberately (signal-only vs. whole-harness vs. structural-axis-aware). Surfaced by the cycle-0092 architect drift review.
Author
Owner

Cycle entry + derived fork decisions (specify, #158)

A /boss run on the World/C21 milestone is taking #158 as the next cycle. Recording
the fork decisions derived before spec production, and reconciling the earlier deferral.

The 2026-06-30 deferral is superseded. The earlier grounding finding on this issue
deferred #158 as premature, coupled to a missing substrate — "a run built from a
serializable Composite blueprint." That substrate now exists: cycle 0092 shipped
aura run <blueprint.json> (#165) and cycle 0093 shipped aura sweep <blueprint.json>
over named axes (#166). Sweep members are now generated runs built from a loaded
blueprint, so reproducing a generated run from its manifest is a present, real need
rather than a not-yet-existing problem. #158 is in scope for this cycle.

Fork 1 — carry vs content-address the topology-data. Decision: content-address
(derived). The manifest already carries topology_hash (SHA256 of the canonical
blueprint_to_json of the signal; landed cycle 0092). #158 adds a content-addressed
blueprint store: the canonical blueprint JSON is written once, keyed by its
topology_hash, beside the run registry (off the frozen engine, invariant 8).
Re-derivation reads the hash from the manifest, loads the stored blueprint, and
re-bootstraps. Rationale: content-addressing keeps the manifest tiny (C18) and dedups one
topology across a whole sweep family (one stored blueprint for N members sharing a
topology — the C11/C12 sweep-invariant-subgraph direction), where carrying the blueprint
inline would duplicate it per member and fight that dedup. The ledger's C18 refinement
(2026-06-29) names content-addressed identity as the natural home for a generated
topology's identity.

Fork 2 — hash domain: signal-only vs whole-harness. Decision: signal-only this
cycle
(forced + derived). The content-id covers the signal blueprint only; the
Stage-1-R scaffolding (broker / sinks / RiskExecutor / cost-graph) is identified by
commit, as today. Rationale: the scaffolding is not yet blueprint-data — it is built
imperatively by wrap_stage1r and is deliberately out of the round-trippable set (C24:
a recording sink captures a runtime mpsc::Sender; construction-arg builders are a C20
concern). A content-id cannot cover data that is not data. Whole-harness /
structural-axis-aware content-addressing is deferred until the scaffolding becomes
blueprint-data (project-as-crate / #156 / #159). The boundary is documented so a reader
knows two runs differing only in scaffolding share a content-id today — correct while the
scaffolding is fixed.

Reproduction surface. Acceptance (2) is realized as a reproduce path over the family
store: for a persisted member, load the stored blueprint by its manifest's
topology_hash, re-wrap through the cycle-1 wrap_stage1r seam, re-bootstrap with the
member's params / window / seed, re-run, and assert the re-run metrics are bit-identical
to the stored metrics (C1). Proven on synthetic data (deterministic); recorded-dataset
reproduction rides the DataServer seam (#124), not this cycle.

Acceptance (1) (two command paths -> same content id) and (3) (a Tier-1 format addition
leaves the content id unchanged) are largely already true post-#164/#156 and are pinned
as #158-context tests.

## Cycle entry + derived fork decisions (specify, #158) A /boss run on the World/C21 milestone is taking #158 as the next cycle. Recording the fork decisions derived before spec production, and reconciling the earlier deferral. **The 2026-06-30 deferral is superseded.** The earlier grounding finding on this issue deferred #158 as premature, coupled to a missing substrate — "a run built from a serializable Composite blueprint." That substrate now exists: cycle 0092 shipped `aura run <blueprint.json>` (#165) and cycle 0093 shipped `aura sweep <blueprint.json>` over named axes (#166). Sweep members are now *generated* runs built from a loaded blueprint, so reproducing a generated run from its manifest is a present, real need rather than a not-yet-existing problem. #158 is in scope for this cycle. **Fork 1 — carry vs content-address the topology-data.** Decision: **content-address** (derived). The manifest already carries `topology_hash` (SHA256 of the canonical `blueprint_to_json` of the signal; landed cycle 0092). #158 adds a content-addressed blueprint store: the canonical blueprint JSON is written once, keyed by its `topology_hash`, beside the run registry (off the frozen engine, invariant 8). Re-derivation reads the hash from the manifest, loads the stored blueprint, and re-bootstraps. Rationale: content-addressing keeps the manifest tiny (C18) and dedups one topology across a whole sweep family (one stored blueprint for N members sharing a topology — the C11/C12 sweep-invariant-subgraph direction), where carrying the blueprint inline would duplicate it per member and fight that dedup. The ledger's C18 refinement (2026-06-29) names content-addressed identity as the natural home for a generated topology's identity. **Fork 2 — hash domain: signal-only vs whole-harness.** Decision: **signal-only this cycle** (forced + derived). The content-id covers the signal blueprint only; the Stage-1-R scaffolding (broker / sinks / RiskExecutor / cost-graph) is identified by commit, as today. Rationale: the scaffolding is not yet blueprint-data — it is built imperatively by `wrap_stage1r` and is deliberately out of the round-trippable set (C24: a recording sink captures a runtime `mpsc::Sender`; construction-arg builders are a C20 concern). A content-id cannot cover data that is not data. Whole-harness / structural-axis-aware content-addressing is deferred until the scaffolding becomes blueprint-data (project-as-crate / #156 / #159). The boundary is documented so a reader knows two runs differing only in scaffolding share a content-id today — correct while the scaffolding is fixed. **Reproduction surface.** Acceptance (2) is realized as a reproduce path over the family store: for a persisted member, load the stored blueprint by its manifest's `topology_hash`, re-wrap through the cycle-1 `wrap_stage1r` seam, re-bootstrap with the member's params / window / seed, re-run, and assert the re-run metrics are bit-identical to the stored metrics (C1). Proven on synthetic data (deterministic); recorded-dataset reproduction rides the DataServer seam (#124), not this cycle. Acceptance (1) (two command paths -> same content id) and (3) (a Tier-1 format addition leaves the content id unchanged) are largely already true post-#164/#156 and are pinned as #158-context tests.
Author
Owner

Cycle 0094 acc-1 realization + finding

Acceptance (1) — "two command paths that build the same topology produce the same content
id" — is realized via aura graph introspect --content-id: it prints SHA256 (hex) of the
op-script's canonical blueprint, the same value aura run stamps as topology_hash (both
via one shared content_id primitive). Verified live: graph introspect --content-id
equals sha256(graph build) for the SMA-cross op-script (both e2be81b2…). Deterministic
and distinguishes topologies; a malformed op-list fails cleanly (exit 2, no partial hash).

Finding: an op-script and the Rust stage1_signal builder produce DIFFERENT canonical
forms (composite debug-name "graph" vs "stage1_signal", a named vs unnamed Sub, an
unbound vs bound Bias.scale), so they are different topologies by the byte definition and
get different content ids. Content-addressing keys on the byte-canonical form, which
currently includes the composite debug-name (a non-load-bearing symbol, invariant 11).
Whether the content id should exclude the debug-name (a topology-canonical form) is filed
forward as issue #171 — it would change the shipped cycle-0092 topology_hash values, so it
is not this cycle.

Acceptance (2) (reproduce, iteration 1) and (3) (Tier-1 id stability) are green. #158's
acceptance is met in its byte-canonical realization; the reproduce path is verified live
(aura sweep -> one shared stored blueprint -> aura reproduce 3/3 bit-identical incl an
open-at-end member).

## Cycle 0094 acc-1 realization + finding Acceptance (1) — "two command paths that build the same topology produce the same content id" — is realized via `aura graph introspect --content-id`: it prints SHA256 (hex) of the op-script's canonical blueprint, the same value `aura run` stamps as `topology_hash` (both via one shared `content_id` primitive). Verified live: `graph introspect --content-id` equals `sha256(graph build)` for the SMA-cross op-script (both `e2be81b2…`). Deterministic and distinguishes topologies; a malformed op-list fails cleanly (exit 2, no partial hash). Finding: an op-script and the Rust `stage1_signal` builder produce DIFFERENT canonical forms (composite debug-name "graph" vs "stage1_signal", a named vs unnamed `Sub`, an unbound vs bound `Bias.scale`), so they are different topologies by the byte definition and get different content ids. Content-addressing keys on the byte-canonical form, which currently includes the composite debug-name (a non-load-bearing symbol, invariant 11). Whether the content id should exclude the debug-name (a topology-canonical form) is filed forward as issue #171 — it would change the shipped cycle-0092 topology_hash values, so it is not this cycle. Acceptance (2) (reproduce, iteration 1) and (3) (Tier-1 id stability) are green. #158's acceptance is met in its byte-canonical realization; the reproduce path is verified live (`aura sweep` -> one shared stored blueprint -> `aura reproduce` 3/3 bit-identical incl an open-at-end member).
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: Brummel/Aura#158