Skip to content

feat: session enumeration confirmation + reply-alias worker pool - #41

Merged
Mearman merged 8 commits into
mainfrom
feat/session-enumeration-reply-aliases
Sep 17, 2026
Merged

Mearman merged 8 commits into
mainfrom
feat/session-enumeration-reply-aliases

Conversation

@Mearman

@Mearman Mearman commented Sep 17, 2026

Copy link
Copy Markdown
Member

Closes #40

Implements the two capabilities the agent-comms cross-machine mesh epic's default cc-peer front needs, gated on what Claude Code's local peer protocol actually supports (checked against source, not assumed):

  • Session enumeration: already fully supported by the existing CcPeer.roster() / GET /sessions (backed by FsRegistryStore.list(), which reads every ~/.claude/sessions/*.json file, not just cc-peer's own). No new capability needed here; this PR documents the finding.
  • Reply aliases: genuinely not supported natively for more than one name per process. The registry is one file per real OS pid (~/.claude/sessions/<pid>.json) with a single optional name field each, so a process can only ever publish one discoverable identity at a time (an existing integration test already demonstrates this: two peers sharing a pid leave only the last-registered name visible). Native SendMessage(name=X) resolution requires a real, live, distinctly-pid'd registry entry per name. This PR adds AliasPool, a minimal mechanism that lazily spawns one lightweight child process per correspondent alias (each running the existing CcPeer class under its own real pid), relays inbound replies back to the parent, and retires aliases on demand.

Work in progress; pushing early per the stacked-PR convention. Will flip to ready once the full slice (pool + Node adapter + worker + docs) lands and CI is green.

…ures

A reply-alias worker process can exit, or crash before registering, before
its parent observes a "started" acknowledgement; this gives that failure
its own machine-readable error code, matching the existing CcPeerError
taxonomy.
AliasPool's Node adapter and worker exchange start/stop commands and
started/message events over child_process.fork()'s IPC channel; this
schema is the single source of truth for that shape, independent of
the UDS wire protocol schemas.
Registering more than one natively-discoverable peer name per process is
not possible: the registry is one file per real OS pid
(~/.claude/sessions/<pid>.json) with a single optional name field each, so
a process publishing a second name overwrites its own entry rather than
adding to it. Each reply alias therefore needs its own real, distinct OS
process.

alias-worker.ts is that process's entry point: it registers a standalone
CcPeer under a given name and relays every inbound reply back over its
fork()'s own IPC channel. ForkedAliasProcess is the Node adapter that
forks one, satisfying the new AliasProcess port.

alias-worker.ts is deliberately its own dedicated tsdown entry (not left
to be pulled in transitively), so it is emitted as a real, directly
forkable file at a predictable path rather than folded into a shared
internal chunk whose location is a bundler implementation detail.
Lazily materialises one ForkedAliasProcess per mesh correspondent name on
ensure(), dedup'd against concurrent calls for the same name, and relays
each alias's own "message" and "exit" events with the correspondent name
attached. retire() waits for an in-flight ensure() of the same name to
settle before stopping it, so a retire issued while an alias is still
starting still stops it once (and if) it becomes active.
Adds a dedicated tsdown entry and package.json subpath export for
alias-pool.ts, mirroring the existing pattern for the "." entry, rather
than re-exporting it through cc-peer.ts (barrel re-exports are banned by
this repo's own eslint config). Also excludes alias-worker.ts from the
coverage gate, matching src/bin/** and sea-entry.ts: it is process
lifecycle glue exercised by a real fork in an integration test, not by
in-process unit coverage.
Records the empirical finding behind AliasPool: session enumeration is
already fully native (the roster builder reads every registry file on
disk, not just cc-peer's own), while reply aliases genuinely are not,
because the registry is one file per real pid with a single name each.
README documents cc-peer/alias-pool's own usage.
Extracts the worker-path extension derivation into workerExtensionFor(),
a pure function both branches can be exercised directly rather than only
through this module's own import.meta.url, which in dev/test always ends
in .ts and so could only ever reach the .mjs branch.

Also fixes the "worker fails to start" integration test: pointing
socketDir directly at a plain file (not a directory) forces mkdir() to
throw on macOS and Linux, but recursive mkdir() against an
already-existing path does not appear to verify it is actually a
directory on Windows, so the worker started successfully there instead
of failing. Nesting socketDir one level inside the broken file forces
mkdir() to create a genuinely new directory entry inside a file, which
has no valid resolution on any platform.
…cketDir

CcPeer.start() skips its socketDir mkdir entirely on Windows (a named
pipe has no filesystem directory of its own), so corrupting socketDir
can never force a failure there regardless of nesting, confirmed by this
test still failing on both Windows CI runners after the first nesting
fix. keys.writeForSocket() and registry.write() both mkdir into
sessionsDir(homeDir) unconditionally on every platform, so corrupting
homeDir instead reaches a real, unconditional mkdir() everywhere.
@Mearman
Mearman marked this pull request as ready for review September 17, 2026 15:05
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 17, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
🔒 Security Review Completed 2026-09-17T15:22:53.250533Z 49417bf Draft marked ready
ℹ️ 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" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@Mearman
Mearman merged commit a5a5579 into main Sep 17, 2026
8 checks passed
@Mearman
Mearman deleted the feat/session-enumeration-reply-aliases branch September 17, 2026 15:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Session enumeration API and reply aliases for the agent-comms front

1 participant