v3.18.1 — Concurrency & Determinism Fixes
Concurrency and determinism fixes for multi-agent / parallel-invocation use, found by an adversarially-verified multi-agent audit of 3.18.0. Each fix ships with regression tests.
Fixed
pmat record-metricno longer loses history —record()previously overwrote<metric>.jsonwith only its own observation. It now reloads under an exclusive fs2 advisory lock (bounded 5s wait), appends, and persists via atomic scratch-then-rename. Torn pre-3.18.1 history files self-heal (moved aside to.json.corrupt).- Fixed machine-global temp paths in
tdg check-regression,tdg baseline compare, andtdg check-quality— concurrent invocations no longer clobber each other's ephemeral comparison state (PID + per-process-counter unique paths). - Deterministic TDG baseline serialization —
files,grade_distribution,languagesare now BTreeMaps: sorted keys, byte-stable output across runs and machines. Pre-3.18.1 baselines load unchanged.TdgBaseline::save()is now atomic. tdg baseline create --nameis honored — previously accepted and silently discarded; now a persisted label, shown inbaseline list --format jsonand preserved bybaseline update.- SQLite index save scratch is process-unique — concurrent savers can no longer rename each other's half-built DB into place; crash-orphaned scratch files (50–275 MB) are swept after 1h via the new
utils::scratchhelper. pmat verifyspec drift — removed afixablefield from the spec example that the shipped struct doesn't have.
Validation
pmat verify --format json→ok: true(format, complexity, satd, clippy-D warnings, full test suite)- 111-command full-CLI dogfood with the release binary: 0 regressions, 0 release blockers
- End-to-end: 6-way concurrent
record-metricwith zero lost updates; parallelcheck-regressionwith zero scratch leftovers; byte-identical baseline re-creation
Full details: CHANGELOG and pmat-book ch73.
🤖 Generated with Claude Code