fix(post_de_cruft_iter4): fix 3 new failures revealed by full batched run

1. tier-1-unit-core::test_app_controller_warmup_done_ts_none_until_completed
   - Race condition: warmup_done_ts was set before the test could read it
     (warmup runs in a background thread that can complete in milliseconds).
   - Fix: use defer_warmup=True + call start_warmup() explicitly so we can
     observe the initial state before warmup begins.

2. tier-1-unit-core::test_fetch_models_aggregates_per_provider_errors
   - Race condition: _fetch_models submits do_fetch to the IO pool; the
     test asserted _model_fetch_errors synchronously before the worker ran.
   - Fix: call wait_io_pool_idle() before asserting the side effect.
   - Test passes in isolation but fails when run as part of the full file
     (IO pool is hot from prior tests).

3. tier-3-live_gui::test_context_sim_live
   - Production bug: _do_generate mutated the frozen ProjectContext dataclass
     returned by flat_config (flat['files'] = ...). flat_config was converted
     from dict[str, Any] to ProjectContext dataclass by cruft_elimination_20260627
     Phase 2 but the consumer code wasn't updated.
   - Fix: call flat.to_dict() to get a mutable dict before mutation.
   - Same bug existed in /api/project endpoint (returns the ProjectContext
     directly; json.dumps fails silently on dataclass), now also calls
     to_dict() at the wire boundary.
This commit is contained in:
ed
2026-06-27 11:54:09 -04:00
parent b3aeaa4376
commit a4901fa24a
4 changed files with 15 additions and 2 deletions
+5 -1
View File
@@ -211,8 +211,12 @@ class HookHandler(BaseHTTPRequestHandler):
self.send_response(200)
self.send_header("Content-Type", "application/json")
self.end_headers()
# flat_config returns a ProjectContext dataclass; json.dumps cannot serialize
# dataclasses directly, so call .to_dict() first. The endpoint is the wire
# boundary; consumers expect the legacy dict[str, Any] shape.
flat = project_manager.flat_config(_get_app_attr(app, "project"))
self.wfile.write(json.dumps({"project": flat}).encode("utf-8"))
flat_dict = flat.to_dict() if hasattr(flat, "to_dict") else flat
self.wfile.write(json.dumps({"project": flat_dict}).encode("utf-8"))
elif self.path == "/api/project_switch_status":
# Determinstic signal for tests waiting on a project switch to complete.
# Polling /api/project returns derived state that may be stale from prior