Skip to content

feat: [AI-7401] stamp launch_surface on serve telemetry events#970

Closed
ralphstodomingo wants to merge 2 commits into
mainfrom
feat/AI-7401-ide-session-telemetry
Closed

feat: [AI-7401] stamp launch_surface on serve telemetry events#970
ralphstodomingo wants to merge 2 commits into
mainfrom
feat/AI-7401-ide-session-telemetry

Conversation

@ralphstodomingo

@ralphstodomingo ralphstodomingo commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

Goal

Tie IDE sessions to Altimate Code telemetry (AI-7401). The serve harness already emits session_start, session_end, and agent_outcome (completed / aborted / abandoned / error) plus returning-user identity (machine_id, first_launch). The one missing dimension is launch surface — there is no way to tell an IDE-webview session from a CLI/TUI one. This adds it.

Change

packages/opencode/src/altimate/telemetry/index.ts:

  • Read ALTIMATE_LAUNCH_SURFACE once at telemetry init into a module-level launchSurface.
  • Stamp it as a launch_surface property on every App Insights envelope, alongside the existing machine_id (omitted when the env var is unset).
  • Reset it on shutdown().

The IDE extension sets ALTIMATE_LAUNCH_SURFACE=ide when it spawns altimate serve (see paired PR AltimateAI/vscode-altimate-mcp-server#<EXT_PR>). Direct CLI/TUI invocations leave it unset, so launch_surface is absent — querying launch_surface == "ide" selects IDE sessions; everything else is terminal.

No new event types and no per-session plumbing: the existing lifecycle events simply gain a filterable dimension.

Tests

Two new cases in test/telemetry/telemetry.test.ts (present-when-set, omitted-when-unset). Full file: 132 pass / 0 fail.

🤖 Generated with Claude Code

https://claude.ai/code/session_013aDZXEPBPcBAYNNcrKZomN


Summary by cubic

Add a launch_surface property to all serve telemetry events to distinguish IDE vs terminal sessions (AI-7401). Read ALTIMATE_LAUNCH_SURFACE at init, trim/lowercase, allow only ide/cli/tui, and omit the field when unset or unrecognized.

Written for commit 58adf31. Summary will update on new commits.

Review in cubic

Summary by CodeRabbit

  • New Features

    • Telemetry events now include the app’s launch surface (e.g., IDE, CLI, TUI) to better distinguish how the app was started.
  • Bug Fixes

    • Improved normalization and validation of launch-surface data, ensuring it’s omitted when unavailable or unrecognized.
    • Added test coverage for launch-surface behavior across multiple environment-variable scenarios.

Read `ALTIMATE_LAUNCH_SURFACE` from the environment once at telemetry
init and attach it as a `launch_surface` property on every App Insights
event. The IDE extension sets this to `ide` when it spawns
`altimate serve`; direct CLI/TUI invocations leave it unset, so the
property is omitted. This lets analytics separate IDE-originated
sessions (and their existing session_start / session_end / agent_outcome
events) from terminal usage without any new per-session plumbing.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013aDZXEPBPcBAYNNcrKZomN
@ralphstodomingo ralphstodomingo self-assigned this Jun 30, 2026
@coderabbitai

coderabbitai Bot commented Jun 30, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Telemetry events now include a launch_surface property derived from ALTIMATE_LAUNCH_SURFACE, with module state initialized during doInit(), attached to App Insights event properties when present, reset on shutdown(), and covered by tests for set, unset, normalized, and invalid values.

Changes

Launch Surface Telemetry

Layer / File(s) Summary
Launch surface capture and lifecycle
packages/opencode/src/altimate/telemetry/index.ts
Adds a module-level launchSurface value, derives it from ALTIMATE_LAUNCH_SURFACE during initialization, injects launch_surface into event properties when set, and clears the value on shutdown.
Telemetry envelope tests
packages/opencode/test/telemetry/telemetry.test.ts
Adds coverage for launch_surface when the env var is set, unset, whitespace-padded, or unrecognized, restoring environment state in each test.

Estimated code review effort: 2 (Simple) | ~10 minutes

Poem

I found a launch from the IDE,
Then CLI hops and TUI glee.
In telemetry it rides along,
Then resets cleanly when done is done. 🐇

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description covers the change and tests, but it omits the required PINEAPPLE prefix and the template's Summary/Test Plan/Checklist sections. Add PINEAPPLE at the top, then use the required Summary, Test Plan, and Checklist headings with completed items.
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: stamping launch_surface on serve telemetry events.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/AI-7401-ide-session-telemetry

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint install failed. For unrecoverable errors, disable the tool in CodeRabbit configuration.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@ralphstodomingo

Copy link
Copy Markdown
Contributor Author

E2E verified — Docker code-server (full chain)

Built this branch (npx turbo build --filter=@altimateai/altimate-code) and swapped the linux-x64 binary into a code-server container running the extension (AltimateAI/vscode-altimate-mcp-server#393), then exercised the real spawn path.

The running serve binary is this branch and embeds the new property (stock 0.8.10 does not):

$ altimate --version
0.0.0-feat/AI-7401-ide-session-telemetry-202606301539
$ grep -c launch_surface <binary>      # this branch: 2    stock 0.8.10: 0

The extension hands it ALTIMATE_LAUNCH_SURFACE=ide on spawn (captured via a binary shim, since the container blocks /proc/environ):

=== spawn … args=serve --port 16384 ===
ALTIMATE_LAUNCH_SURFACE=ide

→ this build reads that env at telemetry init and stamps launch_surface onto every event.

Unit coverage (this PR): full telemetry suite 132 pass / 0 fail, including present-when-set + absent-when-unset, asserted against the real outbound envelope JSON built by toAppInsightsEnvelopes.

code-server diagnostics

@ralphstodomingo ralphstodomingo marked this pull request as ready for review July 1, 2026 02:49
Copilot AI review requested due to automatic review settings July 1, 2026 02:49

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Claude Code Review

This repository is configured for manual code reviews. Comment @claude review to trigger a review and subscribe this PR to future pushes, or @claude review once for a one-time review.

Tip: disable this comment in your organization's Code Review settings.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a launch_surface custom dimension to App Insights telemetry emitted by altimate serve, enabling analytics to distinguish IDE-launched sessions (via ALTIMATE_LAUNCH_SURFACE=ide) from CLI/TUI sessions (unset ⇒ omitted).

Changes:

  • Read ALTIMATE_LAUNCH_SURFACE during telemetry initialization and store it in a module-level launchSurface.
  • Stamp launch_surface onto every emitted App Insights envelope when set.
  • Add tests for present-when-set vs omitted-when-unset behavior.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

File Description
packages/opencode/src/altimate/telemetry/index.ts Captures ALTIMATE_LAUNCH_SURFACE at init and injects launch_surface into telemetry properties; resets on shutdown.
packages/opencode/test/telemetry/telemetry.test.ts Adds regression tests verifying launch_surface is included only when the env var is set.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +1327 to +1329
// Set by the IDE extension when it spawns `altimate serve`; absent for
// direct CLI/TUI invocations.
launchSurface = process.env.ALTIMATE_LAUNCH_SURFACE ?? ""
Comment on lines +604 to +608
Telemetry.track({ type: "session_start", timestamp: 1700000000000, session_id: "sess-ide" })
await Telemetry.flush()

const envelopes = JSON.parse(fetchCalls[0].body)
expect(envelopes[0].data.baseData.properties.launch_surface).toBe("ide")
Comment on lines +621 to +625
Telemetry.track({ type: "session_start", timestamp: 1700000000000, session_id: "sess-cli" })
await Telemetry.flush()

const envelopes = JSON.parse(fetchCalls[0].body)
expect(envelopes[0].data.baseData.properties.launch_surface).toBeUndefined()

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/opencode/test/telemetry/telemetry.test.ts`:
- Line 604: The two Telemetry.track calls for session_start in telemetry.test.ts
are missing required fields for the session_start event. Update both calls at
the relevant test cases to include model_id, provider_id, agent, project_id, os,
arch, and node_version alongside type, timestamp, and session_id, using the
existing test fixtures or mock values already used for
Telemetry.Event["session_start"].
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 728ab0e8-7595-4efd-87c4-9fc1d559294e

📥 Commits

Reviewing files that changed from the base of the PR and between f0fb1e1 and 4953133.

📒 Files selected for processing (2)
  • packages/opencode/src/altimate/telemetry/index.ts
  • packages/opencode/test/telemetry/telemetry.test.ts

process.env.ALTIMATE_LAUNCH_SURFACE = "ide"
const { fetchCalls, cleanup } = await initWithMockedFetch()
try {
Telemetry.track({ type: "session_start", timestamp: 1700000000000, session_id: "sess-ide" })

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== telemetry test context =="
sed -n '520,650p' packages/opencode/test/telemetry/telemetry.test.ts | cat -n

echo
echo "== Event type / Telemetry.track declaration search =="
rg -n "type Event|interface Event|Telemetry\.track|track\(" packages/opencode -g '!**/dist/**' -g '!**/build/**'

echo
echo "== likely telemetry source files =="
fd -a "telemetry" packages/opencode/src packages/opencode/test packages/opencode -t f

Repository: AltimateAI/altimate-code

Length of output: 29640


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== altimate telemetry type definition =="
sed -n '1,220p' packages/opencode/src/altimate/telemetry/index.ts | cat -n

echo
echo "== track implementation area =="
sed -n '1360,1405p' packages/opencode/src/altimate/telemetry/index.ts | cat -n

echo
echo "== any event construction helpers around session_start =="
rg -n '"session_start"|session_start' packages/opencode/src/altimate/telemetry/index.ts packages/opencode/test/telemetry/telemetry.test.ts packages/opencode/test/altimate/telemetry-signals.test.ts

Repository: AltimateAI/altimate-code

Length of output: 14026


Add the required session_start fields to both new telemetry calls
Telemetry.Event["session_start"] requires model_id, provider_id, agent, project_id, os, arch, and node_version; the calls at packages/opencode/test/telemetry/telemetry.test.ts:604 and :621 only pass type, timestamp, and session_id.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/opencode/test/telemetry/telemetry.test.ts` at line 604, The two
Telemetry.track calls for session_start in telemetry.test.ts are missing
required fields for the session_start event. Update both calls at the relevant
test cases to include model_id, provider_id, agent, project_id, os, arch, and
node_version alongside type, timestamp, and session_id, using the existing test
fixtures or mock values already used for Telemetry.Event["session_start"].

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2 issues found across 2 files

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread packages/opencode/src/altimate/telemetry/index.ts Outdated
Comment thread packages/opencode/test/telemetry/telemetry.test.ts
Normalize casing/whitespace and restrict ALTIMATE_LAUNCH_SURFACE to a
known set (ide/cli/tui) so a stray value can't inflate the dimension's
cardinality. Add tests for normalization and unknown-value drop, plus
length assertions before indexing envelopes.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
packages/opencode/test/telemetry/telemetry.test.ts (1)

637-673: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Consider extracting the repeated env-var setup/restore boilerplate.

Each of the four tests duplicates the same origSurface capture/restore and initWithMockedFetch/flush/assert pattern. A small helper (e.g., withLaunchSurface(value, fn)) would reduce duplication across these tests.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/opencode/test/telemetry/telemetry.test.ts` around lines 637 - 673,
The telemetry tests repeat the same environment-variable save/restore and mocked
fetch setup/teardown logic across the launch_surface cases. Extract that
boilerplate into a small helper around Telemetry.track, Telemetry.flush, and
initWithMockedFetch, using the existing launch_surface test block to centralize
the origSurface handling and cleanup. Keep the helper focused on setting
ALTIMATE_LAUNCH_SURFACE, running the test body, then restoring the original
value so the individual tests only assert the expected launch_surface outcome.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@packages/opencode/test/telemetry/telemetry.test.ts`:
- Around line 637-673: The telemetry tests repeat the same environment-variable
save/restore and mocked fetch setup/teardown logic across the launch_surface
cases. Extract that boilerplate into a small helper around Telemetry.track,
Telemetry.flush, and initWithMockedFetch, using the existing launch_surface test
block to centralize the origSurface handling and cleanup. Keep the helper
focused on setting ALTIMATE_LAUNCH_SURFACE, running the test body, then
restoring the original value so the individual tests only assert the expected
launch_surface outcome.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: fabd3c77-0bd0-4dd9-a726-5eef7d811877

📥 Commits

Reviewing files that changed from the base of the PR and between 4953133 and 58adf31.

📒 Files selected for processing (2)
  • packages/opencode/src/altimate/telemetry/index.ts
  • packages/opencode/test/telemetry/telemetry.test.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/opencode/src/altimate/telemetry/index.ts

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 2 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="packages/opencode/src/altimate/telemetry/index.ts">

<violation number="1" location="packages/opencode/src/altimate/telemetry/index.ts:1331">
P3: `KNOWN_LAUNCH_SURFACES` includes `"cli"` and `"tui"` as accepted values, but no code path ever sets them — the IDE extension only ever sets `"ide"` and direct CLI/TUI leaves the env var unset. These are effectively dead allowlist entries that could inflate perceived surface support. Either remove them or add a comment reserving them for future use. If they remain, consider that setting `ALTIMATE_LAUNCH_SURFACE=cli` manually would pass through, so there is no harm — but dead entries risk misleading future maintainers.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

// direct CLI/TUI invocations. Normalize casing/whitespace and restrict to
// a known set so a stray env value can't inflate the launch_surface
// dimension's cardinality. New surfaces must be added to KNOWN_LAUNCH_SURFACES.
const KNOWN_LAUNCH_SURFACES = new Set(["ide", "cli", "tui"])

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: KNOWN_LAUNCH_SURFACES includes "cli" and "tui" as accepted values, but no code path ever sets them — the IDE extension only ever sets "ide" and direct CLI/TUI leaves the env var unset. These are effectively dead allowlist entries that could inflate perceived surface support. Either remove them or add a comment reserving them for future use. If they remain, consider that setting ALTIMATE_LAUNCH_SURFACE=cli manually would pass through, so there is no harm — but dead entries risk misleading future maintainers.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/opencode/src/altimate/telemetry/index.ts, line 1331:

<comment>`KNOWN_LAUNCH_SURFACES` includes `"cli"` and `"tui"` as accepted values, but no code path ever sets them — the IDE extension only ever sets `"ide"` and direct CLI/TUI leaves the env var unset. These are effectively dead allowlist entries that could inflate perceived surface support. Either remove them or add a comment reserving them for future use. If they remain, consider that setting `ALTIMATE_LAUNCH_SURFACE=cli` manually would pass through, so there is no harm — but dead entries risk misleading future maintainers.</comment>

<file context>
@@ -1325,8 +1325,12 @@ export namespace Telemetry {
+      // direct CLI/TUI invocations. Normalize casing/whitespace and restrict to
+      // a known set so a stray env value can't inflate the launch_surface
+      // dimension's cardinality. New surfaces must be added to KNOWN_LAUNCH_SURFACES.
+      const KNOWN_LAUNCH_SURFACES = new Set(["ide", "cli", "tui"])
+      const rawLaunchSurface = (process.env.ALTIMATE_LAUNCH_SURFACE ?? "").trim().toLowerCase()
+      launchSurface = KNOWN_LAUNCH_SURFACES.has(rawLaunchSurface) ? rawLaunchSurface : ""
</file context>

@kilo-code-bot

kilo-code-bot Bot commented Jul 1, 2026

Copy link
Copy Markdown

Code Review Summary

Status: 1 Issue Found | Recommendation: Address before merge

Overview

Severity Count
CRITICAL 0
WARNING 1
SUGGESTION 0

0 new inline comments were posted — the single outstanding issue below is already covered by an active inline review comment at telemetry.test.ts:604. No duplicates were added.

Issue Details (click to expand)

WARNING

File Line Issue
packages/opencode/test/telemetry/telemetry.test.ts 604, 623, 642, 661 The four new Telemetry.track({ type: "session_start", ... }) calls omit the required model_id, provider_id, agent, project_id, os, arch, node_version fields declared on Telemetry.Event["session_start"] (src/altimate/telemetry/index.ts:55-65). Against track(event: Event) (index.ts:1372) this is a tsc type error. It passes under bun test (no typecheck) but breaks any tsc --noEmit/typecheck gate. Supply the missing fields using the same fixture values as the pre-existing session_start test (telemetry.test.ts:562-573, e.g. model_id: "claude-3", provider_id: "anthropic", agent: "builder", os: "linux", arch: "x64", node_version: "v22.0.0").
Resolved / Verified (click to expand)
  • The ALTIMATE_LAUNCH_SURFACE normalization (.trim().toLowerCase()) and allowlist (ide/cli/tui) are in place at index.ts:1331-1333; empty/unrecognized values fall back to "" and are omitted from the envelope. (Previously flagged by Copilot/cubic; addressed in 58adf31.)
  • Explicit fetchCalls.length/envelopes.length assertions before indexing were added to all new tests. (Previously flagged by Copilot/cubic; addressed in 58adf31.)
  • Implementation matches the established machine_id pattern: read once in doInit(), stamped via ...(launchSurface && { launch_surface }) (index.ts:1235), and reset in shutdown() (index.ts:1464).
  • Test isolation confirmed: afterEach calls Telemetry.shutdown() (telemetry.test.ts:521), which resets launchSurface and initPromise, so the four env-var scenarios do not leak into one another.
Files Reviewed (2 files)
  • packages/opencode/src/altimate/telemetry/index.ts — 0 new issues
  • packages/opencode/test/telemetry/telemetry.test.ts — 1 issue (already flagged inline at line 604)

Fix these issues in Kilo Cloud


Reviewed by glm-5.2 · Input: 66K · Output: 19.5K · Cached: 735.2K

@dev-punia-altimate

Copy link
Copy Markdown
Contributor

🤖 Code Review — OpenCodeReview (Gemini) — No Issues Found

No comments generated. Looks good to me.

@ralphstodomingo

Copy link
Copy Markdown
Contributor Author

Superseded by the source field in #968 (+ vscode-altimate-mcp-server#386) — same global-envelope-injection mechanism, finer-grained values. Carried the normalize+allowlist hardening over as a suggestion on #968. Closing; branch kept.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants