use control.nu *
def main [repo: path, cache: path] {
    let repo = ($repo | path expand)
    let cache = ($cache | path expand)
    let out = ($repo | path join audit/2026-10-17-hemera-feature-performance)
    require (not ($out | path join code.json | path exists)) 'one inspection epoch'
    let run_env = (environment $cache A)
    let helper_dir = ($cache | path join helpers)
    mkdir $helper_dir ($cache | path join sections)
    for name in [macho measure] {
        let command = [$run_env.RUSTC --edition=2024 -Dwarnings -O ($out | path join $'($name).rs') -o ($helper_dir | path join $name)]
        let receipt = (capture $command $run_env $repo $out $'compile-($name)')
        require ($receipt.exit_code == 0) $'audit helper compile ($name)'
    }
    let objdump = (^xcrun --find llvm-objdump | str trim)
    let nm = (^xcrun --find llvm-nm | str trim)
    let builds = (open ($out | path join builds.json))
    mut inspections = []
    for b in $builds.builds {
        require ((sha $b.binary) == $b.sha256) 'unchanged frozen binary'
        let dir = ($cache | path join sections $b.cell)
        let sections_command = [($helper_dir | path join macho) $b.binary $dir]
        let sections_result = (capture $sections_command $run_env $repo $out $'sections-($b.cell)')
        require ($sections_result.exit_code == 0) 'Mach-O helper result'
        let sections = (open --raw ($dir | path join sections.tsv) | from tsv | each {|r|
            let backed = ($r.file_backed == 'true')
            $r | update address ($r.address | into int) | update file_offset ($r.file_offset | into int)
                | update bytes ($r.bytes | into int) | update flags ($r.flags | into int) | update file_backed $backed
                | insert sha256 (if $backed { sha ($dir | path join $'($r.segment).($r.section).bin') } else { null })
        })
        let nm_result = (capture [$nm --numeric-sort --demangle $b.binary] $run_env $repo $out $'symbols-($b.cell)')
        require ($nm_result.exit_code == 0) 'raw symbol inspection'
        let symbols = (open --raw ($out | path join $'symbols-($b.cell).stdout') | lines
            | parse --regex '^(?<address>[0-9a-f]+) (?<kind>.) (?<name>.+)$'
            | each {|s| $s | update address ($s.address | into int --radix 16)})
        let text_section = ($sections | where segment == __TEXT and section == __text | first)
        let code = (open --raw ($dir | path join __TEXT.__text.bin) | into binary)
        let functions = (open --raw ($dir | path join functions.tsv) | from tsv | each {|f|
            let address = ($f.address | into int)
            let span = ($f.span_to_next_start | into int)
            let begin = $address - $text_section.address
            let names = ($symbols | where address == $address | get name)
            {address: $address, span_to_next_start: $span, raw_symbols: ($f.symbols | default ''), names: $names,
                normalized_names: ($names | each {|n| $n | str replace --all --regex '::h[0-9a-f]{16}' ''}),
                code_sha256: ($code | bytes at $begin..($begin + $span - 1) | hash sha256),
                relevant_label: ($names | any {|n| $n =~ '(nox::|hemera::|nebu::|reduction::)'})}
        })
        let disassembly = (capture [$objdump --macho --disassemble --demangle $b.binary] $run_env $repo $out $'disassembly-($b.cell)')
        require ($disassembly.exit_code == 0) 'raw disassembly inspection'
        let loads = (capture [/usr/bin/otool -l $b.binary] $run_env $repo $out $'load-commands-($b.cell)')
        require ($loads.exit_code == 0) 'Mach-O load commands'
        let raw = ($out | path join $'disassembly-($b.cell).stdout')
        let normalized = (open --raw $raw | str replace --all $b.binary '<BINARY>'
            | str replace --all --regex '::h[0-9a-f]{16}' '::h<CRATE-HASH>'
            | str replace --all --regex '(?m)^[0-9a-f]{16}\s+' '<ADDRESS> ')
        let normpath = ($out | path join $'disassembly-($b.cell).normalized.txt')
        $normalized | save $normpath
        ^gzip -n $raw $normpath
        $inspections = ($inspections | append {cell: $b.cell, binary_sha256: $b.sha256, sections: $sections,
            functions: $functions, normalized_disassembly_sha256: ($normalized | hash sha256),
            normalization: 'replace binary path, Rust ::h + 16 hex symbol suffixes, and leading 16-hex instruction addresses only; operands unchanged',
            function_span_policy: 'LC_FUNCTION_STARTS to next function start (last to text end), including any alignment padding; exact semantic function size unknown'})
    }
    let completed = $inspections
    let comparisons = ([[A B] [C D] [A P] [B D]] | each {|pair|
        let a = ($completed | where cell == $pair.0 | first)
        let b = ($completed | where cell == $pair.1 | first)
        {parent: $pair.0, candidate: $pair.1,
            sections: ($a.sections | each {|s|
                let t = ($b.sections | where segment == $s.segment and section == $s.section | first)
                {segment: $s.segment, section: $s.section, parent_bytes: $s.bytes, candidate_bytes: $t.bytes,
                    addresses_equal: ($s.address == $t.address), file_backed: $s.file_backed,
                    raw_bytes_equal: (if $s.file_backed { $s.sha256 == $t.sha256 } else { null })}
            }), normalized_disassembly_equal: ($a.normalized_disassembly_sha256 == $b.normalized_disassembly_sha256),
            relevant_functions: ($a.functions | where relevant_label | each {|f|
                let matched = ($b.functions | where {|g| $g.normalized_names == $f.normalized_names})
                {names: $f.normalized_names, parent_address: $f.address, parent_span: $f.span_to_next_start,
                    candidate_matches: ($matched | each {|g| {address: $g.address, span: $g.span_to_next_start,
                        bytes_equal: ($g.code_sha256 == $f.code_sha256)}})}
            })}
    })
    {inspections: $inspections, comparisons: $comparisons,
        helper_sources: ([macho.rs measure.rs inspect.nu] | each {|n| {path: $n, sha256: (sha ($out | path join $n))}}),
        helpers: ([macho measure] | each {|n| let p = ($helper_dir | path join $n); {path: $p, sha256: (sha $p)}}),
        scope: 'All raw section bytes and function-start spans retained; symbol label projection cannot establish a complete reachable call graph. Link-driver rustc invocations retained in Cargo -vv; child linker argv was not instrumented.'
    } | to json | save ($out | path join code.json)
    print ($comparisons | each {|r| {pair: $'($r.parent)/($r.candidate)', changed_sections: ($r.sections | where raw_bytes_equal == false | get section), normalized_disassembly_equal: $r.normalized_disassembly_equal}} | to json)
}

Graph