flakelab 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.
- package/README.md +341 -0
- package/bin/flakelab.mjs +3 -0
- package/dist/artifacts/ndjson.d.ts +3 -0
- package/dist/artifacts/ndjson.js +16 -0
- package/dist/artifacts/ndjson.js.map +1 -0
- package/dist/bisect/archive.d.ts +1 -0
- package/dist/bisect/archive.js +14 -0
- package/dist/bisect/archive.js.map +1 -0
- package/dist/bisect/confidence.d.ts +7 -0
- package/dist/bisect/confidence.js +27 -0
- package/dist/bisect/confidence.js.map +1 -0
- package/dist/bisect/engine.d.ts +10 -0
- package/dist/bisect/engine.js +110 -0
- package/dist/bisect/engine.js.map +1 -0
- package/dist/bisect/git.d.ts +7 -0
- package/dist/bisect/git.js +56 -0
- package/dist/bisect/git.js.map +1 -0
- package/dist/bisect/schema.d.ts +82 -0
- package/dist/bisect/schema.js +33 -0
- package/dist/bisect/schema.js.map +1 -0
- package/dist/bisect/solari-command.d.ts +7 -0
- package/dist/bisect/solari-command.js +95 -0
- package/dist/bisect/solari-command.js.map +1 -0
- package/dist/bisect/solari-evaluator.d.ts +20 -0
- package/dist/bisect/solari-evaluator.js +310 -0
- package/dist/bisect/solari-evaluator.js.map +1 -0
- package/dist/ci/changed-tests.d.ts +7 -0
- package/dist/ci/changed-tests.js +104 -0
- package/dist/ci/changed-tests.js.map +1 -0
- package/dist/ci/job-summary.d.ts +11 -0
- package/dist/ci/job-summary.js +45 -0
- package/dist/ci/job-summary.js.map +1 -0
- package/dist/ci/select-command.d.ts +1 -0
- package/dist/ci/select-command.js +49 -0
- package/dist/ci/select-command.js.map +1 -0
- package/dist/ci/summary-command.d.ts +1 -0
- package/dist/ci/summary-command.js +46 -0
- package/dist/ci/summary-command.js.map +1 -0
- package/dist/cli-help.d.ts +2 -0
- package/dist/cli-help.js +47 -0
- package/dist/cli-help.js.map +1 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +121 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/bisect.d.ts +2 -0
- package/dist/commands/bisect.js +63 -0
- package/dist/commands/bisect.js.map +1 -0
- package/dist/commands/diagnose.d.ts +2 -0
- package/dist/commands/diagnose.js +27 -0
- package/dist/commands/diagnose.js.map +1 -0
- package/dist/commands/discover.d.ts +2 -0
- package/dist/commands/discover.js +46 -0
- package/dist/commands/discover.js.map +1 -0
- package/dist/commands/doctor.d.ts +8 -0
- package/dist/commands/doctor.js +78 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/investigate.d.ts +2 -0
- package/dist/commands/investigate.js +43 -0
- package/dist/commands/investigate.js.map +1 -0
- package/dist/commands/options.d.ts +38 -0
- package/dist/commands/options.js +35 -0
- package/dist/commands/options.js.map +1 -0
- package/dist/commands/prove.d.ts +2 -0
- package/dist/commands/prove.js +21 -0
- package/dist/commands/prove.js.map +1 -0
- package/dist/commands/repair.d.ts +2 -0
- package/dist/commands/repair.js +55 -0
- package/dist/commands/repair.js.map +1 -0
- package/dist/commands/replay.d.ts +2 -0
- package/dist/commands/replay.js +26 -0
- package/dist/commands/replay.js.map +1 -0
- package/dist/commands/report.d.ts +2 -0
- package/dist/commands/report.js +79 -0
- package/dist/commands/report.js.map +1 -0
- package/dist/commands/scan.d.ts +12 -0
- package/dist/commands/scan.js +86 -0
- package/dist/commands/scan.js.map +1 -0
- package/dist/core/plan.d.ts +3 -0
- package/dist/core/plan.js +17 -0
- package/dist/core/plan.js.map +1 -0
- package/dist/discovery/evaluate.d.ts +22 -0
- package/dist/discovery/evaluate.js +81 -0
- package/dist/discovery/evaluate.js.map +1 -0
- package/dist/discovery/minimize.d.ts +24 -0
- package/dist/discovery/minimize.js +73 -0
- package/dist/discovery/minimize.js.map +1 -0
- package/dist/domain/schema.d.ts +155 -0
- package/dist/domain/schema.js +67 -0
- package/dist/domain/schema.js.map +1 -0
- package/dist/faults/install.d.ts +4 -0
- package/dist/faults/install.js +9 -0
- package/dist/faults/install.js.map +1 -0
- package/dist/faults/network-delay.d.ts +5 -0
- package/dist/faults/network-delay.js +34 -0
- package/dist/faults/network-delay.js.map +1 -0
- package/dist/faults/request-failure.d.ts +5 -0
- package/dist/faults/request-failure.js +24 -0
- package/dist/faults/request-failure.js.map +1 -0
- package/dist/investigator/agent.d.ts +26 -0
- package/dist/investigator/agent.js +197 -0
- package/dist/investigator/agent.js.map +1 -0
- package/dist/investigator/budget.d.ts +14 -0
- package/dist/investigator/budget.js +39 -0
- package/dist/investigator/budget.js.map +1 -0
- package/dist/investigator/file.d.ts +2 -0
- package/dist/investigator/file.js +7 -0
- package/dist/investigator/file.js.map +1 -0
- package/dist/investigator/groq.d.ts +5 -0
- package/dist/investigator/groq.js +26 -0
- package/dist/investigator/groq.js.map +1 -0
- package/dist/investigator/ledger.d.ts +17 -0
- package/dist/investigator/ledger.js +121 -0
- package/dist/investigator/ledger.js.map +1 -0
- package/dist/investigator/safe-source.d.ts +6 -0
- package/dist/investigator/safe-source.js +79 -0
- package/dist/investigator/safe-source.js.map +1 -0
- package/dist/investigator/schema.d.ts +110 -0
- package/dist/investigator/schema.js +53 -0
- package/dist/investigator/schema.js.map +1 -0
- package/dist/playwright.d.ts +3 -0
- package/dist/playwright.js +21 -0
- package/dist/playwright.js.map +1 -0
- package/dist/providers/errors.d.ts +21 -0
- package/dist/providers/errors.js +159 -0
- package/dist/providers/errors.js.map +1 -0
- package/dist/repair/file.d.ts +2 -0
- package/dist/repair/file.js +6 -0
- package/dist/repair/file.js.map +1 -0
- package/dist/repair/generator.d.ts +12 -0
- package/dist/repair/generator.js +74 -0
- package/dist/repair/generator.js.map +1 -0
- package/dist/repair/policy.d.ts +2 -0
- package/dist/repair/policy.js +70 -0
- package/dist/repair/policy.js.map +1 -0
- package/dist/repair/remote-proof-runner.d.ts +1 -0
- package/dist/repair/remote-proof-runner.js +53 -0
- package/dist/repair/remote-proof-runner.js.map +1 -0
- package/dist/repair/schema.d.ts +78 -0
- package/dist/repair/schema.js +44 -0
- package/dist/repair/schema.js.map +1 -0
- package/dist/repair/solari-validator.d.ts +25 -0
- package/dist/repair/solari-validator.js +231 -0
- package/dist/repair/solari-validator.js.map +1 -0
- package/dist/repair/validator.d.ts +16 -0
- package/dist/repair/validator.js +81 -0
- package/dist/repair/validator.js.map +1 -0
- package/dist/repair/workspace.d.ts +7 -0
- package/dist/repair/workspace.js +40 -0
- package/dist/repair/workspace.js.map +1 -0
- package/dist/report/browser-entry.d.ts +2 -0
- package/dist/report/browser-entry.js +15 -0
- package/dist/report/browser-entry.js.map +1 -0
- package/dist/report/bundle.d.ts +2 -0
- package/dist/report/bundle.js +77 -0
- package/dist/report/bundle.js.map +1 -0
- package/dist/report/classification.d.ts +9 -0
- package/dist/report/classification.js +55 -0
- package/dist/report/classification.js.map +1 -0
- package/dist/report/components/artifacts.d.ts +4 -0
- package/dist/report/components/artifacts.js +6 -0
- package/dist/report/components/artifacts.js.map +1 -0
- package/dist/report/components/experiments.d.ts +4 -0
- package/dist/report/components/experiments.js +7 -0
- package/dist/report/components/experiments.js.map +1 -0
- package/dist/report/components/hypotheses.d.ts +4 -0
- package/dist/report/components/hypotheses.js +26 -0
- package/dist/report/components/hypotheses.js.map +1 -0
- package/dist/report/components/indicators.d.ts +32 -0
- package/dist/report/components/indicators.js +42 -0
- package/dist/report/components/indicators.js.map +1 -0
- package/dist/report/components/layout.d.ts +29 -0
- package/dist/report/components/layout.js +20 -0
- package/dist/report/components/layout.js.map +1 -0
- package/dist/report/components/proof.d.ts +4 -0
- package/dist/report/components/proof.js +34 -0
- package/dist/report/components/proof.js.map +1 -0
- package/dist/report/components/reproduction.d.ts +4 -0
- package/dist/report/components/reproduction.js +19 -0
- package/dist/report/components/reproduction.js.map +1 -0
- package/dist/report/components/summary.d.ts +4 -0
- package/dist/report/components/summary.js +12 -0
- package/dist/report/components/summary.js.map +1 -0
- package/dist/report/components/verdict.d.ts +4 -0
- package/dist/report/components/verdict.js +27 -0
- package/dist/report/components/verdict.js.map +1 -0
- package/dist/report/model.d.ts +19 -0
- package/dist/report/model.js +82 -0
- package/dist/report/model.js.map +1 -0
- package/dist/report/open.d.ts +1 -0
- package/dist/report/open.js +24 -0
- package/dist/report/open.js.map +1 -0
- package/dist/report/publish.d.ts +12 -0
- package/dist/report/publish.js +67 -0
- package/dist/report/publish.js.map +1 -0
- package/dist/report/redaction.d.ts +1 -0
- package/dist/report/redaction.js +58 -0
- package/dist/report/redaction.js.map +1 -0
- package/dist/report/report-app.d.ts +6 -0
- package/dist/report/report-app.js +16 -0
- package/dist/report/report-app.js.map +1 -0
- package/dist/report/report-details.css +182 -0
- package/dist/report/report.css +404 -0
- package/dist/report/schema.d.ts +101 -0
- package/dist/report/schema.js +71 -0
- package/dist/report/schema.js.map +1 -0
- package/dist/reproducer/file.d.ts +3 -0
- package/dist/reproducer/file.js +14 -0
- package/dist/reproducer/file.js.map +1 -0
- package/dist/reproducer/schema.d.ts +17 -0
- package/dist/reproducer/schema.js +14 -0
- package/dist/reproducer/schema.js.map +1 -0
- package/dist/runner/local.d.ts +12 -0
- package/dist/runner/local.js +72 -0
- package/dist/runner/local.js.map +1 -0
- package/dist/runner/playwright-executor.d.ts +10 -0
- package/dist/runner/playwright-executor.js +148 -0
- package/dist/runner/playwright-executor.js.map +1 -0
- package/dist/security/credentials.d.ts +23 -0
- package/dist/security/credentials.js +105 -0
- package/dist/security/credentials.js.map +1 -0
- package/dist/solari/checkout-fixture.d.ts +3 -0
- package/dist/solari/checkout-fixture.js +54 -0
- package/dist/solari/checkout-fixture.js.map +1 -0
- package/dist/solari/executor.d.ts +17 -0
- package/dist/solari/executor.js +280 -0
- package/dist/solari/executor.js.map +1 -0
- package/dist/solari/retry.d.ts +7 -0
- package/dist/solari/retry.js +50 -0
- package/dist/solari/retry.js.map +1 -0
- package/dist/solari/run-demo.d.ts +21 -0
- package/dist/solari/run-demo.js +64 -0
- package/dist/solari/run-demo.js.map +1 -0
- package/dist/solari/transport.d.ts +1 -0
- package/dist/solari/transport.js +21 -0
- package/dist/solari/transport.js.map +1 -0
- package/dist/solari/usage.d.ts +23 -0
- package/dist/solari/usage.js +53 -0
- package/dist/solari/usage.js.map +1 -0
- package/dist/solari/websocket-proxy.d.ts +7 -0
- package/dist/solari/websocket-proxy.js +131 -0
- package/dist/solari/websocket-proxy.js.map +1 -0
- package/dist/ui/progress.d.ts +5 -0
- package/dist/ui/progress.js +16 -0
- package/dist/ui/progress.js.map +1 -0
- package/package.json +79 -0
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
const UINT32_RANGE = 0x1_0000_0000;
|
|
2
|
+
const GOLDEN_RATIO_32 = 2_654_435_761;
|
|
3
|
+
export function deriveTrialSeed(seed, index) {
|
|
4
|
+
return (seed + index * GOLDEN_RATIO_32) % UINT32_RANGE;
|
|
5
|
+
}
|
|
6
|
+
export function planTrials(request) {
|
|
7
|
+
return Array.from({ length: request.runs }, (_, index) => {
|
|
8
|
+
const seed = deriveTrialSeed(request.seed, index);
|
|
9
|
+
return {
|
|
10
|
+
trialId: `trial-${String(index + 1).padStart(3, "0")}-${seed}`,
|
|
11
|
+
index,
|
|
12
|
+
seed,
|
|
13
|
+
fault: index % 2 === 1 ? request.fault : undefined,
|
|
14
|
+
};
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=plan.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plan.js","sourceRoot":"","sources":["../../src/core/plan.ts"],"names":[],"mappings":"AAEA,MAAM,YAAY,GAAG,aAAa,CAAA;AAClC,MAAM,eAAe,GAAG,aAAa,CAAA;AAErC,MAAM,UAAU,eAAe,CAAC,IAAY,EAAE,KAAa;IACzD,OAAO,CAAC,IAAI,GAAG,KAAK,GAAG,eAAe,CAAC,GAAG,YAAY,CAAA;AACxD,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,OAAmB;IAC5C,OAAO,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE;QACvD,MAAM,IAAI,GAAG,eAAe,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA;QACjD,OAAO;YACL,OAAO,EAAE,SAAS,MAAM,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,IAAI,IAAI,EAAE;YAC9D,KAAK;YACL,IAAI;YACJ,KAAK,EAAE,KAAK,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS;SACnD,CAAA;IACH,CAAC,CAAC,CAAA;AACJ,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { Fault } from "../domain/schema.js";
|
|
2
|
+
import type { TrialExecutor } from "../runner/playwright-executor.js";
|
|
3
|
+
export interface ExperimentOptions {
|
|
4
|
+
concurrency: number;
|
|
5
|
+
fault?: Fault;
|
|
6
|
+
minimumFailureRate: number;
|
|
7
|
+
seed: number;
|
|
8
|
+
signal?: AbortSignal;
|
|
9
|
+
trials: number;
|
|
10
|
+
}
|
|
11
|
+
export interface ExperimentResult {
|
|
12
|
+
confirmed: boolean;
|
|
13
|
+
dominantFailureSignature?: string;
|
|
14
|
+
dominantFailureReason?: string;
|
|
15
|
+
errors: number;
|
|
16
|
+
failed: number;
|
|
17
|
+
failureRate: number;
|
|
18
|
+
lowerBound80: number;
|
|
19
|
+
passed: number;
|
|
20
|
+
trials: number;
|
|
21
|
+
}
|
|
22
|
+
export declare function evaluateExperiment(execute: TrialExecutor, options: ExperimentOptions): Promise<ExperimentResult>;
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { deriveTrialSeed } from "../core/plan.js";
|
|
2
|
+
const WILSON_Z_80 = 1.281_551_565_545;
|
|
3
|
+
function lowerWilsonBound(failures, trials) {
|
|
4
|
+
if (trials === 0) {
|
|
5
|
+
return 0;
|
|
6
|
+
}
|
|
7
|
+
const probability = failures / trials;
|
|
8
|
+
const squaredZ = WILSON_Z_80 ** 2;
|
|
9
|
+
const denominator = 1 + squaredZ / trials;
|
|
10
|
+
const center = probability + squaredZ / (2 * trials);
|
|
11
|
+
const margin = WILSON_Z_80 * Math.sqrt((probability * (1 - probability) + squaredZ / (4 * trials)) / trials);
|
|
12
|
+
return Math.max(0, (center - margin) / denominator);
|
|
13
|
+
}
|
|
14
|
+
function dominantSignature(outcomes) {
|
|
15
|
+
const counts = new Map();
|
|
16
|
+
for (const outcome of outcomes) {
|
|
17
|
+
if (outcome.status === "failed" && outcome.failureSignature) {
|
|
18
|
+
counts.set(outcome.failureSignature, (counts.get(outcome.failureSignature) ?? 0) + 1);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
return [...counts.entries()].sort((left, right) => right[1] - left[1])[0]?.[0];
|
|
22
|
+
}
|
|
23
|
+
function dominantReason(outcomes, signature) {
|
|
24
|
+
return outcomes.find((outcome) => outcome.failureSignature === signature && outcome.failureReason)?.failureReason;
|
|
25
|
+
}
|
|
26
|
+
function validateOptions(options) {
|
|
27
|
+
if (!Number.isInteger(options.trials) || options.trials < 2 || options.trials > 100) {
|
|
28
|
+
throw new Error("experiment trials must be an integer between 2 and 100");
|
|
29
|
+
}
|
|
30
|
+
if (!Number.isInteger(options.concurrency) || options.concurrency < 1 || options.concurrency > 32) {
|
|
31
|
+
throw new Error("experiment concurrency must be an integer between 1 and 32");
|
|
32
|
+
}
|
|
33
|
+
if (options.minimumFailureRate <= 0 || options.minimumFailureRate > 1) {
|
|
34
|
+
throw new Error("minimum failure rate must be greater than 0 and at most 1");
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
export async function evaluateExperiment(execute, options) {
|
|
38
|
+
validateOptions(options);
|
|
39
|
+
const plans = Array.from({ length: options.trials }, (_, index) => ({
|
|
40
|
+
trialId: `experiment-${index + 1}`,
|
|
41
|
+
index,
|
|
42
|
+
seed: deriveTrialSeed(options.seed, index),
|
|
43
|
+
fault: options.fault,
|
|
44
|
+
}));
|
|
45
|
+
const outcomes = new Map();
|
|
46
|
+
let nextIndex = 0;
|
|
47
|
+
const worker = async () => {
|
|
48
|
+
while (!options.signal?.aborted) {
|
|
49
|
+
const index = nextIndex;
|
|
50
|
+
nextIndex += 1;
|
|
51
|
+
if (index >= plans.length) {
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
outcomes.set(index, await execute(plans[index]));
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
await Promise.all(Array.from({ length: Math.min(options.concurrency, plans.length) }, worker));
|
|
58
|
+
const completed = [...outcomes.entries()]
|
|
59
|
+
.sort((left, right) => left[0] - right[0])
|
|
60
|
+
.map((entry) => entry[1]);
|
|
61
|
+
const failed = completed.filter((outcome) => outcome.status === "failed").length;
|
|
62
|
+
const errors = completed.filter((outcome) => outcome.status === "error").length;
|
|
63
|
+
const passed = completed.filter((outcome) => outcome.status === "passed").length;
|
|
64
|
+
const failureRate = completed.length === 0 ? 0 : failed / completed.length;
|
|
65
|
+
const lowerBound80 = lowerWilsonBound(failed, completed.length);
|
|
66
|
+
const dominantFailureSignature = dominantSignature(completed);
|
|
67
|
+
return {
|
|
68
|
+
confirmed: errors === 0
|
|
69
|
+
&& failureRate >= options.minimumFailureRate
|
|
70
|
+
&& lowerBound80 >= options.minimumFailureRate,
|
|
71
|
+
dominantFailureSignature,
|
|
72
|
+
dominantFailureReason: dominantReason(completed, dominantFailureSignature),
|
|
73
|
+
errors,
|
|
74
|
+
failed,
|
|
75
|
+
failureRate,
|
|
76
|
+
lowerBound80,
|
|
77
|
+
passed,
|
|
78
|
+
trials: completed.length,
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=evaluate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"evaluate.js","sourceRoot":"","sources":["../../src/discovery/evaluate.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { NetworkDelayFault } from "../domain/schema.js";
|
|
2
|
+
import type { TrialExecutor } from "../runner/playwright-executor.js";
|
|
3
|
+
import type { ExperimentResult } from "./evaluate.js";
|
|
4
|
+
export interface DelayDiscoveryOptions {
|
|
5
|
+
concurrency: number;
|
|
6
|
+
maximumDelayMs: number;
|
|
7
|
+
minimumFailureRate: number;
|
|
8
|
+
pattern: string;
|
|
9
|
+
seed: number;
|
|
10
|
+
signal?: AbortSignal;
|
|
11
|
+
trials: number;
|
|
12
|
+
}
|
|
13
|
+
export interface DelayExperiment {
|
|
14
|
+
delayMs: number;
|
|
15
|
+
result: ExperimentResult;
|
|
16
|
+
}
|
|
17
|
+
export interface DelayDiscoveryResult {
|
|
18
|
+
baseline: ExperimentResult;
|
|
19
|
+
experiments: DelayExperiment[];
|
|
20
|
+
trigger: NetworkDelayFault;
|
|
21
|
+
triggerResult: ExperimentResult;
|
|
22
|
+
}
|
|
23
|
+
export declare function minimizeItems<T>(values: readonly T[], reproduces: (candidate: readonly T[]) => Promise<boolean>): Promise<T[]>;
|
|
24
|
+
export declare function discoverNetworkDelay(execute: TrialExecutor, options: DelayDiscoveryOptions): Promise<DelayDiscoveryResult>;
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { evaluateExperiment } from "./evaluate.js";
|
|
2
|
+
const MINIMUM_CONFIRMATION_TRIALS = 12;
|
|
3
|
+
async function confirmStableDelay(experiments, minimumDelayMs, evaluateDelay, confirmationTrials) {
|
|
4
|
+
const candidates = [...new Set(experiments
|
|
5
|
+
.filter((entry) => entry.delayMs >= minimumDelayMs && entry.result.confirmed)
|
|
6
|
+
.map((entry) => entry.delayMs))]
|
|
7
|
+
.sort((left, right) => left - right);
|
|
8
|
+
for (const delayMs of candidates) {
|
|
9
|
+
const result = await evaluateDelay(delayMs, confirmationTrials);
|
|
10
|
+
if (result.confirmed) {
|
|
11
|
+
return { delayMs, result };
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
throw new Error("No network delay reproduced the failure in two independent trial batches");
|
|
15
|
+
}
|
|
16
|
+
export async function minimizeItems(values, reproduces) {
|
|
17
|
+
let minimal = [...values];
|
|
18
|
+
let index = 0;
|
|
19
|
+
while (index < minimal.length) {
|
|
20
|
+
const candidate = minimal.filter((_value, candidateIndex) => candidateIndex !== index);
|
|
21
|
+
if (candidate.length > 0 && await reproduces(candidate)) {
|
|
22
|
+
minimal = candidate;
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
index += 1;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return minimal;
|
|
29
|
+
}
|
|
30
|
+
export async function discoverNetworkDelay(execute, options) {
|
|
31
|
+
const common = {
|
|
32
|
+
concurrency: options.concurrency,
|
|
33
|
+
minimumFailureRate: options.minimumFailureRate,
|
|
34
|
+
seed: options.seed,
|
|
35
|
+
signal: options.signal,
|
|
36
|
+
trials: options.trials,
|
|
37
|
+
};
|
|
38
|
+
const baseline = await evaluateExperiment(execute, common);
|
|
39
|
+
if (baseline.failureRate > 0) {
|
|
40
|
+
throw new Error("Baseline failures must be resolved before fault minimization");
|
|
41
|
+
}
|
|
42
|
+
const experiments = [];
|
|
43
|
+
const evaluateDelay = async (delayMs, trials = options.trials) => {
|
|
44
|
+
const fault = { kind: "network-delay", pattern: options.pattern, delayMs };
|
|
45
|
+
const result = await evaluateExperiment(execute, { ...common, fault, trials });
|
|
46
|
+
experiments.push({ delayMs, result });
|
|
47
|
+
return result;
|
|
48
|
+
};
|
|
49
|
+
const maximum = await evaluateDelay(options.maximumDelayMs);
|
|
50
|
+
if (!maximum.confirmed) {
|
|
51
|
+
throw new Error("Maximum network delay did not reproduce the failure confidently");
|
|
52
|
+
}
|
|
53
|
+
let passingDelayMs = 0;
|
|
54
|
+
let failingDelayMs = options.maximumDelayMs;
|
|
55
|
+
while (failingDelayMs - passingDelayMs > 1) {
|
|
56
|
+
const candidate = Math.floor((passingDelayMs + failingDelayMs) / 2);
|
|
57
|
+
const result = await evaluateDelay(candidate);
|
|
58
|
+
if (result.confirmed) {
|
|
59
|
+
failingDelayMs = candidate;
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
passingDelayMs = candidate;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
const stable = await confirmStableDelay(experiments, failingDelayMs, evaluateDelay, Math.max(options.trials, MINIMUM_CONFIRMATION_TRIALS));
|
|
66
|
+
return {
|
|
67
|
+
baseline,
|
|
68
|
+
experiments,
|
|
69
|
+
trigger: { kind: "network-delay", pattern: options.pattern, delayMs: stable.delayMs },
|
|
70
|
+
triggerResult: stable.result,
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=minimize.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"minimize.js","sourceRoot":"","sources":["../../src/discovery/minimize.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export declare const networkDelayFaultSchema: z.ZodObject<{
|
|
3
|
+
kind: z.ZodLiteral<"network-delay">;
|
|
4
|
+
pattern: z.ZodString;
|
|
5
|
+
delayMs: z.ZodNumber;
|
|
6
|
+
}, z.core.$strip>;
|
|
7
|
+
export declare const requestFailureFaultSchema: z.ZodObject<{
|
|
8
|
+
kind: z.ZodLiteral<"request-failure">;
|
|
9
|
+
pattern: z.ZodString;
|
|
10
|
+
statusCode: z.ZodNumber;
|
|
11
|
+
}, z.core.$strip>;
|
|
12
|
+
export declare const faultSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
13
|
+
kind: z.ZodLiteral<"network-delay">;
|
|
14
|
+
pattern: z.ZodString;
|
|
15
|
+
delayMs: z.ZodNumber;
|
|
16
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
17
|
+
kind: z.ZodLiteral<"request-failure">;
|
|
18
|
+
pattern: z.ZodString;
|
|
19
|
+
statusCode: z.ZodNumber;
|
|
20
|
+
}, z.core.$strip>], "kind">;
|
|
21
|
+
export declare const runRequestSchema: z.ZodObject<{
|
|
22
|
+
selector: z.ZodString;
|
|
23
|
+
runs: z.ZodNumber;
|
|
24
|
+
seed: z.ZodNumber;
|
|
25
|
+
artifactDirectory: z.ZodString;
|
|
26
|
+
fault: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
27
|
+
kind: z.ZodLiteral<"network-delay">;
|
|
28
|
+
pattern: z.ZodString;
|
|
29
|
+
delayMs: z.ZodNumber;
|
|
30
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
31
|
+
kind: z.ZodLiteral<"request-failure">;
|
|
32
|
+
pattern: z.ZodString;
|
|
33
|
+
statusCode: z.ZodNumber;
|
|
34
|
+
}, z.core.$strip>], "kind">;
|
|
35
|
+
}, z.core.$strip>;
|
|
36
|
+
export declare const trialPlanSchema: z.ZodObject<{
|
|
37
|
+
trialId: z.ZodString;
|
|
38
|
+
index: z.ZodNumber;
|
|
39
|
+
seed: z.ZodNumber;
|
|
40
|
+
fault: z.ZodOptional<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
41
|
+
kind: z.ZodLiteral<"network-delay">;
|
|
42
|
+
pattern: z.ZodString;
|
|
43
|
+
delayMs: z.ZodNumber;
|
|
44
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
45
|
+
kind: z.ZodLiteral<"request-failure">;
|
|
46
|
+
pattern: z.ZodString;
|
|
47
|
+
statusCode: z.ZodNumber;
|
|
48
|
+
}, z.core.$strip>], "kind">>;
|
|
49
|
+
}, z.core.$strip>;
|
|
50
|
+
export declare const trialOutcomeSchema: z.ZodObject<{
|
|
51
|
+
status: z.ZodEnum<{
|
|
52
|
+
error: "error";
|
|
53
|
+
passed: "passed";
|
|
54
|
+
failed: "failed";
|
|
55
|
+
}>;
|
|
56
|
+
durationMs: z.ZodNumber;
|
|
57
|
+
exitCode: z.ZodNullable<z.ZodNumber>;
|
|
58
|
+
failureSignature: z.ZodOptional<z.ZodString>;
|
|
59
|
+
failureReason: z.ZodOptional<z.ZodString>;
|
|
60
|
+
}, z.core.$strip>;
|
|
61
|
+
export declare const runSummarySchema: z.ZodObject<{
|
|
62
|
+
total: z.ZodNumber;
|
|
63
|
+
passed: z.ZodNumber;
|
|
64
|
+
failed: z.ZodNumber;
|
|
65
|
+
errors: z.ZodNumber;
|
|
66
|
+
baselineFailureRate: z.ZodNumber;
|
|
67
|
+
faultFailureRate: z.ZodNumber;
|
|
68
|
+
}, z.core.$strip>;
|
|
69
|
+
export declare const runEventSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
70
|
+
runId: z.ZodString;
|
|
71
|
+
timestamp: z.ZodISODateTime;
|
|
72
|
+
type: z.ZodLiteral<"run.started">;
|
|
73
|
+
request: z.ZodObject<{
|
|
74
|
+
selector: z.ZodString;
|
|
75
|
+
runs: z.ZodNumber;
|
|
76
|
+
seed: z.ZodNumber;
|
|
77
|
+
artifactDirectory: z.ZodString;
|
|
78
|
+
fault: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
79
|
+
kind: z.ZodLiteral<"network-delay">;
|
|
80
|
+
pattern: z.ZodString;
|
|
81
|
+
delayMs: z.ZodNumber;
|
|
82
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
83
|
+
kind: z.ZodLiteral<"request-failure">;
|
|
84
|
+
pattern: z.ZodString;
|
|
85
|
+
statusCode: z.ZodNumber;
|
|
86
|
+
}, z.core.$strip>], "kind">;
|
|
87
|
+
}, z.core.$strip>;
|
|
88
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
89
|
+
runId: z.ZodString;
|
|
90
|
+
timestamp: z.ZodISODateTime;
|
|
91
|
+
type: z.ZodLiteral<"trial.started">;
|
|
92
|
+
trial: z.ZodObject<{
|
|
93
|
+
trialId: z.ZodString;
|
|
94
|
+
index: z.ZodNumber;
|
|
95
|
+
seed: z.ZodNumber;
|
|
96
|
+
fault: z.ZodOptional<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
97
|
+
kind: z.ZodLiteral<"network-delay">;
|
|
98
|
+
pattern: z.ZodString;
|
|
99
|
+
delayMs: z.ZodNumber;
|
|
100
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
101
|
+
kind: z.ZodLiteral<"request-failure">;
|
|
102
|
+
pattern: z.ZodString;
|
|
103
|
+
statusCode: z.ZodNumber;
|
|
104
|
+
}, z.core.$strip>], "kind">>;
|
|
105
|
+
}, z.core.$strip>;
|
|
106
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
107
|
+
runId: z.ZodString;
|
|
108
|
+
timestamp: z.ZodISODateTime;
|
|
109
|
+
type: z.ZodLiteral<"trial.completed">;
|
|
110
|
+
trial: z.ZodObject<{
|
|
111
|
+
trialId: z.ZodString;
|
|
112
|
+
index: z.ZodNumber;
|
|
113
|
+
seed: z.ZodNumber;
|
|
114
|
+
fault: z.ZodOptional<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
115
|
+
kind: z.ZodLiteral<"network-delay">;
|
|
116
|
+
pattern: z.ZodString;
|
|
117
|
+
delayMs: z.ZodNumber;
|
|
118
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
119
|
+
kind: z.ZodLiteral<"request-failure">;
|
|
120
|
+
pattern: z.ZodString;
|
|
121
|
+
statusCode: z.ZodNumber;
|
|
122
|
+
}, z.core.$strip>], "kind">>;
|
|
123
|
+
}, z.core.$strip>;
|
|
124
|
+
outcome: z.ZodObject<{
|
|
125
|
+
status: z.ZodEnum<{
|
|
126
|
+
error: "error";
|
|
127
|
+
passed: "passed";
|
|
128
|
+
failed: "failed";
|
|
129
|
+
}>;
|
|
130
|
+
durationMs: z.ZodNumber;
|
|
131
|
+
exitCode: z.ZodNullable<z.ZodNumber>;
|
|
132
|
+
failureSignature: z.ZodOptional<z.ZodString>;
|
|
133
|
+
failureReason: z.ZodOptional<z.ZodString>;
|
|
134
|
+
}, z.core.$strip>;
|
|
135
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
136
|
+
runId: z.ZodString;
|
|
137
|
+
timestamp: z.ZodISODateTime;
|
|
138
|
+
type: z.ZodLiteral<"run.completed">;
|
|
139
|
+
summary: z.ZodObject<{
|
|
140
|
+
total: z.ZodNumber;
|
|
141
|
+
passed: z.ZodNumber;
|
|
142
|
+
failed: z.ZodNumber;
|
|
143
|
+
errors: z.ZodNumber;
|
|
144
|
+
baselineFailureRate: z.ZodNumber;
|
|
145
|
+
faultFailureRate: z.ZodNumber;
|
|
146
|
+
}, z.core.$strip>;
|
|
147
|
+
}, z.core.$strip>], "type">;
|
|
148
|
+
export type Fault = z.infer<typeof faultSchema>;
|
|
149
|
+
export type NetworkDelayFault = z.infer<typeof networkDelayFaultSchema>;
|
|
150
|
+
export type RequestFailureFault = z.infer<typeof requestFailureFaultSchema>;
|
|
151
|
+
export type RunEvent = z.infer<typeof runEventSchema>;
|
|
152
|
+
export type RunRequest = z.infer<typeof runRequestSchema>;
|
|
153
|
+
export type RunSummary = z.infer<typeof runSummarySchema>;
|
|
154
|
+
export type TrialOutcome = z.infer<typeof trialOutcomeSchema>;
|
|
155
|
+
export type TrialPlan = z.infer<typeof trialPlanSchema>;
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export const networkDelayFaultSchema = z.object({
|
|
3
|
+
kind: z.literal("network-delay"),
|
|
4
|
+
pattern: z.string().min(1),
|
|
5
|
+
delayMs: z.number().int().min(1).max(30_000),
|
|
6
|
+
});
|
|
7
|
+
export const requestFailureFaultSchema = z.object({
|
|
8
|
+
kind: z.literal("request-failure"),
|
|
9
|
+
pattern: z.string().min(1),
|
|
10
|
+
statusCode: z.number().int().min(400).max(599),
|
|
11
|
+
});
|
|
12
|
+
export const faultSchema = z.discriminatedUnion("kind", [
|
|
13
|
+
networkDelayFaultSchema,
|
|
14
|
+
requestFailureFaultSchema,
|
|
15
|
+
]);
|
|
16
|
+
export const runRequestSchema = z.object({
|
|
17
|
+
selector: z.string().min(1),
|
|
18
|
+
runs: z.number().int().min(2).max(100),
|
|
19
|
+
seed: z.number().int().min(0).max(0xffff_ffff),
|
|
20
|
+
artifactDirectory: z.string().min(1),
|
|
21
|
+
fault: faultSchema,
|
|
22
|
+
});
|
|
23
|
+
export const trialPlanSchema = z.object({
|
|
24
|
+
trialId: z.string().min(1),
|
|
25
|
+
index: z.number().int().nonnegative(),
|
|
26
|
+
seed: z.number().int().min(0).max(0xffff_ffff),
|
|
27
|
+
fault: faultSchema.optional(),
|
|
28
|
+
});
|
|
29
|
+
export const trialOutcomeSchema = z.object({
|
|
30
|
+
status: z.enum(["passed", "failed", "error"]),
|
|
31
|
+
durationMs: z.number().int().nonnegative(),
|
|
32
|
+
exitCode: z.number().int().nullable(),
|
|
33
|
+
failureSignature: z.string().min(1).optional(),
|
|
34
|
+
failureReason: z.string().min(1).max(2_000).optional(),
|
|
35
|
+
});
|
|
36
|
+
export const runSummarySchema = z.object({
|
|
37
|
+
total: z.number().int().nonnegative(),
|
|
38
|
+
passed: z.number().int().nonnegative(),
|
|
39
|
+
failed: z.number().int().nonnegative(),
|
|
40
|
+
errors: z.number().int().nonnegative(),
|
|
41
|
+
baselineFailureRate: z.number().min(0).max(1),
|
|
42
|
+
faultFailureRate: z.number().min(0).max(1),
|
|
43
|
+
});
|
|
44
|
+
const eventBaseSchema = z.object({
|
|
45
|
+
runId: z.string().min(1),
|
|
46
|
+
timestamp: z.iso.datetime(),
|
|
47
|
+
});
|
|
48
|
+
export const runEventSchema = z.discriminatedUnion("type", [
|
|
49
|
+
eventBaseSchema.extend({
|
|
50
|
+
type: z.literal("run.started"),
|
|
51
|
+
request: runRequestSchema,
|
|
52
|
+
}),
|
|
53
|
+
eventBaseSchema.extend({
|
|
54
|
+
type: z.literal("trial.started"),
|
|
55
|
+
trial: trialPlanSchema,
|
|
56
|
+
}),
|
|
57
|
+
eventBaseSchema.extend({
|
|
58
|
+
type: z.literal("trial.completed"),
|
|
59
|
+
trial: trialPlanSchema,
|
|
60
|
+
outcome: trialOutcomeSchema,
|
|
61
|
+
}),
|
|
62
|
+
eventBaseSchema.extend({
|
|
63
|
+
type: z.literal("run.completed"),
|
|
64
|
+
summary: runSummarySchema,
|
|
65
|
+
}),
|
|
66
|
+
]);
|
|
67
|
+
//# sourceMappingURL=schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/domain/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC9C,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,eAAe,CAAC;IAChC,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC1B,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC;CAC7C,CAAC,CAAA;AAEF,MAAM,CAAC,MAAM,yBAAyB,GAAG,CAAC,CAAC,MAAM,CAAC;IAChD,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,iBAAiB,CAAC;IAClC,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC1B,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC;CAC/C,CAAC,CAAA;AAEF,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,CAAC,kBAAkB,CAAC,MAAM,EAAE;IACtD,uBAAuB;IACvB,yBAAyB;CAC1B,CAAC,CAAA;AAEF,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,CAAC,MAAM,CAAC;IACvC,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC3B,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC;IACtC,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,WAAW,CAAC;IAC9C,iBAAiB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACpC,KAAK,EAAE,WAAW;CACnB,CAAC,CAAA;AAEF,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,CAAC,MAAM,CAAC;IACtC,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC1B,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE;IACrC,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,WAAW,CAAC;IAC9C,KAAK,EAAE,WAAW,CAAC,QAAQ,EAAE;CAC9B,CAAC,CAAA;AAEF,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,CAAC,MAAM,CAAC;IACzC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;IAC7C,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE;IAC1C,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;IACrC,gBAAgB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;IAC9C,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,QAAQ,EAAE;CACvD,CAAC,CAAA;AAEF,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,CAAC,MAAM,CAAC;IACvC,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE;IACrC,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE;IACtC,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE;IACtC,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE;IACtC,mBAAmB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IAC7C,gBAAgB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;CAC3C,CAAC,CAAA;AAEF,MAAM,eAAe,GAAG,CAAC,CAAC,MAAM,CAAC;IAC/B,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACxB,SAAS,EAAE,CAAC,CAAC,GAAG,CAAC,QAAQ,EAAE;CAC5B,CAAC,CAAA;AAEF,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,CAAC,kBAAkB,CAAC,MAAM,EAAE;IACzD,eAAe,CAAC,MAAM,CAAC;QACrB,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,aAAa,CAAC;QAC9B,OAAO,EAAE,gBAAgB;KAC1B,CAAC;IACF,eAAe,CAAC,MAAM,CAAC;QACrB,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,eAAe,CAAC;QAChC,KAAK,EAAE,eAAe;KACvB,CAAC;IACF,eAAe,CAAC,MAAM,CAAC;QACrB,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,iBAAiB,CAAC;QAClC,KAAK,EAAE,eAAe;QACtB,OAAO,EAAE,kBAAkB;KAC5B,CAAC;IACF,eAAe,CAAC,MAAM,CAAC;QACrB,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,eAAe,CAAC;QAChC,OAAO,EAAE,gBAAgB;KAC1B,CAAC;CACH,CAAC,CAAA"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { installNetworkDelay } from "./network-delay.js";
|
|
2
|
+
import { installRequestFailure } from "./request-failure.js";
|
|
3
|
+
export async function installFault(page, fault) {
|
|
4
|
+
if (fault.kind === "network-delay") {
|
|
5
|
+
return installNetworkDelay(page, fault);
|
|
6
|
+
}
|
|
7
|
+
return installRequestFailure(page, fault);
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=install.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"install.js","sourceRoot":"","sources":["../../src/faults/install.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAA;AACxD,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAA;AAI5D,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,IAAU,EAAE,KAAY;IACzD,IAAI,KAAK,CAAC,IAAI,KAAK,eAAe,EAAE,CAAC;QACnC,OAAO,mBAAmB,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA;IACzC,CAAC;IACD,OAAO,qBAAqB,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA;AAC3C,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { Page } from "@playwright/test";
|
|
2
|
+
import type { NetworkDelayFault } from "../domain/schema.js";
|
|
3
|
+
export type RemoveNetworkDelay = () => Promise<void>;
|
|
4
|
+
export declare function installNetworkDelay(page: Page, fault: NetworkDelayFault): Promise<RemoveNetworkDelay>;
|
|
5
|
+
export declare function readNetworkDelayFromEnvironment(): NetworkDelayFault | undefined;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { setTimeout as delay } from "node:timers/promises";
|
|
2
|
+
import { networkDelayFaultSchema } from "../domain/schema.js";
|
|
3
|
+
async function continueRoute(route) {
|
|
4
|
+
try {
|
|
5
|
+
await route.continue();
|
|
6
|
+
}
|
|
7
|
+
catch (error) {
|
|
8
|
+
const releasedDuringCleanup = error instanceof Error && error.message.includes("Route is already handled");
|
|
9
|
+
if (!releasedDuringCleanup) {
|
|
10
|
+
throw error;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
export async function installNetworkDelay(page, fault) {
|
|
15
|
+
const validatedFault = networkDelayFaultSchema.parse(fault);
|
|
16
|
+
const handler = async (route) => {
|
|
17
|
+
await delay(validatedFault.delayMs);
|
|
18
|
+
await continueRoute(route);
|
|
19
|
+
};
|
|
20
|
+
await page.route(validatedFault.pattern, handler);
|
|
21
|
+
return async () => page.unroute(validatedFault.pattern, handler);
|
|
22
|
+
}
|
|
23
|
+
export function readNetworkDelayFromEnvironment() {
|
|
24
|
+
if (process.env.FLAKELAB_FAULT_KIND === "request-failure") {
|
|
25
|
+
return undefined;
|
|
26
|
+
}
|
|
27
|
+
const delayMs = Number(process.env.FLAKELAB_NETWORK_DELAY_MS ?? "0");
|
|
28
|
+
const pattern = process.env.FLAKELAB_NETWORK_PATTERN?.trim();
|
|
29
|
+
if (!pattern || delayMs <= 0) {
|
|
30
|
+
return undefined;
|
|
31
|
+
}
|
|
32
|
+
return networkDelayFaultSchema.parse({ kind: "network-delay", pattern, delayMs });
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=network-delay.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"network-delay.js","sourceRoot":"","sources":["../../src/faults/network-delay.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,IAAI,KAAK,EAAE,MAAM,sBAAsB,CAAA;AAE1D,OAAO,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAA;AAI7D,KAAK,UAAU,aAAa,CAAC,KAAY;IACvC,IAAI,CAAC;QACH,MAAM,KAAK,CAAC,QAAQ,EAAE,CAAA;IACxB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,qBAAqB,GACzB,KAAK,YAAY,KAAK,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,0BAA0B,CAAC,CAAA;QAC9E,IAAI,CAAC,qBAAqB,EAAE,CAAC;YAC3B,MAAM,KAAK,CAAA;QACb,CAAC;IACH,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,IAAU,EACV,KAAwB;IAExB,MAAM,cAAc,GAAG,uBAAuB,CAAC,KAAK,CAAC,KAAK,CAAC,CAAA;IAC3D,MAAM,OAAO,GAAG,KAAK,EAAE,KAAY,EAAiB,EAAE;QACpD,MAAM,KAAK,CAAC,cAAc,CAAC,OAAO,CAAC,CAAA;QACnC,MAAM,aAAa,CAAC,KAAK,CAAC,CAAA;IAC5B,CAAC,CAAA;IAED,MAAM,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;IACjD,OAAO,KAAK,IAAI,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;AAClE,CAAC;AAED,MAAM,UAAU,+BAA+B;IAC7C,IAAI,OAAO,CAAC,GAAG,CAAC,mBAAmB,KAAK,iBAAiB,EAAE,CAAC;QAC1D,OAAO,SAAS,CAAA;IAClB,CAAC;IACD,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,yBAAyB,IAAI,GAAG,CAAC,CAAA;IACpE,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,wBAAwB,EAAE,IAAI,EAAE,CAAA;IAC5D,IAAI,CAAC,OAAO,IAAI,OAAO,IAAI,CAAC,EAAE,CAAC;QAC7B,OAAO,SAAS,CAAA;IAClB,CAAC;IACD,OAAO,uBAAuB,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,eAAe,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAA;AACnF,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { Page } from "@playwright/test";
|
|
2
|
+
import type { RequestFailureFault } from "../domain/schema.js";
|
|
3
|
+
export type RemoveRequestFailure = () => Promise<void>;
|
|
4
|
+
export declare function installRequestFailure(page: Page, fault: RequestFailureFault): Promise<RemoveRequestFailure>;
|
|
5
|
+
export declare function readRequestFailureFromEnvironment(): RequestFailureFault | undefined;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { requestFailureFaultSchema } from "../domain/schema.js";
|
|
2
|
+
export async function installRequestFailure(page, fault) {
|
|
3
|
+
const validatedFault = requestFailureFaultSchema.parse(fault);
|
|
4
|
+
const handler = async (route) => {
|
|
5
|
+
await route.fulfill({
|
|
6
|
+
status: validatedFault.statusCode,
|
|
7
|
+
contentType: "application/json",
|
|
8
|
+
body: '{"error":"flakelab-injected-failure"}',
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
await page.route(validatedFault.pattern, handler);
|
|
12
|
+
return async () => page.unroute(validatedFault.pattern, handler);
|
|
13
|
+
}
|
|
14
|
+
export function readRequestFailureFromEnvironment() {
|
|
15
|
+
if (process.env.FLAKELAB_FAULT_KIND !== "request-failure") {
|
|
16
|
+
return undefined;
|
|
17
|
+
}
|
|
18
|
+
return requestFailureFaultSchema.parse({
|
|
19
|
+
kind: "request-failure",
|
|
20
|
+
pattern: process.env.FLAKELAB_NETWORK_PATTERN,
|
|
21
|
+
statusCode: Number(process.env.FLAKELAB_REQUEST_FAILURE_STATUS ?? "503"),
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=request-failure.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"request-failure.js","sourceRoot":"","sources":["../../src/faults/request-failure.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,yBAAyB,EAAE,MAAM,qBAAqB,CAAA;AAI/D,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,IAAU,EACV,KAA0B;IAE1B,MAAM,cAAc,GAAG,yBAAyB,CAAC,KAAK,CAAC,KAAK,CAAC,CAAA;IAC7D,MAAM,OAAO,GAAG,KAAK,EAAE,KAAY,EAAiB,EAAE;QACpD,MAAM,KAAK,CAAC,OAAO,CAAC;YAClB,MAAM,EAAE,cAAc,CAAC,UAAU;YACjC,WAAW,EAAE,kBAAkB;YAC/B,IAAI,EAAE,uCAAuC;SAC9C,CAAC,CAAA;IACJ,CAAC,CAAA;IACD,MAAM,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;IACjD,OAAO,KAAK,IAAI,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;AAClE,CAAC;AAED,MAAM,UAAU,iCAAiC;IAC/C,IAAI,OAAO,CAAC,GAAG,CAAC,mBAAmB,KAAK,iBAAiB,EAAE,CAAC;QAC1D,OAAO,SAAS,CAAA;IAClB,CAAC;IACD,OAAO,yBAAyB,CAAC,KAAK,CAAC;QACrC,IAAI,EAAE,iBAAiB;QACvB,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,wBAAwB;QAC7C,UAAU,EAAE,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,+BAA+B,IAAI,KAAK,CAAC;KACzE,CAAC,CAAA;AACJ,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { LanguageModel } from "ai";
|
|
2
|
+
import type { TrialExecutor } from "../runner/playwright-executor.js";
|
|
3
|
+
import type { InvestigationReport } from "./schema.js";
|
|
4
|
+
export interface InvestigatorOptions {
|
|
5
|
+
concurrency: number;
|
|
6
|
+
execute: TrialExecutor;
|
|
7
|
+
inputUsdPerMillion: number;
|
|
8
|
+
maxCostUsd: number;
|
|
9
|
+
maxExperiments: number;
|
|
10
|
+
maximumDelayMs: number;
|
|
11
|
+
maxSeconds: number;
|
|
12
|
+
maxSteps: number;
|
|
13
|
+
maxTrials: number;
|
|
14
|
+
minimumFailureRate: number;
|
|
15
|
+
model: LanguageModel;
|
|
16
|
+
modelId: string;
|
|
17
|
+
outputTokenLimit: number;
|
|
18
|
+
outputUsdPerMillion: number;
|
|
19
|
+
pattern: string;
|
|
20
|
+
projectRoot: string;
|
|
21
|
+
seed: number;
|
|
22
|
+
signal?: AbortSignal;
|
|
23
|
+
test: string;
|
|
24
|
+
trialsPerExperiment: number;
|
|
25
|
+
}
|
|
26
|
+
export declare function runInvestigation(options: InvestigatorOptions): Promise<InvestigationReport>;
|