perfgraph 0.1.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.
Files changed (263) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +280 -0
  3. package/dist/causal/builder.d.ts +34 -0
  4. package/dist/causal/builder.d.ts.map +1 -0
  5. package/dist/causal/builder.js +132 -0
  6. package/dist/causal/builder.js.map +1 -0
  7. package/dist/causal/index.d.ts +11 -0
  8. package/dist/causal/index.d.ts.map +1 -0
  9. package/dist/causal/index.js +10 -0
  10. package/dist/causal/index.js.map +1 -0
  11. package/dist/causal/rules/js.d.ts +49 -0
  12. package/dist/causal/rules/js.d.ts.map +1 -0
  13. package/dist/causal/rules/js.js +209 -0
  14. package/dist/causal/rules/js.js.map +1 -0
  15. package/dist/causal/rules/layout.d.ts +39 -0
  16. package/dist/causal/rules/layout.d.ts.map +1 -0
  17. package/dist/causal/rules/layout.js +169 -0
  18. package/dist/causal/rules/layout.js.map +1 -0
  19. package/dist/causal/rules/lcp.d.ts +49 -0
  20. package/dist/causal/rules/lcp.d.ts.map +1 -0
  21. package/dist/causal/rules/lcp.js +250 -0
  22. package/dist/causal/rules/lcp.js.map +1 -0
  23. package/dist/causal/rules/network.d.ts +39 -0
  24. package/dist/causal/rules/network.d.ts.map +1 -0
  25. package/dist/causal/rules/network.js +140 -0
  26. package/dist/causal/rules/network.js.map +1 -0
  27. package/dist/causal/types.d.ts +142 -0
  28. package/dist/causal/types.d.ts.map +1 -0
  29. package/dist/causal/types.js +88 -0
  30. package/dist/causal/types.js.map +1 -0
  31. package/dist/cli/analyze.d.ts +33 -0
  32. package/dist/cli/analyze.d.ts.map +1 -0
  33. package/dist/cli/analyze.js +137 -0
  34. package/dist/cli/analyze.js.map +1 -0
  35. package/dist/cli/collect.d.ts +28 -0
  36. package/dist/cli/collect.d.ts.map +1 -0
  37. package/dist/cli/collect.js +125 -0
  38. package/dist/cli/collect.js.map +1 -0
  39. package/dist/cli/extract.d.ts +31 -0
  40. package/dist/cli/extract.d.ts.map +1 -0
  41. package/dist/cli/extract.js +135 -0
  42. package/dist/cli/extract.js.map +1 -0
  43. package/dist/cli/mcp.d.ts +14 -0
  44. package/dist/cli/mcp.d.ts.map +1 -0
  45. package/dist/cli/mcp.js +53 -0
  46. package/dist/cli/mcp.js.map +1 -0
  47. package/dist/cli/normalize.d.ts +58 -0
  48. package/dist/cli/normalize.d.ts.map +1 -0
  49. package/dist/cli/normalize.js +179 -0
  50. package/dist/cli/normalize.js.map +1 -0
  51. package/dist/cli/report.d.ts +33 -0
  52. package/dist/cli/report.d.ts.map +1 -0
  53. package/dist/cli/report.js +137 -0
  54. package/dist/cli/report.js.map +1 -0
  55. package/dist/cli/run.d.ts +49 -0
  56. package/dist/cli/run.d.ts.map +1 -0
  57. package/dist/cli/run.js +243 -0
  58. package/dist/cli/run.js.map +1 -0
  59. package/dist/collect/buffer-monitor.d.ts +25 -0
  60. package/dist/collect/buffer-monitor.d.ts.map +1 -0
  61. package/dist/collect/buffer-monitor.js +69 -0
  62. package/dist/collect/buffer-monitor.js.map +1 -0
  63. package/dist/collect/console.d.ts +25 -0
  64. package/dist/collect/console.d.ts.map +1 -0
  65. package/dist/collect/console.js +82 -0
  66. package/dist/collect/console.js.map +1 -0
  67. package/dist/collect/coverage.d.ts +26 -0
  68. package/dist/collect/coverage.d.ts.map +1 -0
  69. package/dist/collect/coverage.js +99 -0
  70. package/dist/collect/coverage.js.map +1 -0
  71. package/dist/collect/dom.d.ts +37 -0
  72. package/dist/collect/dom.d.ts.map +1 -0
  73. package/dist/collect/dom.js +118 -0
  74. package/dist/collect/dom.js.map +1 -0
  75. package/dist/collect/lighthouse.d.ts +41 -0
  76. package/dist/collect/lighthouse.d.ts.map +1 -0
  77. package/dist/collect/lighthouse.js +111 -0
  78. package/dist/collect/lighthouse.js.map +1 -0
  79. package/dist/collect/network.d.ts +32 -0
  80. package/dist/collect/network.d.ts.map +1 -0
  81. package/dist/collect/network.js +236 -0
  82. package/dist/collect/network.js.map +1 -0
  83. package/dist/collect/orchestrator.d.ts +23 -0
  84. package/dist/collect/orchestrator.d.ts.map +1 -0
  85. package/dist/collect/orchestrator.js +350 -0
  86. package/dist/collect/orchestrator.js.map +1 -0
  87. package/dist/collect/performance.d.ts +28 -0
  88. package/dist/collect/performance.d.ts.map +1 -0
  89. package/dist/collect/performance.js +108 -0
  90. package/dist/collect/performance.js.map +1 -0
  91. package/dist/collect/runtime.d.ts +26 -0
  92. package/dist/collect/runtime.d.ts.map +1 -0
  93. package/dist/collect/runtime.js +81 -0
  94. package/dist/collect/runtime.js.map +1 -0
  95. package/dist/collect/session.d.ts +58 -0
  96. package/dist/collect/session.d.ts.map +1 -0
  97. package/dist/collect/session.js +162 -0
  98. package/dist/collect/session.js.map +1 -0
  99. package/dist/collect/trace.d.ts +40 -0
  100. package/dist/collect/trace.d.ts.map +1 -0
  101. package/dist/collect/trace.js +127 -0
  102. package/dist/collect/trace.js.map +1 -0
  103. package/dist/collect/types.d.ts +317 -0
  104. package/dist/collect/types.d.ts.map +1 -0
  105. package/dist/collect/types.js +12 -0
  106. package/dist/collect/types.js.map +1 -0
  107. package/dist/distill/insights.d.ts +67 -0
  108. package/dist/distill/insights.d.ts.map +1 -0
  109. package/dist/distill/insights.js +317 -0
  110. package/dist/distill/insights.js.map +1 -0
  111. package/dist/distill/summaries.d.ts +71 -0
  112. package/dist/distill/summaries.d.ts.map +1 -0
  113. package/dist/distill/summaries.js +165 -0
  114. package/dist/distill/summaries.js.map +1 -0
  115. package/dist/extract/critical-path.d.ts +17 -0
  116. package/dist/extract/critical-path.d.ts.map +1 -0
  117. package/dist/extract/critical-path.js +95 -0
  118. package/dist/extract/critical-path.js.map +1 -0
  119. package/dist/extract/index.d.ts +16 -0
  120. package/dist/extract/index.d.ts.map +1 -0
  121. package/dist/extract/index.js +32 -0
  122. package/dist/extract/index.js.map +1 -0
  123. package/dist/extract/js-hotspots.d.ts +15 -0
  124. package/dist/extract/js-hotspots.d.ts.map +1 -0
  125. package/dist/extract/js-hotspots.js +22 -0
  126. package/dist/extract/js-hotspots.js.map +1 -0
  127. package/dist/extract/layout-shifts.d.ts +19 -0
  128. package/dist/extract/layout-shifts.d.ts.map +1 -0
  129. package/dist/extract/layout-shifts.js +47 -0
  130. package/dist/extract/layout-shifts.js.map +1 -0
  131. package/dist/extract/lcp-breakdown.d.ts +19 -0
  132. package/dist/extract/lcp-breakdown.d.ts.map +1 -0
  133. package/dist/extract/lcp-breakdown.js +110 -0
  134. package/dist/extract/lcp-breakdown.js.map +1 -0
  135. package/dist/extract/main-thread.d.ts +16 -0
  136. package/dist/extract/main-thread.d.ts.map +1 -0
  137. package/dist/extract/main-thread.js +41 -0
  138. package/dist/extract/main-thread.js.map +1 -0
  139. package/dist/extract/render-blocking.d.ts +16 -0
  140. package/dist/extract/render-blocking.d.ts.map +1 -0
  141. package/dist/extract/render-blocking.js +79 -0
  142. package/dist/extract/render-blocking.js.map +1 -0
  143. package/dist/extract/third-party.d.ts +15 -0
  144. package/dist/extract/third-party.d.ts.map +1 -0
  145. package/dist/extract/third-party.js +127 -0
  146. package/dist/extract/third-party.js.map +1 -0
  147. package/dist/extract/types.d.ts +183 -0
  148. package/dist/extract/types.d.ts.map +1 -0
  149. package/dist/extract/types.js +118 -0
  150. package/dist/extract/types.js.map +1 -0
  151. package/dist/index.d.ts +20 -0
  152. package/dist/index.d.ts.map +1 -0
  153. package/dist/index.js +188 -0
  154. package/dist/index.js.map +1 -0
  155. package/dist/mcp/handlers.d.ts +72 -0
  156. package/dist/mcp/handlers.d.ts.map +1 -0
  157. package/dist/mcp/handlers.js +285 -0
  158. package/dist/mcp/handlers.js.map +1 -0
  159. package/dist/mcp/progress.d.ts +37 -0
  160. package/dist/mcp/progress.d.ts.map +1 -0
  161. package/dist/mcp/progress.js +51 -0
  162. package/dist/mcp/progress.js.map +1 -0
  163. package/dist/mcp/prompts.d.ts +57 -0
  164. package/dist/mcp/prompts.d.ts.map +1 -0
  165. package/dist/mcp/prompts.js +225 -0
  166. package/dist/mcp/prompts.js.map +1 -0
  167. package/dist/mcp/resources.d.ts +48 -0
  168. package/dist/mcp/resources.d.ts.map +1 -0
  169. package/dist/mcp/resources.js +149 -0
  170. package/dist/mcp/resources.js.map +1 -0
  171. package/dist/mcp/server.d.ts +34 -0
  172. package/dist/mcp/server.d.ts.map +1 -0
  173. package/dist/mcp/server.js +452 -0
  174. package/dist/mcp/server.js.map +1 -0
  175. package/dist/mcp/types.d.ts +47 -0
  176. package/dist/mcp/types.d.ts.map +1 -0
  177. package/dist/mcp/types.js +67 -0
  178. package/dist/mcp/types.js.map +1 -0
  179. package/dist/normalize/clock.d.ts +40 -0
  180. package/dist/normalize/clock.d.ts.map +1 -0
  181. package/dist/normalize/clock.js +96 -0
  182. package/dist/normalize/clock.js.map +1 -0
  183. package/dist/normalize/dom-ir.d.ts +16 -0
  184. package/dist/normalize/dom-ir.d.ts.map +1 -0
  185. package/dist/normalize/dom-ir.js +48 -0
  186. package/dist/normalize/dom-ir.js.map +1 -0
  187. package/dist/normalize/index.d.ts +23 -0
  188. package/dist/normalize/index.d.ts.map +1 -0
  189. package/dist/normalize/index.js +118 -0
  190. package/dist/normalize/index.js.map +1 -0
  191. package/dist/normalize/lighthouse-insights.d.ts +27 -0
  192. package/dist/normalize/lighthouse-insights.d.ts.map +1 -0
  193. package/dist/normalize/lighthouse-insights.js +318 -0
  194. package/dist/normalize/lighthouse-insights.js.map +1 -0
  195. package/dist/normalize/lighthouse-ir.d.ts +25 -0
  196. package/dist/normalize/lighthouse-ir.d.ts.map +1 -0
  197. package/dist/normalize/lighthouse-ir.js +151 -0
  198. package/dist/normalize/lighthouse-ir.js.map +1 -0
  199. package/dist/normalize/network-ir.d.ts +23 -0
  200. package/dist/normalize/network-ir.d.ts.map +1 -0
  201. package/dist/normalize/network-ir.js +180 -0
  202. package/dist/normalize/network-ir.js.map +1 -0
  203. package/dist/normalize/runtime-ir.d.ts +18 -0
  204. package/dist/normalize/runtime-ir.d.ts.map +1 -0
  205. package/dist/normalize/runtime-ir.js +114 -0
  206. package/dist/normalize/runtime-ir.js.map +1 -0
  207. package/dist/normalize/trace-ir.d.ts +20 -0
  208. package/dist/normalize/trace-ir.d.ts.map +1 -0
  209. package/dist/normalize/trace-ir.js +224 -0
  210. package/dist/normalize/trace-ir.js.map +1 -0
  211. package/dist/normalize/types.d.ts +536 -0
  212. package/dist/normalize/types.d.ts.map +1 -0
  213. package/dist/normalize/types.js +242 -0
  214. package/dist/normalize/types.js.map +1 -0
  215. package/dist/output/manifest.d.ts +44 -0
  216. package/dist/output/manifest.d.ts.map +1 -0
  217. package/dist/output/manifest.js +232 -0
  218. package/dist/output/manifest.js.map +1 -0
  219. package/dist/output/toon.d.ts +19 -0
  220. package/dist/output/toon.d.ts.map +1 -0
  221. package/dist/output/toon.js +22 -0
  222. package/dist/output/toon.js.map +1 -0
  223. package/dist/output/writer.d.ts +31 -0
  224. package/dist/output/writer.d.ts.map +1 -0
  225. package/dist/output/writer.js +51 -0
  226. package/dist/output/writer.js.map +1 -0
  227. package/dist/report/analyzer.d.ts +29 -0
  228. package/dist/report/analyzer.d.ts.map +1 -0
  229. package/dist/report/analyzer.js +330 -0
  230. package/dist/report/analyzer.js.map +1 -0
  231. package/dist/report/index.d.ts +13 -0
  232. package/dist/report/index.d.ts.map +1 -0
  233. package/dist/report/index.js +12 -0
  234. package/dist/report/index.js.map +1 -0
  235. package/dist/report/markdown.d.ts +21 -0
  236. package/dist/report/markdown.d.ts.map +1 -0
  237. package/dist/report/markdown.js +182 -0
  238. package/dist/report/markdown.js.map +1 -0
  239. package/dist/report/remediations.d.ts +42 -0
  240. package/dist/report/remediations.d.ts.map +1 -0
  241. package/dist/report/remediations.js +179 -0
  242. package/dist/report/remediations.js.map +1 -0
  243. package/dist/report/scorer.d.ts +35 -0
  244. package/dist/report/scorer.d.ts.map +1 -0
  245. package/dist/report/scorer.js +72 -0
  246. package/dist/report/scorer.js.map +1 -0
  247. package/dist/report/types.d.ts +201 -0
  248. package/dist/report/types.d.ts.map +1 -0
  249. package/dist/report/types.js +149 -0
  250. package/dist/report/types.js.map +1 -0
  251. package/dist/shared/fs-utils.d.ts +12 -0
  252. package/dist/shared/fs-utils.d.ts.map +1 -0
  253. package/dist/shared/fs-utils.js +44 -0
  254. package/dist/shared/fs-utils.js.map +1 -0
  255. package/dist/shared/types.d.ts +69 -0
  256. package/dist/shared/types.d.ts.map +1 -0
  257. package/dist/shared/types.js +18 -0
  258. package/dist/shared/types.js.map +1 -0
  259. package/dist/shared/utils.d.ts +6 -0
  260. package/dist/shared/utils.d.ts.map +1 -0
  261. package/dist/shared/utils.js +9 -0
  262. package/dist/shared/utils.js.map +1 -0
  263. package/package.json +67 -0
@@ -0,0 +1,88 @@
1
+ /**
2
+ * Causal Graph types — Zod schemas and TypeScript types.
3
+ *
4
+ * These define the output of Phase 4: a typed DAG where nodes represent
5
+ * performance signals (metrics, bottlenecks, impacts) and edges represent
6
+ * causal relationships with confidence scores.
7
+ *
8
+ * @packageDocumentation
9
+ */
10
+ import { z } from 'zod';
11
+ // ---------------------------------------------------------------------------
12
+ // Shared enums
13
+ // ---------------------------------------------------------------------------
14
+ /** Confidence level for a causal edge */
15
+ export const ConfidenceSchema = z.enum(['strong', 'medium', 'weak']);
16
+ /** Node severity (user-facing classification) */
17
+ export const SeveritySchema = z.enum(['critical', 'warning', 'info']);
18
+ /** Node role in the causal chain */
19
+ export const NodeTypeSchema = z.enum(['metric', 'bottleneck', 'impact']);
20
+ // ---------------------------------------------------------------------------
21
+ // Evidence — optional payload attached to a causal node
22
+ // ---------------------------------------------------------------------------
23
+ /** Evidence payload attached to a causal node */
24
+ export const EvidenceSchema = z.object({
25
+ /** Affected URLs (e.g. render-blocking resource URLs) */
26
+ urls: z.array(z.string()).optional(),
27
+ /** DOM selector for the LCP element or shift source */
28
+ selector: z.string().optional(),
29
+ /** Lighthouse audit ID for cross-referencing */
30
+ lighthouseAuditId: z.string().optional(),
31
+ /** Key metric (name, value, unit) */
32
+ metric: z
33
+ .object({
34
+ name: z.string(),
35
+ value: z.number(),
36
+ unit: z.string(),
37
+ })
38
+ .optional(),
39
+ });
40
+ // ---------------------------------------------------------------------------
41
+ // CausalNode
42
+ // ---------------------------------------------------------------------------
43
+ export const CausalNodeSchema = z.object({
44
+ id: z.string().min(1),
45
+ label: z.string().min(1),
46
+ type: NodeTypeSchema,
47
+ severity: SeveritySchema.optional(),
48
+ /** Raw metric value (e.g. 3200 for TTFB in ms) */
49
+ value: z.number().optional(),
50
+ /** Unit label (e.g. "ms", "bytes", "score") */
51
+ unit: z.string().optional(),
52
+ /** Threshold that was exceeded */
53
+ threshold: z.number().optional(),
54
+ /** Evidence payload attached to this node */
55
+ evidence: EvidenceSchema.optional(),
56
+ });
57
+ // ---------------------------------------------------------------------------
58
+ // CausalEdge
59
+ // ---------------------------------------------------------------------------
60
+ export const CausalEdgeSchema = z.object({
61
+ source: z.string().min(1),
62
+ target: z.string().min(1),
63
+ confidence: ConfidenceSchema,
64
+ /** Human-readable label for this causal relationship */
65
+ label: z.string().min(1),
66
+ /** ID of the rule that generated this edge */
67
+ ruleId: z.string().min(1),
68
+ });
69
+ // ---------------------------------------------------------------------------
70
+ // CausalGraph — the full output of the builder
71
+ // ---------------------------------------------------------------------------
72
+ export const CausalGraphMetadataSchema = z.object({
73
+ /** How many features were present in the input */
74
+ featureCount: z.number().nonnegative(),
75
+ /** How many rules were evaluated (including non-applicable) */
76
+ ruleCount: z.number().nonnegative(),
77
+ totalNodes: z.number().nonnegative(),
78
+ totalEdges: z.number().nonnegative(),
79
+ hasCycle: z.boolean(),
80
+ /** Target URL that was analyzed */
81
+ targetUrl: z.string().optional(),
82
+ });
83
+ export const CausalGraphSchema = z.object({
84
+ nodes: z.array(CausalNodeSchema),
85
+ edges: z.array(CausalEdgeSchema),
86
+ metadata: CausalGraphMetadataSchema,
87
+ });
88
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/causal/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * `analyze` subcommand handler.
3
+ *
4
+ * Reads a FeatureSet JSON file (produced by `perfgraph extract`) and runs
5
+ * causal graph analysis, outputting a CausalGraph as JSON.
6
+ *
7
+ * Usage:
8
+ * perfgraph analyze <features-file>
9
+ * perfgraph analyze --input features.json --output graph.json --pretty
10
+ *
11
+ * @packageDocumentation
12
+ */
13
+ /** Result of the analyze command execution */
14
+ export interface AnalyzeResult {
15
+ /** Whether analysis succeeded */
16
+ success: boolean;
17
+ /** Path to the input FeatureSet file */
18
+ inputFile: string;
19
+ }
20
+ /**
21
+ * Run the analyze command from a FeatureSet file path.
22
+ *
23
+ * @param inputFile - Path to FeatureSet JSON file
24
+ * @param outputFile - Optional output file path (defaults to stdout)
25
+ * @param pretty - Pretty-print JSON (default: false)
26
+ * @returns AnalyzeResult
27
+ */
28
+ export declare function runAnalyze(inputFile: string, outputFile?: string, pretty?: boolean): Promise<AnalyzeResult>;
29
+ /**
30
+ * Parse CLI arguments for the analyze command and execute.
31
+ */
32
+ export declare function runAnalyzeFromArgs(args: string[]): Promise<AnalyzeResult | null>;
33
+ //# sourceMappingURL=analyze.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analyze.d.ts","sourceRoot":"","sources":["../../src/cli/analyze.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAuBH,8CAA8C;AAC9C,MAAM,WAAW,aAAa;IAC5B,iCAAiC;IACjC,OAAO,EAAE,OAAO,CAAC;IACjB,wCAAwC;IACxC,SAAS,EAAE,MAAM,CAAC;CACnB;AAiCD;;;;;;;GAOG;AACH,wBAAsB,UAAU,CAC9B,SAAS,EAAE,MAAM,EACjB,UAAU,CAAC,EAAE,MAAM,EACnB,MAAM,CAAC,EAAE,OAAO,GACf,OAAO,CAAC,aAAa,CAAC,CAiBxB;AAED;;GAEG;AACH,wBAAsB,kBAAkB,CACtC,IAAI,EAAE,MAAM,EAAE,GACb,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CA4D/B"}
@@ -0,0 +1,137 @@
1
+ /**
2
+ * `analyze` subcommand handler.
3
+ *
4
+ * Reads a FeatureSet JSON file (produced by `perfgraph extract`) and runs
5
+ * causal graph analysis, outputting a CausalGraph as JSON.
6
+ *
7
+ * Usage:
8
+ * perfgraph analyze <features-file>
9
+ * perfgraph analyze --input features.json --output graph.json --pretty
10
+ *
11
+ * @packageDocumentation
12
+ */
13
+ import { readFileSync, existsSync } from 'node:fs';
14
+ import { resolve } from 'node:path';
15
+ import { buildCausalGraph } from '../causal/index.js';
16
+ import { FeatureSetSchema } from '../extract/types.js';
17
+ /** Help text shown by `perfgraph analyze --help` */
18
+ const ANALYZE_HELP = `
19
+ ANALYZE OPTIONS
20
+ <file> Path to a FeatureSet JSON file (positional, required)
21
+ --input, -i <file> Path to FeatureSet JSON file (alternative to positional)
22
+ --output, -o <file> Write output to a file (default: stdout)
23
+ --pretty Pretty-print JSON output
24
+ --help, -h Show this help message
25
+
26
+ EXAMPLES
27
+ perfgraph analyze ./features.json
28
+ perfgraph analyze ./features.json --output graph.json
29
+ perfgraph analyze ./features.json --pretty
30
+ `;
31
+ /**
32
+ * Load and validate a FeatureSet from a JSON file.
33
+ */
34
+ function loadFeatureSet(filePath) {
35
+ const resolved = resolve(filePath);
36
+ if (!existsSync(resolved)) {
37
+ throw new Error(`Error: File not found: ${filePath}`);
38
+ }
39
+ let raw;
40
+ try {
41
+ const content = readFileSync(resolved, 'utf-8');
42
+ raw = JSON.parse(content);
43
+ }
44
+ catch (err) {
45
+ throw new Error(`Error: Failed to parse ${filePath}: ${err.message}`);
46
+ }
47
+ // Validate against FeatureSetSchema
48
+ const parsed = FeatureSetSchema.safeParse(raw);
49
+ if (!parsed.success) {
50
+ const firstIssue = parsed.error.issues[0];
51
+ throw new Error(`Error: Invalid FeatureSet format in ${filePath}: ${firstIssue?.path.join('.') ?? ''} ${firstIssue?.message ?? ''}`);
52
+ }
53
+ return parsed.data;
54
+ }
55
+ /**
56
+ * Run the analyze command from a FeatureSet file path.
57
+ *
58
+ * @param inputFile - Path to FeatureSet JSON file
59
+ * @param outputFile - Optional output file path (defaults to stdout)
60
+ * @param pretty - Pretty-print JSON (default: false)
61
+ * @returns AnalyzeResult
62
+ */
63
+ export async function runAnalyze(inputFile, outputFile, pretty) {
64
+ const features = loadFeatureSet(inputFile);
65
+ const graph = buildCausalGraph(features);
66
+ const indent = pretty ? 2 : 0;
67
+ const json = JSON.stringify(graph, null, indent);
68
+ if (outputFile) {
69
+ const { writeFileSync } = await import('node:fs');
70
+ writeFileSync(outputFile, json, 'utf-8');
71
+ }
72
+ else {
73
+ console.log(json);
74
+ }
75
+ return {
76
+ success: true,
77
+ inputFile: resolve(inputFile),
78
+ };
79
+ }
80
+ /**
81
+ * Parse CLI arguments for the analyze command and execute.
82
+ */
83
+ export async function runAnalyzeFromArgs(args) {
84
+ let inputFile;
85
+ let outputFile;
86
+ let pretty = false;
87
+ for (let i = 0; i < args.length; i++) {
88
+ const arg = args[i];
89
+ switch (arg) {
90
+ case '--input':
91
+ case '-i':
92
+ if (i + 1 >= args.length) {
93
+ console.error('Error: --input requires a value');
94
+ return null;
95
+ }
96
+ inputFile = args[++i];
97
+ break;
98
+ case '--output':
99
+ case '-o':
100
+ if (i + 1 >= args.length) {
101
+ console.error('Error: --output requires a value');
102
+ return null;
103
+ }
104
+ outputFile = args[++i];
105
+ break;
106
+ case '--pretty':
107
+ pretty = true;
108
+ break;
109
+ case '--help':
110
+ case '-h':
111
+ console.log(ANALYZE_HELP);
112
+ return null;
113
+ default:
114
+ if (arg.startsWith('--')) {
115
+ console.error(`Error: Unknown flag "${arg}"`);
116
+ return null;
117
+ }
118
+ // First positional arg is the input file
119
+ if (!inputFile) {
120
+ inputFile = arg;
121
+ }
122
+ break;
123
+ }
124
+ }
125
+ if (!inputFile) {
126
+ console.error('Error: <file> is required (positional or --input)');
127
+ return null;
128
+ }
129
+ try {
130
+ return await runAnalyze(inputFile, outputFile, pretty);
131
+ }
132
+ catch (err) {
133
+ console.error(String(err));
134
+ return null;
135
+ }
136
+ }
137
+ //# sourceMappingURL=analyze.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analyze.js","sourceRoot":"","sources":["../../src/cli/analyze.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * `collect` subcommand handler.
3
+ *
4
+ * Parses CLI flags and delegates to the orchestrator.
5
+ * All progress messages are written to stderr; only the final JSON summary
6
+ * (run results) is written to stdout for piping.
7
+ */
8
+ /** Result of the collect command execution */
9
+ export interface CollectResult {
10
+ /** Whether any runs succeeded */
11
+ success: boolean;
12
+ /** Total number of runs attempted */
13
+ runs: number;
14
+ /** Number of successful runs */
15
+ successfulRuns: number;
16
+ /** Output directories for each run */
17
+ outputDirs: string[];
18
+ /** Total warning count across all runs */
19
+ warnings: number;
20
+ }
21
+ /**
22
+ * Parse CLI arguments and execute collection.
23
+ *
24
+ * @param args - Array of CLI arguments (everything after "collect")
25
+ * @returns CollectResult or null if parsing failed
26
+ */
27
+ export declare function runCollect(args: string[]): Promise<CollectResult | null>;
28
+ //# sourceMappingURL=collect.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"collect.d.ts","sourceRoot":"","sources":["../../src/cli/collect.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAMH,8CAA8C;AAC9C,MAAM,WAAW,aAAa;IAC5B,iCAAiC;IACjC,OAAO,EAAE,OAAO,CAAC;IACjB,qCAAqC;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,gCAAgC;IAChC,cAAc,EAAE,MAAM,CAAC;IACvB,sCAAsC;IACtC,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,0CAA0C;IAC1C,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;;;GAKG;AACH,wBAAsB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CAuB9E"}
@@ -0,0 +1,125 @@
1
+ /**
2
+ * `collect` subcommand handler.
3
+ *
4
+ * Parses CLI flags and delegates to the orchestrator.
5
+ * All progress messages are written to stderr; only the final JSON summary
6
+ * (run results) is written to stdout for piping.
7
+ */
8
+ import { run } from '../collect/orchestrator.js';
9
+ import { DEFAULT_RUN_OPTIONS } from '../shared/types.js';
10
+ /**
11
+ * Parse CLI arguments and execute collection.
12
+ *
13
+ * @param args - Array of CLI arguments (everything after "collect")
14
+ * @returns CollectResult or null if parsing failed
15
+ */
16
+ export async function runCollect(args) {
17
+ const options = parseArgs(args);
18
+ if (!options) {
19
+ return null;
20
+ }
21
+ const results = await run(options.url, options);
22
+ const successfulRuns = results.filter((r) => r.success);
23
+ const allOutputDirs = results.map((r) => r.outputDir).filter(Boolean);
24
+ const result = {
25
+ success: successfulRuns.length > 0,
26
+ runs: results.length,
27
+ successfulRuns: successfulRuns.length,
28
+ outputDirs: allOutputDirs,
29
+ warnings: results.reduce((sum, r) => sum + r.warningCount, 0),
30
+ };
31
+ // Write JSON summary to stdout (for piping)
32
+ console.log(JSON.stringify(result, null, 2));
33
+ return result;
34
+ }
35
+ /**
36
+ * Parse CLI flags into CollectorRunOptions.
37
+ *
38
+ * Accepts:
39
+ * --url <url> (required)
40
+ * --output <dir> (default: ./perfgraph-output)
41
+ * --runs <n> (default: 1)
42
+ * --no-lighthouse (flag)
43
+ * --no-coverage (flag)
44
+ * --no-console (flag)
45
+ * --no-dom (flag)
46
+ * --no-network (flag)
47
+ * --no-performance (flag)
48
+ * --no-runtime (flag)
49
+ * --device <name> (optional)
50
+ */
51
+ function parseArgs(args) {
52
+ const options = { ...DEFAULT_RUN_OPTIONS };
53
+ for (let i = 0; i < args.length; i++) {
54
+ const arg = args[i];
55
+ switch (arg) {
56
+ case '--url':
57
+ if (i + 1 >= args.length) {
58
+ console.error('Error: --url requires a value');
59
+ return null;
60
+ }
61
+ options.url = args[++i];
62
+ break;
63
+ case '--output':
64
+ if (i + 1 >= args.length) {
65
+ console.error('Error: --output requires a value');
66
+ return null;
67
+ }
68
+ options.output = args[++i];
69
+ break;
70
+ case '--runs':
71
+ if (i + 1 >= args.length) {
72
+ console.error('Error: --runs requires a value');
73
+ return null;
74
+ }
75
+ options.runs = parseInt(args[++i], 10);
76
+ if (isNaN(options.runs) || options.runs < 1) {
77
+ console.error('Error: --runs must be a positive integer');
78
+ return null;
79
+ }
80
+ break;
81
+ case '--no-lighthouse':
82
+ options.noLighthouse = true;
83
+ break;
84
+ case '--no-coverage':
85
+ options.noCoverage = true;
86
+ break;
87
+ case '--no-console':
88
+ options.noConsole = true;
89
+ break;
90
+ case '--no-dom':
91
+ options.noDom = true;
92
+ break;
93
+ case '--no-network':
94
+ options.noNetwork = true;
95
+ break;
96
+ case '--no-performance':
97
+ options.noPerformance = true;
98
+ break;
99
+ case '--no-runtime':
100
+ options.noRuntime = true;
101
+ break;
102
+ case '--device':
103
+ if (i + 1 >= args.length) {
104
+ console.error('Error: --device requires a value');
105
+ return null;
106
+ }
107
+ options.mobile = args[++i];
108
+ break;
109
+ default:
110
+ if (arg.startsWith('--')) {
111
+ console.error(`Error: Unknown flag "${arg}"`);
112
+ return null;
113
+ }
114
+ // Ignore positional args for now
115
+ break;
116
+ }
117
+ }
118
+ if (!options.url) {
119
+ console.error('Error: --url is required');
120
+ console.error('Usage: perfgraph collect --url <url> [--output <dir>] [--runs <n>]');
121
+ return null;
122
+ }
123
+ return options;
124
+ }
125
+ //# sourceMappingURL=collect.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"collect.js","sourceRoot":"","sources":["../../src/cli/collect.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * `extract` subcommand handler.
3
+ *
4
+ * Reads a normalised IRBundle JSON file (produced by `perfgraph normalize`)
5
+ * and runs feature extraction, outputting a FeatureSet as JSON.
6
+ *
7
+ * Usage:
8
+ * perfgraph extract <ir-file>
9
+ * perfgraph extract --input ir.json --output features.json --pretty
10
+ */
11
+ /** Result of the extract command execution */
12
+ export interface ExtractResult {
13
+ /** Whether extraction succeeded */
14
+ success: boolean;
15
+ /** Path to the input IR file */
16
+ inputFile: string;
17
+ }
18
+ /**
19
+ * Run the extract command from an IR file path.
20
+ *
21
+ * @param inputFile - Path to IR JSON file
22
+ * @param outputFile - Optional output file path (defaults to stdout)
23
+ * @param pretty - Pretty-print JSON (default: false)
24
+ * @returns ExtractResult
25
+ */
26
+ export declare function runExtract(inputFile: string, outputFile?: string, pretty?: boolean): Promise<ExtractResult>;
27
+ /**
28
+ * Parse CLI arguments for the extract command and execute.
29
+ */
30
+ export declare function runExtractFromArgs(args: string[]): Promise<ExtractResult | null>;
31
+ //# sourceMappingURL=extract.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extract.d.ts","sourceRoot":"","sources":["../../src/cli/extract.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAuBH,8CAA8C;AAC9C,MAAM,WAAW,aAAa;IAC5B,mCAAmC;IACnC,OAAO,EAAE,OAAO,CAAC;IACjB,gCAAgC;IAChC,SAAS,EAAE,MAAM,CAAC;CACnB;AAiCD;;;;;;;GAOG;AACH,wBAAsB,UAAU,CAC9B,SAAS,EAAE,MAAM,EACjB,UAAU,CAAC,EAAE,MAAM,EACnB,MAAM,CAAC,EAAE,OAAO,GACf,OAAO,CAAC,aAAa,CAAC,CAiBxB;AAED;;GAEG;AACH,wBAAsB,kBAAkB,CACtC,IAAI,EAAE,MAAM,EAAE,GACb,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CA4D/B"}
@@ -0,0 +1,135 @@
1
+ /**
2
+ * `extract` subcommand handler.
3
+ *
4
+ * Reads a normalised IRBundle JSON file (produced by `perfgraph normalize`)
5
+ * and runs feature extraction, outputting a FeatureSet as JSON.
6
+ *
7
+ * Usage:
8
+ * perfgraph extract <ir-file>
9
+ * perfgraph extract --input ir.json --output features.json --pretty
10
+ */
11
+ import { readFileSync, existsSync } from 'node:fs';
12
+ import { resolve } from 'node:path';
13
+ import { extract } from '../extract/index.js';
14
+ import { IRBundleSchema } from '../normalize/types.js';
15
+ /** Help text shown by `perfgraph extract --help` */
16
+ const EXTRACT_HELP = `
17
+ EXTRACT OPTIONS
18
+ <file> Path to a normalised IR JSON file (positional, required)
19
+ --input, -i <file> Path to IR JSON file (alternative to positional)
20
+ --output, -o <file> Write output to a file (default: stdout)
21
+ --pretty Pretty-print JSON output
22
+ --help, -h Show this help message
23
+
24
+ EXAMPLES
25
+ perfgraph extract ./ir.json
26
+ perfgraph extract ./ir.json --output features.json
27
+ perfgraph extract ./ir.json --pretty
28
+ `;
29
+ /**
30
+ * Load and validate an IRBundle from a JSON file.
31
+ */
32
+ function loadIRBundle(filePath) {
33
+ const resolved = resolve(filePath);
34
+ if (!existsSync(resolved)) {
35
+ throw new Error(`Error: File not found: ${filePath}`);
36
+ }
37
+ let raw;
38
+ try {
39
+ const content = readFileSync(resolved, 'utf-8');
40
+ raw = JSON.parse(content);
41
+ }
42
+ catch (err) {
43
+ throw new Error(`Error: Failed to parse ${filePath}: ${err.message}`);
44
+ }
45
+ // Validate against IRBundleSchema
46
+ const parsed = IRBundleSchema.safeParse(raw);
47
+ if (!parsed.success) {
48
+ const firstIssue = parsed.error.issues[0];
49
+ throw new Error(`Error: Invalid IRBundle format in ${filePath}: ${firstIssue?.path.join('.') ?? ''} ${firstIssue?.message ?? ''}`);
50
+ }
51
+ return parsed.data;
52
+ }
53
+ /**
54
+ * Run the extract command from an IR file path.
55
+ *
56
+ * @param inputFile - Path to IR JSON file
57
+ * @param outputFile - Optional output file path (defaults to stdout)
58
+ * @param pretty - Pretty-print JSON (default: false)
59
+ * @returns ExtractResult
60
+ */
61
+ export async function runExtract(inputFile, outputFile, pretty) {
62
+ const bundle = loadIRBundle(inputFile);
63
+ const features = extract(bundle);
64
+ const indent = pretty ? 2 : 0;
65
+ const json = JSON.stringify(features, null, indent);
66
+ if (outputFile) {
67
+ const { writeFileSync } = await import('node:fs');
68
+ writeFileSync(outputFile, json, 'utf-8');
69
+ }
70
+ else {
71
+ console.log(json);
72
+ }
73
+ return {
74
+ success: true,
75
+ inputFile: resolve(inputFile),
76
+ };
77
+ }
78
+ /**
79
+ * Parse CLI arguments for the extract command and execute.
80
+ */
81
+ export async function runExtractFromArgs(args) {
82
+ let inputFile;
83
+ let outputFile;
84
+ let pretty = false;
85
+ for (let i = 0; i < args.length; i++) {
86
+ const arg = args[i];
87
+ switch (arg) {
88
+ case '--input':
89
+ case '-i':
90
+ if (i + 1 >= args.length) {
91
+ console.error('Error: --input requires a value');
92
+ return null;
93
+ }
94
+ inputFile = args[++i];
95
+ break;
96
+ case '--output':
97
+ case '-o':
98
+ if (i + 1 >= args.length) {
99
+ console.error('Error: --output requires a value');
100
+ return null;
101
+ }
102
+ outputFile = args[++i];
103
+ break;
104
+ case '--pretty':
105
+ pretty = true;
106
+ break;
107
+ case '--help':
108
+ case '-h':
109
+ console.log(EXTRACT_HELP);
110
+ return null;
111
+ default:
112
+ if (arg.startsWith('--')) {
113
+ console.error(`Error: Unknown flag "${arg}"`);
114
+ return null;
115
+ }
116
+ // First positional arg is the input file
117
+ if (!inputFile) {
118
+ inputFile = arg;
119
+ }
120
+ break;
121
+ }
122
+ }
123
+ if (!inputFile) {
124
+ console.error('Error: <file> is required (positional or --input)');
125
+ return null;
126
+ }
127
+ try {
128
+ return await runExtract(inputFile, outputFile, pretty);
129
+ }
130
+ catch (err) {
131
+ console.error(String(err));
132
+ return null;
133
+ }
134
+ }
135
+ //# sourceMappingURL=extract.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extract.js","sourceRoot":"","sources":["../../src/cli/extract.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * `mcp` subcommand handler.
3
+ *
4
+ * Starts a MCP (Model Context Protocol) stdio server so that AI agents
5
+ * (Claude, OpenCode, Cursor, etc.) can invoke perfgraph tools directly.
6
+ *
7
+ * Usage:
8
+ * perfgraph mcp
9
+ */
10
+ /**
11
+ * Parse CLI arguments for the mcp command and execute.
12
+ */
13
+ export declare function runMcpFromArgs(args: string[]): Promise<boolean>;
14
+ //# sourceMappingURL=mcp.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp.d.ts","sourceRoot":"","sources":["../../src/cli/mcp.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAuBH;;GAEG;AACH,wBAAsB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAqBrE"}