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,209 @@
1
+ /**
2
+ * JavaScript / Main Thread causal rules.
3
+ *
4
+ * Chains covered:
5
+ * 1. Long main thread blocking → high TBT → delayed INP
6
+ * 2. Excessive JS → long parse time → main thread contention
7
+ * 3. JS execution hotspots → long tasks → blocking
8
+ *
9
+ * @packageDocumentation
10
+ */
11
+ // ---------------------------------------------------------------------------
12
+ // Thresholds
13
+ // ---------------------------------------------------------------------------
14
+ const TBT_WARN = 200; // ms
15
+ const TBT_CRIT = 600; // ms
16
+ const LONG_TASK_WARN = 5;
17
+ const LONG_TASK_CRIT = 15;
18
+ const BOOTUP_WARN = 2_000; // ms total JS bootup time
19
+ const BOOTUP_CRIT = 5_000;
20
+ const EVALUATED_SCRIPTS_WARN = 50;
21
+ const EVALUATED_SCRIPTS_CRIT = 150;
22
+ // ---------------------------------------------------------------------------
23
+ // Helpers
24
+ // ---------------------------------------------------------------------------
25
+ function confidenceFromDelta(value, warn, crit) {
26
+ if (value >= crit)
27
+ return 'strong';
28
+ if (value >= warn)
29
+ return 'medium';
30
+ return 'weak';
31
+ }
32
+ // ---------------------------------------------------------------------------
33
+ // Rule 1: Main thread blocking → TBT → INP
34
+ // ---------------------------------------------------------------------------
35
+ export const tbtInpChain = {
36
+ id: 'js-tbt-inp-chain',
37
+ label: 'Main thread blocking → high TBT → delayed INP',
38
+ applies(features) {
39
+ const mt = features.mainThreadBlocking;
40
+ return mt != null && mt.blockingScore > 0.3;
41
+ },
42
+ build(features) {
43
+ const mt = features.mainThreadBlocking;
44
+ const busyMs = mt.busyMs;
45
+ const conf = confidenceFromDelta(busyMs, 300, 1000);
46
+ const mtbEvidence = {
47
+ metric: { name: 'Main thread blocking', value: busyMs, unit: 'ms' },
48
+ };
49
+ const nodes = [
50
+ {
51
+ id: 'high-main-thread-blocking',
52
+ label: `Main thread blocked (${Math.round(busyMs)}ms)`,
53
+ type: 'metric',
54
+ severity: busyMs >= 1000 ? 'critical' : busyMs >= 300 ? 'warning' : 'info',
55
+ value: busyMs,
56
+ unit: 'ms',
57
+ threshold: 300,
58
+ evidence: mtbEvidence,
59
+ },
60
+ {
61
+ id: 'high-tbt',
62
+ label: 'High Total Blocking Time',
63
+ type: 'bottleneck',
64
+ severity: busyMs >= 1000 ? 'critical' : 'warning',
65
+ value: busyMs,
66
+ unit: 'ms',
67
+ threshold: TBT_WARN,
68
+ },
69
+ {
70
+ id: 'delayed-inp-tbt',
71
+ label: 'Possible INP delay',
72
+ type: 'impact',
73
+ severity: 'warning',
74
+ },
75
+ ];
76
+ const edges = [
77
+ {
78
+ source: 'high-main-thread-blocking',
79
+ target: 'high-tbt',
80
+ confidence: conf,
81
+ label: 'Main thread blocking increases TBT',
82
+ ruleId: 'js-tbt-inp-chain',
83
+ },
84
+ {
85
+ source: 'high-tbt',
86
+ target: 'delayed-inp-tbt',
87
+ confidence: 'medium',
88
+ label: 'High TBT proxies for INP delay (correlation confirmed)',
89
+ ruleId: 'js-tbt-inp-chain',
90
+ },
91
+ ];
92
+ return { nodes, edges };
93
+ },
94
+ };
95
+ // ---------------------------------------------------------------------------
96
+ // Rule 2: JS execution hotspots → long tasks
97
+ // ---------------------------------------------------------------------------
98
+ export const jsHotspotsChain = {
99
+ id: 'js-hotspots-long-tasks-chain',
100
+ label: 'JS execution hotspots → long tasks',
101
+ applies(features) {
102
+ const js = features.jsHotspots;
103
+ return js != null && js.longTaskCount >= LONG_TASK_WARN;
104
+ },
105
+ build(features) {
106
+ const js = features.jsHotspots;
107
+ const conf = confidenceFromDelta(js.longTaskCount, LONG_TASK_WARN, LONG_TASK_CRIT);
108
+ const hotspotsEvidence = {
109
+ metric: { name: 'Long tasks', value: js.longTaskCount, unit: 'count' },
110
+ };
111
+ const nodes = [
112
+ {
113
+ id: 'js-hotspots',
114
+ label: `${js.longTaskCount} long JS tasks`,
115
+ type: 'metric',
116
+ severity: js.longTaskCount >= LONG_TASK_CRIT ? 'critical' : 'warning',
117
+ value: js.longTaskCount,
118
+ threshold: LONG_TASK_WARN,
119
+ evidence: hotspotsEvidence,
120
+ },
121
+ {
122
+ id: 'long-tasks-js',
123
+ label: 'Long tasks on main thread',
124
+ type: 'bottleneck',
125
+ severity: 'warning',
126
+ },
127
+ ];
128
+ const edges = [
129
+ {
130
+ source: 'js-hotspots',
131
+ target: 'long-tasks-js',
132
+ confidence: conf,
133
+ label: 'JS hotspots create long tasks (>50ms)',
134
+ ruleId: 'js-hotspots-long-tasks-chain',
135
+ },
136
+ ];
137
+ // If there's a max blocking duration, add an edge to delayed-inp
138
+ if (js.maxBlockingDuration > 50) {
139
+ nodes.push({
140
+ id: 'delayed-inp-hotspots',
141
+ label: 'Possible INP delay',
142
+ type: 'impact',
143
+ severity: 'warning',
144
+ });
145
+ edges.push({
146
+ source: 'long-tasks-js',
147
+ target: 'delayed-inp-hotspots',
148
+ confidence: 'medium',
149
+ label: 'Long tasks delay user input processing',
150
+ ruleId: 'js-hotspots-long-tasks-chain',
151
+ });
152
+ }
153
+ return { nodes, edges };
154
+ },
155
+ };
156
+ // ---------------------------------------------------------------------------
157
+ // Rule 3: Excessive scripts → parse time
158
+ // ---------------------------------------------------------------------------
159
+ export const excessiveScriptsChain = {
160
+ id: 'js-excessive-scripts-chain',
161
+ label: 'Many scripts → long parse time → main thread contention',
162
+ applies(features) {
163
+ const js = features.jsHotspots;
164
+ return js != null && js.evaluatedScripts >= EVALUATED_SCRIPTS_WARN;
165
+ },
166
+ build(features) {
167
+ const js = features.jsHotspots;
168
+ const conf = confidenceFromDelta(js.evaluatedScripts, EVALUATED_SCRIPTS_WARN, EVALUATED_SCRIPTS_CRIT);
169
+ const isHeavy = js.bootupTime >= BOOTUP_CRIT;
170
+ const nodes = [
171
+ {
172
+ id: 'many-scripts',
173
+ label: `${js.evaluatedScripts} scripts`,
174
+ type: 'metric',
175
+ severity: isHeavy ? 'critical' : 'warning',
176
+ value: js.evaluatedScripts,
177
+ threshold: EVALUATED_SCRIPTS_WARN,
178
+ },
179
+ {
180
+ id: 'long-parse-time',
181
+ label: `Long parse/compile time (${Math.round(js.bootupTime)}ms)`,
182
+ type: 'bottleneck',
183
+ severity: 'warning',
184
+ value: js.bootupTime,
185
+ unit: 'ms',
186
+ threshold: BOOTUP_WARN,
187
+ },
188
+ ];
189
+ const edges = [
190
+ {
191
+ source: 'many-scripts',
192
+ target: 'long-parse-time',
193
+ confidence: conf,
194
+ label: 'Large number of scripts increases total parse and compile time',
195
+ ruleId: 'js-excessive-scripts-chain',
196
+ },
197
+ ];
198
+ return { nodes, edges };
199
+ },
200
+ };
201
+ // ---------------------------------------------------------------------------
202
+ // Aggregated
203
+ // ---------------------------------------------------------------------------
204
+ export const jsRules = [
205
+ tbtInpChain,
206
+ jsHotspotsChain,
207
+ excessiveScriptsChain,
208
+ ];
209
+ //# sourceMappingURL=js.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"js.js","sourceRoot":"","sources":["../../../src/causal/rules/js.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Layout / DOM causal rules.
3
+ *
4
+ * Chains covered:
5
+ * 1. Layout shift clusters → high CLS
6
+ * 2. Complex DOM (deep nesting, many nodes) → layout instability → CLS
7
+ *
8
+ * @packageDocumentation
9
+ */
10
+ import type { FeatureSet } from '../../extract/types.js';
11
+ import type { CausalNode, CausalEdge } from '../types.js';
12
+ export declare const layoutShiftClusterChain: {
13
+ id: string;
14
+ label: string;
15
+ applies(features: FeatureSet): boolean;
16
+ build(features: FeatureSet): {
17
+ nodes: CausalNode[];
18
+ edges: CausalEdge[];
19
+ };
20
+ };
21
+ export declare const complexDomChain: {
22
+ id: string;
23
+ label: string;
24
+ applies(features: FeatureSet): boolean;
25
+ build(features: FeatureSet): {
26
+ nodes: CausalNode[];
27
+ edges: CausalEdge[];
28
+ };
29
+ };
30
+ export declare const layoutRules: {
31
+ id: string;
32
+ label: string;
33
+ applies(features: FeatureSet): boolean;
34
+ build(features: FeatureSet): {
35
+ nodes: CausalNode[];
36
+ edges: CausalEdge[];
37
+ };
38
+ }[];
39
+ //# sourceMappingURL=layout.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"layout.d.ts","sourceRoot":"","sources":["../../../src/causal/rules/layout.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,KAAK,EAAc,UAAU,EAAE,UAAU,EAAY,MAAM,aAAa,CAAC;AAehF,eAAO,MAAM,uBAAuB;;;sBAIhB,UAAU,GAAG,OAAO;oBAKtB,UAAU,GAAG;QAAE,KAAK,EAAE,UAAU,EAAE,CAAC;QAAC,KAAK,EAAE,UAAU,EAAE,CAAA;KAAE;CAoF1E,CAAC;AAMF,eAAO,MAAM,eAAe;;;sBAIR,UAAU,GAAG,OAAO;oBAKtB,UAAU,GAAG;QAAE,KAAK,EAAE,UAAU,EAAE,CAAC;QAAC,KAAK,EAAE,UAAU,EAAE,CAAA;KAAE;CAqD1E,CAAC;AAMF,eAAO,MAAM,WAAW;;;sBAnKJ,UAAU,GAAG,OAAO;oBAKtB,UAAU,GAAG;QAAE,KAAK,EAAE,UAAU,EAAE,CAAC;QAAC,KAAK,EAAE,UAAU,EAAE,CAAA;KAAE;GAiK1E,CAAC"}
@@ -0,0 +1,169 @@
1
+ /**
2
+ * Layout / DOM causal rules.
3
+ *
4
+ * Chains covered:
5
+ * 1. Layout shift clusters → high CLS
6
+ * 2. Complex DOM (deep nesting, many nodes) → layout instability → CLS
7
+ *
8
+ * @packageDocumentation
9
+ */
10
+ // ---------------------------------------------------------------------------
11
+ // Thresholds
12
+ // ---------------------------------------------------------------------------
13
+ const CLS_WARN = 0.1;
14
+ const CLS_CRIT = 0.25;
15
+ const CLUSTER_SCORE_WARN = 0.3;
16
+ const HIGHLY_COMPLEX_DOM = 5; // highComplexitySubtreeCount >= 5
17
+ // ---------------------------------------------------------------------------
18
+ // Rule 1: Layout shift clusters → CLS
19
+ // ---------------------------------------------------------------------------
20
+ export const layoutShiftClusterChain = {
21
+ id: 'layout-shift-cluster-chain',
22
+ label: 'Layout shift clusters → high CLS',
23
+ applies(features) {
24
+ const ls = features.layoutShifts;
25
+ return ls != null && (ls.cls != null || ls.clusterScore > CLUSTER_SCORE_WARN);
26
+ },
27
+ build(features) {
28
+ const ls = features.layoutShifts;
29
+ // If CLS is defined and below the warning threshold, suppress noise
30
+ if (ls.cls != null && ls.cls < CLS_WARN) {
31
+ if (ls.clusterScore < 0.5) {
32
+ return { nodes: [], edges: [] }; // Skip entirely when cluster is not significant
33
+ }
34
+ // clusterScore >= 0.5 but CLS good — single weak info node
35
+ return {
36
+ nodes: [{
37
+ id: 'cls-minor',
38
+ label: `Layout shifts detected (CLS: ${ls.cls.toFixed(3)}) — within normal threshold`,
39
+ type: 'metric',
40
+ severity: 'info',
41
+ value: ls.cls,
42
+ threshold: CLS_WARN,
43
+ }],
44
+ edges: [],
45
+ };
46
+ }
47
+ const clsValue = ls.cls ?? 0;
48
+ const isPoor = clsValue >= CLS_CRIT || ls.clusterScore > 0.6;
49
+ const conf = clsValue >= CLS_CRIT ? 'strong' : clsValue >= CLS_WARN ? 'medium' : 'weak';
50
+ const clsEvidence = ls.cls != null
51
+ ? { metric: { name: 'CLS', value: ls.cls, unit: 'score' } }
52
+ : undefined;
53
+ const nodes = [
54
+ {
55
+ id: 'layout-shifts',
56
+ label: ls.cls != null ? `Layout shifts (CLS: ${clsValue.toFixed(2)})` : 'Layout shifts detected',
57
+ type: 'metric',
58
+ severity: isPoor ? 'critical' : clsValue >= CLS_WARN ? 'warning' : 'info',
59
+ value: clsValue,
60
+ threshold: CLS_WARN,
61
+ evidence: clsEvidence,
62
+ },
63
+ ];
64
+ const edges = [];
65
+ // If clusterScore is high, add intermediate bottleneck
66
+ if (ls.clusterScore > CLUSTER_SCORE_WARN) {
67
+ nodes.push({
68
+ id: 'layout-shift-clusters',
69
+ label: `Layout shift clusters (score: ${ls.clusterScore.toFixed(2)})`,
70
+ type: 'bottleneck',
71
+ severity: ls.clusterScore > 0.6 ? 'critical' : 'warning',
72
+ value: ls.clusterScore,
73
+ threshold: CLUSTER_SCORE_WARN,
74
+ });
75
+ edges.push({
76
+ source: 'layout-shifts',
77
+ target: 'layout-shift-clusters',
78
+ confidence: 'medium',
79
+ label: 'Shifts cluster together, compounding the problem',
80
+ ruleId: 'layout-shift-cluster-chain',
81
+ });
82
+ }
83
+ nodes.push({
84
+ id: 'high-cls',
85
+ label: 'High Cumulative Layout Shift',
86
+ type: 'impact',
87
+ severity: isPoor ? 'critical' : clsValue >= CLS_WARN ? 'warning' : 'info',
88
+ value: clsValue,
89
+ threshold: CLS_WARN,
90
+ });
91
+ const sourceNode = ls.clusterScore > CLUSTER_SCORE_WARN ? 'layout-shift-clusters' : 'layout-shifts';
92
+ edges.push({
93
+ source: sourceNode,
94
+ target: 'high-cls',
95
+ confidence: conf,
96
+ label: 'Accumulated layout shifts degrade page stability',
97
+ ruleId: 'layout-shift-cluster-chain',
98
+ });
99
+ return { nodes, edges };
100
+ },
101
+ };
102
+ // ---------------------------------------------------------------------------
103
+ // Rule 2: Complex DOM → layout instability
104
+ // ---------------------------------------------------------------------------
105
+ export const complexDomChain = {
106
+ id: 'layout-complex-dom-chain',
107
+ label: 'Complex DOM → layout instability → CLS',
108
+ applies(features) {
109
+ return features.layoutShifts?.highComplexitySubtreeCount != null
110
+ && features.layoutShifts.highComplexitySubtreeCount >= HIGHLY_COMPLEX_DOM;
111
+ },
112
+ build(features) {
113
+ const ls = features.layoutShifts;
114
+ const isDeep = ls.deepNesting;
115
+ const conf = isDeep ? 'strong' : 'medium';
116
+ const nodes = [
117
+ {
118
+ id: 'complex-dom-tree',
119
+ label: `${ls.highComplexitySubtreeCount} complex DOM subtrees`,
120
+ type: 'metric',
121
+ severity: isDeep ? 'warning' : 'info',
122
+ value: ls.highComplexitySubtreeCount,
123
+ threshold: HIGHLY_COMPLEX_DOM,
124
+ },
125
+ {
126
+ id: 'layout-instability',
127
+ label: 'Layout instability',
128
+ type: 'bottleneck',
129
+ severity: isDeep ? 'warning' : 'info',
130
+ },
131
+ ];
132
+ const edges = [
133
+ {
134
+ source: 'complex-dom-tree',
135
+ target: 'layout-instability',
136
+ confidence: conf,
137
+ label: 'Complex DOM structure increases likelihood of shifts',
138
+ ruleId: 'layout-complex-dom-chain',
139
+ },
140
+ ];
141
+ // Connect to CLS impact if there's a CLS value
142
+ if (ls.cls != null) {
143
+ nodes.push({
144
+ id: 'high-cls-dom',
145
+ label: 'High Cumulative Layout Shift',
146
+ type: 'impact',
147
+ severity: 'warning',
148
+ value: ls.cls,
149
+ threshold: CLS_WARN,
150
+ });
151
+ edges.push({
152
+ source: 'layout-instability',
153
+ target: 'high-cls-dom',
154
+ confidence: 'weak',
155
+ label: 'Layout instability may lead to CLS',
156
+ ruleId: 'layout-complex-dom-chain',
157
+ });
158
+ }
159
+ return { nodes, edges };
160
+ },
161
+ };
162
+ // ---------------------------------------------------------------------------
163
+ // Aggregated
164
+ // ---------------------------------------------------------------------------
165
+ export const layoutRules = [
166
+ layoutShiftClusterChain,
167
+ complexDomChain,
168
+ ];
169
+ //# sourceMappingURL=layout.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"layout.js","sourceRoot":"","sources":["../../../src/causal/rules/layout.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,49 @@
1
+ /**
2
+ * LCP-related causal rules.
3
+ *
4
+ * Chains covered:
5
+ * 1. High TTFB → delayed HTML parse → delayed CSS discovery → blocked render → ↑LCP
6
+ * 2. Render-blocking resources → blocked render → ↑LCP
7
+ * 3. Slow LCP resource load → ↑LCP
8
+ *
9
+ * @packageDocumentation
10
+ */
11
+ import type { FeatureSet } from '../../extract/types.js';
12
+ import type { CausalNode, CausalEdge } from '../types.js';
13
+ export declare const ttfbLcpChain: {
14
+ id: string;
15
+ label: string;
16
+ applies(features: FeatureSet): boolean;
17
+ build(features: FeatureSet): {
18
+ nodes: CausalNode[];
19
+ edges: CausalEdge[];
20
+ };
21
+ };
22
+ export declare const renderBlockingLcpChain: {
23
+ id: string;
24
+ label: string;
25
+ applies(features: FeatureSet): boolean;
26
+ build(features: FeatureSet): {
27
+ nodes: CausalNode[];
28
+ edges: CausalEdge[];
29
+ };
30
+ };
31
+ export declare const lcpResourceDelayChain: {
32
+ id: string;
33
+ label: string;
34
+ applies(features: FeatureSet): boolean;
35
+ build(features: FeatureSet): {
36
+ nodes: CausalNode[];
37
+ edges: CausalEdge[];
38
+ };
39
+ };
40
+ export declare const lcpRules: {
41
+ id: string;
42
+ label: string;
43
+ applies(features: FeatureSet): boolean;
44
+ build(features: FeatureSet): {
45
+ nodes: CausalNode[];
46
+ edges: CausalEdge[];
47
+ };
48
+ }[];
49
+ //# sourceMappingURL=lcp.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lcp.d.ts","sourceRoot":"","sources":["../../../src/causal/rules/lcp.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,KAAK,EAAc,UAAU,EAAE,UAAU,EAAY,MAAM,aAAa,CAAC;AAyChF,eAAO,MAAM,YAAY;;;sBAIL,UAAU,GAAG,OAAO;oBAItB,UAAU,GAAG;QAAE,KAAK,EAAE,UAAU,EAAE,CAAC;QAAC,KAAK,EAAE,UAAU,EAAE,CAAA;KAAE;CAkF1E,CAAC;AAMF,eAAO,MAAM,sBAAsB;;;sBAIf,UAAU,GAAG,OAAO;oBAKtB,UAAU,GAAG;QAAE,KAAK,EAAE,UAAU,EAAE,CAAC;QAAC,KAAK,EAAE,UAAU,EAAE,CAAA;KAAE;CA8D1E,CAAC;AAMF,eAAO,MAAM,qBAAqB;;;sBAId,UAAU,GAAG,OAAO;oBAKtB,UAAU,GAAG;QAAE,KAAK,EAAE,UAAU,EAAE,CAAC;QAAC,KAAK,EAAE,UAAU,EAAE,CAAA;KAAE;CAyC1E,CAAC;AAMF,eAAO,MAAM,QAAQ;;;sBAjOD,UAAU,GAAG,OAAO;oBAItB,UAAU,GAAG;QAAE,KAAK,EAAE,UAAU,EAAE,CAAC;QAAC,KAAK,EAAE,UAAU,EAAE,CAAA;KAAE;GAiO1E,CAAC"}