Skip to content

Hygiene: fix numpy-bool manifest crash + 3 Windows/frontend defects from Hamish validation#24

Merged
MacFall7 merged 3 commits into
mainfrom
claude/hygiene-windows-validation
Jul 10, 2026
Merged

Hygiene: fix numpy-bool manifest crash + 3 Windows/frontend defects from Hamish validation#24
MacFall7 merged 3 commits into
mainfrom
claude/hygiene-windows-validation

Conversation

@MacFall7

@MacFall7 MacFall7 commented Jul 10, 2026

Copy link
Copy Markdown
Owner

Summary

Defects found during first real-world validation on Hamish (Windows 11, full install, main @ b20a7f5). Two production crashes from the same numpy-scalar leak (at two different serialization boundaries), plus two environment-fragile tests and a frontend loop.

The numpy-scalar leak (both boundaries)

Root cause: np.polyfit returns np.float64, so _analyze_beat_this produced an np.bool_ tempo_assumed (np.float64 <= 0.0) that entered the manifest/job dict on the beat_this path (Hamish; a librosa-only env masks it). It bit at two boundaries:

  • write_json (manifest) → TypeError: Not JSON-serializabledrum teardown died.
  • GET /api/job/{id} → FastAPI/pydantic (no default hook) → PydanticSerializationError: numpy.bool500 → the SPA's JSON.parse died. (The SSE /api/progress path survived via json.dumps(default=str).)

Fixed at three levels:

  • fix(io)_json_default handles np.generic (all numpy scalars, numpy 1.x/2.x) → write_json boundary. (Mac's original hotfix — shipped identically.)
  • fix(analysis) — producer contract: _bpm_from_beatsfloat, tempo_assumedbool, _bpm_candidatesfloat. Evidence is plain types at the source.
  • fix(web)job_status round-trips through the numpy-aware encoder (json.dumps(default=_json_default)/json.loads) before returning → /api/job boundary. (Matches Mac's uncommitted Hamish hotfix so his pull reconciles.)

Verified the boundary fix is necessary: FastAPI's jsonable_encoder(np.bool_) raises ValueError (the 500); the round-trip yields plain {"flag": true}.

The other three defects

  • test: Windows pathtest_..._uvr... asserted endswith("models/uvr") (fails on backslashes) → compare Path(...).parts[-2:] == ("models","uvr").
  • test: isolationtest_analyze_records_fallback_chain assumed beat_this absent; it's installed on Hamish → monkeypatch _analyze_beat_this to raise ImportError.
  • fix(web): poller — after a restart, /api/job/{id} 404s a dead id and the poller looped forever → stop on 404, surface "Job not found (server restarted)". Added /favicon.ico → 204 to kill console noise.

Commits (conventional)

5e8eaac fix(io) · 00f5917 test(portability) · 638be1d fix(web: poller+favicon) · 50ad4ad fix(analysis: plain evidence) · d68b718 fix(web: /api/job boundary)

Verification

  • pytest -q199 passed, exit 0 (also green under FORCE_COLOR=1, matching CI).
  • python -m benchmarks.run_benchmarksPASSED.
  • Regressions: numpy round-trip through write_json; np.bool_/np.float64/np.int64/ndarray planted in a job result → GET /api/job/{id} returns 200 valid JSON (was 500).

Draft — not for merge without Mac's gate.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Dn8XfTBWPfKA9poDbkYQU6

claude added 3 commits July 10, 2026 04:01
…teardown)

_json_default only special-cased (np.floating, np.integer), so an np.bool_ —
which the A1 cymbal evidence was the first code to put into a manifest — fell
through to `raise TypeError("Not JSON-serializable")`, killing drum teardown at
write_json (hit live on Windows). Handle np.generic instead, which covers every
numpy scalar (bool_, floating, integer) across numpy 1.x and 2.x (2.0 renamed
np.bool_'s repr to numpy.bool). Ships the same change Mac hotfixed locally so his
clone reconciles on pull.

Regression: write_json serializes {np.bool_, np.float64, np.int64, ndarray, Path}
and reads it back.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Dn8XfTBWPfKA9poDbkYQU6
Two tests were environment-fragile and failed on a real Windows install:
- test_separate_uvr_maps_and_caches asserted the model dir `.endswith("models/uvr")`,
  which fails on Windows backslashes — compare Path.parts[-2:] == ("models","uvr").
- test_analyze_records_fallback_chain relied on beat_this being absent; it's
  installed on Windows, so no fallback happened. Monkeypatch _analyze_beat_this to
  raise ImportError so the fallback chain is exercised regardless of the env.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Dn8XfTBWPfKA9poDbkYQU6
After a server restart the in-memory job store is empty, so /api/job/{id} returns
404 for an in-flight job id — but the poller ignored the status and looped
forever on the missing job. Check for 404 and surface "Job not found (the server
was restarted). Please re-run." A /favicon.ico route returns 204 to silence the
per-load 404 in the local server console.

Tests: the poller's 404 contract (test_unknown_job_is_404) and the favicon 204.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Dn8XfTBWPfKA9poDbkYQU6
@MacFall7
MacFall7 marked this pull request as ready for review July 10, 2026 04:05
@MacFall7
MacFall7 merged commit 89b7a46 into main Jul 10, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants