Files
orca/src/shared/daemon-adoption-telemetry.ts
T
Jinwoo Hong a7fda48fe3 feat(telemetry): measure macOS stale-daemon adoption and cwd denials (#18043)
* feat(telemetry): measure macOS stale-daemon adoption and cwd denials

Adds two enum-only PostHog events so #17696 can be sized instead of guessed at:

- daemon_adopted: once per macOS launch that keeps a daemon an earlier app
  launch forked (invisible to daemon_lifecycle, which only sees replacements).
  Carries app-version match, spawner-path class (installed app / Squirrel
  ShipIt cache / other / missing), the existing TCC attribution verdict, and
  the bucketed live-session count.
- daemon_pty_cwd_denied: the symptom itself. The daemon probes the requested
  cwd in its own process (only its TCC context counts) and returns an additive
  cwdReadableByDaemon field; the app emits only when the daemon was denied AND
  the app can read the same path, so a missing or genuinely unreadable cwd
  never counts. Non-permission errors read as readable on purpose.

Both emitters swallow every failure; nothing here can delay or fail daemon
startup or a PTY spawn. Off macOS neither event fires. The new wire field is
optional, so older daemons and clients are unaffected.

* fix(telemetry): keep cwd-denial classification inside the swallow guard

Read the pid record at emit time (inside the try) rather than passing the
adapter's startup snapshot: a throwing app-environment read can no longer
escape spawn(), and a denial after a respawn is billed to the daemon that
actually spawned the PTY.
2026-09-01 22:33:39 -04:00

68 lines
2.2 KiB
TypeScript

// Enums for the `daemon_adopted` and `daemon_pty_cwd_denied` telemetry events (#17696).
// Both exist to measure how often a macOS app runs on a daemon left behind by an earlier app
// bundle, and how often such a daemon actually spawns a terminal whose cwd it cannot read.
// Enum-only: no paths, versions, or exact counts ever reach the wire.
/** How the adopted daemon's recorded app version compares to the running app. */
export const DAEMON_ADOPTED_APP_VERSION_MATCH = ['same', 'different', 'unknown'] as const
export type DaemonAdoptedAppVersionMatch = (typeof DAEMON_ADOPTED_APP_VERSION_MATCH)[number]
/**
* Where the binary that forked the adopted daemon lives now. `updater-cache` is the Squirrel
* ShipIt staging area — a daemon attributed there is the reported #17696 shape.
*/
export const DAEMON_SPAWNER_PATH_CLASSES = [
'applications',
'updater-cache',
'other',
'missing',
'unknown'
] as const
export type DaemonSpawnerPathClass = (typeof DAEMON_SPAWNER_PATH_CLASSES)[number]
export const DAEMON_TCC_ATTRIBUTION_VALUES = ['intact', 'severed', 'unknown'] as const
/** Which macOS-protected folder class the denied cwd falls under. */
export const DAEMON_PTY_CWD_CLASSES = [
'documents',
'desktop',
'downloads',
'other-home',
'outside-home'
] as const
export type DaemonPtyCwdClass = (typeof DAEMON_PTY_CWD_CLASSES)[number]
export function classifyDaemonSpawnerPath(
spawnerExecPath: string | null,
exists: (path: string) => boolean
): DaemonSpawnerPathClass {
if (!spawnerExecPath) {
return 'unknown'
}
if (!exists(spawnerExecPath)) {
return 'missing'
}
if (/\/Library\/Caches\/[^/]*ShipIt\//.test(spawnerExecPath)) {
return 'updater-cache'
}
return /^(?:\/private)?\/Applications\//.test(spawnerExecPath) ? 'applications' : 'other'
}
export function classifyDaemonPtyCwd(cwd: string, homeDir: string): DaemonPtyCwdClass {
const home = homeDir.replace(/\/+$/, '')
if (!home || !(cwd === home || cwd.startsWith(`${home}/`))) {
return 'outside-home'
}
const topLevel = cwd.slice(home.length + 1).split('/')[0]
switch (topLevel) {
case 'Documents':
return 'documents'
case 'Desktop':
return 'desktop'
case 'Downloads':
return 'downloads'
default:
return 'other-home'
}
}