From 6d981976c02b158b6afe98017176b1c83516271f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Guti=C3=A9rrez?= <35082514+alezmad@users.noreply.github.com> Date: Mon, 4 May 2026 13:12:11 +0100 Subject: [PATCH] refactor(cli): drop CLAUDEMESH_SESSION_PRESENCE flag MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit per-session presence is small and uncomplicated enough that a rollback flag isn't load-bearing. backwards compat is already covered at the protocol layer — older brokers reply unknown_message_type to session_hello and the SessionBrokerClient marks itself closed for that mesh, which is the same outcome the flag would have given. removing the flag, the helper, and the conditional from the registry hook. Co-Authored-By: Claude Opus 4.7 (1M context) --- apps/cli/CHANGELOG.md | 16 +++++++++------- apps/cli/src/commands/launch.ts | 5 ++--- apps/cli/src/daemon/run.ts | 21 ++++----------------- docs/roadmap.md | 3 +-- 4 files changed, 16 insertions(+), 29 deletions(-) diff --git a/apps/cli/CHANGELOG.md b/apps/cli/CHANGELOG.md index 454dab4..f95d91c 100644 --- a/apps/cli/CHANGELOG.md +++ b/apps/cli/CHANGELOG.md @@ -31,9 +31,12 @@ access shape). `parent_attestation`). Older payloads continue to work. - **`claudemesh launch`** — generates an ed25519 session keypair and a 12 h parent attestation per launch (mesh secret key signs it), - forwards both to the daemon under `body.presence`. The flag - `CLAUDEMESH_SESSION_PRESENCE` defaults to ON; set `=0` to roll back - if a broker on a given mesh is misbehaving. + forwards both to the daemon under `body.presence`. Per-session + presence is always on; older brokers that don't recognize + `session_hello` reply `unknown_message_type` and the daemon quietly + drops the per-session WS for that mesh — the regular member-keyed + WS still covers all functionality, the only loss is sibling-session + visibility on that mesh. - **latent 1.29.0 bug fix** — `claudemesh launch` referenced `claudeSessionId` before its `const` declaration further down the file, hitting the temporal dead zone → `ReferenceError` silently @@ -44,10 +47,9 @@ access shape). ### Sequencing -The broker side ships first and bakes for ~24 h. Only then does the -flag default flip on the CLI side. Older CLIs continue working -unchanged (no per-session WS), and the protocol is purely additive on -the wire. +The broker side ships first and bakes for ~24 h. Older CLIs continue +working unchanged (no per-session WS), and the protocol is purely +additive on the wire. ### Verification (smoke) diff --git a/apps/cli/src/commands/launch.ts b/apps/cli/src/commands/launch.ts index 1d7c3be..8a48775 100644 --- a/apps/cli/src/commands/launch.ts +++ b/apps/cli/src/commands/launch.ts @@ -680,9 +680,8 @@ export async function runLaunch(flags: LaunchFlags, rawArgs: string[]): Promise< sessionTokenForCleanup = minted.token; // Per-session ephemeral keypair + parent attestation (1.30.0+). - // Behind CLAUDEMESH_SESSION_PRESENCE: the daemon ignores the - // presence material when the flag is off, so sending it always is - // forward-compatible. + // Older daemons ignore unknown body fields, so sending presence + // material always is forward-compatible. let presencePayload: { session_pubkey: string; session_secret_key: string; diff --git a/apps/cli/src/daemon/run.ts b/apps/cli/src/daemon/run.ts index d7f1c4e..352cb28 100644 --- a/apps/cli/src/daemon/run.ts +++ b/apps/cli/src/daemon/run.ts @@ -28,18 +28,6 @@ export interface RunDaemonOptions { clonePolicy?: ClonePolicy; } -/** - * 1.30.0 feature flag. Default ON — the daemon opens a long-lived WS per - * registered session so siblings see each other in `peer list`. Set - * CLAUDEMESH_SESSION_PRESENCE=0 (or "false"/"off") to disable for - * rollback if the broker side is misbehaving on a given mesh. - */ -function isSessionPresenceEnabled(): boolean { - const v = process.env.CLAUDEMESH_SESSION_PRESENCE; - if (v === undefined || v === "") return true; - return v !== "0" && v.toLowerCase() !== "false" && v.toLowerCase() !== "off"; -} - /** Detect a few common container environments to pick UDS-only by default. */ function detectContainer(): boolean { if (process.env.KUBERNETES_SERVICE_HOST) return true; @@ -167,14 +155,13 @@ export async function runDaemon(opts: RunDaemonOptions = {}): Promise { let drain: DrainHandle | null = null; drain = startDrainWorker({ db: outboxDb, brokers }); - // 1.30.0 — per-session broker presence. Default OFF for one release - // cycle so the broker side bakes before the flag flips. Opt-in via - // CLAUDEMESH_SESSION_PRESENCE=1; flips to default-on in 1.30.0 GA. - const sessionPresenceEnabled = isSessionPresenceEnabled(); + // 1.30.0 — per-session broker presence. Always on. Older CLIs that + // don't include `presence` material in the register body just won't + // get a session WS; the daemon's own member-keyed broker still + // covers them. const sessionBrokers = new Map(); setRegistryHooks({ onRegister: (info) => { - if (!sessionPresenceEnabled) return; if (!info.presence) return; const meshConfig = meshConfigs.get(info.mesh); if (!meshConfig) { diff --git a/docs/roadmap.md b/docs/roadmap.md index 736e5fd..e573815 100644 --- a/docs/roadmap.md +++ b/docs/roadmap.md @@ -277,8 +277,7 @@ identity (deferred for security review). signature checks; daemon adds a slim `SessionBrokerClient` and registry lifecycle hooks. Also fixes a latent 1.29.0 TDZ bug where `claudemesh launch`'s IPC session-token registration was silently - failing every run. Flag-gated for one cycle, default ON in this - release; set `CLAUDEMESH_SESSION_PRESENCE=0` for rollback. Spec at + failing every run. Spec at `.artifacts/specs/2026-05-04-per-session-presence.md`. What's left for true v2.0.0 (next sessions):