repro-surgeon 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 (111) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/CODE_OF_CONDUCT.md +7 -0
  3. package/CONTRIBUTING.md +31 -0
  4. package/LICENSE +21 -0
  5. package/README.md +159 -0
  6. package/SECURITY.md +15 -0
  7. package/dist/cli.d.ts +3 -0
  8. package/dist/cli.js +165 -0
  9. package/dist/cli.js.map +1 -0
  10. package/dist/config.d.ts +3 -0
  11. package/dist/config.js +177 -0
  12. package/dist/config.js.map +1 -0
  13. package/dist/dependencies.d.ts +37 -0
  14. package/dist/dependencies.js +237 -0
  15. package/dist/dependencies.js.map +1 -0
  16. package/dist/engine.d.ts +25 -0
  17. package/dist/engine.js +327 -0
  18. package/dist/engine.js.map +1 -0
  19. package/dist/export.d.ts +7 -0
  20. package/dist/export.js +520 -0
  21. package/dist/export.js.map +1 -0
  22. package/dist/graph.d.ts +3 -0
  23. package/dist/graph.js +247 -0
  24. package/dist/graph.js.map +1 -0
  25. package/dist/index.d.ts +7 -0
  26. package/dist/index.js +7 -0
  27. package/dist/index.js.map +1 -0
  28. package/dist/oracle.d.ts +2 -0
  29. package/dist/oracle.js +81 -0
  30. package/dist/oracle.js.map +1 -0
  31. package/dist/protection.d.ts +2 -0
  32. package/dist/protection.js +6 -0
  33. package/dist/protection.js.map +1 -0
  34. package/dist/report.d.ts +5 -0
  35. package/dist/report.js +539 -0
  36. package/dist/report.js.map +1 -0
  37. package/dist/runner.d.ts +3 -0
  38. package/dist/runner.js +195 -0
  39. package/dist/runner.js.map +1 -0
  40. package/dist/snapshot.d.ts +11 -0
  41. package/dist/snapshot.js +220 -0
  42. package/dist/snapshot.js.map +1 -0
  43. package/dist/state.d.ts +9 -0
  44. package/dist/state.js +143 -0
  45. package/dist/state.js.map +1 -0
  46. package/dist/transforms.d.ts +3 -0
  47. package/dist/transforms.js +188 -0
  48. package/dist/transforms.js.map +1 -0
  49. package/dist/types.d.ts +207 -0
  50. package/dist/types.js +2 -0
  51. package/dist/types.js.map +1 -0
  52. package/docs/architecture.md +91 -0
  53. package/docs/assets/report.png +0 -0
  54. package/docs/configuration.md +73 -0
  55. package/docs/evidence/dependency-removal.json +109 -0
  56. package/docs/evidence/next-frameworks.json +271 -0
  57. package/docs/evidence/next-pages.json +152 -0
  58. package/docs/evidence/rounding.json +46 -0
  59. package/docs/report-surface.md +22 -0
  60. package/docs/troubleshooting.md +47 -0
  61. package/docs/validation.md +103 -0
  62. package/examples/next-container/README.md +7 -0
  63. package/examples/next-container/app/about/page.jsx +1 -0
  64. package/examples/next-container/app/case.css +5 -0
  65. package/examples/next-container/app/layout.jsx +3 -0
  66. package/examples/next-container/app/page.jsx +4 -0
  67. package/examples/next-container/lib/catalog.js +2 -0
  68. package/examples/next-container/next.config.mjs +1 -0
  69. package/examples/next-container/package-lock.json +952 -0
  70. package/examples/next-container/package.json +13 -0
  71. package/examples/next-container/repro-surgeon.json +37 -0
  72. package/examples/next-css-bom/README.md +7 -0
  73. package/examples/next-css-bom/app/about/page.jsx +1 -0
  74. package/examples/next-css-bom/app/case.css +3 -0
  75. package/examples/next-css-bom/app/layout.jsx +3 -0
  76. package/examples/next-css-bom/app/page.jsx +4 -0
  77. package/examples/next-css-bom/lib/catalog.js +2 -0
  78. package/examples/next-css-bom/next.config.mjs +1 -0
  79. package/examples/next-css-bom/package-lock.json +952 -0
  80. package/examples/next-css-bom/package.json +13 -0
  81. package/examples/next-css-bom/repro-surgeon.json +36 -0
  82. package/examples/next-pages/README.md +14 -0
  83. package/examples/next-pages/lib/unused-catalog.js +5 -0
  84. package/examples/next-pages/next.config.mjs +1 -0
  85. package/examples/next-pages/package-lock.json +952 -0
  86. package/examples/next-pages/package.json +11 -0
  87. package/examples/next-pages/pages/health.jsx +3 -0
  88. package/examples/next-pages/pages/index.jsx +9 -0
  89. package/examples/next-pages/repro-surgeon.json +18 -0
  90. package/examples/next-root-param/README.md +7 -0
  91. package/examples/next-root-param/app/[lang-country]/about/page.jsx +1 -0
  92. package/examples/next-root-param/app/[lang-country]/layout.tsx +4 -0
  93. package/examples/next-root-param/app/[lang-country]/page.tsx +3 -0
  94. package/examples/next-root-param/lib/catalog.js +2 -0
  95. package/examples/next-root-param/next-env.d.ts +2 -0
  96. package/examples/next-root-param/next.config.mjs +1 -0
  97. package/examples/next-root-param/package-lock.json +1016 -0
  98. package/examples/next-root-param/package.json +19 -0
  99. package/examples/next-root-param/repro-surgeon.json +37 -0
  100. package/examples/next-root-param/tsconfig.json +35 -0
  101. package/examples/rounding/README.md +16 -0
  102. package/examples/rounding/check.mjs +6 -0
  103. package/examples/rounding/config/store.json +7 -0
  104. package/examples/rounding/fixtures/invoice.json +11 -0
  105. package/examples/rounding/package-lock.json +7 -0
  106. package/examples/rounding/package.json +7 -0
  107. package/examples/rounding/repro-surgeon.json +12 -0
  108. package/examples/rounding/src/catalog.mjs +9 -0
  109. package/examples/rounding/src/shipping.mjs +7 -0
  110. package/examples/rounding/src/totals.mjs +11 -0
  111. package/package.json +29 -0
package/dist/report.js ADDED
@@ -0,0 +1,539 @@
1
+ import { mkdir, writeFile } from 'node:fs/promises';
2
+ import { join } from 'node:path';
3
+ /** Public evidence omits raw execution diagnostics and private setup errors. */
4
+ export function sanitizeReport(report) {
5
+ return {
6
+ ...report,
7
+ stopReason: report.status === 'failed' ? 'The run failed. Inspect the private checkpoint and logs for details.' : report.stopReason,
8
+ trials: report.trials.map(trial => ({ ...trial, diagnostics: [], reason: trial.status === 'invalid' ? 'Evaluation was invalid; details are in the private run logs.' : trial.reason })),
9
+ verification: { ...report.verification, reason: report.verification.status === 'failed' ? 'Fresh verification failed. Inspect the private checkpoint and logs for details.' : report.verification.reason },
10
+ };
11
+ }
12
+ function escapeHtml(value) {
13
+ return String(value)
14
+ .replaceAll('&', '&')
15
+ .replaceAll('<', '&lt;')
16
+ .replaceAll('>', '&gt;')
17
+ .replaceAll('"', '&quot;')
18
+ .replaceAll("'", '&#39;');
19
+ }
20
+ function finite(value) {
21
+ return Number.isFinite(value) ? Math.max(0, value) : 0;
22
+ }
23
+ function formatBytes(value) {
24
+ const bytes = finite(value);
25
+ if (bytes < 1_000)
26
+ return `${Math.round(bytes)} B`;
27
+ if (bytes < 1_000_000)
28
+ return `${Number((bytes / 1_000).toFixed(1))} kB`;
29
+ return `${Number((bytes / 1_000_000).toFixed(1))} MB`;
30
+ }
31
+ function formatDuration(value) {
32
+ const milliseconds = finite(value);
33
+ if (milliseconds < 1_000)
34
+ return `${Math.round(milliseconds)} ms`;
35
+ const seconds = milliseconds / 1_000;
36
+ if (seconds < 60)
37
+ return `${seconds.toFixed(seconds < 10 ? 1 : 0)} s`;
38
+ const minutes = Math.floor(seconds / 60);
39
+ const remainder = Math.round(seconds % 60);
40
+ return remainder === 0 ? `${minutes} min` : `${minutes} min ${remainder} s`;
41
+ }
42
+ function formatDate(value) {
43
+ const date = new Date(value);
44
+ if (Number.isNaN(date.getTime()))
45
+ return value;
46
+ return new Intl.DateTimeFormat('en', {
47
+ dateStyle: 'medium',
48
+ timeStyle: 'short',
49
+ timeZone: 'UTC',
50
+ }).format(date) + ' UTC';
51
+ }
52
+ function shellArgument(value) {
53
+ if (/^[A-Za-z0-9_./:@%+=,-]+$/.test(value))
54
+ return value;
55
+ return `'${value.replaceAll("'", `'"'"'`)}'`;
56
+ }
57
+ function shellCommand(command) {
58
+ return command.map(shellArgument).join(' ');
59
+ }
60
+ function reductionPercent(initial, current) {
61
+ const before = finite(initial.sourceBytes);
62
+ const after = finite(current.sourceBytes);
63
+ if (before === 0 || after >= before)
64
+ return 0;
65
+ return Math.round(((before - after) / before) * 100);
66
+ }
67
+ function runState(status) {
68
+ const labels = {
69
+ calibrating: 'Calibrating baseline',
70
+ reducing: 'Reduction in progress',
71
+ paused: 'Run paused',
72
+ verifying: 'Fresh verification in progress',
73
+ complete: 'Run complete',
74
+ failed: 'Run failed',
75
+ };
76
+ const tone = status === 'complete' ? 'positive' : status === 'failed' ? 'negative' : 'attention';
77
+ return { label: labels[status], tone };
78
+ }
79
+ function verificationState(report) {
80
+ if (report.verification.status === 'verified') {
81
+ return { title: 'Fresh verification passed', tone: 'positive', routeLabel: 'Verified' };
82
+ }
83
+ if (report.verification.status === 'failed') {
84
+ return { title: 'Fresh verification failed', tone: 'negative', routeLabel: 'Failed' };
85
+ }
86
+ return { title: 'Fresh verification pending', tone: 'attention', routeLabel: 'Pending' };
87
+ }
88
+ function metricPair(label, before, after, formatter = String) {
89
+ return `<div class="measure-pair">
90
+ <dt>${escapeHtml(label)}</dt>
91
+ <dd><span>${escapeHtml(formatter(before))}</span><span class="measure-arrow" aria-hidden="true">→</span><strong>${escapeHtml(formatter(after))}</strong></dd>
92
+ </div>`;
93
+ }
94
+ function trialState(trial) {
95
+ if (trial.accepted)
96
+ return 'accepted';
97
+ return trial.status === 'invalid' ? 'invalid' : 'rejected';
98
+ }
99
+ function renderTrial(trial) {
100
+ const state = trialState(trial);
101
+ const pathList = trial.paths.length
102
+ ? trial.paths.map((path) => `<code>${escapeHtml(path)}</code>`).join('<span aria-hidden="true"> · </span>')
103
+ : '<span>Whole snapshot</span>';
104
+ return `<article class="trial" data-trial-entry data-trial-state="${state}">
105
+ <div class="trial-line">
106
+ <span class="trial-index">${escapeHtml(trial.index)}</span>
107
+ <div class="trial-main">
108
+ <div class="trial-title-row">
109
+ <h3>${escapeHtml(trial.description)}</h3>
110
+ <span class="state-label state-${state}">${state}</span>
111
+ </div>
112
+ <p class="trial-paths">${pathList}</p>
113
+ </div>
114
+ <div class="trial-measure"><strong>${formatBytes(trial.after.sourceBytes)}</strong><span>${formatDuration(trial.durationMs)}</span></div>
115
+ </div>
116
+ <details class="trial-detail">
117
+ <summary>Inspect decision</summary>
118
+ <div class="trial-detail-grid">
119
+ <div><span>Decision</span><strong>${escapeHtml(trial.reason)}</strong></div>
120
+ <div><span>Failure observation</span><strong>${escapeHtml(trial.status)}</strong></div>
121
+ <div><span>Confirmations</span><strong>${escapeHtml(trial.confirmations)}</strong></div>
122
+ <div><span>Candidate</span><code>${escapeHtml(trial.candidateHash)}</code></div>
123
+ <div><span>Source change</span><strong>${formatBytes(trial.before.sourceBytes)} → ${formatBytes(trial.after.sourceBytes)}</strong></div>
124
+ <div><span>Files</span><strong>${escapeHtml(trial.before.files)} → ${escapeHtml(trial.after.files)}</strong></div>
125
+ </div>
126
+ <div class="diagnostics"><h4>Execution privacy</h4><p class="empty-note">Raw execution output is not embedded in this report.</p></div>
127
+ </details>
128
+ </article>`;
129
+ }
130
+ function renderFiles(report) {
131
+ if (report.files.length === 0)
132
+ return '<p class="empty-note" id="file-list">No retained files recorded.</p>';
133
+ const largest = Math.max(1, ...report.files.map((file) => finite(file.bytes)));
134
+ return `<ol class="file-list" id="file-list">
135
+ ${report.files.map((file) => {
136
+ const width = Math.max(2, Math.round((finite(file.bytes) / largest) * 100));
137
+ return `<li data-file-entry>
138
+ <div class="file-row"><code>${escapeHtml(file.path)}</code><span>${formatBytes(file.bytes)}</span></div>
139
+ <span class="file-bar" style="--file-width:${width}%" aria-hidden="true"></span>
140
+ </li>`;
141
+ }).join('')}
142
+ </ol>`;
143
+ }
144
+ function renderReview(report) {
145
+ const findings = report.reviewFindings.map((finding) => `<li>
146
+ <span class="finding-kind">${escapeHtml(finding.kind)}</span>
147
+ <div><code>${escapeHtml(finding.path)}</code><p>${escapeHtml(finding.message)}</p></div>
148
+ </li>`).join('');
149
+ const warnings = report.warnings.map((warning) => `<li>${escapeHtml(warning)}</li>`).join('');
150
+ const excluded = report.excluded.map((item) => `<li><code>${escapeHtml(item.path)}</code><span>${escapeHtml(item.reason)}</span></li>`).join('');
151
+ if (!findings && !warnings && !excluded) {
152
+ return '<p class="empty-note">No review findings, warnings, or excluded paths recorded.</p>';
153
+ }
154
+ return `${findings ? `<h3>Review findings</h3><ul class="finding-list">${findings}</ul>` : ''}
155
+ ${warnings ? `<h3>Warnings</h3><ul class="plain-list">${warnings}</ul>` : ''}
156
+ ${excluded ? `<h3>Excluded from source inventory</h3><ul class="excluded-list">${excluded}</ul>` : ''}`;
157
+ }
158
+ function reportScript() {
159
+ return `<script>
160
+ (() => {
161
+ const trialSearch = document.querySelector('#trial-search');
162
+ const trialEntries = [...document.querySelectorAll('[data-trial-entry]')];
163
+ const trialButtons = [...document.querySelectorAll('[data-trial-filter]')];
164
+ const trialCount = document.querySelector('#trial-count');
165
+
166
+ const updateTrials = () => {
167
+ const query = (trialSearch?.value || '').trim().toLocaleLowerCase();
168
+ const enabled = new Set(trialButtons.filter((button) => button.getAttribute('aria-pressed') === 'true').map((button) => button.dataset.trialFilter));
169
+ let visible = 0;
170
+ for (const entry of trialEntries) {
171
+ const matchesState = enabled.has(entry.dataset.trialState);
172
+ const matchesQuery = !query || (entry.textContent || '').toLocaleLowerCase().includes(query);
173
+ entry.hidden = !(matchesState && matchesQuery);
174
+ if (!entry.hidden) visible += 1;
175
+ }
176
+ if (trialCount) trialCount.textContent = visible + (visible === 1 ? ' trial shown' : ' trials shown');
177
+ };
178
+
179
+ trialSearch?.addEventListener('input', updateTrials);
180
+ for (const button of trialButtons) {
181
+ button.addEventListener('click', () => {
182
+ button.setAttribute('aria-pressed', button.getAttribute('aria-pressed') === 'true' ? 'false' : 'true');
183
+ updateTrials();
184
+ });
185
+ }
186
+ updateTrials();
187
+
188
+ const fileSearch = document.querySelector('#file-search');
189
+ const fileEntries = [...document.querySelectorAll('[data-file-entry]')];
190
+ const fileCount = document.querySelector('#file-count');
191
+ const updateFiles = () => {
192
+ const query = (fileSearch?.value || '').trim().toLocaleLowerCase();
193
+ let visible = 0;
194
+ for (const entry of fileEntries) {
195
+ entry.hidden = Boolean(query) && !(entry.textContent || '').toLocaleLowerCase().includes(query);
196
+ if (!entry.hidden) visible += 1;
197
+ }
198
+ if (fileCount) fileCount.textContent = visible + (visible === 1 ? ' file shown' : ' files shown');
199
+ };
200
+ fileSearch?.addEventListener('input', updateFiles);
201
+ updateFiles();
202
+
203
+ const copyButton = document.querySelector('[data-copy-command]');
204
+ const copyStatus = document.querySelector('#copy-status');
205
+ copyButton?.addEventListener('click', async () => {
206
+ const command = copyButton.getAttribute('data-copy-command') || '';
207
+ let copied = false;
208
+ try {
209
+ if (navigator.clipboard?.writeText) {
210
+ await navigator.clipboard.writeText(command);
211
+ copied = true;
212
+ }
213
+ } catch {}
214
+ if (!copied) {
215
+ const field = document.createElement('textarea');
216
+ field.value = command;
217
+ field.setAttribute('readonly', '');
218
+ field.className = 'copy-fallback';
219
+ document.body.append(field);
220
+ field.select();
221
+ copied = document.execCommand('copy');
222
+ field.remove();
223
+ }
224
+ if (copyStatus) copyStatus.textContent = copied ? 'Command copied.' : 'Copy failed. Select the command manually.';
225
+ });
226
+ })();
227
+ </script>`;
228
+ }
229
+ export function renderReport(report) {
230
+ report = sanitizeReport(report);
231
+ const verification = verificationState(report);
232
+ const state = runState(report.status);
233
+ const command = shellCommand(report.command);
234
+ const accepted = report.trials.filter((trial) => trial.accepted).length;
235
+ const discarded = report.trials.filter((trial) => !trial.accepted).length;
236
+ const invalid = report.trials.filter((trial) => trial.status === 'invalid').length;
237
+ const percent = reductionPercent(report.initial, report.current);
238
+ const noReduction = percent === 0 && report.initial.files <= report.current.files;
239
+ const baselineRoute = !report.baseline
240
+ ? 'Not recorded'
241
+ : `${report.baseline.completed >= report.baseline.required ? 'Established' : 'Incomplete'} (${report.baseline.completed}/${report.baseline.required})`;
242
+ const reductionRoute = report.trials.length === 0
243
+ ? 'No trials'
244
+ : report.status === 'reducing'
245
+ ? 'In progress'
246
+ : `${accepted} accepted`;
247
+ const branchMarkup = discarded > 0
248
+ ? `<p class="branch-summary"><span aria-hidden="true"></span><strong>${discarded}</strong> discarded branches</p>`
249
+ : '<p class="branch-empty">No discarded trial branches</p>';
250
+ const trials = report.trials.length
251
+ ? report.trials.map(renderTrial).join('')
252
+ : '<p class="empty-note">No trials recorded.</p>';
253
+ return `<!doctype html>
254
+ <html lang="en">
255
+ <head>
256
+ <meta charset="utf-8">
257
+ <meta name="viewport" content="width=device-width, initial-scale=1">
258
+ <meta name="color-scheme" content="light">
259
+ <title>${escapeHtml(report.name)} · Repro Surgeon evidence</title>
260
+ <style>
261
+ :root { color-scheme: light; --paper:#f4f0e5; --paper-deep:#e9e2d2; --ink:#17211e; --muted:#59625d; --line:#a8afa7; --line-strong:#59645e; --signal:#006a62; --signal-soft:#d6e6df; --danger:#923b2f; --danger-soft:#f0dcd4; --amber:#805c12; --amber-soft:#eee0b7; --white:#fffdf7; --radius:4px; --measure:74ch; }
262
+ * { box-sizing:border-box; }
263
+ html { background:var(--paper-deep); color:var(--ink); font-family:ui-sans-serif,-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif; font-size:16px; line-height:1.5; }
264
+ body { margin:0; min-width:320px; }
265
+ button,input,summary { font:inherit; }
266
+ button { color:inherit; }
267
+ code,.measure-pair dd,.trial-index,.state-label,.run-meta,.masthead,.route-node strong,.file-row span { font-family:ui-monospace,SFMono-Regular,Consolas,"Liberation Mono",monospace; }
268
+ code { overflow-wrap:anywhere; }
269
+ a { color:inherit; }
270
+ [hidden] { display:none !important; }
271
+ .skip-link { position:fixed; inset:8px auto auto 8px; z-index:20; padding:8px 12px; background:var(--ink); color:var(--white); transform:translateY(-160%); }
272
+ .skip-link:focus { transform:none; }
273
+ :focus-visible { outline:3px solid var(--signal); outline-offset:3px; }
274
+ .sheet { width:min(1180px,calc(100% - 32px)); margin:24px auto 64px; background:var(--paper); border:1px solid var(--line-strong); box-shadow:0 18px 46px rgba(23,33,30,.13); }
275
+ .masthead { display:flex; justify-content:space-between; align-items:flex-start; gap:24px; padding:12px 28px; border-bottom:3px solid var(--ink); font-size:.72rem; font-weight:700; letter-spacing:.06em; text-transform:uppercase; }
276
+ .masthead span:first-child { flex:0 0 auto; }
277
+ .masthead span:last-child { min-width:0; text-align:right; overflow-wrap:anywhere; }
278
+ .opening { display:grid; grid-template-columns:minmax(0,1.45fr) minmax(300px,.8fr); border-bottom:1px solid var(--line-strong); }
279
+ .opening-copy { padding:42px 44px 38px; }
280
+ h1,h2,h3,h4,p { margin-top:0; }
281
+ h1 { max-width:15ch; margin-bottom:16px; font-size:clamp(2.45rem,6vw,5.4rem); line-height:.94; letter-spacing:-.035em; font-weight:760; text-wrap:balance; }
282
+ .lede { max-width:var(--measure); margin:0; color:var(--muted); font-size:1.03rem; }
283
+ .verification { padding:38px 32px; background:var(--ink); color:var(--white); }
284
+ .verification h2 { max-width:13ch; margin-bottom:18px; font-size:clamp(1.65rem,3vw,2.6rem); line-height:1.06; letter-spacing:-.025em; }
285
+ .verification p { max-width:44ch; color:#dbe2de; }
286
+ .verification .status-stamp { display:inline-flex; align-items:center; gap:9px; margin-bottom:26px; padding:5px 9px; border:1px solid currentColor; border-radius:999px; font:700 .75rem/1 ui-monospace,SFMono-Regular,monospace; letter-spacing:.04em; text-transform:uppercase; }
287
+ .verification .status-stamp::before { content:""; width:9px; height:9px; border-radius:50%; background:currentColor; }
288
+ .verification .tone-positive { color:#87ddc7; }
289
+ .verification .tone-negative { color:#ff9c88; }
290
+ .verification .tone-attention { color:#f2cf70; }
291
+ .verification dl { display:grid; grid-template-columns:1fr 1fr; gap:16px; margin:26px 0 0; }
292
+ .verification dt { color:#aeb9b4; font-size:.75rem; text-transform:uppercase; letter-spacing:.06em; }
293
+ .verification dd { margin:3px 0 0; font-weight:700; }
294
+ .evidence-route { padding:30px 44px 34px; border-bottom:1px solid var(--line-strong); }
295
+ .route-track { display:grid; grid-template-columns:repeat(3,minmax(0,1fr)); position:relative; margin-top:2px; }
296
+ .route-track::before { content:""; position:absolute; top:13px; left:16.6%; right:16.6%; height:2px; background:var(--line-strong); }
297
+ .route-node { min-width:0; position:relative; z-index:1; text-align:center; }
298
+ .route-node::before { content:""; display:block; width:20px; height:20px; margin:3px auto 10px; border:5px solid var(--paper); outline:2px solid var(--line-strong); border-radius:50%; background:var(--signal); }
299
+ .route-node.route-pending::before { background:var(--amber-soft); }
300
+ .route-node.route-failed::before { background:var(--danger); }
301
+ .route-node span { display:block; color:var(--muted); font-size:.78rem; }
302
+ .route-node strong,.route-node span { overflow-wrap:anywhere; }
303
+ .route-node strong { font-size:.85rem; }
304
+ .branch-summary { display:flex; justify-content:center; align-items:center; gap:5px; min-width:0; margin:6px 4px 0; color:var(--muted); font-size:.7rem; line-height:1.25; }
305
+ .branch-summary span { flex:0 0 12px; width:12px; height:8px; border-left:1px solid var(--line-strong); border-bottom:1px solid var(--line-strong); transform:skewX(-28deg); }
306
+ .branch-summary strong { color:var(--danger); font-size:inherit; }
307
+ .branch-empty { margin:5px 0 0; color:var(--muted); font-size:.7rem; }
308
+ .result { display:grid; grid-template-columns:minmax(0,1.15fr) minmax(300px,.85fr); border-bottom:1px solid var(--line-strong); }
309
+ .result-main { padding:42px 44px; }
310
+ .result h2,.section-heading h2,.review h2 { margin-bottom:18px; font-size:clamp(1.65rem,3vw,2.55rem); line-height:1.05; letter-spacing:-.025em; }
311
+ .result-verdict { margin-bottom:30px; font-size:1rem; color:var(--muted); }
312
+ .reduction-number { display:flex; align-items:baseline; gap:12px; margin:0 0 22px; }
313
+ .reduction-number strong { font-size:clamp(3.6rem,8vw,7rem); line-height:.82; letter-spacing:-.04em; }
314
+ .reduction-number span { font-weight:720; max-width:12ch; line-height:1.1; }
315
+ .measure-list { display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); border-top:1px solid var(--line); border-left:1px solid var(--line); margin:0; }
316
+ .measure-pair { padding:14px 16px; border-right:1px solid var(--line); border-bottom:1px solid var(--line); }
317
+ .measure-pair dt { color:var(--muted); font-size:.75rem; text-transform:uppercase; letter-spacing:.06em; }
318
+ .measure-pair dd { display:flex; align-items:center; gap:8px; margin:5px 0 0; font-size:.9rem; }
319
+ .measure-pair dd span:first-child { color:var(--muted); text-decoration:line-through; text-decoration-thickness:1px; }
320
+ .measure-arrow { color:var(--signal); }
321
+ .result-aside { padding:42px 32px; border-left:1px solid var(--line-strong); }
322
+ .result-aside h3,.review h3 { margin:28px 0 10px; font-size:1rem; }
323
+ .result-aside h3:first-child,.review h3:first-child { margin-top:0; }
324
+ .command-line { display:flex; align-items:stretch; background:var(--white); border:1px solid var(--line-strong); }
325
+ .command-line code { flex:1; padding:12px 14px; white-space:pre-wrap; }
326
+ .copy-button { min-width:84px; min-height:44px; border:0; border-left:1px solid var(--line-strong); background:var(--signal); color:white; font-weight:750; cursor:pointer; }
327
+ .copy-button:hover { background:#00564f; }
328
+ .copy-status { min-height:1.5em; margin:6px 0 0; color:var(--muted); font-size:.78rem; }
329
+ .oracle-grid { display:grid; gap:12px; }
330
+ .oracle-grid div { border-top:1px solid var(--line); padding-top:9px; }
331
+ .oracle-grid span { display:block; color:var(--muted); font-size:.75rem; text-transform:uppercase; letter-spacing:.05em; }
332
+ .oracle-grid strong,.oracle-grid code { display:block; margin-top:3px; }
333
+ .section { padding:42px 44px 48px; border-bottom:1px solid var(--line-strong); }
334
+ .section-heading { display:flex; align-items:end; justify-content:space-between; gap:20px; margin-bottom:22px; }
335
+ .section-heading h2 { margin-bottom:0; }
336
+ .section-heading p { max-width:48ch; margin-bottom:2px; color:var(--muted); }
337
+ .controls { display:flex; flex-wrap:wrap; align-items:end; gap:10px; padding:14px 0 18px; border-top:1px solid var(--line); border-bottom:1px solid var(--line); }
338
+ .search-field { flex:1 1 260px; }
339
+ .search-field label { display:block; margin-bottom:5px; color:var(--muted); font-size:.78rem; font-weight:700; }
340
+ .search-field input { width:100%; min-height:44px; padding:8px 11px; background:var(--white); border:1px solid var(--line-strong); border-radius:0; color:var(--ink); }
341
+ .filter-group { display:flex; flex-wrap:wrap; gap:6px; }
342
+ .filter-button { min-height:44px; padding:7px 11px; border:1px solid var(--line-strong); background:transparent; cursor:pointer; }
343
+ .filter-button[aria-pressed="true"] { background:var(--ink); color:var(--white); }
344
+ .count-status { min-width:104px; margin:0 0 10px; color:var(--muted); font-size:.78rem; text-align:right; }
345
+ .trial-list { border-bottom:1px solid var(--line); }
346
+ .trial { border-top:1px solid var(--line); }
347
+ .trial-line { display:grid; grid-template-columns:42px minmax(0,1fr) 110px; align-items:start; gap:14px; padding:17px 0; }
348
+ .trial-index { display:grid; place-items:center; width:34px; height:34px; border:1px solid var(--line-strong); font-weight:700; }
349
+ .trial-title-row { display:flex; align-items:start; justify-content:space-between; gap:12px; }
350
+ .trial-title-row h3 { margin:1px 0 4px; font-size:1rem; }
351
+ .state-label { flex:none; padding:3px 7px; border:1px solid currentColor; border-radius:999px; font-size:.68rem; font-weight:800; text-transform:uppercase; }
352
+ .state-accepted { color:var(--signal); }
353
+ .state-rejected { color:var(--danger); }
354
+ .state-invalid { color:var(--amber); }
355
+ .trial-paths { margin:0; color:var(--muted); font-size:.8rem; }
356
+ .trial-measure { text-align:right; }
357
+ .trial-measure span { display:block; color:var(--muted); font-size:.75rem; }
358
+ .trial-detail { margin:0 0 16px 56px; border:1px solid var(--line); background:var(--white); }
359
+ .trial-detail summary { display:flex; align-items:center; min-height:44px; padding:9px 12px; cursor:pointer; font-weight:720; }
360
+ .trial-detail[open] summary { border-bottom:1px solid var(--line); }
361
+ .trial-detail-grid { display:grid; grid-template-columns:repeat(3,minmax(0,1fr)); }
362
+ .trial-detail-grid div { min-height:76px; padding:11px 12px; border-right:1px solid var(--line); border-bottom:1px solid var(--line); }
363
+ .trial-detail-grid div:nth-child(3n) { border-right:0; }
364
+ .trial-detail-grid span { display:block; color:var(--muted); font-size:.72rem; text-transform:uppercase; letter-spacing:.04em; }
365
+ .trial-detail-grid strong,.trial-detail-grid code { display:block; margin-top:5px; font-size:.82rem; }
366
+ .diagnostics { padding:12px; }
367
+ .diagnostics h4 { margin-bottom:6px; }
368
+ .files-layout { display:grid; grid-template-columns:minmax(0,1.35fr) minmax(260px,.65fr); gap:40px; }
369
+ .file-list { margin:0; padding:0; list-style:none; border-top:1px solid var(--line); }
370
+ .file-list li { padding:11px 0; border-bottom:1px solid var(--line); }
371
+ .file-row { display:flex; justify-content:space-between; gap:20px; font-size:.84rem; }
372
+ .file-bar { display:block; width:var(--file-width); height:3px; margin-top:8px; background:var(--signal); }
373
+ .run-meta { margin:0; }
374
+ .run-meta div { display:grid; grid-template-columns:116px 1fr; gap:12px; padding:8px 0; border-bottom:1px solid var(--line); font-size:.78rem; }
375
+ .run-meta dt { color:var(--muted); }
376
+ .run-meta dd { margin:0; overflow-wrap:anywhere; }
377
+ .review { padding:42px 44px 48px; }
378
+ .finding-list,.excluded-list,.plain-list { margin:0; padding:0; list-style:none; }
379
+ .finding-list li { display:grid; grid-template-columns:100px 1fr; gap:16px; padding:12px 0; border-top:1px solid var(--line); }
380
+ .finding-kind { align-self:start; padding:3px 7px; background:var(--amber-soft); font:700 .7rem ui-monospace,SFMono-Regular,monospace; text-transform:uppercase; }
381
+ .finding-list p { margin:3px 0 0; color:var(--muted); }
382
+ .plain-list li,.excluded-list li { padding:9px 0; border-top:1px solid var(--line); }
383
+ .excluded-list li { display:grid; grid-template-columns:minmax(160px,.55fr) 1fr; gap:18px; }
384
+ .empty-note { padding:16px; border:1px dashed var(--line-strong); color:var(--muted); }
385
+ .footer { display:flex; justify-content:space-between; gap:24px; padding:14px 28px; border-top:3px solid var(--ink); font-size:.74rem; color:var(--muted); }
386
+ .copy-fallback { position:fixed; left:-9999px; top:0; }
387
+ .sr-only { position:absolute; width:1px; height:1px; padding:0; margin:-1px; overflow:hidden; clip:rect(0,0,0,0); white-space:nowrap; border:0; }
388
+ @media (max-width:760px) {
389
+ .sheet { width:100%; margin:0; border-width:0; box-shadow:none; }
390
+ .masthead,.footer { padding-inline:18px; }
391
+ .opening,.result,.files-layout { grid-template-columns:1fr; }
392
+ .opening-copy,.verification,.evidence-route,.result-main,.result-aside,.section,.review { padding:30px 20px; }
393
+ .result-aside { border-left:0; border-top:1px solid var(--line-strong); }
394
+ .measure-list,.trial-detail-grid { grid-template-columns:1fr; }
395
+ .trial-detail-grid div,.trial-detail-grid div:nth-child(3n) { border-right:0; }
396
+ .section-heading { display:block; }
397
+ .section-heading p { margin-top:8px; }
398
+ .trial-line { grid-template-columns:34px minmax(0,1fr); gap:10px; }
399
+ .trial-measure { grid-column:2; display:flex; gap:12px; text-align:left; }
400
+ .trial-measure span { display:inline; }
401
+ .trial-title-row { display:block; }
402
+ .state-label { display:inline-block; margin-top:6px; }
403
+ .trial-detail { margin-left:44px; }
404
+ .excluded-list li { grid-template-columns:1fr; gap:4px; }
405
+ .count-status { width:100%; text-align:left; }
406
+ }
407
+ @media (max-width:480px) {
408
+ .route-node strong { font-size:.7rem; }
409
+ .route-node span { font-size:.68rem; }
410
+ .command-line { display:block; }
411
+ .copy-button { width:100%; border-left:0; border-top:1px solid var(--line-strong); }
412
+ .file-row { display:block; }
413
+ .file-row span { display:block; margin-top:4px; }
414
+ .run-meta div { grid-template-columns:1fr; gap:2px; }
415
+ .footer { display:block; }
416
+ }
417
+ @media print {
418
+ html,body { background:white; }
419
+ .sheet { width:100%; margin:0; border:0; box-shadow:none; }
420
+ .controls,.copy-button,.copy-status,.skip-link { display:none !important; }
421
+ .trial[hidden],.file-list li[hidden] { display:block !important; }
422
+ .trial-detail { break-inside:avoid; }
423
+ }
424
+ </style>
425
+ </head>
426
+ <body>
427
+ <a class="skip-link" href="#main">Skip to run evidence</a>
428
+ <main class="sheet" id="main" data-surface="report">
429
+ <header>
430
+ <div class="masthead"><span>Repro Surgeon / run evidence</span><span>${escapeHtml(report.id)}</span></div>
431
+ <div class="opening">
432
+ <div class="opening-copy">
433
+ <h1>${escapeHtml(report.name)}</h1>
434
+ <p class="lede"><strong class="state-label state-${state.tone === 'negative' ? 'rejected' : state.tone === 'positive' ? 'accepted' : 'invalid'}">${escapeHtml(state.label)}</strong> ${escapeHtml(report.stopReason)}</p>
435
+ </div>
436
+ <section class="verification" id="verification" aria-labelledby="verification-title">
437
+ <span class="status-stamp tone-${verification.tone}">${escapeHtml(report.verification.status)}</span>
438
+ <h2 id="verification-title">${escapeHtml(verification.title)}</h2>
439
+ <p>${escapeHtml(report.verification.reason)}</p>
440
+ <dl>
441
+ <div><dt>Fresh runs</dt><dd>${escapeHtml(report.verification.runs)}</dd></div>
442
+ <div><dt>Snapshot</dt><dd><code>${escapeHtml(report.verification.snapshotHash)}</code></dd></div>
443
+ <div><dt>Environment</dt><dd>${escapeHtml(report.verification.environment)}</dd></div>
444
+ <div><dt>Created</dt><dd>${escapeHtml(formatDate(report.createdAt))}</dd></div>
445
+ </dl>
446
+ </section>
447
+ </div>
448
+ </header>
449
+
450
+ <nav class="evidence-route" aria-label="Evidence path">
451
+ <div class="route-track">
452
+ <div class="route-node"><strong>Baseline</strong><span>${escapeHtml(baselineRoute)}</span></div>
453
+ <div class="route-node"><strong>Reduction</strong><span>${escapeHtml(reductionRoute)}</span>${branchMarkup}</div>
454
+ <div class="route-node route-${report.verification.status === 'verified' ? 'verified' : report.verification.status}"><strong>Fresh verification</strong><span>${escapeHtml(verification.routeLabel)}</span></div>
455
+ </div>
456
+ </nav>
457
+
458
+ <section class="result" id="result" aria-labelledby="result-title">
459
+ <div class="result-main">
460
+ <h2 id="result-title">${noReduction ? 'No reduction accepted' : 'Reduced source, same configured failure'}</h2>
461
+ <p class="result-verdict">${accepted} accepted ${accepted === 1 ? 'change' : 'changes'} from ${report.evaluations} evaluations in ${formatDuration(report.elapsedMs)}. ${discarded} discarded; ${invalid} invalid.</p>
462
+ <p class="reduction-number"><strong>${percent}%</strong><span>less source by recorded bytes</span></p>
463
+ <dl class="measure-list">
464
+ ${metricPair('Source', report.initial.sourceBytes, report.current.sourceBytes, formatBytes)}
465
+ ${metricPair('Files', report.initial.files, report.current.files)}
466
+ ${metricPair('Total snapshot', report.initial.bytes, report.current.bytes, formatBytes)}
467
+ ${metricPair('Dependencies', report.initial.dependencies, report.current.dependencies)}
468
+ </dl>
469
+ </div>
470
+ <aside class="result-aside" aria-label="Failure contract">
471
+ <h3>Reproduction command</h3>
472
+ <div class="command-line"><code>${escapeHtml(command)}</code><button class="copy-button" type="button" data-copy-command="${escapeHtml(command)}">Copy</button></div>
473
+ <p class="copy-status" id="copy-status" role="status" aria-live="polite"></p>
474
+ <h3>Configured failure check</h3>
475
+ <div class="oracle-grid">
476
+ <div><span>Exact exit</span><strong>${escapeHtml(report.oracle.exitCode)}</strong></div>
477
+ <div><span>Required output</span>${report.oracle.allOf.map((item) => `<code>${escapeHtml(item)}</code>`).join('')}</div>
478
+ <div><span>Forbidden output</span>${report.oracle.noneOf.length ? report.oracle.noneOf.map((item) => `<code>${escapeHtml(item)}</code>`).join('') : '<strong>None configured</strong>'}</div>
479
+ </div>
480
+ </aside>
481
+ </section>
482
+
483
+ <section class="section" aria-labelledby="trials-title">
484
+ <div class="section-heading"><h2 id="trials-title">Reduction decisions</h2><p>Search and filter recorded trials. Expand any decision to inspect its evidence summary.</p></div>
485
+ <div class="controls" aria-label="Trial controls">
486
+ <div class="search-field"><label for="trial-search">Search trials</label><input id="trial-search" type="search" placeholder="Path or decision" aria-controls="trial-list"></div>
487
+ <div class="filter-group" aria-label="Trial states">
488
+ <button class="filter-button" type="button" data-trial-filter="accepted" aria-pressed="true">Accepted</button>
489
+ <button class="filter-button" type="button" data-trial-filter="rejected" aria-pressed="true">Rejected</button>
490
+ <button class="filter-button" type="button" data-trial-filter="invalid" aria-pressed="true">Invalid</button>
491
+ </div>
492
+ <p class="count-status" id="trial-count" role="status" aria-live="polite">${report.trials.length} trials shown</p>
493
+ </div>
494
+ <div class="trial-list" id="trial-list">${trials}</div>
495
+ </section>
496
+
497
+ <section class="section" aria-labelledby="files-title">
498
+ <div class="section-heading"><h2 id="files-title">Retained source</h2><p>Files remaining in the reduced snapshot. Byte bars compare retained file size within this run.</p></div>
499
+ <div class="files-layout">
500
+ <div>
501
+ <div class="controls">
502
+ <div class="search-field"><label for="file-search">Find a retained file</label><input id="file-search" type="search" placeholder="File path" aria-controls="file-list"></div>
503
+ <p class="count-status" id="file-count" role="status" aria-live="polite">${report.files.length} files shown</p>
504
+ </div>
505
+ ${renderFiles(report)}
506
+ </div>
507
+ <aside aria-label="Run metadata">
508
+ <dl class="run-meta">
509
+ <div><dt>Adapter</dt><dd>${escapeHtml(report.adapter.name)} ${escapeHtml(report.adapter.version ?? 'version not recorded')}</dd></div>
510
+ <div><dt>Router</dt><dd>${escapeHtml(report.adapter.router)}</dd></div>
511
+ <div><dt>Runtime</dt><dd>${escapeHtml(report.runtime.node)} / npm ${escapeHtml(report.runtime.npm)}</dd></div>
512
+ <div><dt>Host</dt><dd>${escapeHtml(report.runtime.platform)} / ${escapeHtml(report.runtime.arch)}</dd></div>
513
+ <div><dt>Tool</dt><dd>${escapeHtml(report.runtime.tool)}</dd></div>
514
+ <div><dt>Run ID</dt><dd>${escapeHtml(report.id)}</dd></div>
515
+ </dl>
516
+ </aside>
517
+ </div>
518
+ </section>
519
+
520
+ <section class="review" aria-labelledby="review-title">
521
+ <h2 id="review-title">Review before sharing</h2>
522
+ ${renderReview(report)}
523
+ </section>
524
+
525
+ <footer class="footer"><span>Generated locally by Repro Surgeon. No source is published by this report.</span><span>${escapeHtml(report.id)}</span></footer>
526
+ </main>
527
+ ${reportScript()}
528
+ </body>
529
+ </html>`;
530
+ }
531
+ export async function writeReport(report, directory) {
532
+ report = sanitizeReport(report);
533
+ await mkdir(directory, { recursive: true });
534
+ await Promise.all([
535
+ writeFile(join(directory, 'report.html'), renderReport(report), 'utf8'),
536
+ writeFile(join(directory, 'report.json'), `${JSON.stringify(report, null, 2)}\n`, 'utf8'),
537
+ ]);
538
+ }
539
+ //# sourceMappingURL=report.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"report.js","sourceRoot":"","sources":["../src/report.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { CommandResult, RunOptions } from './types.ts';
2
+ export declare function cleanEnvironment(home: string, names: string[]): Record<string, string>;
3
+ export declare function runCommand(command: string[], options: RunOptions): Promise<CommandResult>;