v0.5.13
Fixes from the 2026-07-12 focused re-audit of the v0.5.12 delta. Headline: the v0.5.12 H-1 fix was a no-op in production and is now actually closed.
Fixed
- Submit
depends_onTOCTOU fix was a no-op (H-1, regression of the v0.5.12 fix). The v0.5.12 post-commit cascade re-check read the parent through a cached identity-map object; withexpire_on_commit=Falsethe intervening commit never refreshed it, so the cascade gate saw a stale non-terminal state and never fired — a child concurrently orphaned by its parent still stranded QUEUED forever./submitnowsession.refresh()es each parent before the cascade re-check (matching the idiom every other_cascade_on_parent_terminalcaller already uses), guarded for a parent pruned mid-submit. New real-race regression test drives the actual/submitendpoint with a concurrent-session/completeand fails on the pre-fix code. scheduling_timeoutqueue-clock reset on refuse-admission re-routes (M-1 follow-up). A refuse-admission requeue funnels through the same helper that resetslast_enqueued_at, so a job that never ran but kept getting offered-and-refused (e.g. oscillatinggpu_contention, which does not grow the exclusion set) reset its timeout clock every bounce and could evadescheduling_timeoutforever. Refuse-admission re-routes now preserve the clock; only requeues of a job that actually dispatched reset it.- Worker
run_jobexception path leaked a signal-poll thread and a fast_path child (F1/F2). On a raise past the terminal path, the outerfinallynow stops the signal-poll thread (it would otherwise spin onGET /signalforever for a terminal job) and SIGKILLs afast_pathchild that has no scope cgroup to reap.
CI
- Property-based fuzzing of the broker state machine (H-4, audit 2026-07-10). A
hypothesisRuleBasedStateMachine(tests/property/) generates arbitrary interleavings of submit / claim / start / complete / cancel / worker-death-reclaim / scheduling-timeout / sweep against the real broker (in-process FastAPI + SQLite + sweeper) and asserts the invariants the CAS discipline guarantees: no terminal state is ever clobbered, a job is terminally cancelled at most once, a reclaim never silently drops a pending user cancel, and (added 2026-07-12) a default-policy dependent of a failed parent is never stranded on a runnable path. The harness now generatesdepends_onedges so it actually exercises the cascade (previously it created none, leaving the cancel-at-most-once invariant vacuous). Runs bounded in CI (JOBD_H4_EXAMPLES/JOBD_H4_STEPSenv overrides for a deep run). - The
liveCI job silently skipped 5 of 9 marked-live tests (H-3 follow-up). It exported onlyJOBD_LIVE, while the e2e / MCP / project-defaults live tests gate onJOBD_E2E/RUN_LIVE_JOBDand require an external broker — so they skipped, and skips don't fail pytest. The job now stands up a real broker + worker from the committedconfig/, exports all three opt-in gates, and guards against a broken gate silently running zero tests.