mirror of
https://github.com/hanzoai/datastore.git
synced 2026-10-30 14:48:37 +00:00
Four findings from a critical re-read of the recently-added scripts. None are bugs in the strict sense, but each makes the code easier for a future reader (or a future Claude editing it) to understand without re-deriving intent. 1. `build_commit_diff.py:50` — when a SHA isn't found, the error suggestion was `sorted(by_sha8.keys())[:8]` (alphabetically-first 8 SHAs). For a typo like `fdf46xxx → fdf46ee1`, the user got a list of `00..` / `01..` SHAs and had to spot the close match themselves. Switch to longest-common-prefix ranking via a small `_common_prefix` helper, so the actual close match floats to the top. Verified: `diff fdf46xxx zzzz0000` now suggests `fdf46ee1` first for the typo and falls back to alphabetical for the no-prefix-match input. 2. `build_commit_diff.py:60` — `delta_pct` had four distinct semantics (missing data, 0→0, 0→positive, normal) implemented correctly but unexplained. Add a 4-line comment so a future editor doesn't "fix" the 0→0 → "" branch into a 0. 3. `build_noise_stats.py:55` — `statistics.stdev(values) if len(values) >= 2 else 0.0` had a dead `else` branch, since the outer `if len(values) < MIN_RUNS: continue` already guaranteed `len(values) >= 3`. Drop the conditional and add a one-line comment naming the invariant. 4. `build_noise_stats.py:57` — `statistics.quantiles(values, n=20)[18]` is the 95th percentile, but a future reader had to know that `n=20` returns 19 cut points and that index 18 is the 95 % mark. Add a 3-line comment explaining the magic number and the `< 4` fallback to `max`. No behavior change for any well-formed input. Smoke parity preserved: `cumulative_gains.tsv` md5 unchanged at `e5a27e01008ef7e23597ee041f68103b`; `#99651` row bit-identical; 18 unit tests pass.
90 lines
3.8 KiB
Python
90 lines
3.8 KiB
Python
#!/usr/bin/env python3
|
|
"""Per-(scenario, backend, metric) noise characterization.
|
|
|
|
For each (scenario, backend) group in `merged_metrics.tsv`, computes the
|
|
median, sample stddev, coefficient of variation (`cv = stddev / |median|`),
|
|
and p95 of every metric in `_common.HEADLINE_METRICS` across the available
|
|
runs. Output: `noise_stats.tsv` — one row per (scenario, backend, metric).
|
|
|
|
The use case is calibration. The skill claims a ~5 % rps noise floor and
|
|
~10 % p99 noise floor (see `references/methodology.md`); this output lets
|
|
a future Claude verify those claims hold across the current dataset and
|
|
flag scenarios that are notably noisier than the others.
|
|
|
|
Skips (scenario, backend) pairs with `< 3` runs because stddev is only
|
|
meaningful with at least three points (matching the spirit of
|
|
`build_cumulative_gains.py`'s `< 2 * WINDOW_SIZE` skip, but lower because
|
|
this is descriptive rather than median-of-3-vs-3).
|
|
"""
|
|
import csv
|
|
import statistics
|
|
import sys
|
|
from collections import defaultdict
|
|
from pathlib import Path
|
|
|
|
from _common import HEADLINE_METRICS, to_float
|
|
|
|
ROOT = Path(__file__).parent
|
|
|
|
MIN_RUNS = 3
|
|
|
|
|
|
def main():
|
|
by_sb = defaultdict(list) # (scenario, backend) -> list of row dicts
|
|
with open(ROOT / "merged_metrics.tsv") as f:
|
|
for r in csv.DictReader(f, delimiter="\t"):
|
|
by_sb[(r["scenario"], r["backend"])].append(r)
|
|
|
|
out_path = ROOT / "noise_stats.tsv"
|
|
cols = ["scenario", "backend", "metric", "n_runs",
|
|
"median", "stddev", "cv", "p95"]
|
|
skipped = []
|
|
with open(out_path, "w", newline="") as fout:
|
|
w = csv.writer(fout, delimiter="\t", lineterminator="\n")
|
|
w.writerow(cols)
|
|
for (sc, be), rows in sorted(by_sb.items()):
|
|
if len(rows) < MIN_RUNS:
|
|
skipped.append((sc, be, len(rows)))
|
|
continue
|
|
for metric, _ in HEADLINE_METRICS:
|
|
# Include zeros: for non-negative metrics like `error_pct`,
|
|
# zero is the dominant baseline. Excluding it would bias the
|
|
# noise sample upward and make a stable metric look noisy.
|
|
# Only `None` (parse failure / missing column) is dropped.
|
|
values = [v for v in (to_float(r.get(metric)) for r in rows)
|
|
if v is not None and v >= 0]
|
|
if len(values) < MIN_RUNS:
|
|
continue
|
|
med = statistics.median(values)
|
|
# `len(values) >= MIN_RUNS = 3` here, so `stdev` is always defined.
|
|
sd = statistics.stdev(values)
|
|
# `cv` is undefined when the median is exactly zero (which
|
|
# is common for `error_pct` on healthy windows). Emit "" to
|
|
# mark "no scale to normalise against" rather than 0.
|
|
cv = (sd / abs(med)) if med > 0 else None
|
|
# `quantiles(n=20)` returns 19 cut points splitting the data
|
|
# into 20 equal buckets; index 18 is the cut between buckets
|
|
# 19 and 20 → the 95th percentile. For `len < 4` we don't have
|
|
# enough points to estimate a p95, so fall back to `max`.
|
|
p95 = (statistics.quantiles(values, n=20)[18]
|
|
if len(values) >= 4 else max(values))
|
|
w.writerow([
|
|
sc, be, metric, len(values),
|
|
f"{med:.4f}", f"{sd:.4f}",
|
|
f"{cv:.4f}" if cv is not None else "",
|
|
f"{p95:.4f}",
|
|
])
|
|
print(f"Wrote {out_path}", file=sys.stderr)
|
|
if skipped:
|
|
print(
|
|
f"Skipped {len(skipped)} (scenario, backend) pair(s) "
|
|
f"with < {MIN_RUNS} runs:",
|
|
file=sys.stderr,
|
|
)
|
|
for sc, be, n in skipped:
|
|
print(f" {sc} [{be}]: {n} run(s)", file=sys.stderr)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|