feat(analytics): add Source column classifying sessions by SDLC tooling#402
Merged
Conversation
Skill dispatches ran inline in the parent transcript and were never priced (enrichDispatchCosts only enriched kind === 'agent'). They now get costUSD/tokens by re-attributing the session's own already-priced usage records that fall inside the skill's time window.
…ction hasCostData gated the Timeline's "cost..." subtitle on kind === 'agent' only, so it under-reported once skill dispatches could also carry costUSD. Bar rendering and the detail panel already check costUSD without a kind restriction, so only this gate needed broadening.
…t matching window buildDispatches() attributed agent:* api_requests to whichever subagent_completed window happened to be processed first in event order. When parallel subagents' completion windows overlap, a wider window could greedily claim a request meant for a narrower, more precise one — leaving the correct dispatch with no cost at all. OTEL carries no per-invocation id to disambiguate exactly, so this switches to a two-pass design: collect every agent window first, then attribute each request to the narrowest window that contains it.
…what's implemented Clarify that only agent/skill dispatches with attributable usage in their time window show cost; slash commands are point events and never do.
…than the pricing table pricing.json is manually vendored and lags new model releases; a model like claude-sonnet-5 (no shared version segment with any -4-* key) was hitting lookupPrice() returning null, so per-agent dispatches showed correctly attributed tokens but no cost in the timeline. Every -4-* version bump within a Claude tier has kept the same per-token rate, so lookupPrice() now falls back to the latest known same-tier price when no exact/segment match exists, in addition to pinning an explicit claude-sonnet-5 entry.
8nevil8
approved these changes
Jul 1, 2026
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.
Summary
Adds a "Source" column to the analytics dashboard's Sessions table (right after "Branch") that classifies each session by which SDLC tooling/framework it used: CodeMie AI Factory (sdlc-factory skills/agents/commands), Superpowers, OpenSpec, SpecKit, BMAD, or Pure chat as the fallback when no signal is found.
Changes
src/cli/commands/analytics/report/session-source-detector.ts— new Strategy-pattern detector registry: an ordered, first-match-wins list of{name, label, matches}detectors, extensible without editing a branching if/else chain.src/cli/commands/analytics/report/payload-builder.ts— wiresdetectSessionSource()in using theskillInvocations/agentInvocations/commandInvocationsdata already flowing through the pipeline (no new telemetry needed); addssessionSourceto eachReportSessionRecord.src/cli/commands/analytics/report/types.ts— adds thesessionSource: stringfield.src/cli/commands/analytics/report/client/app.js— renders the new "Source" column in the Sessions table (header/row/alignment-mask arrays + search filter).Detection is name-based only (no filesystem marker inspection), per an explicit product decision to keep the mechanism uniform across all bundles, including SpecKit/BMAD (which in this repo are otherwise only implemented via filesystem init markers).
Testing
session-source-detector.test.ts(11 cases) and an addedpayload-builder.test.tscaseChecklist
npm run cigates: license-check, lint (scoped — no new violations), typecheck, build, unit (2185 passed), integration (220 passed))main