Skip to content

feat(export): add thinking_ratio to daily and session summaries (#633) - #635

Merged
lis186 merged 1 commit into
mainfrom
feat/633-thinking-ratio
Sep 9, 2026
Merged

lis186 merged 1 commit into
mainfrom
feat/633-thinking-ratio

Conversation

@lis186

@lis186 lis186 commented Sep 9, 2026 •

Copy link
Copy Markdown
Owner

Summary

  • Adds thinking_ratio (FLOAT, 0–1) to both daily and session export rows
  • Ratio of thinkingDuration / elapsed across proxy-observed turns only
  • null when no proxy turns with elapsed data exist (imported-only days/sessions)
  • Not a timestamp or elapsed timing — a dimensionless ratio; does not touch INV-2

Why this field

Adversarial review by two independent reviewers (Fable 5.1 + Sol) confirmed:

  • first/last_received_at timestamps → blocker (INV-2 violation) → dropped
  • total_elapsed_s / total_thinking_s → major (INV-2 "elapsed timings") → dropped
  • thinking_ratio → not an issue (dimensionless ratio, not a timing)
  • Session duration available from Anthropic telemetry (duration_ms) → don't duplicate

Thinking ratio is the one metric only ccxray can provide: "what fraction of wait time was extended thinking" is invisible to Anthropic's per-request telemetry.

Implementation

  • parseFloat(entry.elapsed) guards added (field is a string from toFixed(1))
  • Daily/session accumulators: _totalThinkingS, _totalElapsedS, _elapsedTurns
  • Ratio rounded to 4 decimal places, computed in finishDaily/finishSession
  • Test golden normalizer updated; schema additivity test updated

Second review — codex gate

Reviewer: codex (gpt-5.6-terra), 4 rounds.

Round Findings Disposition
R1 2 major: elapsed not guarded on !imported; elapsed missing from mergeEntry fill-if-null Fixed
R2 2 major: thinkingDuration also needs !imported guard; receivedAt/elapsed paired merge mixes copies Fixed
R3 1 major: else branch still mixes timing pair Fixed (simplified to atomic-only)
R4 1 minor: ratio can exceed 1 due to rounding mismatch Fixed (Math.min clamp)

codex gate clean

Test plan

  • 68 existing export tests pass (golden baselines, schema additivity, dedup, cross-agent)
  • Imported-only entries produce thinking_ratio: null (no false zero)
  • parseFloat handles the string elapsed field correctly

🤖 Generated with Claude Code

@lis186
lis186 force-pushed the feat/633-thinking-ratio branch 3 times, most recently from a8a2fe6 to 56b7945 Compare September 9, 2026 10:41
A dimensionless 0–1 float: total thinkingDuration / total elapsed, computed
per-day and per-session from proxy-observed turns only. null when no proxy
turns with elapsed data exist (imported-only sessions/days).

Not an elapsed timing or a timestamp — it's a ratio, so it does not touch
INV-2's exclusion of exact timestamps and elapsed timings. Adversarial
review by two independent reviewers confirmed this distinction.

elapsed is a string (forward.js toFixed(1)); parseFloat guards added.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@lis186
lis186 force-pushed the feat/633-thinking-ratio branch from 56b7945 to 1750492 Compare September 9, 2026 10:43
@lis186
lis186 merged commit 5bc9126 into main Sep 9, 2026
3 checks passed
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