Overview
Phase 4a of the hygiene perf mode (prompt: PyAutoMind/issued/hygiene_unit_test_timing.md). Time the library unit suites, track a rolling per-test baseline, flag slow-test regressions; hygiene perf surfaces + routes them. Mirrors the shipped import_time leg (#62): a tracked signal in Heart, hygiene acts.
Plan
heart/checks/unit_test_timing.py — off-tick (running suites is minutes → daily cron / on-demand, NOT tick.sh). Runs pytest --durations=N -q per library in a subprocess (rule 4: Heart never imports the test stack; the runner is injected so stdlib-only tests use fixtures). Parses the slowest-durations section, rolling baseline in ~/.pyauto-heart/timings-unit/, ratio-vs-median classify (1.5/3.0), writes ~/.pyauto-heart/unit_test_timing.json, colored summary.
state.py aggregate + dashboard.py advisory section (local-only family) — not in the readiness gating set.
- stdlib-only tests with injected duration source.
- Follow-on (PyAutoBrain): hygiene
perf reads unit_test_timing.json when present (fallback silent), like #93.
Design note
Greenfield — no --durations in any library pytest config; test_run tracks pass/fail + slow-skips, not per-test durations. Chose off-tick self-run (option b) over read-CI-artifact (option a) for a self-contained single-repo first cut; the runner is injected so switching sources later is cheap.
Boundary
Developer-loop cost (unit-suite speed) — hygiene, distinct from /profiling (likelihood/modeling) and test_run (release pass/fail). Slow-but-correct tests are marked, not force-optimized.
Siblings: 4b workspace test-mode timing, 4c function profiling.
Overview
Phase 4a of the hygiene
perfmode (prompt:PyAutoMind/issued/hygiene_unit_test_timing.md). Time the library unit suites, track a rolling per-test baseline, flag slow-test regressions; hygieneperfsurfaces + routes them. Mirrors the shippedimport_timeleg (#62): a tracked signal in Heart, hygiene acts.Plan
heart/checks/unit_test_timing.py— off-tick (running suites is minutes → daily cron / on-demand, NOT tick.sh). Runspytest --durations=N -qper library in a subprocess (rule 4: Heart never imports the test stack; the runner is injected so stdlib-only tests use fixtures). Parses the slowest-durations section, rolling baseline in~/.pyauto-heart/timings-unit/, ratio-vs-median classify (1.5/3.0), writes~/.pyauto-heart/unit_test_timing.json, colored summary.state.pyaggregate +dashboard.pyadvisory section (local-only family) — not in the readiness gating set.perfreadsunit_test_timing.jsonwhen present (fallback silent), like #93.Design note
Greenfield — no
--durationsin any library pytest config;test_runtracks pass/fail + slow-skips, not per-test durations. Chose off-tick self-run (option b) over read-CI-artifact (option a) for a self-contained single-repo first cut; the runner is injected so switching sources later is cheap.Boundary
Developer-loop cost (unit-suite speed) — hygiene, distinct from
/profiling(likelihood/modeling) andtest_run(release pass/fail). Slow-but-correct tests are marked, not force-optimized.Siblings: 4b workspace test-mode timing, 4c function profiling.