From adc94b026061675a29430e6170f066e8114e8823 Mon Sep 17 00:00:00 2001 From: geobelsky Date: Sat, 23 May 2026 18:22:39 +0000 Subject: [PATCH] feat(telemetry): capture error_class on setup_complete failures When setup fails, the dashboard's Phase Failures view showed only the phase (auth_check / init_scan) but not WHY. Now we populate error_class: - auth_check -> "oauth_missing" - init_scan -> classifyError(err) of the underlying exception Backend already reads error_class from any event payload (no migration). Co-Authored-By: Claude Opus 4.7 (1M context) --- src/cli.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/cli.ts b/src/cli.ts index a9fec6d..5b28adf 100644 --- a/src/cli.ts +++ b/src/cli.ts @@ -425,6 +425,7 @@ async function main() { let setupOutcome: "success" | "fallback" | "failed" = "failed"; let setupMethod: "llm" | "deterministic" = "deterministic"; let setupPhaseFailed: string | null = null; + let setupErrorClass: import("./telemetry.js").ErrorClass | null = null; let setupPresetsApplied = 0; let setupScannersRun = 0; let setupScannersFailed = 0; @@ -441,6 +442,7 @@ async function main() { scanners_run: setupScannersRun, scanners_failed: setupScannersFailed, phase_failed: setupPhaseFailed, + error_class: setupErrorClass, presets_applied: setupPresetsApplied, is_workspace: isWorkspace, child_repos: childRepos, @@ -463,6 +465,7 @@ async function main() { console.error(` export ANTHROPIC_API_KEY=sk-ant-... (API key)\n`); setupOutcome = "failed"; setupPhaseFailed = "auth_check"; + setupErrorClass = "oauth_missing"; await sendSetupTelemetry(); process.exit(1); } @@ -517,7 +520,8 @@ async function main() { setupOutcome = "failed"; setupPhaseFailed = "init_scan"; const { classifyError, reportError } = await import("./telemetry.js"); - try { reportError("setup", classifyError(err), true); } catch { /* swallow */ } + setupErrorClass = classifyError(err); + try { reportError("setup", setupErrorClass, true); } catch { /* swallow */ } await sendSetupTelemetry(); throw err; }