feat: telemetry for the workspace link lifecycle

RA
12h ago
+835-94

Closes #1508

What

Telemetry for the workspace link lifecycle in altimate-code, per the shared event contract (one name per fact, the backend's workspace id on every row, fired on the API success response, a client property on every envelope).

  • workspace_linked on a successful bind, create-and-bind or rebind, with workspace_id and how (bind_existing, create_and_bind, rebind_remote, rebind_path); workspace_created before it when the CLI created the workspace; workspace_switched on a rebind with the previous and the new id.
  • workspace_link_failed on a rejected link call with a reason class: auth, not_found, conflict, network, other.
  • workspace_unlinked on a successful unbind, with the id the caller knew.
  • Every failed workspace call through the shared request helper reports workspace_api_error (status class and status, endpoint with ids masked) or workspace_auth_expired on 401 and 403.
  • Every envelope carries client: altimate-code.
  • The create-and-link browser hand-off no longer drops the machine id for everyone: when the user config is unreadable (the link and auth login <url> paths skip instance bootstrap), the context follows the telemetry module's own decision instead of failing closed, since that module already sends the id in the same situation.

The emits live inside the workspace API client, so every caller (the link command, the TUI, the server routes) reports the same way. first_launch already carries install_method, so the install-source row needs nothing here.

Why

Nothing today records that a project was linked, to which workspace, how, or why a link failed; the dashboard could only infer a link from the MCP census. These are the funnel stages between taking a workspace into the CLI and the first use.

Verification

  • New link-telemetry.test.ts: 7 tests against a stubbed backend, asserting the events for bind, create-and-bind, rebind by remote and by path, unlink (2xx and 404), every failure class (404, 403, 409, unreachable, 500), endpoint masking, the timeout class, and the reason classifier.
  • The plugin test for the unreadable-config case now covers both telemetry off (id omitted) and telemetry on (id present).
  • Workspace, plugin and telemetry suites: 1,248 tests pass; tsgo --noEmit, oxlint and the marker guard clean.

Review log (claims and residuals Codex reviews against): https://github.com/AltimateAI/altimate-code/pull/1509#issuecomment-6189571040

πŸ€– Generated with Claude Code

https://claude.ai/code/session_011AhtJPr3nmT1Po92ZQk4VE


Summary by cubic

Adds telemetry for the workspace link lifecycle β€” linking, creating, switching, unlinking, and every failure β€” so the dashboard can attribute the funnel between taking a workspace into the CLI and first use. The create-and-link browser hand-off no longer drops the machine id when config is unreadable; it follows the telemetry module's own decision, sending the id only when telemetry is on.

  • workspace_linked, workspace_created, workspace_switched, and workspace_unlinked fire on the API success response carrying the backend workspace id; recovery-path unlinks carry the server-found id, and the unbound create-then-rebind path reports workspace_created with how: create_unbound and workspace_link_failed otherwise.
  • workspace_link_failed fires on rejected link calls with the reason classified as auth, not_found, conflict, network, or other; a failure that follows the server's answer (stalled or refused body) is classified by the answered status, so a 403/404/409/412 body failure keeps its class; every failed workspace call emits workspace_api_error β€” or workspace_auth_expired on 401/403 β€” with status_class covering 4xx, 5xx, network, timeout, and response for bad 2xx bodies; endpoints mask ids by route position rather than spelling, so an id spelled like a route word is still masked.
  • Every envelope carries client: altimate-code, and workspace ids ride as string properties rather than measurements, so the dashboards join on them.

Summary by CodeRabbit

  • Improvements
    • Workspace linking, creation, switching, and unlinking now report lifecycle activity and API outcomes, with clearer distinctions between network failures and server responses.
    • Workspace telemetry records workspace IDs consistently and includes additional lifecycle and API error details.
    • When configuration cannot be read, telemetry settings are checked before deciding whether to include a machine ID in the CLI context.