From 30b79d6cd0afe7e258aaee06657ea2d6ddb4464a Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Mon, 21 Sep 2026 18:55:57 +0000 Subject: [PATCH 1/2] One plan doc asserted that no SHA-256 computation exists in .dag; it does, and the real blocker is a different one docs/plans/dag-native-scm-design.md section 5's "Verified:" paragraph and open question 2 both say no SHA-256 computation exists in .dag, with "std.content_hash sha256_hex_digest and extdeps.crypto.hash sha256_digest validate hex; they do not hash bytes". That was true when written and is not now: extdeps.crypto.sha2 computes SHA-256 in the substrate (sha256, sha256_hex, FIPS 180-4), witnessed by test.claim.sha256_fips_witness. Why that witness is evidence rather than a restatement of the type, since it is the part easiest to get wrong: sha2 never relies on the type to wrap. Every 32-bit operation routes through std.bitwise, whose word32_add takes the modulus explicitly, so the interpreter's unbounded-Int evaluation yields the same residues and a wrong wrap changes the digest. Cite it for the computation, never as evidence that UInt32 wraps. The dissolve-on condition was "a computing cryptographic digest reachable from .dag", which is now half met, so it is restated as what remains rather than deleted: v2.std.node Hash minted from a cryptographic family. std.fabric_storage's refs are being moved onto the pure kernel in gunbc#11996, and that PR's reason for refusing the shell-out arm is recorded here because this note would otherwise invite it -- fabric_object_preimage produces bytes IN MEMORY, so a shell transport over a file path costs a temp-file write per object, which manufactures the custody gap that verification exists to close. SCOPE NOTE: the matching stale bullet in docs/plans/fabric-storage.md is deliberately NOT touched here. gunbc#11996 is already editing that file and is the authority for the fabric half, so correcting it in two PRs would be the fork DESIGN section 3 forbids. Co-Authored-By: Claude Opus 5 (1M context) --- docs/plans/dag-native-scm-design.md | 39 +++++++++++++++++++++++------ 1 file changed, 32 insertions(+), 7 deletions(-) diff --git a/docs/plans/dag-native-scm-design.md b/docs/plans/dag-native-scm-design.md index f0a83da258d..a6b78a2dc15 100644 --- a/docs/plans/dag-native-scm-design.md +++ b/docs/plans/dag-native-scm-design.md @@ -177,13 +177,34 @@ independently authored work has always addressed. Gone is everything around it: history, working-tree alignment, rebasing, and cloning. **Identity is currently weaker than the model needs.** *Verified:* `v2.std.node` `Hash` is -`Fnv1a64Structural` — 64-bit, non-cryptographic — and no SHA-256 *computation* exists in `.dag` +`Fnv1a64Structural` — 64-bit, non-cryptographic. A 64-bit non-cryptographic digest is a **locator, +not a durable intersubjective identity**, and adding a host builtin is closed because DESIGN freezes +the v1 seed's growth surfaces. **Declared rung:** the first slice uses the available digest and +states this limitation rather than implying cross-party agreement it cannot support. + +**Corrected 2026-09-21 — the dissolve-on condition has been half met, and the half that remains is a +different one.** This paragraph said "no SHA-256 *computation* exists in `.dag` (`std.content_hash` `sha256_hex_digest` and `extdeps.crypto.hash` `sha256_digest` validate hex; they -do not hash bytes). A 64-bit non-cryptographic digest is a **locator, not a durable intersubjective -identity**, and adding a host builtin is closed because DESIGN freezes the v1 seed's growth -surfaces. **Declared rung:** the first slice uses the available digest and states this limitation -rather than implying cross-party agreement it cannot support. **Dissolve-on:** a computing -cryptographic digest reachable from `.dag`. +do not hash bytes)". That was true when written. `extdeps.crypto.sha2` now computes SHA-256 in the +substrate (`sha256`, `sha256_hex`, FIPS 180-4), witnessed by `test.claim.sha256_fips_witness` — and +the witness discriminates rather than restating the type, because `sha2` routes every 32-bit +operation through `std.bitwise`, whose `word32_add` takes the modulus explicitly, so the +interpreter's unbounded-`Int` evaluation yields the same residues and a wrong wrap changes the +digest. + +What has **not** happened is the migration: `extdeps.crypto.sha2`'s only importers are +`extdeps.crypto.nist_p256` and its own witness. `std.content_hash` does not import it, so +`v2.std.node` `Hash` and `std.fabric_storage`'s object refs still mint through +`content_hash_of_value`. **Revised dissolve-on:** `v2.std.node` `Hash` minted from a cryptographic +family. `std.fabric_storage`'s object refs are being moved onto the pure kernel in gunbc#11996 — +the shell-out alternative was refused there for a structural reason worth recording, since it is the +one this note would otherwise invite: `fabric_object_preimage` produces bytes **in memory**, so a +shell transport over a file path means a temp-file write per object, which manufactures the custody +gap (hash one file, store another) that verification exists to close. `v2.std.node` is the half that +remains, and it is gated on native emission of the `sha2` closure — blocked by +`gunbc.recurring_failure_mode` `bounded_natural_arithmetic_evaluated_as_unbounded_int`, whose +prerequisite is `MachineWidth` reified as a value. Both halves are owned by the lane holding +`#11819`; open question 2 below is narrowed accordingly rather than closed. ## 6. Confidentiality @@ -506,7 +527,11 @@ operator decision, not this note's. 1. **Authoring capture.** The largest fork, and the reason §7 is scoped as it is. Until an authoring surface records what an author *did*, proposals must be stated explicitly rather than inferred. -2. **Durable identity** (§5) — the declared rung. Needs a computing cryptographic digest. +2. **Durable identity** (§5) — the declared rung. **Narrowed 2026-09-21:** a computing + cryptographic digest now exists (`extdeps.crypto.sha2`); what is missing is a consumed path from + it to `v2.std.node` `Hash`, which is gated on native emission of that closure. + `std.fabric_storage` is being migrated in gunbc#11996; `v2.std.node` is the remaining half. + See §5. 3. **Recursion into named edges** — the next slice, and the one that demonstrates the differentiator. 4. **Retraction epochs** (§6) — the weakest claim in the note. 5. **Positional append** — whether two appends commute. Special-casing risks re-importing the From 1895135e9b9b84dd30a3637d74435ecbe3749afe Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Tue, 22 Sep 2026 03:28:46 +0000 Subject: [PATCH 2/2] Say what word32_add does: it wraps by comparison, it takes no modulus parameter Review 69880 (non-blocking). The load-bearing claim -- no value transits above 2^32-1, so unbounded-Int evaluation yields the same residues -- was right; the mechanism named beside it was not. Co-Authored-By: Claude Opus 5 (1M context) --- docs/plans/dag-native-scm-design.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/plans/dag-native-scm-design.md b/docs/plans/dag-native-scm-design.md index a6b78a2dc15..807b59f5a9e 100644 --- a/docs/plans/dag-native-scm-design.md +++ b/docs/plans/dag-native-scm-design.md @@ -188,7 +188,7 @@ different one.** This paragraph said "no SHA-256 *computation* exists in `.dag` do not hash bytes)". That was true when written. `extdeps.crypto.sha2` now computes SHA-256 in the substrate (`sha256`, `sha256_hex`, FIPS 180-4), witnessed by `test.claim.sha256_fips_witness` — and the witness discriminates rather than restating the type, because `sha2` routes every 32-bit -operation through `std.bitwise`, whose `word32_add` takes the modulus explicitly, so the +operation through `std.bitwise`, whose `word32_add` wraps by comparison against `word32_modulus` so no value transits above 2^32-1, and the interpreter's unbounded-`Int` evaluation yields the same residues and a wrong wrap changes the digest.