go-data-race-completion-path-global
Done. I built a faithful before/after reproducer, captured the real race-detector output, applied the return-value fix, and verified it.
Deliverable: ~/go-data-race-completion-path-global.md
Root cause (confirmed by live -race output): A package-level priceAsOf string was written inside computeCostUSD (invoked by every tick-completion goroutine) and read later at outcome assembly. The trace named computeCostUSD on both sides of a write/write race and again against processCompletion's read — the classic "same function, package address" signature of an unsynchronized global. The claimed priceAsOfMu guard was never locked.
Fix applied in ~/race-lab/after/tick.go:
- Deleted the global and the unused mutex.
- Kept the frozen computeCostUSD(t Tick) float64 signature, made it pure.
- Added computeCostUSDWithAsOf(t Tick) (cost float64, priceAsOf string) as a thin wrapper.
- At the call site: cost, asOf := computeCostUSDWithAsOf(t) and set Outcome.PriceAsOf = asOf.
Verification (actual runs):
- Before: go test -race -count=1 ./... → exit 1, 2× WARNING: DATA RACE.
- After: go test -race -count=1 ./... → ok tickafter 1.020s, exit 0.
- Re-ran the exact failing tests by name: both PASS.
- Frozen signature preserved; no package-global references remain.
The document includes the gh run view <id> --log-failed | grep "WARNING: DATA RACE" diagnostic path, the full root-cause analysis, the diff, and a reviewer checklist.
# Evidence - Problem class: go-data-race-completion-path-global - Model: openrouter/deepseek/deepseek-v4.1-flash - Solved: 2026-10-10T20:56:50.521Z - Verification: solution produced by pi in sandbox; see signatures.json
{"description": "Go scheduler: a package-level string global (price-as-of stamp) written inside a cost-computation helper called from every tick-completion goroutine and read at completion-assembly sites -> DATA RACE (CI race job red on 4 runs; failures surface in unrelated concurrent tests). Diagnosis: gh run view <id> --log-failed + grep WARNING: DATA RACE gives the exact write/write stack (same function both sides = unsynchronized global); comment claimed locking that did not exist. Fix that worked: eliminate the global entirely - return the stamp alongside the cost from a thin computeCostUSDWithAsOf wrapper (frozen signature kept), populate the outcome field from the return value at the call sites. Verify: go test -race -count=1 package green + the exact failing tests re-run. Lesson: any value captured on one goroutine and consumed at outcome-assembly must travel as a return value, never via a package global, even when values are identical across goroutines.", "environment": "", "language": "", "model": "openrouter/deepseek/deepseek-v4.1-flash", "problem_class": "go-data-race-completion-path-global", "provider": "openrouter", "solved_at": "2026-10-10T20:56:50.521Z", "version": ""}