fleetd #450: make PeerLauncher.spawn(SpawnRequest, PlacementDecision) abstract #451
Reference in New Issue
Block a user
Delete Branch "worker/450-abstract-spawn-599e1c-5"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
fleetd #450: make
PeerLauncher.spawn(SpawnRequest, PlacementDecision)abstract.Why
The
defaultmethod re-entered the single-argumentspawn(SpawnRequest), whichre-runs checks (
enforceNotQuarantined,enforceNotCoolingOff,enforceMaxLoad,enforceModelEnabledinCompositePeerLauncher) that can refuse the exact profileplace()just chose — the windowPlacementDecisionexists to close (#444). OnlyCompositePeerLauncheroverrode it; nothing forced a future placement-doinglauncher to override it too, so it could inherit the wrong body silently.
What changed
PeerLauncher.spawn(SpawnRequest, PlacementDecision)is now abstract (javadocrewritten to describe the two legal bodies instead of "the default").
HerdrPeerLauncher(the base class ofClaudeCodeLauncherandOpenCodeLauncher— re-measured in this tree at
822327e, neither of those two classes implementsPeerLauncherdirectly, they extend this abstract class, and neither overridesspawn(SpawnRequest)orplace()with placement filtering of its own) gets there-entering form, with a comment saying why it's correct there.
CompositePeerLauncher's existing routing-form override is untouched.PeerLauncherimplementers needed overrides to keep compiling(
FleetdBackendErrorSinkTest.NeverSpawnsLauncher;SessionManagerTest.RaceLauncher,.NoResumeLauncher,.ClearContextSpyLauncher,.LazyIdLauncher) — each mirrors its own existingspawn(SpawnRequest)shape: a delegating wrapper delegates, an "unreachable"stub throws the same
UnsupportedOperationException, the single-profile fakere-enters.
Deviation from the brief: the ticket/brief listed
ConfigRef,ClaudeCodeLauncher,CompositePeerLauncher,OpenCodeLauncher,HerdrPeerLauncheras the fivesrc/mainimplementers to give explicit overrides. Re-measured in this worktree at822327e:ConfigRef(packageconfig, implementsSupplier<FleetConfig>) doesnot implement
PeerLauncherat all — only mentioned in comments — so it neededno change.
ClaudeCodeLauncher/OpenCodeLauncherdo not implementPeerLauncherdirectly; they
extends HerdrPeerLauncher, which isabstract(only because ofits own
buildLaunchadapter hook, unrelated to placement) and already owns theentire spawn/placement contract. So the override belongs once, in
HerdrPeerLauncher,where both subclasses inherit it — duplicating it into the two leaf classes would
copy the exact same body for no reason. This was a decision within the brief's
delegated authority ("decide from what the class actually does, not from what the
others got"; "ConfigRef... check what kind of implementer it even is before
assuming").
Evidence
Full
mvn -B clean install(green, before deleting anything):Deleted
HerdrPeerLauncher's new override, rebuilt — fails, naming both classesthat would otherwise have silently inherited nothing:
(exit=1,
BUILD FAILURE)Restored the override, rebuilt — green again:
Scope
Only #450's scope. Did not touch
enforce*checks, the routing branch'sfall-through behavior, the #447 test, or revisit #425/#435/#444.
Out-of-scope note (not investigated further):
PeerLauncherhas two moredefaultmethods with the same "only some implementers may safely inherit"shape —
defaultProfileFor(MemberRole)andplace(MemberRole)(both wrapdefaultProfile()and are documented as correct only for a no-placementlauncher). Flagging per the brief's scope rule; not fixed here.