Skip to content

8: Build and reproducibility graph

flowchart TD
    source["cmd/*-mutator<br/>Go source"]
    build["go build<br/>-buildmode=c-archive"]
    archive(["libcrucible*.a<br/>c-archive"])
    link["clang++<br/>harness.cpp + .a"]
    force["-Wl,-u,<br/>LLVMFuzzerCustomMutator<br/>permanent requirement"]
    verify{"verify-mutators<br/>symbol + engine gate"}
    binary(["crucible-libfuzzer-*<br/>runnable binary"])
    preflight{"crucible harness-smoke + preflight<br/>lifecycle · control · visibility · reach"}

    source ==>|"Go package"| build
    build ==>|".a archive"| archive
    archive ==>|"archive member"| link
    force ==>|"strong reference"| link
    link ==>|"ELF / Mach-O"| verify
    verify ==>|"defined T symbol"| binary
    binary ==>|"executable"| preflight

    subgraph was["WAS, now absent"]
        oldWire["pkg/rpc.GraphComputePayload<br/>device + nodes[] absent"]
        oldTargets["four -mutator rules<br/>wrong GGUF engine"]
        oldVerify["verify-mutators<br/>Linux-only narrow glob"]
        oldCpp["harness/cpp<br/>five sources unbuilt"]
        oldPreflight["preflight.sh<br/>always exit 0"]
        oldName["rpc_tensor.Name<br/>no strategy"]
        oldSeed["five c-archives<br/>seed discarded"]
    end

    subgraph now["NOW, verified in source"]
        newWire["GraphComputePayload<br/>Device + Nodes"]
        newTargets["misnamed rules<br/>removed"]
        newVerify["verify-mutators<br/>portable + engine-aware"]
        newCpp["harness/cpp<br/>all fuzz sources built"]
        newPreflight["preflight.sh<br/>non-zero on defect"]
        newName["field.name_no_terminator<br/>registered"]
        newSeed["getMutator(seed)<br/>all c-archives"]
    end

    oldWire -. "fixed" .-> newWire
    oldTargets -. "removed" .-> newTargets
    oldVerify -. "fixed" .-> newVerify
    oldCpp -. "fixed" .-> newCpp
    oldPreflight -. "fixed" .-> newPreflight
    oldName -. "fixed" .-> newName
    oldSeed -. "fixed" .-> newSeed

    classDef gen fill:#3b3028,stroke:#b08a5a,stroke-width:1.5px,color:#f3ead7
    classDef exec fill:#44372b,stroke:#c49a6c,stroke-width:1.5px,color:#f7edd9
    classDef assess fill:#3c432d,stroke:#9a9b62,stroke-width:1.5px,color:#f2eddc
    classDef record fill:#4b362c,stroke:#a86f4c,stroke-width:1.5px,color:#f5e6d3
    classDef gate fill:#542f2b,stroke:#b96f5c,stroke-width:2px,color:#fae8dc
    classDef hazard fill:#51452d,stroke:#b59658,stroke-width:2px,color:#f8edcf
    classDef ghost fill:#302c28,stroke:#7f7668,stroke-width:1px,stroke-dasharray:5 3,color:#b9afa0
    classDef io fill:#2f3832,stroke:#87927a,stroke-width:1.5px,color:#edf0e2
    class source,build gen
    class archive,link,binary exec
    class verify,preflight assess
    class force hazard
    class oldWire,oldTargets,oldVerify,oldCpp,oldPreflight,oldName,oldSeed ghost
    class newWire,newTargets,newVerify,newCpp,newPreflight,newName,newSeed record

The C archive carries a weak fallback definition so ordinary non-fuzzer builds link. A real harness must force-link the custom entry point and prove that libFuzzer's strong default-mutator definition won over the weak stub. A running binary or an archive on the link line proves neither condition.

The stated bar is Replicability, Robustness, Reproducibility. This is where it failed, and what closing it looked like.

Reviewed: 2026-08-20.