A node rename mints a fresh trace directory for a bit-identical run #354

Open
opened 2026-07-27 11:37:53 +02:00 by claude · 0 comments
Collaborator

Observation

Found by the #311 cycle-close field test, source-blind, against the built binary. Corpus: fieldtests/cycle-311-trace-identity/ (fixtures c311_1_spread.ops.json and c311_3b_spread_rename_nodes.ops.json).

Two blueprints identical in every respect except their node identifiers produce byte-identical recorded series but land in two trace directories:

fixture                  identity id (graph introspect --content-id F --identity-id)         handle
1_spread                 befa2062de57c0eb…                                                   spreadwatch-7958ba7c
3b_spread_rename_nodes   befa2062de57c0eb…  (same)                                           spreadwatch-6e269cb5

The recorded tap series compare byte-identical across the two addresses.

Cause, visible without reading source

RunManifest.params records node-qualified names, and the run-identity digest hashes the merged params/defaults vector. The two stored manifests differ in exactly that key:

spreadwatch-7958ba7c   [["fast.length",{"I64":2}], ["slow.length",{"I64":4}], ["bias.scale",{"F64":1.0}]]
spreadwatch-6e269cb5   [["quick.length",{"I64":2}], ["lazy.length",{"I64":4}], ["b.scale",{"F64":1.0}]]

#311's audit pass substituted blueprint_identity_json's debug-symbol-blind projection for topology_hash inside the digest, which is what makes a description-only edit converge. That substitution reaches one hashed field; the parameter vector re-admits the same names through another.

The fork

This is a design call, not a mechanical fix — two established positions in this repository disagree:

  • (a) The handle follows the record. manifest.params is part of what the run record describes, and two records that differ are two runs. Under this reading the behaviour is correct and #311's C22 clause is what needs narrowing (already done — see below).
  • (b) The handle follows #171's identity projection. blueprint_identity_json deliberately blanks bound-param names while keeping position, kind and value, i.e. the repository's own definition of blueprint identity says param names are not identity-bearing. Under this reading a run whose parameters differ only in name is one run, and the digest should hash the parameter vector name-blind.

Option (b) carries a mechanical trap worth stating up front: the vector is merged name-sorted, so dropping the names without also fixing the ordering would silently reorder values (fast/slow[2,4] but lazy/quick[4,2]). A name-blind digest must take its order from the blueprint's structural position, which #171's projection already preserves.

What was done in the #311 cycle

Nothing to the behaviour. C22's clause asserted the convergent reading outright ("two blueprints differing only in such names compute bit-identically, so one address is the correct answer") and was corrected to state what actually holds, naming this issue as the open fork. The description-only case, which does converge, is pinned by a test.

Severity is low in practice: it costs a duplicate directory for a bit-identical run after a rename, and nothing is lost or misread. It is filed because it is the last member of the class #311 set out to close — something that is not part of a run's identity reaching its address — and because a contract now points here for the answer.

## Observation Found by the #311 cycle-close field test, source-blind, against the built binary. Corpus: `fieldtests/cycle-311-trace-identity/` (fixtures `c311_1_spread.ops.json` and `c311_3b_spread_rename_nodes.ops.json`). Two blueprints identical in every respect except their node identifiers produce byte-identical recorded series but land in two trace directories: ``` fixture identity id (graph introspect --content-id F --identity-id) handle 1_spread befa2062de57c0eb… spreadwatch-7958ba7c 3b_spread_rename_nodes befa2062de57c0eb… (same) spreadwatch-6e269cb5 ``` The recorded tap series compare byte-identical across the two addresses. ## Cause, visible without reading source `RunManifest.params` records node-qualified names, and the run-identity digest hashes the merged `params`/`defaults` vector. The two stored manifests differ in exactly that key: ``` spreadwatch-7958ba7c [["fast.length",{"I64":2}], ["slow.length",{"I64":4}], ["bias.scale",{"F64":1.0}]] spreadwatch-6e269cb5 [["quick.length",{"I64":2}], ["lazy.length",{"I64":4}], ["b.scale",{"F64":1.0}]] ``` #311's audit pass substituted `blueprint_identity_json`'s debug-symbol-blind projection for `topology_hash` inside the digest, which is what makes a description-only edit converge. That substitution reaches one hashed field; the parameter vector re-admits the same names through another. ## The fork This is a design call, not a mechanical fix — two established positions in this repository disagree: - **(a) The handle follows the record.** `manifest.params` is part of what the run record describes, and two records that differ are two runs. Under this reading the behaviour is correct and #311's C22 clause is what needs narrowing (already done — see below). - **(b) The handle follows #171's identity projection.** `blueprint_identity_json` deliberately blanks bound-param names while keeping position, kind and value, i.e. the repository's own definition of blueprint identity says param names are not identity-bearing. Under this reading a run whose parameters differ only in name is one run, and the digest should hash the parameter vector name-blind. Option (b) carries a mechanical trap worth stating up front: the vector is merged **name-sorted**, so dropping the names without also fixing the ordering would silently reorder values (`fast`/`slow` → `[2,4]` but `lazy`/`quick` → `[4,2]`). A name-blind digest must take its order from the blueprint's structural position, which #171's projection already preserves. ## What was done in the #311 cycle Nothing to the behaviour. C22's clause asserted the convergent reading outright ("two blueprints differing only in such names compute bit-identically, so one address is the correct answer") and was corrected to state what actually holds, naming this issue as the open fork. The description-only case, which does converge, is pinned by a test. Severity is low in practice: it costs a duplicate directory for a bit-identical run after a rename, and nothing is lost or misread. It is filed because it is the last member of the class #311 set out to close — something that is not part of a run's identity reaching its address — and because a contract now points here for the answer.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: Brummel/Aura#354