zeitzeuge 0.5.1 → 0.6.0

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.
@@ -1,17 +1,30 @@
1
1
  import { type BackendProtocol } from 'deepagents';
2
2
  import type { BaseChatModel } from '@langchain/core/language_models/chat_models';
3
3
  import type { Ora } from 'ora';
4
- import type { Finding } from '../types.js';
4
+ import type { Finding, HeapSummary, TraceResult } from '../types.js';
5
+ import type { PerformanceMetrics } from '../vitest/metrics.js';
6
+ /** Context for building a dynamic page-load user message. */
7
+ export interface PageLoadContext {
8
+ url: string;
9
+ heapSummary: HeapSummary;
10
+ traceResult: TraceResult;
11
+ }
5
12
  /**
6
13
  * Analyze performance data using a Deep Agent that explores
7
14
  * the workspace containing heap + trace data + source files.
8
15
  */
9
- export declare function analyze(model: BaseChatModel, backend: BackendProtocol, spinner: Ora): Promise<Finding[]>;
16
+ export declare function analyze(model: BaseChatModel, backend: BackendProtocol, spinner: Ora, context?: PageLoadContext): Promise<Finding[]>;
17
+ /** Context for building a dynamic Vitest user message. */
18
+ export interface VitestAnalysisContext {
19
+ metrics: PerformanceMetrics;
20
+ hasHeapProfiles: boolean;
21
+ hasListenerTracking: boolean;
22
+ }
10
23
  /**
11
24
  * Analyze Vitest test performance data using a Deep Agent that explores
12
25
  * the workspace containing CPU profiles + test timing + source files.
13
26
  */
14
- export declare function analyzeTestPerformance(model: BaseChatModel, backend: BackendProtocol, spinner: Ora): Promise<Finding[]>;
27
+ export declare function analyzeTestPerformance(model: BaseChatModel, backend: BackendProtocol, spinner: Ora, context?: VitestAnalysisContext): Promise<Finding[]>;
15
28
  /**
16
29
  * Format bytes into a human-readable string.
17
30
  * Kept for backwards compatibility with existing imports.
@@ -1 +1 @@
1
- {"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../src/analysis/agent.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,eAAe,EAGrB,MAAM,YAAY,CAAC;AAEpB,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,6CAA6C,CAAC;AACjF,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC;AAM/B,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAwC3C;;;GAGG;AACH,wBAAsB,OAAO,CAC3B,KAAK,EAAE,aAAa,EACpB,OAAO,EAAE,eAAe,EACxB,OAAO,EAAE,GAAG,GACX,OAAO,CAAC,OAAO,EAAE,CAAC,CAoCpB;AAED;;;GAGG;AACH,wBAAsB,sBAAsB,CAC1C,KAAK,EAAE,aAAa,EACpB,OAAO,EAAE,eAAe,EACxB,OAAO,EAAE,GAAG,GACX,OAAO,CAAC,OAAO,EAAE,CAAC,CAwCpB;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAIjD"}
1
+ {"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../src/analysis/agent.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,eAAe,EAGrB,MAAM,YAAY,CAAC;AAEpB,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,6CAA6C,CAAC;AACjF,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC;AAM/B,OAAO,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACrE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAwC/D,6DAA6D;AAC7D,MAAM,WAAW,eAAe;IAC9B,GAAG,EAAE,MAAM,CAAC;IACZ,WAAW,EAAE,WAAW,CAAC;IACzB,WAAW,EAAE,WAAW,CAAC;CAC1B;AA6DD;;;GAGG;AACH,wBAAsB,OAAO,CAC3B,KAAK,EAAE,aAAa,EACpB,OAAO,EAAE,eAAe,EACxB,OAAO,EAAE,GAAG,EACZ,OAAO,CAAC,EAAE,eAAe,GACxB,OAAO,CAAC,OAAO,EAAE,CAAC,CAwBpB;AAED,0DAA0D;AAC1D,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,kBAAkB,CAAC;IAC5B,eAAe,EAAE,OAAO,CAAC;IACzB,mBAAmB,EAAE,OAAO,CAAC;CAC9B;AAkDD;;;GAGG;AACH,wBAAsB,sBAAsB,CAC1C,KAAK,EAAE,aAAa,EACpB,OAAO,EAAE,eAAe,EACxB,OAAO,EAAE,GAAG,EACZ,OAAO,CAAC,EAAE,qBAAqB,GAC9B,OAAO,CAAC,OAAO,EAAE,CAAC,CAwBpB;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAIjD"}
@@ -1,2 +1,2 @@
1
- export declare const SYSTEM_PROMPT = "You are an expert web performance engineer. You have access to a virtual filesystem workspace containing captured data from a real page load: heap snapshot, network trace, and Chrome runtime trace.\n\n## Workspace structure\n\n- /heap/summary.json \u2014 Parsed V8 heap snapshot: largest objects, type stats, constructor stats, detached DOM nodes, closure stats\n- /trace/summary.json \u2014 Page load metrics: timing, long tasks, render-blocking resources, resource breakdown\n- /trace/network-waterfall.json \u2014 Every network request with timing, size, priority, render-blocking status\n- /trace/asset-manifest.json \u2014 Index of all assets with paths to stored files\n- /trace/runtime/summary.json \u2014 Runtime trace overview: frame breakdown (scripting/layout/paint/GC), blocking function count, listener imbalances, GC stats\n- /trace/runtime/blocking-functions.json \u2014 Functions that blocked the main thread > 50ms, with script URL, line number, call stack, and duration\n- /trace/runtime/event-listeners.json \u2014 Event listener add/remove counts per event type, with source locations\n- /trace/runtime/frame-breakdown.json \u2014 Time spent in scripting vs layout vs paint vs GC\n- /trace/runtime/raw-events.json \u2014 Full Chrome trace events (large file \u2014 read to investigate specific function calls, layouts, GC, and event dispatches)\n- /scripts/*.js \u2014 Actual JavaScript source files captured during page load\n- /styles/*.css \u2014 Actual CSS source files\n- /html/document.html \u2014 The HTML document\n\n## Your workflow\n\n1. Read /heap/summary.json, /trace/summary.json, AND /trace/runtime/summary.json first for the big picture\n2. Identify the highest-impact issues from all datasets\n3. For each issue, dive into the relevant source files to understand the root cause\n4. Provide specific, code-level fixes\n\n## What to look for\n\n### Memory issues (from heap data)\n- Memory leaks: unbounded arrays, maps, caches that grow without bound\n- Detached DOM nodes: DOM elements removed from the document but still referenced\n- Large retained objects: single objects or trees retaining disproportionate memory\n- Closure leaks: closures capturing variables they no longer need\n\n### Page-load issues (from trace + source code)\n- Render-blocking scripts: <script> in <head> without async/defer \u2014 read the script to judge if it must be synchronous\n- Render-blocking CSS: large stylesheets blocking first paint\n- Long tasks (> 50ms): identify the function/module causing the block by reading the source\n- Large bundles: scripts > 100KB \u2014 search for unused imports or code that could be lazy-loaded\n- Sequential waterfalls: resources chained sequentially that could load in parallel\n\n### Runtime issues (from Chrome trace)\n- Frame-blocking functions: read /trace/runtime/blocking-functions.json first, then inspect the actual script source at the reported line number to understand what the function does and how to optimize it\n- Event listener leaks: check /trace/runtime/event-listeners.json for event types where addCount >> removeCount, then grep the scripts for those addEventListener calls\n- GC pressure: high GC pause counts or duration suggest excessive short-lived object creation \u2014 look for hot loops creating objects\n- Layout thrashing: forced synchronous layouts caused by reading layout properties (offsetHeight, getBoundingClientRect) after DOM writes\n\n## Output guidelines\n\n- Report 3\u20137 findings, ordered by impact (mix of memory, page-load, and runtime if all have issues)\n- Be specific \u2014 name actual files, functions, object constructors, and retention paths\n- Provide concrete code fixes, not generic advice\n- If heap, trace, and runtime all look healthy, say so \u2014 don't manufacture issues";
1
+ export declare const SYSTEM_PROMPT = "You are an expert web performance engineer. You have access to a virtual filesystem workspace containing captured data from a real page load: heap snapshot, network trace, and Chrome runtime trace.\n\n## Workspace structure\n\n- /heap/summary.json \u2014 Parsed V8 heap snapshot: largest objects, type stats, constructor stats, detached DOM nodes, closure stats\n- /trace/summary.json \u2014 Page load metrics: timing, long tasks, render-blocking resources, resource breakdown\n- /trace/network-waterfall.json \u2014 Every network request with timing, size, priority, render-blocking status\n- /trace/asset-manifest.json \u2014 Index of all assets with paths to stored files\n- /trace/runtime/summary.json \u2014 Runtime trace overview: frame breakdown (scripting/layout/paint/GC), blocking function count, listener imbalances, GC stats\n- /trace/runtime/blocking-functions.json \u2014 Functions that blocked the main thread > 50ms, with script URL, line number, call stack, and duration\n- /trace/runtime/event-listeners.json \u2014 Event listener add/remove counts per event type, with source locations\n- /trace/runtime/frame-breakdown.json \u2014 Time spent in scripting vs layout vs paint vs GC\n- /trace/runtime/raw-events.json \u2014 Full Chrome trace events (large file \u2014 read to investigate specific function calls, layouts, GC, and event dispatches)\n- /scripts/*.js \u2014 Actual JavaScript source files captured during page load\n- /styles/*.css \u2014 Actual CSS source files\n- /html/document.html \u2014 The HTML document\n\n## Your workflow\n\n1. Read /heap/summary.json, /trace/summary.json, AND /trace/runtime/summary.json first for the big picture\n2. Identify the highest-impact issues from all datasets\n3. For each issue, dive into the relevant source files to understand the root cause\n4. Provide specific, code-level fixes\n\n## What to look for\n\n### Memory issues (from heap data)\n- Memory leaks: unbounded arrays, maps, caches that grow without bound\n- Detached DOM nodes: DOM elements removed from the document but still referenced\n- Large retained objects: single objects or trees retaining disproportionate memory\n- Closure leaks: closures capturing variables they no longer need\n\n### Page-load issues (from trace + source code)\n- Render-blocking scripts: <script> in <head> without async/defer \u2014 read the script to judge if it must be synchronous\n- Render-blocking CSS: large stylesheets blocking first paint\n- Long tasks (> 50ms): identify the function/module causing the block by reading the source\n- Large bundles: scripts > 100KB \u2014 search for unused imports or code that could be lazy-loaded\n- Sequential waterfalls: resources chained sequentially that could load in parallel\n\n### Runtime issues (from Chrome trace)\n- Frame-blocking functions: read /trace/runtime/blocking-functions.json first, then inspect the actual script source at the reported line number to understand what the function does and how to optimize it\n- Event listener leaks: check /trace/runtime/event-listeners.json for event types where addCount >> removeCount, then grep the scripts for those addEventListener calls\n- GC pressure: high GC pause counts or duration suggest excessive short-lived object creation \u2014 look for hot loops creating objects\n- Layout thrashing: forced synchronous layouts caused by reading layout properties (offsetHeight, getBoundingClientRect) after DOM writes\n\n## Severity classification\n\nAssign severity based on measured impact \u2014 do NOT guess:\n\n- **critical** \u2014 A blocking function >500ms, retained heap object >5MB,\n render-blocking resource >200KB, listener addCount > 10\u00D7 removeCount,\n or GC pauses totalling >500ms\n- **warning** \u2014 A blocking function 100\u2013500ms, retained heap object 1\u20135MB,\n render-blocking resource 50\u2013200KB, listener addCount > 2\u00D7 removeCount,\n or GC pauses totalling 100\u2013500ms\n- **info** \u2014 Blocking function 50\u2013100ms, retained object <1MB, minor\n optimisation opportunities, or observations about dependency usage\n\nAlways base severity on the actual numbers from the captured data \u2014 never inflate.\n\n## Verification rules\n\nThese rules are mandatory for every finding:\n\n1. **ALWAYS read the source file** in /scripts/, /styles/, or /html/ and\n verify the code BEFORE suggesting a fix. Never suggest a fix for code\n you have not read.\n2. **Never guess at line numbers** \u2014 confirm by reading the file. If the\n trace reports a line number but the source doesn't match, say so.\n3. Each `suggestedFix` MUST reference the actual current code and describe\n what to change. Include a before/after snippet from the real source.\n4. If the heap summary, trace summary, and runtime summary all show healthy\n numbers, state that the page is well-optimised \u2014 do NOT manufacture\n findings.\n5. Never report a finding based solely on a URL or resource name \u2014 always\n read the actual content to confirm the issue.\n\n## Cross-referencing data\n\n- When a script appears in BOTH /trace/runtime/blocking-functions.json (CPU)\n AND /heap/summary.json (memory), mention both dimensions in the finding.\n- Check /trace/runtime/event-listeners.json for listener imbalances and\n cross-reference with the actual addEventListener calls in /scripts/.\n- Use /trace/network-waterfall.json to identify sequential chains, then read\n the initiating script to confirm the dependency.\n- When GC pauses are significant, cross-reference with heap data to identify\n which constructors or allocation patterns are responsible.\n\n## Estimating impactMs\n\nEvery finding should include an `impactMs` estimate when possible:\n\n- For render-blocking resources: impactMs \u2248 the resource's load duration\n (from the network waterfall) that could be deferred.\n- For blocking functions: impactMs \u2248 the function's duration minus 50ms\n (the long-task threshold).\n- For memory issues: impactMs may not apply \u2014 use `retainedSize` instead.\n- If you cannot reasonably estimate the savings, omit impactMs rather than\n guessing.\n\n## Output guidelines\n\n- Report 3\u20137 findings, ordered by impact (mix of memory, page-load, and runtime if all have issues)\n- Be specific \u2014 name actual files, functions, object constructors, and retention paths\n- Provide concrete code fixes, not generic advice\n- If heap, trace, and runtime all look healthy, say so \u2014 don't manufacture issues\n\n## Structured output fields\n\nFor each finding, fill in as many fields as applicable:\n\n- `sourceFile` \u2014 the workspace path (e.g. /scripts/app.js) or resource URL\n where the issue occurs. Always set this when you can identify the file.\n- `lineNumber` \u2014 the 1-based line number in the source file. Only set after\n verifying by reading the file.\n- `confidence` \u2014 `high` if you read the source and confirmed the issue,\n `medium` if the profiling data strongly suggests it but you couldn't fully\n verify, `low` if inferred from patterns.\n- `estimatedSavingsMs` \u2014 your estimate of time saved if the fix is applied.\n- `beforeCode` \u2014 a snippet of the CURRENT problematic code, copied from the\n source file you read. Keep it focused (5\u201315 lines).\n- `afterCode` \u2014 the IMPROVED code snippet showing the fix. Must be a drop-in\n replacement for `beforeCode`.\n- `impactMs` \u2014 the current measured cost (e.g. blocking function duration,\n resource load time).";
2
2
  //# sourceMappingURL=prompts.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"prompts.d.ts","sourceRoot":"","sources":["../../src/analysis/prompts.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,aAAa,ytHAkDwD,CAAC"}
1
+ {"version":3,"file":"prompts.d.ts","sourceRoot":"","sources":["../../src/analysis/prompts.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,aAAa,i1OA4HH,CAAC"}
package/dist/cli.js CHANGED
@@ -59,12 +59,86 @@ var SYSTEM_PROMPT = `You are an expert web performance engineer. You have access
59
59
  - GC pressure: high GC pause counts or duration suggest excessive short-lived object creation — look for hot loops creating objects
60
60
  - Layout thrashing: forced synchronous layouts caused by reading layout properties (offsetHeight, getBoundingClientRect) after DOM writes
61
61
 
62
+ ## Severity classification
63
+
64
+ Assign severity based on measured impact — do NOT guess:
65
+
66
+ - **critical** — A blocking function >500ms, retained heap object >5MB,
67
+ render-blocking resource >200KB, listener addCount > 10× removeCount,
68
+ or GC pauses totalling >500ms
69
+ - **warning** — A blocking function 100–500ms, retained heap object 1–5MB,
70
+ render-blocking resource 50–200KB, listener addCount > 2× removeCount,
71
+ or GC pauses totalling 100–500ms
72
+ - **info** — Blocking function 50–100ms, retained object <1MB, minor
73
+ optimisation opportunities, or observations about dependency usage
74
+
75
+ Always base severity on the actual numbers from the captured data — never inflate.
76
+
77
+ ## Verification rules
78
+
79
+ These rules are mandatory for every finding:
80
+
81
+ 1. **ALWAYS read the source file** in /scripts/, /styles/, or /html/ and
82
+ verify the code BEFORE suggesting a fix. Never suggest a fix for code
83
+ you have not read.
84
+ 2. **Never guess at line numbers** — confirm by reading the file. If the
85
+ trace reports a line number but the source doesn't match, say so.
86
+ 3. Each \`suggestedFix\` MUST reference the actual current code and describe
87
+ what to change. Include a before/after snippet from the real source.
88
+ 4. If the heap summary, trace summary, and runtime summary all show healthy
89
+ numbers, state that the page is well-optimised — do NOT manufacture
90
+ findings.
91
+ 5. Never report a finding based solely on a URL or resource name — always
92
+ read the actual content to confirm the issue.
93
+
94
+ ## Cross-referencing data
95
+
96
+ - When a script appears in BOTH /trace/runtime/blocking-functions.json (CPU)
97
+ AND /heap/summary.json (memory), mention both dimensions in the finding.
98
+ - Check /trace/runtime/event-listeners.json for listener imbalances and
99
+ cross-reference with the actual addEventListener calls in /scripts/.
100
+ - Use /trace/network-waterfall.json to identify sequential chains, then read
101
+ the initiating script to confirm the dependency.
102
+ - When GC pauses are significant, cross-reference with heap data to identify
103
+ which constructors or allocation patterns are responsible.
104
+
105
+ ## Estimating impactMs
106
+
107
+ Every finding should include an \`impactMs\` estimate when possible:
108
+
109
+ - For render-blocking resources: impactMs ≈ the resource's load duration
110
+ (from the network waterfall) that could be deferred.
111
+ - For blocking functions: impactMs ≈ the function's duration minus 50ms
112
+ (the long-task threshold).
113
+ - For memory issues: impactMs may not apply — use \`retainedSize\` instead.
114
+ - If you cannot reasonably estimate the savings, omit impactMs rather than
115
+ guessing.
116
+
62
117
  ## Output guidelines
63
118
 
64
119
  - Report 3–7 findings, ordered by impact (mix of memory, page-load, and runtime if all have issues)
65
120
  - Be specific — name actual files, functions, object constructors, and retention paths
66
121
  - Provide concrete code fixes, not generic advice
67
- - If heap, trace, and runtime all look healthy, say so — don't manufacture issues`;
122
+ - If heap, trace, and runtime all look healthy, say so — don't manufacture issues
123
+
124
+ ## Structured output fields
125
+
126
+ For each finding, fill in as many fields as applicable:
127
+
128
+ - \`sourceFile\` — the workspace path (e.g. /scripts/app.js) or resource URL
129
+ where the issue occurs. Always set this when you can identify the file.
130
+ - \`lineNumber\` — the 1-based line number in the source file. Only set after
131
+ verifying by reading the file.
132
+ - \`confidence\` — \`high\` if you read the source and confirmed the issue,
133
+ \`medium\` if the profiling data strongly suggests it but you couldn't fully
134
+ verify, \`low\` if inferred from patterns.
135
+ - \`estimatedSavingsMs\` — your estimate of time saved if the fix is applied.
136
+ - \`beforeCode\` — a snippet of the CURRENT problematic code, copied from the
137
+ source file you read. Keep it focused (5–15 lines).
138
+ - \`afterCode\` — the IMPROVED code snippet showing the fix. Must be a drop-in
139
+ replacement for \`beforeCode\`.
140
+ - \`impactMs\` — the current measured cost (e.g. blocking function duration,
141
+ resource load time).`;
68
142
 
69
143
  // src/vitest/prompts.ts
70
144
  var VITEST_SYSTEM_PROMPT = `You are an expert in JavaScript/TypeScript performance optimization.
@@ -105,7 +179,9 @@ Every hot function and script in the workspace has a \`sourceCategory\` field:
105
179
  - /heap-profiles/index.json — (optional) Manifest mapping test files to heap profiles
106
180
  - /heap-profiles/<file>.json — (optional) Heap profile summary: allocation hotspots,
107
181
  per-script allocated bytes (with sourceCategory)
108
- - /hot-functions/application.json — **START HERE**: Hot functions from application code only
182
+ - /hot-functions/application.json — **START HERE**: Hot functions from application code only.
183
+ Each entry includes a \`sourceSnippet\` (lines around the hot line) and \`workspacePath\`
184
+ (path to the full source file in the workspace) when source code is available.
109
185
  - /hot-functions/dependencies.json — Hot functions from third-party dependencies
110
186
  - /hot-functions/global.json — All hot functions across all categories
111
187
  - /scripts/application.json — Per-script time breakdown for application code
@@ -113,8 +189,11 @@ Every hot function and script in the workspace has a \`sourceCategory\` field:
113
189
  - /listener-tracking.json — (optional) Event listener tracking data captured from
114
190
  worker processes. Contains per-event-type add/remove counts for EventTarget and
115
191
  EventEmitter, plus exceedances where listener counts exceeded maxListeners.
116
- - /tests/*.tsTest source files
117
- - /src/*.ts Application and dependency source files referenced by hot functions
192
+ - /src/index.jsonMapping of source files to their hot functions (quick overview
193
+ of which files matter and what bottlenecks they contain)
194
+ - /tests/<relative-path> — Test source files (directory structure preserved)
195
+ - /src/<relative-path> — Application and dependency source files referenced by
196
+ hot functions (directory structure preserved from the project root)
118
197
 
119
198
  ## Your workflow
120
199
 
@@ -159,6 +238,9 @@ Every hot function and script in the workspace has a \`sourceCategory\` field:
159
238
  - When allocation hotspots match CPU hotspots, prioritize fixes there first
160
239
 
161
240
  ### Call chain analysis
241
+ - Each hot function includes a \`callerChain\` field — the chain of callers
242
+ from the hot function up toward the entry point. Use this to understand
243
+ WHY a function is hot and which application-level call triggers it.
162
244
  - Trace expensive call trees to find which APPLICATION function triggers them
163
245
  - Follow the call tree from application entry points down to the hot leaf functions
164
246
  - Identify which application-level design decisions lead to the bottleneck
@@ -208,6 +290,63 @@ Each finding MUST use one of these exact category values:
208
290
  Prefer more specific categories (algorithm, serialization, allocation, event-handling)
209
291
  over generic ones (hot-function, other) when the root cause is clear.
210
292
 
293
+ ## Severity classification
294
+
295
+ Assign severity based on measured impact — do NOT guess:
296
+
297
+ - **critical** — A single function consuming >15% self-time, listener exceedances
298
+ (count exceeding maxListeners), or GC overhead >10% of total profile duration
299
+ - **warning** — A function consuming 5–15% self-time, listener add/remove imbalance
300
+ where addCount > 2× removeCount, or GC overhead between 5–10%
301
+ - **info** — A function consuming <5% self-time, minor inefficiencies,
302
+ dependency observations, or small optimisation opportunities
303
+
304
+ Always base severity on the actual numbers from the profiling data — never inflate.
305
+
306
+ ## Verification rules
307
+
308
+ These rules are mandatory for every finding:
309
+
310
+ 1. **ALWAYS read the source file** in /src/ or /tests/ and verify the code
311
+ BEFORE suggesting a fix. Never suggest a fix for code you have not read.
312
+ 2. **Never guess at line numbers** — confirm by reading the file. If the profile
313
+ reports line 42 but the source at line 42 doesn't match, say so.
314
+ 3. Each \`suggestedFix\` MUST reference the actual current code and describe
315
+ what to change. Include a before/after snippet from the real source.
316
+ 4. If /hot-functions/application.json is empty or every function is <1%
317
+ self-time, state that the application code is efficient — do NOT
318
+ manufacture findings.
319
+ 5. Never report a finding based solely on a function name — always read the
320
+ implementation to confirm the issue exists.
321
+
322
+ ## Cross-referencing data
323
+
324
+ - When a function appears in BOTH /hot-functions/ (CPU hotspot) AND
325
+ /heap-profiles/ (allocation hotspot), prioritise it and mention both
326
+ dimensions in the finding.
327
+ - Cross-reference /hot-functions/ data with /heap-profiles/ when both are
328
+ present to find functions that are expensive in both CPU and memory.
329
+ - Check whether hot dependency calls originate from application code by
330
+ tracing the call tree in /profiles/.
331
+ - When /listener-tracking.json is present, cross-reference exceedance stack
332
+ traces with the source code in /src/ to pinpoint the registration site.
333
+ - /metrics/current.json contains pre-computed aggregate metrics (suite totals,
334
+ CPU category breakdown, top hot functions). Use it for the big-picture
335
+ numbers when sizing impact.
336
+
337
+ ## Estimating impactMs
338
+
339
+ Every finding should include an \`impactMs\` estimate when possible:
340
+
341
+ - Use the hot function's \`selfTime\` as the baseline cost.
342
+ - Estimate what fraction of that cost the fix would eliminate
343
+ (e.g. an O(n²) → O(n) fix on data of size 1000 might eliminate ~99%).
344
+ - impactMs = selfTime × estimated fraction eliminated.
345
+ - Example: a function with selfTime 200ms in a 1000ms run, where an
346
+ algorithm fix would remove ~80% of the work → impactMs ≈ 160.
347
+ - If you cannot reasonably estimate the savings, omit impactMs rather than
348
+ guessing.
349
+
211
350
  ## Output guidelines
212
351
 
213
352
  - Report 3–7 findings, ordered by impact ON THE APPLICATION CODE
@@ -218,7 +357,28 @@ over generic ones (hot-function, other) when the root cause is clear.
218
357
  - When reporting a dependency bottleneck, explain what application code is
219
358
  calling it and how the developer can reduce that cost
220
359
  - If the application code is already efficient, say so — don't force findings
221
- about test infrastructure just to fill the report`;
360
+ about test infrastructure just to fill the report
361
+
362
+ ## Structured output fields
363
+
364
+ For each finding, fill in as many fields as applicable:
365
+
366
+ - \`sourceFile\` — the workspace path (e.g. /src/utils/parser.ts) or original
367
+ file path where the issue occurs. Always set this when you can identify
368
+ the file.
369
+ - \`lineNumber\` — the 1-based line number in the source file. Only set after
370
+ verifying by reading the file.
371
+ - \`confidence\` — \`high\` if you read the source and confirmed the issue,
372
+ \`medium\` if the profiling data strongly suggests it but you couldn't fully
373
+ verify, \`low\` if inferred from patterns.
374
+ - \`estimatedSavingsMs\` — your estimate of time saved if the fix is applied.
375
+ - \`beforeCode\` — a snippet of the CURRENT problematic code, copied from the
376
+ source file you read. Keep it focused (5–15 lines).
377
+ - \`afterCode\` — the IMPROVED code snippet showing the fix. Must be a drop-in
378
+ replacement for \`beforeCode\`.
379
+ - \`affectedTests\` — list of test names that exercise this code path and would
380
+ benefit from the fix.
381
+ - \`impactMs\` — the current measured cost (e.g. selfTime of the hot function).`;
222
382
 
223
383
  // src/schema.ts
224
384
  import { z } from "zod";
@@ -256,11 +416,18 @@ var init_schema = __esm(() => {
256
416
  category: z.string().describe(`Category of the performance issue. Use one of: ${ALL_CATEGORIES.join(", ")}`),
257
417
  resourceUrl: z.string().optional().describe("URL of the resource involved"),
258
418
  workspacePath: z.string().optional().describe("Path in the VFS workspace"),
259
- impactMs: z.number().optional().describe("Impact on page load time in ms"),
419
+ impactMs: z.number().optional().describe("Estimated current cost in ms (e.g. selfTime of the hot function)"),
420
+ estimatedSavingsMs: z.number().optional().describe("Estimated time savings in ms if the fix is applied. Computed as impactMs × fraction eliminated by the fix."),
421
+ confidence: z.enum(["high", "medium", "low"]).optional().describe("How confident you are in this finding. high = verified in source code, medium = strong signal but partial verification, low = inferred from data patterns"),
260
422
  retainedSize: z.number().optional().describe("Retained heap size in bytes"),
261
423
  retainerPath: z.array(z.string()).optional().describe("Object retention path in the heap"),
424
+ sourceFile: z.string().optional().describe("Primary source file where the issue occurs (workspace path or original path)"),
425
+ lineNumber: z.number().optional().describe("Line number in the source file where the issue occurs (1-based)"),
262
426
  suggestedFix: z.string().describe("Code snippet or guidance to fix the issue"),
427
+ beforeCode: z.string().optional().describe("The current problematic code snippet from the source file"),
428
+ afterCode: z.string().optional().describe("The improved code snippet that fixes the issue"),
263
429
  testFile: z.string().optional().describe("Test file path (for test performance findings)"),
430
+ affectedTests: z.array(z.string()).optional().describe("Test names that would benefit from this fix (for test performance findings)"),
264
431
  hotFunction: z.object({
265
432
  name: z.string(),
266
433
  scriptUrl: z.string(),
@@ -362,32 +529,46 @@ async function invokeWithTodoStreaming(agent, userMessage, spinner) {
362
529
  }
363
530
  return lastValues;
364
531
  }
365
- async function analyze(model, backend, spinner) {
532
+ function buildPageLoadUserMessage(ctx) {
533
+ const { url, heapSummary, traceResult } = ctx;
534
+ const m = traceResult.metrics;
535
+ const reqCount = traceResult.networkRequests.length;
536
+ const renderBlocking = traceResult.networkRequests.filter((r) => r.isRenderBlocking).length;
537
+ const totalTransfer = traceResult.networkRequests.reduce((s, r) => s + r.encodedSize, 0);
538
+ const hasRuntime = !!traceResult.runtimeTrace;
539
+ const lines = [
540
+ "Analyze the frontend performance data in this workspace.",
541
+ "",
542
+ `URL: ${url}`,
543
+ `Page load: ${Math.round(m.loadComplete)}ms | FCP: ${Math.round(m.firstContentfulPaint)}ms | LCP: ${Math.round(m.largestContentfulPaint)}ms | TBT: ${Math.round(m.totalBlockingTime)}ms`,
544
+ `Heap: ${formatBytes(heapSummary.metadata.totalSize)} total, ${heapSummary.metadata.nodeCount.toLocaleString()} nodes, ${heapSummary.detachedNodes.count} detached DOM nodes`,
545
+ `Network: ${reqCount} requests, ${formatBytes(totalTransfer)} transferred, ${renderBlocking} render-blocking`,
546
+ `Long tasks: ${m.longTasks.length}`
547
+ ];
548
+ if (hasRuntime) {
549
+ const rt = traceResult.runtimeTrace;
550
+ lines.push(`Runtime trace: ${rt.blockingFunctions.length} blocking functions, ${rt.gcEvents.length} GC events (${Math.round(rt.gcEvents.reduce((s, e) => s + e.duration, 0))}ms total)`);
551
+ }
552
+ lines.push("", "Available data:", "- /heap/summary.json — parsed heap snapshot", "- /trace/summary.json — page load metrics", "- /trace/network-waterfall.json — request timing and sizes", "- /trace/asset-manifest.json — index of stored assets");
553
+ if (hasRuntime) {
554
+ lines.push("- /trace/runtime/summary.json — runtime trace overview", "- /trace/runtime/blocking-functions.json — main thread blocking functions", "- /trace/runtime/event-listeners.json — listener add/remove counts", "- /trace/runtime/frame-breakdown.json — scripting vs layout vs paint vs GC", "- /trace/runtime/raw-events.json — full Chrome trace events");
555
+ }
556
+ lines.push("- /scripts/ — JavaScript source files", "- /styles/ — CSS source files", "- /html/document.html — page markup", "", "Explore the workspace, read source files to verify root causes, and provide code-level fixes.");
557
+ return lines.join(`
558
+ `);
559
+ }
560
+ async function analyze(model, backend, spinner, context) {
366
561
  const agent = createDeepAgent({
367
562
  model,
368
563
  systemPrompt: SYSTEM_PROMPT,
369
564
  backend,
370
565
  responseFormat: providerStrategy(FindingsSchema)
371
566
  });
372
- const userMessage = [
567
+ const userMessage = context ? buildPageLoadUserMessage(context) : [
373
568
  "Analyze the frontend performance data in this workspace.",
374
569
  "",
375
- "The workspace contains heap snapshot data, page-load trace data, and Chrome runtime trace data.",
376
- "",
377
570
  "Start by reading /heap/summary.json, /trace/summary.json, and /trace/runtime/summary.json",
378
- "to understand the overall picture. Then explore:",
379
- "",
380
- "- /trace/network-waterfall.json for request timing",
381
- "- /trace/runtime/blocking-functions.json for function-level main thread blocking",
382
- "- /trace/runtime/event-listeners.json for listener add/remove imbalances",
383
- "- /trace/runtime/frame-breakdown.json for frame breakdown (scripting vs layout vs paint vs GC)",
384
- "- /scripts/ for the actual JavaScript source code",
385
- "- /styles/ for CSS source",
386
- "- /html/document.html for the page markup",
387
- "",
388
- "Look for memory issues (from the heap data), page-load issues (from the network trace),",
389
- "and runtime issues (from the Chrome trace — blocking functions, listener leaks, GC pressure).",
390
- "When you find a problem, read the actual source file to provide a specific, code-level fix."
571
+ "to understand the overall picture, then explore source files to verify root causes."
391
572
  ].join(`
392
573
  `);
393
574
  const result = await invokeWithTodoStreaming(agent, userMessage, spinner);
@@ -397,36 +578,44 @@ async function analyze(model, backend, spinner) {
397
578
  }
398
579
  return findings;
399
580
  }
400
- async function analyzeTestPerformance(model, backend, spinner) {
581
+ function buildVitestUserMessage(ctx) {
582
+ const { metrics, hasHeapProfiles, hasListenerTracking } = ctx;
583
+ const lines = [
584
+ "Analyze the performance of the APPLICATION CODE being tested in this Vitest workspace.",
585
+ "",
586
+ `Test suite: ${metrics.suite.totalTests} tests, total duration ${metrics.suite.totalDuration}ms`,
587
+ `CPU breakdown: application ${metrics.cpu.applicationPercent}%, dependencies ${metrics.cpu.dependencyPercent}%, GC ${metrics.cpu.gcPercentage}%, idle ${metrics.cpu.idlePercentage}%`,
588
+ `Slowest file: ${metrics.suite.slowestFile} (${metrics.suite.slowestFileDuration}ms)`,
589
+ `Slowest test: ${metrics.suite.slowestTestName} (${metrics.suite.slowestTestDuration}ms)`,
590
+ "",
591
+ "Available data:",
592
+ "- /hot-functions/application.json — application-level CPU hotspots",
593
+ "- /scripts/application.json — per-file CPU time for application code",
594
+ "- /hot-functions/dependencies.json — dependency CPU hotspots",
595
+ "- /scripts/dependencies.json — per-file CPU time for dependencies"
596
+ ];
597
+ if (hasListenerTracking) {
598
+ lines.push("- /listener-tracking.json — event listener add/remove patterns and exceedances");
599
+ }
600
+ if (hasHeapProfiles) {
601
+ lines.push("- /heap-profiles/index.json — heap profile manifest", "- /heap-profiles/<file>.json — per-file allocation hotspots");
602
+ }
603
+ lines.push("- /summary.json — overall test run summary", "- /timing/overview.json — per-file test durations", "- /timing/slow-tests.json — tests exceeding the slow threshold", "- /profiles/ — full CPU profile summaries with call trees", "- /metrics/current.json — pre-computed aggregate metrics", "- /src/ and /tests/ — source files", "", "Focus findings on the APPLICATION code — what can the developer change in their own", "codebase to improve performance? Read source files to verify root causes before suggesting fixes.");
604
+ return lines.join(`
605
+ `);
606
+ }
607
+ async function analyzeTestPerformance(model, backend, spinner, context) {
401
608
  const agent = createDeepAgent({
402
609
  model,
403
610
  systemPrompt: VITEST_SYSTEM_PROMPT,
404
611
  backend,
405
612
  responseFormat: providerStrategy(FindingsSchema)
406
613
  });
407
- const userMessage = [
614
+ const userMessage = context ? buildVitestUserMessage(context) : [
408
615
  "Analyze the performance of the APPLICATION CODE being tested in this Vitest workspace.",
409
616
  "",
410
- "Follow this order:",
411
- "1. Read /hot-functions/application.json these are the hotspots IN the user's own code",
412
- "2. Read /scripts/application.json — per-file CPU time for application source files",
413
- "3. Read /hot-functions/dependencies.json — expensive dependency calls",
414
- "4. If present, read /heap-profiles/index.json and /heap-profiles/<file>.json for allocation hotspots",
415
- "5. If present, read /listener-tracking.json — event listener add/remove patterns",
416
- " from worker processes. Look for exceedances (too many listeners on a single target)",
417
- " and add/remove imbalances (listeners registered but never cleaned up).",
418
- "6. Read /summary.json and /timing/overview.json for the big picture",
419
- "7. Read CPU profiles in /profiles/ for detailed call trees",
420
- "8. Read source files in /src/ and /tests/ to understand root causes and propose code-level fixes",
421
- "",
422
- "Focus findings on the APPLICATION code — what can the developer change in their own codebase",
423
- "to improve performance? Dependency bottlenecks are worth reporting if the developer can",
424
- "reduce how they call the dependency or choose an alternative.",
425
- "",
426
- "If /listener-tracking.json is present, analyze exceedances and imbalances.",
427
- "For listener exceedances (e.g. AbortSignal with 15 abort listeners when max is 10),",
428
- "use the stack trace to identify the code adding listeners and suggest proper cleanup",
429
- "(e.g. AbortController, removeEventListener, { once: true })."
617
+ "Start with /hot-functions/application.json, then explore source files to verify",
618
+ "root causes and provide code-level fixes."
430
619
  ].join(`
431
620
  `);
432
621
  const result = await invokeWithTodoStreaming(agent, userMessage, spinner);
@@ -1898,16 +2087,40 @@ function generateMarkdown(options) {
1898
2087
  sections.push(`## ${emoji} ${f.title}`);
1899
2088
  sections.push("");
1900
2089
  const context = [`**${categoryLabel}**`];
2090
+ if (f.confidence)
2091
+ context.push(`confidence: ${f.confidence}`);
1901
2092
  if (f.impactMs != null)
1902
2093
  context.push(`${f.impactMs.toFixed(0)}ms impact`);
2094
+ if (f.estimatedSavingsMs != null)
2095
+ context.push(`~${f.estimatedSavingsMs.toFixed(0)}ms savings`);
1903
2096
  if (f.retainedSize != null)
1904
2097
  context.push(`${formatBytes2(f.retainedSize)} retained`);
2098
+ if (f.sourceFile)
2099
+ context.push(`\`${f.sourceFile}${f.lineNumber != null ? `:${f.lineNumber}` : ""}\``);
1905
2100
  if (f.resourceUrl)
1906
2101
  context.push(`\`${f.resourceUrl}\``);
1907
2102
  sections.push(context.join(" · "));
1908
2103
  sections.push("");
1909
2104
  sections.push(f.description);
1910
2105
  sections.push("");
2106
+ if (f.beforeCode || f.afterCode) {
2107
+ if (f.beforeCode) {
2108
+ sections.push(`### Before`);
2109
+ sections.push("");
2110
+ sections.push("```js");
2111
+ sections.push(f.beforeCode);
2112
+ sections.push("```");
2113
+ sections.push("");
2114
+ }
2115
+ if (f.afterCode) {
2116
+ sections.push(`### After`);
2117
+ sections.push("");
2118
+ sections.push("```js");
2119
+ sections.push(f.afterCode);
2120
+ sections.push("```");
2121
+ sections.push("");
2122
+ }
2123
+ }
1911
2124
  if (f.suggestedFix) {
1912
2125
  sections.push(`### How to fix`);
1913
2126
  sections.push("");
@@ -2043,19 +2256,47 @@ function generateTestMarkdown(options) {
2043
2256
  sections.push(`## ${emoji} ${f.title}`);
2044
2257
  sections.push("");
2045
2258
  const context = [`**${categoryLabel}**`];
2259
+ if (f.confidence)
2260
+ context.push(`confidence: ${f.confidence}`);
2046
2261
  if (f.impactMs != null)
2047
2262
  context.push(`${f.impactMs.toFixed(0)}ms impact`);
2263
+ if (f.estimatedSavingsMs != null)
2264
+ context.push(`~${f.estimatedSavingsMs.toFixed(0)}ms savings`);
2048
2265
  if (f.testFile)
2049
2266
  context.push(`\`${f.testFile}\``);
2050
2267
  if (f.hotFunction) {
2051
2268
  context.push(`\`${f.hotFunction.name}\` (${f.hotFunction.selfTime.toFixed(0)}ms, ${f.hotFunction.selfPercent.toFixed(1)}%)`);
2052
2269
  }
2270
+ if (f.sourceFile)
2271
+ context.push(`\`${f.sourceFile}${f.lineNumber != null ? `:${f.lineNumber}` : ""}\``);
2053
2272
  if (f.resourceUrl)
2054
2273
  context.push(`\`${f.resourceUrl}\``);
2055
2274
  sections.push(context.join(" · "));
2056
2275
  sections.push("");
2276
+ if (f.affectedTests && f.affectedTests.length > 0) {
2277
+ sections.push(`**Affected tests:** ${f.affectedTests.map((t) => `\`${t}\``).join(", ")}`);
2278
+ sections.push("");
2279
+ }
2057
2280
  sections.push(f.description);
2058
2281
  sections.push("");
2282
+ if (f.beforeCode || f.afterCode) {
2283
+ if (f.beforeCode) {
2284
+ sections.push(`### Before`);
2285
+ sections.push("");
2286
+ sections.push("```ts");
2287
+ sections.push(f.beforeCode);
2288
+ sections.push("```");
2289
+ sections.push("");
2290
+ }
2291
+ if (f.afterCode) {
2292
+ sections.push(`### After`);
2293
+ sections.push("");
2294
+ sections.push("```ts");
2295
+ sections.push(f.afterCode);
2296
+ sections.push("```");
2297
+ sections.push("");
2298
+ }
2299
+ }
2059
2300
  if (f.suggestedFix) {
2060
2301
  sections.push(`### How to fix`);
2061
2302
  sections.push("");
@@ -2207,7 +2448,11 @@ async function main() {
2207
2448
  const agentSpinner = createSpinner("Analyzing...");
2208
2449
  let findings;
2209
2450
  try {
2210
- findings = await analyze(model, workspace.backend, agentSpinner);
2451
+ findings = await analyze(model, workspace.backend, agentSpinner, {
2452
+ url,
2453
+ heapSummary,
2454
+ traceResult: captureResult.trace
2455
+ });
2211
2456
  agentSpinner.succeed(`Analysis complete — ${findings.length} findings`);
2212
2457
  } catch (err) {
2213
2458
  agentSpinner.fail(`Analysis failed: ${err instanceof Error ? err.message : "Unknown error"}`);
@@ -1 +1 @@
1
- {"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../../src/output/report.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACrE,OAAO,KAAK,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAC5E,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAoC/D,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,WAAW,EAAE,WAAW,CAAC;IACzB,KAAK,EAAE,WAAW,CAAC;CACpB;AAED,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,UAAU,EAAE,cAAc,EAAE,CAAC;IAC7B,QAAQ,EAAE,iBAAiB,EAAE,CAAC;IAC9B,OAAO,CAAC,EAAE,kBAAkB,CAAC;CAC9B;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,GAAG,MAAM,CAI9E;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,aAAa,GAAG,MAAM,CAiH/D;AAID;;;GAGG;AACH,wBAAgB,eAAe,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,iBAAiB,GAAG,MAAM,CAItF;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,iBAAiB,GAAG,MAAM,CAuNvE"}
1
+ {"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../../src/output/report.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACrE,OAAO,KAAK,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAC5E,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAoC/D,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,WAAW,EAAE,WAAW,CAAC;IACzB,KAAK,EAAE,WAAW,CAAC;CACpB;AAED,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,UAAU,EAAE,cAAc,EAAE,CAAC;IAC7B,QAAQ,EAAE,iBAAiB,EAAE,CAAC;IAC9B,OAAO,CAAC,EAAE,kBAAkB,CAAC;CAC9B;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,GAAG,MAAM,CAI9E;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,aAAa,GAAG,MAAM,CAwI/D;AAID;;;GAGG;AACH,wBAAgB,eAAe,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,iBAAiB,GAAG,MAAM,CAItF;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,iBAAiB,GAAG,MAAM,CAoPvE"}
package/dist/schema.d.ts CHANGED
@@ -23,10 +23,21 @@ export declare const FindingSchema: z.ZodObject<{
23
23
  resourceUrl: z.ZodOptional<z.ZodString>;
24
24
  workspacePath: z.ZodOptional<z.ZodString>;
25
25
  impactMs: z.ZodOptional<z.ZodNumber>;
26
+ estimatedSavingsMs: z.ZodOptional<z.ZodNumber>;
27
+ confidence: z.ZodOptional<z.ZodEnum<{
28
+ low: "low";
29
+ medium: "medium";
30
+ high: "high";
31
+ }>>;
26
32
  retainedSize: z.ZodOptional<z.ZodNumber>;
27
33
  retainerPath: z.ZodOptional<z.ZodArray<z.ZodString>>;
34
+ sourceFile: z.ZodOptional<z.ZodString>;
35
+ lineNumber: z.ZodOptional<z.ZodNumber>;
28
36
  suggestedFix: z.ZodString;
37
+ beforeCode: z.ZodOptional<z.ZodString>;
38
+ afterCode: z.ZodOptional<z.ZodString>;
29
39
  testFile: z.ZodOptional<z.ZodString>;
40
+ affectedTests: z.ZodOptional<z.ZodArray<z.ZodString>>;
30
41
  hotFunction: z.ZodOptional<z.ZodObject<{
31
42
  name: z.ZodString;
32
43
  scriptUrl: z.ZodString;
@@ -48,10 +59,21 @@ export declare const FindingsSchema: z.ZodObject<{
48
59
  resourceUrl: z.ZodOptional<z.ZodString>;
49
60
  workspacePath: z.ZodOptional<z.ZodString>;
50
61
  impactMs: z.ZodOptional<z.ZodNumber>;
62
+ estimatedSavingsMs: z.ZodOptional<z.ZodNumber>;
63
+ confidence: z.ZodOptional<z.ZodEnum<{
64
+ low: "low";
65
+ medium: "medium";
66
+ high: "high";
67
+ }>>;
51
68
  retainedSize: z.ZodOptional<z.ZodNumber>;
52
69
  retainerPath: z.ZodOptional<z.ZodArray<z.ZodString>>;
70
+ sourceFile: z.ZodOptional<z.ZodString>;
71
+ lineNumber: z.ZodOptional<z.ZodNumber>;
53
72
  suggestedFix: z.ZodString;
73
+ beforeCode: z.ZodOptional<z.ZodString>;
74
+ afterCode: z.ZodOptional<z.ZodString>;
54
75
  testFile: z.ZodOptional<z.ZodString>;
76
+ affectedTests: z.ZodOptional<z.ZodArray<z.ZodString>>;
55
77
  hotFunction: z.ZodOptional<z.ZodObject<{
56
78
  name: z.ZodString;
57
79
  scriptUrl: z.ZodString;
@@ -1 +1 @@
1
- {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;;;;;;;;;GAUG;AACH,eAAO,MAAM,cAAc,iaA2BjB,CAAC;AAEX,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;iBAwBxB,CAAC;AAEH,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;iBAEzB,CAAC"}
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;;;;;;;;;GAUG;AACH,eAAO,MAAM,cAAc,iaA2BjB,CAAC;AAEX,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAwDxB,CAAC;AAEH,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAEzB,CAAC"}