tokentrace 0.21.0 → 0.21.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -4,6 +4,28 @@ All notable changes to TokenTrace are documented here.
4
4
 
5
5
  ## Unreleased
6
6
 
7
+ ## [0.21.2] - 2026-06-26
8
+
9
+ ### Fixed
10
+
11
+ - **ProjScan circular-import warnings removed.** Shared scan-health, analytics,
12
+ evidence, review-queue, project-signal, session-comparison, and unknown-cost
13
+ repair contracts now live in leaf type modules so the import graph stays
14
+ acyclic. Added a regression test for these architecture boundaries.
15
+
16
+ ### Changed
17
+
18
+ - **Low-risk dependency refresh.** Updated patch and minor dependencies within
19
+ the existing major-version ranges after audit and package-security checks.
20
+
21
+ ## [0.21.1] - 2026-06-26
22
+
23
+ ### Changed
24
+
25
+ - **README and website handoff now match the simplified product.** Refreshed the
26
+ public docs around preflight, Today, Evidence, Fix Data, and current
27
+ Playwright-captured `0.21.0` dashboard screenshots.
28
+
7
29
  ## [0.21.0] - 2026-06-26
8
30
 
9
31
  ### Added
package/README.md CHANGED
@@ -4,13 +4,26 @@
4
4
 
5
5
  # TokenTrace CLI
6
6
 
7
- Local-first AI CLI usage analytics. TokenTrace scans local CLI logs and local usage databases, normalizes token usage, estimates missing counts with confidence labels, and shows cost, model, project, session, repair, and evidence analytics in a browser dashboard.
7
+ Local-first AI CLI usage analytics for developers and coding agents.
8
+
9
+ TokenTrace answers one practical question before the next expensive AI CLI run:
10
+ is your local usage evidence ready to trust? It scans local Claude Code, Codex,
11
+ structured usage logs, and usage-shaped local databases, then labels token and
12
+ cost data as exact, estimated, unknown, cached, or non-cache. The dashboard
13
+ opens on **Today**, with direct paths into Sessions, Evidence, and Fix Data.
8
14
 
9
15
  TokenTrace is designed for local development machines first, with macOS-oriented defaults. It does not require a cloud account and does not send telemetry or logs anywhere.
10
16
 
11
17
  [Website](https://www.baseframelabs.com/apps/tokentrace) · [Source](https://github.com/abhiyoheswaran1/tokentrace)
12
18
 
13
- ![TokenTrace overview dashboard](docs/assets/overview-0.12.0.png)
19
+ ![TokenTrace Today dashboard](docs/assets/today-0.21.0.png)
20
+
21
+ ## What TokenTrace Helps You Do
22
+
23
+ - Check readiness before another coding-agent run with `tokentrace preflight --json` or MCP `get_preflight`.
24
+ - See today’s local cost, tokens, sessions, confidence, anomalies, and repair signals in one first screen.
25
+ - Trace every important number back to local files, parser state, sessions, model rates, and confidence labels.
26
+ - Fix missing cost data through a guided repair queue without uploading prompts or message bodies.
14
27
 
15
28
  ## Start In Seconds
16
29
 
@@ -133,8 +146,7 @@ explicit scan tool. It does not scan files on startup, and its scan tool require
133
146
  `confirmLocalScan=true` before reading local usage files or writing the local
134
147
  database.
135
148
 
136
- Before starting another long coding-agent run, use the read-only preflight
137
- surface:
149
+ Before starting another long coding-agent run, use preflight:
138
150
 
139
151
  ```bash
140
152
  tokentrace preflight --json
@@ -195,13 +207,17 @@ tokentrace roadmap --json
195
207
  # Inspect roadmap handoff, action recipes, and release status
196
208
  ```
197
209
 
198
- ## Local Sources And Trust
210
+ ## Daily Loop And Trust
199
211
 
200
- TokenTrace 0.12.0 bundles local source expansion, evidence exports, scan
201
- scheduling, scoped guardrails, parser profile preview, saved reports, and
202
- agent-readable release status.
212
+ TokenTrace now organizes the product around the daily loop:
203
213
 
204
- New trust surfaces include:
214
+ 1. **Preflight**: decide whether local evidence is ready before another agent run.
215
+ 2. **Today**: review cost, token, session, confidence, anomaly, and repair signals.
216
+ 3. **Evidence**: trace numbers back to source files, parser confidence, sessions, and model-rate state.
217
+ 4. **Fix Data**: resolve unknown cost, parser review, and model-rate gaps.
218
+ 5. **Advanced**: inspect Scan Health, Discovery, Parsers, Raw Data, Query, and Model Rates when you need the full diagnostic surface.
219
+
220
+ Trust surfaces include:
205
221
 
206
222
  - native structured usage log and Cursor-style chat export ingestion
207
223
  - Source Coverage in Scan Health for native, profile-assisted, fallback, and
@@ -214,11 +230,6 @@ New trust surfaces include:
214
230
  cost, high-cost sessions, and confidence trends
215
231
  - operating metadata export without raw usage records
216
232
 
217
- The 0.12.0 dashboard also tightens the daily operator path: setup buttons now
218
- open the exact Settings section, scan results show what changed and where to go
219
- next, and Evidence explains when it is being opened as a contextual drill-down
220
- rather than a sidebar destination.
221
-
222
233
  ## Accuracy And Evidence
223
234
 
224
235
  TokenTrace labels the trust level behind imported numbers:
@@ -270,10 +281,13 @@ Default discovery checks these locations when present:
270
281
  - TokenTrace wrapper logs in the local app-data directory
271
282
  - Any custom folders configured in Settings
272
283
 
273
- Use **Settings** in the dashboard to add custom folders, toggle raw message storage, and trigger scans. Use **Scan Health**, **Discovery**, **Parsers**, and **Raw Data** to inspect discovered files, parser decisions, warnings, failures, extracted metadata, and confidence levels.
284
+ Use **Settings** to add custom folders, toggle raw message storage, and trigger
285
+ scans. Use **Scan Health**, **Discovery**, **Parsers**, and **Raw Data** to
286
+ inspect discovered files, parser decisions, warnings, failures, extracted
287
+ metadata, and confidence levels.
274
288
 
275
289
  Settings also supports optional local monthly usage guardrails. Set a cost
276
- limit, token limit, or both, and Overview will show month-to-date progress from
290
+ limit, token limit, or both, and Today will show month-to-date progress from
277
291
  imported local CLI usage.
278
292
 
279
293
  Sessions includes built-in and local saved views for recurring review paths:
@@ -362,13 +376,13 @@ Codex CLI status-line integration is intentionally deferred until its status-lin
362
376
 
363
377
  Dashboard views:
364
378
 
365
- ![TokenTrace overview dashboard](docs/assets/overview-0.12.0.png)
379
+ ![TokenTrace Today dashboard](docs/assets/today-0.21.0.png)
366
380
 
367
- ![TokenTrace processed tokens evidence trail](docs/assets/evidence-0.12.0.png)
381
+ ![TokenTrace unknown cost evidence trail](docs/assets/evidence-0.21.0.png)
368
382
 
369
- ![TokenTrace unknown cost repair queue](docs/assets/repair-0.12.0.png)
383
+ ![TokenTrace Fix Data queue](docs/assets/fix-data-0.21.0.png)
370
384
 
371
- ![TokenTrace Scan Health parser review](docs/assets/scan-health-0.12.0.png)
385
+ ![TokenTrace Scan Health parser review](docs/assets/scan-health-0.21.0.png)
372
386
 
373
387
  CLI startup and help:
374
388
 
@@ -403,6 +417,7 @@ Stop the server with `Ctrl+C` in the terminal where `tokentrace` is running.
403
417
  - `npm run security:ioc` scans lockfiles, workflows, and local Claude/VS Code hook files for high-signal supply-chain compromise indicators.
404
418
  - Public npm publishing is configured through GitHub Actions Trusted Publishing and provenance from version tags.
405
419
  - Socket GitHub checks and ProjScan are used as release guardrails, alongside `npm audit --audit-level=moderate`.
420
+ - `npm run release:check` fails when a gate command exits non-zero. The import graph is expected to remain free of circular dependencies; `tests/import-boundaries.test.ts` protects shared type/helper modules from importing higher-level orchestration barrels.
406
421
  - Release notes are published directly in GitHub Releases from the relevant changelog section, not as a link-only summary.
407
422
 
408
423
  See [SECURITY.md](SECURITY.md) for the full security and privacy model.
@@ -3,6 +3,11 @@
3
3
  TokenTrace is a local-first CLI and dashboard for AI coding-agent token, cost,
4
4
  session, parser, and evidence analytics.
5
5
 
6
+ The current product loop is: run preflight, review Today, inspect Sessions or
7
+ Evidence, then use Fix Data when model rates or parser confidence block trusted
8
+ costs. Advanced pages remain available for diagnostics, but agents should start
9
+ from preflight before long runs.
10
+
6
11
  ## Start Here
7
12
 
8
13
  Use the read-only discovery manifest before running any other TokenTrace command:
@@ -101,19 +106,22 @@ curl http://127.0.0.1:3030/api/roadmap
101
106
  tokentrace preflight --json
102
107
  ```
103
108
 
104
- 4. Refresh local data when the human expects current usage:
109
+ 4. Follow the preflight decision. Use Today for the human-facing status, Evidence
110
+ for numeric claims, and Fix Data for unknown-cost work.
111
+
112
+ 5. Refresh local data when the human expects current usage:
105
113
 
106
114
  ```bash
107
115
  tokentrace scan --json
108
116
  ```
109
117
 
110
- 5. Check trust before making claims:
118
+ 6. Check trust before making claims:
111
119
 
112
120
  ```bash
113
121
  tokentrace doctor --json
114
122
  ```
115
123
 
116
- 6. Explain totals with evidence:
124
+ 7. Explain totals with evidence:
117
125
 
118
126
  ```bash
119
127
  tokentrace evidence --json
@@ -5,6 +5,9 @@ session, parser, and repair questions. The goal is not to make agents guess from
5
5
  terminal history. The goal is to make them check local TokenTrace data first,
6
6
  then report with confidence labels and evidence.
7
7
 
8
+ The current workflow is short: preflight first, Today for status, Evidence for
9
+ numbers, and Fix Data for unknown-cost or parser-confidence repairs.
10
+
8
11
  ## MCP Install
9
12
 
10
13
  MCP registry name:
Binary file
Binary file
Binary file
package/llms.txt CHANGED
@@ -2,6 +2,10 @@
2
2
 
3
3
  > Local-first analytics for AI CLI usage, focused on coding-agent tokens, costs, sessions, parser confidence, and evidence trails.
4
4
 
5
+ Current product loop: preflight before long runs, Today for local readiness and
6
+ daily usage, Sessions for conversation detail, Evidence for numeric claims, and
7
+ Fix Data for unknown cost or parser-confidence work.
8
+
5
9
  ## Agent Entry Point
6
10
 
7
11
  Start with:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tokentrace",
3
- "version": "0.21.0",
3
+ "version": "0.21.2",
4
4
  "mcpName": "io.github.abhiyoheswaran1/tokentrace",
5
5
  "description": "Local-first dashboard for AI CLI token, cost, and session analytics.",
6
6
  "author": {
package/server.json CHANGED
@@ -8,12 +8,12 @@
8
8
  "url": "https://github.com/abhiyoheswaran1/tokentrace",
9
9
  "source": "github"
10
10
  },
11
- "version": "0.21.0",
11
+ "version": "0.21.2",
12
12
  "packages": [
13
13
  {
14
14
  "registryType": "npm",
15
15
  "identifier": "tokentrace",
16
- "version": "0.21.0",
16
+ "version": "0.21.2",
17
17
  "runtimeHint": "npx",
18
18
  "packageArguments": [
19
19
  {
@@ -1,10 +1,7 @@
1
1
  import type { DataConfidenceGrade, DataConfidenceScore } from "@/src/lib/data-confidence";
2
- import type { EvidenceMetric } from "@/src/lib/evidence-trail";
2
+ import type { EvidenceMetric } from "@/src/lib/evidence/metrics";
3
3
  import type { LocalRecommendation } from "@/src/lib/recommendations";
4
- import type { ProjectSignalRow } from "@/src/lib/project-signals";
5
- import type { ReviewQueueItem } from "@/src/lib/review-queue";
6
- import type { ScanConfidenceSummary, ScanHealth } from "@/src/lib/scan-health";
7
- import type { SessionComparisonRow } from "@/src/lib/session-comparison";
4
+ import type { ScanConfidenceSummary, ScanHealth } from "@/src/lib/scan-health-types";
8
5
  import type { UsageGuardrailProgress } from "@/src/lib/usage-guardrails";
9
6
 
10
7
  export type TrendPoint = {
@@ -172,6 +169,60 @@ export type ModelAliasSuggestion = {
172
169
  parserHref: string;
173
170
  };
174
171
 
172
+ export type ReviewQueueCategory =
173
+ | "guardrail"
174
+ | "cost-repair"
175
+ | "session"
176
+ | "project"
177
+ | "model"
178
+ | "cache"
179
+ | "baseline";
180
+
181
+ export type ReviewQueueItem = {
182
+ id: string;
183
+ severity: "high" | "medium" | "low";
184
+ category: ReviewQueueCategory;
185
+ title: string;
186
+ evidence: string;
187
+ action: string;
188
+ href: string;
189
+ impactLabel: string;
190
+ impactValue: string;
191
+ };
192
+
193
+ export type SessionComparisonRow = {
194
+ sessionId: string;
195
+ title: string;
196
+ project: string;
197
+ tool: string;
198
+ models: string;
199
+ totalTokens: number;
200
+ cost: number | null;
201
+ peerSessions: number;
202
+ peerMedianTokens: number;
203
+ peerMedianCost: number | null;
204
+ tokenMultiple: number;
205
+ costMultiple: number | null;
206
+ severity: "high" | "medium" | "low";
207
+ flag: "token outlier" | "cost outlier";
208
+ evidence: string;
209
+ action: string;
210
+ href: string;
211
+ };
212
+
213
+ export type ProjectSignalRow = {
214
+ id: string;
215
+ severity: "high" | "medium" | "low";
216
+ project: string;
217
+ path: string;
218
+ signal: "dominant usage" | "unknown cost" | "estimated tokens" | "model concentration";
219
+ evidence: string;
220
+ action: string;
221
+ href: string;
222
+ metricLabel: string;
223
+ metricValue: string;
224
+ };
225
+
175
226
  export type DebugScanFile = {
176
227
  id: string;
177
228
  scanRunId: string;
@@ -1,5 +1,5 @@
1
1
  import { sqlite } from "@/src/db/client";
2
- import type { AnalyticsFilters } from "@/src/lib/analytics";
2
+ import type { AnalyticsFilters } from "@/src/lib/analytics-types";
3
3
  import type { EvidenceMetric } from "@/src/lib/evidence/metrics";
4
4
 
5
5
  export type EvidenceSessionRow = {
@@ -1,4 +1,4 @@
1
- import type { AnalyticsFilters } from "@/src/lib/analytics";
1
+ import type { AnalyticsFilters } from "@/src/lib/analytics-types";
2
2
  import type { EvidenceMetric } from "@/src/lib/evidence/metrics";
3
3
  import {
4
4
  mapEvidenceTrail,
@@ -1,18 +1,7 @@
1
- import type { ProjectAnalyticsRow, SessionRow } from "@/src/lib/analytics";
1
+ import type { ProjectAnalyticsRow, ProjectSignalRow, SessionRow } from "@/src/lib/analytics-types";
2
2
  import { formatTokens } from "@/src/lib/format";
3
3
 
4
- export type ProjectSignalRow = {
5
- id: string;
6
- severity: "high" | "medium" | "low";
7
- project: string;
8
- path: string;
9
- signal: "dominant usage" | "unknown cost" | "estimated tokens" | "model concentration";
10
- evidence: string;
11
- action: string;
12
- href: string;
13
- metricLabel: string;
14
- metricValue: string;
15
- };
4
+ export type { ProjectSignalRow } from "@/src/lib/analytics-types";
16
5
 
17
6
  type ProjectSignalInput = {
18
7
  totalTokens: number;
@@ -2,33 +2,16 @@ import { formatCurrency, formatTokens } from "@/src/lib/format";
2
2
  import type {
3
3
  ModelAnalyticsRow,
4
4
  ProjectAnalyticsRow,
5
+ ReviewQueueCategory,
6
+ ReviewQueueItem,
5
7
  SessionRow,
6
8
  SummaryMetrics,
7
9
  ToolComparisonRow,
8
10
  UnknownCostQueueRow
9
- } from "@/src/lib/analytics";
11
+ } from "@/src/lib/analytics-types";
10
12
  import type { UsageGuardrailProgress, UsageGuardrailMetric } from "@/src/lib/usage-guardrails";
11
13
 
12
- export type ReviewQueueCategory =
13
- | "guardrail"
14
- | "cost-repair"
15
- | "session"
16
- | "project"
17
- | "model"
18
- | "cache"
19
- | "baseline";
20
-
21
- export type ReviewQueueItem = {
22
- id: string;
23
- severity: "high" | "medium" | "low";
24
- category: ReviewQueueCategory;
25
- title: string;
26
- evidence: string;
27
- action: string;
28
- href: string;
29
- impactLabel: string;
30
- impactValue: string;
31
- };
14
+ export type { ReviewQueueCategory, ReviewQueueItem } from "@/src/lib/analytics-types";
32
15
 
33
16
  type ReviewQueueInput = {
34
17
  summary: Pick<SummaryMetrics, "totalTokens" | "totalCost" | "inputTokens" | "cachedTokens" | "unknownCostInteractions">;
@@ -6,7 +6,7 @@ import type {
6
6
  ScanHealthNoteGroup,
7
7
  ScanHealthRun,
8
8
  SupplyChainHealth
9
- } from "@/src/lib/scan-health";
9
+ } from "@/src/lib/scan-health-types";
10
10
 
11
11
  export function incrementCount(target: Record<string, number>, key: string, amount = 1) {
12
12
  target[key] = (target[key] ?? 0) + amount;
@@ -0,0 +1,104 @@
1
+ export type ScanHealthRun = {
2
+ id: string;
3
+ startedAt: number;
4
+ completedAt: number | null;
5
+ filesScanned: number;
6
+ recordsImported: number;
7
+ warnings: string[];
8
+ errors: string[];
9
+ };
10
+
11
+ export type ScanHealthFile = {
12
+ id: string;
13
+ scanRunId: string;
14
+ path: string;
15
+ modifiedTime: number | null;
16
+ sizeBytes: number;
17
+ parser: string | null;
18
+ status: string;
19
+ recordsImported: number;
20
+ warnings: string[];
21
+ errors: string[];
22
+ rawMetadata: Record<string, unknown>;
23
+ };
24
+
25
+ export type ScanConfidenceSummary = {
26
+ interactions: number;
27
+ exactTokenInteractions: number;
28
+ tokenizerEstimateInteractions?: number;
29
+ simpleEstimateInteractions?: number;
30
+ highConfidenceTokenInteractions: number;
31
+ lowConfidenceTokenInteractions: number;
32
+ unknownTokenInteractions: number;
33
+ estimatedTokenInteractions: number;
34
+ exactCostInteractions: number;
35
+ estimatedCostInteractions: number;
36
+ unknownCostInteractions: number;
37
+ unknownCostCauses: {
38
+ missingModelName: number;
39
+ missingPricing: number;
40
+ missingTokenCount: number;
41
+ other: number;
42
+ };
43
+ };
44
+
45
+ export type ScanHealthAction = {
46
+ label: string;
47
+ href: string;
48
+ reason: string;
49
+ tone: "default" | "warning" | "destructive";
50
+ };
51
+
52
+ export type SupplyChainHealth = {
53
+ status: "passed" | "failed" | "not-run";
54
+ checkedAt: number | null;
55
+ findings: number;
56
+ summary: string;
57
+ };
58
+
59
+ export type ScanHealthNoteGroup = {
60
+ severity: "warning" | "error";
61
+ message: string;
62
+ count: number;
63
+ examples: string[];
64
+ };
65
+
66
+ export type ScanHealth = {
67
+ latestRun: ScanHealthRun | null;
68
+ lastSuccessfulRun: ScanHealthRun | null;
69
+ latestFiles: ScanHealthFile[];
70
+ headline: string;
71
+ description: string;
72
+ tone: "success" | "warning" | "destructive" | "secondary";
73
+ latestStatusCounts: Record<string, number>;
74
+ parserCounts: Record<string, number>;
75
+ latestWarnings: string[];
76
+ latestErrors: string[];
77
+ latestNoteGroups: ScanHealthNoteGroup[];
78
+ freshness: {
79
+ state: "no-scan" | "no-successful-scan" | "fresh" | "stale";
80
+ lastSuccessfulCompletedAt: number | null;
81
+ staleAfterMs: number;
82
+ description: string;
83
+ };
84
+ tokenCoverage: {
85
+ exact: number;
86
+ tokenizerEstimate: number;
87
+ simpleEstimate: number;
88
+ highConfidenceEstimate: number;
89
+ lowConfidenceEstimate: number;
90
+ unknown: number;
91
+ estimated: number;
92
+ total: number;
93
+ };
94
+ costCoverage: {
95
+ priced: number;
96
+ exact: number;
97
+ estimated: number;
98
+ unknown: number;
99
+ unknownCauses: ScanConfidenceSummary["unknownCostCauses"];
100
+ total: number;
101
+ };
102
+ supplyChain: SupplyChainHealth;
103
+ actions: ScanHealthAction[];
104
+ };
@@ -8,111 +8,23 @@ import {
8
8
  uniqueMessages,
9
9
  type ScanHealthRuleStats
10
10
  } from "@/src/lib/scan-health-rules";
11
+ import type {
12
+ ScanConfidenceSummary,
13
+ ScanHealth,
14
+ ScanHealthFile,
15
+ ScanHealthRun,
16
+ SupplyChainHealth
17
+ } from "@/src/lib/scan-health-types";
11
18
 
12
- export type ScanHealthRun = {
13
- id: string;
14
- startedAt: number;
15
- completedAt: number | null;
16
- filesScanned: number;
17
- recordsImported: number;
18
- warnings: string[];
19
- errors: string[];
20
- };
21
-
22
- export type ScanHealthFile = {
23
- id: string;
24
- scanRunId: string;
25
- path: string;
26
- modifiedTime: number | null;
27
- sizeBytes: number;
28
- parser: string | null;
29
- status: string;
30
- recordsImported: number;
31
- warnings: string[];
32
- errors: string[];
33
- rawMetadata: Record<string, unknown>;
34
- };
35
-
36
- export type ScanConfidenceSummary = {
37
- interactions: number;
38
- exactTokenInteractions: number;
39
- tokenizerEstimateInteractions?: number;
40
- simpleEstimateInteractions?: number;
41
- highConfidenceTokenInteractions: number;
42
- lowConfidenceTokenInteractions: number;
43
- unknownTokenInteractions: number;
44
- estimatedTokenInteractions: number;
45
- exactCostInteractions: number;
46
- estimatedCostInteractions: number;
47
- unknownCostInteractions: number;
48
- unknownCostCauses: {
49
- missingModelName: number;
50
- missingPricing: number;
51
- missingTokenCount: number;
52
- other: number;
53
- };
54
- };
55
-
56
- export type ScanHealthAction = {
57
- label: string;
58
- href: string;
59
- reason: string;
60
- tone: "default" | "warning" | "destructive";
61
- };
62
-
63
- export type SupplyChainHealth = {
64
- status: "passed" | "failed" | "not-run";
65
- checkedAt: number | null;
66
- findings: number;
67
- summary: string;
68
- };
69
-
70
- export type ScanHealthNoteGroup = {
71
- severity: "warning" | "error";
72
- message: string;
73
- count: number;
74
- examples: string[];
75
- };
76
-
77
- export type ScanHealth = {
78
- latestRun: ScanHealthRun | null;
79
- lastSuccessfulRun: ScanHealthRun | null;
80
- latestFiles: ScanHealthFile[];
81
- headline: string;
82
- description: string;
83
- tone: "success" | "warning" | "destructive" | "secondary";
84
- latestStatusCounts: Record<string, number>;
85
- parserCounts: Record<string, number>;
86
- latestWarnings: string[];
87
- latestErrors: string[];
88
- latestNoteGroups: ScanHealthNoteGroup[];
89
- freshness: {
90
- state: "no-scan" | "no-successful-scan" | "fresh" | "stale";
91
- lastSuccessfulCompletedAt: number | null;
92
- staleAfterMs: number;
93
- description: string;
94
- };
95
- tokenCoverage: {
96
- exact: number;
97
- tokenizerEstimate: number;
98
- simpleEstimate: number;
99
- highConfidenceEstimate: number;
100
- lowConfidenceEstimate: number;
101
- unknown: number;
102
- estimated: number;
103
- total: number;
104
- };
105
- costCoverage: {
106
- priced: number;
107
- exact: number;
108
- estimated: number;
109
- unknown: number;
110
- unknownCauses: ScanConfidenceSummary["unknownCostCauses"];
111
- total: number;
112
- };
113
- supplyChain: SupplyChainHealth;
114
- actions: ScanHealthAction[];
115
- };
19
+ export type {
20
+ ScanConfidenceSummary,
21
+ ScanHealth,
22
+ ScanHealthAction,
23
+ ScanHealthFile,
24
+ ScanHealthNoteGroup,
25
+ ScanHealthRun,
26
+ SupplyChainHealth
27
+ } from "@/src/lib/scan-health-types";
116
28
 
117
29
  export function buildScanHealth({
118
30
  scanRuns,
@@ -1,25 +1,7 @@
1
- import type { SessionRow } from "@/src/lib/analytics";
1
+ import type { SessionComparisonRow, SessionRow } from "@/src/lib/analytics-types";
2
2
  import { formatCurrency, formatTokens } from "@/src/lib/format";
3
3
 
4
- export type SessionComparisonRow = {
5
- sessionId: string;
6
- title: string;
7
- project: string;
8
- tool: string;
9
- models: string;
10
- totalTokens: number;
11
- cost: number | null;
12
- peerSessions: number;
13
- peerMedianTokens: number;
14
- peerMedianCost: number | null;
15
- tokenMultiple: number;
16
- costMultiple: number | null;
17
- severity: "high" | "medium" | "low";
18
- flag: "token outlier" | "cost outlier";
19
- evidence: string;
20
- action: string;
21
- href: string;
22
- };
4
+ export type { SessionComparisonRow } from "@/src/lib/analytics-types";
23
5
 
24
6
  function median(values: number[]) {
25
7
  if (!values.length) return 0;
@@ -1,46 +1,21 @@
1
1
  import { prepareCached } from "@/src/db/prepared";
2
2
  import { modelNameCandidates } from "@/src/lib/model-aliases";
3
- import type { UnknownCostRepairWorkbenchGroup } from "@/src/lib/unknown-cost-repair/types";
4
-
5
- export type AutoClassificationRule = "exact-model" | "family-fragment" | "parser-source" | "none";
6
-
7
- export type AutoClassification = {
8
- suggestedModel: string | null;
9
- suggestedProvider: string | null;
10
- confidence: number;
11
- rule: AutoClassificationRule;
12
- evidence: {
13
- matchedRows: number;
14
- sampleSourceFile: string | null;
15
- };
16
- };
17
-
18
- export type ClassifyInput = {
19
- cause: UnknownCostRepairWorkbenchGroup["cause"];
20
- providerId: string;
21
- model: string;
22
- sourceFile: string;
23
- };
24
-
25
- export type PricedModelRow = {
26
- providerId: string;
27
- providerName: string;
28
- modelName: string;
29
- usageCount: number;
30
- };
31
-
32
- export type SourcePricedRow = {
33
- sourceFile: string;
34
- providerId: string;
35
- providerName: string;
36
- modelName: string;
37
- usageCount: number;
38
- };
39
-
40
- export type ClassificationLookups = {
41
- pricedByProvider: Map<string, PricedModelRow[]>;
42
- pricedBySource: Map<string, SourcePricedRow>;
43
- };
3
+ import type {
4
+ AutoClassification,
5
+ ClassificationLookups,
6
+ ClassifyInput,
7
+ PricedModelRow,
8
+ SourcePricedRow
9
+ } from "@/src/lib/unknown-cost-repair/classification-types";
10
+
11
+ export type {
12
+ AutoClassification,
13
+ AutoClassificationRule,
14
+ ClassificationLookups,
15
+ ClassifyInput,
16
+ PricedModelRow,
17
+ SourcePricedRow
18
+ } from "@/src/lib/unknown-cost-repair/classification-types";
44
19
 
45
20
  export function buildClassificationLookups(): ClassificationLookups {
46
21
  const pricedRows = prepareCached(
@@ -0,0 +1,41 @@
1
+ import type { UnknownCostRepairCause } from "@/src/lib/repair-actions";
2
+
3
+ export type AutoClassificationRule = "exact-model" | "family-fragment" | "parser-source" | "none";
4
+
5
+ export type AutoClassification = {
6
+ suggestedModel: string | null;
7
+ suggestedProvider: string | null;
8
+ confidence: number;
9
+ rule: AutoClassificationRule;
10
+ evidence: {
11
+ matchedRows: number;
12
+ sampleSourceFile: string | null;
13
+ };
14
+ };
15
+
16
+ export type ClassifyInput = {
17
+ cause: UnknownCostRepairCause;
18
+ providerId: string;
19
+ model: string;
20
+ sourceFile: string;
21
+ };
22
+
23
+ export type PricedModelRow = {
24
+ providerId: string;
25
+ providerName: string;
26
+ modelName: string;
27
+ usageCount: number;
28
+ };
29
+
30
+ export type SourcePricedRow = {
31
+ sourceFile: string;
32
+ providerId: string;
33
+ providerName: string;
34
+ modelName: string;
35
+ usageCount: number;
36
+ };
37
+
38
+ export type ClassificationLookups = {
39
+ pricedByProvider: Map<string, PricedModelRow[]>;
40
+ pricedBySource: Map<string, SourcePricedRow>;
41
+ };
@@ -1,4 +1,4 @@
1
- import type { AutoClassification } from "@/src/lib/unknown-cost-repair/auto-classify";
1
+ import type { AutoClassification } from "@/src/lib/unknown-cost-repair/classification-types";
2
2
  import type { UnknownCostRepairAction, UnknownCostRepairCause } from "@/src/lib/repair-actions";
3
3
 
4
4
  export type UnknownCostRepairStatus = "unresolved" | "ignored" | "resolved" | "needs-parser-review";