Repository navigation
Conversation
Claude Code's stream-json result event already carries usage, total_cost_usd,
num_turns, duration_ms, session_id and subtype; we typed it as `result?: string`
and dropped the rest, then asked the model to self-estimate its own token count
in the prompt.
Parse the whole event instead:
- total_tokens on the `complete` event is now the measured count (all four
usage buckets), with token_source ('harness' | 'agent' | 'none') alongside it
so counts from a harness that measures are never compared with a model's
guess. Codex and Gemini expose no structured stream, so their runs report
'none' rather than a silent zero.
- `subtype` decides whether the install is confirmed. error_max_turns and
error_during_execution still exit 0, which is exactly the refused-or-abandoned
case the exit code could not distinguish; such a run now closes the funnel as
partial and frames the demo guide as post-install work.
- Terminal runs print one line of run economics (tokens, cost, turns, duration),
and cost/turns/subtype go to debug notes since the proto has no fields yet.
Drop the token self-estimate from the MCP telemetry section and the complete
row: an unlabelled estimate is worse than no number now that the wizard has a
measured one. token_source is deliberately absent from the marker allowlist, so
a forged marker cannot claim its guess was measured.
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Claude Code's
stream-jsonresult event carriesusage,total_cost_usd,num_turns,duration_ms,session_idandsubtype. We typed it asresult?: stringand discarded the rest, then spent prompt budget asking the model to self-estimate its own token count. This parses the event instead.Tokens
completenow carries the measured count (all four usage buckets summed, so it matches what the run actually billed) plustoken_source:harness— read out of Claude Code's result eventagent— a model self-estimate, only ever a fallback, and labelled as suchnone— Codex and Gemini give no structured stream, so their runs report no count rather than a silent zeroNever compare token counts across harnesses without that field.
Run outcome
subtypeseparates a finished run fromerror_max_turns/error_during_execution. Both of those still exit 0, which is exactly the "exit 0 but the model refused or abandoned" caseinstallConfirmedpreviously had to guess at from the install marker alone. The harness verdict is now decisive when we have it: such a run closes the funnel aspartial, warns in the terminal, and frames the demo guide as post-install work.Also
442.0k tokens · $0.18 · 12 turns · 41s.note()calls, since the proto has no fields for them (added to the known-gaps list intelemetry.ts).completerow. GUI handoffs now report no token number rather than an unlabelled guess that arrives indistinguishable from a measured one.token_sourceis deliberately not in the marker allowlist, so a forged marker cannot claim its guess was measured.Notes for review
src/prompt/build.ts:52andtemplates/install-prompt.mdfor the self-estimate instruction. It actually lived only in the MCP section (mcpTelemetrySection) andCOMPLETE_ROW; the stdout/terminal path only ever asked forduration_ms.token_sourceis a new metadata field. If the telemetry endpoint rejects unknown metadata fields the way it 400s unknown steps,completeevents will start failing until the proto gains it. Worth confirming before this ships.Testing
npm run typecheckandnpm run buildpass. Parser smoke-tested end to end against a fakeclaudebinary emitting real-shapedstream-json, for both asuccessresult and anerror_max_turnsresult that exits 0: stats parse, the error path warns, and the telemetry marker in the same stream is still extracted.Note
Medium Risk
Changes onboarding funnel outcomes and telemetry metadata (
token_source,total_tokenssourcing); backend must accept the new metadata field orcompleteevents may fail.Overview
The wizard now reads real token usage, cost, turns, and duration from Claude Code’s
stream-jsonresult event instead of prompting models to self-estimate tokens. Terminal runs show a dim run economics line and warn when the resultsubtypeindicates the run did not finish cleanly (e.g. turn limit or mid-execution error), even when exit code is 0.Telemetry
completeevents attachtotal_tokensonly when there is a measured harness total (both phases summed) or a labelled agent fallback, always withtoken_source(harness/agent/none). Harness-reported errors makeinstallConfirmeddecisive for funnelsuccessvspartial. MCP install prompts no longer ask for token estimates oncomplete; marker parsing still blocks forgedtoken_source. Cost and extra harness fields go to debugnote()until the proto supports them.Reviewed by Cursor Bugbot for commit 91e8259. Bugbot is set up for automated code reviews on this repo. Configure here.