Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ jobs:
"5_thermal_load", "6_display", "7_physical",
"8_apple_diagnostics", "9_idle_drain",
"10_race_bench", "11_ssd_test", "12_memory_bandwidth",
"13_gpu_variance"]
"13_gpu_variance", "14_llama_bench"]
FILENAME_RE = re.compile(r"^\d{4}-\d{2}-\d{2}-[a-z0-9-]+-[0-9a-f]{4}\.json$")

def find_keys(obj, predicate, path=""):
Expand Down
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,15 @@ All notable changes to this project are documented here. Format follows [Keep a

## [Unreleased]

### Added: in-store verification toolkit (wave 8)

- **`--store` thorough profile.** One flag for verifying a new unit (M5 especially): turns on `--noaccel` and `--gpu` and runs a longer warmup with more iterations, so an intermittent batch defect has more chances to surface. Honors any timing env vars the user set.
- **`compare-reports.sh`.** Diffs two reports side by side (a known-good sibling vs the unit under test) and flags every metric where the unit materially trails. Since the absolute thresholds aren't calibrated yet, this unit-to-unit comparison is the most trustworthy in-store signal.
- **Benchmark Reference** (`Verification/Benchmark Reference.md`). Install-this / run-this / expected-score guide with sourced, adversarially-verified Cinebench R24 + Geekbench 6 baselines per generation (M1-M5 families + Intel 2019), the in-store and hotel protocols, the Hong Kong return constraint, and live-lookup links (Geekbench Browser, mianibench.com crowd distributions). Corrected the stale M5 Max baseline in the m5-2026 calibration (~25-28k to ~29,000-29,400 GB6 multi-core).
- **Phase 12 STREAM triad.** Memory bandwidth now prefers a vendored single-file STREAM triad (`stream-triad.c`: real copy / scale / add / triad), compiled at runtime with clang, no network. Falls back to the pure-Python `memmove` proxy when clang is unavailable. Closes the copy-only-proxy gap; `details.method` records which ran.
- **Phase 14 `--llama` (opt-in).** Clones and builds llama.cpp at a pinned ref and runs `llama-bench`, a combined CPU+GPU+memory AI load (the workload class the M5 defect was reported on). Off by default; it reaches the network and runs third-party code (disclosed in SECURITY.md) and skips cleanly without git / cmake / network / model.
- **Schema 1.3.** Phase 12 gains the triad method and `*_triad_gb_per_s` fields; new phase key `14_llama_bench` (a `skipped` placeholder by default), added to the CI submission-audit required-phase list. Backward compatible: both phase-12 methods keep `mean_copy_gb_per_s`, and 14 is skipped unless opted in.

### Added: roadmap completion (wave 7)

- **Phase 4b non-accelerated CPU variance** (`cpu-variance.sh WORKLOAD=blake2b`, opt-in `./run --noaccel`). Reruns the Phase 4 variance methodology with BLAKE2b, which has no dedicated CPU instruction and so exercises the integer pipelines and memory instead of the SHA engine. Catches batch defects that SHA-NI / the Apple crypto coprocessor hide. Same script and verdict logic as Phase 4 (no duplicated thresholds): real `pass`/`warn`/`fail` when run, `skipped` placeholder otherwise. Runs on the already-hot chassis after Phase 4 with a short re-warm and no cold burst. Adds ~6 min when enabled.
Expand Down
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ The verification scripts and runbook **don't need to change**. They're calibrati

## Improving a script

The scripts in `Verification/scripts/` are deliberately self-contained: bash plus Python heredocs, no external dependencies beyond what ships with macOS. Keep it that way. If you need to add a third-party benchmark (Geekbench, sysbench), or something that genuinely needs more than the stdlib (the opt-in `--gpu` phase compiles a Metal kernel with `swiftc` at runtime), make it optional and have it skip cleanly when the dependency is absent, so the default `./run` stays pure bash plus Python stdlib.
The scripts in `Verification/scripts/` are deliberately self-contained: bash plus Python heredocs, no external dependencies beyond what ships with macOS. Keep it that way. Two patterns in the tree show how to go further without breaking that: a vendored single-file source compiled at runtime with a pure fallback (the Phase 12 STREAM triad, `stream-triad.c`, falls back to a `memmove` proxy, and never touches the network), and a strictly opt-in phase that may use the network or third-party code (the `--gpu` Metal compile and the `--llama` llama.cpp clone/build), off by default, skipping cleanly when unavailable, and disclosed in [SECURITY.md](SECURITY.md). The default `./run` stays pure bash plus Python stdlib and offline; anything beyond that is opt-in and disclosed.

### Validating changes to a script

Expand Down
17 changes: 13 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,9 @@ Or without a preset, which auto-detects chassis class from `system_profiler` (fi
./run
```

The orchestrator runs the automated phases (preflight → inventory → battery → race benchmark → SSD test → memory bandwidth → CPU variance → thermal load) end-to-end, asks for sudo once upfront (Phase 5 and the SSD page-cache drop need it), and writes a SCHEMA-compliant report to `Reports/local/` plus a sanitized PR-able copy to `Reports/submissions/`. Two heavier passes are opt-in: `--noaccel` adds a non-accelerated (BLAKE2b) variance pass, and `--gpu` adds a Metal GPU compute pass. Runtime ~20 min on Intel, ~27 min on Air, ~47 min on MacBook Pro (add ~6 min for `--noaccel`).
The orchestrator runs the automated phases (preflight → inventory → battery → race benchmark → SSD test → memory bandwidth → CPU variance → thermal load) end-to-end, asks for sudo once upfront (Phase 5 and the SSD page-cache drop need it), and writes a SCHEMA-compliant report to `Reports/local/` plus a sanitized PR-able copy to `Reports/submissions/`. Opt-in flags add heavier passes: `--noaccel` (a non-accelerated BLAKE2b variance pass), `--gpu` (a Metal GPU compute pass), and `--llama` (clones and builds llama.cpp for a combined CPU+GPU+memory AI load). `--store` bundles the thorough profile for verifying a new unit. Runtime ~20 min on Intel, ~27 min on Air, ~47 min on MacBook Pro.

> Verifying a new purchase, especially in a store you can't easily return to? The [Benchmark Reference](Verification/Benchmark%20Reference.md) is the install-this / run-this / expected-score guide (sourced per-generation Cinebench + Geekbench baselines, the in-store and hotel protocols, and crowd-sourced live-lookup links). To diff your unit against a known-good sibling, run `Verification/scripts/compare-reports.sh reference.json yours.json`.

`./run --no-sudo` skips the 10-min thermal phase (the only phase that needs sudo) for a half-runtime no-password variance-only pass.

Expand All @@ -61,11 +63,12 @@ See [`examples/sample-report-illustrative/`](examples/sample-report-illustrative
| 3 | Sensor & port inventory | (uses Phase 1 output) |
| 10 | Race benchmark (cold) | `xz -9 -T<P>` of a 200 MB random blob → `race-bench.sh` |
| 11 | SSD sequential read/write (cold) | 2 GB incompressible random data, page cache dropped between → `ssd-test.sh` |
| 12 | Memory bandwidth (cold) | multi-threaded `memmove` over cache-busting buffers → `memory-bandwidth.sh` |
| 12 | Memory bandwidth (cold) | multi-threaded STREAM triad (vendored C, clang at runtime) with a `memmove` fallback → `memory-bandwidth.sh` |
| 4 | **CPU performance variance** | 5 s burst + chassis-class-aware warmup (300 s on Pro, 60 s on Air) + 5 × 60 s timed iterations, parallel SHA-256 → `cpu-variance.sh` |
| 4b | Non-accelerated CPU variance (opt-in `--noaccel`) | same methodology with BLAKE2b (no crypto instruction, hits the integer pipelines) → `cpu-variance.sh` |
| 5 | Sustained thermal load (chassis-class-aware thresholds) | 10 min continuous + `powermetrics` sampling → `thermal-load.sh` |
| 13 | GPU compute variance (opt-in `--gpu`) | sustained Metal FMA load, compiled with `swiftc` at runtime → `gpu-variance.sh` |
| 14 | Combined CPU+GPU+memory (opt-in `--llama`) | clones + builds llama.cpp, runs `llama-bench` (AI inference load) → `llama-bench.sh` |
| 6 | Display visual inspection | fullscreen color cycle in Safari → `display-test.sh` |
| 7 | Manual physical inspection | hinge, keyboard, speakers, ports, Touch ID, etc. (runbook checklist) |
| 8 | Apple Diagnostics | reboot + Cmd-D |
Expand Down Expand Up @@ -114,16 +117,21 @@ mac-shakedown/
├── Verification/ # generation-agnostic test machinery
│ ├── Runbook.md # the procedure
│ ├── Pass-Fail Criteria.md # thresholds (parameterized by chassis class)
│ ├── Benchmark Reference.md # install/run/expected-score + in-store protocol
│ ├── per-core-pinning.md # why macOS has no per-core affinity (methodology note)
│ └── scripts/
│ ├── run-shakedown.sh # the orchestrator (`./run` execs this)
│ ├── inventory.sh # system_profiler + sysctl → JSON
│ ├── battery.sh # ioreg battery health → JSON
│ ├── race-bench.sh # cold xz race → JSON
│ ├── ssd-test.sh # sequential SSD read/write → JSON (sudo for purge)
│ ├── memory-bandwidth.sh # multi-threaded memmove bandwidth → JSON
│ ├── memory-bandwidth.sh # STREAM triad (stream-triad.c) or memmove fallback → JSON
│ ├── stream-triad.c # vendored STREAM-style triad, compiled at runtime
│ ├── cpu-variance.sh # burst + warmup + 5×60s timed iters → JSON (WORKLOAD=blake2b for 4b)
│ ├── thermal-load.sh # 10-min sustained + powermetrics → JSON (sudo)
│ ├── gpu-variance.sh # opt-in Metal compute variance, swiftc at runtime → JSON
│ ├── llama-bench.sh # opt-in llama.cpp combined load (clone+build) → JSON
│ ├── compare-reports.sh # diff two reports (unit vs known-good sibling)
│ └── display-test.sh # fullscreen color cycle (HTML)
├── targets/ # preset SKU configs
│ ├── README.md
Expand Down Expand Up @@ -180,12 +188,13 @@ The manual phases (display, physical inspection, Apple Diagnostics, idle drain)

Wave 7 shipped most of the original roadmap: the non-accelerated variance pass (Phase 4b, BLAKE2b), GPU compute variance (Phase 13, Metal), memory bandwidth (Phase 12), a conservative SSD floor, the `active-cooled-pro-14` / `active-cooled-pro-16` thermal sub-classes, and M1-M4 plus Intel-era generation calibrations.

Wave 8 added the in-store toolkit: the `--store` thorough profile, `compare-reports.sh` (diff your unit against a known-good sibling), a sourced [Benchmark Reference](Verification/Benchmark%20Reference.md), a vendored STREAM triad in Phase 12 (real copy / scale / add / triad), and an opt-in `--llama` phase that builds llama.cpp for a combined CPU+GPU+memory load.

Still open:

- **Hosted aggregator.** Eventually, submission via API to a public site so reports aren't reviewed by hand. Until then, the PR-submission flow above *is* the aggregator. Slower, but no infra, and PR review catches PII before merge.
- **Calibrated v0.3 thresholds.** The race / SSD / memory-bandwidth / GPU phases are informational in v0.2. Once the submission corpus has per-SKU baselines, they get chassis-family pass/fail bands. The SSD floor is the only band today, and it's a conservative sanity floor (flags below 500 MB/s with the cache dropped), not a calibrated range.
- **Per-core pinning.** macOS lacks public CPU affinity APIs, so we can't pin workers to specific cores; a defective single core gets averaged across N P-cores. Reporting `worker_imbalance_pct_per_iter` is the partial mitigation. The investigation is written up in [`Verification/per-core-pinning.md`](Verification/per-core-pinning.md): the short version is that `THREAD_AFFINITY_POLICY` is ignored on Apple Silicon and QoS hints only steer between the P and E clusters, so there's no per-core pinning to be had today.
- **Full STREAM triad.** Phase 12 measures copy bandwidth via `memmove` (a lower bound on the memory subsystem). Scale / add / triad need a native kernel, which would break the pure-stdlib property of the default run.

## Origin

Expand Down
Loading