Skip to content

feat: PostHog tracking for Capgo Builder onboarding + build lifecycle#2287

Open
WcaleNieWolny wants to merge 14 commits into
mainfrom
feat/builder-tracking-posthog
Open

feat: PostHog tracking for Capgo Builder onboarding + build lifecycle#2287
WcaleNieWolny wants to merge 14 commits into
mainfrom
feat/builder-tracking-posthog

Conversation

@WcaleNieWolny
Copy link
Copy Markdown
Contributor

@WcaleNieWolny WcaleNieWolny commented May 18, 2026

Summary

Adds PostHog tracking (via the existing sendEventToTracking dual-writer) for two event families in the Capgo Builder flow.

1. Per-step CLI onboarding tracking

  • New event Builder Onboarding Step fired per wizard step transition in both iOS (cli/src/build/onboarding/ui/app.tsx) and Android (cli/src/build/onboarding/android/ui/app.tsx) onboarding wizards.
  • Routed through the existing /private/events endpoint via the existing sendEvent() helper — no new backend endpoint.
  • Carries step, platform, app_id, optional duration_ms, optional error_category.
  • error_category is a closed enum (iOS: apple_api_unauthorized, apple_api_rate_limited, cert_limit_reached, profile_creation_failed, p8_invalid, unknown; Android: keystore_invalid, google_oauth_failed, play_account_id_invalid, unknown). Raw error messages never leave the CLI.
  • New helper cli/src/build/onboarding/telemetry.ts honors CAPGO_DISABLE_TELEMETRY / CAPGO_DISABLE_POSTHOG.

2. Server-side build lifecycle tracking

  • Build Requested fires from public/build/request.ts after the build_requests row is inserted.
  • Build Started, Build Succeeded, Build Failed, Build Timed Out fire from triggers/cron_reconcile_build_status.ts on status transitions.
  • Transition detection uses a new pure helper classifyBuildTransition in utils/build_tracking.ts. Idempotency is enforced by skipping when the previous status is already terminal — reuses the canonical TERMINAL_BUILD_STATUSES set from utils/build_timeout.ts.
  • failure_category is a closed enum (timeout, builder_error, validation_error, unknown). Raw error text never reaches PostHog.

Out of scope: the capgo_builder repo is not modified. Build Started is derived from the existing reconciliation cron diff, not a new builder push.

What's not changed

  • No new backend endpoint — reuses /private/events.
  • No new front-end pages, no schema migrations, no new env vars (other than honoring the existing CAPGO_DISABLE_TELEMETRY / CAPGO_DISABLE_POSTHOG).
  • The cron reuses default background-task semantics (waitUntil); no change to its completion model.

Test plan

  • bun run cli:check passes
  • New unit tests pass: error mappers (11), CLI telemetry helper (8), build transition + failure-category helpers (12) — 31 cases total
  • Adjacent existing tests still pass: tests/tracking.unit.test.ts, tests/posthog.unit.test.ts, tests/builder-payload.unit.test.ts, tests/build-timeout.unit.test.ts
  • Manual: walk through npx @capgo/cli build init --platform=ios two steps in staging; confirm Builder Onboarding Step events arrive in PostHog with the expected step, platform, app_id, and an org groups association
  • Manual: trigger one cloud build via npx @capgo/cli build request against staging; confirm Build RequestedBuild StartedBuild Succeeded/Build Failed arrive in PostHog with duration_seconds on terminal events and failure_category on failures
  • Confirm by sampling PostHog events that no error_category or failure_category value is anything other than the closed-enum members, and no raw error strings or file paths appear in any property

Documentation

Spec: docs/superpowers/specs/2026-05-18-capgo-builder-posthog-tracking-design.md
Plan: docs/superpowers/plans/2026-05-18-capgo-builder-posthog-tracking.md

Known limitations called out by reviewers but kept as-is

  • A CLI retry on a transient network error can produce a duplicate Build Requested event because build_requests has no idempotency key. Pre-existing behavior; the spec acknowledges this.
  • The cron emission uses sendEventToTracking's default background-task mode (the established convention across every other call site). Switching to foreground would serialize the cron loop and is left for a separate discussion.

Summary by CodeRabbit

  • New Features

    • Added PostHog telemetry for iOS/Android builder onboarding: step transitions, per-step duration, and error categorization; build lifecycle tracking for requests and status transitions (started, succeeded, failed, timed out).
    • Telemetry is best-effort and won’t disrupt onboarding when disabled.
  • Documentation

    • Added implementation plan and design/spec for builder telemetry.
  • Tests

    • Added unit tests for onboarding error mapping, telemetry payloads, and build-failure classification.

Review Change Stack

Adds the design doc covering two event families:

- Builder Onboarding Step (per-wizard-step, fired CLI -> backend
  -> sendEventToTracking) with closed-enum error categories
- Build lifecycle (Requested / Started / Succeeded / Failed /
  Timed Out) fired entirely server-side from the existing
  request handler and reconciliation cron

No changes to the capgo_builder repo; build_started is derived
from the existing builder polling.
The existing /private/events handler already implements auth,
org resolution, app_id permission check, and sendEventToTracking
with org grouping. Adding a second endpoint would duplicate
~80 lines of working code. CLI posts directly with the new
event name.
10 bite-sized TDD tasks covering iOS + Android error category
mappers, the CLI telemetry helper, useEffect wiring in both
wizards, pure build-transition / failure-category helpers,
Build Requested emission in request.ts, transition events from
cron_reconcile_build_status, full verification, and PR creation.

Reuses /private/events; no new backend endpoint. capgo_builder
repo is not touched.
The wizards previously stored only err.message in React state, then
reconstructed `new Error(message)` to pass to the category mapper —
losing the .status / .phase / instanceof discriminators the mapper
relies on. Capture the mapped category at handleError time via a
ref and pass it directly to the telemetry helper, bypassing the
mapper for wizard-emitted events. Tests, the helper interface, and
both wizards are updated.
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 18, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 05609a62-75d3-4b45-9aad-fe7d60edad6c

📥 Commits

Reviewing files that changed from the base of the PR and between c595d2c and f4a76b6.

📒 Files selected for processing (6)
  • cli/src/build/onboarding/android/ui/app.tsx
  • docs/superpowers/plans/2026-05-18-capgo-builder-posthog-tracking.md
  • docs/superpowers/specs/2026-05-18-capgo-builder-posthog-tracking-design.md
  • supabase/functions/_backend/utils/build_tracking.ts
  • tests/build-tracking-helpers.unit.test.ts
  • tests/builder-onboarding-telemetry.unit.test.ts
✅ Files skipped from review due to trivial changes (2)
  • docs/superpowers/plans/2026-05-18-capgo-builder-posthog-tracking.md
  • docs/superpowers/specs/2026-05-18-capgo-builder-posthog-tracking-design.md
🚧 Files skipped from review as they are similar to previous changes (4)
  • supabase/functions/_backend/utils/build_tracking.ts
  • cli/src/build/onboarding/android/ui/app.tsx
  • tests/build-tracking-helpers.unit.test.ts
  • tests/builder-onboarding-telemetry.unit.test.ts

📝 Walkthrough

Walkthrough

This PR adds end-to-end PostHog telemetry for Capgo Builder: onboarding step events (iOS/Android) with error-category tagging, a telemetry helper with env-opt-out, backend build lifecycle event emission (request & cron transitions), mapping helpers for error/failure categories, unit tests, and design/plan docs.

Changes

Builder Telemetry Implementation

Layer / File(s) Summary
Error Category Types and Mappers
cli/src/build/onboarding/types.ts, cli/src/build/onboarding/android/types.ts, cli/src/build/onboarding/error-categories.ts, tests/onboarding-error-categories.unit.test.ts
iOS and Android onboarding error types added; mappers classify raw errors by instance, HTTP-like status, and phase, with unknown fallback; tests validate precedence and mappings.
Telemetry Core Module
cli/src/build/onboarding/telemetry.ts, tests/builder-onboarding-telemetry.unit.test.ts
Adds trackBuilderOnboardingStep with TrackBuilderOnboardingStepInput, env-var opt-out (CAPGO_DISABLE_TELEMETRY/CAPGO_DISABLE_POSTHOG), rounded duration_ms, platform-specific error-category resolution or override, safe best-effort send, and tests covering payloads, mapping, disables, and failure swallowing.
iOS Onboarding Telemetry Integration
cli/src/build/onboarding/ui/app.tsx
Resolves/caches effective API key and organization ID once per session, emits step-transition telemetry with per-step duration and mapped OnboardingErrorCategory, and clears stored error category on retry/restart/completion.
Android Onboarding Telemetry Integration
cli/src/build/onboarding/android/ui/app.tsx
Same telemetry plumbing for Android: resolves API key/org-id, emits per-step events including duration, maps errors into AndroidOnboardingErrorCategory, and clears error-category state on retry/restart.
Backend Build Tracking Helpers
supabase/functions/_backend/utils/build_tracking.ts, tests/build-tracking-helpers.unit.test.ts
Exports classifyBuildTransition and mapBuildFailureCategory; classifier handles terminal/idempotent checks and timed_out override; failure mapper recognizes timeout, validation_error, builder_error, or unknown; tests cover transitions and message-based classification.
Build Request Event Emission
supabase/functions/_backend/public/build/request.ts
Emits Build Requested build-lifecycle event after persisting a build request with org grouping and tags for app_id, platform, build_mode.
Cron Reconciliation Build Lifecycle Events
supabase/functions/_backend/triggers/cron_reconcile_build_status.ts
Records previous status, classifies transition (started/succeeded/failed/timed_out), builds per-transition metadata/tags (including duration and failure category where applicable), and emits build-lifecycle events.
Design and Implementation Documentation
docs/superpowers/specs/2026-05-18-capgo-builder-posthog-tracking-design.md, docs/superpowers/plans/2026-05-18-capgo-builder-posthog-tracking.md
Adds spec and plan describing event schemas, closed enums, server/client responsibilities, privacy posture, implementation checklist, testing, and rollout instructions.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • Cap-go/capgo#2064: Related to Android onboarding and MissingScopesError used by Android error mapping.
  • Cap-go/capgo#2070: Related changes to build request/reconciliation flow and timeout/status behavior consumed by build lifecycle tracking.

Suggested reviewers

  • zinc-builds

Poem

🐰 I hopped through lines of code tonight,

Traced events, errors, and timing right,
From iOS steps to Android try,
Builds report when they run or die,
PostHog listens—telemetry takes flight!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat: PostHog tracking for Capgo Builder onboarding + build lifecycle' directly describes the main changes: adding PostHog tracking for both CLI onboarding steps and server-side build lifecycle events.
Description check ✅ Passed The PR description includes a detailed Summary covering both event families and their implementation, a comprehensive Test plan with manual verification steps, and a Documentation section referencing added specs and plans. The description is largely complete, though the Checklist section is not explicitly filled out.
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.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ 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/builder-tracking-posthog

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

@codspeed-hq
Copy link
Copy Markdown
Contributor

codspeed-hq Bot commented May 18, 2026

Merging this PR will not alter performance

✅ 43 untouched benchmarks
⏩ 2 skipped benchmarks1


Comparing feat/builder-tracking-posthog (8d92f93) with main (1d8f303)

Open in CodSpeed

Footnotes

  1. 2 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 7

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
supabase/functions/_backend/triggers/cron_reconcile_build_status.ts (1)

214-225: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Transition telemetry is race-prone without compare-and-set on status.

previousStatus is read from a stale snapshot, but Line 216 update only matches id. Concurrent reconciliations can both update and both emit the same transition event. Add a status guard in the update (eq('status', previousStatus)) and emit tracking only when that guarded update actually applies.

Also applies to: 252-291

🤖 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 `@supabase/functions/_backend/triggers/cron_reconcile_build_status.ts` around
lines 214 - 225, The current update to build_requests uses only .eq('id',
build.id) and reads previousStatus from a snapshot, so concurrent
reconciliations can both update and both emit transition telemetry; change the
update call in the reconciliation logic to include a status guard by adding
.eq('status', previousStatus) to the Supabase query (the call on
supabase.from('build_requests').update({...}).eq('id', build.id)), then only
emit the transition/telemetry when the guarded update actually applied (i.e.,
when the update returned a successful result/affected row(s) rather than an
error or zero rows). Apply the same change to the second reconciliation block
covering the code around the other update/emit (the block referenced in the
review for lines 252-291).
🧹 Nitpick comments (2)
docs/superpowers/specs/2026-05-18-capgo-builder-posthog-tracking-design.md (1)

110-136: 💤 Low value

Add language identifier to code fence.

The fenced code block at line 110 lacks a language specification, which triggers a markdown linting warning (MD040). Since this is an ASCII architecture diagram, specify text or plaintext as the language identifier.

📝 Proposed fix
-```
+```text
 ONBOARDING:
🤖 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 `@docs/superpowers/specs/2026-05-18-capgo-builder-posthog-tracking-design.md`
around lines 110 - 136, The fenced ASCII diagram starting with "ONBOARDING:"
should include a language identifier to satisfy MD040; update the opening code
fence that wraps the diagram (the block showing ONBOARDING, BUILDS,
sendEventToTracking, trackPosthogEvent, etc.) to use ```text (or ```plaintext)
instead of just ```, so the block becomes a text/plaintext code fence.
tests/builder-onboarding-telemetry.unit.test.ts (1)

24-143: ⚡ Quick win

Use it.concurrent for these test cases to match repo test policy.

These tests currently use it(...); the repository test guideline for tests/**/*.test.ts requires it.concurrent(...) for parallel execution.

As per coding guidelines, "Design all tests for parallel execution across files; use it.concurrent() instead of it() to run tests in parallel within the same file for faster CI/CD".

🤖 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 `@tests/builder-onboarding-telemetry.unit.test.ts` around lines 24 - 143,
Update each test declaration in this file to run concurrently by replacing
it(...) with it.concurrent(...); specifically modify the tests with descriptions
like "builds the expected payload and calls sendEvent once", "includes
error_category only when an error is provided", "uses the Android mapper when
platform is android", "skips when CAPGO_DISABLE_TELEMETRY is set", "skips when
CAPGO_DISABLE_POSTHOG is set", "swallows errors thrown by sendEvent", "does not
include duration_ms when undefined", and "uses pre-computed errorCategory when
provided (skipping the mapper)" so they call it.concurrent and otherwise keep
the same callbacks that call trackBuilderOnboardingStep and assert on
sendEventMock.
🤖 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 `@cli/src/build/onboarding/android/ui/app.tsx`:
- Around line 68-70: Reorder the three imports in app.tsx to satisfy the
perfectionist/sort-imports rule: locate the imports for
mapAndroidOnboardingError, trackBuilderOnboardingStep, and
ANDROID_STEP_PROGRESS/getAndroidPhaseLabel and reorder them to match the
repository's configured import groups/sort order (or run the linter autofix) so
the import sequence and grouping match perfectionist's expectations.

In `@docs/superpowers/plans/2026-05-18-capgo-builder-posthog-tracking.md`:
- Line 572: The current code wraps the wizard state error string as new
Error(error) which loses properties inspected by mapIosOnboardingError and
mapAndroidOnboardingError; instead pass the original error object (from wizard
state) or precompute and pass the mapped category to the telemetry helper.
Locate where error: step === 'error' && error ? new Error(error) : undefined is
set and change it to forward the original error object (e.g., errorObject) or
call the mapper (mapIosOnboardingError / mapAndroidOnboardingError) at that
point and pass the resulting category into the telemetry helper so the telemetry
receives the preserved onboarding error_category.

In `@docs/superpowers/specs/2026-05-18-capgo-builder-posthog-tracking-design.md`:
- Line 206: Update the stale endpoint reference: find the phrase mentioning "the
new /private/track_onboarding endpoint" in the spec and either change it to
reference the reused "/private/events" endpoint or remove the endpoint-specific
wording (e.g., replace with "No per-org rate limit on onboarding events");
ensure the surrounding text remains consistent with the architectural decision
to reuse /private/events.
- Line 23: Update the sentence that reads "Sent from the CLI through a new
backend endpoint" to clarify that the CLI uses the existing endpoint by
referencing "/private/events" (e.g., "Sent from the CLI through the existing
/private/events endpoint") so it matches the architectural decision described in
the section around the CLI wizard step transition and the reuse of the
/private/events endpoint.

In `@supabase/functions/_backend/public/build/request.ts`:
- Around line 317-329: The awaited sendEventToTracking call can throw and should
be best-effort: wrap the call to sendEventToTracking(c, { ... }) in a try/catch
so any rejection is caught, log the error (e.g., console.error or the
request/logger available on c) with context "Build Requested telemetry failed"
and do not rethrow or change the API response; keep the original behavior for
successful paths. Ensure you reference the existing sendEventToTracking
invocation and its context parameter c when applying the try/catch so telemetry
failures do not convert a successful build request into an API error.

In `@supabase/functions/_backend/utils/build_tracking.ts`:
- Around line 19-24: The current early-return checks evaluate equality before
honoring a timeout override, causing input.timeoutApplied true with
input.previous === input.next to return null; update the conditional order or
add a branch so that when input.timeoutApplied is true the function returns
'timed_out' regardless of equality — e.g., check input.timeoutApplied (or add a
specific conditional for input.timeoutApplied && input.previous === input.next)
before/above the input.previous === input.next check in the build/tracking logic
so callers passing raw next statuses get the 'timed_out' transition.

In `@tests/builder-onboarding-telemetry.unit.test.ts`:
- Line 9: Move the import of trackBuilderOnboardingStep so it appears at the top
of tests/builder-onboarding-telemetry.unit.test.ts before any runtime
statements; the lint error is caused by the import occurring after executable
code, so locate the current import of trackBuilderOnboardingStep and place it
with the other top-level imports to satisfy the import/first rule.

---

Outside diff comments:
In `@supabase/functions/_backend/triggers/cron_reconcile_build_status.ts`:
- Around line 214-225: The current update to build_requests uses only .eq('id',
build.id) and reads previousStatus from a snapshot, so concurrent
reconciliations can both update and both emit transition telemetry; change the
update call in the reconciliation logic to include a status guard by adding
.eq('status', previousStatus) to the Supabase query (the call on
supabase.from('build_requests').update({...}).eq('id', build.id)), then only
emit the transition/telemetry when the guarded update actually applied (i.e.,
when the update returned a successful result/affected row(s) rather than an
error or zero rows). Apply the same change to the second reconciliation block
covering the code around the other update/emit (the block referenced in the
review for lines 252-291).

---

Nitpick comments:
In `@docs/superpowers/specs/2026-05-18-capgo-builder-posthog-tracking-design.md`:
- Around line 110-136: The fenced ASCII diagram starting with "ONBOARDING:"
should include a language identifier to satisfy MD040; update the opening code
fence that wraps the diagram (the block showing ONBOARDING, BUILDS,
sendEventToTracking, trackPosthogEvent, etc.) to use ```text (or ```plaintext)
instead of just ```, so the block becomes a text/plaintext code fence.

In `@tests/builder-onboarding-telemetry.unit.test.ts`:
- Around line 24-143: Update each test declaration in this file to run
concurrently by replacing it(...) with it.concurrent(...); specifically modify
the tests with descriptions like "builds the expected payload and calls
sendEvent once", "includes error_category only when an error is provided", "uses
the Android mapper when platform is android", "skips when
CAPGO_DISABLE_TELEMETRY is set", "skips when CAPGO_DISABLE_POSTHOG is set",
"swallows errors thrown by sendEvent", "does not include duration_ms when
undefined", and "uses pre-computed errorCategory when provided (skipping the
mapper)" so they call it.concurrent and otherwise keep the same callbacks that
call trackBuilderOnboardingStep and assert on sendEventMock.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: 86155c78-e235-4024-b26b-5c9006cfabab

📥 Commits

Reviewing files that changed from the base of the PR and between d9c7cb4 and c595d2c.

📒 Files selected for processing (14)
  • cli/src/build/onboarding/android/types.ts
  • cli/src/build/onboarding/android/ui/app.tsx
  • cli/src/build/onboarding/error-categories.ts
  • cli/src/build/onboarding/telemetry.ts
  • cli/src/build/onboarding/types.ts
  • cli/src/build/onboarding/ui/app.tsx
  • docs/superpowers/plans/2026-05-18-capgo-builder-posthog-tracking.md
  • docs/superpowers/specs/2026-05-18-capgo-builder-posthog-tracking-design.md
  • supabase/functions/_backend/public/build/request.ts
  • supabase/functions/_backend/triggers/cron_reconcile_build_status.ts
  • supabase/functions/_backend/utils/build_tracking.ts
  • tests/build-tracking-helpers.unit.test.ts
  • tests/builder-onboarding-telemetry.unit.test.ts
  • tests/onboarding-error-categories.unit.test.ts

Comment thread cli/src/build/onboarding/android/ui/app.tsx Outdated
Comment thread docs/superpowers/plans/2026-05-18-capgo-builder-posthog-tracking.md Outdated
Comment thread docs/superpowers/specs/2026-05-18-capgo-builder-posthog-tracking-design.md Outdated
Comment on lines +317 to +329
await sendEventToTracking(c, {
event: 'Build Requested',
channel: 'build-lifecycle',
icon: '🛠️',
notify: false,
user_id: org_id,
groups: { organization: org_id },
tags: {
app_id,
platform,
build_mode,
},
})
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Don’t let telemetry failure fail a successful build request.

This awaited tracking call can reject and turn a successful persisted build request into an API error. Please make this best-effort (log and continue).

Proposed fix
-  await sendEventToTracking(c, {
-    event: 'Build Requested',
-    channel: 'build-lifecycle',
-    icon: '🛠️',
-    notify: false,
-    user_id: org_id,
-    groups: { organization: org_id },
-    tags: {
-      app_id,
-      platform,
-      build_mode,
-    },
-  })
+  try {
+    await sendEventToTracking(c, {
+      event: 'Build Requested',
+      channel: 'build-lifecycle',
+      icon: '🛠️',
+      notify: false,
+      user_id: org_id,
+      groups: { organization: org_id },
+      tags: {
+        app_id,
+        platform,
+        build_mode,
+      },
+    })
+  }
+  catch (error) {
+    cloudlogErr({
+      requestId: c.get('requestId'),
+      message: 'Failed to emit Build Requested tracking event',
+      app_id,
+      org_id,
+      error: (error as Error)?.message ?? String(error),
+    })
+  }
🤖 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 `@supabase/functions/_backend/public/build/request.ts` around lines 317 - 329,
The awaited sendEventToTracking call can throw and should be best-effort: wrap
the call to sendEventToTracking(c, { ... }) in a try/catch so any rejection is
caught, log the error (e.g., console.error or the request/logger available on c)
with context "Build Requested telemetry failed" and do not rethrow or change the
API response; keep the original behavior for successful paths. Ensure you
reference the existing sendEventToTracking invocation and its context parameter
c when applying the try/catch so telemetry failures do not convert a successful
build request into an API error.

Comment thread supabase/functions/_backend/utils/build_tracking.ts Outdated
Comment thread tests/builder-onboarding-telemetry.unit.test.ts Outdated
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c595d2c6d7

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +252 to +256
const transition = classifyBuildTransition({
previous: previousStatus,
next: effectiveStatus,
timeoutApplied,
})
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Track build transitions at write sites, not only in cron

This new transition emitter only runs inside cron_reconcile_build_status, but build status is also advanced in request-time handlers (public/build/start.ts sets status to running and public/build/status.ts updates terminal states + updated_at). Because this cron processes only stale non-terminal rows, builds that are actively polled or started through those endpoints can skip the transition window entirely, so Build Started/terminal lifecycle events are never sent. That makes PostHog lifecycle funnels incomplete for normal build flows; emit the same tracking when those other status writes occur (or centralize status-transition tracking in a shared write path).

Useful? React with 👍 / 👎.

- android/ui/app.tsx: reorder telemetry imports next to other
  ../../ depth imports to satisfy perfectionist/sort-imports
- builder-onboarding-telemetry.unit.test.ts: move
  trackBuilderOnboardingStep import above the vi.mock setup to
  satisfy import/first (vi.mock is hoisted by Vitest)
- build_tracking.ts: timeoutApplied now overrides the
  previous===next no-change check so a stale-snapshot caller
  passing equal statuses with timeoutApplied=true still emits
  'timed_out'. Adds matching test case.
- docs/spec: drop stale references to the never-built
  /private/track_onboarding endpoint; clarify the CLI uses the
  existing /private/events route. Tag the ASCII architecture
  diagram with the 'text' language for MD040.
- docs/plan: replace the stale `new Error(error)` snippet in
  both wizard wirings with the shipped errorCategoryRef +
  errorCategory: ... pattern, and add a one-line note pointing
  to the fix.

Skipped (with reasons):
- request.ts try/catch around sendEventToTracking: redundant.
  sendEventToTracking already swallows per-provider errors via
  runTrackedCall and returns Promise.resolve(null) via
  backgroundTask in production. Adding a wrap would diverge
  from every other call site (on_app_create.ts, stripe_event.ts,
  etc.) that follows the same pattern.
- cron_reconcile_build_status.ts optimistic-concurrency guard
  on the build_requests update: pre-existing systemic concern.
  None of the cron's other state mutations (recordBuildTime,
  status updates) use such a guard either. Adding it just for
  telemetry would be partial and inconsistent; out of scope.
- Converting it() to it.concurrent() in
  builder-onboarding-telemetry.unit.test.ts: the tests mutate
  shared process.env via beforeEach/afterEach. Concurrent
  execution would race on the env vars and produce flakes.
@sonarqubecloud
Copy link
Copy Markdown

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant