Add cluster.disable_console_workers (reverse gh-602's console-routing half; preserve controller-exclusion) - #616
Add cluster.disable_console_workers (reverse gh-602's console-routing half; preserve controller-exclusion)#616lukstafi wants to merge 2 commits into
Conversation
When `cluster.disable_console_workers: true`, machines with role "console" are never selected to run worker slots and are never auto-started by the keepalive — freeing the console box for interactive/SSH use. Defaults to false for back-compat. - config: parse `disable_console_workers` (YAML snake_case) into `ClusterConfig.disableConsoleWorkers` (camelCase TS); add to the reference schema + the `LudicsFullConfig.cluster` interface so config validation and the config-reference lint accept the key. - selectMachineForSlot: exclude console-role machines from the candidate set when the flag is on, applied after the requirement filter. If excluding the console empties the pool, block the assignment (return null) rather than falling back onto the console. This also neutralizes the gh-ludics-602 console-preference routing — ludics self-tasks fall through to the controller fallback instead of the console. - maybeAutoStartSlots: skip auto-starting any slot whose assigned machine has role "console" when the flag is on. - tests: parse (true/false/absent), console excluded-when-on / included-when-off, and the no-eligible-machine path returns null (no fallback to console). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 221ca129ad
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if (clusterConfig().disableConsoleWorkers) { | ||
| eligible = eligible.filter((m) => m.role !== "console"); |
There was a problem hiding this comment.
Filter consoles out of health-routing selectors
With disable_console_workers enabled, this new filter only affects slot assignment; routeOrSkipRequirementsUnmet in src/health.ts still calls selectOnlineCapableMachine, which builds its candidate list from all clusterMachines() and returns the first fresh capability match. In a setup where the console is the only online machine matching a project's os/gpu requirements, nightly test-health will still SSH to the console and run the suite there, defeating the config's purpose of reserving the console for interactive use. Apply the same console-role exclusion to the capability selector or share the eligibility filter.
Useful? React with 👍 / 👎.
…sion The first cut neutralized gh-ludics-602's entire console-preference branch, which also dropped gh-602's controller-protection: ludics self-modifying tasks fell back to the controller (mac-studio) when the console was excluded. Self-orchestration on the controller repoints the global `ludics` symlink and boots the dashboard, so that is not acceptable. Correct policy (a faithful 180° of gh-602's half (2) only): - gh-602 half (1) — keep ludics self-tasks OFF the controller/leader — STAYS. - gh-602 half (2) — prefer/route them to the console — is REVERSED: the console flips from preferred to forbidden for all worker slots. So with disable_console_workers on, a ludics self-task is excluded from BOTH the console AND the controller/leader; if no other eligible worker exists, selectMachineForSlot returns null (blocks → awaits manual/SSH handling) rather than ever falling back to the controller. Non-ludics tasks only lose the console (the controller stays available to them). Flag off (default) keeps gh-602 behavior unchanged — full back-compat. - cluster.ts: hoist the gh-602 `isLudicsSelfTask` predicate; in the disable_console_workers block exclude console for all tasks and additionally exclude role "leader" for self-tasks, blocking (null) on empty. - tests: self-task + flag ON with only leader+console → null (asserts it does NOT pick the controller), incl. console-down variant; self-task still routes to a real non-console/non-leader worker; non-ludics keeps the controller; flag-OFF gh-602 routing stays green. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Goal
Add a
cluster.disable_console_workersboolean config option (defaultfalse, full back-compat). Whentrue, machines whoseroleisconsoleare never selected to run worker slots, and the keepalive never auto-starts slots on them — freeing the console machine (currentlymacbook-pro) for interactive/SSH use.Policy: a faithful 180° of gh-ludics-602's console-routing half
gh-ludics-602 ("self-orchestration breaks the controller") has two halves for ludics self-modifying tasks:
ludicssymlink and boots the dashboard. This MUST stay.This flag reverses only half (2): the console flips from preferred to forbidden for all worker slots. Half (1) stays.
Net effect with the flag on:
ludics init) #602's exact predicate,project == "ludics"case-insensitive) are excluded from both the console and the controller/leader. If no other eligible worker exists,selectMachineForSlotreturnsnull— it blocks (awaits manual/SSH handling) rather than ever falling back to the controller.ludics init) #602 behavior is unchanged — console-preferred, controller-protected.What changed
src/config.ts,templates/config.reference.yaml): addeddisable_console_workers(YAML snake_case) to the cluster reference schema and theLudicsFullConfig.clusterinterface. Parsed inclusterConfig()(src/cluster.ts) intoClusterConfig.disableConsoleWorkers(camelCase TS), defaultfalse. NewdisableConsoleWorkers()helper.selectMachineForSlot,src/cluster.ts): hoisted Orchestrating a ludics self-task on the controller node takes down the live controller (dashboard launchd bootout + global symlink repoint via worktreeludics init) #602'sisLudicsSelfTaskpredicate; when the flag is on, console-role machines are removed from the candidate set for every task, and for ludics self-tasks the leader/controller is additionally removed. Empties-to-null(blocks) rather than falling back onto the console or the controller. Applied after the requirement filter.maybeAutoStartSlots,src/mag.ts): skips auto-starting any slot whose assigned machine has roleconsolewhen the flag is on.src/cluster.test.ts): parse oftrue/false/absent; non-ludics task keeps the controller but loses the console; ludics self-task with flag ON and only leader+console available returnsnull(asserts it does not pick the controller), incl. a console-down variant; ludics self-task still routes to a real non-console/non-leader worker; flag-off Orchestrating a ludics self-task on the controller node takes down the live controller (dashboard launchd bootout + global symlink repoint via worktreeludics init) #602 console routing stays green; the no-eligible-machine path returnsnullwithout falling back to the console.Activating config
The federation controller harness already sets
cluster.disable_console_workers: truein itsconfig.yaml(currently inert until this merges + deploys).Operational consequence
With the flag on and the console as the only otherwise-eligible online machine, assignments block rather than running on the console. For ludics self-modifying tasks specifically, when neither a non-console/non-leader worker nor the (forbidden) console/controller is available, the task blocks and awaits manual/SSH handling — by design, this is preferable to re-triggering the gh-602 controller-disruption.
Validation
bun run build— ✅bun run typecheck— ✅bun run lint— ✅bun run lint:config-reference— ✅bun test src/cluster.test.ts— ✅ 41 pass / 0 failbun test src/mag-remote-dispatch-path.test.ts— ✅ 3 pass / 0 fail🤖 Generated with Claude Code