sparkforensics-server 0.5.2 → 0.8.1

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 (445) hide show
  1. package/index.js +16 -7
  2. package/package.json +1 -1
  3. package/public/assets/AutoscalingChurn-DenWKTv-.js +1 -0
  4. package/public/assets/CacheUtilization-DLz7NdjV.js +1 -0
  5. package/public/assets/CachingOpportunity-zpQIqhzm.js +1 -0
  6. package/public/assets/ChartTheme-DAiARbLP.js +8 -0
  7. package/public/assets/ColdStart-C-9HjxWl.js +1 -0
  8. package/public/assets/ConfigAudit-D0V9tcrJ.js +1 -0
  9. package/public/assets/CoreUsageArea-yeerrljd.js +1 -0
  10. package/public/assets/Dashboard-DkUPrHKV.js +1 -0
  11. package/public/assets/DisclosureContext-DK1_iz6J.js +1 -0
  12. package/public/assets/DuplicatePlanSubtree-xDNDbCd3.js +1 -0
  13. package/public/assets/DurationHistogram-B6jsE0Ov.js +1 -0
  14. package/public/assets/EmptyState-C1uL40VU.js +1 -0
  15. package/public/assets/ExecutorUtilization-DXDZKmSc.js +1 -0
  16. package/public/assets/GcPressure-MRf7I4IG.js +1 -0
  17. package/public/assets/ImpactEstimate-Dm3xWbzV.js +1 -0
  18. package/public/assets/IncompleteRun-CaLOhMtf.js +1 -0
  19. package/public/assets/JobFailures-CzmzlvhO.js +1 -0
  20. package/public/assets/MemoryUtilization-AWUMUjCH.js +1 -0
  21. package/public/assets/NestedLoopJoin-C9sNr6Ss.js +1 -0
  22. package/public/assets/OverBroadcast-BOmRE6ca.js +1 -0
  23. package/public/assets/PartitionHint-BL2EmJfE.js +1 -0
  24. package/public/assets/PartitionSizing-BzBySvUq.js +1 -0
  25. package/public/assets/PlanExplorer-DdiQRcJU.js +1 -0
  26. package/public/assets/PlanGraphRoute-CIH9gBuR.js +1 -0
  27. package/public/assets/PlanView-B1hxzFRs.js +2 -0
  28. package/public/assets/PythonUdf-DvgCCueD.js +1 -0
  29. package/public/assets/RetryWaste-uXXu_CyM.js +1 -0
  30. package/public/assets/RowPagination-C-LzWkI5.js +1 -0
  31. package/public/assets/RowStatusCluster-Dbtmte7l.js +1 -0
  32. package/public/assets/ShuffleIO-nALwzC1_.js +1 -0
  33. package/public/assets/Skew-CHMEKgvk.js +1 -0
  34. package/public/assets/SlowHost-yyvjpHk6.js +1 -0
  35. package/public/assets/SmallFiles-y6odJ97n.js +1 -0
  36. package/public/assets/SpeculationWaste-C-SD2LOt.js +1 -0
  37. package/public/assets/Spill-DHTMmOup.js +1 -0
  38. package/public/assets/StageFailed-CQ3DxC9R.js +1 -0
  39. package/public/assets/StageFindingGroup-BgYLyj5q.js +1 -0
  40. package/public/assets/StageHeader-CIETkjVZ.js +1 -0
  41. package/public/assets/StagePill--P7PDd3s.js +1 -0
  42. package/public/assets/StageShape-BIv8vx_o.js +1 -0
  43. package/public/assets/StageSlowness-MMqzERxN.js +1 -0
  44. package/public/assets/Straggler-BgrY7AyW.js +1 -0
  45. package/public/assets/TaskFailures-BHHyKYTs.js +1 -0
  46. package/public/assets/TinyTask-DDScNhCl.js +1 -0
  47. package/public/assets/UnderBroadcast-CGIC04TI.js +1 -0
  48. package/public/assets/WidgetLeadSummary-CXFZP00C.js +1 -0
  49. package/public/assets/button-DbpTz2yk.js +1 -0
  50. package/public/assets/charts-vendor-CtTxwTeu.js +59 -0
  51. package/public/assets/composite-C9Nu2EI9.js +1 -0
  52. package/public/assets/d3-vendor-DNlD2-cz.js +1 -0
  53. package/public/assets/detector-registry-Bp8hrLua.js +2 -0
  54. package/public/assets/downsample-WmNM1qc9.js +1 -0
  55. package/public/assets/finding-anchor-Dr40LkS9.js +1 -0
  56. package/public/assets/findings-of-type-BL2u3RGZ.js +1 -0
  57. package/public/assets/impact-sort-mC5ISgX8.js +1 -0
  58. package/public/assets/inbox-KPU1Gppm.js +1 -0
  59. package/public/assets/index-CaRVPvAT.css +2 -0
  60. package/public/assets/index-fDiwfuoO.js +14 -0
  61. package/public/assets/inertValue-L9VxV0VE.js +1 -0
  62. package/public/assets/instrument-sans-latin-ext-wdth-normal-C5E2Gvlv.woff2 +0 -0
  63. package/public/assets/instrument-sans-latin-wdth-normal-BVScPF0l.woff2 +0 -0
  64. package/public/assets/jetbrains-mono-latin-ext-wght-normal-DBQx-q_a.woff2 +0 -0
  65. package/public/assets/jetbrains-mono-latin-wght-normal-B9CIFXIH.woff2 +0 -0
  66. package/public/assets/layout.worker-CLcBHxVp.js +3 -0
  67. package/public/assets/{parser-worker-CA5RxqKc.js → parser-worker-CRIOPMOW.js} +8 -8
  68. package/public/assets/plan-graph-vendor-Ce6d4HU6.js +7 -0
  69. package/public/assets/react-vendor-C6KcUD36.js +9 -0
  70. package/public/assets/select-BHqOqun5.js +1 -0
  71. package/public/assets/toggle-DPeN6aNa.js +1 -0
  72. package/public/assets/toggle-group-Kl3uyHSr.js +1 -0
  73. package/public/assets/usePagedRows-BafD6bEN.js +1 -0
  74. package/public/assets/useRecentFiles-DzJZAoOT.js +3 -0
  75. package/public/assets/useRegisterFieldControl-pQv-ZDoU.js +1 -0
  76. package/public/assets/useScrollLock-BCxn_dMp.js +1 -0
  77. package/public/assets/useSortMode-DjrAN-z4.js +1 -0
  78. package/public/docs/404.html +3 -7
  79. package/public/docs/assets/{app.eYTPqTeq.js → app.1gvzd5Zb.js} +1 -1
  80. package/public/docs/assets/chunks/@localSearchIndexroot.DS2TQP5_.js +1 -0
  81. package/public/docs/assets/chunks/{VPLocalSearchBox.DsZrQKQR.js → VPLocalSearchBox.CNxT3s0I.js} +1 -1
  82. package/public/docs/assets/chunks/{theme.DsTNE2pE.js → theme.C5lLqUv7.js} +2 -2
  83. package/public/docs/assets/contributor-guide_architecture_board-widgets.md.CqKM_jEG.js +1 -0
  84. package/public/docs/assets/contributor-guide_architecture_board-widgets.md.CqKM_jEG.lean.js +1 -0
  85. package/public/docs/assets/{contributor-guide_architecture_board-widgets_caching-and-memory.md.8bH1HnZp.js → contributor-guide_architecture_board-widgets_caching-and-memory.md.BYDo3ClR.js} +1 -1
  86. package/public/docs/assets/contributor-guide_architecture_board-widgets_plan-advisor.md.ajUAVdbc.js +1 -0
  87. package/public/docs/assets/contributor-guide_architecture_board-widgets_visual-system-and-templating.md.WqY74T0T.js +1 -0
  88. package/public/docs/assets/contributor-guide_architecture_board-widgets_visual-system-and-templating.md.WqY74T0T.lean.js +1 -0
  89. package/public/docs/assets/contributor-guide_architecture_detector-contract.md.CHHgywoP.js +1 -0
  90. package/public/docs/assets/{contributor-guide_architecture_detector-contract.md.wj6Et6UD.lean.js → contributor-guide_architecture_detector-contract.md.CHHgywoP.lean.js} +1 -1
  91. package/public/docs/assets/contributor-guide_architecture_detector-contract_plan-attribution.md.DIz3_oz9.js +1 -0
  92. package/public/docs/assets/contributor-guide_architecture_detector-contract_plan-attribution.md.DIz3_oz9.lean.js +1 -0
  93. package/public/docs/assets/contributor-guide_architecture_detector-contract_threshold-tables.md.WH4tRHPL.js +1 -0
  94. package/public/docs/assets/{contributor-guide_architecture_detector-contract_threshold-tables.md.CKjWG56Y.lean.js → contributor-guide_architecture_detector-contract_threshold-tables.md.WH4tRHPL.lean.js} +1 -1
  95. package/public/docs/assets/{contributor-guide_architecture_drill-down.md.CqZPrdo9.js → contributor-guide_architecture_drill-down.md.yB-Hz2XT.js} +1 -1
  96. package/public/docs/assets/{contributor-guide_architecture_drill-down.md.CqZPrdo9.lean.js → contributor-guide_architecture_drill-down.md.yB-Hz2XT.lean.js} +1 -1
  97. package/public/docs/assets/contributor-guide_architecture_drill-down_plan-graph.md.BQZE04sw.js +1 -0
  98. package/public/docs/assets/{contributor-guide_architecture_drill-down_plan-graph.md.DwOozIEs.lean.js → contributor-guide_architecture_drill-down_plan-graph.md.BQZE04sw.lean.js} +1 -1
  99. package/public/docs/assets/contributor-guide_architecture_impact-estimation.md.K71YB-Rr.js +1 -0
  100. package/public/docs/assets/{contributor-guide_architecture_impact-estimation.md.CZv_ZGOp.lean.js → contributor-guide_architecture_impact-estimation.md.K71YB-Rr.lean.js} +1 -1
  101. package/public/docs/assets/contributor-guide_architecture_impact-estimation_caveats-tuning-and-coverage.md.DLCAffwn.js +1 -0
  102. package/public/docs/assets/{contributor-guide_architecture_impact-estimation_caveats-tuning-and-coverage.md.BUucRc0A.lean.js → contributor-guide_architecture_impact-estimation_caveats-tuning-and-coverage.md.DLCAffwn.lean.js} +1 -1
  103. package/public/docs/assets/contributor-guide_architecture_impact-estimation_stage-union-rollup.md.JFrzDMwo.js +1 -0
  104. package/public/docs/assets/contributor-guide_architecture_impact-estimation_stage-union-rollup.md.JFrzDMwo.lean.js +1 -0
  105. package/public/docs/assets/contributor-guide_architecture_overview.md.nxkpOhgf.js +1 -0
  106. package/public/docs/assets/contributor-guide_architecture_state-and-history_run-comparison-internals.md.U-9KMDFK.js +1 -0
  107. package/public/docs/assets/{contributor-guide_architecture_state-and-history_run-comparison-internals.md.CZA0JLtV.lean.js → contributor-guide_architecture_state-and-history_run-comparison-internals.md.U-9KMDFK.lean.js} +1 -1
  108. package/public/docs/assets/contributor-guide_architecture_widget-rendering.md.BrSz8Ezh.js +1 -0
  109. package/public/docs/assets/contributor-guide_architecture_widget-rendering_findings-tab.md.B7rjSF_h.js +1 -0
  110. package/public/docs/assets/contributor-guide_architecture_widget-rendering_findings-tab.md.B7rjSF_h.lean.js +1 -0
  111. package/public/docs/assets/{contributor-guide_architecture_widget-rendering_list-sort-mode.md.BuHKgH0C.js → contributor-guide_architecture_widget-rendering_list-sort-mode.md.37hcZJ7q.js} +1 -1
  112. package/public/docs/assets/{contributor-guide_architecture_widget-rendering_row-expand-contract.md.ZT89u9f1.js → contributor-guide_architecture_widget-rendering_row-expand-contract.md.mK_VmAWk.js} +1 -1
  113. package/public/docs/assets/{contributor-guide_architecture_worker-protocol.md.BAnhi2-d.js → contributor-guide_architecture_worker-protocol.md.Br6OE7RW.js} +1 -1
  114. package/public/docs/assets/contributor-guide_architecture_worker-protocol.md.Br6OE7RW.lean.js +1 -0
  115. package/public/docs/assets/contributor-guide_architecture_worker-protocol_cli-and-mcp.md.IVyaXrGe.js +1 -0
  116. package/public/docs/assets/{contributor-guide_architecture_worker-protocol_cli-and-mcp.md.DC1YqXBp.lean.js → contributor-guide_architecture_worker-protocol_cli-and-mcp.md.IVyaXrGe.lean.js} +1 -1
  117. package/public/docs/assets/{contributor-guide_architecture_worker-protocol_core-and-event-validation.md.DSVFPpWb.js → contributor-guide_architecture_worker-protocol_core-and-event-validation.md.DVSXn-bb.js} +1 -1
  118. package/public/docs/assets/{contributor-guide_architecture_worker-protocol_evidence-availability.md.CjimIDBY.js → contributor-guide_architecture_worker-protocol_evidence-availability.md.D3S5cyOW.js} +2 -2
  119. package/public/docs/assets/{contributor-guide_architecture_worker-protocol_evidence-availability.md.CjimIDBY.lean.js → contributor-guide_architecture_worker-protocol_evidence-availability.md.D3S5cyOW.lean.js} +1 -1
  120. package/public/docs/assets/contributor-guide_architecture_worker-protocol_evidence-report.md.CtmCU57I.js +1 -0
  121. package/public/docs/assets/{contributor-guide_architecture_worker-protocol_evidence-report.md.DVGZOWvW.lean.js → contributor-guide_architecture_worker-protocol_evidence-report.md.CtmCU57I.lean.js} +1 -1
  122. package/public/docs/assets/contributor-guide_contributing.md.DBW4drtZ.js +1 -0
  123. package/public/docs/assets/{contributor-guide_development-setup.md.D9bu4j_c.js → contributor-guide_development-setup.md.B21ZTDhn.js} +3 -3
  124. package/public/docs/assets/contributor-guide_development-setup.md.B21ZTDhn.lean.js +1 -0
  125. package/public/docs/assets/contributor-guide_testing.md.DpkozNoG.js +4 -0
  126. package/public/docs/assets/{contributor-guide_testing.md.By6XGR9a.lean.js → contributor-guide_testing.md.DpkozNoG.lean.js} +1 -1
  127. package/public/docs/assets/{index.md.CHJVslga.js → index.md.lMm7SUMz.js} +1 -1
  128. package/public/docs/assets/{index.md.CHJVslga.lean.js → index.md.lMm7SUMz.lean.js} +1 -1
  129. package/public/docs/assets/instrument-sans-latin-ext-wdth-normal.C5E2Gvlv.woff2 +0 -0
  130. package/public/docs/assets/instrument-sans-latin-wdth-normal.BVScPF0l.woff2 +0 -0
  131. package/public/docs/assets/jetbrains-mono-cyrillic-wght-normal.D73BlboJ.woff2 +0 -0
  132. package/public/docs/assets/jetbrains-mono-greek-wght-normal.Bw9x6K1M.woff2 +0 -0
  133. package/public/docs/assets/jetbrains-mono-latin-ext-wght-normal.DBQx-q_a.woff2 +0 -0
  134. package/public/docs/assets/jetbrains-mono-latin-wght-normal.B9CIFXIH.woff2 +0 -0
  135. package/public/docs/assets/jetbrains-mono-vietnamese-wght-normal.Bt-aOZkq.woff2 +0 -0
  136. package/public/docs/assets/style.Cfxqlj0y.css +1 -0
  137. package/public/docs/assets/user-guide_getting-started_ci-and-automation.md.C0pcQoNc.js +29 -0
  138. package/public/docs/assets/user-guide_getting-started_ci-and-automation.md.C0pcQoNc.lean.js +1 -0
  139. package/public/docs/assets/user-guide_getting-started_reading-the-dashboard.md.CGaxPX_1.js +1 -0
  140. package/public/docs/assets/{user-guide_getting-started_tuning-thresholds.md.B_MyjyZm.js → user-guide_getting-started_tuning-thresholds.md.BGVE-wrc.js} +2 -2
  141. package/public/docs/assets/{user-guide_getting-started_tuning-thresholds.md.B_MyjyZm.lean.js → user-guide_getting-started_tuning-thresholds.md.BGVE-wrc.lean.js} +1 -1
  142. package/public/docs/assets/{user-guide_mcp-tools.md.C65SjWUL.js → user-guide_mcp-tools.md.49r3L2YE.js} +1 -1
  143. package/public/docs/assets/{user-guide_mcp-tools_compare-runs.md.Cc_gLoix.js → user-guide_mcp-tools_compare-runs.md.BQ_kIptC.js} +11 -6
  144. package/public/docs/assets/user-guide_mcp-tools_compare-runs.md.BQ_kIptC.lean.js +1 -0
  145. package/public/docs/assets/user-guide_mcp-tools_diagnose-run.md.azCZXkH8.js +44 -0
  146. package/public/docs/assets/{user-guide_mcp-tools_diagnose-run.md.BP1vnHA5.lean.js → user-guide_mcp-tools_diagnose-run.md.azCZXkH8.lean.js} +1 -1
  147. package/public/docs/assets/{user-guide_mcp-tools_evaluate-budgets.md.BB0nDY3Z.js → user-guide_mcp-tools_evaluate-budgets.md.dpQpRQ7z.js} +2 -2
  148. package/public/docs/assets/{user-guide_mcp-tools_evaluate-budgets.md.BB0nDY3Z.lean.js → user-guide_mcp-tools_evaluate-budgets.md.dpQpRQ7z.lean.js} +1 -1
  149. package/public/docs/assets/{user-guide_mcp-tools_get-finding-evidence.md.rKyu4wts.js → user-guide_mcp-tools_get-finding-evidence.md.CH6FkNLX.js} +2 -1
  150. package/public/docs/assets/{user-guide_mcp-tools_get-finding-evidence.md.rKyu4wts.lean.js → user-guide_mcp-tools_get-finding-evidence.md.CH6FkNLX.lean.js} +1 -1
  151. package/public/docs/assets/{user-guide_mcp-tools_get-run-summary.md.DpxZ4ZNp.js → user-guide_mcp-tools_get-run-summary.md.EhaIsele.js} +1 -1
  152. package/public/docs/assets/user-guide_run-comparison.md.B_LOkdBf.js +1 -0
  153. package/public/docs/assets/user-guide_run-comparison.md.B_LOkdBf.lean.js +1 -0
  154. package/public/docs/assets/user-guide_understanding-findings.md.C4riKCKl.js +1 -0
  155. package/public/docs/assets/user-guide_understanding-findings.md.C4riKCKl.lean.js +1 -0
  156. package/public/docs/contributor-guide/architecture/board-widgets/caching-and-memory.html +6 -10
  157. package/public/docs/contributor-guide/architecture/board-widgets/plan-advisor.html +6 -10
  158. package/public/docs/contributor-guide/architecture/board-widgets/visual-system-and-templating.html +6 -10
  159. package/public/docs/contributor-guide/architecture/board-widgets.html +6 -10
  160. package/public/docs/contributor-guide/architecture/detector-contract/plan-attribution.html +6 -10
  161. package/public/docs/contributor-guide/architecture/detector-contract/threshold-tables.html +6 -10
  162. package/public/docs/contributor-guide/architecture/detector-contract.html +6 -10
  163. package/public/docs/contributor-guide/architecture/drill-down/plan-graph.html +6 -10
  164. package/public/docs/contributor-guide/architecture/drill-down.html +6 -10
  165. package/public/docs/contributor-guide/architecture/impact-estimation/caveats-tuning-and-coverage.html +6 -10
  166. package/public/docs/contributor-guide/architecture/impact-estimation/stage-union-rollup.html +6 -10
  167. package/public/docs/contributor-guide/architecture/impact-estimation.html +6 -10
  168. package/public/docs/contributor-guide/architecture/index.html +5 -9
  169. package/public/docs/contributor-guide/architecture/overview.html +6 -10
  170. package/public/docs/contributor-guide/architecture/state-and-history/history-server-intake.html +5 -9
  171. package/public/docs/contributor-guide/architecture/state-and-history/run-comparison-internals.html +6 -10
  172. package/public/docs/contributor-guide/architecture/state-and-history.html +5 -9
  173. package/public/docs/contributor-guide/architecture/widget-rendering/findings-tab.html +6 -10
  174. package/public/docs/contributor-guide/architecture/widget-rendering/investigation-routing.html +5 -9
  175. package/public/docs/contributor-guide/architecture/widget-rendering/list-sort-mode.html +6 -10
  176. package/public/docs/contributor-guide/architecture/widget-rendering/reference-section.html +5 -9
  177. package/public/docs/contributor-guide/architecture/widget-rendering/row-expand-contract.html +6 -10
  178. package/public/docs/contributor-guide/architecture/widget-rendering.html +6 -10
  179. package/public/docs/contributor-guide/architecture/worker-protocol/cli-and-mcp.html +6 -10
  180. package/public/docs/contributor-guide/architecture/worker-protocol/core-and-event-validation.html +6 -10
  181. package/public/docs/contributor-guide/architecture/worker-protocol/evidence-availability.html +7 -11
  182. package/public/docs/contributor-guide/architecture/worker-protocol/evidence-report.html +6 -10
  183. package/public/docs/contributor-guide/architecture/worker-protocol.html +6 -10
  184. package/public/docs/contributor-guide/contributing.html +6 -10
  185. package/public/docs/contributor-guide/development-setup.html +8 -12
  186. package/public/docs/contributor-guide/testing.html +9 -10
  187. package/public/docs/favicon.svg +2 -2
  188. package/public/docs/hashmap.json +1 -1
  189. package/public/docs/index.html +6 -10
  190. package/public/docs/logo-dark.svg +1 -0
  191. package/public/docs/logo-light.svg +1 -0
  192. package/public/docs/tuning-reference/anti-patterns.html +5 -9
  193. package/public/docs/tuning-reference/aqe.html +5 -9
  194. package/public/docs/tuning-reference/bottleneck-broadcast-sizing.html +5 -9
  195. package/public/docs/tuning-reference/bottleneck-cold-start.html +5 -9
  196. package/public/docs/tuning-reference/bottleneck-duplicate-plan-subtree.html +5 -9
  197. package/public/docs/tuning-reference/bottleneck-failures.html +5 -9
  198. package/public/docs/tuning-reference/bottleneck-gc.html +5 -9
  199. package/public/docs/tuning-reference/bottleneck-job-failure-rate.html +5 -9
  200. package/public/docs/tuning-reference/bottleneck-memory-utilization.html +5 -9
  201. package/public/docs/tuning-reference/bottleneck-retry-waste.html +5 -9
  202. package/public/docs/tuning-reference/bottleneck-shuffle.html +5 -9
  203. package/public/docs/tuning-reference/bottleneck-skew.html +5 -9
  204. package/public/docs/tuning-reference/bottleneck-slow-host.html +5 -9
  205. package/public/docs/tuning-reference/bottleneck-small-files.html +5 -9
  206. package/public/docs/tuning-reference/bottleneck-spill.html +5 -9
  207. package/public/docs/tuning-reference/bottleneck-straggler.html +5 -9
  208. package/public/docs/tuning-reference/bottleneck-tiny-tasks.html +5 -9
  209. package/public/docs/tuning-reference/bottleneck-utilization.html +5 -9
  210. package/public/docs/tuning-reference/caching.html +5 -9
  211. package/public/docs/tuning-reference/cluster-config.html +5 -9
  212. package/public/docs/tuning-reference/config.html +5 -9
  213. package/public/docs/tuning-reference/data-formats.html +5 -9
  214. package/public/docs/tuning-reference/index.html +5 -9
  215. package/public/docs/tuning-reference/intro.html +5 -9
  216. package/public/docs/tuning-reference/joins.html +5 -9
  217. package/public/docs/tuning-reference/memory-model.html +5 -9
  218. package/public/docs/tuning-reference/metrics.html +5 -9
  219. package/public/docs/tuning-reference/partitioning.html +5 -9
  220. package/public/docs/tuning-reference/pyspark.html +5 -9
  221. package/public/docs/tuning-reference/shuffle.html +5 -9
  222. package/public/docs/tuning-reference/spark-architecture.html +5 -9
  223. package/public/docs/tuning-reference/table-formats.html +5 -9
  224. package/public/docs/user-guide/alternative-log-retrieval/managed-platforms.html +5 -9
  225. package/public/docs/user-guide/alternative-log-retrieval/ssh-bastion.html +5 -9
  226. package/public/docs/user-guide/alternative-log-retrieval.html +5 -9
  227. package/public/docs/user-guide/getting-started/ci-and-automation.html +17 -15
  228. package/public/docs/user-guide/getting-started/reading-the-dashboard.html +6 -10
  229. package/public/docs/user-guide/getting-started/regression-metric-keys.html +5 -9
  230. package/public/docs/user-guide/getting-started/tuning-thresholds.html +7 -11
  231. package/public/docs/user-guide/getting-started.html +5 -9
  232. package/public/docs/user-guide/mcp-tools/compare-runs.html +16 -15
  233. package/public/docs/user-guide/mcp-tools/diagnose-run.html +28 -11
  234. package/public/docs/user-guide/mcp-tools/evaluate-budgets.html +6 -10
  235. package/public/docs/user-guide/mcp-tools/get-finding-documentation.html +5 -9
  236. package/public/docs/user-guide/mcp-tools/get-finding-evidence.html +7 -10
  237. package/public/docs/user-guide/mcp-tools/get-reference-doc.html +5 -9
  238. package/public/docs/user-guide/mcp-tools/get-run-summary.html +6 -10
  239. package/public/docs/user-guide/mcp-tools/list-runs.html +5 -9
  240. package/public/docs/user-guide/mcp-tools.html +6 -10
  241. package/public/docs/user-guide/run-comparison/how-stages-are-matched.html +5 -9
  242. package/public/docs/user-guide/run-comparison.html +6 -10
  243. package/public/docs/user-guide/understanding-findings.html +6 -10
  244. package/public/export-template.html +46 -46
  245. package/public/favicon.svg +2 -2
  246. package/public/index.html +8 -10
  247. package/public/sample-runs/sample-run.ndjson.gz +0 -0
  248. package/vendor-core/allocation.js +126 -39
  249. package/vendor-core/analyzer.js +85 -58
  250. package/vendor-core/api-merge-writes.js +3 -0
  251. package/vendor-core/aqe-skew.js +347 -0
  252. package/vendor-core/cli/budgets.js +6 -4
  253. package/vendor-core/cli/collect-run-pair.js +89 -0
  254. package/vendor-core/cli/collect-run-worker.js +16 -0
  255. package/vendor-core/cli/collect-run.js +1 -2
  256. package/vendor-core/cli/native-zstd.js +12 -16
  257. package/vendor-core/comparability.js +234 -0
  258. package/vendor-core/comparison-output.js +15 -7
  259. package/vendor-core/comparison-verdict.js +105 -25
  260. package/vendor-core/core-source-hash.txt +1 -1
  261. package/vendor-core/core-time-series.js +0 -1
  262. package/vendor-core/core-usage-locality.js +1 -1
  263. package/vendor-core/delta-log-paths.js +10 -1
  264. package/vendor-core/detectors.js +1078 -416
  265. package/vendor-core/docs-config.js +0 -4
  266. package/vendor-core/docs-content/detection/cache.md +2 -1
  267. package/vendor-core/docs-content/detection/cfg.md +19 -11
  268. package/vendor-core/docs-content/detection/cold.md +2 -1
  269. package/vendor-core/docs-content/detection/gc.md +7 -3
  270. package/vendor-core/docs-content/detection/host.md +11 -1
  271. package/vendor-core/docs-content/detection/mem.md +17 -6
  272. package/vendor-core/docs-content/detection/part.md +3 -1
  273. package/vendor-core/docs-content/detection/plan.md +55 -13
  274. package/vendor-core/docs-content/detection/shfl.md +11 -5
  275. package/vendor-core/docs-content/detection/skew.md +48 -1
  276. package/vendor-core/docs-content/detection/slow.md +4 -2
  277. package/vendor-core/docs-content/detection/spec.md +6 -1
  278. package/vendor-core/docs-content/detection/spill.md +6 -3
  279. package/vendor-core/docs-content/detection/strag.md +19 -6
  280. package/vendor-core/docs-content/detection/tiny.md +9 -3
  281. package/vendor-core/docs-content/detection/util.md +6 -2
  282. package/vendor-core/effective-conf.js +7 -10
  283. package/vendor-core/efficiency-model.js +24 -16
  284. package/vendor-core/etl-phases.js +1 -2
  285. package/vendor-core/event-handlers.js +175 -57
  286. package/vendor-core/event-schemas.js +21 -16
  287. package/vendor-core/evidence-availability.js +9 -2
  288. package/vendor-core/evidence-report.js +118 -35
  289. package/vendor-core/executor-peaks.js +41 -0
  290. package/vendor-core/export-data.js +5 -5
  291. package/vendor-core/finding-identity.js +78 -0
  292. package/vendor-core/finding-presentation.js +129 -39
  293. package/vendor-core/finding-types.js +108 -30
  294. package/vendor-core/format-utils.js +14 -15
  295. package/vendor-core/html-export.js +1 -1
  296. package/vendor-core/impact-band.js +2 -2
  297. package/vendor-core/impact-format.js +47 -19
  298. package/vendor-core/impact-model.js +28 -17
  299. package/vendor-core/job-groups.js +4 -4
  300. package/vendor-core/mcp-server-factory.js +48 -12
  301. package/vendor-core/mcp-tools.js +179 -24
  302. package/vendor-core/median.js +2 -2
  303. package/vendor-core/nested-loop-join.js +73 -0
  304. package/vendor-core/occupancy.js +1 -2
  305. package/vendor-core/parser-worker.js +1 -1
  306. package/vendor-core/plan-graph-model.js +14 -22
  307. package/vendor-core/plan-node-detail.js +2 -3
  308. package/vendor-core/plan-summary.js +24 -19
  309. package/vendor-core/plan-tree-walk.js +6 -8
  310. package/vendor-core/python-stage.js +12 -1
  311. package/vendor-core/recommendation-rollup.js +13 -12
  312. package/vendor-core/redact.js +52 -46
  313. package/vendor-core/remediation.js +10 -5
  314. package/vendor-core/run-aggregates.js +6 -8
  315. package/vendor-core/run-comparison.js +226 -66
  316. package/vendor-core/run-identity.js +12 -0
  317. package/vendor-core/run-interpretation.js +21 -0
  318. package/vendor-core/run-metrics.js +2 -2
  319. package/vendor-core/run-output.js +44 -11
  320. package/vendor-core/run-totals.js +12 -0
  321. package/vendor-core/run-verdict.js +76 -3
  322. package/vendor-core/scaling-sim.js +3 -4
  323. package/vendor-core/snappy-block.js +2 -2
  324. package/vendor-core/spark-conf.js +168 -0
  325. package/vendor-core/sql-stages.js +2 -2
  326. package/vendor-core/stage-alignment.js +2 -12
  327. package/vendor-core/stage-identity.js +58 -3
  328. package/vendor-core/stage-label.js +14 -0
  329. package/vendor-core/stage-plan-nodes.js +17 -3
  330. package/vendor-core/stage-quantiles.js +141 -9
  331. package/vendor-core/stage-structure.js +17 -3
  332. package/vendor-core/threshold-overrides.js +9 -3
  333. package/vendor-core/types.js +70 -23
  334. package/vendor-core/wall-clock.js +8 -0
  335. package/vendor-core/wasted-core-hours.js +12 -12
  336. package/vendor-core/write-targets.js +146 -14
  337. package/vendor-core/zstd-worker-client.js +1 -1
  338. package/vendor-core/zstd-worker.js +1 -1
  339. package/public/assets/AutoscalingChurn-8t3U3isq.js +0 -1
  340. package/public/assets/CacheUtilization-CJs9tTum.js +0 -1
  341. package/public/assets/CachingOpportunity-D1NcHs0V.js +0 -1
  342. package/public/assets/ColdStart-CdRJ9gD8.js +0 -1
  343. package/public/assets/ConfigAudit-B5Gbe5js.js +0 -1
  344. package/public/assets/CoreUsageArea-a--NTRGY.js +0 -1
  345. package/public/assets/Dashboard-C1hNeX49.js +0 -2
  346. package/public/assets/DisclosureContext-ZpE6CkHx.js +0 -1
  347. package/public/assets/DuplicatePlanSubtree-dobXdz7E.js +0 -1
  348. package/public/assets/ExecutorUtilization-D9grwi7t.js +0 -1
  349. package/public/assets/GcPressure-8-G2ri10.js +0 -1
  350. package/public/assets/IncompleteRun-B91lky7a.js +0 -1
  351. package/public/assets/JobFailures-BsWvBMyJ.js +0 -1
  352. package/public/assets/MemoryUtilization-BM5schZI.js +0 -1
  353. package/public/assets/OverBroadcast-DdN8JIJH.js +0 -1
  354. package/public/assets/PartitionHint-CUvbnnxy.js +0 -1
  355. package/public/assets/PartitionSizing-CY5HDYtp.js +0 -1
  356. package/public/assets/PlanExplorer-DgHCDBD_.js +0 -1
  357. package/public/assets/PlanGraphRoute-DH3KJb8j.js +0 -1
  358. package/public/assets/RetryWaste-DOnE9vGF.js +0 -1
  359. package/public/assets/ShuffleIO-MMnDESkF.js +0 -1
  360. package/public/assets/Skew-BmZZJ5ms.js +0 -1
  361. package/public/assets/SlowHost-CsJzfEqo.js +0 -1
  362. package/public/assets/SmallFiles-BoK3R1Ex.js +0 -1
  363. package/public/assets/SpeculationWaste-CnVxB5AJ.js +0 -1
  364. package/public/assets/Spill-BhNicyBy.js +0 -1
  365. package/public/assets/StageFailed-mAhHU4l_.js +0 -1
  366. package/public/assets/StageFindingGroup-BEtPWcT0.js +0 -1
  367. package/public/assets/StageHeader-DJkYkrsU.js +0 -1
  368. package/public/assets/StageShape-BDxRknLp.js +0 -1
  369. package/public/assets/StageSlowness-BPRw-otN.js +0 -1
  370. package/public/assets/Straggler-CZCbnOWP.js +0 -1
  371. package/public/assets/TaskFailures-C57YcLFQ.js +0 -1
  372. package/public/assets/TinyTask-Bi84qU7n.js +0 -1
  373. package/public/assets/UnderBroadcast-DdQV7htE.js +0 -1
  374. package/public/assets/charts-vendor-0VMaLVLN.js +0 -59
  375. package/public/assets/finding-anchor-Cl6_5hfV.js +0 -1
  376. package/public/assets/impact-sort-CssZ6MT2.js +0 -1
  377. package/public/assets/index-2h_TgUAb.css +0 -2
  378. package/public/assets/index-B-03mG7K.js +0 -14
  379. package/public/assets/plan-graph-vendor-BYl-AzN5.js +0 -7
  380. package/public/assets/react-vendor-DEdfrRTJ.js +0 -9
  381. package/public/assets/select-CQjNhprm.js +0 -1
  382. package/public/assets/usePagedRows-Dyl6T8Ok.js +0 -1
  383. package/public/assets/useRecentFiles-XZEnLlal.js +0 -11
  384. package/public/assets/useSortMode-Dhvit8dt.js +0 -1
  385. package/public/docs/assets/chunks/@localSearchIndexroot.u_e5bQz4.js +0 -1
  386. package/public/docs/assets/contributor-guide_architecture_board-widgets.md.YQcj5EI4.js +0 -1
  387. package/public/docs/assets/contributor-guide_architecture_board-widgets.md.YQcj5EI4.lean.js +0 -1
  388. package/public/docs/assets/contributor-guide_architecture_board-widgets_plan-advisor.md.RlzvUmNm.js +0 -1
  389. package/public/docs/assets/contributor-guide_architecture_board-widgets_visual-system-and-templating.md.DYgUpIJB.js +0 -1
  390. package/public/docs/assets/contributor-guide_architecture_board-widgets_visual-system-and-templating.md.DYgUpIJB.lean.js +0 -1
  391. package/public/docs/assets/contributor-guide_architecture_detector-contract.md.wj6Et6UD.js +0 -1
  392. package/public/docs/assets/contributor-guide_architecture_detector-contract_plan-attribution.md.yNex4bys.js +0 -1
  393. package/public/docs/assets/contributor-guide_architecture_detector-contract_plan-attribution.md.yNex4bys.lean.js +0 -1
  394. package/public/docs/assets/contributor-guide_architecture_detector-contract_threshold-tables.md.CKjWG56Y.js +0 -1
  395. package/public/docs/assets/contributor-guide_architecture_drill-down_plan-graph.md.DwOozIEs.js +0 -1
  396. package/public/docs/assets/contributor-guide_architecture_impact-estimation.md.CZv_ZGOp.js +0 -1
  397. package/public/docs/assets/contributor-guide_architecture_impact-estimation_caveats-tuning-and-coverage.md.BUucRc0A.js +0 -1
  398. package/public/docs/assets/contributor-guide_architecture_impact-estimation_stage-union-rollup.md.DdCGtAGu.js +0 -1
  399. package/public/docs/assets/contributor-guide_architecture_impact-estimation_stage-union-rollup.md.DdCGtAGu.lean.js +0 -1
  400. package/public/docs/assets/contributor-guide_architecture_overview.md.C1sSvm9i.js +0 -1
  401. package/public/docs/assets/contributor-guide_architecture_state-and-history_run-comparison-internals.md.CZA0JLtV.js +0 -1
  402. package/public/docs/assets/contributor-guide_architecture_widget-rendering.md.BOZ1azXG.js +0 -1
  403. package/public/docs/assets/contributor-guide_architecture_widget-rendering_findings-tab.md.BQXycK6G.js +0 -1
  404. package/public/docs/assets/contributor-guide_architecture_widget-rendering_findings-tab.md.BQXycK6G.lean.js +0 -1
  405. package/public/docs/assets/contributor-guide_architecture_worker-protocol.md.BAnhi2-d.lean.js +0 -1
  406. package/public/docs/assets/contributor-guide_architecture_worker-protocol_cli-and-mcp.md.DC1YqXBp.js +0 -1
  407. package/public/docs/assets/contributor-guide_architecture_worker-protocol_evidence-report.md.DVGZOWvW.js +0 -1
  408. package/public/docs/assets/contributor-guide_contributing.md.CQMvGwFt.js +0 -1
  409. package/public/docs/assets/contributor-guide_development-setup.md.D9bu4j_c.lean.js +0 -1
  410. package/public/docs/assets/contributor-guide_testing.md.By6XGR9a.js +0 -1
  411. package/public/docs/assets/inter-italic-cyrillic-ext.r48I6akx.woff2 +0 -0
  412. package/public/docs/assets/inter-italic-cyrillic.By2_1cv3.woff2 +0 -0
  413. package/public/docs/assets/inter-italic-greek-ext.1u6EdAuj.woff2 +0 -0
  414. package/public/docs/assets/inter-italic-greek.DJ8dCoTZ.woff2 +0 -0
  415. package/public/docs/assets/inter-italic-latin-ext.CN1xVJS-.woff2 +0 -0
  416. package/public/docs/assets/inter-italic-latin.C2AdPX0b.woff2 +0 -0
  417. package/public/docs/assets/inter-italic-vietnamese.BSbpV94h.woff2 +0 -0
  418. package/public/docs/assets/inter-roman-cyrillic-ext.BBPuwvHQ.woff2 +0 -0
  419. package/public/docs/assets/inter-roman-cyrillic.C5lxZ8CY.woff2 +0 -0
  420. package/public/docs/assets/inter-roman-greek-ext.CqjqNYQ-.woff2 +0 -0
  421. package/public/docs/assets/inter-roman-greek.BBVDIX6e.woff2 +0 -0
  422. package/public/docs/assets/inter-roman-latin-ext.4ZJIpNVo.woff2 +0 -0
  423. package/public/docs/assets/inter-roman-latin.Di8DUHzh.woff2 +0 -0
  424. package/public/docs/assets/inter-roman-vietnamese.BjW4sHH5.woff2 +0 -0
  425. package/public/docs/assets/style.tmDhD3c8.css +0 -1
  426. package/public/docs/assets/user-guide_getting-started_ci-and-automation.md.OUQqw3mI.js +0 -23
  427. package/public/docs/assets/user-guide_getting-started_ci-and-automation.md.OUQqw3mI.lean.js +0 -1
  428. package/public/docs/assets/user-guide_getting-started_reading-the-dashboard.md.Obf3W3__.js +0 -1
  429. package/public/docs/assets/user-guide_mcp-tools_compare-runs.md.Cc_gLoix.lean.js +0 -1
  430. package/public/docs/assets/user-guide_mcp-tools_diagnose-run.md.BP1vnHA5.js +0 -23
  431. package/public/docs/assets/user-guide_run-comparison.md.BUALkohi.js +0 -1
  432. package/public/docs/assets/user-guide_run-comparison.md.BUALkohi.lean.js +0 -1
  433. package/public/docs/assets/user-guide_understanding-findings.md.C9YRruMT.js +0 -1
  434. package/public/docs/assets/user-guide_understanding-findings.md.C9YRruMT.lean.js +0 -1
  435. /package/public/docs/assets/{contributor-guide_architecture_board-widgets_caching-and-memory.md.8bH1HnZp.lean.js → contributor-guide_architecture_board-widgets_caching-and-memory.md.BYDo3ClR.lean.js} +0 -0
  436. /package/public/docs/assets/{contributor-guide_architecture_board-widgets_plan-advisor.md.RlzvUmNm.lean.js → contributor-guide_architecture_board-widgets_plan-advisor.md.ajUAVdbc.lean.js} +0 -0
  437. /package/public/docs/assets/{contributor-guide_architecture_overview.md.C1sSvm9i.lean.js → contributor-guide_architecture_overview.md.nxkpOhgf.lean.js} +0 -0
  438. /package/public/docs/assets/{contributor-guide_architecture_widget-rendering.md.BOZ1azXG.lean.js → contributor-guide_architecture_widget-rendering.md.BrSz8Ezh.lean.js} +0 -0
  439. /package/public/docs/assets/{contributor-guide_architecture_widget-rendering_list-sort-mode.md.BuHKgH0C.lean.js → contributor-guide_architecture_widget-rendering_list-sort-mode.md.37hcZJ7q.lean.js} +0 -0
  440. /package/public/docs/assets/{contributor-guide_architecture_widget-rendering_row-expand-contract.md.ZT89u9f1.lean.js → contributor-guide_architecture_widget-rendering_row-expand-contract.md.mK_VmAWk.lean.js} +0 -0
  441. /package/public/docs/assets/{contributor-guide_architecture_worker-protocol_core-and-event-validation.md.DSVFPpWb.lean.js → contributor-guide_architecture_worker-protocol_core-and-event-validation.md.DVSXn-bb.lean.js} +0 -0
  442. /package/public/docs/assets/{contributor-guide_contributing.md.CQMvGwFt.lean.js → contributor-guide_contributing.md.DBW4drtZ.lean.js} +0 -0
  443. /package/public/docs/assets/{user-guide_getting-started_reading-the-dashboard.md.Obf3W3__.lean.js → user-guide_getting-started_reading-the-dashboard.md.CGaxPX_1.lean.js} +0 -0
  444. /package/public/docs/assets/{user-guide_mcp-tools.md.C65SjWUL.lean.js → user-guide_mcp-tools.md.49r3L2YE.lean.js} +0 -0
  445. /package/public/docs/assets/{user-guide_mcp-tools_get-run-summary.md.DpxZ4ZNp.lean.js → user-guide_mcp-tools_get-run-summary.md.EhaIsele.lean.js} +0 -0
@@ -10,16 +10,27 @@
10
10
 
11
11
 
12
12
 
13
- /** One concrete change a finding's fix makes, alongside its prose `recommendation`. Only a Spark
14
- * property the detector already names; `suggested` is null when it computes no value. Sizes carry a
15
- * Spark unit suffix ("384m"), counts are plain numbers, switches are booleans. */
16
-
13
+ /** One concrete change a finding's fix makes, alongside its prose `recommendation`. Entries are
14
+ * applied together unless the recommendation words them as alternatives ("either ... or"), as an
15
+ * idle-capacity finding does with dynamic allocation off: then a consumer applies one. */
16
+
17
+
18
+ /** A Spark property the detector already names; `suggested` is null when it computes no value.
19
+ * Sizes carry a Spark unit suffix ("384m"), counts are plain numbers, switches are booleans. */
20
+
17
21
 
18
22
 
19
23
 
20
24
 
21
25
 
22
26
 
27
+ /** A fix no Spark property makes: the job's code or data has to change. `hint` is the same
28
+ * wording the finding's `recommendation` gives. */
29
+
30
+
31
+
32
+
33
+
23
34
  // The columns every finding carries, whatever its detector.
24
35
 
25
36
 
@@ -77,12 +88,20 @@
77
88
 
78
89
 
79
90
 
80
- // ── Per-stage detectors ─────────────────────────────────────────────────────
81
-
82
91
  /** What a skewed stage reads, which decides the fix: 'shuffleJoin' (a shuffle feeding a join, where
83
92
  * AQE skew-join handling applies), 'inputScan' (uneven input files) or 'other'. */
84
93
 
85
94
 
95
+ /** What AQE skew-join handling did for a 'shuffleJoin' stage, read from the final plan and the
96
+ * effective conf: 'split' (it split the skewed partition, so the rest is not join skew),
97
+ * 'evenReads' (the shuffle reads are even, so no partition is skewed for AQE to split),
98
+ * 'belowThreshold' (the partition is under the effective skew threshold or factor), 'planShape' (an
99
+ * operator sits between the join and its shuffle), 'userRepartition' (the shuffle is an explicit
100
+ * repartition), 'joinType' (the join type does not let AQE split the skewed side),
101
+ * 'extraShuffle' (splitting would add a shuffle for the operator above the join) or 'notSplit'
102
+ * (nothing in the log explains it). */
103
+
104
+
86
105
  /** What a stage reads, by the dominant side: a shuffle, input files, or neither. */
87
106
 
88
107
 
@@ -92,8 +111,23 @@
92
111
  * enough, so the stage's own repartition(n) or RDD parallelism is). */
93
112
 
94
113
 
114
+ /** Why a stage's slow tail is slow (attributeTail in stage-quantiles.ts). 'data': the slow tasks
115
+ * read far more than the median task, so run time follows data volume. 'gc', 'fetchWait' and
116
+ * 'host': the tail's extra time is GC, shuffle fetch wait, or tasks piled on one host.
117
+ * 'unexplained': the slow tasks read no more than the median and none of those accounts for their
118
+ * time. 'unattributed': the stage has no data volume to compare and what data, GC, fetch wait and
119
+ * host do not explain is the largest share (or the stage has no tail attribution), so only the
120
+ * duration is known. */
121
+
122
+
95
123
 
96
124
 
125
+
126
+
127
+
128
+
129
+
130
+
97
131
 
98
132
 
99
133
 
@@ -112,8 +146,9 @@
112
146
 
113
147
 
114
148
 
115
-
149
+
116
150
 
151
+
117
152
 
118
153
 
119
154
 
@@ -144,6 +179,10 @@
144
179
 
145
180
 
146
181
 
182
+
183
+
184
+
185
+
147
186
 
148
187
 
149
188
 
@@ -174,11 +213,23 @@
174
213
 
175
214
 
176
215
 
177
-
216
+
217
+
178
218
 
179
219
 
180
-
220
+
221
+
181
222
 
223
+
224
+
225
+
226
+
227
+
228
+
229
+
230
+
231
+
232
+
182
233
 
183
234
 
184
235
 
@@ -200,8 +251,6 @@
200
251
 
201
252
 
202
253
 
203
-
204
- // ── App-level detectors ─────────────────────────────────────────────────────
205
254
 
206
255
 
207
256
  // valueText is always 'missing': the ApplicationEnd event the log lacks.
@@ -214,35 +263,38 @@
214
263
 
215
264
 
216
265
 
217
-
266
+
218
267
 
219
268
 
220
269
 
221
-
222
-
270
+
271
+
223
272
 
224
273
 
225
274
 
275
+
226
276
 
227
277
 
228
278
 
229
279
 
230
-
231
-
280
+
281
+
282
+
232
283
 
233
-
284
+
234
285
 
235
286
 
236
287
 
237
288
 
238
289
 
239
-
240
-
290
+
291
+
241
292
 
242
-
243
-
244
-
293
+
245
294
 
295
+
296
+
297
+
246
298
 
247
299
 
248
300
 
@@ -293,17 +345,13 @@
293
345
 
294
346
 
295
347
 
296
-
297
- // ── Config-scope detectors ──────────────────────────────────────────────────
298
348
 
299
349
 
300
350
 
301
351
 
302
- // valueText is the audited property's current value, or a note that it is unset or inverted.
352
+ // valueText is the audited property's current value, or a note that it is unset.
303
353
 
304
354
 
305
- // ── SQL-scope (Plan Advisor) detectors ──────────────────────────────────────
306
-
307
355
 
308
356
 
309
357
 
@@ -333,13 +381,41 @@
333
381
 
334
382
 
335
383
 
336
- /** How the effective spark.sql.autoBroadcastJoinThreshold relates to the finding: 'limits' (the
384
+
385
+
386
+
387
+
388
+
389
+
390
+
391
+
392
+
393
+ /** A BroadcastNestedLoopJoin or CartesianProduct whose output is far larger than both inputs.
394
+ * `nodeName` is the operator, `joinType` the Spark join type (null when the plan line has none)
395
+ * and `condition` the join condition with expression ids removed (null for a join without one).
396
+ * `leftRows` and `rightRows` are the input row counts the executors reported, null for a
397
+ * CartesianProduct, which re-reads its inputs so their counts are not row counts. */
398
+
399
+
400
+
401
+
402
+
403
+
404
+
405
+
406
+
407
+
408
+ /** How the effective broadcast threshold (spark.sql.autoBroadcastJoinThreshold, or its adaptive counterpart under AQE) relates to the finding: 'limits' (the
337
409
  * property decided it, or is unknown), 'notLimiting' (already admits, or already below, the
338
410
  * broadcast, so something else decided it) or 'disabled' (-1). */
339
411
 
340
412
 
341
413
 
414
+
342
415
 
416
+
417
+
418
+
343
419
 
344
420
 
345
421
 
@@ -349,8 +425,6 @@
349
425
 
350
426
 
351
427
 
352
- // ── Unions ──────────────────────────────────────────────────────────────────
353
-
354
428
  /** Public evidence fields per finding type: what a report row's `evidence` carries. */
355
429
 
356
430
 
@@ -379,6 +453,8 @@
379
453
 
380
454
 
381
455
 
456
+
457
+
382
458
 
383
459
 
384
460
 
@@ -410,6 +486,8 @@
410
486
 
411
487
 
412
488
 
489
+
490
+
413
491
 
414
492
 
415
493
 
@@ -14,9 +14,9 @@ const BOTTLENECK_WIDGET = {
14
14
  coldStart: 'executor-timeline', utilization: 'executor-timeline', speculationWaste: 'executor-timeline',
15
15
  } ;
16
16
 
17
- // Cross-widget stage recurrence: how many distinct board widgets (skew+straggler on one stage
18
- // still count as one, task-skew) flag a stage. Computed once from the full catalog each widget
19
- // already receives.
17
+ // Cross-widget stage recurrence: how many distinct widget groups (skew, slowHost and straggler
18
+ // share task-skew) flag a stage. No production code calls it, and the group names in
19
+ // BOTTLENECK_WIDGET are labels, not ids of rendered widgets.
20
20
  // `stageId` may be number|null|undefined: sql/config-scope findings never set it; `stageId == null`
21
21
  // below treats both the same.
22
22
  export function stageWidgetFrequency(catalog ) {
@@ -69,9 +69,7 @@ export function formatStageIdsLabel(stageIds , maxShown = DEFAU
69
69
  }
70
70
 
71
71
  /** Worst (lowest IMPACT_BAND_ORDER) impact band across findings, undefined when empty. Shared by
72
- * every widget that badges/colors a group of findings.
73
- * @param {{ impactBand: 'critical' | 'warning' | 'info' }[]} findings
74
- * @returns {'critical' | 'warning' | 'info' | undefined} */
72
+ * every widget that badges/colors a group of findings. */
75
73
  export function worstImpactBand(
76
74
  findings ,
77
75
  ) {
@@ -285,15 +283,16 @@ export function formatRawWaste(rawWaste ) {
285
283
  }
286
284
  }
287
285
 
288
- // formatRawWaste/fmtMs round to a fixed precision (one decimal place, or
289
- // whole milliseconds below 1s), which can collapse a small but genuinely
290
- // nonzero value down to a formatted string that reads exactly like zero
291
- // (0.04 coreHours -> "0.0 core-h"). Checking the raw value against 0 misses
292
- // this; checking the *formatted* text against zero's own formatted text
293
- // catches it regardless of unit. The fractional group must consume the
294
- // entire decimal part (all zeros) before the terminator: otherwise a real
295
- // value like "0.5 core-h" leaves the "." unconsumed, and the terminator
296
- // char class excludes ".", so it correctly fails to match.
286
+ /** A cost-only figure as core time. Task time summed over tasks (`ms`) is core time, and printing
287
+ * it as a duration beside wall-clock savings reads as run time it does not shorten. */
288
+ export function asCoreTime(rawWaste ) {
289
+ return rawWaste.unit === 'ms' ? { ...rawWaste, unit: 'coreMs' } : rawWaste;
290
+ }
291
+
292
+ // True when a formatted figure reads as zero, including a small nonzero value the fixed rounding
293
+ // collapsed (0.04 coreHours -> "0.0 core-h"). It tests the formatted text, so it holds for any unit.
294
+ // The fractional group must consume the whole decimal part before the terminator, so "0.5 core-h"
295
+ // does not match.
297
296
  export function readsAsZero(formatted ) {
298
297
  return /^0(\.0+)?(?:[^0-9.]|$)/.test(formatted);
299
298
  }
@@ -25,7 +25,7 @@ export function buildHtmlExportData(
25
25
  skippedLines ,
26
26
  { redact, buildId, producer } ,
27
27
  ) {
28
- const raw = { appModel, catalog, configFindings: auditConfig(appModel.app) };
28
+ const raw = { appModel, catalog, configFindings: auditConfig(appModel.app, appModel.stages) };
29
29
  const run = redact ? redactRunModel(raw.appModel, raw.catalog, raw.configFindings) : raw;
30
30
  const interpretation = interpretRun(run.appModel, run.catalog, run.configFindings);
31
31
  const provenance = { coreVersion: CORE_VERSION, buildId, producer };
@@ -1,8 +1,8 @@
1
1
 
2
2
 
3
3
  // The run-wide noise floor, as a share of the run's duration, that grades every wall-clock
4
- // estimate (NOT SOURCED: our own, unvalidated). skew and straggler default their firing floors to
5
- // these same figures (detectors.ts), so a finding they admit grades at least warning here.
4
+ // estimate. skew and straggler default their firing floors to these same figures (detectors.ts), so
5
+ // a finding they admit grades at least warning here. Source status: threshold-tables.md.
6
6
  export const IMPACT_FLOOR_PCT_WARN = 0.005;
7
7
  export const IMPACT_FLOOR_PCT_CRIT = 0.02;
8
8
 
@@ -1,18 +1,33 @@
1
1
  // Savings figures as every surface prints them: the dashboard's widgets and verdict, and the
2
2
  // CLI/MCP evidence report. One formatter set, so units and rounding never drift between paths.
3
- import { fmtMs, formatRawWaste, formatWallClockRange, readsAsZero } from './format-utils.js';
3
+ // A figure that rounds to zero ("0s", "0.0 core-h") reads as a measured nothing, so every
4
+ // formatter here shows no figure for it (see readsAsZero in format-utils.ts).
5
+ import { asCoreTime, fmtMs, formatRawWaste, formatWallClockRange, readsAsZero } from './format-utils.js';
4
6
 
5
7
 
8
+ /** The raw figure as the surfaces print it: a cost-only (`resourceOnly`) task-time figure in core
9
+ * time, anything else as the detector emitted it. `rawWaste` itself stays untouched. */
10
+ function shownRawWaste(estimate ) {
11
+ const rawWaste = estimate.rawWaste;
12
+ return rawWaste && estimate.basis === 'resourceOnly' ? asCoreTime(rawWaste) : rawWaste;
13
+ }
14
+
15
+ /** " (modeled)" after a cost-only figure that rests on an assumed constant, so a modeled core
16
+ * time never reads as a measured one. Empty for any other estimate. */
17
+ function certaintyNote(estimate ) {
18
+ return estimate.basis === 'resourceOnly' && estimate.estimateMethod === 'modeled' ? ' (modeled)' : '';
19
+ }
20
+
6
21
  /** A finding's one-line savings figure: the wall-clock range for a time-based
7
22
  * finding, the raw resource figure for a `resourceOnly` one, or nothing for a
8
- * purely informational estimate or a raw figure that rounds to zero ("0.0
9
- * core-h" reads as a measured nothing). */
23
+ * purely informational estimate. */
10
24
  export function impactFigure(finding ) {
11
25
  const estimate = finding.impactEstimate;
12
26
  if (!estimate) return null;
13
27
  if (estimate.wallClock) return formatWallClockRange(estimate.wallClock.low, estimate.wallClock.high);
14
- if (estimate.rawWaste) {
15
- const text = formatRawWaste(estimate.rawWaste);
28
+ const rawWaste = shownRawWaste(estimate);
29
+ if (rawWaste) {
30
+ const text = formatRawWaste(rawWaste);
16
31
  return readsAsZero(text) ? null : text;
17
32
  }
18
33
  return null;
@@ -25,7 +40,7 @@ export function rawWasteMeaning(rawWaste )
25
40
  case 'mbSeconds': return 'of unused executor memory';
26
41
  case 'coreHours':
27
42
  case 'coreMs': return rawWaste.idle ? 'of idle core capacity' : 'of core time';
28
- case 'bytes': return 'of extra data written';
43
+ case 'bytes': return rawWaste.reread ? 'of input read by the repeated scans' : 'of extra data written';
29
44
  case 'ms': return 'of task time';
30
45
  default: return null;
31
46
  }
@@ -40,30 +55,34 @@ export function savingsMeaning(finding ) {
40
55
  const estimate = finding.impactEstimate;
41
56
  if (!estimate) return null;
42
57
  if (estimate.wallClock) return 'of run time';
43
- return rawWasteMeaning(estimate.rawWaste);
58
+ const meaning = rawWasteMeaning(estimate.rawWaste);
59
+ return meaning && `${meaning}${certaintyNote(estimate)}`;
44
60
  }
45
61
 
46
62
  /** A finding's "Potential savings" figure as the widget board shows it: the
47
63
  * wall-clock range, or the raw waste only when there is no wall-clock claim,
48
64
  * never both (they would read as two competing numbers). A zero-value
49
- * estimate is suppressed like an informational one: "0s" reads as a measured
50
- * figure. `meaning` says what the shown figure counts. */
65
+ * estimate is suppressed like an informational one. `meaning` says what the
66
+ * shown figure counts. */
51
67
  export function impactEstimateFigure(estimate ) {
52
68
  if (!estimate) return null;
53
69
  const highText = estimate.wallClock && estimate.wallClock.high > 0 ? fmtMs(estimate.wallClock.high) : null;
54
70
  if (highText && !readsAsZero(highText)) {
55
71
  return { text: formatWallClockRange(estimate.wallClock .low, estimate.wallClock .high), meaning: 'of run time' };
56
72
  }
57
- const rawWasteText = estimate.rawWaste && estimate.rawWaste.value > 0 ? formatRawWaste(estimate.rawWaste) : null;
58
- if (rawWasteText && !readsAsZero(rawWasteText)) return { text: rawWasteText, meaning: rawWasteMeaning(estimate.rawWaste) };
73
+ const rawWaste = shownRawWaste(estimate);
74
+ const rawWasteText = rawWaste && rawWaste.value > 0 ? formatRawWaste(rawWaste) : null;
75
+ if (rawWasteText && !readsAsZero(rawWasteText)) {
76
+ const meaning = rawWasteMeaning(estimate.rawWaste);
77
+ return { text: rawWasteText, meaning: meaning && `${meaning}${certaintyNote(estimate)}` };
78
+ }
59
79
  return null;
60
80
  }
61
81
 
62
82
  /** Compact single-value form for dense lists (the stage table's finding chips,
63
83
  * the stage dialog): the high-end wall-clock figure, or the raw-waste figure
64
84
  * when there's no wall-clock claim, or `null` for a purely informational or a
65
- * zero-value estimate (a `0s` in the spot a real estimate goes would read as a
66
- * measured nothing). */
85
+ * zero-value estimate. */
67
86
  export function impactEstimateCompact(estimate ) {
68
87
  if (!estimate) return null;
69
88
  if (estimate.wallClock) {
@@ -71,10 +90,11 @@ export function impactEstimateCompact(estimate )
71
90
  const text = fmtMs(estimate.wallClock.high);
72
91
  return readsAsZero(text) ? null : text;
73
92
  }
74
- if (estimate.rawWaste) {
75
- if (estimate.rawWaste.value <= 0) return null;
76
- const text = formatRawWaste(estimate.rawWaste);
77
- return readsAsZero(text) ? null : text;
93
+ const rawWaste = shownRawWaste(estimate);
94
+ if (rawWaste) {
95
+ if (rawWaste.value <= 0) return null;
96
+ const text = formatRawWaste(rawWaste);
97
+ return readsAsZero(text) ? null : `${text}${certaintyNote(estimate)}`;
78
98
  }
79
99
  return null;
80
100
  }
@@ -88,14 +108,22 @@ export function impactEstimateCompact(estimate )
88
108
  * formatting and zero rules as the step's own savings figure, which it does
89
109
  * not repeat: the step already shows it. */
90
110
  export function estimateProvenance(finding ) {
111
+ const sentence = provenanceSentence(finding);
112
+ const assumptions = finding.impactEstimate?.assumptions;
113
+ if (!sentence || !assumptions) return sentence;
114
+ return `${sentence} ${assumptions[0].toUpperCase()}${assumptions.slice(1)}.`;
115
+ }
116
+
117
+ function provenanceSentence(finding ) {
91
118
  const estimate = finding.impactEstimate;
92
119
  if (!estimate || estimate.estimateMethod === 'none') return null;
93
120
  const method = `${estimate.estimateMethod[0].toUpperCase()}${estimate.estimateMethod.slice(1)}`;
94
- const rawWaste = estimate.rawWaste && estimate.rawWaste.value > 0 ? estimate.rawWaste : null;
121
+ const shown = shownRawWaste(estimate);
122
+ const rawWaste = shown && shown.value > 0 ? shown : null;
95
123
  const raw = rawWaste && !readsAsZero(formatRawWaste(rawWaste)) ? formatRawWaste(rawWaste) : null;
96
124
  const wallClock = estimate.wallClock;
97
125
  if (estimate.basis === 'resourceOnly') {
98
- return raw ? `${method}; ${raw} wasted, which may not shorten the run.` : null;
126
+ return raw ? `${method}; ${raw} ${rawWasteMeaning(estimate.rawWaste) ?? 'wasted'}, which may not shorten the run.` : null;
99
127
  }
100
128
  if (!wallClock || wallClock.high <= 0) return null;
101
129
  const highText = formatWallClockRange(wallClock.high, wallClock.high);
@@ -19,6 +19,10 @@ import {
19
19
 
20
20
 
21
21
 
22
+
23
+
24
+
25
+
22
26
 
23
27
 
24
28
  // Assumed shuffle-network throughput per executor link, ~1 Gbps. Starting assumption, unvalidated.
@@ -43,10 +47,8 @@ export function measuredTaskOverhead(stage )
43
47
 
44
48
  // Both constants above are single-device figures (one NIC, one local disk). A stage's shuffle
45
49
  // reads and spills are spread over every executor that ran its tasks, each moving its own share
46
- // in parallel, so the stage's aggregate bandwidth scales with that executor count. Dividing a
47
- // stage-wide byte total by one device's bandwidth modeled the whole cluster as one link: on 14
48
- // real logs that claimed up to 1,870s of shuffle time on stages whose tasks measured ~0s of
49
- // shuffle fetch wait (222 of 284 shuffle findings). No executor data falls back to one device.
50
+ // in parallel, so the stage's aggregate bandwidth scales with that executor count. No executor
51
+ // data falls back to one device.
50
52
  export function stageIoParallelism(stage ) {
51
53
  const executors = Array.isArray(stage.executorStats) ? stage.executorStats.length : 0;
52
54
  return Math.max(1, executors);
@@ -55,9 +57,7 @@ export function stageIoParallelism(stage ) {
55
57
  // Wall-clock the stage's tasks spent blocked fetching shuffle blocks: fetchWaitTime is a
56
58
  // cross-task sum like executorRunTime, so dividing by the stage's average concurrency converts it
57
59
  // (the gc estimate's conversion). Null when the stage has no run time or duration to convert with.
58
- // On 14 real logs the link model claimed 2780s over 284 shuffle findings, 256s once capped at
59
- // this, with about zero fetch wait on 5 of the 10 non-info ones: reads that overlapped compute
60
- // stalled nothing.
60
+ // The link model caps at this because reads that overlap compute stall nothing.
61
61
  export function fetchWaitWallClockMs(stage ) {
62
62
  const fetchWaitMs = stage.fetchWaitTime;
63
63
  const runTimeMs = stage.executorRunTime ?? 0;
@@ -66,10 +66,9 @@ export function fetchWaitWallClockMs(stage ) {
66
66
  return fetchWaitMs / (runTimeMs / durationMs);
67
67
  }
68
68
 
69
- // Wall-clock a stage's wasted (retried) attempts cost it. Each one delayed only its own task, and
70
- // attempts of different tasks ran side by side: one lost executor fails every task it was running
71
- // at once (4 wasted attempts of 36.6s each, all first attempts, on a real stage that ran 41 tasks
72
- // at once, claimed as 146.6s). So the stage lost at most its longest retry chain, the most attempts
69
+ // Wall-clock a stage's wasted (retried) attempts cost it. Each one delays only its own task, and
70
+ // attempts of different tasks run side by side: one lost executor fails every task it was running
71
+ // at once. So the stage loses at most its longest retry chain, the most attempts
73
72
  // one task wasted (its highest attempt number + 1) times the mean wasted attempt, or their summed
74
73
  // time spread over its slots, whichever is larger. Without a sample of every wasted attempt
75
74
  // (retryTaskSamples is capped), the chain isn't known: the summed time.
@@ -99,10 +98,8 @@ export const EXECUTOR_STARTUP_OVERHEAD_MS = 15000;
99
98
  // Assumed re-read throughput, shared by cachingOpportunity and cacheUtilization.
100
99
  export const RE_READ_THROUGHPUT_BPS = 125_000_000;
101
100
 
102
- // Below this share of executorRunTime spent on CPU, a stage's tasks were idle, waiting on something
103
- // outside Spark: on 14 real logs (2026-09-23) every non-Python stage under 1% was a JDBC read, a
104
- // file listing or a Delta log read, while file writes, which more partitions do parallelize,
105
- // start at 2%.
101
+ // Below this share of executorRunTime spent on CPU, a stage's tasks are idle, waiting on something
102
+ // outside Spark (rationale: impact-estimation/caveats-tuning-and-coverage.md, Idle CPU share).
106
103
  const IDLE_CPU_SHARE_MAX = 0.01;
107
104
 
108
105
  // True when the stage's tasks spent under IDLE_CPU_SHARE_MAX of their run time on CPU. False when
@@ -118,8 +115,8 @@ export function tasksMostlyIdle(stage , sql = n
118
115
  return cpuMs / runMs < IDLE_CPU_SHARE_MAX;
119
116
  }
120
117
 
121
- // skew, straggler and stageSlowness claim time off the stage's longest task itself, so the
122
- // occupancy clip must not floor them at that same task (see estimateSingleStage).
118
+ // skew, straggler, stageSlowness and lowShuffleParallelism claim time off the stage's longest task
119
+ // itself, so the occupancy clip must not floor them at that same task (see estimateSingleStage).
123
120
  export const TAIL_CLAIM = { shortensLongestTask: true };
124
121
 
125
122
  // No quantifiable magnitude -> 'informational'; a rawWaste figure with no stage window ->
@@ -130,6 +127,20 @@ export function costOnly(estimateMethod , rawWaste
130
127
  : { basis: 'informational', wallClock: null, estimateMethod };
131
128
  }
132
129
 
130
+ /** The estimate with what its model assumes and leaves out (`ImpactEstimate.assumptions`). */
131
+ export function withAssumptions(estimate , assumptions ) {
132
+ return { ...estimate, assumptions };
133
+ }
134
+
135
+ /** The throughput assumption behind a per-executor I/O model (stageIoParallelism), in the words
136
+ * `ImpactEstimate.assumptions` carries: the rate and how many executors it was spread over. */
137
+ export function ioModelAssumption(bytesPerSecond , stage ) {
138
+ const executors = Array.isArray(stage.executorStats) ? stage.executorStats.length : 0;
139
+ const rate = `${Math.round(bytesPerSecond / 1e6)} MB/s`;
140
+ if (executors === 0) return `assumes ${rate} on one device, as the stage has no per-executor data`;
141
+ return `assumes ${rate} per executor over ${executors} ${executors === 1 ? 'executor' : 'executors'}`;
142
+ }
143
+
133
144
  /** The estimate() of an entry whose findings have no waste model at all. */
134
145
  export function noWasteModel() {
135
146
  return costOnly('none');
@@ -1,10 +1,10 @@
1
- // §8 Concurrent-job-group reliability guard. Groups jobs by SQL
2
- // execution id (jobs with none form singleton groups). If two DIFFERENT groups' intervals overlap,
3
- // wall-clock-based estimates become unreliable. Jobs WITHIN a group overlapping (AQE) is normal.
1
+ // Concurrent-job-group reliability guard. Groups jobs by SQL execution id (jobs with none form
2
+ // singleton groups). If two DIFFERENT groups' intervals overlap, wall-clock-based estimates become
3
+ // unreliable. Jobs WITHIN a group overlapping (AQE) is normal.
4
4
  export function checkConcurrentJobGroups(jobs ) {
5
5
  const list = jobs ? [...jobs.values()] : [];
6
6
  // Build one interval per group: [min submission, max completion].
7
- const groups = new Map(); // key -> { start, end }
7
+ const groups = new Map();
8
8
  let singletonSeq = 0;
9
9
  for (const j of list) {
10
10
  if (j.submissionTime == null || j.completionTime == null) continue;