Skip to content

Captain session identity: session_id wiring (#709) + self-describing -n names (#708) - #710

Merged
tu11aa merged 2 commits into
developfrom
crew/sess-id
Aug 21, 2026
Merged

Captain session identity: session_id wiring (#709) + self-describing -n names (#708)#710
tu11aa merged 2 commits into
developfrom
crew/sess-id

Conversation

@tu11aa

@tu11aa tu11aa commented Aug 21, 2026

Copy link
Copy Markdown
Owner

Summary

Two related identity gaps closed together (same files, one branch):

#709 — captain-bound channel now carries session_id. captain-channel-factory.ts hardcoded sessionIdFor: () => undefined. Resolves it from the same registry entry statusFor already reads (keyed by the launch-time socket path via readClaudeStatusBySocketPath), extracted into a small testable captainSessionIdFor. This:

  • restores the pid-reuse guard at registry.ts:137 (was silently skipped for every captain send)
  • removes the "Another Claude session sent a message:" wrapper + peer-guardrail paragraph on captain-bound CREW DONE/ping/Telegram sends
  • falls back to omitting session_id (never throws) when the captain hasn't registered in ~/.claude/sessions/ yet

#708 — captains and crews now get a self-describing name. squadrant never passed claude's -n, --name flag, so display names auto-derived from the cwd basename (squadrant-fix-706-67, helpa-06) — a crew calling ListAgents couldn't tell its own captain apart from an unrelated session and misrouted its report. Added captainSessionName(project) / crewSessionName(project, name) in @squadrant/shared (sanitized to the same safe-filename charset captainSocketPath() already enforces) and wired into both claude launch paths:

  • buildAgentCmd (captain/command, launch.ts) → squadrant-captain-<project>
  • claude driver's buildCommand (crew, crew-spawn.ts) → squadrant-crew-<project>-<name>

-n is claude-only. Added as an optional SpawnOptions.sessionName field that only the claude driver reads — codex/gemini/opencode buildCommand implementations were checked and ignore unknown fields safely (each reads only the specific opts.* keys it cares about), so this is a no-op for them.

Proof (#709 success criterion)

packages/cli/src/lib/__tests__/captain-channel-factory.test.ts builds a real ClaudePeerChannel wired the same way buildCaptainChannel() is, with a stub wire capturing the envelope:

  • captain resolvable in registry → envelope.session_id === "sess-captain-1"
  • captain not resolvable → envelope.session_id === undefined, send() still resolves (no throw)
✓ captainSessionIdFor > resolves the sessionId from the registry entry matching the captain's socket path
✓ captainSessionIdFor > returns undefined, not throw, when the captain has not registered yet
✓ captain envelope carries session_id end-to-end (#709) > includes session_id when the captain is resolvable in the registry
✓ captain envelope carries session_id end-to-end (#709) > omits session_id (does not throw) when the captain is not resolvable in the registry

Test plan

Not touched: daemon, captainChannel/controlChannel semantics, no drive-by refactors.

tu11aa added 2 commits August 21, 2026 13:20
Resolve the captain's own sessionId from the same registry entry
statusFor already reads (keyed by the launch-time socket path) and
wire it into ClaudePeerChannel's sessionIdFor, instead of hardcoding
undefined. Restores the pid-reuse guard and drops the "Another Claude
session sent a message" wrapper on captain-bound sends. Falls back to
omitting session_id (never throws) when the captain hasn't registered
yet.
squadrant never passed claude's `-n, --name` flag, so every session's
display name auto-derived from the cwd basename (e.g.
"squadrant-fix-706-67", "helpa-06") — indistinguishable via ListAgents.
A crew that could not tell its captain apart from an unrelated session
sent its PR report to the wrong one.

Adds `@squadrant/shared`'s captainSessionName/crewSessionName
(sanitized to the same safe-filename charset captainSocketPath()
already enforces) and wires them into both claude launch paths:
buildAgentCmd (captain/command, launch.ts) and the claude driver's
buildCommand (crew, crew-spawn.ts). Format: "squadrant-captain-<project>"
and "squadrant-crew-<project>-<name>".

`-n` is claude-only — added as an optional SpawnOptions field only the
claude driver reads; codex/gemini/opencode buildCommand implementations
were checked and ignore unknown fields safely, so they're unaffected.
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.

1 participant