// 8-dim cache_key composition for v9.8 admissibility.
//
// Every providence_cache record is keyed on a SHA-256 over eight
// concatenated bytes — the 8-dim invariant. Bumping any one of the
// dimensions invalidates prior records on lookup (this is the honesty
// property: old answers do not silently serve under new conditions).
//
// An optional 9th dimension — verifier_policy_hash — exists for *audit
// legibility* (#000058). It does NOT add correctness coverage; the
// verifier-policy fields are already a subset of governance_policy_hash.
// 8-dim is the default write form; 9-dim is opt-in for one-hash-diff
// answerability of "did the *verifier* rules change?"
//
// Render: dot -Tsvg cache-key-8dim.dot -o cache-key-8dim.svg

digraph cache_key_8dim {
    rankdir=TB
    node [shape=box, style="rounded,filled", fontname="Helvetica", fontsize=10]
    edge [fontname="Helvetica", fontsize=9]
    bgcolor="white"
    ranksep=0.6
    nodesep=0.3

    subgraph cluster_dims {
        label="EIGHT MANDATORY DIMENSIONS  (concat in fixed order)"
        labeljust="l"
        fontname="Helvetica-Bold"
        style="rounded,filled"
        fillcolor="#f5faff"
        margin=14

        // Top row: corpus / question / model state
        d1 [label="1. source_root\nMerkle root over\ningested source(s)", fillcolor="#e6f0ff"]
        d2 [label="2. question_hash\ndedup-mode aware\n(strict | equiv. class)", fillcolor="#e6f0ff"]
        d3 [label="3. model_profile_hash\nmodel id + sampling +\nsystem prompt + tools", fillcolor="#e6f0ff"]
        d4 [label="4. conversation_hash\nprior turns committed\ninto the cache_key", fillcolor="#e6f0ff"]

        // Bottom row: policy / pinned versions
        d5 [label="5. governance_policy_hash\nverifier + answer_mode +\nquantifier guard + …\n(superset of #9)", fillcolor="#e6f0ff"]
        d6 [label="6. schema_version\nv9.8.0\nschema-level compat", fillcolor="#e6f0ff"]
        d7 [label="7. canonicalization_version\nnorm-v1\npinned preprocessing", fillcolor="#e6f0ff"]
        d8 [label="8. chunking_version\ntok-512-v1\npinned leaf boundaries", fillcolor="#e6f0ff"]

        {rank=same; d1; d2; d3; d4}
        {rank=same; d5; d6; d7; d8}

        // Invisible spine to enforce the 2-row layout
        d1 -> d5 [style=invis]
        d2 -> d6 [style=invis]
        d3 -> d7 [style=invis]
        d4 -> d8 [style=invis]
    }

    // Optional 9th — render as sibling-of-cluster
    d9 [label="9. verifier_policy_hash\n(opt-in, #000058)\nsubset of #5; exists for\none-hash-diff legibility,\nNOT new coverage", fillcolor="#fff0e0", style="rounded,filled,dashed"]

    sha [label="sha256(d1 ‖ d2 ‖ d3 ‖ d4 ‖ d5 ‖ d6 ‖ d7 ‖ d8  [ ‖ d9 ])", fillcolor="#999999", fontcolor="white", shape=cds, fontsize=11]

    key [label="cache_key (32 bytes, hex)\nkeys one providence_cache row", fillcolor="#28a745", fontcolor="white", shape=note]

    invariant [label="HONESTY PROPERTY\nbumping ANY dimension invalidates prior\nrecords on lookup — no silent reuse\nunder new conditions", fillcolor="#fff0e0", shape=note]

    // Cluster -> sha (one collapsed edge by anchoring on d8)
    d5 -> sha
    d6 -> sha
    d7 -> sha
    d8 -> sha
    d9 -> sha [style=dashed, label="opt-in"]

    sha -> key -> invariant [style=dotted, color="#666666"]
}
