flakelab 0.1.0 → 0.1.2
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.
- package/README.md +225 -38
- package/dist/analysis/blob-report.d.ts +15 -0
- package/dist/analysis/blob-report.js +137 -0
- package/dist/analysis/blob-report.js.map +1 -0
- package/dist/analysis/cli.d.ts +7 -0
- package/dist/analysis/cli.js +28 -0
- package/dist/analysis/cli.js.map +1 -0
- package/dist/analysis/schema.d.ts +175 -0
- package/dist/analysis/schema.js +34 -0
- package/dist/analysis/schema.js.map +1 -0
- package/dist/analysis/zip-archive.d.ts +6 -0
- package/dist/analysis/zip-archive.js +193 -0
- package/dist/analysis/zip-archive.js.map +1 -0
- package/dist/artifacts/paths.d.ts +3 -0
- package/dist/artifacts/paths.js +34 -0
- package/dist/artifacts/paths.js.map +1 -0
- package/dist/artifacts/retention.d.ts +1 -0
- package/dist/artifacts/retention.js +80 -0
- package/dist/artifacts/retention.js.map +1 -0
- package/dist/bisect/engine.js +0 -1
- package/dist/bisect/engine.js.map +1 -1
- package/dist/bisect/schema.d.ts +5 -6
- package/dist/bisect/schema.js +1 -2
- package/dist/bisect/schema.js.map +1 -1
- package/dist/bisect/solari-evaluator.js +9 -1
- package/dist/bisect/solari-evaluator.js.map +1 -1
- package/dist/ci/job-summary.d.ts +2 -0
- package/dist/ci/job-summary.js +120 -2
- package/dist/ci/job-summary.js.map +1 -1
- package/dist/ci/select-command.js +1 -1
- package/dist/ci/select-command.js.map +1 -1
- package/dist/ci/summary-command.js +12 -7
- package/dist/ci/summary-command.js.map +1 -1
- package/dist/cli-arguments.d.ts +44 -0
- package/dist/cli-arguments.js +356 -0
- package/dist/cli-arguments.js.map +1 -0
- package/dist/cli-command-help.d.ts +11 -0
- package/dist/cli-command-help.js +211 -0
- package/dist/cli-command-help.js.map +1 -0
- package/dist/cli-help.d.ts +5 -2
- package/dist/cli-help.js +122 -45
- package/dist/cli-help.js.map +1 -1
- package/dist/cli-option-definitions.d.ts +202 -0
- package/dist/cli-option-definitions.js +59 -0
- package/dist/cli-option-definitions.js.map +1 -0
- package/dist/cli.js +100 -100
- package/dist/cli.js.map +1 -1
- package/dist/commands/analyze-summary.d.ts +5 -0
- package/dist/commands/analyze-summary.js +89 -0
- package/dist/commands/analyze-summary.js.map +1 -0
- package/dist/commands/analyze.d.ts +6 -0
- package/dist/commands/analyze.js +128 -0
- package/dist/commands/analyze.js.map +1 -0
- package/dist/commands/bisect.d.ts +2 -2
- package/dist/commands/bisect.js +32 -3
- package/dist/commands/bisect.js.map +1 -1
- package/dist/commands/diagnose.d.ts +3 -2
- package/dist/commands/diagnose.js +355 -23
- package/dist/commands/diagnose.js.map +1 -1
- package/dist/commands/discover.d.ts +18 -2
- package/dist/commands/discover.js +215 -25
- package/dist/commands/discover.js.map +1 -1
- package/dist/commands/doctor.d.ts +2 -0
- package/dist/commands/doctor.js +66 -25
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/investigate.d.ts +3 -2
- package/dist/commands/investigate.js +22 -3
- package/dist/commands/investigate.js.map +1 -1
- package/dist/commands/options.d.ts +123 -16
- package/dist/commands/options.js +24 -2
- package/dist/commands/options.js.map +1 -1
- package/dist/commands/prove.d.ts +2 -2
- package/dist/commands/prove.js +38 -1
- package/dist/commands/prove.js.map +1 -1
- package/dist/commands/repair.d.ts +8 -2
- package/dist/commands/repair.js +32 -9
- package/dist/commands/repair.js.map +1 -1
- package/dist/commands/replay.d.ts +2 -2
- package/dist/commands/replay.js +15 -2
- package/dist/commands/replay.js.map +1 -1
- package/dist/commands/report.d.ts +2 -2
- package/dist/commands/report.js +35 -10
- package/dist/commands/report.js.map +1 -1
- package/dist/commands/scan-summary.d.ts +7 -0
- package/dist/commands/scan-summary.js +175 -0
- package/dist/commands/scan-summary.js.map +1 -0
- package/dist/commands/scan.d.ts +9 -12
- package/dist/commands/scan.js +66 -62
- package/dist/commands/scan.js.map +1 -1
- package/dist/core/plan.js +1 -1
- package/dist/core/plan.js.map +1 -1
- package/dist/diagnosis/checkpoint.d.ts +6 -0
- package/dist/diagnosis/checkpoint.js +46 -0
- package/dist/diagnosis/checkpoint.js.map +1 -0
- package/dist/diagnosis/cli.d.ts +7 -0
- package/dist/diagnosis/cli.js +84 -0
- package/dist/diagnosis/cli.js.map +1 -0
- package/dist/diagnosis/recommendation.d.ts +13 -0
- package/dist/diagnosis/recommendation.js +95 -0
- package/dist/diagnosis/recommendation.js.map +1 -0
- package/dist/diagnosis/run-state.d.ts +52 -0
- package/dist/diagnosis/run-state.js +173 -0
- package/dist/diagnosis/run-state.js.map +1 -0
- package/dist/diagnosis/schema.d.ts +207 -0
- package/dist/diagnosis/schema.js +108 -0
- package/dist/diagnosis/schema.js.map +1 -0
- package/dist/diagnosis/solari-handoff.d.ts +9 -0
- package/dist/diagnosis/solari-handoff.js +40 -0
- package/dist/diagnosis/solari-handoff.js.map +1 -0
- package/dist/diagnosis/summary.d.ts +3 -0
- package/dist/diagnosis/summary.js +115 -0
- package/dist/diagnosis/summary.js.map +1 -0
- package/dist/discovery/auth-cookie.d.ts +19 -0
- package/dist/discovery/auth-cookie.js +26 -0
- package/dist/discovery/auth-cookie.js.map +1 -0
- package/dist/discovery/evaluate.d.ts +35 -2
- package/dist/discovery/evaluate.js +136 -30
- package/dist/discovery/evaluate.js.map +1 -1
- package/dist/discovery/event-loop.d.ts +25 -0
- package/dist/discovery/event-loop.js +84 -0
- package/dist/discovery/event-loop.js.map +1 -0
- package/dist/discovery/minimize.d.ts +61 -1
- package/dist/discovery/minimize.js +179 -7
- package/dist/discovery/minimize.js.map +1 -1
- package/dist/discovery/resource-loading.d.ts +25 -0
- package/dist/discovery/resource-loading.js +84 -0
- package/dist/discovery/resource-loading.js.map +1 -0
- package/dist/discovery/runner-environment.d.ts +26 -0
- package/dist/discovery/runner-environment.js +68 -0
- package/dist/discovery/runner-environment.js.map +1 -0
- package/dist/discovery/startup-event.d.ts +25 -0
- package/dist/discovery/startup-event.js +84 -0
- package/dist/discovery/startup-event.js.map +1 -0
- package/dist/discovery/storage-state.d.ts +26 -0
- package/dist/discovery/storage-state.js +86 -0
- package/dist/discovery/storage-state.js.map +1 -0
- package/dist/discovery/temporal-environment.d.ts +31 -0
- package/dist/discovery/temporal-environment.js +43 -0
- package/dist/discovery/temporal-environment.js.map +1 -0
- package/dist/discovery/visual-environment.d.ts +28 -0
- package/dist/discovery/visual-environment.js +42 -0
- package/dist/discovery/visual-environment.js.map +1 -0
- package/dist/domain/schema.d.ts +840 -20
- package/dist/domain/schema.js +216 -6
- package/dist/domain/schema.js.map +1 -1
- package/dist/faults/browser-context.d.ts +16 -0
- package/dist/faults/browser-context.js +60 -0
- package/dist/faults/browser-context.js.map +1 -0
- package/dist/faults/cookie-header.d.ts +5 -0
- package/dist/faults/cookie-header.js +25 -0
- package/dist/faults/cookie-header.js.map +1 -0
- package/dist/faults/document-bootstrap.d.ts +5 -0
- package/dist/faults/document-bootstrap.js +141 -0
- package/dist/faults/document-bootstrap.js.map +1 -0
- package/dist/faults/install.d.ts +1 -1
- package/dist/faults/install.js +199 -6
- package/dist/faults/install.js.map +1 -1
- package/dist/faults/pattern.d.ts +1 -0
- package/dist/faults/pattern.js +24 -0
- package/dist/faults/pattern.js.map +1 -0
- package/dist/investigator/agent.js +39 -17
- package/dist/investigator/agent.js.map +1 -1
- package/dist/investigator/ledger.d.ts +1 -1
- package/dist/investigator/ledger.js +2 -2
- package/dist/investigator/ledger.js.map +1 -1
- package/dist/investigator/safe-source.d.ts +1 -0
- package/dist/investigator/safe-source.js +12 -3
- package/dist/investigator/safe-source.js.map +1 -1
- package/dist/investigator/schema.d.ts +293 -2
- package/dist/investigator/schema.js +100 -2
- package/dist/investigator/schema.js.map +1 -1
- package/dist/proof/cli.d.ts +7 -0
- package/dist/proof/cli.js +108 -0
- package/dist/proof/cli.js.map +1 -0
- package/dist/proof/preflight.d.ts +4 -0
- package/dist/proof/preflight.js +9 -0
- package/dist/proof/preflight.js.map +1 -0
- package/dist/repair/generator.d.ts +12 -1
- package/dist/repair/generator.js +30 -6
- package/dist/repair/generator.js.map +1 -1
- package/dist/repair/remote-proof-runner.js +6 -10
- package/dist/repair/remote-proof-runner.js.map +1 -1
- package/dist/repair/schema.d.ts +77 -2
- package/dist/repair/schema.js +23 -2
- package/dist/repair/schema.js.map +1 -1
- package/dist/repair/solari-validator.d.ts +2 -0
- package/dist/repair/solari-validator.js +4 -6
- package/dist/repair/solari-validator.js.map +1 -1
- package/dist/repair/summary.d.ts +10 -0
- package/dist/repair/summary.js +58 -0
- package/dist/repair/summary.js.map +1 -0
- package/dist/repair/validator.d.ts +1 -0
- package/dist/repair/validator.js +53 -12
- package/dist/repair/validator.js.map +1 -1
- package/dist/report/bundle.js +16 -37
- package/dist/report/bundle.js.map +1 -1
- package/dist/report/model.js +131 -12
- package/dist/report/model.js.map +1 -1
- package/dist/report/open.d.ts +9 -0
- package/dist/report/open.js +23 -0
- package/dist/report/open.js.map +1 -1
- package/dist/report/report-client.css +2 -0
- package/dist/report/report-client.js +58 -0
- package/dist/report/schema.d.ts +115 -5
- package/dist/report/schema.js +24 -5
- package/dist/report/schema.js.map +1 -1
- package/dist/reproducer/schema.d.ts +89 -4
- package/dist/reproducer/schema.js +3 -4
- package/dist/reproducer/schema.js.map +1 -1
- package/dist/runner/execution-fault.d.ts +10 -0
- package/dist/runner/execution-fault.js +24 -0
- package/dist/runner/execution-fault.js.map +1 -0
- package/dist/runner/fault-proxy.d.ts +7 -0
- package/dist/runner/fault-proxy.js +366 -0
- package/dist/runner/fault-proxy.js.map +1 -0
- package/dist/runner/local.js +2 -2
- package/dist/runner/local.js.map +1 -1
- package/dist/runner/native-scan.d.ts +25 -0
- package/dist/runner/native-scan.js +306 -0
- package/dist/runner/native-scan.js.map +1 -0
- package/dist/runner/playwright-executor.d.ts +3 -0
- package/dist/runner/playwright-executor.js +125 -66
- package/dist/runner/playwright-executor.js.map +1 -1
- package/dist/runner/process-tree.d.ts +7 -0
- package/dist/runner/process-tree.js +62 -0
- package/dist/runner/process-tree.js.map +1 -0
- package/dist/runner/project-bridge.d.ts +7 -0
- package/dist/runner/project-bridge.js +83 -0
- package/dist/runner/project-bridge.js.map +1 -0
- package/dist/runner/trial-reporter.d.ts +7 -0
- package/dist/runner/trial-reporter.js +47 -0
- package/dist/runner/trial-reporter.js.map +1 -0
- package/dist/scan/failure-clusters.d.ts +24 -0
- package/dist/scan/failure-clusters.js +74 -0
- package/dist/scan/failure-clusters.js.map +1 -0
- package/dist/scan/schema.d.ts +170 -0
- package/dist/scan/schema.js +71 -0
- package/dist/scan/schema.js.map +1 -0
- package/dist/solari/executor.d.ts +5 -1
- package/dist/solari/executor.js +25 -17
- package/dist/solari/executor.js.map +1 -1
- package/dist/solari/run-demo.d.ts +13 -1
- package/dist/solari/run-demo.js +35 -16
- package/dist/solari/run-demo.js.map +1 -1
- package/dist/solari/usage.d.ts +8 -2
- package/dist/solari/usage.js +14 -4
- package/dist/solari/usage.js.map +1 -1
- package/dist/ui/boundary.d.ts +17 -0
- package/dist/ui/boundary.js +18 -0
- package/dist/ui/boundary.js.map +1 -0
- package/dist/ui/console.d.ts +4 -0
- package/dist/ui/console.js +11 -0
- package/dist/ui/console.js.map +1 -0
- package/dist/ui/document.d.ts +40 -0
- package/dist/ui/document.js +120 -0
- package/dist/ui/document.js.map +1 -0
- package/dist/ui/format.d.ts +8 -0
- package/dist/ui/format.js +32 -0
- package/dist/ui/format.js.map +1 -0
- package/dist/ui/progress.d.ts +17 -1
- package/dist/ui/progress.js +51 -8
- package/dist/ui/progress.js.map +1 -1
- package/dist/ui/status.d.ts +7 -0
- package/dist/ui/status.js +36 -0
- package/dist/ui/status.js.map +1 -0
- package/dist/ui/style.d.ts +8 -0
- package/dist/ui/style.js +22 -0
- package/dist/ui/style.js.map +1 -0
- package/dist/ui/text.d.ts +17 -0
- package/dist/ui/text.js +123 -0
- package/dist/ui/text.js.map +1 -0
- package/dist/ui/theme.d.ts +23 -0
- package/dist/ui/theme.js +77 -0
- package/dist/ui/theme.js.map +1 -0
- package/dist/ui/trial-progress.d.ts +13 -0
- package/dist/ui/trial-progress.js +42 -0
- package/dist/ui/trial-progress.js.map +1 -0
- package/package.json +14 -19
- package/dist/faults/network-delay.d.ts +0 -5
- package/dist/faults/network-delay.js +0 -34
- package/dist/faults/network-delay.js.map +0 -1
- package/dist/faults/request-failure.d.ts +0 -5
- package/dist/faults/request-failure.js +0 -24
- package/dist/faults/request-failure.js.map +0 -1
- package/dist/playwright.d.ts +0 -3
- package/dist/playwright.js +0 -21
- package/dist/playwright.js.map +0 -1
- package/dist/report/browser-entry.d.ts +0 -2
- package/dist/report/browser-entry.js +0 -15
- package/dist/report/browser-entry.js.map +0 -1
- package/dist/report/components/artifacts.d.ts +0 -4
- package/dist/report/components/artifacts.js +0 -6
- package/dist/report/components/artifacts.js.map +0 -1
- package/dist/report/components/experiments.d.ts +0 -4
- package/dist/report/components/experiments.js +0 -7
- package/dist/report/components/experiments.js.map +0 -1
- package/dist/report/components/hypotheses.d.ts +0 -4
- package/dist/report/components/hypotheses.js +0 -26
- package/dist/report/components/hypotheses.js.map +0 -1
- package/dist/report/components/indicators.d.ts +0 -32
- package/dist/report/components/indicators.js +0 -42
- package/dist/report/components/indicators.js.map +0 -1
- package/dist/report/components/layout.d.ts +0 -29
- package/dist/report/components/layout.js +0 -20
- package/dist/report/components/layout.js.map +0 -1
- package/dist/report/components/proof.d.ts +0 -4
- package/dist/report/components/proof.js +0 -34
- package/dist/report/components/proof.js.map +0 -1
- package/dist/report/components/reproduction.d.ts +0 -4
- package/dist/report/components/reproduction.js +0 -19
- package/dist/report/components/reproduction.js.map +0 -1
- package/dist/report/components/summary.d.ts +0 -4
- package/dist/report/components/summary.js +0 -12
- package/dist/report/components/summary.js.map +0 -1
- package/dist/report/components/verdict.d.ts +0 -4
- package/dist/report/components/verdict.js +0 -27
- package/dist/report/components/verdict.js.map +0 -1
- package/dist/report/report-app.d.ts +0 -6
- package/dist/report/report-app.js +0 -16
- package/dist/report/report-app.js.map +0 -1
- package/dist/report/report-details.css +0 -182
- package/dist/report/report.css +0 -404
package/dist/repair/validator.js
CHANGED
|
@@ -1,34 +1,75 @@
|
|
|
1
|
-
import { readdir } from "node:fs/promises";
|
|
2
|
-
import { dirname, relative, resolve } from "node:path";
|
|
1
|
+
import { readFile, readdir } from "node:fs/promises";
|
|
2
|
+
import { dirname, join, relative, resolve } from "node:path";
|
|
3
3
|
import { evaluateExperiment } from "../discovery/evaluate.js";
|
|
4
4
|
import { createPlaywrightExecutor } from "../runner/playwright-executor.js";
|
|
5
5
|
import { proofOfFixSchema } from "./schema.js";
|
|
6
6
|
import { validatePatchInSolari } from "./solari-validator.js";
|
|
7
7
|
import { applyCandidatePatch, createPatchWorkspace } from "./workspace.js";
|
|
8
|
+
const TEST_FILE = /\.(?:spec|test)\.[cm]?[jt]sx?$/u;
|
|
9
|
+
const MAX_REGRESSION_SELECTORS = 50;
|
|
10
|
+
const SKIPPED_DIRECTORIES = new Set([".flakelab", ".git", "node_modules"]);
|
|
8
11
|
async function evaluate(root, selector, options, hostile, trials) {
|
|
9
12
|
return evaluateExperiment(createPlaywrightExecutor(root, selector, { signal: options.signal }), {
|
|
10
13
|
concurrency: options.concurrency,
|
|
11
|
-
|
|
14
|
+
faults: hostile ? options.reproducer.faults : [],
|
|
12
15
|
minimumFailureRate: options.reproducer.expectedFailure.minimumRate,
|
|
13
16
|
seed: options.reproducer.seed,
|
|
14
17
|
signal: options.signal,
|
|
15
18
|
trials,
|
|
16
19
|
});
|
|
17
20
|
}
|
|
18
|
-
async function
|
|
19
|
-
const directory = dirname(resolve(root, selectedTest));
|
|
20
|
-
const selected = resolve(root, selectedTest);
|
|
21
|
+
async function collectRegressionTests(directory, files) {
|
|
21
22
|
const entries = await readdir(directory, { withFileTypes: true });
|
|
22
|
-
|
|
23
|
-
.
|
|
24
|
-
|
|
23
|
+
for (const entry of entries) {
|
|
24
|
+
if (files.length > MAX_REGRESSION_SELECTORS) {
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
const path = join(directory, entry.name);
|
|
28
|
+
if (entry.isDirectory() && !SKIPPED_DIRECTORIES.has(entry.name)) {
|
|
29
|
+
await collectRegressionTests(path, files);
|
|
30
|
+
}
|
|
31
|
+
else if (entry.isFile() && TEST_FILE.test(entry.name)) {
|
|
32
|
+
files.push(path);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
export async function nearbyRegressionSelectors(root, selectedTest, candidate) {
|
|
37
|
+
const selected = resolve(root, selectedTest);
|
|
38
|
+
const directories = new Set([
|
|
39
|
+
dirname(selected),
|
|
40
|
+
...candidate.edits.map((edit) => dirname(resolve(root, edit.path))),
|
|
41
|
+
]);
|
|
42
|
+
const files = [];
|
|
43
|
+
for (const directory of directories) {
|
|
44
|
+
await collectRegressionTests(directory, files);
|
|
45
|
+
}
|
|
46
|
+
const selectors = [...new Set(files)]
|
|
25
47
|
.filter((path) => path !== selected)
|
|
26
|
-
.map((path) => relative(root, path).replaceAll("\\", "/"))
|
|
48
|
+
.map((path) => relative(root, path).replaceAll("\\", "/"))
|
|
49
|
+
.sort((left, right) => left.localeCompare(right));
|
|
50
|
+
if (selectors.length > MAX_REGRESSION_SELECTORS) {
|
|
51
|
+
throw new Error(`Nearby regression selection exceeds the ${MAX_REGRESSION_SELECTORS}-test safety limit`);
|
|
52
|
+
}
|
|
53
|
+
return selectors;
|
|
27
54
|
}
|
|
28
55
|
function passes(result) {
|
|
29
56
|
return result.errors === 0 && result.failed === 0 && result.passed === result.trials;
|
|
30
57
|
}
|
|
58
|
+
async function candidateSourceLocations(projectRoot, candidate) {
|
|
59
|
+
return Promise.all(candidate.edits.map(async (edit) => {
|
|
60
|
+
const content = await readFile(resolve(projectRoot, edit.path), "utf8");
|
|
61
|
+
const offset = content.indexOf(edit.before);
|
|
62
|
+
if (offset < 0) {
|
|
63
|
+
throw new Error(`Candidate source location no longer exists in ${edit.path}`);
|
|
64
|
+
}
|
|
65
|
+
return {
|
|
66
|
+
line: content.slice(0, offset).split(/\r?\n/u).length,
|
|
67
|
+
path: edit.path,
|
|
68
|
+
};
|
|
69
|
+
}));
|
|
70
|
+
}
|
|
31
71
|
export async function validateProofOfFix(options, patchPath) {
|
|
72
|
+
const sourceLocations = await candidateSourceLocations(options.projectRoot, options.candidate);
|
|
32
73
|
const beforeHostile = await evaluate(options.projectRoot, options.reproducer.test, options, true, options.reproducer.trials);
|
|
33
74
|
const signatureMatches = !options.reproducer.expectedFailure.signature
|
|
34
75
|
|| beforeHostile.dominantFailureSignature === options.reproducer.expectedFailure.signature;
|
|
@@ -38,7 +79,7 @@ export async function validateProofOfFix(options, patchPath) {
|
|
|
38
79
|
const workspace = await createPatchWorkspace(options.projectRoot);
|
|
39
80
|
try {
|
|
40
81
|
const diff = await applyCandidatePatch(workspace.root, options.candidate);
|
|
41
|
-
const regressionSelectors = await nearbyRegressionSelectors(workspace.root, options.reproducer.test);
|
|
82
|
+
const regressionSelectors = await nearbyRegressionSelectors(workspace.root, options.reproducer.test, options.candidate);
|
|
42
83
|
const remote = await validatePatchInSolari({
|
|
43
84
|
apiKey: options.apiKey,
|
|
44
85
|
baseUrl: options.baseUrl,
|
|
@@ -56,10 +97,10 @@ export async function validateProofOfFix(options, patchPath) {
|
|
|
56
97
|
return {
|
|
57
98
|
diff,
|
|
58
99
|
proof: proofOfFixSchema.parse({
|
|
59
|
-
version: 1,
|
|
60
100
|
execution: "solari-microvm",
|
|
61
101
|
patchAccepted,
|
|
62
102
|
patchPath,
|
|
103
|
+
sourceLocations,
|
|
63
104
|
staticChecks: { typecheck: remote.typecheck, lint: remote.lint },
|
|
64
105
|
staticDiagnostics: {
|
|
65
106
|
...(remote.typecheckDiagnostic
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validator.js","sourceRoot":"","sources":["../../src/repair/validator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAA;
|
|
1
|
+
{"version":3,"file":"validator.js","sourceRoot":"","sources":["../../src/repair/validator.ts"],"names":[],"mappings":"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"}
|
package/dist/report/bundle.js
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
import { build } from "vite";
|
|
2
1
|
import { existsSync } from "node:fs";
|
|
3
|
-
import { mkdir, writeFile } from "node:fs/promises";
|
|
4
|
-
import { dirname } from "node:path";
|
|
2
|
+
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
3
|
+
import { dirname, resolve } from "node:path";
|
|
5
4
|
import { fileURLToPath } from "node:url";
|
|
6
|
-
|
|
7
|
-
const
|
|
5
|
+
const CLIENT_SCRIPT = "report-client.js";
|
|
6
|
+
const CLIENT_STYLES = "report-client.css";
|
|
8
7
|
function escapeEmbeddedJson(value) {
|
|
9
8
|
return JSON.stringify(value)
|
|
10
9
|
.replaceAll("<", String.raw `\u003c`)
|
|
@@ -39,39 +38,19 @@ function htmlDocument(report, script, styles) {
|
|
|
39
38
|
</html>
|
|
40
39
|
`;
|
|
41
40
|
}
|
|
41
|
+
async function readClientAsset(projectRoot, name) {
|
|
42
|
+
const installedPath = fileURLToPath(new URL(`./${name}`, import.meta.url));
|
|
43
|
+
const assetPath = existsSync(installedPath)
|
|
44
|
+
? installedPath
|
|
45
|
+
: resolve(projectRoot, "dist", "report", name);
|
|
46
|
+
return readFile(assetPath, "utf8");
|
|
47
|
+
}
|
|
42
48
|
export async function writePortableReport(projectRoot, outputPath, report) {
|
|
43
|
-
const
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
logLevel: "silent",
|
|
48
|
-
root: projectRoot,
|
|
49
|
-
build: {
|
|
50
|
-
// Everything the report references — the Geist Mono woff2 above all — has to become a
|
|
51
|
-
// data URI, or the generated file stops working the moment it is moved.
|
|
52
|
-
assetsInlineLimit: MAX_INLINE_ASSET_BYTES,
|
|
53
|
-
cssCodeSplit: false,
|
|
54
|
-
minify: true,
|
|
55
|
-
write: false,
|
|
56
|
-
rollupOptions: {
|
|
57
|
-
input: existsSync(sourceEntry) ? sourceEntry : compiledEntry,
|
|
58
|
-
},
|
|
59
|
-
},
|
|
60
|
-
});
|
|
61
|
-
const outputs = Array.isArray(result) ? result : [result];
|
|
62
|
-
const entries = outputs.flatMap((output) => "output" in output ? output.output : []);
|
|
63
|
-
const script = entries.find((entry) => entry.type === "chunk" && entry.isEntry);
|
|
64
|
-
const stylesheet = entries.find((entry) => entry.type === "asset" && entry.fileName.endsWith(".css"));
|
|
65
|
-
if (script?.type !== "chunk") {
|
|
66
|
-
throw new Error("Vite did not produce the FlakeLab report script");
|
|
67
|
-
}
|
|
68
|
-
const detached = entries.filter((entry) => entry.type === "asset" && !entry.fileName.endsWith(".css"));
|
|
69
|
-
if (detached.length > 0) {
|
|
70
|
-
const names = detached.map((entry) => entry.fileName).join(", ");
|
|
71
|
-
throw new Error(`Report assets must be inlined to stay portable: ${names}`);
|
|
72
|
-
}
|
|
73
|
-
const styles = stylesheet?.type === "asset" ? stylesheet.source.toString() : "";
|
|
49
|
+
const [script, styles] = await Promise.all([
|
|
50
|
+
readClientAsset(projectRoot, CLIENT_SCRIPT),
|
|
51
|
+
readClientAsset(projectRoot, CLIENT_STYLES),
|
|
52
|
+
]);
|
|
74
53
|
await mkdir(dirname(outputPath), { recursive: true });
|
|
75
|
-
await writeFile(outputPath, htmlDocument(report, script
|
|
54
|
+
await writeFile(outputPath, htmlDocument(report, script, styles), "utf8");
|
|
76
55
|
}
|
|
77
56
|
//# sourceMappingURL=bundle.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bundle.js","sourceRoot":"","sources":["../../src/report/bundle.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"bundle.js","sourceRoot":"","sources":["../../src/report/bundle.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;AACpC,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AAC7D,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AAIxC,MAAM,aAAa,GAAG,kBAAkB,CAAA;AACxC,MAAM,aAAa,GAAG,mBAAmB,CAAA;AAEzC,SAAS,kBAAkB,CAAC,KAAqB;IAC/C,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC;SACzB,UAAU,CAAC,GAAG,EAAE,MAAM,CAAC,GAAG,CAAA,QAAQ,CAAC;SACnC,UAAU,CAAC,GAAG,EAAE,MAAM,CAAC,GAAG,CAAA,QAAQ,CAAC;SACnC,UAAU,CAAC,GAAG,EAAE,MAAM,CAAC,GAAG,CAAA,QAAQ,CAAC;SACnC,UAAU,CAAC,QAAQ,EAAE,MAAM,CAAC,GAAG,CAAA,QAAQ,CAAC;SACxC,UAAU,CAAC,QAAQ,EAAE,MAAM,CAAC,GAAG,CAAA,QAAQ,CAAC,CAAA;AAC7C,CAAC;AAED,SAAS,UAAU,CAAC,KAAa;IAC/B,OAAO,KAAK;SACT,UAAU,CAAC,GAAG,EAAE,OAAO,CAAC;SACxB,UAAU,CAAC,GAAG,EAAE,MAAM,CAAC;SACvB,UAAU,CAAC,GAAG,EAAE,MAAM,CAAC;SACvB,UAAU,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAA;AAC9B,CAAC;AAED,SAAS,YAAY,CAAC,MAAsB,EAAE,MAAc,EAAE,MAAc;IAC1E,OAAO;;;;;;;sBAOa,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC;WAClC,MAAM;;;;yDAIwC,kBAAkB,CAAC,MAAM,CAAC;0BACzD,MAAM,CAAC,UAAU,CAAC,UAAU,EAAE,MAAM,CAAC,GAAG,CAAA,WAAW,CAAC;;;CAG7E,CAAA;AACD,CAAC;AAED,KAAK,UAAU,eAAe,CAAC,WAAmB,EAAE,IAAY;IAC9D,MAAM,aAAa,GAAG,aAAa,CAAC,IAAI,GAAG,CAAC,KAAK,IAAI,EAAE,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAA;IAC1E,MAAM,SAAS,GAAG,UAAU,CAAC,aAAa,CAAC;QACzC,CAAC,CAAC,aAAa;QACf,CAAC,CAAC,OAAO,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,CAAC,CAAA;IAChD,OAAO,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC,CAAA;AACpC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,WAAmB,EACnB,UAAkB,EAClB,MAAsB;IAEtB,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QACzC,eAAe,CAAC,WAAW,EAAE,aAAa,CAAC;QAC3C,eAAe,CAAC,WAAW,EAAE,aAAa,CAAC;KAC5C,CAAC,CAAA;IACF,MAAM,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;IACrD,MAAM,SAAS,CAAC,UAAU,EAAE,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,CAAA;AAC3E,CAAC"}
|
package/dist/report/model.js
CHANGED
|
@@ -1,14 +1,104 @@
|
|
|
1
1
|
import { classifyFailure } from "./classification.js";
|
|
2
2
|
import { redactText } from "./redaction.js";
|
|
3
3
|
import { evidenceReportSchema } from "./schema.js";
|
|
4
|
+
function safeReportPath(path) {
|
|
5
|
+
const normalized = path.replaceAll("\\", "/");
|
|
6
|
+
const segments = normalized.split("/");
|
|
7
|
+
if (!normalized || normalized.startsWith("/") || /^[a-z]:/iu.test(normalized)
|
|
8
|
+
|| /^[a-z][a-z\d+.-]*:/iu.test(normalized) || segments.includes("..")
|
|
9
|
+
|| /[\0\r\n]/u.test(normalized)) {
|
|
10
|
+
throw new Error("Evidence links must be safe project-relative paths");
|
|
11
|
+
}
|
|
12
|
+
return redactText(normalized);
|
|
13
|
+
}
|
|
14
|
+
function isStateCondition(condition) {
|
|
15
|
+
return condition.kind === "auth-cookie-expiry" || condition.kind === "storage-state-delay";
|
|
16
|
+
}
|
|
17
|
+
function stateConditionLabel(condition) {
|
|
18
|
+
if (condition.kind === "auth-cookie-expiry") {
|
|
19
|
+
return `Cookie ${condition.cookieName} withheld`;
|
|
20
|
+
}
|
|
21
|
+
return `${condition.storage} key ${condition.key} hidden for ${condition.delayMs} ms`;
|
|
22
|
+
}
|
|
23
|
+
function isTemporalCondition(condition) {
|
|
24
|
+
return condition.kind === "clock-jump"
|
|
25
|
+
|| condition.kind === "locale"
|
|
26
|
+
|| condition.kind === "timezone";
|
|
27
|
+
}
|
|
28
|
+
function temporalConditionLabel(condition) {
|
|
29
|
+
if (condition.kind === "clock-jump") {
|
|
30
|
+
return `Clock shifted ${condition.offsetMs} ms after ${condition.jumpAfterMs} ms`;
|
|
31
|
+
}
|
|
32
|
+
return condition.kind === "locale"
|
|
33
|
+
? `Locale set to ${condition.locale}`
|
|
34
|
+
: `Timezone set to ${condition.timezoneId}`;
|
|
35
|
+
}
|
|
36
|
+
function isTimingCondition(condition) {
|
|
37
|
+
return condition.kind === "event-loop-stall"
|
|
38
|
+
|| condition.kind === "network-delay"
|
|
39
|
+
|| condition.kind === "resource-loading-delay"
|
|
40
|
+
|| condition.kind === "startup-event-delay";
|
|
41
|
+
}
|
|
42
|
+
function timingConditionLabel(condition) {
|
|
43
|
+
if (condition.kind === "event-loop-stall") {
|
|
44
|
+
return `Event loop stalled ${condition.durationMs} ms after ${condition.startAfterMs} ms`;
|
|
45
|
+
}
|
|
46
|
+
if (condition.kind === "network-delay") {
|
|
47
|
+
return `Network delayed by ${condition.delayMs} ms`;
|
|
48
|
+
}
|
|
49
|
+
return condition.kind === "resource-loading-delay"
|
|
50
|
+
? `${condition.resourceType} loading delayed by ${condition.delayMs} ms`
|
|
51
|
+
: `${condition.event} listeners delayed by ${condition.delayMs} ms`;
|
|
52
|
+
}
|
|
53
|
+
function isVisualCondition(condition) {
|
|
54
|
+
return condition.kind === "animation-speed"
|
|
55
|
+
|| condition.kind === "reduced-motion"
|
|
56
|
+
|| condition.kind === "viewport";
|
|
57
|
+
}
|
|
58
|
+
function visualConditionLabel(condition) {
|
|
59
|
+
if (condition.kind === "animation-speed") {
|
|
60
|
+
return `Animation speed set to ${condition.rate}x`;
|
|
61
|
+
}
|
|
62
|
+
return condition.kind === "reduced-motion"
|
|
63
|
+
? "Reduced motion enabled"
|
|
64
|
+
: `Viewport set to ${condition.width}x${condition.height}`;
|
|
65
|
+
}
|
|
66
|
+
function runnerConditionLabel(condition) {
|
|
67
|
+
return condition.kind === "worker-pressure"
|
|
68
|
+
? `Worker pressure set to ${condition.workers} parallel workers`
|
|
69
|
+
: `Shared-state interference from ${condition.copies} overlapping copies`;
|
|
70
|
+
}
|
|
71
|
+
function responseConditionLabel(condition) {
|
|
72
|
+
if (condition.kind === "response-duplication") {
|
|
73
|
+
return `Response tail duplicated by ${condition.duplicateBytes} bytes`;
|
|
74
|
+
}
|
|
75
|
+
return condition.kind === "response-reordering"
|
|
76
|
+
? `First response in each pair held by ${condition.holdMs} ms`
|
|
77
|
+
: `Response truncated by ${condition.removeBytes} bytes`;
|
|
78
|
+
}
|
|
4
79
|
function conditionLabel(condition) {
|
|
5
80
|
if (condition.kind === "baseline") {
|
|
6
81
|
return "Clean baseline";
|
|
7
82
|
}
|
|
8
|
-
if (condition
|
|
9
|
-
return
|
|
83
|
+
if (isStateCondition(condition)) {
|
|
84
|
+
return stateConditionLabel(condition);
|
|
85
|
+
}
|
|
86
|
+
if (isTemporalCondition(condition)) {
|
|
87
|
+
return temporalConditionLabel(condition);
|
|
88
|
+
}
|
|
89
|
+
if (isTimingCondition(condition)) {
|
|
90
|
+
return timingConditionLabel(condition);
|
|
10
91
|
}
|
|
11
|
-
|
|
92
|
+
if (isVisualCondition(condition)) {
|
|
93
|
+
return visualConditionLabel(condition);
|
|
94
|
+
}
|
|
95
|
+
if (condition.kind === "worker-pressure" || condition.kind === "shared-state-interference") {
|
|
96
|
+
return runnerConditionLabel(condition);
|
|
97
|
+
}
|
|
98
|
+
if (condition.kind === "request-failure") {
|
|
99
|
+
return `HTTP ${condition.statusCode} response injected`;
|
|
100
|
+
}
|
|
101
|
+
return responseConditionLabel(condition);
|
|
12
102
|
}
|
|
13
103
|
function cleanResult(result) {
|
|
14
104
|
return {
|
|
@@ -23,7 +113,6 @@ function cleanResult(result) {
|
|
|
23
113
|
export function buildEvidenceReport(options) {
|
|
24
114
|
const { investigation, proof, reproducer } = options;
|
|
25
115
|
const ownership = classifyFailure(investigation);
|
|
26
|
-
const trigger = reproducer.faults[0];
|
|
27
116
|
const matrix = [
|
|
28
117
|
{ label: "Before · hostile", result: cleanResult(proof.beforeHostile) },
|
|
29
118
|
{ label: "After · hostile", result: cleanResult(proof.afterHostile) },
|
|
@@ -33,21 +122,38 @@ export function buildEvidenceReport(options) {
|
|
|
33
122
|
result: cleanResult(regression.result),
|
|
34
123
|
})),
|
|
35
124
|
];
|
|
125
|
+
const controlExperimentIds = investigation.experiments
|
|
126
|
+
.filter((experiment) => experiment.condition.kind === "baseline")
|
|
127
|
+
.map((experiment) => experiment.id);
|
|
128
|
+
const interventionExperimentIds = investigation.experiments
|
|
129
|
+
.filter((experiment) => investigation.conclusionEvidenceIds.includes(experiment.id)
|
|
130
|
+
&& experiment.condition.kind !== "baseline")
|
|
131
|
+
.map((experiment) => experiment.id);
|
|
132
|
+
if (controlExperimentIds.length === 0) {
|
|
133
|
+
throw new Error("Evidence report requires a clean control experiment");
|
|
134
|
+
}
|
|
135
|
+
if (interventionExperimentIds.length === 0) {
|
|
136
|
+
throw new Error("Evidence report requires a cited intervention experiment");
|
|
137
|
+
}
|
|
36
138
|
return evidenceReportSchema.parse({
|
|
37
|
-
version: 1,
|
|
38
139
|
generatedAt: (options.generatedAt ?? new Date()).toISOString(),
|
|
39
140
|
status: proof.patchAccepted ? "FIX_PROVEN" : "PATCH_REJECTED",
|
|
40
141
|
test: redactText(investigation.test),
|
|
41
142
|
model: redactText(investigation.model),
|
|
42
143
|
conclusion: redactText(investigation.conclusion),
|
|
144
|
+
causalClaim: {
|
|
145
|
+
controlExperimentIds,
|
|
146
|
+
interventionExperimentIds,
|
|
147
|
+
},
|
|
43
148
|
ownership: {
|
|
44
149
|
...ownership,
|
|
45
150
|
rationale: redactText(ownership.rationale),
|
|
46
151
|
},
|
|
47
152
|
trigger: {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
153
|
+
faults: reproducer.faults.map((fault) => ({
|
|
154
|
+
...fault,
|
|
155
|
+
pattern: redactText(fault.pattern),
|
|
156
|
+
})),
|
|
51
157
|
minimumFailureRate: reproducer.expectedFailure.minimumRate,
|
|
52
158
|
signature: reproducer.expectedFailure.signature,
|
|
53
159
|
},
|
|
@@ -62,8 +168,21 @@ export function buildEvidenceReport(options) {
|
|
|
62
168
|
id: experiment.id,
|
|
63
169
|
hypothesisId: experiment.hypothesisId,
|
|
64
170
|
condition: conditionLabel(experiment.condition),
|
|
171
|
+
representativeRuns: experiment.result.representativeRuns.map((run) => ({
|
|
172
|
+
...run,
|
|
173
|
+
artifacts: run.artifacts.map((artifact) => ({
|
|
174
|
+
...artifact,
|
|
175
|
+
path: safeReportPath(artifact.path),
|
|
176
|
+
})),
|
|
177
|
+
})),
|
|
65
178
|
result: cleanResult(experiment.result),
|
|
66
179
|
})),
|
|
180
|
+
replayCommand: `flakelab replay ${JSON.stringify(options.paths.reproducer)} --concurrency 1`,
|
|
181
|
+
sourcePaths: investigation.sourcePaths.map(safeReportPath),
|
|
182
|
+
sourceLocations: proof.sourceLocations.map((location) => ({
|
|
183
|
+
line: location.line,
|
|
184
|
+
path: safeReportPath(location.path),
|
|
185
|
+
})),
|
|
67
186
|
proof: {
|
|
68
187
|
accepted: proof.patchAccepted,
|
|
69
188
|
execution: proof.execution,
|
|
@@ -72,10 +191,10 @@ export function buildEvidenceReport(options) {
|
|
|
72
191
|
},
|
|
73
192
|
usage: investigation.usage,
|
|
74
193
|
artifacts: [
|
|
75
|
-
{ label: "Investigation", path:
|
|
76
|
-
{ label: "Reproducer", path:
|
|
77
|
-
{ label: "Candidate patch", path:
|
|
78
|
-
{ label: "Proof of fix", path:
|
|
194
|
+
{ label: "Investigation", path: safeReportPath(options.paths.investigation) },
|
|
195
|
+
{ label: "Reproducer", path: safeReportPath(options.paths.reproducer) },
|
|
196
|
+
{ label: "Candidate patch", path: safeReportPath(options.paths.patch) },
|
|
197
|
+
{ label: "Proof of fix", path: safeReportPath(options.paths.proof) },
|
|
79
198
|
],
|
|
80
199
|
});
|
|
81
200
|
}
|
package/dist/report/model.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"model.js","sourceRoot":"","sources":["../../src/report/model.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAA;AACrD,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAA;AAE3C,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAA;AAiBlD,SAAS,cAAc,CAAC,SAA8B;IACpD,IAAI,SAAS,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"model.js","sourceRoot":"","sources":["../../src/report/model.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAA;AACrD,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAA;AAE3C,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAA;AAiBlD,SAAS,cAAc,CAAC,IAAY;IAClC,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;IAC7C,MAAM,QAAQ,GAAG,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;IACtC,IAAI,CAAC,UAAU,IAAI,UAAU,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,WAAW,CAAC,IAAI,CAAC,UAAU,CAAC;WACxE,sBAAsB,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC;WAClE,WAAW,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;QAClC,MAAM,IAAI,KAAK,CAAC,oDAAoD,CAAC,CAAA;IACvE,CAAC;IACD,OAAO,UAAU,CAAC,UAAU,CAAC,CAAA;AAC/B,CAAC;AAkBD,SAAS,gBAAgB,CAAC,SAA8B;IACtD,OAAO,SAAS,CAAC,IAAI,KAAK,oBAAoB,IAAI,SAAS,CAAC,IAAI,KAAK,qBAAqB,CAAA;AAC5F,CAAC;AAED,SAAS,mBAAmB,CAAC,SAAyB;IACpD,IAAI,SAAS,CAAC,IAAI,KAAK,oBAAoB,EAAE,CAAC;QAC5C,OAAO,UAAU,SAAS,CAAC,UAAU,WAAW,CAAA;IAClD,CAAC;IACD,OAAO,GAAG,SAAS,CAAC,OAAO,QAAQ,SAAS,CAAC,GAAG,eAAe,SAAS,CAAC,OAAO,KAAK,CAAA;AACvF,CAAC;AAED,SAAS,mBAAmB,CAAC,SAA8B;IACzD,OAAO,SAAS,CAAC,IAAI,KAAK,YAAY;WACjC,SAAS,CAAC,IAAI,KAAK,QAAQ;WAC3B,SAAS,CAAC,IAAI,KAAK,UAAU,CAAA;AACpC,CAAC;AAED,SAAS,sBAAsB,CAAC,SAA4B;IAC1D,IAAI,SAAS,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;QACpC,OAAO,iBAAiB,SAAS,CAAC,QAAQ,aAAa,SAAS,CAAC,WAAW,KAAK,CAAA;IACnF,CAAC;IACD,OAAO,SAAS,CAAC,IAAI,KAAK,QAAQ;QAChC,CAAC,CAAC,iBAAiB,SAAS,CAAC,MAAM,EAAE;QACrC,CAAC,CAAC,mBAAmB,SAAS,CAAC,UAAU,EAAE,CAAA;AAC/C,CAAC;AAED,SAAS,iBAAiB,CAAC,SAA8B;IACvD,OAAO,SAAS,CAAC,IAAI,KAAK,kBAAkB;WACvC,SAAS,CAAC,IAAI,KAAK,eAAe;WAClC,SAAS,CAAC,IAAI,KAAK,wBAAwB;WAC3C,SAAS,CAAC,IAAI,KAAK,qBAAqB,CAAA;AAC/C,CAAC;AAED,SAAS,oBAAoB,CAAC,SAA0B;IACtD,IAAI,SAAS,CAAC,IAAI,KAAK,kBAAkB,EAAE,CAAC;QAC1C,OAAO,sBAAsB,SAAS,CAAC,UAAU,aAAa,SAAS,CAAC,YAAY,KAAK,CAAA;IAC3F,CAAC;IACD,IAAI,SAAS,CAAC,IAAI,KAAK,eAAe,EAAE,CAAC;QACvC,OAAO,sBAAsB,SAAS,CAAC,OAAO,KAAK,CAAA;IACrD,CAAC;IACD,OAAO,SAAS,CAAC,IAAI,KAAK,wBAAwB;QAChD,CAAC,CAAC,GAAG,SAAS,CAAC,YAAY,uBAAuB,SAAS,CAAC,OAAO,KAAK;QACxE,CAAC,CAAC,GAAG,SAAS,CAAC,KAAK,yBAAyB,SAAS,CAAC,OAAO,KAAK,CAAA;AACvE,CAAC;AAED,SAAS,iBAAiB,CAAC,SAA8B;IACvD,OAAO,SAAS,CAAC,IAAI,KAAK,iBAAiB;WACtC,SAAS,CAAC,IAAI,KAAK,gBAAgB;WACnC,SAAS,CAAC,IAAI,KAAK,UAAU,CAAA;AACpC,CAAC;AAED,SAAS,oBAAoB,CAAC,SAA0B;IACtD,IAAI,SAAS,CAAC,IAAI,KAAK,iBAAiB,EAAE,CAAC;QACzC,OAAO,0BAA0B,SAAS,CAAC,IAAI,GAAG,CAAA;IACpD,CAAC;IACD,OAAO,SAAS,CAAC,IAAI,KAAK,gBAAgB;QACxC,CAAC,CAAC,wBAAwB;QAC1B,CAAC,CAAC,mBAAmB,SAAS,CAAC,KAAK,IAAI,SAAS,CAAC,MAAM,EAAE,CAAA;AAC9D,CAAC;AAED,SAAS,oBAAoB,CAAC,SAA0B;IACtD,OAAO,SAAS,CAAC,IAAI,KAAK,iBAAiB;QACzC,CAAC,CAAC,0BAA0B,SAAS,CAAC,OAAO,mBAAmB;QAChE,CAAC,CAAC,kCAAkC,SAAS,CAAC,MAAM,qBAAqB,CAAA;AAC7E,CAAC;AAED,SAAS,sBAAsB,CAAC,SAE9B;IACA,IAAI,SAAS,CAAC,IAAI,KAAK,sBAAsB,EAAE,CAAC;QAC9C,OAAO,+BAA+B,SAAS,CAAC,cAAc,QAAQ,CAAA;IACxE,CAAC;IACD,OAAO,SAAS,CAAC,IAAI,KAAK,qBAAqB;QAC7C,CAAC,CAAC,uCAAuC,SAAS,CAAC,MAAM,KAAK;QAC9D,CAAC,CAAC,yBAAyB,SAAS,CAAC,WAAW,QAAQ,CAAA;AAC5D,CAAC;AAED,SAAS,cAAc,CAAC,SAA8B;IACpD,IAAI,SAAS,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;QAClC,OAAO,gBAAgB,CAAA;IACzB,CAAC;IACD,IAAI,gBAAgB,CAAC,SAAS,CAAC,EAAE,CAAC;QAChC,OAAO,mBAAmB,CAAC,SAAS,CAAC,CAAA;IACvC,CAAC;IACD,IAAI,mBAAmB,CAAC,SAAS,CAAC,EAAE,CAAC;QACnC,OAAO,sBAAsB,CAAC,SAAS,CAAC,CAAA;IAC1C,CAAC;IACD,IAAI,iBAAiB,CAAC,SAAS,CAAC,EAAE,CAAC;QACjC,OAAO,oBAAoB,CAAC,SAAS,CAAC,CAAA;IACxC,CAAC;IACD,IAAI,iBAAiB,CAAC,SAAS,CAAC,EAAE,CAAC;QACjC,OAAO,oBAAoB,CAAC,SAAS,CAAC,CAAA;IACxC,CAAC;IACD,IAAI,SAAS,CAAC,IAAI,KAAK,iBAAiB,IAAI,SAAS,CAAC,IAAI,KAAK,2BAA2B,EAAE,CAAC;QAC3F,OAAO,oBAAoB,CAAC,SAAS,CAAC,CAAA;IACxC,CAAC;IACD,IAAI,SAAS,CAAC,IAAI,KAAK,iBAAiB,EAAE,CAAC;QACzC,OAAO,QAAQ,SAAS,CAAC,UAAU,oBAAoB,CAAA;IACzD,CAAC;IACD,OAAO,sBAAsB,CAAC,SAAS,CAAC,CAAA;AAC1C,CAAC;AAED,SAAS,WAAW,CAAC,MAOpB;IAQC,OAAO;QACL,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,WAAW,EAAE,MAAM,CAAC,WAAW;QAC/B,YAAY,EAAE,MAAM,CAAC,YAAY;QACjC,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,MAAM,EAAE,MAAM,CAAC,MAAM;KACtB,CAAA;AACH,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,OAA2B;IAC7D,MAAM,EAAE,aAAa,EAAE,KAAK,EAAE,UAAU,EAAE,GAAG,OAAO,CAAA;IACpD,MAAM,SAAS,GAAG,eAAe,CAAC,aAAa,CAAC,CAAA;IAChD,MAAM,MAAM,GAAG;QACb,EAAE,KAAK,EAAE,kBAAkB,EAAE,MAAM,EAAE,WAAW,CAAC,KAAK,CAAC,aAAa,CAAC,EAAE;QACvE,EAAE,KAAK,EAAE,iBAAiB,EAAE,MAAM,EAAE,WAAW,CAAC,KAAK,CAAC,YAAY,CAAC,EAAE;QACrE,EAAE,KAAK,EAAE,eAAe,EAAE,MAAM,EAAE,WAAW,CAAC,KAAK,CAAC,YAAY,CAAC,EAAE;QACnE,GAAG,KAAK,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;YACxC,KAAK,EAAE,gBAAgB,UAAU,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE;YACxD,MAAM,EAAE,WAAW,CAAC,UAAU,CAAC,MAAM,CAAC;SACvC,CAAC,CAAC;KACJ,CAAA;IACD,MAAM,oBAAoB,GAAG,aAAa,CAAC,WAAW;SACnD,MAAM,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,IAAI,KAAK,UAAU,CAAC;SAChE,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,UAAU,CAAC,EAAE,CAAC,CAAA;IACrC,MAAM,yBAAyB,GAAG,aAAa,CAAC,WAAW;SACxD,MAAM,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,aAAa,CAAC,qBAAqB,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;WAC9E,UAAU,CAAC,SAAS,CAAC,IAAI,KAAK,UAAU,CAAC;SAC7C,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,UAAU,CAAC,EAAE,CAAC,CAAA;IACrC,IAAI,oBAAoB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACtC,MAAM,IAAI,KAAK,CAAC,qDAAqD,CAAC,CAAA;IACxE,CAAC;IACD,IAAI,yBAAyB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC3C,MAAM,IAAI,KAAK,CAAC,0DAA0D,CAAC,CAAA;IAC7E,CAAC;IACD,OAAO,oBAAoB,CAAC,KAAK,CAAC;QAChC,WAAW,EAAE,CAAC,OAAO,CAAC,WAAW,IAAI,IAAI,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE;QAC9D,MAAM,EAAE,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,gBAAgB;QAC7D,IAAI,EAAE,UAAU,CAAC,aAAa,CAAC,IAAI,CAAC;QACpC,KAAK,EAAE,UAAU,CAAC,aAAa,CAAC,KAAK,CAAC;QACtC,UAAU,EAAE,UAAU,CAAC,aAAa,CAAC,UAAU,CAAC;QAChD,WAAW,EAAE;YACX,oBAAoB;YACpB,yBAAyB;SAC1B;QACD,SAAS,EAAE;YACT,GAAG,SAAS;YACZ,SAAS,EAAE,UAAU,CAAC,SAAS,CAAC,SAAS,CAAC;SAC3C;QACD,OAAO,EAAE;YACP,MAAM,EAAE,UAAU,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;gBACxC,GAAG,KAAK;gBACR,OAAO,EAAE,UAAU,CAAC,KAAK,CAAC,OAAO,CAAC;aACnC,CAAC,CAAC;YACH,kBAAkB,EAAE,UAAU,CAAC,eAAe,CAAC,WAAW;YAC1D,SAAS,EAAE,UAAU,CAAC,eAAe,CAAC,SAAS;SAChD;QACD,UAAU,EAAE,aAAa,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;YACxD,EAAE,EAAE,UAAU,CAAC,EAAE;YACjB,SAAS,EAAE,UAAU,CAAC,UAAU,CAAC,SAAS,CAAC;YAC3C,MAAM,EAAE,UAAU,CAAC,MAAM;YACzB,WAAW,EAAE,UAAU,CAAC,UAAU,CAAC,WAAW,CAAC;YAC/C,qBAAqB,EAAE,UAAU,CAAC,qBAAqB;SACxD,CAAC,CAAC;QACH,WAAW,EAAE,aAAa,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;YAC1D,EAAE,EAAE,UAAU,CAAC,EAAE;YACjB,YAAY,EAAE,UAAU,CAAC,YAAY;YACrC,SAAS,EAAE,cAAc,CAAC,UAAU,CAAC,SAAS,CAAC;YAC/C,kBAAkB,EAAE,UAAU,CAAC,MAAM,CAAC,kBAAkB,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;gBACrE,GAAG,GAAG;gBACN,SAAS,EAAE,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;oBAC1C,GAAG,QAAQ;oBACX,IAAI,EAAE,cAAc,CAAC,QAAQ,CAAC,IAAI,CAAC;iBACpC,CAAC,CAAC;aACJ,CAAC,CAAC;YACH,MAAM,EAAE,WAAW,CAAC,UAAU,CAAC,MAAM,CAAC;SACvC,CAAC,CAAC;QACH,aAAa,EAAE,mBAAmB,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC,kBAAkB;QAC5F,WAAW,EAAE,aAAa,CAAC,WAAW,CAAC,GAAG,CAAC,cAAc,CAAC;QAC1D,eAAe,EAAE,KAAK,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;YACxD,IAAI,EAAE,QAAQ,CAAC,IAAI;YACnB,IAAI,EAAE,cAAc,CAAC,QAAQ,CAAC,IAAI,CAAC;SACpC,CAAC,CAAC;QACH,KAAK,EAAE;YACL,QAAQ,EAAE,KAAK,CAAC,aAAa;YAC7B,SAAS,EAAE,KAAK,CAAC,SAAS;YAC1B,YAAY,EAAE,KAAK,CAAC,YAAY;YAChC,MAAM;SACP;QACD,KAAK,EAAE,aAAa,CAAC,KAAK;QAC1B,SAAS,EAAE;YACT,EAAE,KAAK,EAAE,eAAe,EAAE,IAAI,EAAE,cAAc,CAAC,OAAO,CAAC,KAAK,CAAC,aAAa,CAAC,EAAE;YAC7E,EAAE,KAAK,EAAE,YAAY,EAAE,IAAI,EAAE,cAAc,CAAC,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC,EAAE;YACvE,EAAE,KAAK,EAAE,iBAAiB,EAAE,IAAI,EAAE,cAAc,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE;YACvE,EAAE,KAAK,EAAE,cAAc,EAAE,IAAI,EAAE,cAAc,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE;SACrE;KACF,CAAC,CAAA;AACJ,CAAC"}
|
package/dist/report/open.d.ts
CHANGED
|
@@ -1 +1,10 @@
|
|
|
1
|
+
type AskQuestion = (question: string) => Promise<string>;
|
|
2
|
+
interface ConfirmOpenOptions {
|
|
3
|
+
ask?: AskQuestion;
|
|
4
|
+
environment?: NodeJS.ProcessEnv;
|
|
5
|
+
inputIsTTY?: boolean;
|
|
6
|
+
outputIsTTY?: boolean;
|
|
7
|
+
}
|
|
1
8
|
export declare function openLocalReport(path: string): void;
|
|
9
|
+
export declare function confirmLocalReportOpen(options?: ConfirmOpenOptions): Promise<boolean>;
|
|
10
|
+
export {};
|
package/dist/report/open.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { spawn } from "node:child_process";
|
|
2
|
+
import { createInterface } from "node:readline/promises";
|
|
2
3
|
function opener() {
|
|
3
4
|
if (process.platform === "win32") {
|
|
4
5
|
return { command: "explorer.exe", args: [] };
|
|
@@ -21,4 +22,26 @@ export function openLocalReport(path) {
|
|
|
21
22
|
});
|
|
22
23
|
child.unref();
|
|
23
24
|
}
|
|
25
|
+
function interactive(options) {
|
|
26
|
+
const environment = options.environment ?? process.env;
|
|
27
|
+
return (options.inputIsTTY ?? Boolean(process.stdin.isTTY))
|
|
28
|
+
&& (options.outputIsTTY ?? Boolean(process.stderr.isTTY))
|
|
29
|
+
&& !environment.CI;
|
|
30
|
+
}
|
|
31
|
+
async function askInTerminal(question) {
|
|
32
|
+
const prompt = createInterface({ input: process.stdin, output: process.stderr });
|
|
33
|
+
try {
|
|
34
|
+
return await prompt.question(question);
|
|
35
|
+
}
|
|
36
|
+
finally {
|
|
37
|
+
prompt.close();
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
export async function confirmLocalReportOpen(options = {}) {
|
|
41
|
+
if (!interactive(options)) {
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
const answer = (await (options.ask ?? askInTerminal)("Open the generated report in your browser? [Y/n] ")).trim().toLowerCase();
|
|
45
|
+
return answer === "" || answer === "y" || answer === "yes";
|
|
46
|
+
}
|
|
24
47
|
//# sourceMappingURL=open.js.map
|
package/dist/report/open.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"open.js","sourceRoot":"","sources":["../../src/report/open.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAA;
|
|
1
|
+
{"version":3,"file":"open.js","sourceRoot":"","sources":["../../src/report/open.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAA;AAC1C,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAA;AAWxD,SAAS,MAAM;IACb,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;QACjC,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,IAAI,EAAE,EAAE,EAAE,CAAA;IAC9C,CAAC;IACD,IAAI,OAAO,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;QAClC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,EAAE,CAAA;IACtC,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,EAAE,EAAE,CAAA;AAC1C,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,IAAY;IAC1C,MAAM,QAAQ,GAAG,MAAM,EAAE,CAAA;IACzB,MAAM,KAAK,GAAG,KAAK,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC,GAAG,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE;QAC9D,QAAQ,EAAE,IAAI;QACd,KAAK,EAAE,KAAK;QACZ,KAAK,EAAE,QAAQ;QACf,WAAW,EAAE,IAAI;KAClB,CAAC,CAAA;IACF,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,EAAE;QACvB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,mFAAmF,CAAC,CAAA;IAC3G,CAAC,CAAC,CAAA;IACF,KAAK,CAAC,KAAK,EAAE,CAAA;AACf,CAAC;AAED,SAAS,WAAW,CAAC,OAA2B;IAC9C,MAAM,WAAW,GAAG,OAAO,CAAC,WAAW,IAAI,OAAO,CAAC,GAAG,CAAA;IACtD,OAAO,CAAC,OAAO,CAAC,UAAU,IAAI,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;WACtD,CAAC,OAAO,CAAC,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;WACtD,CAAC,WAAW,CAAC,EAAE,CAAA;AACtB,CAAC;AAED,KAAK,UAAU,aAAa,CAAC,QAAgB;IAC3C,MAAM,MAAM,GAAG,eAAe,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAA;IAChF,IAAI,CAAC;QACH,OAAO,MAAM,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAA;IACxC,CAAC;YAAS,CAAC;QACT,MAAM,CAAC,KAAK,EAAE,CAAA;IAChB,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAC1C,UAA8B,EAAE;IAEhC,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,EAAE,CAAC;QAC1B,OAAO,KAAK,CAAA;IACd,CAAC;IACD,MAAM,MAAM,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,IAAI,aAAa,CAAC,CAClD,mDAAmD,CACpD,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAA;IACvB,OAAO,MAAM,KAAK,EAAE,IAAI,MAAM,KAAK,GAAG,IAAI,MAAM,KAAK,KAAK,CAAA;AAC5D,CAAC"}
|