Repository navigation
fix(challenge): load the role-dispatch file on first use - #22
Conversation
The supervisor canary boots every new image with an empty /data and no secrets and requires /version to answer. create_app read $HYPERTRAIN_ROLE_DISPATCH eagerly, so the canary crashed with FileNotFoundError and the production update was refused. create_app now hands the store a non-None wrapper that loads the file on the first role replay under a lock and caches the RoleLaunch. A missing, unreadable or invalid file raises ChallengeError(503, "ROLE_DISPATCH_UNAVAILABLE") at that call, which the existing handler maps to HTTP; failures are not cached, so fixing the file needs no restart. store.py's None checks are unchanged. Errors raised by the loaded factory pass through untouched. Rejected: exposing the state in /health (non-goal, not trivial without touching the store). Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
|
Warning Review limit reachedYou've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Next included review available in 56 minutes. View limit details
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info
📝 Walkthrough
Merge Risk: ⚪ Minimal · up to
|
…rors Two mutants survived the first three tests: a wrapper without the lock (16 concurrent first calls each loaded the file) and an 'except Exception' that would turn a RuntimeError into a 503. Add a 16-thread test asserting a single load and a test that an unexpected load error propagates. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Why
The Cortex challenge-supervisor starts a canary of every new image with an empty tmpfs
/dataand no secrets, and requires/versionto answer.create_apploaded$HYPERTRAIN_ROLE_DISPATCHeagerly (app.py), so any GO image crashed at boot when the file was missing and the production update was refused ("canary did not answer /version").e319cf6(current prod image) never loaded role dispatch, so it passed.What
create_apphands the store a wrapper that loads the dispatch file on first use (thread-safe, cached on success only). A missing, unreadable or invalid file raisesChallengeError(503, "ROLE_DISPATCH_UNAVAILABLE")at the point a role replay is needed; fixing the file works without a restart. Valid file: same launch behaviour,role_dispatch.loadcalled once. Unset env: unchanged (None).store.pyuntouched (is Nonechecks keep working because the wrapper is notNone).Evidence
tests/challenge/test_role_dispatch_lazy.py(3 tests): boot +/version200 with a missing file (fails on base, passes here); 503 for missing / invalid JSON / extra field, then success after the file is fixed; valid file loaded once with identical refusal to the eager loader.test_role_dispatch_consumers_v2.pystill passes (21 passed, 3 skipped: genuine-CUDA index not set).Risk / rollback
A broken dispatch file is no longer caught at boot but at the first role replay (503). Scope pre-approved by the Principal for
src/(this change only). Revert the merge commit.🤖 Generated with Claude Code
Summary by CodeRabbit
Update after review
RuntimeError) propagates instead of becoming a 503 (except Exceptionmutant fails).LEASE_EXPIRED) instead of failing at boot. This is intended for the supervisor canary; a broken file is detectable with the first replay and fixed without a restart.