CB-401 Stage A follow-up: rename WorkerService -> ClaudeCodeLauncher

Name the first-class Claude Code adapter explicitly, per the Peer Launcher SPI:
WorkerService was the de-facto Claude-Code launcher; as an in-tree PeerLauncher impl
it should say so. Pure IDE rename (class + file + WorkerServiceTest) plus stale
Javadoc/comment mentions swept to the new name. No behaviour change.

Gate: IDE diagnostics 0/0 on touched files; mvn clean install BUILD SUCCESS,
MVN_EXIT=0, 183 tests pass. Deferral #1 from issue #3 cleared.
This commit is contained in:
Dai Ha
2026-07-18 14:39:56 +02:00
parent e056c7e1fa
commit 3aa69a9e32
11 changed files with 60 additions and 60 deletions
@@ -22,7 +22,7 @@ import dev.ltms.bridged.session.GitWorktrees;
import dev.ltms.bridged.session.SessionManager;
import dev.ltms.bridged.peer.PeerLauncher;
import dev.ltms.bridged.session.SessionReaper;
import dev.ltms.bridged.worker.WorkerService;
import dev.ltms.bridged.worker.ClaudeCodeLauncher;
import io.javalin.Javalin;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -57,13 +57,13 @@ public final class Bridged {
AgentControl agents = new AgentControl(herdr);
WorkspaceControl spaces = new WorkspaceControl(herdr);
PeerLauncher workers = new WorkerService(agents, spaces, guard,
PeerLauncher workers = new ClaudeCodeLauncher(agents, spaces, guard,
cfg.workerProfiles(), cfg.defaultProfile(), System::getenv);
// CB-117: herdr keeps worker panes alive across a daemon restart, and their ids died with
// the previous process — reap those leaked orphans now, before we start serving.
workers.reapOrphanWorkers();
// CB-301: authoritative session registry + lifecycle FSM on top of WorkerService.
// CB-301: authoritative session registry + lifecycle FSM on top of ClaudeCodeLauncher.
// CB-301-ext: worktree provisioning seam, optionally rooted at a configured directory.
// CB-303 part 2: context cap is opt-in and disabled (0) when absent/null.
int contextCap = 0;
@@ -121,8 +121,8 @@ public final class Bridged {
// Caller identity is resolved from the connection (peer PID → herdr pane), not arguments.
ConnectionIdentity identity = new ConnectionIdentity(
new PaneLocator(herdr), new LsofPeerPidLookup(), new LsofProcessCwdLookup());
// Cast to WorkerService: BridgeMcp is not yet migrated to PeerLauncher (Stage A scope).
BridgeMcp mcp = new BridgeMcp(messages, rendezvous, (WorkerService) workers, sessions, identity, presence);
// Cast to ClaudeCodeLauncher: BridgeMcp is not yet migrated to PeerLauncher (Stage A scope).
BridgeMcp mcp = new BridgeMcp(messages, rendezvous, (ClaudeCodeLauncher) workers, sessions, identity, presence);
// CB-303 part 3: single ordered shutdown hook. Drain sessions first while herdr is still
// open (so releases reach the daemon), then stop poller/message/mcp/reaper, and close herdr
@@ -136,7 +136,7 @@ public final class Bridged {
herdr.close();
}));
Javalin app = new BridgedApp(herdr, (WorkerService) workers, sessions, messages, rendezvous, presence, mcp.servlet()).build();
Javalin app = new BridgedApp(herdr, (ClaudeCodeLauncher) workers, sessions, messages, rendezvous, presence, mcp.servlet()).build();
app.start(cfg.bind().host(), cfg.bind().port());
log.info("bridged listening on {}:{}, herdr socket {}",
cfg.bind().host(), cfg.bind().port(), socket);
@@ -12,7 +12,7 @@ import java.util.Map;
*
* <p>herdr owns the PID→pane truth: {@code pane.process_info} reports each pane's {@code shell_pid}
* and foreground process PIDs. This scans agent panes; a spawn-time {@code pid→terminal} cache is
* the obvious optimization once wired into {@code WorkerService}.
* the obvious optimization once wired into {@code ClaudeCodeLauncher}.
*/
public final class PaneLocator {
@@ -9,7 +9,7 @@ import dev.ltms.bridged.msg.Rendezvous;
import dev.ltms.bridged.session.SessionManager;
import dev.ltms.bridged.session.WorkerSession;
import dev.ltms.bridged.session.WorktreeRequest;
import dev.ltms.bridged.worker.WorkerService;
import dev.ltms.bridged.worker.ClaudeCodeLauncher;
import io.modelcontextprotocol.common.McpTransportContext;
import io.modelcontextprotocol.json.McpJsonMapper;
import io.modelcontextprotocol.json.jackson3.JacksonMcpJsonMapperSupplier;
@@ -34,8 +34,8 @@ import java.util.stream.Collectors;
* / {@code bridge_status}; the worker calls {@code bridge_reply}.
*
* <p>Beyond delegation the primary also manages the fleet here (CB-108): {@code bridge_spawn} /
* {@code bridge_list} / {@code bridge_stop} adapt {@link WorkerService} so a worker's whole lifecycle
* is driven through MCP, with the subscription boundary still enforced inside {@code WorkerService}.
* {@code bridge_list} / {@code bridge_stop} adapt {@link ClaudeCodeLauncher} so a worker's whole lifecycle
* is driven through MCP, with the subscription boundary still enforced inside {@code ClaudeCodeLauncher}.
*
* <p>The tool <em>logic</em> lives in package-private static methods returning a
* {@link McpSchema.CallToolResult}, so it is unit-testable without standing up the HTTP transport;
@@ -59,7 +59,7 @@ public final class BridgeMcp {
private final HttpServletStreamableServerTransportProvider transport;
private final McpSyncServer server;
public BridgeMcp(MessageService messages, Rendezvous rendezvous, WorkerService workers,
public BridgeMcp(MessageService messages, Rendezvous rendezvous, ClaudeCodeLauncher workers,
SessionManager sessions, ConnectionIdentity identity, WorkerPresence presence) {
McpJsonMapper json = new JacksonMcpJsonMapperSupplier().get();
this.transport = HttpServletStreamableServerTransportProvider.builder()
@@ -103,7 +103,7 @@ public final class BridgeMcp {
status(messages, str(req.arguments(), "sessionId")))
.toolCall(pollTool(), (_, req) ->
poll(messages, str(req.arguments(), "ticket")))
// Fleet management (CB-108): spawn/list/stop over WorkerService.
// Fleet management (CB-108): spawn/list/stop over ClaudeCodeLauncher.
.toolCall(spawnTool(), (exchange, req) -> {
Map<String, Object> a = req.arguments();
// CB-112: worker inherits the primary's cwd unless the call pins one.
@@ -342,14 +342,14 @@ public final class BridgeMcp {
}
/** {@code bridge_profiles}: the configured worker profiles and the default. */
static McpSchema.CallToolResult profiles(WorkerService workers) {
static McpSchema.CallToolResult profiles(ClaudeCodeLauncher workers) {
return text(json(Map.of(
"profiles", workers.profiles(),
"default", workers.defaultProfile() == null ? "" : workers.defaultProfile())));
}
/** {@code bridge_list}: bridge-owned roster merged with live herdr status by paneId. */
static McpSchema.CallToolResult listWorkers(WorkerService workers, SessionManager sessions) {
static McpSchema.CallToolResult listWorkers(ClaudeCodeLauncher workers, SessionManager sessions) {
try {
Map<String, Agent> live = workers.list().stream()
.filter(a -> a.paneId() != null)
@@ -6,7 +6,7 @@ import java.util.Set;
/**
* SPI for materializing a connected peer — the only way the bridge core creates or tears down
* a peer process. Every launcher is a first-party, in-tree adapter selected by (future) profile
* config; today's single adapter is the {@code WorkerService} / Claude Code over herdr.
* config; today's single adapter is the {@code ClaudeCodeLauncher} / Claude Code over herdr.
*
* <p>The core delegates spawn and teardown to this interface without knowing how the peer is set
* up. Environment variables, CLI flags, subscription guards, transport (herdr tab/pane) layout,
@@ -12,7 +12,7 @@ import dev.ltms.bridged.msg.Rendezvous;
import dev.ltms.bridged.session.SessionManager;
import dev.ltms.bridged.session.WorkerSession;
import dev.ltms.bridged.session.WorktreeRequest;
import dev.ltms.bridged.worker.WorkerService;
import dev.ltms.bridged.worker.ClaudeCodeLauncher;
import io.javalin.Javalin;
import io.javalin.http.Context;
import jakarta.servlet.http.HttpServlet;
@@ -44,7 +44,7 @@ public final class BridgedApp {
private static final long MAX_ASK_TIMEOUT_MS = 115_000;
private final HerdrClient herdr;
private final WorkerService workers;
private final ClaudeCodeLauncher workers;
private final SessionManager sessions; // CB-301: authoritative session registry
private final MessageService messages;
private final Rendezvous rendezvous;
@@ -52,7 +52,7 @@ public final class BridgedApp {
private final HttpServlet mcpServlet; // MCP Streamable-HTTP endpoint, mounted at /mcp (nullable)
private final ObjectMapper mapper = new ObjectMapper();
public BridgedApp(HerdrClient herdr, WorkerService workers, SessionManager sessions,
public BridgedApp(HerdrClient herdr, ClaudeCodeLauncher workers, SessionManager sessions,
MessageService messages, Rendezvous rendezvous, WorkerPresence presence,
HttpServlet mcpServlet) {
this.herdr = herdr;
@@ -42,9 +42,9 @@ import java.util.regex.Pattern;
* clutter the user's real work spaces. Teardown removes the worker's pane <em>and</em> its
* now-empty tab, tolerating an already-gone worker so a repeated DELETE is harmless.
*/
public final class WorkerService implements PeerLauncher {
public final class ClaudeCodeLauncher implements PeerLauncher {
private static final Logger log = LoggerFactory.getLogger(WorkerService.class);
private static final Logger log = LoggerFactory.getLogger(ClaudeCodeLauncher.class);
/** herdr rejects a duplicate agent {@code name}; we retry a bumped name this many times. */
private static final int NAME_RETRIES = 8;
@@ -86,9 +86,9 @@ public final class WorkerService implements PeerLauncher {
// cannot collide with same-profile workers that outlived a restart. See startUniquelyNamed.
private final String nameNonce = String.format("%06x", new SecureRandom().nextInt(1 << 24));
public WorkerService(AgentControl agents, WorkspaceControl spaces, SubscriptionGuard guard,
Map<String, BridgedConfig.Worker> profiles, String defaultProfile,
Function<String, String> env) {
public ClaudeCodeLauncher(AgentControl agents, WorkspaceControl spaces, SubscriptionGuard guard,
Map<String, BridgedConfig.Worker> profiles, String defaultProfile,
Function<String, String> env) {
this.agents = agents;
this.spaces = spaces;
this.guard = guard;
@@ -12,7 +12,7 @@ import dev.ltms.bridged.session.FakeWorktrees;
import dev.ltms.bridged.session.SessionManager;
import dev.ltms.bridged.session.WorkerSession;
import dev.ltms.bridged.session.WorktreeRequest;
import dev.ltms.bridged.worker.WorkerService;
import dev.ltms.bridged.worker.ClaudeCodeLauncher;
import io.modelcontextprotocol.spec.McpSchema;
import org.junit.jupiter.api.Test;
@@ -39,11 +39,11 @@ class BridgeMcpTest {
return ((McpSchema.TextContent) r.content().getFirst()).text();
}
private static WorkerService workerService(FakeHerdr h, String baseUrl, Set<String> allow) {
private static ClaudeCodeLauncher workerService(FakeHerdr h, String baseUrl, Set<String> allow) {
BridgedConfig.Worker cfg = new BridgedConfig.Worker(
"ltms-local", baseUrl, "coder", null, "BRIDGED_WORKER_TOKEN", null,
"tab", "bridged-workers", "worker: {profile} #{n}", null, null, null);
return new WorkerService(new AgentControl(h), new WorkspaceControl(h),
return new ClaudeCodeLauncher(new AgentControl(h), new WorkspaceControl(h),
new SubscriptionGuard(allow), Map.of(cfg.profile(), cfg), cfg.profile(), _ -> "tok");
}
@@ -16,7 +16,7 @@ import dev.ltms.bridged.session.FakeWorktrees;
import dev.ltms.bridged.session.GitWorktrees;
import dev.ltms.bridged.session.SessionManager;
import dev.ltms.bridged.session.Worktrees;
import dev.ltms.bridged.worker.WorkerService;
import dev.ltms.bridged.worker.ClaudeCodeLauncher;
import io.javalin.Javalin;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
@@ -64,7 +64,7 @@ class BridgedAppTest {
"ltms-local", workerBaseUrl, "coder", null, "BRIDGED_WORKER_TOKEN", null,
placement, "bridged-workers", "worker: {profile} #{n}", null, null, null);
AgentControl agents = new AgentControl(herdr);
WorkerService workers = new WorkerService(
ClaudeCodeLauncher workers = new ClaudeCodeLauncher(
agents, new WorkspaceControl(herdr), new SubscriptionGuard(allow),
Map.of(wcfg.profile(), wcfg), wcfg.profile(),
k -> "BRIDGED_WORKER_TOKEN".equals(k) ? "tok-abc" : null);
@@ -5,7 +5,7 @@ import dev.ltms.bridged.guard.SubscriptionGuard;
import dev.ltms.bridged.herdr.AgentControl;
import dev.ltms.bridged.herdr.FakeHerdr;
import dev.ltms.bridged.herdr.WorkspaceControl;
import dev.ltms.bridged.worker.WorkerService;
import dev.ltms.bridged.worker.ClaudeCodeLauncher;
import org.junit.jupiter.api.Test;
import java.util.List;
@@ -28,7 +28,7 @@ class SessionManagerTest {
"ltms-local", "http://gx00.gw:8000", "coder", null, "BRIDGED_WORKER_TOKEN",
List.of("ccs", "ltms-local"), "tab", "bridged-workers",
"worker: {profile} #{n}", null, null, null);
WorkerService workers = new WorkerService(new AgentControl(herdr), new WorkspaceControl(herdr),
ClaudeCodeLauncher workers = new ClaudeCodeLauncher(new AgentControl(herdr), new WorkspaceControl(herdr),
new SubscriptionGuard(Set.of("gx00.gw")), Map.of(cfg.profile(), cfg), cfg.profile(), _ -> null);
return new SessionManager(workers);
}
@@ -42,7 +42,7 @@ class SessionManagerTest {
"ltms-local", "http://gx00.gw:8000", "coder", null, "BRIDGED_WORKER_TOKEN",
List.of("ccs", "ltms-local"), "tab", "bridged-workers",
"worker: {profile} #{n}", null, null, null);
WorkerService workers = new WorkerService(new AgentControl(herdr), new WorkspaceControl(herdr),
ClaudeCodeLauncher workers = new ClaudeCodeLauncher(new AgentControl(herdr), new WorkspaceControl(herdr),
new SubscriptionGuard(Set.of("gx00.gw")), Map.of(cfg.profile(), cfg), cfg.profile(), _ -> null);
return new SessionManager(workers, new GitWorktrees(), clock, contextCap);
}
@@ -5,7 +5,7 @@ import dev.ltms.bridged.guard.SubscriptionGuard;
import dev.ltms.bridged.herdr.AgentControl;
import dev.ltms.bridged.herdr.FakeHerdr;
import dev.ltms.bridged.herdr.WorkspaceControl;
import dev.ltms.bridged.worker.WorkerService;
import dev.ltms.bridged.worker.ClaudeCodeLauncher;
import org.junit.jupiter.api.Test;
import java.util.List;
@@ -21,12 +21,12 @@ import static org.junit.jupiter.api.Assertions.*;
*/
class WorktreeSessionManagerTest {
private static WorkerService workerService(FakeHerdr herdr) {
private static ClaudeCodeLauncher workerService(FakeHerdr herdr) {
BridgedConfig.Worker cfg = new BridgedConfig.Worker(
"ltms-local", "http://gx00.gw:8000", "coder", null, "BRIDGED_WORKER_TOKEN",
List.of("ccs", "ltms-local"), "tab", "bridged-workers",
"worker: {profile} #{n}", null, null, null);
return new WorkerService(new AgentControl(herdr), new WorkspaceControl(herdr),
return new ClaudeCodeLauncher(new AgentControl(herdr), new WorkspaceControl(herdr),
new SubscriptionGuard(Set.of("gx00.gw")), Map.of(cfg.profile(), cfg), cfg.profile(), _ -> null);
}
@@ -18,13 +18,13 @@ import java.util.function.Function;
import static org.junit.jupiter.api.Assertions.*;
/** The step-4 launch-flag injection: the bridge MCP + reply charter are appended to the argv. */
class WorkerServiceTest {
class ClaudeCodeLauncherTest {
private WorkerService service(FakeHerdr herdr, List<String> argv, String mcpUrl) {
private ClaudeCodeLauncher service(FakeHerdr herdr, List<String> argv, String mcpUrl) {
BridgedConfig.Worker cfg = new BridgedConfig.Worker(
"ltms-local", "http://gx00.gw:8000", "coder", null, "BRIDGED_WORKER_TOKEN",
argv, "tab", "bridged-workers", "worker: {profile} #{n}", mcpUrl, null, null);
return new WorkerService(new AgentControl(herdr), new WorkspaceControl(herdr),
return new ClaudeCodeLauncher(new AgentControl(herdr), new WorkspaceControl(herdr),
new SubscriptionGuard(Set.of("gx00.gw")), Map.of(cfg.profile(), cfg), cfg.profile(), _ -> null);
}
@@ -54,12 +54,12 @@ class WorkerServiceTest {
assertEquals(List.of("bash", "-c", "sleep 1"), spawnedArgv(herdr), "argv untouched without mcpUrl");
}
private WorkerService multiProfile(FakeHerdr herdr) {
private ClaudeCodeLauncher multiProfile(FakeHerdr herdr) {
BridgedConfig.Worker gx10 = new BridgedConfig.Worker("gx10", "http://gx10.gw:8000", "coder",
null, "BRIDGED_WORKER_TOKEN", List.of("ccs", "gx10"), "tab", "bridged-workers", "w #{n}", null, null, null);
BridgedConfig.Worker ollama = new BridgedConfig.Worker("ollama", "http://ollama.ltms.dev", null,
null, "BRIDGED_WORKER_TOKEN", List.of("ccs", "ollama"), "tab", "bridged-workers", "w #{n}", null, null, null);
return new WorkerService(new AgentControl(herdr), new WorkspaceControl(herdr),
return new ClaudeCodeLauncher(new AgentControl(herdr), new WorkspaceControl(herdr),
new SubscriptionGuard(Set.of("gx10.gw", "ollama.ltms.dev")),
Map.of("gx10", gx10, "ollama", ollama), "gx10", _ -> "tok");
}
@@ -103,7 +103,7 @@ class WorkerServiceTest {
BridgedConfig.Worker cfg = new BridgedConfig.Worker("ltms-local", "http://gx00.gw:8000", "coder",
null, "BRIDGED_WORKER_TOKEN", List.of("ccs", "ltms-local"), "tab", "bridged-workers",
"w #{n}", null, "/pinned/dir", null);
WorkerService svc = new WorkerService(new AgentControl(herdr), new WorkspaceControl(herdr),
ClaudeCodeLauncher svc = new ClaudeCodeLauncher(new AgentControl(herdr), new WorkspaceControl(herdr),
new SubscriptionGuard(Set.of("gx00.gw")), Map.of("ltms-local", cfg), "ltms-local", _ -> null);
svc.spawn("ltms-local", null, "/caller/home");
assertEquals("/pinned/dir", startCwd(herdr), "a profile-pinned cwd overrides the caller's");
@@ -135,7 +135,7 @@ class WorkerServiceTest {
case "GITEA_HOST" -> "git.ltms.dev";
default -> null;
};
new WorkerService(new AgentControl(herdr), new WorkspaceControl(herdr),
new ClaudeCodeLauncher(new AgentControl(herdr), new WorkspaceControl(herdr),
new SubscriptionGuard(Set.of("gx00.gw")), Map.of("impl", cfg), "impl", host).spawn();
Map<String, String> env = startEnv(herdr);
@@ -151,7 +151,7 @@ class WorkerServiceTest {
BridgedConfig.Worker cfg = new BridgedConfig.Worker("ltms-local", "http://gx00.gw:8000", "coder",
null, "BRIDGED_WORKER_TOKEN", List.of("ccs"), "tab", "bridged-workers", "w #{n}",
null, null, null);
new WorkerService(new AgentControl(herdr), new WorkspaceControl(herdr),
new ClaudeCodeLauncher(new AgentControl(herdr), new WorkspaceControl(herdr),
new SubscriptionGuard(Set.of("gx00.gw")), Map.of("ltms-local", cfg), "ltms-local",
_ -> "would-be-secret").spawn();
@@ -164,20 +164,20 @@ class WorkerServiceTest {
@Test
void isForeignWorkerMatchesOurSchemeWithANonSelfNonce() {
assertTrue(WorkerService.isForeignWorker("claude-ollama-be09c2-2", "aaaaaa"),
assertTrue(ClaudeCodeLauncher.isForeignWorker("claude-ollama-be09c2-2", "aaaaaa"),
"a bridge worker name with a different nonce is a prior daemon's orphan");
assertTrue(WorkerService.isForeignWorker("claude-gx10-4127af-11", "aaaaaa"),
assertTrue(ClaudeCodeLauncher.isForeignWorker("claude-gx10-4127af-11", "aaaaaa"),
"profile and multi-digit seq are still parsed; foreign nonce ⇒ reap");
}
@Test
void isForeignWorkerSparesOurOwnLiveWorkersAndNonWorkers() {
assertFalse(WorkerService.isForeignWorker("claude-ollama-abcdef-3", "abcdef"),
assertFalse(ClaudeCodeLauncher.isForeignWorker("claude-ollama-abcdef-3", "abcdef"),
"a worker with THIS process's nonce is ours and live — never reap it");
assertFalse(WorkerService.isForeignWorker(null, "abcdef"), "an unnamed agent is not a worker");
assertFalse(WorkerService.isForeignWorker("claude", "abcdef"), "a bare kind name is not a worker");
assertFalse(WorkerService.isForeignWorker("my-repl", "abcdef"), "a user's own label is not a worker");
assertFalse(WorkerService.isForeignWorker("claude-ollama-XYZ123-2", "abcdef"),
assertFalse(ClaudeCodeLauncher.isForeignWorker(null, "abcdef"), "an unnamed agent is not a worker");
assertFalse(ClaudeCodeLauncher.isForeignWorker("claude", "abcdef"), "a bare kind name is not a worker");
assertFalse(ClaudeCodeLauncher.isForeignWorker("my-repl", "abcdef"), "a user's own label is not a worker");
assertFalse(ClaudeCodeLauncher.isForeignWorker("claude-ollama-XYZ123-2", "abcdef"),
"a non-hex nonce does not match our scheme");
}
@@ -193,7 +193,7 @@ class WorkerServiceTest {
@Test
void reapsAForeignOrphanButSparesOurOwnWorkerAndUserSessions() {
FakeHerdr herdr = new FakeHerdr();
WorkerService svc = multiProfile(herdr);
ClaudeCodeLauncher svc = multiProfile(herdr);
herdr.withAgent("claude-ollama-be09c2-2", "term_orphan", "wQ:pF", "wQ:t8") // prior daemon's leak
.withAgent("claude-gx10-" + svc.nameNonce() + "-1", "term_mine", "wQ:pMine", "wQ:tMine"); // ours, live
// (the fake's default unnamed term_a stands in for a user's own Claude session)
@@ -210,7 +210,7 @@ class WorkerServiceTest {
@Test
void reapCountsAnAlreadyGoneOrphanAsReaped() {
FakeHerdr herdr = new FakeHerdr().paneCloseFailsWith("pane_not_found");
WorkerService svc = multiProfile(herdr);
ClaudeCodeLauncher svc = multiProfile(herdr);
herdr.withAgent("claude-ollama-0d856d-3", "term_gone", "wQ:pS", "wQ:tD");
assertEquals(1, svc.reapOrphanWorkers(),
@@ -228,7 +228,7 @@ class WorkerServiceTest {
@Test
void spawnReturnsPeerHandleWithIdEqualToPaneId() {
FakeHerdr herdr = new FakeHerdr();
WorkerService svc = service(herdr, List.of("ccs", "ltms-local"), null);
ClaudeCodeLauncher svc = service(herdr, List.of("ccs", "ltms-local"), null);
PeerHandle handle = svc.spawn(new SpawnRequest(null, null, null));
@@ -239,7 +239,7 @@ class WorkerServiceTest {
@Test
void spawnReturnsPeerHandleWithCorrectTerminalId() {
FakeHerdr herdr = new FakeHerdr();
WorkerService svc = service(herdr, List.of("ccs", "ltms-local"), null);
ClaudeCodeLauncher svc = service(herdr, List.of("ccs", "ltms-local"), null);
PeerHandle handle = svc.spawn(new SpawnRequest("ltms-local", null, "/caller"));
@@ -249,7 +249,7 @@ class WorkerServiceTest {
@Test
void capabilitiesIncludeMidTurnAskWorktreeOrphanReap() {
FakeHerdr herdr = new FakeHerdr();
WorkerService svc = service(herdr, List.of("ccs", "ltms-local"), null);
ClaudeCodeLauncher svc = service(herdr, List.of("ccs", "ltms-local"), null);
Set<Capability> caps = svc.capabilities();
@@ -265,7 +265,7 @@ class WorkerServiceTest {
"impl", "http://gx00.gw:8000", "coder", null, "BRIDGED_WORKER_TOKEN",
List.of("ccs", "impl"), "tab", "bridged-workers", "w #{n}", null, null, null,
"GITEA_ACCESS_TOKEN", null);
WorkerService svc = new WorkerService(new AgentControl(herdr), new WorkspaceControl(herdr),
ClaudeCodeLauncher svc = new ClaudeCodeLauncher(new AgentControl(herdr), new WorkspaceControl(herdr),
new SubscriptionGuard(Set.of("gx00.gw")), Map.of("impl", cfg), "impl",
_ -> "tok");
@@ -276,7 +276,7 @@ class WorkerServiceTest {
@Test
void capabilitiesExcludeSelfPrWhenNoGitToken() {
FakeHerdr herdr = new FakeHerdr();
WorkerService svc = service(herdr, List.of("ccs", "ltms-local"), null);
ClaudeCodeLauncher svc = service(herdr, List.of("ccs", "ltms-local"), null);
assertFalse(svc.capabilities().contains(Capability.SELF_PR),
"no git token profile → no SELF_PR capability");
@@ -285,7 +285,7 @@ class WorkerServiceTest {
@Test
void effectiveCwdViaSpawnRequestMatchesExistingResolution() {
FakeHerdr herdr = new FakeHerdr();
WorkerService svc = service(herdr, List.of("ccs", "ltms-local"), null);
ClaudeCodeLauncher svc = service(herdr, List.of("ccs", "ltms-local"), null);
String cwd = svc.effectiveCwd(new SpawnRequest("ltms-local", "/work/proj", "/caller/home"));
@@ -295,7 +295,7 @@ class WorkerServiceTest {
@Test
void profilesViaPeerLauncherMatchesExistingApi() {
FakeHerdr herdr = new FakeHerdr();
WorkerService svc = multiProfile(herdr);
ClaudeCodeLauncher svc = multiProfile(herdr);
assertEquals(Set.of("gx10", "ollama"), svc.profiles(), "profiles() via PeerLauncher must match");
}
@@ -303,7 +303,7 @@ class WorkerServiceTest {
@Test
void defaultProfileViaPeerLauncherMatches() {
FakeHerdr herdr = new FakeHerdr();
WorkerService svc = multiProfile(herdr);
ClaudeCodeLauncher svc = multiProfile(herdr);
assertEquals("gx10", svc.defaultProfile(), "defaultProfile() via PeerLauncher must match");
}
@@ -311,7 +311,7 @@ class WorkerServiceTest {
@Test
void stopViaPeerLauncherTearsDownByHandleId() {
FakeHerdr herdr = new FakeHerdr();
WorkerService svc = service(herdr, List.of("ccs", "ltms-local"), null);
ClaudeCodeLauncher svc = service(herdr, List.of("ccs", "ltms-local"), null);
PeerHandle handle = svc.spawn(new SpawnRequest(null, null, null));
svc.stop(handle.id());