fix(cli): honor CLIDE_SOCK as an explicit target, fail loudly if dead (T-247)
The `clide` shell client only ever computed the socket path from the workspace's FNV-1a hash — it never read CLIDE_SOCK, so the var the app exports to spawned agents was a no-op and a bogus CLIDE_SOCK was silently ignored (it still hit the discovered instance). Now: when CLIDE_SOCK is set the client connects to it directly, beating discovery, and a dead socket aborts with EX_UNAVAILABLE rather than falling back to a different instance (the split-brain footgun). Unset → the deterministic per-workspace path (D-70) as before. The server keeps deterministic binding; this is a client-side targeting override only. Also fixes a pre-existing -Wstringop-truncation warning in find_workspace_root (strncpy+manual-null → snprintf). Tests: the e2e suite now clears the inherited CLIDE_SOCK so discovery tests stay hermetic (the suite may run inside a clide instance), plus two new tests — a valid CLIDE_SOCK pins from a non-git dir, a dead one fails loudly and returns no data. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -6784,3 +6784,4 @@ is enough. Removed the Team-tab account card (and its usage prop + i18n keys);
|
||||
the budget now lives only on the Activity tab, next to the /usage refresh
|
||||
control that fetches it (T-415). The three-tab card facelift stays. Q-34
|
||||
answered: budget surfaces once, on Activity.', NULL, '2026-06-27 05:55:56', '2026-06-27 05:55:56.468', '2026-06-27 05:55:56.468', NULL, 'ba7329e54bf44c2cb5a9e7fb63e685f3', 2) ON CONFLICT(hash) DO NOTHING;
|
||||
INSERT INTO ticket_history (ticket_record_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FB0TNQM6QCYT7JBF352YVJ48', 'status', 'backlog', 'in_progress', NULL, '2026-06-27 06:06:03', '2026-06-27 06:06:03.770', '2026-06-27 06:06:03.770', NULL, 'c1cff9a2f682f3bb8f719f6771cf36c3', 2) ON CONFLICT(hash) DO NOTHING;
|
||||
|
||||
@@ -8436,3 +8436,13 @@ is enough. Removed the Team-tab account card (and its usage prop + i18n keys);
|
||||
the budget now lives only on the Activity tab, next to the /usage refresh
|
||||
control that fetches it (T-415). The three-tab card facelift stays. Q-34
|
||||
answered: budget surfaces once, on Activity.', 'done', 'low', NULL, NULL, NULL, '2026-05-23 20:48:38', '2026-06-27 05:55:56.468', NULL, 'c69aaa48a145eccdaed208eb01ab8a57', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash);
|
||||
INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FB0TNQM6QCYT7JBF352YVJ48', 'bug', NULL, 'clide CLI ignores CLIDE_SOCK and auto-discovers; stale sockets orphaned in runtime dir', 'The `clide` CLI does not honor the `CLIDE_SOCK` env var — it auto-discovers a running instance instead. Proof: with `CLIDE_SOCK=/run/user/1000/clide/DOES_NOT_EXIST.sock`, `clide version` still returns `{"version":"2.1.0"}` from the live app. Separately, the runtime socket dir accumulates orphaned socket files: `/run/user/1000/clide/` held two `.sock` entries while only one GUI process (the `build/linux/x64/debug/bundle/clide` bundle) was running, so a previous run''s socket was never cleaned up.
|
||||
|
||||
Why it matters: today (single instance) it''s harmless, but it''s a latent split-brain + observability hole. If two clide instances are ever live on the same machine, the CLI attaches to whichever discovery resolves first, with (a) no way to target a specific instance and (b) no way to find out which one you''re talking to. Combined with the stale-socket litter, `clide` could silently drive the wrong window. This is a D-6 surface gap — the CLI must be able to address the same instance the user is in.
|
||||
|
||||
Fix (scope to confirm):
|
||||
- Honor `CLIDE_SOCK` when set (explicit target beats discovery); error clearly if that socket is dead rather than silently falling back.
|
||||
- Clean up orphaned/stale socket files on app startup (and on clean shutdown) — detect a dead listener and unlink before binding a new hash.
|
||||
- Add a way to enumerate/identify live instances (e.g. a `clide instances` verb, or include the instance id/socket path + pid in `clide version`) so a human or agent can pick the right one.
|
||||
|
||||
Acceptance: a bogus `CLIDE_SOCK` fails loudly instead of returning data from a different instance; a valid `CLIDE_SOCK` pins the CLI to that instance; startup leaves exactly one live socket for one running app (no orphan accumulation); there is a CLI affordance to list/identify running instances.', 'in_progress', 'medium', NULL, NULL, 'D-6', '2026-06-05 21:28:48', '2026-06-27 06:06:03.770', NULL, '15ee4bd8e47ee2b0c1d2919fc2e3e013', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash);
|
||||
|
||||
Reference in New Issue
Block a user