Carry or content-address a generated run's topology in its manifest #158
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
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):
Depends on #155; adjacent to #156.
Grounding finding (specify, #158) — deferred to the World / project-as-crate cycle
A
/bossrun 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
FlatGraphand 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 aFlatGraphimperatively (crates/aura-cli/src/main.rs:119-156) andsim_optimal_manifest(:164-181) constructs the manifest with no blueprint in hand. Socommitstill 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
Compositeblueprint, 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 canonicalblueprint_to_jsonform (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.
Canonical-form prerequisite flagged by the 2026-06-30 milestone fieldtest (
fieldtests/milestone-topology-as-data/):aura graph buildappends a trailing newline that the libraryblueprint_to_jsonomits (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.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_jsonof the run's signal blueprint. The fixedStage-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 atopology_hashtoday. 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.
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 shippedaura 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 canonicalblueprint_to_jsonof the signal; landed cycle 0092). #158 adds a content-addressedblueprint 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_stage1rand is deliberately out of the round-trippable set (C24:a recording sink captures a runtime
mpsc::Sender; construction-arg builders are a C20concern). 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-1wrap_stage1rseam, re-bootstrap with themember'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 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 theop-script's canonical blueprint, the same value
aura runstamps astopology_hash(bothvia one shared
content_idprimitive). Verified live:graph introspect --content-idequals
sha256(graph build)for the SMA-cross op-script (bothe2be81b2…). Deterministicand distinguishes topologies; a malformed op-list fails cleanly (exit 2, no partial hash).
Finding: an op-script and the Rust
stage1_signalbuilder produce DIFFERENT canonicalforms (composite debug-name "graph" vs "stage1_signal", a named vs unnamed
Sub, anunbound vs bound
Bias.scale), so they are different topologies by the byte definition andget 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 reproduce3/3 bit-identical incl anopen-at-end member).