bc13b8e92c
Two leads now work as peers rather than one primary plus workers. The arc:
CB-530/531 lead identity: `leaders:` names panes, `leadScan:` discovers them by
tab label (LeadTabScanner, TTL-cached, worker spaces excluded).
CB-532 leads can message each other AND be answered. Principal.leader now
carries its terminal, so ownsSession() can be true for a lead; the
"and you must be a worker" conjunct beside it protected nothing.
Retires `primary:` — reply nudges follow the delegating lead, a
binding recorded at bridge_send where both halves are known.
CB-533 ClaudeCodeLauncher passes --model. argv is usually a wrapper
(`ccs <profile>`) that re-exports its own model family, so
ANTHROPIC_MODEL alone was silently overruled.
CB-534 a lead is deliverable. The CB-113 readiness gate only opened for
terminals in WorkerPresence, which only workers ever enter, so every
lead->lead send waited out the ~60s grace and failed having never
been typed. The gate guards a *spawned* peer's boot window; a lead
is never spawned.
CB-535 bridge_list returns `leads` alongside `workers`, with `self` on the
caller's row. An empty worker roster no longer reads as "no peers".
CB-536 CLAUDE.md: lead<->lead is coordinate-only, never sideways delegation.
Propagated byte-identically to wiki/7-Use-Cases.md.
MIXED PROVENANCE — recorded deliberately rather than hidden. This tree also carries
in-progress CB-537 (context separation) authored by the peer lead gpt-sol-5.6 and
its worker: Capability.CONTEXT_RESET, SessionManager.clearAfterTurn, and the
Injector/TurnListener/CompletionResolver/launcher changes around it. That work was
done in this shared working tree rather than a worktree, and is entangled with the
above in BridgedConfig.java, Bridged.java and ClaudeCodeLauncher.java, so neither
lead could stage its own half without sweeping in the other's. Committing the whole
green state is the honest resolution; the peer branches from here.
Note for whoever picks CB-537 up: the design in this commit is SUPERSEDED. Both
leads agreed to replace the global `clearAfterTurn` boolean with per-delivery
policy (inherit|fresh|thread) applied PRE-delivery, because a post-turn reset races
by construction — Injector.onStatus clears awaitingCompletion and dequeues the next
message in the same tick. `fresh` is also a correctness guarantee, so an adapter
without a reset capability must refuse it rather than log a no-op.
mvn clean install: Tests run: 464, Failures: 0, Errors: 0, Skipped: 0. BUILD SUCCESS.
95 lines
3.9 KiB
Java
95 lines
3.9 KiB
Java
package dev.ltms.bridged.peer;
|
|
|
|
import java.util.List;
|
|
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 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,
|
|
* and naming conventions are all adapter-private — the core sees only the returned
|
|
* {@link PeerHandle} whose {@code id()} is the registry/routing key.
|
|
*
|
|
* <p>The interface is a superset of what {@code SessionManager} and {@code Bridged.main} call
|
|
* on the concrete launcher today.
|
|
*/
|
|
public interface PeerLauncher {
|
|
|
|
/**
|
|
* The set of {@link Capability capabilities} this launcher declares. A peer whose profile
|
|
* opts into a git-forge token should include {@link Capability#SELF_PR}; the base set for
|
|
* the Claude Code herdr adapter is always {@code MID_TURN_ASK, WORKTREE, ORPHAN_REAP}.
|
|
*/
|
|
Set<Capability> capabilities();
|
|
|
|
/**
|
|
* {@code profileName}/requestedCwd null/blank → default resolution. Returns after the peer
|
|
* process is live (env + argv + placement complete). Never returns {@code null}.
|
|
*
|
|
* @param req the spawn parameters (profile, requested cwd, caller cwd)
|
|
* @return a handle whose {@link PeerHandle#id()} is the registry/routing key
|
|
* @throws IllegalArgumentException if the profile is unknown and no default is configured
|
|
*/
|
|
PeerHandle spawn(SpawnRequest req);
|
|
|
|
/**
|
|
* The configured worker profile names — the set of names {@code spawn(profileName)} accepts.
|
|
*/
|
|
Set<String> profiles();
|
|
|
|
/**
|
|
* The profile a no-argument {@link #spawn(SpawnRequest)} uses, or {@code null} if none is configured.
|
|
*/
|
|
String defaultProfile();
|
|
|
|
/**
|
|
* Resolve the effective working directory for a spawn {@code req} without actually spawning.
|
|
* Resolution order: requestedCwd → profile cwd → callerCwd → daemon cwd.
|
|
*
|
|
* @return the resolved absolute path, never null/blank
|
|
*/
|
|
String effectiveCwd(SpawnRequest req);
|
|
|
|
/**
|
|
* The parity-overlay file list for {@code profileName} (default list when unset). Used by
|
|
* worktree provisioning to copy config files into the isolated checkout before spawning.
|
|
*/
|
|
List<String> parityOverlay(String profileName);
|
|
|
|
/**
|
|
* The set of all agents this launcher currently tracks, transport-specific. Each element
|
|
* exposes at minimum a pane-like {@code id()} matching this launcher's {@link PeerHandle}
|
|
* scheme, plus transport-level status. Callers merge this set with the session registry to
|
|
* build a live roster view.
|
|
*/
|
|
List<?> list();
|
|
|
|
/**
|
|
* Reap orphaned peers left behind by a prior daemon process. Only peers whose naming scheme
|
|
* matches this launcher's and whose nonce differs from the current process are eligible.
|
|
* Best-effort: a failure to list or to stop any one peer is logged and never aborts startup.
|
|
*
|
|
* @return the number of orphaned peers reaped
|
|
*/
|
|
int reapOrphanWorkers();
|
|
|
|
/**
|
|
* Tear a peer down by its registry/routing key ({@link PeerHandle#id()}). Tolerates an
|
|
* already-gone peer. Also cleans up launcher-private resources (e.g. empty dedicated tabs)
|
|
* when safe to do so.
|
|
*/
|
|
void stop(String id);
|
|
|
|
/**
|
|
* Discard the context of the peer identified by {@code id}. Implementations must bypass normal
|
|
* bridge delivery/turn accounting. Unsupported peer kinds return {@code false} without sending
|
|
* a guessed command.
|
|
*
|
|
* @return {@code true} when a reset was sent and its status transition must settle before reuse
|
|
*/
|
|
boolean clearContext(String id);
|
|
}
|