feat: default cc-peer front (slot identity, yield, dedup) - #171
Merged
Merged
Conversation
probeSlotOwner reads a slot's lock file without writing to it, and loadIdentityForFront loads or creates the slot's persisted identity without taking the exclusivity lock. Together these let a caller assume a not-yet-live (harness, cwd) slot's future identity while leaving the lock free for that slot's real owner to acquire normally later.
…ests Wraps probeSlotOwner's own parameter list and a multi-line assertion in the identity-store test suite onto prettier's expected line breaks.
createBridgeMeshSyncFromIdentity and createBridgeMeshFromIdentity build a mesh from an already-loaded identity, letting createBridgeMeshSync/createBridgeMesh keep owning loadOrCreateIdentity's lock while the cc-peer front (agent-comms#157) builds a mesh identity from loadIdentityForFront's lock-free one instead. Also exports the identity-store slot helpers from core/index.ts so bridge code outside core/ can reach them the same way it already reaches everything else in this factory.
…r the default front selectSessionsToFront filters a cc-peer roster down to the real Claude Code sessions the front should attach to: excludes other cc-peer-library peers (identified by cc-peer's own literal "cc-peer" version marker) and any session whose own identity slot is already held by a live bridge. matchInboundMessageSession attributes an inbound cc-peer message to the fronted session it came from, by matching the envelope's uds:<socketPath> convention against each fronted session's own messagingSocketPath. Kept free of any real cc-peer/MeshStore construction so the decision logic is testable purely over data; front-runtime.ts (agent-comms#157, still to come) builds the real stateful controller on top of these functions.
Fires true right after this store becomes coordinator (a fresh bind in init(), or a takeover via PeerLifecycle.handleBecomeCoordinator) and false right before shutdown() drops the role, mirroring the existing onDelivery/onPatch/onError callback fields. Gives bridge-mesh.ts a place to start and stop a coordinator-only, Node/filesystem-specific capability -- the cc-peer front (agent-comms#157) -- without pulling that concern into this transport-agnostic core.
CcPeerFront polls the injected roster on a fixed interval, attaching newly-selected sessions and detaching ones that exited or yielded (their own slot got claimed by a live bridge), diffing against what's already fronted so nothing is re-attached or double-torn-down across ticks. stop() detaches every still-fronted session, since a side that just lost the coordinator role has no business relaying on any session's behalf anymore. Mirrors StaleAgentChecker's own coordinator-only periodic-probe shape and stays free of any real cc-peer/MeshStore construction, matching front.ts's own testability discipline.
buildFrontedSessionRecord wires both relay directions for a single fronted session against its already-constructed mesh store/tool and the front's shared cc-peer peer: mesh-to-session sends a formatted delivery to the session's own pid, session-to-mesh posts an inbound cc-peer message into the session's own project room. detachFrontedSession marks the agent offline before shutting its store down. Mirrors bridges/cc-peer/bridge.ts's own wireCcPeerBridge split -- kept free of any real CcPeer.create()/createBridgeMeshFromIdentity construction so it's testable against fakes, with front-runtime.ts (still to come) supplying the real ones.
…uction createDefaultCcPeerFront builds the real CcPeerFront: a shared, lazily-created CcPeer instance (created on the first poll tick that actually needs it, not at start()), and an attach function that loads a not-yet-fronted session's identity via loadIdentityForFront, builds its mesh via createBridgeMeshFromIdentity, registers and rooms it, then wires the relay via buildFrontedSessionRecord. A construction or attach failure reports through onError rather than throwing, so a machine with no local Claude Code sessions -- or one where cc-peer itself can't bind -- degrades to a clean no-op front instead of crashing the coordinator that owns it. Widens CcPeerRosterEntryLike.name and CcPeerFrontDeps.pollIntervalMs/onError to explicit `| undefined` so they type-check against cc-peer's own RegistryEntry and an options object's optional fields under this repo's exactOptionalPropertyTypes. Untested directly, matching run.ts's own established precedent for real CcPeer.create() construction -- front.ts, front-controller.ts, and front-relay.ts already carry the front's entire decision/diffing/relay logic under direct DI-based unit tests.
…fault front wireDefaultCcPeerFront builds the callback a real bridge assigns to its own store.onCoordinatorRoleChanged: starts the front the moment that store becomes this machine's mesh coordinator, stops it the moment it loses that role. This is the piece that actually makes "a machine's coordinator bridge fronts local Claude Code sessions by default" true, rather than a capability every bridge builds but nothing switches on -- the real bridge entry points wire it next. Kept the only file outside bridges/cc-peer/ that needs to know cc-peer exists, matching this repo's own portable-runtime-boundary convention: core/mesh-store.ts's hook is a bare boolean callback, and core/bridge-mesh.ts's factories stay cc-peer-agnostic.
…entry point Every bridge entry point (pi, claude-code, mcp, codex, opencode, user, cc-peer's own one-shot command) now assigns store.onCoordinatorRoleChanged = wireDefaultCcPeerFront(store) right after constructing its own mesh, before init() ever runs. This is what actually makes "a machine's coordinator bridge fronts local Claude Code sessions by default" true for a real deployment, rather than leaving the front's own machinery built but never switched on -- whichever bridge type happens to win this machine's coordinator election starts fronting, and stops the moment it loses that role. user/controller.ts's fromExisting() path (wrapping an already-built store shared with a UI, e.g. pi's own web server) deliberately does not re-wire this -- the store's owning bridge already did, and wiring it twice would silently orphan the first front instance without ever starting it.
Adds a subsection alongside the existing cc-peer (cross-machine Claude Code relay) docs explaining the coordinator-run default front: identity belongs to the (harness, cwd) slot rather than whichever process currently serves it, no configuration is needed, and an empty local roster degrades to a clean no-op.
Mearman
force-pushed
the
feat/ccpeer-front
branch
from
September 17, 2026 16:54
053281f to
7b44592
Compare
Mearman
marked this pull request as ready for review
September 17, 2026 16:57
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #157
Implements the default coordinator-run cc-peer front: the machine's coordinator bridge fronts local Claude Code sessions that don't already have their own live agent-comms bridge, using the same (harness, cwd) identity slot that session's own bridge would use, so addressing carries over unchanged the moment that session's own bridge appears.
Work in progress; pushing early per the stacked-PR convention. Will flip to ready once the full slice lands and CI is green.
Building on top of cc-peer's session-enumeration support (ExaDev/cc-peer#40), already available in the installed version -- no cc-peer version bump needed.
Reply-alias wiring via cc-peer's AliasPool is out of scope here (#158, blocked on this PR); this PR's design is checked not to foreclose it -- the shared front-wide CcPeer instance and per-session mesh identity are exactly what #158's reply routing will sit on top of.