feat(analytics): runtime_type across the full event chain + BYOK run events#4510
feat(analytics): runtime_type across the full event chain + BYOK run events#4510elihahhahahah11 wants to merge 4 commits into
Conversation
…events Make runtime_type (amr_cloud / byok / local_cli) a first-class analytics dimension on every event so the behavioural funnel can split AMR / BYOK / CLI without static cohorts. - contracts: add runtime_type to AnalyticsConfigureGlobals (derived in deriveConfigureGlobals as the single active runtime — no 'both' cascade) and ChatAnalyticsHints; widen run agent_provider_id to allow BYOK providers. - daemon: stamp runtime_type on run_created/run_finished, with the web client's per-run hint overriding the BYOK-blind server derivation (runtimeTypeForRunAnalytics). - web: register runtime_type as a super-property so all client events carry it; emit run_created/run_finished for BYOK runs, which stream client-side and so never produced daemon run events before (they were invisible to the funnel). Red-spec first: apps/daemon/tests/run-runtime-type-analytics.test.ts pins the hint-override; apps/web/tests/byok-run-analytics.test.ts pins the BYOK builders.
|
Hi @elihahhahahah11! 👋 Thanks for wiring 💡 To drive this PR to merge hands-free, paste this to your AI coding agent (Claude Code / Codex / opencode / Cursor …): |
mrcfps
left a comment
There was a problem hiding this comment.
Thanks for wiring this through — the overall direction makes sense, but I left two follow-ups that affect how trustworthy the new BYOK runtime funnel will be in practice.
🔁 Powered by Looper · runner=reviewer · agent=opencode · An autonomous AI dev team for your GitHub repos.|
Hey @elihahhahahah11 — I took another look after @mrcfps's pass. The two follow-ups above are the right ones to address on this head:
Once those are handled, this should be in a good place for another review pass. |
mrcfps
left a comment
There was a problem hiding this comment.
Thanks for wiring this through — I found two follow-ups that still affect how trustworthy the new BYOK runtime funnel will be on this head.
🔁 Powered by Looper · runner=reviewer · agent=opencode · An autonomous AI dev team for your GitHub repos.|
QA 验收记录 验收范围:
已验证:
未验证:
风险/关注点:
结论:
|
|
Hey @elihahhahahah11 — quick status check on this head:
Once those are addressed, this should be ready for another look. |
mrcfps
left a comment
There was a problem hiding this comment.
Thanks for pushing this forward — I found two follow-ups that still affect how trustworthy the BYOK runtime funnel is on this head.
🔁 Powered by Looper · runner=reviewer · agent=opencode · An autonomous AI dev team for your GitHub repos.|
Hey @elihahhahahah11 — I checked the latest review on this head. The same two follow-ups from @mrcfps are still the right things to close out before another pass:
Once those are addressed, this should be ready for another look. |
mrcfps
left a comment
There was a problem hiding this comment.
Thanks for pushing this forward — I found three follow-ups that still affect how trustworthy the new runtime analytics will be on this head.
🔁 Powered by Looper · runner=reviewer · agent=opencode · An autonomous AI dev team for your GitHub repos.|
Hey @elihahhahahah11 — I checked the latest review on this head. The three follow-ups from @mrcfps look like the right things to close out before another pass:
Once those are addressed, this should be ready for another look. |
|
Addressed all three follow-ups in 0516f07:
Validation: contracts build+test (164), web + daemon typecheck, web analytics (23) + daemon analytics (8) tests, |
|
Hey @elihahhahahah11 — thanks for the detailed update. I see the three follow-ups from @mrcfps are addressed on this head, and the next maintainer review is already pending on the latest revision. Once that pass lands, we’ll have the up-to-date reviewer signal on this version. |
mrcfps
left a comment
There was a problem hiding this comment.
@elihahhahahah11 I re-reviewed the updated runtime analytics chain on ad41825 and verified the earlier follow-ups are now covered in the diff: BYOK run events pin runtime_type per event, the success-path BYOK run_finished emit survives project-file refresh failures, and deriveConfigureGlobals now lets API mode win over a stale remembered AMR agent. Thanks for pushing the fixes through — this looks ready from my review side.
…ished, mode-first derivation - byok-run: stamp runtime_type='byok' on run_created/run_finished instead of relying on the mutable super-property, so a mid-stream mode switch can't split one run across runtime buckets. Adds optional runtime_type to RunCreatedProps for the per-event override (daemon already pins it). - ProjectView: wrap the artifact-count refresh in try/catch so a rejected refreshProjectFiles() no longer swallows the success run_finished. - deriveConfigureGlobals: check mode==='api' before agentId==='amr' so an AMR→BYOK switch (which leaves agentId='amr') reports runtime_type=byok, not amr_cloud. Adds a regression test.





































































Why
While drilling the user-behaviour funnel down by runtime environment (AMR / BYOK / CLI) I hit a wall:
runtime_type(the only field that cleanly separatesbyokfromamr_cloud) was emitted only on onboardingui_clickevents. It was absent fromrun_created/run_finished/ export, so the daemon-side run events could not be split by runtime, and BYOK runs were effectively invisible to analytics. The only workaround was hand-built static cohorts that need daily rebuilding and double-count config-switchers.Two root causes, both fixed here:
runtime_typewas never promoted to a global public param (unlikeconfigure_type), so it didn't ride onto the full event chain.config.mode === 'api') stream client-side straight to the user's provider and never reach the daemon, so the daemon's authoritativerun_created/run_finishedwere never emitted for them. The web already hadtrackRunCreated/trackRunFinisheddefined but no callers.What users will see
No user-facing UI change. Internally, every analytics event now carries
runtime_type(amr_cloud/byok/local_cli/none), and BYOK runs now emitrun_created/run_finishedlike daemon runs do — so dashboards can finally split the run funnel by AMR / BYOK / CLI.Surface area
packages/contracts:runtime_typeadded toAnalyticsConfigureGlobals;runtimeTypeadded toChatAnalyticsHints;runagent_provider_idwidened to allow BYOK providers.Not a user capability, so the UI/CLI dual-track rule doesn't apply — this is analytics instrumentation behind existing flows.
Bug fix verification
Red-spec first, per AGENTS.md:
apps/daemon/tests/run-runtime-type-analytics.test.ts— pins that a clientruntime_type='byok'hint overrides the daemon's BYOK-blind derivation. Went red (helper absent) → green.apps/web/tests/byok-run-analytics.test.ts— pins the BYOKrun_created/run_finishedprop builders (provider mapping, model-id bucketing, required fields).Validation
pnpm guard(61 pass)pnpm --filter @open-design/contracts build && pnpm --filter @open-design/contracts test(164 pass)pnpm --filter @open-design/daemon typecheck+ daemon analytics tests (8 pass)pnpm --filter @open-design/web typecheck+ web analytics tests (22 pass)Notes / follow-ups
run_finishedcurrently reportsresult,artifact_count,asked_user_question,total_duration_ms; token-usage and duration-breakdown fields are left as an honest follow-up (token_count_source: 'unknown') rather than faked.configure_type(incl.both) is intentionally left as-is;runtime_typeis now the canonical runtime dimension.🤖 Generated with Claude Code