spawn/packages/cli/src/shared
Ahmed Abushagur 1e64d34e5a
Some checks are pending
CLI Release / Build and release CLI (push) Waiting to run
Lint / macOS Compatibility (push) Waiting to run
Lint / ShellCheck (push) Waiting to run
Lint / Biome Lint (push) Waiting to run
feat(telemetry): funnel + lifecycle events for onboarding drop-off (#3305)
* feat(telemetry): funnel + lifecycle events for onboarding drop-off

Adds low-volume, high-signal product events on top of the existing
errors/warnings telemetry (shared/telemetry.ts). Answers "where do users
bail before reaching a running agent" at the fleet level.

Funnel events (in orchestrate.ts, both fast and sequential paths):

  funnel_started              pipeline begins
  funnel_cloud_authed         cloud.authenticate() ok
  funnel_credentials_ready    OR key + preProvision resolved
  funnel_vm_ready             VM booted and SSH-reachable
  funnel_install_completed    agent install succeeded (tarball or live)
  funnel_configure_completed  agent.configure() ran
  funnel_prelaunch_completed  gateway / dashboard / preLaunch hooks done
  funnel_handoff              about to launch TUI (final step)

Every event carries elapsed_ms since funnel_started, plus agent and cloud
via telemetry context. Per-step counts reveal the drop-off funnel in
PostHog without touching any PII.

Lifecycle events (new shared/lifecycle-telemetry.ts):

  spawn_connected  { spawn_id, agent, cloud, connect_count, date }
    fired from list.ts when the user reconnects via the interactive picker.
    Increments connection.metadata.connect_count and writes last_connected_at
    so subsequent events and the eventual spawn_deleted have the total.

  spawn_deleted    { spawn_id, agent, cloud, lifetime_hours, connect_count, date }
    fired from delete.ts (both interactive confirmAndDelete and headless
    cmdDelete loop) after a successful cloud destroy. lifetime_hours is
    computed from SpawnRecord.timestamp to now. Clamped at 0 for corrupt
    clocks. connect_count is read from metadata.

New captureEvent(name, properties) helper in telemetry.ts:
- Respects SPAWN_TELEMETRY=0 opt-out (no new flag)
- Runs every string property through the existing scrubber (API keys,
  GitHub tokens, bearer, emails, IPs, base64 blobs, home paths)
- Non-string values pass through untouched

Tests: 20 new (15 lifecycle-telemetry + 2 captureEvent + 3 assertion
additions to disabled-telemetry). Full suite: 2129/2129 pass.

Bumps 1.0.10 -> 1.0.11. Patch bump — auto-propagates under #3296 policy.

* fix(test): replace mock.module with spyOn in lifecycle-telemetry tests

mock.module contaminates the global module registry when running under
--coverage, causing telemetry.test.ts and history-cov.test.ts to receive
mocked implementations instead of the real modules. Switch to spyOn with
mockRestore in afterEach so the real modules are preserved across files.

Agent: pr-maintainer
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

---------

Co-authored-by: L <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-15 11:35:53 +07:00
..
agent-setup.ts fix(security): use temp file for GitHub token to avoid process listing exposure (#3301) 2026-04-14 21:56:13 +07:00
agent-tarball.ts fix: extract tarballs directly to $HOME on non-root VMs (#3253) 2026-04-10 13:45:16 +07:00
agents.ts feat(security): add periodic security scan cron for VMs (#3214) 2026-04-06 23:29:14 -07:00
billing-guidance.ts fix: standardize ESM import extensions across 35 production files (#2827) 2026-03-20 08:51:40 -07:00
cloud-init.ts refactor(test): extract shouldSkipCloudInit helper and add unit tests (#2958) 2026-03-24 22:32:53 +07:00
cursor-proxy.ts fix(cursor): update proxy model list to current models (#3105) 2026-03-29 21:25:58 -07:00
lifecycle-telemetry.ts feat(telemetry): funnel + lifecycle events for onboarding drop-off (#3305) 2026-04-15 11:35:53 +07:00
oauth-constants.ts fix: restore hyphens in OAuth code regex + add regression test (#2171) 2026-03-03 22:52:29 -08:00
oauth.ts fix(spawn-fix): load API keys via config file, not just process.env (#3095) 2026-03-31 03:03:47 +07:00
orchestrate.ts feat(telemetry): funnel + lifecycle events for onboarding drop-off (#3305) 2026-04-15 11:35:53 +07:00
parse.ts refactor: remove dead deepMerge export from parse.ts (#2663) 2026-03-15 13:57:47 -07:00
paths.ts fix(update): cache successful update checks for 1 hour (#2755) 2026-03-17 23:08:05 -07:00
result.ts refactor: replace indiscriminate try/catch with guarded Result helpers (#2477) 2026-03-10 18:55:07 -07:00
shell.ts feat: add Windows PowerShell support — remove bash dependency for local execution (#2727) 2026-03-17 16:35:23 -07:00
skills.ts fix(security): validate remotePath in injectInstructionSkill to prevent shell injection (#3276) 2026-04-11 17:50:05 -07:00
spawn-config.ts refactor: remove dead exported types from picker.ts and spawn-config.ts (#2553) 2026-03-12 21:43:05 -04:00
spawn-skill.ts fix: add pi agent and daytona cloud to embedded skill lists (#3172) 2026-04-04 14:52:05 +07:00
ssh-keys.ts fix: handle missing ssh-keygen in getSshFingerprint (#2926) 2026-03-24 06:50:45 +07:00
ssh-runner.ts fix: complete VM recovery rewrite for spawn fix command (#3178) 2026-04-05 11:27:47 +07:00
ssh.ts fix(ux): reduce SSH wait verbosity and clarify agent handoff (#3056) 2026-03-27 15:22:46 +07:00
star-prompt.ts feat(cli): add star-the-repo nudge after successful spawns (#3025) 2026-03-27 03:15:12 +07:00
telemetry.ts feat(telemetry): funnel + lifecycle events for onboarding drop-off (#3305) 2026-04-15 11:35:53 +07:00
ui.ts feat: add PostHog telemetry for CLI errors and warnings (#3242) 2026-04-08 18:02:39 -07:00