next-leak 0.12.0 → 0.12.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.
@@ -1,7 +1,8 @@
1
1
  import { createRequire as __nextLeakCreateRequire } from 'node:module';import { fileURLToPath as __nextLeakFileURLToPath } from 'node:url';import { dirname as __nextLeakDirname } from 'node:path';const require = __nextLeakCreateRequire(import.meta.url);const __filename = __nextLeakFileURLToPath(import.meta.url);const __dirname = __nextLeakDirname(__filename);
2
2
  import {
3
- effectiveVerdict
4
- } from "./chunk-4NKGNMEA.js";
3
+ effectiveVerdict,
4
+ withdrawnByDisagreement
5
+ } from "./chunk-UU4RXOZO.js";
5
6
  import {
6
7
  assessPeakPressure,
7
8
  describePeakPressure,
@@ -74,7 +75,7 @@ function measuredSection(route, parameters) {
74
75
  }
75
76
  const verdict = effectiveVerdict(route);
76
77
  const color = VERDICT_COLOR[verdict];
77
- const withdrawn = route.confidence.supersededVerdict === void 0 ? "" : `<p class="warn">Measured <strong>${route.trend.verdict}</strong>, withdrawn: the run did not observe what that verdict needs.</p>`;
78
+ const withdrawn = route.confidence.supersededVerdict === void 0 || withdrawnByDisagreement(route.confidence) ? "" : `<p class="warn">Measured <strong>${route.trend.verdict}</strong>, withdrawn: the run did not observe what that verdict needs.</p>`;
78
79
  const warnings = route.confidence.warnings.length === 0 ? "" : `<ul class="warn">${route.confidence.warnings.map((warning) => `<li>${escapeHtml(warning.detail)}</li>`).join("")}</ul>`;
79
80
  const curve = route.samples.map((sample) => (sample / MB).toFixed(1)).join(" \u2192 ");
80
81
  const findings = [...route.diff?.grownNodes ?? [], ...route.diff?.newNodes ?? []];
@@ -6,8 +6,9 @@ import {
6
6
  effectiveVerdict,
7
7
  minGrowthFor,
8
8
  resolveCycles,
9
- warrantsIssueDraft
10
- } from "./chunk-4NKGNMEA.js";
9
+ warrantsIssueDraft,
10
+ withdrawnByDisagreement
11
+ } from "./chunk-UU4RXOZO.js";
11
12
  import {
12
13
  assessPeakPressure,
13
14
  assessPressureVerdict,
@@ -95030,7 +95031,7 @@ function abandonLines(route) {
95030
95031
  }
95031
95032
  function confidenceLines(route) {
95032
95033
  const lines = [];
95033
- if (route.confidence.supersededVerdict !== void 0) {
95034
+ if (route.confidence.supersededVerdict !== void 0 && !withdrawnByDisagreement(route.confidence)) {
95034
95035
  lines.push(
95035
95036
  ` measured ${route.trend.verdict}, withdrawn: the run did not observe what that verdict needs`
95036
95037
  );
@@ -95621,7 +95622,7 @@ async function measureRoute(context, route, requestPath, index, pass = void 0) {
95621
95622
  };
95622
95623
  }
95623
95624
  async function writeEvidenceBundle(report, workDir) {
95624
- const { renderHtmlReport } = await import("./html-report-6KGPHCMA.js");
95625
+ const { renderHtmlReport } = await import("./html-report-DLKFB3IU.js");
95625
95626
  const { renderIssueMarkdown } = await import("./issue-report-OALZZLVR.js");
95626
95627
  for (const route of report.routes) {
95627
95628
  if (route.status === "measured" && warrantsIssueDraft(route)) {
@@ -121,6 +121,9 @@ function classifyMemoryTrend(heapSamples, externalSamples, options = {}) {
121
121
  }
122
122
 
123
123
  // src/confidence.ts
124
+ function withdrawnByDisagreement(confidence) {
125
+ return confidence.warnings.some((warning) => warning.code === "repetitions-disagree");
126
+ }
124
127
  var resolveCycles = (cycles) => Math.max(cycles * 2, 6);
125
128
  function effectiveVerdict(report) {
126
129
  return report.confidence.supersededVerdict ?? report.trend.verdict;
@@ -324,6 +327,7 @@ export {
324
327
  minGrowthFor,
325
328
  classifyTrend,
326
329
  classifyMemoryTrend,
330
+ withdrawnByDisagreement,
327
331
  resolveCycles,
328
332
  effectiveVerdict,
329
333
  warrantsIssueDraft,
package/dist/cli.js CHANGED
@@ -22,10 +22,10 @@ import {
22
22
  runSelfCheck,
23
23
  unregisterChild,
24
24
  validateTarget
25
- } from "./chunk-5VXBMWDN.js";
25
+ } from "./chunk-L5KWU2RU.js";
26
26
  import {
27
27
  classifyTrend
28
- } from "./chunk-4NKGNMEA.js";
28
+ } from "./chunk-UU4RXOZO.js";
29
29
  import "./chunk-E464SO7G.js";
30
30
  import "./chunk-6XYFBOL2.js";
31
31
 
@@ -55,12 +55,41 @@ export type ConfidenceReport = {
55
55
  warnings: MeasurementWarning[];
56
56
  /**
57
57
  * Verdict the evidence actually supports, when the measurement is not merely
58
- * noisy but invalid. Only ever downgrades `leak`: accusing an app of leaking
59
- * on evidence that does not hold is the expensive error — it sends someone
60
- * chasing a ghost and ends as an issue against this tool.
58
+ * noisy but invalid.
59
+ *
60
+ * Two different mechanisms set this, and they mean different things.
61
+ * `assessConfidence` sets it when a run did not observe what its own verdict
62
+ * requires, and only ever downgrades `leak`: accusing an app of leaking on
63
+ * evidence that does not hold is the expensive error — it sends someone
64
+ * chasing a ghost and ends as an issue against this tool. `aggregateRepetitions`
65
+ * sets it for *any* verdict when repetitions of the same route disagreed,
66
+ * which is not a flaw in this run at all. `withdrawnByDisagreement` below
67
+ * tells the two apart; anything that explains a withdrawal to a reader has to.
61
68
  */
62
69
  supersededVerdict?: TrendVerdict;
63
70
  };
71
+ /**
72
+ * Whether a withdrawal came from repetitions disagreeing rather than from this
73
+ * run failing its own audit.
74
+ *
75
+ * The distinction matters to anyone phrasing it. An audited withdrawal means
76
+ * the run never observed what the verdict needs — it never settled, the
77
+ * disconnects cut nothing, the deltas were too thin. A disagreement means the
78
+ * opposite: this run observed exactly what it needed, and another run of the
79
+ * same route observed something else. Telling a reader the run "did not observe
80
+ * what that verdict needs" in the second case is simply untrue, and the
81
+ * disagreement already carries its own warning naming the verdicts it produced.
82
+ *
83
+ * Both can be true of one report, and then this answers `true` and the audit's
84
+ * sentence is dropped along with the disagreement's. `aggregateRepetitions`
85
+ * keeps the winning pass's own warnings and overwrites only `supersededVerdict`,
86
+ * which both mechanisms set to `inconclusive`, so no reading is lost: the
87
+ * audit's warning still prints its own detail, which names the cause the generic
88
+ * sentence never did. Separating the two would mean carrying the winner's
89
+ * withdrawal reason through the aggregation, and it would buy the reader a
90
+ * sentence they already have in a more specific form.
91
+ */
92
+ export declare function withdrawnByDisagreement(confidence: ConfidenceReport): boolean;
64
93
  export type ConfidenceInput = {
65
94
  trend: TrendResult;
66
95
  loadOutcomes: readonly LoadOutcome[];
@@ -1,8 +1,8 @@
1
1
  import { createRequire as __nextLeakCreateRequire } from 'node:module';import { fileURLToPath as __nextLeakFileURLToPath } from 'node:url';import { dirname as __nextLeakDirname } from 'node:path';const require = __nextLeakCreateRequire(import.meta.url);const __filename = __nextLeakFileURLToPath(import.meta.url);const __dirname = __nextLeakDirname(__filename);
2
2
  import {
3
3
  renderHtmlReport
4
- } from "./chunk-7WUE3WOI.js";
5
- import "./chunk-4NKGNMEA.js";
4
+ } from "./chunk-G2777DKL.js";
5
+ import "./chunk-UU4RXOZO.js";
6
6
  import "./chunk-E464SO7G.js";
7
7
  import "./chunk-6XYFBOL2.js";
8
8
  export {
package/dist/index.js CHANGED
@@ -41,13 +41,13 @@ import {
41
41
  sourceIndexAt,
42
42
  summarizeBaseline,
43
43
  validateTarget
44
- } from "./chunk-5VXBMWDN.js";
44
+ } from "./chunk-L5KWU2RU.js";
45
45
  import {
46
46
  renderHtmlReport
47
- } from "./chunk-7WUE3WOI.js";
47
+ } from "./chunk-G2777DKL.js";
48
48
  import {
49
49
  classifyTrend
50
- } from "./chunk-4NKGNMEA.js";
50
+ } from "./chunk-UU4RXOZO.js";
51
51
  import {
52
52
  renderIssueMarkdown
53
53
  } from "./chunk-YPVBX3QA.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "next-leak",
3
- "version": "0.12.0",
3
+ "version": "0.12.1",
4
4
  "description": "Find out whether your Next.js app actually leaks memory — how much, on which route, and whose fault it is.",
5
5
  "keywords": [
6
6
  "nextjs",