#!/usr/bin/env bash
# Measure the 0.9.3 baseline numbers for one BioMCP clone.
#
# Every number prints with the command behind it, in this shape:
#
#   ### <section-id> — <title>
#   $ <command>
#   <command output>
#   RESULT <key> = <value>
#
# so a record can hold the exact evidence and a second run can be compared
# key by key. The script carries no host locks: schedule the measurement
# through the configured build runner and run both comparison arms on
# that one host to keep the comparison like-for-like. The script refuses
# to start while any build, test, or gate process is alive.
#
# Usage:
#   tools/measure-0-9-3-baseline <clone-dir> [options]
#
# Options:
#   --dry-run        print every command without running anything
#   --only a,b,c     run only the named sections
#   --expect-tag T   fail unless the clone's HEAD is exactly at tag T
#   --release-record FILE   reuse a retained release record (no network calls)
#   --target-build-log TARGET=FILE   reuse a complete release build log
#
# The clone must be a clean checkout of the tree to measure (ticket 2069
# measures tag v0.9.2). Timed build numbers assume the host's documented
# cargo config (incremental off, line-tables-only dev debug) and a quiet
# machine; the host section records both.

set -euo pipefail

FAILED=0
DRY_RUN=0
ONLY=""
EXPECT_TAG=""
CLONE=""
RELEASE_RECORD=""
TARGET_BUILD_LOGS=()

usage() {
  cat >&2 <<'USAGEEOF'
usage: measure-0-9-3-baseline <clone-dir> [--dry-run] [--only a,b,c]
                              [--expect-tag vX.Y.Z]
                              [--release-record FILE] [--target-build-log TARGET=FILE]
USAGEEOF
  exit 2
}

while (($#)); do
  case "$1" in
    --dry-run) DRY_RUN=1 ;;
    --only) shift; ONLY="${1:-}" ;;
    --only=*) ONLY="${1#*=}" ;;
    --expect-tag) shift; EXPECT_TAG="${1:-}" ;;
    --expect-tag=*) EXPECT_TAG="${1#*=}" ;;
    --release-record) shift; RELEASE_RECORD="${1:-}" ;;
    --target-build-log) shift; TARGET_BUILD_LOGS+=("${1:-}") ;;
    -h|--help) sed -n '2,25p' "$0" | sed 's/^# \{0,1\}//' >&2; exit 0 ;;
    -*) echo "unknown option: $1" >&2; usage ;;
    *) if [[ -n "$CLONE" ]]; then echo "one clone directory only" >&2; usage; fi
       CLONE="$1" ;;
  esac
  shift
done

[[ -n "$CLONE" ]] || usage
[[ -d "$CLONE" ]] || { echo "clone directory not found: $CLONE" >&2; exit 2; }
# Resolve retained inputs before changing into the measured checkout.
if [[ -n "$RELEASE_RECORD" ]]; then
  RELEASE_RECORD="$(python3 -c 'import os,sys; print(os.path.abspath(sys.argv[1]))' "$RELEASE_RECORD")"
fi
for i in "${!TARGET_BUILD_LOGS[@]}"; do
  entry="${TARGET_BUILD_LOGS[$i]}"
  [[ "$entry" == *=* ]] || { echo "target build log requires TARGET=FILE" >&2; exit 2; }
  path="$(python3 -c 'import os,sys; print(os.path.abspath(sys.argv[1]))' "${entry#*=}")"
  TARGET_BUILD_LOGS[$i]="${entry%%=*}=$path"
done

export PATH="$HOME/.cargo/bin:$HOME/.local/bin:$PATH"
cd "$CLONE"
CLONE="$(pwd)"
LOGD=".cache/measure"
mkdir -p "$LOGD"
# Keep temporary fixtures inside the checkout, as the routine gates do.
# Store security checks deliberately reject symlink components in paths.
mkdir -p "$LOGD/tmp"
chmod 700 "$LOGD/tmp"
TMPDIR="$(cd "$LOGD/tmp" && pwd -P)"
export TMPDIR

say() { printf '\n### %s — %s\n' "$1" "$2"; }
result() { printf 'RESULT %s = %s\n' "$1" "$2"; }
show() { printf '$ %s\n' "$1"; }

# The manifest and lockfile parsers need tomllib (Python 3.11); the macOS
# gate host's system python3 is older, so they run under the first
# interpreter that has it, syncing the clone's uv venv when needed.
if python3 -c 'import tomllib' >/dev/null 2>&1; then
  TOML_PY=(python3)
elif command -v uv >/dev/null 2>&1; then
  TOML_PY=(uv run python3)
else
  TOML_PY=(python3)
fi

# runsh runs a shell string and prints it first; the record shows the
# command behind every number.
runsh() {
  show "$1"
  if ((DRY_RUN)); then return 0; fi
  bash -c "$1"
}

# timedsh prints the command, runs it, and records its wall time.
# python3's clock gives the same sub-second precision on every gate host;
# GNU date's %s.%N does not exist on the macOS one.
timedsh() {
  local label="$1" command="$2" start end wall status logfile
  shift 2
  show "$command"
  if ((DRY_RUN)); then result "${label}_wall_s" dry-run; return 0; fi
  start=$(python3 -c 'import time; print(time.time())')
  if bash -e -o pipefail -c "$command"; then
    :
  else
    status=$?
    for logfile in "$@"; do cat "$logfile" >&2; done
    return "$status"
  fi
  end=$(python3 -c 'import time; print(time.time())')
  wall=$(awk -v s="$start" -v e="$end" 'BEGIN { printf "%.1f", e - s }')
  result "${label}_wall_s" "$wall"
}

# timedsh_exit prints the command, runs it, records its wall time, and
# writes the command's own exit status to the named file. A coverage suite's
# nonzero exit is data the reports need, so the run continues and the status
# reaches the report step instead of stopping the script.
timedsh_exit() {
  local label="$1" exitfile="$2" command="$3" start end wall status logfile
  shift 3
  show "$command"
  if ((DRY_RUN)); then result "${label}_wall_s" dry-run; return 0; fi
  start=$(python3 -c 'import time; print(time.time())')
  set +e
  bash -e -o pipefail -c "$command"
  status=$?
  set -e
  end=$(python3 -c 'import time; print(time.time())')
  wall=$(awk -v s="$start" -v e="$end" 'BEGIN { printf "%.1f", e - s }')
  if [[ "$status" != 0 ]]; then
    FAILED=1
    for logfile in "$@"; do cat "$logfile" >&2; done
  fi
  printf '%s\n' "$status" >"$exitfile"
  result "${label}_wall_s" "$wall"
}

want_section() {
  [[ -z "$ONLY" ]] && return 0
  [[ ",$ONLY," == *",$1,"* ]]
}

quiet_pids() {
  local name pids
  for name in cargo rustc cargo-nextest clippy-driver pytest mkdocs make uv cargo-deny cargo-llvm-cov; do
    pids=$(pgrep -x "$name" 2>/dev/null || true)
    if [[ -n "$pids" ]]; then
      echo "busy: process(es) named $name are running:" >&2
      ps -o pid=,etime=,args= -p "$(echo "$pids" | tr '\n' ',' | sed 's/,$//')" >&2 || true
      return 1
    fi
  done
  return 0
}

# ---------------------------------------------------------------- host

# du_bytes, file_size and gnu_time answer on every gate host; the
# Linux-specific tools stay first where they exist.
file_size() { stat -c %s "$1" 2>/dev/null || stat -f %z "$1"; }
du_bytes() {
  if du -sb . >/dev/null 2>&1; then du -sb "$1" | awk '{print $1}'
  else du -sk "$1" | awk '{print $1 * 1024}'; fi
}
# gnu_time finds a GNU time on the host (Linux /usr/bin/time, gtime
# elsewhere) or fails so the caller uses native BSD time.
gnu_time() {
  if /usr/bin/time --version >/dev/null 2>&1; then echo /usr/bin/time
  elif command -v gtime >/dev/null 2>&1; then command -v gtime
  else return 1; fi
}

if want_section host; then
  say host "machine and toolchain conditions at the start"
  runsh 'hostname; uname -sr; nproc || sysctl -n hw.ncpu'
  runsh 'cat /proc/loadavg || uptime'
  runsh 'free -g | sed -n 1,2p || vm_stat | head -5'
  runsh 'df -h . | tail -1'
  runsh 'rustc --version; cargo --version; cargo nextest --version; cargo-deny --version; cargo llvm-cov --version; cargo llvm-lines --version; ruff --version; python3 --version; uv --version; node --version 2>/dev/null || true; mustmatch --version 2>/dev/null || true'
  runsh 'cat ~/.cargo/config.toml 2>/dev/null || echo "no ~/.cargo/config.toml"'
  runsh 'cat .config/nextest.toml 2>/dev/null || echo "no .config/nextest.toml"'
fi

# ---------------------------------------------------------------- clone

if want_section clone; then
  say clone "the tree being measured"
  runsh 'git rev-parse HEAD; git describe --tags --exact-match HEAD 2>/dev/null || true; git log -1 --format="%H %s"; git status --porcelain | wc -l'
  if ((!DRY_RUN)) && [[ -n "$EXPECT_TAG" ]]; then
    tag=$(git describe --tags --exact-match HEAD 2>/dev/null || true)
    [[ "$tag" == "$EXPECT_TAG" ]] || { echo "clone HEAD is not at $EXPECT_TAG (found: ${tag:-none})" >&2; exit 2; }
  fi
fi

# ---------------------------------------------------------------- quiet

if want_section quiet; then
  say quiet "no other build or gate process is running"
  show "pgrep -x cargo rustc cargo-nextest clippy-driver pytest mkdocs make uv cargo-deny cargo-llvm-cov"
  if ((!DRY_RUN)); then
    quiet_pids || exit 3
    echo "quiet: no matching process is running"
  fi
fi

# ---------------------------------------------------------------- cold dev build

if want_section working-checkout; then
  say working-checkout "target/ bytes at entry, before any measurement build"
  show "du -sb target (du -sk * 1024 where -b is absent); existing state, not a clean build"
  if ((!DRY_RUN)); then
    if [[ -d target ]]; then
      result working_checkout_build_folder_bytes "$(du_bytes target)"
    else
      result working_checkout_build_folder_bytes "unavailable (no target directory in this checkout)"
    fi
  fi
fi

if want_section release-target-counts; then
  say release-target-counts "observed compiler work from retained release-target build logs"
  show "python3 (unique Compiling name/version pairs, including the product; cached crates absent from logs stay uncounted)"
  if ((!DRY_RUN)); then
    python3 - ${TARGET_BUILD_LOGS[@]+"${TARGET_BUILD_LOGS[@]}"} <<'PY'
import re
import sys
from pathlib import Path

logs = dict(entry.split("=", 1) for entry in sys.argv[1:])
targets = {"linux": "x86_64-unknown-linux-gnu",
           "linux_arm64": "aarch64-unknown-linux-gnu",
           "windows": "x86_64-pc-windows-msvc"}
for label, target in targets.items():
    path = logs.get(target)
    key = f"crates_compiled_{label}_release"
    if not path or not Path(path).is_file():
        print(f"RESULT {key} = unavailable (no retained {target} build log)")
        continue
    text = Path(path).read_text(errors="replace")
    # gh preserves Windows color either as ANSI escapes or printable ^[ codes.
    text = re.sub(r"(?:\x1b|\^\[)\[[0-?]*[ -/]*[@-~]", "", text)
    print(f"retained input {target}: {path}")
    pairs = set(re.findall(r"\bCompiling ([\w-]+) v([^\s]+)", text))
    if not re.search(r"Finished [`\"]release['`\"] profile", text):
        print(f"RESULT {key} = unavailable (retained log lacks successful release completion)")
        continue
    print(f"RESULT {key} = {len(pairs)}")
    print(f"METHOD {key}: observed unique Compiling pairs only; cache state and command must be retained with the input; not a resolved graph or total compiler units")
PY
  fi
fi

if want_section python-test-functions; then
  say python-test-functions "AST test function definitions, separate from parametrized collected cases"
  show "python3 (test_ functions and methods of Test classes; file-level tooling references; retained TSV inventory)"
  if ((!DRY_RUN)); then
    python3 - "$LOGD/python-test-functions.tsv" <<'PY'
import ast
import sys
from pathlib import Path

ignored = {"tools/run-offline", "tools/with-build-identity"}
rows = []
for path in sorted(Path("tests").rglob("*.py")):
    if not (path.name.startswith("test_") or path.name.endswith("_test.py")):
        continue
    tree = ast.parse(path.read_text(), filename=str(path))
    definitions = [node for node in tree.body
                   if isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef))]
    for node in tree.body:
        if isinstance(node, ast.ClassDef) and (node.name.startswith("Test") or any(
            isinstance(base, ast.Name) and base.id == "TestCase" or
            isinstance(base, ast.Attribute) and base.attr == "TestCase"
            for base in node.bases
        )):
            definitions.extend(n for n in node.body
                               if isinstance(n, (ast.FunctionDef, ast.AsyncFunctionDef)))
    count = sum(node.name.startswith("test_") for node in definitions)
    if not count:
        continue
    references = set()
    for node in ast.walk(tree):
        value = ""
        if isinstance(node, ast.Constant) and isinstance(node.value, str):
            value = node.value
        elif isinstance(node, ast.BinOp) and isinstance(node.op, ast.Div):
            parts = []
            cursor = node
            while isinstance(cursor, ast.BinOp) and isinstance(cursor.op, ast.Div):
                if isinstance(cursor.right, ast.Constant) and isinstance(cursor.right.value, str):
                    parts.insert(0, cursor.right.value)
                cursor = cursor.left
            if isinstance(cursor, ast.Constant) and isinstance(cursor.value, str):
                parts.insert(0, cursor.value)
            value = "/".join(parts)
        if (value.startswith(("tools/", "scripts/", ".github/workflows/")) or value == "Makefile") and "\n" not in value:
            if value not in ignored and not value.startswith(("scripts/fixtures/", "spec/fixtures/")):
                references.add(value)
    rows.append((str(path), "tooling" if references else "other", count, ",".join(sorted(references))))
total = sum(row[2] for row in rows)
tooling = sum(row[2] for row in rows if row[1] == "tooling")
Path(sys.argv[1]).write_text("path\tclassification\tfunctions\treferences\n" + "".join(
    f"{path}\t{kind}\t{count}\t{refs}\n" for path, kind, count, refs in rows))
print(f"RESULT python_test_functions = {total}")
print(f"RESULT python_tooling_test_functions = {tooling}")
print(f"RESULT python_tooling_test_share_pct = {100 * tooling / total:.2f}" if total else
      "RESULT python_tooling_test_share_pct = unavailable (no test functions)")
print("METHOD: file-level convention: tooling path references, excluding generic offline/identity wrappers; mixed files count wholly as tooling. This is a reviewable classification, not semantic proof for every function. AST definitions exclude parametrization expansion and dynamically generated tests.")
PY
  fi
fi

if want_section release-history; then
  say release-history "retained release record; no new workflows or asset downloads"
  show "python3 (retained publishing elapsed duration, archive bytes, full-mode attempt rows)"
  if ((!DRY_RUN)); then
    python3 - "$RELEASE_RECORD" <<'PY'
import re
import sys
from pathlib import Path

path = Path(sys.argv[1]) if sys.argv[1] else None
text = path.read_text() if path and path.is_file() else ""
if text:
    print(f"retained release record: {path}")
    print(text)
duration = re.search(r"elapsed (\d+) minutes (\d+) seconds", text)
archives = re.findall(r"^\| (biomcp-[^ |]+\.(?:tar\.gz|zip)) \| ([\d,]+) \|", text, re.M)
attempts = re.findall(r"^\| \[\d+\]\(https://github.com/[^)]+/actions/runs/\d+\) \|", text, re.M)
unavailable = "unavailable (no matching evidence in retained release record)"
print(f"RESULT release_workflow_wall_s = {int(duration[1]) * 60 + int(duration[2])}" if duration else
      f"RESULT release_workflow_wall_s = {unavailable}")
for name, size in archives:
    print(f"RESULT release_archive_bytes_{name} = {size.replace(',', '')}")
if not archives:
    print(f"RESULT release_archive_bytes = {unavailable}")
print(f"RESULT full_rehearsals_count = {len(attempts)}" if attempts else
      f"RESULT full_rehearsals_count = {unavailable}")
PY
  fi
fi

if want_section cold-dev-build; then
  say cold-dev-build "cold dev build of every target (routine feature set)"
  if TIME_BIN=$(gnu_time); then
    timedsh cold_dev_build \
      "$TIME_BIN -f \"TIMEFMT WALL %e USER %U SYS %S MAXRSS_KB %M\" tools/with-build-identity cargo build --locked --no-default-features --all-targets --timings"
  else
    timedsh cold_dev_build \
      '/usr/bin/time -l tools/with-build-identity cargo build --locked --no-default-features --all-targets --timings'
  fi
fi

# ---------------------------------------------------------------- rebuild after one Rust edit

if want_section rust-edit-rebuild; then
  say rust-edit-rebuild "rebuild after one Rust edit (dev profile, incremental off)"
  runsh 'touch src/render/markdown/gene.rs'
  if TIME_BIN=$(gnu_time); then
    timedsh rust_edit_rebuild \
      "$TIME_BIN -f \"TIMEFMT WALL %e USER %U SYS %S MAXRSS_KB %M\" tools/with-build-identity cargo build --locked --no-default-features --all-targets"
  else
    timedsh rust_edit_rebuild \
      '/usr/bin/time -l tools/with-build-identity cargo build --locked --no-default-features --all-targets'
  fi
fi

# ---------------------------------------------------------------- rebuild after one doc edit

if want_section doc-edit-rebuild; then
  say doc-edit-rebuild "rebuild after one doc edit (a spec page touch; v0.9.2 build.rs scans the whole package)"
  runsh 'touch spec/entity/gene.md'
  if TIME_BIN=$(gnu_time); then
    timedsh doc_edit_rebuild \
      "$TIME_BIN -f \"TIMEFMT WALL %e USER %U SYS %S MAXRSS_KB %M\" tools/with-build-identity cargo build --locked --no-default-features --all-targets"
  else
    timedsh doc_edit_rebuild \
      '/usr/bin/time -l tools/with-build-identity cargo build --locked --no-default-features --all-targets'
  fi
fi

# ---------------------------------------------------------------- dependency counts

if want_section dep-counts; then
  say dep-counts "direct dependencies, Cargo.lock packages, crates compiled, duplicate names"
  show "${TOML_PY[*]} (counts from Cargo.toml and Cargo.lock)"
  if ((!DRY_RUN)); then
    "${TOML_PY[@]}" - "$LOGD/dep-counts.txt" <<'PY'
import sys
import tomllib
from collections import Counter
from pathlib import Path

out = []
manifest = tomllib.loads(Path("Cargo.toml").read_text())
normal = manifest.get("dependencies", {})
optional = sorted(k for k, v in normal.items() if isinstance(v, dict) and v.get("optional"))
dev = manifest.get("dev-dependencies", {})
win = manifest.get("target", {}).get('cfg(windows)', {}).get("dependencies", {})
unix_dev = manifest.get("target", {}).get("cfg(unix)", {}).get("dev-dependencies", {})
out.append(f"RESULT direct_dependencies_normal = {len(normal)} (optional: {len(optional)}: {', '.join(optional)})")
out.append(f"RESULT direct_dependencies_dev = {len(dev)}")
out.append(f"RESULT direct_dependencies_windows_only = {len(win)}")
out.append(f"RESULT direct_dependencies_unix_dev = {len(unix_dev)}")

lock = tomllib.loads(Path("Cargo.lock").read_text())
packages = lock.get("package", [])
names = Counter(p["name"] for p in packages)
dups = sorted(n for n, c in names.items() if c > 1)
out.append(f"RESULT cargo_lock_packages = {len(packages)}")
out.append(f"RESULT cargo_lock_duplicate_names = {len(dups)} (extra copies: {sum(names[n] for n in dups) - len(dups)})")
Path(sys.argv[1]).write_text("\n".join(out) + "\n")
print("\n".join(out))
PY
  fi
  runsh "cargo tree --locked --no-default-features -e normal,build --prefix none > $LOGD/tree-normal-build.txt"
  runsh "cargo tree --locked --no-default-features -e normal,build,dev --prefix none > $LOGD/tree-normal-build-dev.txt"
  show "${TOML_PY[*]} (unique crate name@version pairs in each cargo tree, workspace members excluded)"
  if ((!DRY_RUN)); then
    "${TOML_PY[@]}" - "$LOGD/tree-normal-build.txt" "$LOGD/tree-normal-build-dev.txt" <<'PY'
import sys
from collections import Counter

workspace = {"biomcp-cli", "biomcp-mcp-contract-client"}
for label, path in (("normal_build", sys.argv[1]), ("with_dev", sys.argv[2])):
    pairs = set()
    for line in open(path):
        fields = line.split()
        if len(fields) < 2 or not fields[1].startswith("v"):
            continue
        if fields[0] in workspace:
            continue
        pairs.add((fields[0], fields[1]))
    print(f"RESULT crates_compiled_{label} = {len(pairs)}")
    names = Counter(name for name, _ in pairs)
    dups = sorted(n for n, c in names.items() if c > 1)
    print(f"RESULT duplicate_crate_names_{label} = {len(dups)} ({', '.join(dups) if dups else 'none'})")
PY
  fi
fi

# ---------------------------------------------------------------- prepare (context)

if want_section prepare-context; then
  say prepare-context "one prepare so the timed gates below start with fresh artifacts (context, not a baseline number)"
  timedsh make_prepare_test 'make prepare-test'
fi

# ---------------------------------------------------------------- make test

if want_section make-test; then
  say make-test "the routine gate, wall time with artifacts already fresh"
  timedsh make_test "make test > $LOGD/make-test.log 2>&1" "$LOGD/make-test.log"
  runsh "grep -E 'Summary \\[|tests? run:' $LOGD/make-test.log | tail -1 || true"
  runsh "grep -E '^=+ .* (passed|failed|error).* =+$' $LOGD/make-test.log | tail -2 || true"
  runsh "grep -iE 'documentation built|docs built' $LOGD/make-test.log | tail -1 || true"
  show "python3 (test counts parsed from the make-test log)"
  if ((!DRY_RUN)); then
    python3 - "$LOGD/make-test.log" <<'PY'
import re
import sys

text = open(sys.argv[1], errors="replace").read()
m = re.search(r"Summary \[.*?\]\s+(\d+) tests? run:.*?(\d+) passed.*?(\d+) skipped", text)
if m:
    print(f"RESULT rust_tests_run = {m.group(1)}")
    print(f"RESULT rust_tests_passed = {m.group(2)}")
    print(f"RESULT rust_tests_skipped = {m.group(3)}")
else:
    print("RESULT rust_tests_run = parse-failed")
p = re.findall(r"=+ (\d+ passed[^=]*?) =+", text)
if p:
    print(f"RESULT python_lane_summary = {p[-1].strip()}")
PY
  fi
fi

# ---------------------------------------------------------------- build folder after make test

if want_section build-folder-after-make-test; then
  say build-folder-after-make-test "target/ bytes after make test"
  show "du -sb target (du -sk * 1024 where -b is absent)"
  runsh 'du -sh target'
  if ((!DRY_RUN)); then
    result build_folder_bytes_after_make_test "$(du_bytes target)"
  fi
fi

# ---------------------------------------------------------------- rust test census

if want_section rust-test-census; then
  say rust-test-census "test-duration census of the routine Rust suite (from the archive make test built)"
  timedsh_exit rust_test_census "$LOGD/census.exit" \
    "NEXTEST_EXPERIMENTAL_LIBTEST_JSON=1 tools/run-offline -- cargo nextest run --archive-file .cache/routine-tests.tar.zst --config-file .config/nextest.toml --message-format libtest-json-plus > $LOGD/census.jsonl 2> $LOGD/census.err" "$LOGD/census.jsonl" "$LOGD/census.err"
  if ((!DRY_RUN)); then
    census_status="$(<"$LOGD/census.exit")"
    if [[ "$census_status" == "0" ]]; then
      result rust_test_census_collection complete
    else
      result rust_test_census_collection "incomplete (exit $census_status)"
    fi
  fi
  runsh "tail -2 $LOGD/census.err || true"
  show "python3 (count tests at or over one second from the libtest-json-plus stream)"
  if ((!DRY_RUN)); then
    python3 - "$LOGD/census.jsonl" <<'PY'
import json
import sys

tests = {}
for line in open(sys.argv[1], errors="replace"):
    try:
        event = json.loads(line)
    except json.JSONDecodeError:
        continue
    if event.get("type") != "test":
        continue
    if event.get("event") not in ("ok", "failed", "timeout", "ignored"):
        continue
    time = event.get("exec_time")
    if time is None:
        continue
    tests[event.get("name", "?")] = max(tests.get(event.get("name", "?"), 0.0), float(time))
slow = sorted(((t, n) for n, t in tests.items() if t >= 1.0), reverse=True)
print(f"RESULT rust_tests_with_duration = {len(tests)}")
print(f"RESULT tests_over_1s = {len(slow)}")
print(f"RESULT tests_over_1s_sum_s = {sum(t for t, _ in slow):.1f}")
print("slowest tests:")
for t, n in slow[:15]:
    print(f"  {t:8.1f}s  {n}")
PY
  fi
fi

# ---------------------------------------------------------------- python test count

if want_section python-test-count; then
  say python-test-count "python lane test count (collection, no runs)"
  timedsh python_collect \
    "tools/run-offline -- env BIOMCP_BIN=$PWD/target/spec/biomcp uv run --no-sync pytest tests/ --collect-only -q > $LOGD/pytest-collect.txt 2>&1" "$LOGD/pytest-collect.txt"
  runsh "tail -2 $LOGD/pytest-collect.txt"
  show "python3 (collected count)"
  if ((!DRY_RUN)); then
    count=$(grep -oE '[0-9]+ tests? collected' "$LOGD/pytest-collect.txt" | grep -oE '^[0-9]+' | tail -1 || true)
    result python_tests_collected "${count:-parse-failed}"
  fi
fi

# ---------------------------------------------------------------- spec block census

if want_section spec-block-census; then
  say spec-block-census "executable bash blocks across the spec pages"
  BASH_FENCE='^[[:space:]]*```bash[[:space:]]*$'
  runsh "grep -rlE '$BASH_FENCE' spec --include='*.md' | wc -l"
  runsh "grep -rE '$BASH_FENCE' spec --include='*.md' | wc -l"
  if ((!DRY_RUN)); then
    result spec_pages_with_bash_blocks "$(grep -rlE "$BASH_FENCE" spec --include='*.md' | wc -l)"
    result spec_bash_blocks "$(grep -rE "$BASH_FENCE" spec --include='*.md' | wc -l)"
  fi
fi

# ---------------------------------------------------------------- make spec

if want_section make-spec; then
  say make-spec "the spec lane, wall time with artifacts already fresh"
  timedsh make_spec "make spec > $LOGD/make-spec.log 2>&1" "$LOGD/make-spec.log"
  runsh "tail -6 $LOGD/make-spec.log"
fi

# ---------------------------------------------------------------- make lint

if want_section make-lint; then
  say make-lint "the lint gate, wall time"
  timedsh make_lint "make lint > $LOGD/make-lint.log 2>&1" "$LOGD/make-lint.log"
  runsh "tail -6 $LOGD/make-lint.log"
fi

# ---------------------------------------------------------------- release build

if want_section release-build; then
  say release-build "cold release build (default features, shipped profile: thin LTO, one codegen unit, strip)"
  if TIME_BIN=$(gnu_time); then
    timedsh release_build \
      "$TIME_BIN -v -o $LOGD/release-time.txt tools/with-build-identity cargo build --release --locked --timings > $LOGD/release-build.log 2>&1" "$LOGD/release-build.log"
  else
    timedsh release_build \
      "/usr/bin/time -l -o $LOGD/release-time.txt tools/with-build-identity cargo build --release --locked --timings > $LOGD/release-build.log 2>&1" "$LOGD/release-build.log"
  fi
  runsh "grep -E 'Elapsed \\(wall clock|Maximum resident set size|User time|System time' $LOGD/release-time.txt 2>/dev/null || true"
  runsh "tail -3 $LOGD/release-build.log"
  if ((!DRY_RUN)) && [[ -f $LOGD/release-time.txt ]]; then
    rss=$(grep -oE 'Maximum resident set size \(kbytes\): [0-9]+' "$LOGD/release-time.txt" | grep -oE '[0-9]+' || true)
    if [[ -z "$rss" ]]; then
      # BSD time reports bytes; GNU time reports KiB. Keep the raw file.
      rss=$(awk '/maximum resident set size/ {printf "%.0f", $1 / 1024}' "$LOGD/release-time.txt")
    fi
    result release_peak_rss_kb "${rss:-parse-failed}"
  fi
fi

# ---------------------------------------------------------------- build folder after release

if want_section build-folder-after-release; then
  say build-folder-after-release "target/ bytes after the release build"
  show "du -sb target (du -sk * 1024 where -b is absent)"
  runsh 'du -sh target'
  if ((!DRY_RUN)); then
    result build_folder_bytes_after_release_build "$(du_bytes target)"
  fi
fi

# ---------------------------------------------------------------- stripped binary

if want_section stripped-binary; then
  say stripped-binary "the stripped release binary's size in bytes"
  show "stat -c %s target/release/biomcp (stat -f %z where -c is absent)"
  runsh 'file target/release/biomcp | head -1'
  if ((!DRY_RUN)); then
    if file target/release/biomcp | grep -q 'not stripped'; then
      cp target/release/biomcp "$LOGD/biomcp.stripped"
      strip "$LOGD/biomcp.stripped"
      result stripped_release_binary_bytes "$(file_size "$LOGD/biomcp.stripped") (stripped a copy; profile does not strip)"
    else
      result stripped_release_binary_bytes "$(file_size target/release/biomcp)"
    fi
  fi
fi

# ---------------------------------------------------------------- llvm lines

if want_section llvm-lines; then
  say llvm-lines "LLVM IR lines and function copies of the library, release profile"
  timedsh llvm_lines "cargo llvm-lines --release --lib > $LOGD/llvm-lines.txt 2>&1" "$LOGD/llvm-lines.txt"
  runsh "head -8 $LOGD/llvm-lines.txt"
  show "awk (sum of the Lines and Copies columns)"
  if ((!DRY_RUN)); then
    awk '$3 == "(TOTAL)" { printf "RESULT llvm_lines_total = %d\nRESULT llvm_function_copies = %d\n", $1, $2 }' "$LOGD/llvm-lines.txt"
  fi
fi

# ---------------------------------------------------------------- deny advisories

if want_section deny-advisories; then
  say deny-advisories "advisories ignored in deny.toml"
  show "${TOML_PY[*]} (count of [advisories].ignore entries)"
  if ((!DRY_RUN)); then
    "${TOML_PY[@]}" - <<'PY'
import tomllib
from pathlib import Path

deny = tomllib.loads(Path("deny.toml").read_text())
ignored = deny.get("advisories", {}).get("ignore", [])
print(f"RESULT ignored_advisories = {len(ignored)}")
for entry in ignored:
    print(f"  {entry.get('id')}")
PY
  fi
fi

# ---------------------------------------------------------------- coverage

if want_section coverage; then
  say coverage "line coverage of three suites through cargo-llvm-cov (dev build instrumented)"

  # cov_suite_reason[label] names every suite whose run cannot back a
  # coverage number: its exit is nonzero, its summary shows failed tests,
  # or its summary never parsed. A report set fed by any such suite prints
  # incomplete instead of a percentage.
  declare -A cov_suite_reason=()

  # cov_clause prints the count of one "N <clause>" piece of a suite
  # summary (cov_clause <clause> <summary>), or nothing when the piece is
  # absent (nextest omits a zero "failed" clause; pytest omits zero pieces
  # entirely).
  cov_clause() {
    grep -oE "[0-9]+ $1" <<<"$2" | grep -oE '^[0-9]+' || true
  }

  # record_cov_suite prints one RESULT line with a suite's exit status and
  # test counts, and fills cov_suite_reason for a failed or unproven run.
  record_cov_suite() {
    local label="$1" kind="$2" exitfile="$3" logfile="$4"
    local status summary counts reason n_run n_passed n_failed n_errors n_timeout n_skipped pages failed_pages
    status="$(<"$exitfile")"
    counts="summary unparsed"
    n_failed=""
    n_errors=""
    n_timeout=""
    case "$kind" in
      nextest)
        summary="$(grep -E 'Summary \[' "$logfile" | tail -1 || true)"
        if [[ -n "$summary" ]]; then
          # Fail-fast summaries show executed/selected tests. The
          # numerator is the work that actually ran.
          n_run="$(sed -nE 's/.*] +([0-9]+)(\/[0-9]+)? tests? run:.*/\1/p' <<<"$summary")"
          n_passed="$(cov_clause passed "$summary")"
          n_failed="$(cov_clause failed "$summary")"
          n_timeout="$(cov_clause 'timed out' "$summary")"
          n_skipped="$(cov_clause skipped "$summary")"
          if [[ -n "$n_run" ]]; then
            counts="${n_run} run: ${n_passed:-0} passed, ${n_failed:-0} failed, ${n_timeout:-0} timed out, ${n_skipped:-0} skipped"
          fi
        fi
        ;;
      pytest)
        summary="$(grep -E '^=+ .* (passed|failed|error).* =+$' "$logfile" | tail -1 || true)"
        if [[ -n "$summary" ]]; then
          n_passed="$(cov_clause passed "$summary")"
          n_failed="$(cov_clause failed "$summary")"
          n_errors="$(cov_clause errors? "$summary")"
          n_skipped="$(cov_clause skipped "$summary")"
          counts="${n_passed:-0} passed, ${n_failed:-0} failed, ${n_errors:-0} errors, ${n_skipped:-0} skipped"
        fi
        ;;
      spec)
        # Current runners list all selected pages in one header; older
        # runners print one singular header for each page.
        pages="$(awk '
          /^=== spec pages: / {
            sub(/^=== spec pages: /, ""); sub(/ ===$/, "")
            aggregate += NF
          }
          /^=== spec page: / { singular++ }
          END { print aggregate + singular }
        ' "$logfile")"
        failed_pages="$(grep -oE 'spec run failed \([0-9]+\)' "$logfile" | grep -oE '[0-9]+' | tail -1 || true)"
        if [[ -z "$failed_pages" ]]; then
          failed_pages="$(grep -c 'spec page failed: ' "$logfile" || true)"
        fi
        n_failed="$failed_pages"
        if ((pages > 0)); then
          counts="${pages} pages, ${failed_pages:-0} failed"
        fi
        ;;
    esac
    result "coverage_${label}" "exit ${status}; ${counts}"
    reason=""
    if [[ "$counts" == "summary unparsed" ]]; then
      reason="summary unparsed"
    elif [[ -n "$n_failed" && "$n_failed" != "0" ]]; then
      reason="${n_failed} failed"
      if [[ -n "$n_errors" && "$n_errors" != "0" ]]; then
        reason="$reason, ${n_errors} errors"
      fi
    elif [[ -n "$n_errors" && "$n_errors" != "0" ]]; then
      reason="${n_errors} errors"
    elif [[ -n "$n_timeout" && "$n_timeout" != "0" ]]; then
      reason="${n_timeout} timed out"
    elif [[ "$status" != "0" ]]; then
      reason="exit ${status}"
    fi
    if [[ -n "$reason" ]]; then
      cov_suite_reason["$label"]="${label}: ${reason}"
    fi
  }

  COVT="target/llvm-cov-target"
  # cov_build_env_keys names every key the coverage build environment
  # exports, so the lanes that never compile anything can strip exactly
  # those keys again before they run.
  COV_BUILD_ENV_KEYS=()
  declare -A COV_BUILD_ENV_RESTORE=()
  remember_cov_env() {
    local key="$1"
    if [[ ! ${COV_BUILD_ENV_RESTORE[$key]+saved} ]]; then
      COV_BUILD_ENV_RESTORE[$key]="$(declare -p "$key" 2>/dev/null || printf 'unset %q' "$key")"
    fi
  }
  runsh 'cargo llvm-cov clean --workspace'
  show 'eval each line of "cargo llvm-cov show-env" as an export; CARGO_TARGET_DIR=target/llvm-cov-target; LLVM_PROFILE_FILE per suite'
  if ((!DRY_RUN)); then
    while IFS= read -r line; do
      remember_cov_env "${line%%=*}"
      eval "export $line"
      COV_BUILD_ENV_KEYS+=("${line%%=*}")
    done < <(cargo llvm-cov show-env 2>/dev/null | grep -E '^[A-Z_]+=')
    remember_cov_env CARGO_INCREMENTAL
    remember_cov_env CARGO_TARGET_DIR
    export CARGO_INCREMENTAL=0
    export CARGO_TARGET_DIR="$PWD/$COVT"
    COV_BUILD_ENV_KEYS+=(CARGO_INCREMENTAL CARGO_TARGET_DIR)
    mkdir -p "$CARGO_TARGET_DIR"
  fi
  timedsh coverage_build \
    "cargo build --locked --no-default-features --all-targets > $LOGD/cov-build.log 2>&1" "$LOGD/cov-build.log"
  # absolute path: the suites run subprocesses from many working
  # directories, and a relative profile path silently drops their profiles
  export LLVM_PROFILE_FILE="$CARGO_TARGET_DIR/out-%8m.profraw"
  timedsh_exit coverage_integration_tests "$LOGD/cov-integration.exit" \
    "tools/run-offline -- cargo nextest run --locked --no-default-features -E 'kind(test)' > $LOGD/cov-integration.log 2>&1" "$LOGD/cov-integration.log"
  runsh "grep -E 'Summary \\[|tests? run:' $LOGD/cov-integration.log | tail -1 || true"
  if ((!DRY_RUN)); then
    record_cov_suite integration_tests nextest "$LOGD/cov-integration.exit" "$LOGD/cov-integration.log"
  fi
  export LLVM_PROFILE_FILE="$CARGO_TARGET_DIR/unit-%8m.profraw"
  timedsh_exit coverage_unit_tests "$LOGD/cov-unit.exit" \
    "tools/run-offline -- cargo nextest run --locked --no-default-features -E 'kind(lib) | kind(bin)' > $LOGD/cov-unit.log 2>&1" "$LOGD/cov-unit.log"
  runsh "grep -E 'Summary \\[|tests? run:' $LOGD/cov-unit.log | tail -1 || true"
  if ((!DRY_RUN)); then
    record_cov_suite unit_tests nextest "$LOGD/cov-unit.exit" "$LOGD/cov-unit.log"
  fi
  # Driver suites consume prepared instrumented binaries, while nested
  # Cargo checks need the caller's ordinary compiler/cache/linker settings.
  # Restore each previous value, or unset keys introduced by show-env.
  show "restore ${COV_BUILD_ENV_KEYS[*]:-<every show-env key, CARGO_INCREMENTAL, CARGO_TARGET_DIR>}"
  if ((!DRY_RUN)); then
    for key in "${!COV_BUILD_ENV_RESTORE[@]}"; do
      eval "${COV_BUILD_ENV_RESTORE[$key]}"
    done
  fi
  export LLVM_PROFILE_FILE="$PWD/$COVT/out-%8m.profraw"
  timedsh_exit coverage_python_lane "$LOGD/cov-pytest.exit" \
    "tools/run-offline -- env BIOMCP_ROUTINE_TEST_LANE=1 BIOMCP_BIN=\$PWD/$COVT/debug/biomcp uv run --no-sync pytest tests/ -n 4 --dist loadfile --basetemp $LOGD/pytest-basetemp > $LOGD/cov-pytest.log 2>&1" "$LOGD/cov-pytest.log"
  runsh "grep -E '^=+ .* (passed|failed|error).* =+$' $LOGD/cov-pytest.log | tail -2 || true"
  if ((!DRY_RUN)); then
    record_cov_suite python_lane pytest "$LOGD/cov-pytest.exit" "$LOGD/cov-pytest.log"
  fi
  say coverage "spec lane against the instrumented dev binary (hand-written artifacts env)"
  runsh "cat > .cache/spec-artifacts.env <<'ENVEOF'
export BIOMCP_SPEC_ARTIFACT_MODE=spec
export BIOMCP_SPEC_FEATURE_OFF_BIN=$PWD/$COVT/debug/biomcp
export BIOMCP_SPEC_MCP_EXAMPLE_BIN=$PWD/$COVT/debug/examples/rmcp_streamable_http_contract
export BIOMCP_SPEC_CARGO_TREE=$PWD/.cache/spec-artifacts/cargo-tree-no-default-features.txt
export BIOMCP_SPEC_CARGO_METADATA=$PWD/.cache/spec-artifacts/cargo-metadata.json
export BIOMCP_BIN=$PWD/$COVT/debug/biomcp
ENVEOF
cat .cache/spec-artifacts.env"
  timedsh_exit coverage_spec_lane "$LOGD/cov-spec.exit" \
    "PATH=\"$PWD/$COVT/debug:\$PATH\" BIOMCP_SPEC_ARTIFACTS_PREPARED=1 ROUTINE_CARGO_FEATURES=--no-default-features SPEC_PROFILE=dev tools/run-offline -- bash scripts/run-specs.sh spec > $LOGD/cov-spec.log 2>&1" "$LOGD/cov-spec.log"
  runsh "tail -4 $LOGD/cov-spec.log || true"
  if ((!DRY_RUN)); then
    record_cov_suite spec_lane spec "$LOGD/cov-spec.exit" "$LOGD/cov-spec.log"
  fi
  # Reports: report merges every profraw under target/llvm-cov-target, so
  # the set not being reported moves aside first. Test code leaves the
  # report by path; inline #[cfg(test)] modules stay in, so these are the
  # llvm-cov view, not the span-reduced view of the iteration-speed study.
  # Field 10 of the TOTAL row is the Lines cover percentage.
  COV_REGEX='(^|/)(tests?|examples?|benches)/|(^|/)(tests?\.rs|_tests?\.rs|tests?_[^/]*\.rs)$|test_support|(^|/)generated/'
  echo "denominator, one rule for all three reports: product code only — removed by --ignore-filename-regex: files under a tests/, test/, examples/, example/, benches/ or bench/ directory; files named tests.rs, test.rs, _tests.rs, _test.rs, tests_*.rs or test_*.rs; any path containing test_support; files under a generated/ directory — inline #[cfg(test)] modules stay counted"
  COV_HOLD="$LOGD/cov-hold"
  mkdir -p "$COV_HOLD"
  for report_set in outside-in unit combined; do
    say coverage "report: $report_set"
    case "$report_set" in
      outside-in) aside="unit"; feeds="integration_tests python_lane spec_lane" ;;
      unit) aside="out"; feeds="unit_tests" ;;
      combined) aside=""; feeds="integration_tests python_lane spec_lane unit_tests" ;;
    esac
    if ((!DRY_RUN)); then
      if [[ -n "$aside" ]]; then
        show "mv $COVT/$aside-*.profraw $COV_HOLD/ (report the other set)"
        mv "$COVT"/$aside-*.profraw "$COV_HOLD"/ 2>/dev/null || true
      else
        show "mv $COV_HOLD/*.profraw $COVT/ (report everything)"
        mv "$COV_HOLD"/*.profraw "$COVT"/ 2>/dev/null || true
      fi
    fi
    # report discovers profraws and objects under target/llvm-cov-target on
    # its own, but only while no show-env export pins its search: the eval'd
    # CARGO_LLVM_COV_TARGET_DIR (printed before CARGO_TARGET_DIR was set, so
    # it names the plain target directory, which holds no profraws at its
    # top level) pins it. Driver suites already restored the caller's
    # environment; these report-only removals prevent any caller pins
    # from redirecting profile discovery.
    runsh "env -u CARGO_TARGET_DIR -u CARGO_LLVM_COV -u CARGO_LLVM_COV_SHOW_ENV -u CARGO_LLVM_COV_TARGET_DIR cargo llvm-cov report --ignore-filename-regex '$COV_REGEX' > $LOGD/cov-report-${report_set//-/_}.txt 2>&1 || { status=\$?; cat $LOGD/cov-report-${report_set//-/_}.txt >&2; exit \$status; }; tail -4 $LOGD/cov-report-${report_set//-/_}.txt"
    if ((!DRY_RUN)); then
      incomplete=""
      for feed in $feeds; do
        if [[ -n "${cov_suite_reason[$feed]:-}" ]]; then
          incomplete="${incomplete:+$incomplete, }${cov_suite_reason[$feed]}"
        fi
      done
      if [[ -n "$incomplete" ]]; then
        # a set fed by a failed or unproven suite never prints a number
        result "coverage_${report_set//-/_}_lines_pct" "incomplete ($incomplete)"
      else
        pct=$(awk '/^TOTAL/ {print $10}' "$LOGD/cov-report-${report_set//-/_}.txt" | tr -d '%')
        result "coverage_${report_set//-/_}_lines_pct" "${pct:-parse-failed}"
      fi
      if [[ -n "$aside" ]]; then
        show "mv $COV_HOLD/*.profraw $COVT/ (restore)"
        mv "$COV_HOLD"/*.profraw "$COVT"/ 2>/dev/null || true
      fi
    fi
  done
fi

# ---------------------------------------------------------------- run time (amendment)

if want_section runtime; then
  say runtime "run-time measurements with the release binary (thin LTO, one codegen unit)"
  # The host's real cache root follows the platform default: ~/.cache on
  # Linux, ~/Library/Caches on macOS.
  runsh 'HOST_CACHE=$(python3 -c "import sys; print(sys.argv[1] if sys.platform != \"darwin\" else sys.argv[2])" "$HOME/.cache/biomcp" "$HOME/Library/Caches/biomcp"); { find "$HOST_CACHE/http" -type f 2>/dev/null || true; } | wc -l; du -sh "$HOST_CACHE" 2>/dev/null || echo "no host cache"'
  show "python3 (five warm/cache-off pairs; ten drug-card pairs; raw samples, median and spread in seconds)"
  if ((!DRY_RUN)); then
    if RUN_SCRATCH="$PWD/$LOGD/runtime" python3 - <<'PY'
import hashlib
import json
import os
import statistics
import subprocess
import sys
import time
from pathlib import Path

bin_path = os.path.abspath("target/release/biomcp")
scratch = Path(os.environ["RUN_SCRATCH"])
scratch.mkdir(parents=True, exist_ok=True)
commands = {
    "get_gene_BRAF": ["get", "gene", "BRAF"],
    "get_variant_BRAF_V600E": ["get", "variant", "BRAF V600E"],
    "get_drug_imatinib": ["get", "drug", "imatinib"],
    "search_article_BRAF": ["search", "article", "-g", "BRAF", "--limit", "10"],
    "search_all_BRAF_melanoma": ["--json", "search", "all", "--gene", "BRAF", "--disease", "melanoma", "--counts-only"],
}
samples = []
summary = {}


def run_once(case, argv, cache, mode, phase):
    env = dict(os.environ)
    env["BIOMCP_CACHE_DIR"] = str(cache)
    if mode == "default":
        env.pop("BIOMCP_CACHE_MODE", None)
    else:
        env["BIOMCP_CACHE_MODE"] = mode
    cache.mkdir(parents=True, exist_ok=True)
    start = time.perf_counter()
    timed_out = False
    try:
        proc = subprocess.run([bin_path, *argv], capture_output=True, env=env, timeout=180)
        output, errors, code = proc.stdout, proc.stderr, proc.returncode
    except subprocess.TimeoutExpired as error:
        output, errors, code = error.stdout or b"", error.stderr or b"", None
        timed_out = True
    elapsed = time.perf_counter() - start
    stem = f"{len(samples):04d}-{case}-{phase}-{mode}"
    stdout_file, stderr_file = stem + ".stdout", stem + ".stderr"
    (scratch / stdout_file).write_bytes(output)
    (scratch / stderr_file).write_bytes(errors)
    gwas_errors = []
    try:
        payload = json.loads(output)
        gwas_errors = [section.get("error") for section in payload.get("sections", [])
                       if section.get("entity") == "gwas"]
    except (ValueError, AttributeError, TypeError):
        pass
    sample = dict(case=case, argv=argv, phase=phase, mode=mode,
                  cache_dir=os.path.relpath(cache, scratch), elapsed_s=elapsed,
                  exit_code=code, timed_out=timed_out, gwas_errors=gwas_errors,
                  stdout_file=stdout_file, stderr_file=stderr_file,
                  stdout_bytes=len(output), stdout_sha256=hashlib.sha256(output).hexdigest())
    samples.append(sample)
    (scratch / "samples.json").write_text(json.dumps(samples, indent=2) + "\n")
    if code != 0 or timed_out:
        print("failed command: " + " ".join([bin_path, *argv]), file=sys.stderr)
        print(output.decode(errors="replace"), file=sys.stderr, end="")
        print(errors.decode(errors="replace"), file=sys.stderr, end="")
    print(f"sample {stem}: {elapsed:.6f}s exit {code} timeout {timed_out} gwas {gwas_errors}", flush=True)
    return sample


def report(label, values):
    times = [sample["elapsed_s"] for sample in values]
    median = statistics.median(times)
    spread = max(times) - min(times)
    summary[label] = dict(median_s=median, spread_s=spread,
                          exit_codes=[sample["exit_code"] for sample in values],
                          timeouts=sum(sample["timed_out"] for sample in values))
    print(f"RESULT runtime_{label}_median_s = {median:.6f}")
    print(f"RESULT runtime_{label}_spread_s = {spread:.6f}")
    (scratch / "summary.json").write_text(json.dumps(summary, indent=2) + "\n")


large = Path.home() / ("Library/Caches/biomcp" if sys.platform == "darwin" else ".cache/biomcp")
for label, cache in (("empty_cache", scratch / "empty-cache"), ("large_cache", large)):
    values = [run_once("version", ["--version"], cache, "default", "measure") for _ in range(5)]
    report("version_" + label, values)

for case, argv in commands.items():
    warm = scratch / "warm-cache" / case
    run_once(case, argv, warm, "default", "prefetch")
    pairs = {"infinite": [], "off": []}
    for index in range(10 if case == "get_drug_imatinib" else 5):
        pairs["infinite"].append(run_once(case, argv, warm, "infinite", "measure"))
        # Each bypass gets its own root. It cannot migrate, clean or erase warm data.
        off = scratch / "off-cache" / case / str(index)
        pairs["off"].append(run_once(case, argv, off, "off", "measure"))
    for mode, label in (("infinite", "warm"), ("off", "nocache")):
        report(label + "_" + case, pairs[mode])

# Default mode observes the day-cache rule, separately from infinite mode.
# Drug cards include openFDA labels/counts plus uncached providers: live timing
# alone does not prove absence of provider requests.
for case, argv in {
    "day_gwas_BRAF": ["--json", "search", "gwas", "-g", "BRAF"],
    "day_openfda_drug_imatinib": ["get", "drug", "imatinib"],
}.items():
    warm = scratch / "day-cache" / case
    run_once(case, argv, warm, "default", "prefetch")
    values = [run_once(case, argv, warm, "default", "measure") for _ in range(5)]
    report(case, values)

raise SystemExit(1 if any(s["exit_code"] != 0 or s["timed_out"] for s in samples) else 0)
PY
    then
      :
    else
      FAILED=1
    fi
  fi
fi

if want_section edit-test-group; then
  say edit-test-group "one Rust edit followed by one existing gene-render test group"
  runsh 'touch src/render/markdown/gene.rs'
  timedsh_exit edit_test_group "$LOGD/edit-test-group.exit" \
    "tools/run-offline -- tools/with-build-identity cargo nextest run --locked --no-default-features --lib -E 'test(gene_markdown)' > $LOGD/edit-test-group.log 2>&1" "$LOGD/edit-test-group.log"
  if ((!DRY_RUN)); then
    result edit_test_group_exit "$(<"$LOGD/edit-test-group.exit")"
    if [[ "$(<"$LOGD/edit-test-group.exit")" != 0 ]] || ! grep -qE 'Summary .* [1-9][0-9]* tests? run:' "$LOGD/edit-test-group.log"; then
      result edit_test_group_collection "incomplete (failed or empty test group; retain log)"
    else
      result edit_test_group_collection complete
    fi
  fi
fi

# ---------------------------------------------------------------- ci history

if want_section ci-history; then
  say ci-history "the last ten green CI runs of ci.yml (wall time and runner-minutes)"
  show "gh api + python3 (per run: updated_at - run_started_at; runner-minutes summed over jobs)"
  if ((!DRY_RUN)); then
    python3 - <<'PY'
import json
import subprocess
from datetime import datetime

def gh(path):
    out = subprocess.run(["gh", "api", path], check=True, capture_output=True, text=True)
    return json.loads(out.stdout)

def parse(iso):
    return datetime.fromisoformat(iso.replace("Z", "+00:00"))

try:
    runs = gh("repos/genomoncology/biomcp/actions/workflows/ci.yml/runs?status=success&per_page=10")
except (subprocess.CalledProcessError, FileNotFoundError) as error:
    print(f"skipped: gh api unavailable or unauthenticated ({error})")
    raise SystemExit(0)
walls = []
runner_totals = []
for run in runs.get("workflow_runs", []):
    start = run.get("run_started_at") or run.get("created_at")
    wall = (parse(run["updated_at"]) - parse(start)).total_seconds() / 60.0
    jobs = gh(f"repos/genomoncology/biomcp/actions/runs/{run['id']}/jobs?per_page=100")
    job_minutes = 0.0
    for job in jobs.get("jobs", []):
        if job.get("completed_at") and job.get("started_at"):
            job_minutes += (parse(job["completed_at"]) - parse(job["started_at"])).total_seconds() / 60.0
    walls.append(wall)
    runner_totals.append(job_minutes)
    print(f"run {run['id']} {run['head_sha'][:9]} {start} wall {wall:.1f}m runner {job_minutes:.1f}m")
walls_sorted = sorted(walls)
print(f"RESULT ci_green_runs = {len(walls)}")
print(f"RESULT ci_wall_minutes_median = {walls_sorted[len(walls_sorted) // 2]:.1f}")
print(f"RESULT ci_wall_minutes_range = {walls_sorted[0]:.1f}-{walls_sorted[-1]:.1f}")
print(f"RESULT ci_runner_minutes_mean = {sum(runner_totals) / len(runner_totals):.1f}")
full = [(w, r) for w, r in zip(walls, runner_totals) if r > 30.0]
full_walls = sorted(w for w, _ in full)
if full:
    print(f"RESULT ci_full_runs = {len(full)} (runner-minutes over 30; docs-only runs excluded)")
    print(f"RESULT ci_full_wall_minutes_median = {full_walls[len(full_walls) // 2]:.1f}")
    print(f"RESULT ci_full_wall_minutes_range = {full_walls[0]:.1f}-{full_walls[-1]:.1f}")
    print(f"RESULT ci_full_runner_minutes_mean = {sum(r for _, r in full) / len(full):.1f}")
PY
  fi
fi

# ---------------------------------------------------------------- host after

if want_section host-after; then
  say host-after "machine conditions at the end"
  runsh 'cat /proc/loadavg 2>/dev/null || uptime'
  runsh 'free -g 2>/dev/null | sed -n 1,2p || vm_stat | head -5'
  runsh 'df -h . | tail -1'
fi

printf '\n### done — measurement complete\n'
exit "$FAILED"
