Seal Hash Graph DAG (recheck-6 blocker D)
05 - Seal Hash Graph DAG (recheck-6 blocker D)
Load-bearing copy: doc 00 §Seal hash dependency graph (acyclic). This doc is the explicit node/edge list + the acyclicity proof + the demonstration that the two old back-edges are cycles.
The cycle Codex found
- envelope manifest binds
codex_checkpoint_content_sha256; - the Codex checkpoint contains
CODEX_DETACHED_SEAL, which bindssealed_envelope_manifest_sha256; - therefore the manifest depends on checkpoint bytes that depend on the manifest;
seal_report_checkpoint_content_sha256additionally asks the checkpoint to hash itself.
A path/revision/read-back statement does not remove the cycle — the hash graph had to change.
The DAG (consumer ← producer)
N1 normalized_active_content_sha256[d] (leaf: extractor output, per active doc)
N2 active_corpus_membership_sha256 (leaf: document_id set)
N3 marker_fence_registry_sha256 (leaf: extractor markers)
N4 superseded_boundary_sha256 (leaf: extractor fence ranges)
N5 guard_set_sha256 (= N1[doc06]) + guard_set_revision (leaf)
N6 active_corpus_sha256 <- N1[d] (all active d)
N7 envelope_manifest_sha256 <- N2, N3, N4, N5, N6, N1[d] (NO checkpoint hash; NOT N8)
N8 detached_seal_sha256 <- N2, N5, N6, N7, parent_checkpoint_id, report_documents[]
(NOT N8; NOT its checkpoint's content hash)
N9 codex_checkpoint_content_sha256_excluding_seal = NON_AUTHORITY_DIAGNOSTIC; consumed by NOTHING (sink)
Acyclicity proof (computed, doc 08)
Topological order exists: N1 → N2 → N3 → N4 → N5 → N6 → N7 → N8 → N9. A depth-first cycle check over
the edge list returns acyclic = True. Three invariants verified in code:
- N9 (checkpoint content) is consumed by no node (it is a diagnostic sink).
- N7 (manifest) input set contains no checkpoint revision/content node and not N8.
- N8 (seal) input set contains neither N8 nor the checkpoint content node.
And the two former back-edges are confirmed cycles when re-introduced:
- add
N7 ← N8(manifest binds the seal/checkpoint) → cycle detected = True. - add
N8 ← N8(seal hashes its own checkpoint) → cycle detected = True.
How the cycle is broken (and tamper-detection preserved)
- The manifest no longer binds
codex_checkpoint_kb_revisionorcodex_checkpoint_content_sha256(binding either would require knowing the checkpoint revision/content, which is fixed only after the seal is written — a revision-level cycle). It still binds the checkpoint identity viaapproved_by_recheck_checkpoint(a path chosen in advance — no cycle). seal_report_checkpoint_content_sha256is removed; the diagnosticcodex_checkpoint_content_sha256_excluding_seal(N9) is computed over the checkpoint with the seal region removed and is an input to nothing.- The checkpoint's immutability is anchored out-of-band by its platform-assigned monotonic
kb_revision- MCP read-back (doc 06), not by a content hash that includes the seal.
Editing the corpus → recomputed N7 ≠ sealed N7 (in the checkpoint) → fail closed. Editing the recorded
anchor revision → ≠ live checkpoint revision on read-back → fail closed. Re-pointing the anchor to a
different checkpoint → ≠ manifest-bound approved_by_recheck_checkpoint → fail closed. (G-SEAL-HASH-GRAPH-ACYCLIC,
status SEAL_HASH_GRAPH_CYCLE; doc 06.)
Load-bearing vs diagnostic
| node | role |
|---|---|
| N1–N8 | load-bearing (gate authoring) |
N9 codex_checkpoint_content_sha256_excluding_seal |
NON_AUTHORITY_DIAGNOSTIC (sink) |
No load-bearing node includes a value that transitively depends on itself.