Goal
Size the process-wide runtime runnable-slot budget from host capacity by default, while preserving one explicit, inspectable embedder override.
Current behavior
The schema-v4 coordinator from #982 defaults to maxInt(u64), so typed engine threads remain unbounded unless an embedder sets a fixed limit. This completes enforcement but not #502's automatic-bounding requirement.
Scope
- Replace the temporary unlimited default with one automatic policy:
max(1, detected logical CPUs - 1)typed runnable slots. The reserved lane is for the embedder/foreground host mutator, which executes outside the typed engine-thread boundary. - Query host capacity through
std.Thread.getCpuCount; use a fail-safe single slot when detection fails. - Make the public scheduler override nullable:
nullselects automatic sizing, a number selects an exact fixed limit, zero pauses entry/resume, andmaxInt(u64)is an intentional explicit unlimited policy. - Expose detected logical CPUs, the automatic host reservation, configured override, effective limit, and policy mode in the coherent machine-readable scheduler snapshot.
- Reapplying automatic policy refreshes host detection and wakes waiters when effective capacity grows. Lowering capacity continues to grandfather currently runnable threads.
- Add deterministic policy-function tests for 1, 2, and large logical-CPU counts plus real coordinator tests for automatic/fixed transitions and snapshot invariants.
- Update the runtime resource documentation and generated docs manifest.
Non-goals
Priority classes, dynamic load sensing, OS affinity/priority, compilation queues, cancellation, and memory-pressure feedback remain separate #502 work.
Acceptance
- The default effective limit is finite and derived from the detected host count.
- One-core hosts retain forward progress with one typed slot.
- Explicit zero/fixed/unlimited policies remain exact and observable.
- Automatic/fixed transitions preserve
active_slots = sum(resource.runnable)and wake blocked entrants only when capacity permits. - Focused normal/TSan scheduler tests, full units, runtime-thread audit, and deterministic threadfuzz pass.
- A local single-thread lifecycle diagnostic shows no material regression from the #982 parent.