@systemfsoftware/stryker-js 11.0.0 → 12.0.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.
@@ -1,7 +1,6 @@
1
- import { a as Reporter_exports, c as ErrorText_exports, d as Mutant_exports, i as Report_exports, l as Format_exports, n as Options_exports, o as TestRunner_exports, r as Plugin_exports, s as Trace_exports$1, t as Checker_exports, u as Instrument_exports } from "./dist-ClUhPgb6.mjs";
2
- import { t as StrykerConfig } from "./stryker-config.schema-CCnDtVuW.mjs";
3
- import { D as VerdictReached, E as SkippedReported, _ as PluginsReported, b as RunFailed$1, c as Heartbeat, f as OutputMode, i as FormatRegistryResolved, l as HelpRendered, m as PlanKnown, n as StageError, p as PhaseEntered, t as PrepareError, u as ModeSignal, w as RunStarted, x as RunMutantTested, y as RunEvent } from "./Run.schema-B_qdjbe9.mjs";
4
- import { Cell, Sandwich, Workflow } from "@systemfsoftware/effect-cell-types";
1
+ import { A as Plugin_exports, D as VerdictReached, E as SkippedReported, F as ErrorText_exports, I as Format_exports, L as Instrument_exports, M as Reporter_exports, N as TestRunner_exports, O as Checker_exports, P as Trace_exports$1, R as Mutant_exports, _ as PluginsReported, b as RunFailed$1, c as Heartbeat, f as OutputMode, i as FormatRegistryResolved, j as Report_exports, k as Options_exports, l as HelpRendered, m as PlanKnown, n as StageError, p as PhaseEntered, t as PrepareError, u as ModeSignal, w as RunStarted, x as RunMutantTested, y as RunEvent } from "./Run.schema-BxsyHwHr.mjs";
2
+ import { t as mergeConfig } from "./merge-config-ByZJPeQZ.mjs";
3
+ import { Blueprint, Cell, Handle, Sandwich, Workflow } from "@systemfsoftware/effect-cell-types";
5
4
  import * as Boolean$1 from "effect/Boolean";
6
5
  import * as Match from "effect/Match";
7
6
  import * as Option$1 from "effect/Option";
@@ -9,22 +8,21 @@ import * as Predicate$1 from "effect/Predicate";
9
8
  import * as Result from "effect/Result";
10
9
  import * as S from "effect/Schema";
11
10
  import * as Effect$1 from "effect/Effect";
12
- import { absurd, dual } from "effect/Function";
11
+ import { absurd, dual, pipe } from "effect/Function";
13
12
  import * as Arr from "effect/Array";
14
13
  import * as SchemaGetter$1 from "effect/SchemaGetter";
15
- import { Prototype } from "effect/Pipeable";
16
14
  import * as Context from "effect/Context";
17
- import { Boolean, Option, Predicate, Schema, SchemaGetter } from "effect";
15
+ import { Boolean, Option, Predicate, Schema, SchemaGetter, SchemaTransformation } from "effect";
16
+ import * as Exit from "effect/Exit";
18
17
  import * as RpcMiddleware from "effect/unstable/rpc/RpcMiddleware";
19
- import * as Metric from "effect/Metric";
20
18
  import * as Cause from "effect/Cause";
19
+ import * as Metric from "effect/Metric";
21
20
  import * as SchemaTransformation$1 from "effect/SchemaTransformation";
22
21
  import * as Record from "effect/Record";
23
22
  import * as Path from "effect/Path";
24
23
  import * as Config from "effect/Config";
25
24
  import * as FileSystem from "effect/FileSystem";
26
25
  import * as Clock from "effect/Clock";
27
- import * as Exit from "effect/Exit";
28
26
  import * as Stream from "effect/Stream";
29
27
  import * as ChildProcess from "effect/unstable/process/ChildProcess";
30
28
  import * as ChildProcessSpawner from "effect/unstable/process/ChildProcessSpawner";
@@ -61,8 +59,8 @@ import { RpcClientError } from "effect/unstable/rpc/RpcClientError";
61
59
  import * as Socket from "effect/unstable/socket/Socket";
62
60
  import * as NodeFileSystem$1 from "@effect/platform-node-shared/NodeFileSystem";
63
61
  import * as NodePath$1 from "@effect/platform-node-shared/NodePath";
64
- import * as Equivalence from "effect/Equivalence";
65
62
  import { badArgument } from "effect/PlatformError";
63
+ import * as Equivalence from "effect/Equivalence";
66
64
  import { Session } from "@systemfsoftware/stryker-vm-harness";
67
65
  import * as Console from "effect/Console";
68
66
  import * as Formatter from "effect/Formatter";
@@ -180,14 +178,15 @@ var WorkerBootTimeoutError = class extends Schema.TaggedError()("WorkerBootTimeo
180
178
  };
181
179
  //#endregion
182
180
  //#region src/Checker/Checker.handle.ts
183
- const TypeId$4 = Symbol.for("@systemfsoftware/stryker-js/CheckerHandle");
181
+ const TypeId$11 = Symbol.for("~systemfsoftware/stryker-js/Checker");
184
182
  const checkerDuration = Metric.timer("stryker.checker.duration", { description: "Checker worker RPC duration in milliseconds" });
185
183
  const checkerMutantsChecked = Metric.counter("stryker.checker.mutants.checked", { description: "Total number of mutants a checker worker answered for" });
186
184
  const checkerRpcFailures = Metric.counter("stryker.checker.rpc_failures", {
187
185
  description: "Checker worker RPC calls that did not complete, excluding interruptions",
188
186
  incremental: true
189
187
  });
190
- const ClientTypeId = Symbol.for("@systemfsoftware/stryker-js/CheckerHandle/client");
188
+ const CheckerHandle = Handle.make()(TypeId$11);
189
+ const isCheckerHandle = CheckerHandle.is;
191
190
  const connectionCrashed = (cause) => ChildProcessCrashedError.make({
192
191
  pid: 0,
193
192
  exit: {
@@ -200,24 +199,17 @@ const recordCheckerCall = (spanName, checkerName, mutants, call) => call.pipe(Ef
200
199
  "stryker.checker.name": checkerName,
201
200
  "stryker.mutants.count": mutants.length
202
201
  } }), Effect$1.timed, Effect$1.onExit((exit) => Match.value(exit).pipe(Match.tag("Success", () => Metric.update(checkerMutantsChecked, mutants.length)), Match.tag("Failure", (failure) => failure.cause.pipe(Cause.hasInterruptsOnly, Match.value, Match.when(true, () => Effect$1.void), Match.orElse(() => Metric.update(checkerRpcFailures, 1)))), Match.exhaustive)), Effect$1.tap(([duration]) => Metric.update(checkerDuration, duration)), Effect$1.map(([, result]) => result), Effect$1.mapError((error) => Match.value(error).pipe(Match.tag("CheckerFailed", (failed) => failed), Match.orElse((e) => connectionCrashed(e.message)))));
203
- const checkOf = (self, checkerName, mutants) => recordCheckerCall("stryker.checker.check", checkerName, mutants, self[ClientTypeId].check({
202
+ const checkOf = (self, checkerName, mutants) => recordCheckerCall("stryker.checker.check", checkerName, mutants, CheckerHandle.slot(self).check({
204
203
  checkerName,
205
204
  mutants: [...mutants]
206
205
  }));
207
- const groupOf$1 = (self, checkerName, mutants) => recordCheckerCall("stryker.checker.group", checkerName, mutants, self[ClientTypeId].group({
206
+ const groupOf$1 = (self, checkerName, mutants) => recordCheckerCall("stryker.checker.group", checkerName, mutants, CheckerHandle.slot(self).group({
208
207
  checkerName,
209
208
  mutants: [...mutants]
210
209
  }));
211
- const makeCheckerHandle = (client) => {
212
- const self = {
213
- [TypeId$4]: TypeId$4,
214
- [ClientTypeId]: client,
215
- ...Prototype,
216
- check: (checkerName, mutants) => checkOf(self, checkerName, mutants),
217
- group: (checkerName, mutants) => groupOf$1(self, checkerName, mutants)
218
- };
219
- return self;
220
- };
210
+ const check = dual((args) => isCheckerHandle(args[0]), (self, checkerName, mutants) => checkOf(self, checkerName, mutants));
211
+ const group = dual((args) => isCheckerHandle(args[0]), (self, checkerName, mutants) => groupOf$1(self, checkerName, mutants));
212
+ const makeCheckerHandle = (client) => CheckerHandle.make({}, client);
221
213
  //#endregion
222
214
  //#region src/Checker/Checker.schema.ts
223
215
  var UndescribableMutant = class extends S.TaggedError()("UndescribableMutant", {
@@ -245,7 +237,7 @@ const CheckerMutantFromMutant = S.decodeTo(CheckerMutant, SchemaTransformation$1
245
237
  })
246
238
  }))(Mutant_exports.Mutant);
247
239
  //#endregion
248
- //#region src/Checker/Checker.cell.ts
240
+ //#region src/Checker/Checker.parts.ts
249
241
  const plansById = (plans) => new Map(plans.map((plan) => [plan.mutant.id, plan]));
250
242
  const missingPlanIds = (plans, present) => plans.map((plan) => plan.mutant.id).filter((id) => !present.has(id));
251
243
  const answeredPlanIds = (paired) => new Set(paired.map(([plan]) => plan.mutant.id));
@@ -313,8 +305,8 @@ const pairGroups = (checkerName, plans, idGroups) => Match.value(partitionGroups
313
305
  unrequestedIds: [...partition.unrequested],
314
306
  requestedIds: plans.map((plan) => plan.mutant.id)
315
307
  }))), Match.orElse((partition) => admitGroupedPlans(checkerName, plans, partition)));
316
- const writeDecidedAnswers = (plans, checkerName, answers) => Effect$1.fromResult(pairCheckResults(checkerName, plans, Object.fromEntries(answers.map((answer) => [answer.id, answer.result]))));
317
- const writeDecidedGroups = (plans, checkerName, idGroups) => Effect$1.fromResult(pairGroups(checkerName, plans, idGroups));
308
+ const writeDecidedAnswers = (input) => Effect$1.fromResult(pairCheckResults(input.checkerName, input.plans, Object.fromEntries(input.answers.map((answer) => [answer.id, answer.result]))));
309
+ const writeDecidedGroups = (input) => Effect$1.fromResult(pairGroups(input.checkerName, input.plans, input.idGroups));
318
310
  const wireRecordOf = (mutant) => Result.mapError(S.decodeResult(CheckerMutantFromMutant)(mutant), (error) => UndescribableMutant.make({
319
311
  id: mutant.id,
320
312
  fileName: mutant.fileName,
@@ -356,7 +348,7 @@ const skippedIdsOf = (undescribable) => `${undescribable.slice(0, SKIPPED_IDS_IN
356
348
  onSome: (count) => `, +${count - SKIPPED_IDS_IN_WARNING} more`
357
349
  })}`;
358
350
  const refusalReasonsOf = (undescribable) => [...new Set(undescribable.map((mutant) => mutant.reason))].join("; ");
359
- const logSkippedMutants = (checkerName, undescribable) => Match.value(undescribable.length).pipe(Match.when(0, () => Effect$1.void), Match.orElse(() => Effect$1.logWarning(`Checker "${checkerName}" skipped ${undescribable.length} mutant(s) it cannot be told about: ${refusalReasonsOf(undescribable)} (${skippedIdsOf(undescribable)})`)));
351
+ const logSkippedMutants = (input) => Match.value(input.undescribable.length).pipe(Match.when(0, () => Effect$1.void), Match.orElse(() => Effect$1.logWarning(`Checker "${input.checkerName}" skipped ${input.undescribable.length} mutant(s) it cannot be told about: ${refusalReasonsOf(input.undescribable)} (${skippedIdsOf(input.undescribable)})`)));
360
352
  const recordSkipped = (skipped) => Boolean$1.match(skipped > 0, {
361
353
  onTrue: () => Metric.update(UndescribableMutant.skipped, skipped),
362
354
  onFalse: () => Effect$1.void
@@ -365,9 +357,14 @@ const partitionedFor = (input) => Option$1.match(Option$1.fromUndefinedOr(input.
365
357
  onSome: (known) => selectedFromLookup(input.plans, known),
366
358
  onNone: () => partitionMutantsForWire(input.plans)
367
359
  });
360
+ //#endregion
361
+ //#region src/Checker/Checker.cell.ts
368
362
  const readCheckCommand = (input) => Effect$1.gen(function* () {
369
363
  const partitioned = partitionedFor(input);
370
- yield* logSkippedMutants(input.checkerName, partitioned.undescribable);
364
+ yield* logSkippedMutants({
365
+ checkerName: input.checkerName,
366
+ undescribable: partitioned.undescribable
367
+ });
371
368
  yield* recordSkipped(partitioned.undescribable.length);
372
369
  yield* Effect$1.annotateCurrentSpan({ "stryker.checker.skipped_mutants_count": partitioned.undescribable.length });
373
370
  const answers = yield* input.checker.check(input.checkerName, partitioned.wire);
@@ -407,7 +404,11 @@ const commandFailed = (issue, input) => Checker_exports.CheckerFailed.make({
407
404
  mutantIds: input.plans.map((plan) => plan.mutant.id)
408
405
  });
409
406
  const checkCell = Sandwich.named("stryker.checker.check_plans")(readCheckCommand).decide(admitCheckerAnswer).write({
410
- CheckResultDecision: ({ pairs }, raw) => writeDecidedAnswers(raw.plans, raw.checkerName, pairs),
407
+ CheckResultDecision: ({ pairs }, raw) => writeDecidedAnswers({
408
+ plans: raw.plans,
409
+ checkerName: raw.checkerName,
410
+ answers: pairs
411
+ }),
411
412
  CheckGroupDecision: (_decision, raw) => Effect$1.fail(CheckerSkippedRequested.make({
412
413
  checkerName: raw.checkerName,
413
414
  phase: "check",
@@ -418,7 +419,11 @@ const checkCell = Sandwich.named("stryker.checker.check_plans")(readCheckCommand
418
419
  CommandRejected: ({ issue }, raw) => Effect$1.fail(commandFailed(issue, raw))
419
420
  });
420
421
  const checkGroupedCell = Sandwich.named("stryker.checker.group_plans")(readGroupCommand).decide(admitCheckerAnswer).write({
421
- CheckGroupDecision: ({ groups }, raw) => writeDecidedGroups(raw.plans, raw.checkerName, groups),
422
+ CheckGroupDecision: ({ groups }, raw) => writeDecidedGroups({
423
+ plans: raw.plans,
424
+ checkerName: raw.checkerName,
425
+ idGroups: groups
426
+ }),
422
427
  CheckResultDecision: (_decision, raw) => Effect$1.fail(CheckerSkippedRequested.make({
423
428
  checkerName: raw.checkerName,
424
429
  phase: "group",
@@ -479,6 +484,22 @@ const forkOptionsSchema = S.StructWithRest(S.Struct({
479
484
  extends: extendsPropertySchema
480
485
  }), [S.Record(S.String, S.Unknown)]);
481
486
  //#endregion
487
+ //#region src/config/default-options.ts
488
+ const isNonNullObject$1 = (value) => typeof value === "object" && value !== null;
489
+ const isRecordValue = (value) => isNonNullObject$1(value) && Array.isArray(value) === false;
490
+ const isArrayValue$1 = (value) => Array.isArray(value);
491
+ const freezeArrayValue = (value) => Object.freeze(value.map((element) => deepFreeze(element)));
492
+ const freezeMapEntry = ([entryKey, entryValue]) => [deepFreeze(entryKey), deepFreeze(entryValue)];
493
+ const freezeMapValue = (value) => Object.freeze(new Map([...value.entries()].map(freezeMapEntry)));
494
+ const freezeSetValue = (value) => Object.freeze(new Set([...value.values()].map((element) => deepFreeze(element))));
495
+ const freezeRegExpValue = (value) => Object.freeze(value);
496
+ const freezeRecordValue = (value) => Object.freeze(Record.map(value, (propertyValue) => deepFreeze(propertyValue)));
497
+ function deepFreeze(target) {
498
+ return Match.value(target).pipe(Match.when(isArrayValue$1, freezeArrayValue), Match.when((value) => value instanceof Map, freezeMapValue), Match.when((value) => value instanceof RegExp, freezeRegExpValue), Match.when((value) => value instanceof Set, freezeSetValue), Match.when(isRecordValue, freezeRecordValue), Match.orElse(() => target));
499
+ }
500
+ const createDefaultOptions = S.decodeEffect(Options_exports.StrykerOptionsSchema)({}).pipe(Effect$1.orDie);
501
+ const defaultOptions = Effect$1.map(createDefaultOptions, (options) => deepFreeze(options));
502
+ //#endregion
482
503
  //#region src/ConfigError.schema.ts
483
504
  var ConfigFileNotFoundError = class extends S.TaggedError()("ConfigFileNotFoundError", { file: S.String }) {
484
505
  exitClass = "ConfigError";
@@ -697,13 +718,16 @@ const interpretDryRunResult = Workflow.make({
697
718
  });
698
719
  //#endregion
699
720
  //#region src/pooled-test-runner.handle.ts
700
- const TypeId$3 = Symbol.for("@systemfsoftware/stryker-js/PooledTestRunner");
701
- const make$3 = (runner) => ({
702
- [TypeId$3]: TypeId$3,
703
- ...Prototype,
704
- ...runner
705
- });
706
- const withTimeout = (inner) => ({
721
+ const TypeId$10 = Symbol.for("~systemfsoftware/stryker-js/PooledTestRunner");
722
+ const PooledTestRunner = Handle.make()(TypeId$10);
723
+ PooledTestRunner.is;
724
+ const make$3 = (runner) => PooledTestRunner.make({
725
+ capabilities: runner.capabilities,
726
+ init: runner.init,
727
+ dryRun: runner.dryRun,
728
+ mutantRun: runner.mutantRun
729
+ });
730
+ const withTimeout = (inner) => make$3({
707
731
  ...inner,
708
732
  dryRun: (options) => inner.dryRun(options).pipe(Effect$1.timeoutOrElse({
709
733
  duration: Duration.millis(options.timeout),
@@ -725,7 +749,7 @@ const maxRetries = 2;
725
749
  const exhaustedMessage = (cause) => `Test runner crashed. Tried ${maxRetries} times to restart it without any luck. ${Cause.pretty(cause)}`;
726
750
  const withRetry = (inner) => {
727
751
  const attempt = (run, onExhausted) => run.pipe(Effect$1.tapError((error) => Match.value(error).pipe(Match.when(S.is(OutOfMemoryError), (outOfMemory) => Effect$1.logInfo(`Test runner process [${outOfMemory.pid}] ran out of memory. That usually means the tests leak memory. Stryker restarts the process and carries on, but the run is slower for it.`)), Match.orElse(() => Effect$1.void))), Effect$1.retry({ times: maxRetries }), Effect$1.catchCause((cause) => Effect$1.succeed(onExhausted(exhaustedMessage(cause)))));
728
- return {
752
+ return make$3({
729
753
  ...inner,
730
754
  dryRun: (options) => attempt(inner.dryRun(options), (errorMessage) => ({
731
755
  status: "error",
@@ -735,11 +759,11 @@ const withRetry = (inner) => {
735
759
  status: "error",
736
760
  errorMessage
737
761
  }))
738
- };
762
+ });
739
763
  };
740
764
  const withMaxReuse = dual(2, (options, retire) => (inner) => Match.value(options.maxTestRunnerReuse).pipe(Match.when((restartAfter) => restartAfter <= 0, () => Effect$1.succeed(inner)), Match.orElse((restartAfter) => Effect$1.gen(function* () {
741
765
  const runs = yield* Ref.make(0);
742
- return {
766
+ return make$3({
743
767
  ...inner,
744
768
  mutantRun: (runOptions) => {
745
769
  const policy = (self) => Effect$1.gen(function* () {
@@ -752,7 +776,7 @@ const withMaxReuse = dual(2, (options, retire) => (inner) => Match.value(options
752
776
  });
753
777
  return policy(inner.mutantRun(runOptions));
754
778
  }
755
- };
779
+ });
756
780
  }))));
757
781
  const nextEnvironmentState = (requested) => Boolean$1.match(requested, {
758
782
  onTrue: () => "loaded-static-mutant",
@@ -768,7 +792,7 @@ const reloadPlanOf = (requested, current, canReload) => ({
768
792
  });
769
793
  const withEnvironmentReload = dual(2, (inner, retire) => Effect$1.gen(function* () {
770
794
  const state = yield* Ref.make("pristine");
771
- return {
795
+ return make$3({
772
796
  ...inner,
773
797
  dryRun: (options) => {
774
798
  const policy = (self) => Ref.set(state, "loaded").pipe(Effect$1.andThen(self));
@@ -792,8 +816,11 @@ const withEnvironmentReload = dual(2, (inner, retire) => Effect$1.gen(function*
792
816
  reloadEnvironment: plan.reloadEnvironment
793
817
  }));
794
818
  })
795
- };
819
+ });
796
820
  }));
821
+ //#endregion
822
+ //#region src/command-runner.blueprint.ts
823
+ const TypeId$9 = Symbol.for("~systemfsoftware/stryker-js/CommandRunner");
797
824
  const ALL_TESTS_NAME = "All tests";
798
825
  const isCommandRunner = (name) => typeof name === "string" && name.toLowerCase() === "command";
799
826
  const commandRunnerCapabilities = { reloadEnvironment: true };
@@ -845,11 +872,7 @@ const commandRunnerMutantRun = (config, mutantPick) => runCommand(config, mutant
845
872
  onFailure: (failure) => Effect$1.fail(failure),
846
873
  onSuccess: (decision) => Effect$1.succeed(decision.asResult)
847
874
  })));
848
- const commandRunner = dual(2, (context, spawner) => {
849
- const config = {
850
- workingDir: context.sandboxWorkingDirectory,
851
- options: context.options
852
- };
875
+ const pooledRunnerOf = (config, spawner) => {
853
876
  const provided = Effect$1.provideService(ChildProcessSpawner.ChildProcessSpawner, spawner);
854
877
  return make$3({
855
878
  capabilities: Effect$1.succeed(commandRunnerCapabilities),
@@ -857,6 +880,23 @@ const commandRunner = dual(2, (context, spawner) => {
857
880
  dryRun: () => commandRunnerDryRun(config).pipe(provided),
858
881
  mutantRun: (options) => commandRunnerMutantRun(config, options).pipe(provided)
859
882
  });
883
+ };
884
+ const CommandRunners = Blueprint.make()(TypeId$9).steps({
885
+ steps: {},
886
+ targets: { runner: (spec) => (spawner) => pooledRunnerOf({
887
+ workingDir: spec.workingDir,
888
+ options: spec.options
889
+ }, spawner) }
890
+ });
891
+ const commandRunner = dual(2, (context, spawner) => CommandRunners.of({
892
+ workingDir: context.sandboxWorkingDirectory,
893
+ options: context.options
894
+ }).runner(spawner));
895
+ S.Struct({
896
+ command: S.Literals(["run", "merge-reports"]),
897
+ isDryRun: S.Boolean,
898
+ mode: S.Literals(["human", "machine"]),
899
+ isCi: S.Boolean
860
900
  });
861
901
  //#endregion
862
902
  //#region src/config/warning-enabled.workflow.ts
@@ -1203,7 +1243,14 @@ var Trace_exports = /* @__PURE__ */ __exportAll$1({
1203
1243
  layerTraceContextServer: () => layerTraceContextServer,
1204
1244
  withLinkedSpan: () => withLinkedSpan
1205
1245
  });
1206
- const WorkerOptionsWire = S.fromJsonString(Options_exports.StrykerOptionsSchema);
1246
+ const isEscapedKey = (key) => JSON.stringify(key) !== `"${key}"`;
1247
+ const omitEscapedKeys = (key, value) => isEscapedKey(key) ? void 0 : value;
1248
+ const withoutEscapedKeys = (options) => Option$1.getOrThrow(S.decodeUnknownOption(Options_exports.StrykerOptionsSchema)(JSON.parse(JSON.stringify(options, omitEscapedKeys))));
1249
+ const OptionsLawDomain = S.declare((value) => S.is(Options_exports.StrykerOptionsSchema)(value), { toCodecArbitrary: () => S.link()(Options_exports.StrykerOptionsSchema, {
1250
+ decode: SchemaGetter.transform(withoutEscapedKeys),
1251
+ encode: SchemaGetter.passthrough()
1252
+ }) });
1253
+ const WorkerOptionsWire = S.fromJsonString(Options_exports.StrykerOptionsSchema.pipe(S.decodeTo(OptionsLawDomain, SchemaTransformation.passthrough())));
1207
1254
  var WorkerOptions = class WorkerOptions extends Context.Service()("@systemfsoftware/stryker-js-plugin-runtime/worker-options.service/WorkerOptions") {
1208
1255
  static layer = Layer.effect(WorkerOptions, Effect$1.gen(function* () {
1209
1256
  const workerDir = yield* Config.String("STRYKER_WORKER_DIR");
@@ -1219,17 +1266,29 @@ const restrictSocket = (address) => Match.value(address).pipe(Match.tag("UnixPat
1219
1266
  onTrue: () => Effect$1.void,
1220
1267
  onFalse: () => Effect$1.flatMap(FileSystem.FileSystem, (fs) => fs.chmod(path, 384))
1221
1268
  })), Match.orElse(() => Effect$1.void));
1222
- const workerServerLayer = (params) => Layer.unwrap(Effect$1.gen(function* () {
1269
+ const TypeId$8 = Symbol.for("~systemfsoftware/stryker-js-plugin-runtime/WorkerServer");
1270
+ const workerServerLayerOf = (params) => Layer.unwrap(Effect$1.gen(function* () {
1223
1271
  const socket = yield* SocketServer.SocketServer;
1224
1272
  yield* restrictSocket(socket.address);
1225
1273
  return RpcServer.layer(params.rpcs).pipe(Layer.provide(params.handlers), Layer.provide(params.schemaServices), Layer.provide(RpcServer.layerProtocolSocketServer), Layer.provide(RpcSerialization.layerNdjson), Layer.provide(traceContextServer));
1226
1274
  }));
1275
+ Blueprint.make()(TypeId$8).steps({
1276
+ steps: {},
1277
+ targets: { layer: workerServerLayerOf }
1278
+ }).is;
1279
+ const workerServerLayer = workerServerLayerOf;
1227
1280
  const TRACES_SUFFIX = "/v1/traces";
1228
1281
  const tracesUrlOf = (endpoint) => Option$1.match(Option$1.liftPredicate(endpoint.replace(/\/+$/u, ""), (trimmed) => trimmed.endsWith(TRACES_SUFFIX)), {
1229
1282
  onSome: (trimmed) => trimmed,
1230
1283
  onNone: () => `${endpoint.replace(/\/+$/u, "")}${TRACES_SUFFIX}`
1231
1284
  });
1232
- const canonicalTracesUrl = S.String.pipe(S.check(S.isPattern(/\/v1\/traces$/u)), S.check(S.isPattern(/[^/]$/u)));
1285
+ const canonicalTracesUrl = S.String.pipe(S.check(S.isPattern(/\/v1\/traces$/u, { arbitraryConstraint: {
1286
+ patterns: [{
1287
+ source: "\\/v1\\/traces$",
1288
+ flags: "u"
1289
+ }],
1290
+ minLength: 12
1291
+ } })));
1233
1292
  const TracesUrl = S.String.pipe(S.decodeTo(canonicalTracesUrl, {
1234
1293
  decode: SchemaGetter$1.transform(tracesUrlOf),
1235
1294
  encode: SchemaGetter$1.passthrough()
@@ -1261,23 +1320,22 @@ var Worker_exports = /* @__PURE__ */ __exportAll$1({
1261
1320
  });
1262
1321
  //#endregion
1263
1322
  //#region src/spawned-socket-worker.handle.ts
1264
- const TypeId$2 = Symbol.for("@systemfsoftware/stryker-js/SpawnedSocketWorker");
1265
- const ClientLayerTypeId = Symbol.for("@systemfsoftware/stryker-js/SpawnedSocketWorker/clientLayer");
1266
- const make$2 = (worker) => ({
1267
- [TypeId$2]: TypeId$2,
1268
- [ClientLayerTypeId]: worker.clientLayer,
1323
+ const TypeId$7 = Symbol.for("~systemfsoftware/stryker-js/SpawnedSocketWorker");
1324
+ const SpawnedSocketWorker = Handle.make()(TypeId$7);
1325
+ SpawnedSocketWorker.is;
1326
+ const make$2 = (worker) => SpawnedSocketWorker.make({
1269
1327
  pid: worker.pid,
1270
- exited: worker.exited,
1271
- ...Prototype
1272
- });
1273
- const clientLayer = (self) => self[ClientLayerTypeId];
1328
+ exited: worker.exited
1329
+ }, { clientLayer: worker.clientLayer });
1330
+ const clientLayer = (self) => SpawnedSocketWorker.slot(self).clientLayer;
1274
1331
  //#endregion
1275
1332
  //#region src/WorkerLauncher.service.ts
1276
1333
  var WorkerLauncher = class extends Context.Service()("@systemfsoftware/stryker-js/WorkerLauncher.service/WorkerLauncher") {};
1277
1334
  //#endregion
1278
- //#region src/worker-client.resource.ts
1335
+ //#region src/worker-client.blueprint.ts
1336
+ const TypeId$6 = Symbol.for("~systemfsoftware/stryker-js/WorkerClient");
1279
1337
  const connectRetry = Schedule.max([Schedule.spaced(50), Schedule.recurs(100)]);
1280
- const makeWorkerClient = (params) => Effect$1.gen(function* () {
1338
+ const scopedOf$2 = (params) => Effect$1.gen(function* () {
1281
1339
  const launcher = yield* WorkerLauncher;
1282
1340
  const optionsJson = yield* S.encodeEffect(Worker_exports.WorkerOptionsWire)(params.options).pipe(Effect$1.orDie);
1283
1341
  const worker = yield* launcher.spawn({
@@ -1292,6 +1350,11 @@ const makeWorkerClient = (params) => Effect$1.gen(function* () {
1292
1350
  const traceContext = yield* Layer.build(Trace_exports.layerTraceContextClient);
1293
1351
  return yield* RpcClient.make(params.rpcs).pipe(Effect$1.provideContext(Context.merge(protocol, traceContext)));
1294
1352
  });
1353
+ const WorkerClients = () => Blueprint.make()(TypeId$6).steps({
1354
+ steps: {},
1355
+ targets: { scoped: scopedOf$2 }
1356
+ });
1357
+ const makeWorkerClient = (params) => WorkerClients().of(params).scoped;
1295
1358
  const ReporterStageTypeId = Symbol.for("@systemfsoftware/stryker-js/ReporterStage");
1296
1359
  const carriesAttachments = (stage) => "attachments" in stage;
1297
1360
  const makeReporterStage = (attachments) => {
@@ -1677,7 +1740,7 @@ var RunEvents = class extends Context.Service()("@systemfsoftware/stryker-js/run
1677
1740
  var RunIdentity = class extends Context.Service()("@systemfsoftware/stryker-js/run-events.service/RunIdentity") {};
1678
1741
  //#endregion
1679
1742
  //#region package.json
1680
- var version = "11.0.0";
1743
+ var version = "12.0.0";
1681
1744
  //#endregion
1682
1745
  //#region src/stryker-package.schema.ts
1683
1746
  var StrykerPackage = class extends S.Class("StrykerPackage")({
@@ -2108,7 +2171,8 @@ var ClearTextReportCommand = class extends S.TaggedClass()("ClearTextReportComma
2108
2171
  };
2109
2172
  var ClearTextReportRendered = class extends S.TaggedClass()("ClearTextReportRendered", {
2110
2173
  stdout: S.Array(ReportChunkSchema),
2111
- diagnostics: S.Array(ReportChunkSchema)
2174
+ diagnostics: S.Array(ReportChunkSchema),
2175
+ stderr: S.Array(ReportChunkSchema)
2112
2176
  }) {
2113
2177
  [ClearTextReportTypeId] = ClearTextReportTypeId;
2114
2178
  };
@@ -2525,7 +2589,11 @@ const renderClearTextReport = Workflow.make({
2525
2589
  const sections = renderClearText(report, metrics, command.render);
2526
2590
  return Result.succeed(ClearTextReportRendered.make({
2527
2591
  stdout: [...sections.stdout],
2528
- diagnostics: [...sections.diagnostics]
2592
+ diagnostics: [...sections.diagnostics],
2593
+ stderr: Boolean$1.match(command.render.debug, {
2594
+ onTrue: () => [...sections.diagnostics],
2595
+ onFalse: () => []
2596
+ })
2529
2597
  }));
2530
2598
  }
2531
2599
  })
@@ -2575,14 +2643,8 @@ const renderOptionsOf = (options) => ({
2575
2643
  });
2576
2644
  const readClearTextReport = (input) => Effect$1.map(Stream.fromAsyncIterable(input.events, failAsClearText).pipe(Stream.filterMap(terminalReportOf), Stream.run(Sink.last())), (terminal) => ({
2577
2645
  _tag: "ClearTextReportCommand",
2578
- reported: Option$1.match(terminal, {
2579
- onNone: () => void 0,
2580
- onSome: (ready) => ready.report
2581
- }),
2582
- computed: Option$1.match(terminal, {
2583
- onNone: () => void 0,
2584
- onSome: (ready) => ready.metrics
2585
- }),
2646
+ reported: Option$1.getOrUndefined(Option$1.map(terminal, (ready) => ready.report)),
2647
+ computed: Option$1.getOrUndefined(Option$1.map(terminal, (ready) => ready.metrics)),
2586
2648
  render: renderOptionsOf(input.options),
2587
2649
  rendered: true
2588
2650
  }));
@@ -2619,13 +2681,10 @@ const renderLine = (line) => runsOf(line).map(renderSpan).join("");
2619
2681
  const renderChunk = (chunk) => chunk.map(renderLine).join("\n");
2620
2682
  const writeChunks = (output, channel, chunks) => output.write(channel, chunks.map((chunk) => `${renderChunk(chunk)}\n`)).pipe(Effect$1.mapError(failAsClearText), Effect$1.asVoid);
2621
2683
  const clearTextReportCell = Sandwich.named("stryker.report.clearText")(readClearTextReport).decide(renderClearTextReport).write({
2622
- ClearTextReportRendered: (rendered, raw) => Effect$1.gen(function* () {
2684
+ ClearTextReportRendered: (rendered, _raw) => Effect$1.gen(function* () {
2623
2685
  const output = yield* ReporterOutput;
2624
2686
  yield* writeChunks(output, "stdout", rendered.stdout);
2625
- yield* Boolean$1.match(raw.render.debug, {
2626
- onTrue: () => writeChunks(output, "stderr", rendered.diagnostics),
2627
- onFalse: () => Effect$1.void
2628
- });
2687
+ yield* Effect$1.forEach(rendered.stderr, (chunk) => writeChunks(output, "stderr", [chunk]), { discard: true });
2629
2688
  }),
2630
2689
  ClearTextReportSuppressed: () => Effect$1.void,
2631
2690
  CommandRejected: ({ issue }) => Effect$1.fail(failAsClearText(issue))
@@ -2642,11 +2701,16 @@ const clearTextReporterFactory = (context) => {
2642
2701
  const JsonReportTypeId = Symbol.for("@systemfsoftware/stryker-js/JsonReport");
2643
2702
  var JsonReportCommand = class extends S.TaggedClass()("JsonReportCommand", {
2644
2703
  reported: S.optional(Report_exports.MutationTestResultSchema),
2645
- rendered: S.Boolean
2704
+ rendered: S.Boolean,
2705
+ debug: S.Boolean,
2706
+ fileName: S.String
2646
2707
  }) {
2647
2708
  static [Workflow.InstrumentationBrand] = { rendered: "stryker.report.render" };
2648
2709
  };
2649
- var JsonReportRendered = class extends S.TaggedClass()("JsonReportRendered", { report: Report_exports.MutationTestResultSchema }) {
2710
+ var JsonReportRendered = class extends S.TaggedClass()("JsonReportRendered", {
2711
+ report: Report_exports.MutationTestResultSchema,
2712
+ announceFileName: S.Option(S.String)
2713
+ }) {
2650
2714
  [JsonReportTypeId] = JsonReportTypeId;
2651
2715
  };
2652
2716
  var JsonReportSuppressed = class extends S.TaggedClass()("JsonReportSuppressed", {}) {
@@ -2659,7 +2723,13 @@ const renderJsonReport = Workflow.make({
2659
2723
  error: S.Never,
2660
2724
  decide: (command) => Option$1.match(Option$1.fromUndefinedOr(command.reported), {
2661
2725
  onNone: () => Result.succeed(JsonReportSuppressed.make({})),
2662
- onSome: (report) => Result.succeed(JsonReportRendered.make({ report }))
2726
+ onSome: (report) => Result.succeed(JsonReportRendered.make({
2727
+ report,
2728
+ announceFileName: Boolean$1.match(command.debug, {
2729
+ onTrue: () => Option$1.some(command.fileName),
2730
+ onFalse: () => Option$1.none()
2731
+ })
2732
+ }))
2663
2733
  })
2664
2734
  });
2665
2735
  //#endregion
@@ -2674,13 +2744,11 @@ const readJsonReport = (input) => Effect$1.map(Stream.fromAsyncIterable(input.ev
2674
2744
  _tag: "JsonReportCommand",
2675
2745
  reported: Option$1.getOrUndefined(last),
2676
2746
  rendered: true,
2747
+ debug: input.options.logLevel === "debug",
2748
+ fileName: input.options.jsonReporter.fileName,
2677
2749
  options: input.options
2678
2750
  }));
2679
2751
  const jsonBytesOf = (report) => S.encodeEffect(S.fromJsonString(S.Unknown, { space: 0 }))(report).pipe(Effect$1.mapError(failAsJsonReporter));
2680
- const announceRelativePath = (output, options, path) => Boolean$1.match(options.logLevel === "debug", {
2681
- onTrue: () => Effect$1.ignore(output.write("stderr", [`Using relative path ${path.normalize(options.jsonReporter.fileName)}\n`])),
2682
- onFalse: () => Effect$1.void
2683
- });
2684
2752
  const jsonReportCell = Sandwich.named("stryker.report.json")(readJsonReport).decide(renderJsonReport).write({
2685
2753
  JsonReportRendered: (rendered, raw) => Effect$1.gen(function* () {
2686
2754
  const output = yield* ReporterOutput;
@@ -2688,7 +2756,7 @@ const jsonReportCell = Sandwich.named("stryker.report.json")(readJsonReport).dec
2688
2756
  const path = yield* Path.Path;
2689
2757
  const json = yield* jsonBytesOf(rendered.report);
2690
2758
  const fileName = path.resolve(raw.options.jsonReporter.fileName);
2691
- yield* announceRelativePath(output, raw.options, path);
2759
+ yield* Effect$1.forEach(Option$1.toArray(rendered.announceFileName), (name) => Effect$1.ignore(output.write("stderr", [`Using relative path ${path.normalize(name)}\n`])), { discard: true });
2692
2760
  yield* fs.makeDirectory(path.dirname(fileName), { recursive: true }).pipe(Effect$1.mapError(failAsJsonReporter));
2693
2761
  yield* fs.writeFileString(fileName, json).pipe(Effect$1.mapError(failAsJsonReporter));
2694
2762
  const url = yield* path.toFileUrl(fileName).pipe(Effect$1.mapError(failAsJsonReporter));
@@ -2705,116 +2773,11 @@ const jsonReporterFactory = (context) => {
2705
2773
  }));
2706
2774
  };
2707
2775
  //#endregion
2708
- //#region src/render-progress-report.workflow.ts
2709
- const ProgressReportTypeId = Symbol.for("@systemfsoftware/stryker-js/ProgressReport");
2710
- const ProgressTimingSchema = S.Struct({
2711
- net: S.Finite,
2712
- overhead: S.Finite
2713
- });
2714
- const ProgressCapabilitiesSchema = S.Struct({ reloadEnvironment: S.Boolean });
2715
- const ProgressTallySchema = S.Struct({
2716
- survived: S.Finite,
2717
- timedOut: S.Finite,
2718
- tested: S.Finite,
2719
- mutants: S.Finite,
2720
- total: S.Finite,
2721
- ticks: S.Finite,
2722
- ticksByMutantId: S.Record(S.String, S.Finite),
2723
- timing: ProgressTimingSchema,
2724
- capabilities: ProgressCapabilitiesSchema,
2725
- startedAt: S.Finite
2726
- });
2727
- const ProgressBarStateSchema = S.Struct({
2728
- format: S.String,
2729
- total: S.Finite,
2730
- curr: S.Finite,
2731
- width: S.Finite,
2732
- complete: S.String,
2733
- incomplete: S.String
2734
- });
2735
- const ProgressStateSchema = S.Struct({
2736
- tally: ProgressTallySchema,
2737
- bar: S.NullOr(ProgressBarStateSchema)
2738
- });
2739
- var ProgressReportCommand = class extends S.TaggedClass()("ProgressReportCommand", {
2740
- kind: S.Literals([
2741
- "tick",
2742
- "skip",
2743
- "finalize"
2744
- ]),
2745
- state: ProgressStateSchema,
2746
- now: S.Finite
2747
- }) {
2748
- static [Workflow.InstrumentationBrand] = { now: "stryker.report.rendered" };
2749
- };
2750
- var ProgressBarTick = class extends S.TaggedClass()("ProgressBarTick", {
2751
- bar: ProgressBarStateSchema,
2752
- tally: ProgressTallySchema,
2753
- now: S.Finite
2754
- }) {
2755
- [ProgressReportTypeId] = ProgressReportTypeId;
2756
- };
2757
- var ProgressLineBreak = class extends S.TaggedClass()("ProgressLineBreak", {}) {
2758
- [ProgressReportTypeId] = ProgressReportTypeId;
2759
- };
2760
- var ProgressChunkSuppressed = class extends S.TaggedClass()("ProgressChunkSuppressed", {}) {
2761
- [ProgressReportTypeId] = ProgressReportTypeId;
2762
- };
2763
- const ProgressReportDecision = S.Union([
2764
- ProgressBarTick,
2765
- ProgressLineBreak,
2766
- ProgressChunkSuppressed
2767
- ]);
2768
- const isComplete$1 = (bar) => bar.curr >= bar.total;
2769
- const renderProgressReport = Workflow.make({
2770
- command: ProgressReportCommand,
2771
- decision: ProgressReportDecision,
2772
- error: S.Never,
2773
- decide: (command) => Result.succeed(Match.value(command.kind).pipe(Match.when("finalize", () => Option$1.match(Option$1.fromNullishOr(command.state.bar), {
2774
- onNone: () => ProgressChunkSuppressed.make({}),
2775
- onSome: (bar) => Boolean$1.match(isComplete$1(bar), {
2776
- onTrue: () => ProgressChunkSuppressed.make({}),
2777
- onFalse: () => ProgressLineBreak.make({})
2778
- })
2779
- })), Match.when("skip", () => ProgressChunkSuppressed.make({})), Match.when("tick", () => Option$1.match(Option$1.fromNullishOr(command.state.bar), {
2780
- onNone: () => ProgressChunkSuppressed.make({}),
2781
- onSome: (bar) => ProgressBarTick.make({
2782
- bar,
2783
- tally: command.state.tally,
2784
- now: command.now
2785
- })
2786
- })), Match.exhaustive))
2787
- });
2788
- //#endregion
2789
- //#region src/progress-report.cell.ts
2790
- const failAsProgress = (cause) => Reporter_exports.ReporterFailed.make({
2791
- reporterName: "progress",
2792
- event: "mutationTestReportReady",
2793
- cause: Option$1.getOrElse(Option$1.map(ErrorText_exports.ErrorText.fromCause(cause), (rendered) => rendered.text), () => "")
2794
- });
2776
+ //#region src/progress-report.steps.ts
2795
2777
  const PROGRESS_BAR_FORMAT = "Mutation testing [:bar] :percent (elapsed: :et, remaining: :etc) :tested/:mutants Mutants tested (:survived survived, :timedOut timed out)";
2796
2778
  const PROGRESS_BAR_WIDTH = 50;
2797
2779
  const PROGRESS_BAR_COMPLETE = "=";
2798
2780
  const PROGRESS_BAR_INCOMPLETE = " ";
2799
- const emptyTally = (startedAt) => ({
2800
- survived: 0,
2801
- timedOut: 0,
2802
- tested: 0,
2803
- mutants: 0,
2804
- total: 0,
2805
- ticks: 0,
2806
- ticksByMutantId: {},
2807
- timing: {
2808
- net: 0,
2809
- overhead: 0
2810
- },
2811
- capabilities: { reloadEnvironment: false },
2812
- startedAt
2813
- });
2814
- const INITIAL_PROGRESS = {
2815
- tally: emptyTally(0),
2816
- bar: null
2817
- };
2818
2781
  const TALLY_COUNTED = {
2819
2782
  Killed: {
2820
2783
  survived: 0,
@@ -2917,24 +2880,14 @@ const advance = (state, event, now) => Match.value(event).pipe(Match.tag("dryRun
2917
2880
  kind: "skip",
2918
2881
  state
2919
2882
  })));
2920
- const readProgressStep = (input) => Effect$1.map(Effect$1.sync(() => performance.now()), (now) => Option$1.match(Option$1.fromNullishOr(input.event), {
2883
+ const progressStep = (input) => Option$1.match(Option$1.fromNullishOr(input.event), {
2921
2884
  onNone: () => ({
2922
- _tag: "ProgressReportCommand",
2923
2885
  kind: "finalize",
2924
- state: input.state,
2925
- now
2886
+ state: input.state
2926
2887
  }),
2927
- onSome: (event) => {
2928
- const step = advance(input.state, event, now);
2929
- return {
2930
- _tag: "ProgressReportCommand",
2931
- kind: step.kind,
2932
- state: step.state,
2933
- now
2934
- };
2935
- }
2936
- }));
2937
- const isComplete = (bar) => bar.curr >= bar.total;
2888
+ onSome: (present) => advance(input.state, present, input.now)
2889
+ });
2890
+ const isComplete$1 = (bar) => bar.curr >= bar.total;
2938
2891
  const secondsBetween = (now, startedAt) => Math.floor((now - startedAt) / 1e3);
2939
2892
  const formatTime = (timeInSeconds) => {
2940
2893
  const hours = Math.floor(timeInSeconds / 3600);
@@ -2972,7 +2925,128 @@ const lineBreakOf = (complete) => Boolean$1.match(complete, {
2972
2925
  onTrue: () => "\n",
2973
2926
  onFalse: () => ""
2974
2927
  });
2975
- const renderTick = (tick) => `\r${formatBar(tick.bar, progressData(tick.tally, tick.now))}${lineBreakOf(isComplete(tick.bar))}`;
2928
+ const renderTick = (tick) => `\r${formatBar(tick.bar, progressData(tick.tally, tick.now))}${lineBreakOf(isComplete$1(tick.bar))}`;
2929
+ //#endregion
2930
+ //#region src/render-progress-report.workflow.ts
2931
+ const ProgressReportTypeId = Symbol.for("@systemfsoftware/stryker-js/ProgressReport");
2932
+ const ProgressTimingSchema = S.Struct({
2933
+ net: S.Finite,
2934
+ overhead: S.Finite
2935
+ });
2936
+ const ProgressCapabilitiesSchema = S.Struct({ reloadEnvironment: S.Boolean });
2937
+ const ProgressTallySchema = S.Struct({
2938
+ survived: S.Finite,
2939
+ timedOut: S.Finite,
2940
+ tested: S.Finite,
2941
+ mutants: S.Finite,
2942
+ total: S.Finite,
2943
+ ticks: S.Finite,
2944
+ ticksByMutantId: S.Record(S.String, S.Finite),
2945
+ timing: ProgressTimingSchema,
2946
+ capabilities: ProgressCapabilitiesSchema,
2947
+ startedAt: S.Finite
2948
+ });
2949
+ const ProgressBarStateSchema = S.Struct({
2950
+ format: S.String,
2951
+ total: S.Finite,
2952
+ curr: S.Finite,
2953
+ width: S.Finite,
2954
+ complete: S.String,
2955
+ incomplete: S.String
2956
+ });
2957
+ const ProgressStateSchema = S.Struct({
2958
+ tally: ProgressTallySchema,
2959
+ bar: S.NullOr(ProgressBarStateSchema)
2960
+ });
2961
+ var ProgressReportCommand = class extends S.TaggedClass()("ProgressReportCommand", {
2962
+ kind: S.Literals([
2963
+ "tick",
2964
+ "skip",
2965
+ "finalize"
2966
+ ]),
2967
+ state: ProgressStateSchema,
2968
+ now: S.Finite
2969
+ }) {
2970
+ static [Workflow.InstrumentationBrand] = { now: "stryker.report.rendered" };
2971
+ };
2972
+ var ProgressBarTick = class extends S.TaggedClass()("ProgressBarTick", {
2973
+ bar: ProgressBarStateSchema,
2974
+ tally: ProgressTallySchema,
2975
+ now: S.Finite
2976
+ }) {
2977
+ [ProgressReportTypeId] = ProgressReportTypeId;
2978
+ };
2979
+ var ProgressLineBreak = class extends S.TaggedClass()("ProgressLineBreak", {}) {
2980
+ [ProgressReportTypeId] = ProgressReportTypeId;
2981
+ };
2982
+ var ProgressChunkSuppressed = class extends S.TaggedClass()("ProgressChunkSuppressed", {}) {
2983
+ [ProgressReportTypeId] = ProgressReportTypeId;
2984
+ };
2985
+ const ProgressReportDecision = S.Union([
2986
+ ProgressBarTick,
2987
+ ProgressLineBreak,
2988
+ ProgressChunkSuppressed
2989
+ ]);
2990
+ const isComplete = (bar) => bar.curr >= bar.total;
2991
+ const renderProgressReport = Workflow.make({
2992
+ command: ProgressReportCommand,
2993
+ decision: ProgressReportDecision,
2994
+ error: S.Never,
2995
+ decide: (command) => Result.succeed(Match.value(command.kind).pipe(Match.when("finalize", () => Option$1.match(Option$1.fromNullishOr(command.state.bar), {
2996
+ onNone: () => ProgressChunkSuppressed.make({}),
2997
+ onSome: (bar) => Boolean$1.match(isComplete(bar), {
2998
+ onTrue: () => ProgressChunkSuppressed.make({}),
2999
+ onFalse: () => ProgressLineBreak.make({})
3000
+ })
3001
+ })), Match.when("skip", () => ProgressChunkSuppressed.make({})), Match.when("tick", () => Option$1.match(Option$1.fromNullishOr(command.state.bar), {
3002
+ onNone: () => ProgressChunkSuppressed.make({}),
3003
+ onSome: (bar) => ProgressBarTick.make({
3004
+ bar,
3005
+ tally: command.state.tally,
3006
+ now: command.now
3007
+ })
3008
+ })), Match.exhaustive))
3009
+ });
3010
+ //#endregion
3011
+ //#region src/progress-report.cell.ts
3012
+ const failAsProgress = (cause) => Reporter_exports.ReporterFailed.make({
3013
+ reporterName: "progress",
3014
+ event: "mutationTestReportReady",
3015
+ cause: Option$1.getOrElse(Option$1.map(ErrorText_exports.ErrorText.fromCause(cause), (rendered) => rendered.text), () => "")
3016
+ });
3017
+ const emptyTally = (startedAt) => ({
3018
+ survived: 0,
3019
+ timedOut: 0,
3020
+ tested: 0,
3021
+ mutants: 0,
3022
+ total: 0,
3023
+ ticks: 0,
3024
+ ticksByMutantId: {},
3025
+ timing: {
3026
+ net: 0,
3027
+ overhead: 0
3028
+ },
3029
+ capabilities: { reloadEnvironment: false },
3030
+ startedAt
3031
+ });
3032
+ const INITIAL_PROGRESS = {
3033
+ tally: emptyTally(0),
3034
+ bar: null
3035
+ };
3036
+ const readProgressStep = (input) => Effect$1.gen(function* () {
3037
+ const now = yield* Clock.currentTimeMillis;
3038
+ const step = progressStep({
3039
+ state: input.state,
3040
+ event: input.event,
3041
+ now
3042
+ });
3043
+ return {
3044
+ _tag: "ProgressReportCommand",
3045
+ kind: step.kind,
3046
+ state: step.state,
3047
+ now
3048
+ };
3049
+ });
2976
3050
  const writeChunk = (chunk) => Effect$1.flatMap(ReporterOutput, (output) => Effect$1.ignore(output.write("stdout", [chunk])));
2977
3051
  const progressReportCell = Sandwich.named("stryker.report.progress")(readProgressStep).decide(renderProgressReport).write({
2978
3052
  ProgressBarTick: (tick, raw) => Effect$1.as(writeChunk(renderTick(tick)), raw.state),
@@ -3061,7 +3135,7 @@ const phaseEntered = (phase) => Effect$1.gen(function* () {
3061
3135
  }));
3062
3136
  });
3063
3137
  //#endregion
3064
- //#region src/run/load-config.cell.ts
3138
+ //#region src/run/load-config.parts.ts
3065
3139
  const isNonNullObject = (value) => typeof value === "object" && value !== null;
3066
3140
  const combine = (prefixes, suffixes, extensions) => prefixes.flatMap((prefix) => suffixes.flatMap((suffix) => extensions.map((extension) => `${prefix}stryker${suffix}.${extension}`)));
3067
3141
  const CONFIG_FILE_NAME_PREFIXES = ["", "."];
@@ -3228,7 +3302,7 @@ const applyConfigFactory = (factory, configEnv) => factory(configEnv);
3228
3302
  /**
3229
3303
  * Settle a config module's default export into the object the document schema decodes.
3230
3304
  *
3231
- * `./config` types `StrykerConfig.define` as accepting the config object, a promise of it,
3305
+ * `./config` types `defineConfig` as accepting the config object, a promise of it,
3232
3306
  * or a factory receiving `ConfigEnv`, so the loader accepts all three. The factory
3233
3307
  * is invoked here because this is the only place that knows the invocation the
3234
3308
  * config is being read for; the promise is awaited here because a promise is a
@@ -3536,20 +3610,10 @@ const readLoadConfig = (input) => Effect$1.gen(function* () {
3536
3610
  };
3537
3611
  const cliRecord = yield* S.decodeEffect(ConfigDocumentSchema)(input.cliOptions).pipe(Effect$1.orDie);
3538
3612
  return yield* loadOptionsFromConfigFile(cliRecord, configEnv).pipe(Effect$1.map((fileOptions) => LoadConfigCommand.make({
3539
- document: StrykerConfig.merge(Option$1.getOrElse(fileOptions, () => ({})), cliRecord),
3613
+ document: mergeConfig(Option$1.getOrElse(fileOptions, () => ({})), cliRecord),
3540
3614
  fileFound: Option$1.isSome(fileOptions)
3541
3615
  })));
3542
3616
  });
3543
- const loadConfig = Sandwich.named("stryker.config_read")(readLoadConfig).decide(resolveConfig).write({
3544
- ConfigFromFile: ({ options }) => Effect$1.succeed(options),
3545
- ConfigFromDefaults: ({ options }) => Effect$1.succeed(options),
3546
- ConfigOptionsRefused: ({ message }) => Effect$1.fail(ConfigError.make({ message: configErrorMessage(describeMessageOf(message)) })),
3547
- CommandRejected: ({ issue }) => Effect$1.fail(ConfigError.make({ message: issue }))
3548
- });
3549
- const readConfig = dual(2, (cliOptions, invocation) => loadConfig.run({
3550
- cliOptions,
3551
- invocation
3552
- }));
3553
3617
  const emitPreparePhaseEntered = phaseEntered("prepare");
3554
3618
  const failConfigWith = (message) => Effect$1.fail(ConfigError.make({ message })).pipe(Effect$1.tapCause(() => emitPreparePhaseEntered));
3555
3619
  const readRunConfig = (input) => Effect$1.gen(function* () {
@@ -3566,6 +3630,18 @@ const readRunConfig = (input) => Effect$1.gen(function* () {
3566
3630
  basePath: env.basePath
3567
3631
  });
3568
3632
  });
3633
+ //#endregion
3634
+ //#region src/run/load-config.cell.ts
3635
+ const loadConfig = Sandwich.named("stryker.config_read")(readLoadConfig).decide(resolveConfig).write({
3636
+ ConfigFromFile: ({ options }) => Effect$1.succeed(options),
3637
+ ConfigFromDefaults: ({ options }) => Effect$1.succeed(options),
3638
+ ConfigOptionsRefused: ({ message }) => Effect$1.fail(ConfigError.make({ message: configErrorMessage(describeMessageOf(message)) })),
3639
+ CommandRejected: ({ issue }) => Effect$1.fail(ConfigError.make({ message: issue }))
3640
+ });
3641
+ const readConfig = dual(2, (cliOptions, invocation) => loadConfig.run({
3642
+ cliOptions,
3643
+ invocation
3644
+ }));
3569
3645
  const loadConfigCell = Sandwich.named("stryker.load_config")(readRunConfig).decide(resolveConfig).write({
3570
3646
  ConfigFromFile: ({ options }, raw) => Effect$1.succeed({
3571
3647
  options,
@@ -3620,9 +3696,10 @@ const classifyWorkerExit = Workflow.make({
3620
3696
  decide: decide$8
3621
3697
  });
3622
3698
  //#endregion
3623
- //#region src/worker-protocol.resource.ts
3699
+ //#region src/worker-protocol.blueprint.ts
3700
+ const TypeId$5 = Symbol.for("~systemfsoftware/stryker-js/WorkerProtocol");
3624
3701
  const droppedConnection = RpcClientError.make({ reason: Socket.SocketReadError.make({ cause: /* @__PURE__ */ new Error("worker connection dropped with the request in flight") }) });
3625
- const layerWorkerProtocol = (socket) => Layer.effect(RpcClient.Protocol, Effect$1.gen(function* () {
3702
+ const layerOf = (socket) => Layer.effect(RpcClient.Protocol, Effect$1.gen(function* () {
3626
3703
  const handlers = MutableHashMap.empty();
3627
3704
  const inFlight = MutableHashMap.empty();
3628
3705
  const connected = yield* Ref.make(false);
@@ -3661,6 +3738,11 @@ const layerWorkerProtocol = (socket) => Layer.effect(RpcClient.Protocol, Effect$
3661
3738
  send: (clientId, request, transferables) => track(clientId, request).pipe(Effect$1.andThen(inner.send(clientId, request, transferables)))
3662
3739
  });
3663
3740
  }));
3741
+ const WorkerProtocol = Blueprint.make()(TypeId$5).steps({
3742
+ steps: {},
3743
+ targets: { layer: (spec) => layerOf(spec.socket) }
3744
+ });
3745
+ const layerWorkerProtocol = (socket) => WorkerProtocol.of({ socket }).layer;
3664
3746
  //#endregion
3665
3747
  //#region src/drivers/node.ts
3666
3748
  const restrictToOwnerOrWarn = (fs, file) => fs.chmod(file, 384).pipe(Effect$1.tapError((cause) => Effect$1.logWarning(`Could not restrict "${file}" to its owner; the worker directory's own mode still protects it.`).pipe(Effect$1.annotateLogs("cause", cause))), Effect$1.catchTag("PlatformError", () => Effect$1.void));
@@ -3897,7 +3979,7 @@ const writeHtmlFile = (fileName, html) => Effect$1.gen(function* () {
3897
3979
  const readRenderCommand = (input) => Effect$1.succeed({
3898
3980
  _tag: "RenderHtmlReport",
3899
3981
  fileName: input.fileName,
3900
- inlinedBundle: inlinedBundle(),
3982
+ inlinedBundle: input.inlinedBundle,
3901
3983
  report: input.report
3902
3984
  });
3903
3985
  const writeHtmlReport = Sandwich.named("html_report.write")(readRenderCommand).decide(renderHtmlReport).write({
@@ -3916,7 +3998,8 @@ const failAsHtmlReporter = (cause) => Reporter_exports.ReporterFailed.make({
3916
3998
  });
3917
3999
  const drainEvents = (fileName, events) => Stream.runForEach(Stream.fromAsyncIterable(events, failAsHtmlReporter).pipe(Stream.filter(S.is(Reporter_exports.MutationTestReportReady))), (ready) => writeHtmlReport.run({
3918
4000
  fileName,
3919
- report: ready.report
4001
+ report: ready.report,
4002
+ inlinedBundle: inlinedBundle()
3920
4003
  }).pipe(Effect$1.mapError(failAsHtmlReporter)));
3921
4004
  const makeHtmlReporter = dual(2, (options, _init) => (events) => Layer.build(nodeFsPathLayer).pipe(Effect$1.flatMap((platform) => Effect$1.provideContext(drainEvents(options.htmlReporter.fileName, events), platform)), Effect$1.scoped));
3922
4005
  var HtmlReporter_exports = /* @__PURE__ */ __exportAll({ makeHtmlReporter: () => makeHtmlReporter });
@@ -3927,7 +4010,8 @@ const PERCENTAGE_OPTION = /^(100|[1-9]?[0-9])%$/;
3927
4010
  var TestRunnersOnly = class extends S.TaggedClass()("TestRunnersOnly", {
3928
4011
  testRunners: S.Finite,
3929
4012
  total: S.Finite,
3930
- isPercentage: S.Boolean
4013
+ isPercentage: S.Boolean,
4014
+ announcement: S.Option(S.String)
3931
4015
  }) {
3932
4016
  [ConcurrencyDecisionTypeId] = ConcurrencyDecisionTypeId;
3933
4017
  };
@@ -3935,7 +4019,8 @@ var TestRunnersAndCheckers = class extends S.TaggedClass()("TestRunnersAndChecke
3935
4019
  testRunners: S.Finite,
3936
4020
  checkers: S.Finite,
3937
4021
  total: S.Finite,
3938
- isPercentage: S.Boolean
4022
+ isPercentage: S.Boolean,
4023
+ announcement: S.Option(S.String)
3939
4024
  }) {
3940
4025
  [ConcurrencyDecisionTypeId] = ConcurrencyDecisionTypeId;
3941
4026
  };
@@ -3957,31 +4042,37 @@ const defaultedTotal = (availableParallelism) => Boolean$1.match(availableParall
3957
4042
  const percentageDetails = (text, availableParallelism) => Option$1.match(percentageOf(text), {
3958
4043
  onSome: (percentage) => ({
3959
4044
  total: percentageTotal(percentage, availableParallelism),
3960
- isPercentage: true
4045
+ isPercentage: true,
4046
+ announcement: Option$1.some(`Computed concurrency ${percentageTotal(percentage, availableParallelism)} from "${text}" based on ${availableParallelism} available parallelism.`)
3961
4047
  }),
3962
4048
  onNone: () => ({
3963
4049
  total: defaultedTotal(availableParallelism),
3964
- isPercentage: false
4050
+ isPercentage: false,
4051
+ announcement: Option$1.none()
3965
4052
  })
3966
4053
  });
3967
4054
  const detailsOf = (concurrency, availableParallelism) => Match.value(concurrency).pipe(Match.when(Predicate$1.isString, (text) => percentageDetails(text, availableParallelism)), Match.when(Predicate$1.isNumber, (total) => ({
3968
4055
  total,
3969
- isPercentage: false
4056
+ isPercentage: false,
4057
+ announcement: Option$1.none()
3970
4058
  })), Match.orElse(() => ({
3971
4059
  total: defaultedTotal(availableParallelism),
3972
- isPercentage: false
4060
+ isPercentage: false,
4061
+ announcement: Option$1.none()
3973
4062
  })));
3974
4063
  const splitOf = (details, checkerCount) => Boolean$1.match(checkerCount > 0, {
3975
4064
  onTrue: () => TestRunnersAndCheckers.make({
3976
4065
  testRunners: max$1(floor(details.total / 2), 1),
3977
4066
  checkers: max$1(ceil(details.total / 2), 1),
3978
4067
  total: details.total,
3979
- isPercentage: details.isPercentage
4068
+ isPercentage: details.isPercentage,
4069
+ announcement: details.announcement
3980
4070
  }),
3981
4071
  onFalse: () => TestRunnersOnly.make({
3982
4072
  testRunners: details.total,
3983
4073
  total: details.total,
3984
- isPercentage: details.isPercentage
4074
+ isPercentage: details.isPercentage,
4075
+ announcement: details.announcement
3985
4076
  })
3986
4077
  });
3987
4078
  const decide$7 = (command) => Result.succeed(splitOf(detailsOf(command.concurrency, command.availableParallelism), command.checkerCount));
@@ -4003,19 +4094,15 @@ const readConcurrency = (record) => Effect$1.sync(() => ({
4003
4094
  availableParallelism: availableParallelism(),
4004
4095
  record
4005
4096
  }));
4006
- const announcePercentage = (command, total, isPercentage) => Boolean$1.match(isPercentage, {
4007
- onTrue: () => Effect$1.logDebug(`Computed concurrency ${total} from "${command.concurrency}" based on ${command.availableParallelism} available parallelism.`),
4008
- onFalse: () => Effect$1.void
4009
- });
4010
4097
  const concurrencyCell = Sandwich.named("stryker.concurrency")(readConcurrency).decide(resolveConcurrency).write({
4011
- TestRunnersAndCheckers: (split, command) => Effect$1.as(Effect$1.andThen(announcePercentage(command, split.total, split.isPercentage), Effect$1.logInfo(`Creating ${split.checkers} checker process(es) and ${split.testRunners} test runner process(es).`)), {
4098
+ TestRunnersAndCheckers: (split, command) => Effect$1.as(Effect$1.andThen(Effect$1.forEach(Option$1.toArray(split.announcement), (line) => Effect$1.logDebug(line), { discard: true }), Effect$1.logInfo(`Creating ${split.checkers} checker process(es) and ${split.testRunners} test runner process(es).`)), {
4012
4099
  ...command.record,
4013
4100
  concurrency: {
4014
4101
  testRunners: split.testRunners,
4015
4102
  checkers: split.checkers
4016
4103
  }
4017
4104
  }),
4018
- TestRunnersOnly: (split, command) => Effect$1.as(Effect$1.andThen(announcePercentage(command, split.total, split.isPercentage), Effect$1.logInfo(`Creating ${split.testRunners} test runner process(es).`)), {
4105
+ TestRunnersOnly: (split, command) => Effect$1.as(Effect$1.andThen(Effect$1.forEach(Option$1.toArray(split.announcement), (line) => Effect$1.logDebug(line), { discard: true }), Effect$1.logInfo(`Creating ${split.testRunners} test runner process(es).`)), {
4019
4106
  ...command.record,
4020
4107
  concurrency: {
4021
4108
  testRunners: split.testRunners,
@@ -4058,6 +4145,9 @@ const admitIncrementalReport = Workflow.make({
4058
4145
  error: S.Never,
4059
4146
  decide: (command) => Result.succeed(decide$6(command))
4060
4147
  });
4148
+ //#endregion
4149
+ //#region src/VmRunner.blueprint.ts
4150
+ const TypeId$4 = Symbol.for("~systemfsoftware/stryker-js/VmTestRunner");
4061
4151
  const isVmRunner = (name) => typeof name === "string" && name.toLowerCase() === "vm";
4062
4152
  const vmRunnerCapabilities = { reloadEnvironment: true };
4063
4153
  const HOST_TIMEOUT_SLACK_MS = 1e3;
@@ -4178,12 +4268,17 @@ const pooledVmRunner = (config, scope) => {
4178
4268
  })))
4179
4269
  });
4180
4270
  };
4181
- const vmTestRunner = (config) => Effect$1.gen(function* () {
4271
+ const scopedOf$1 = (config) => Effect$1.gen(function* () {
4182
4272
  const scope = yield* Effect$1.scope;
4183
4273
  return pooledVmRunner(config, scope);
4184
4274
  });
4275
+ const VmRunners = Blueprint.make()(TypeId$4).steps({
4276
+ steps: {},
4277
+ targets: { scoped: scopedOf$1 }
4278
+ });
4279
+ const vmTestRunner = (config) => VmRunners.of(config).scoped;
4185
4280
  //#endregion
4186
- //#region src/read-project.cell.ts
4281
+ //#region src/read-project.parts.ts
4187
4282
  const ALWAYS_IGNORE = Object.freeze([
4188
4283
  "node_modules",
4189
4284
  ".git",
@@ -4596,7 +4691,7 @@ const readProjectCommand = (input) => Effect$1.gen(function* () {
4596
4691
  const mutatePatterns = input.options.mutate;
4597
4692
  const { testFileIgnores, testFilePatterns } = testFileSelectionOf(input.options);
4598
4693
  const inputFileNames = yield* resolveInputFileNames(ignoreRulesOf(input.options), input.basePath);
4599
- const defaults = yield* StrykerConfig.defaultOptions;
4694
+ const defaults = yield* defaultOptions;
4600
4695
  const decision = selectFiles(selectionOf$1(inputFileNames, mutatePatterns, testFilePatterns, testFileIgnores, input.basePath, input.targetMutatePatterns));
4601
4696
  yield* Boolean.match(stringArrayEquivalence(mutatePatterns, defaults.mutate), {
4602
4697
  onTrue: () => Effect$1.void,
@@ -4619,7 +4714,7 @@ const readProjectCommand = (input) => Effect$1.gen(function* () {
4619
4714
  testFiles: [...decision.testFiles]
4620
4715
  });
4621
4716
  });
4622
- const discardLogOf = (command, discard) => Boolean.match(command.incremental, {
4717
+ const discardLogOf = ({ command, discard }) => Boolean.match(command.incremental, {
4623
4718
  onFalse: () => Effect$1.void,
4624
4719
  onTrue: () => Option$1.match(Option$1.fromUndefinedOr(command.contents), {
4625
4720
  onNone: () => Effect$1.void,
@@ -4629,15 +4724,26 @@ const discardLogOf = (command, discard) => Boolean.match(command.incremental, {
4629
4724
  })
4630
4725
  })
4631
4726
  });
4632
- const projectOf = (command, report) => ({
4727
+ const projectOf = ({ command, report }) => ({
4633
4728
  options: command.options,
4634
4729
  targetMutatePatterns: command.targetMutatePatterns,
4635
4730
  basePath: command.basePath,
4636
4731
  project: makeProject(command.fileDescriptions, report, command.testFiles)
4637
4732
  });
4733
+ //#endregion
4734
+ //#region src/read-project.cell.ts
4638
4735
  const readProjectCell = Sandwich.named("stryker.project_read")(readProjectCommand).decide(admitIncrementalReport).write({
4639
- IncrementalReportKeep: (keep, command) => Effect$1.succeed(projectOf(command, keep.report)),
4640
- IncrementalReportDiscard: (discard, command) => Effect$1.as(discardLogOf(command, discard), projectOf(command, void 0)),
4736
+ IncrementalReportKeep: (keep, command) => Effect$1.succeed(projectOf({
4737
+ command,
4738
+ report: keep.report
4739
+ })),
4740
+ IncrementalReportDiscard: (discard, command) => Effect$1.as(discardLogOf({
4741
+ command,
4742
+ discard
4743
+ }), projectOf({
4744
+ command,
4745
+ report: void 0
4746
+ })),
4641
4747
  CommandRejected: ({ issue }) => Effect$1.fail(badArgument({
4642
4748
  module: "stryker-js",
4643
4749
  method: "incremental-report.cell",
@@ -5006,7 +5112,7 @@ const PriorReportDocument = S.Struct({
5006
5112
  }))
5007
5113
  });
5008
5114
  //#endregion
5009
- //#region src/Survivors/Survivors.cell.ts
5115
+ //#region src/Survivors/Survivors.parts.ts
5010
5116
  const DEFAULT_SURVIVORS_PRIOR_REPORT = "reports/mutation-report.json";
5011
5117
  const EMPTY_CONFIG = {};
5012
5118
  const hashContent = (content) => bytesToHex(sha256(utf8ToBytes(content)));
@@ -5035,9 +5141,9 @@ const reportMutantToMutant = (file, mutant, resolveAbsolutePath, relativize) =>
5035
5141
  };
5036
5142
  const extractSurvivors = (priorReport, resolveAbsolutePath, relativize) => Object.entries(priorReport.files).flatMap(([file, fileResult]) => fileResult.mutants.filter((mutant) => mutant.status === "Survived").map((mutant) => reportMutantToMutant(file, mutant, resolveAbsolutePath, relativize)));
5037
5143
  const resolveAbsolutePathOf = (basePath) => (file) => `${basePath}/${file}`;
5038
- const resolveSurvivorsRunOptions = (cliOptions, mode) => readConfig(cliOptions, {
5144
+ const resolveSurvivorsRunOptions = (input) => readConfig(input.cliOptions, {
5039
5145
  command: "run",
5040
- mode
5146
+ mode: input.mode
5041
5147
  });
5042
5148
  const priorReportPathOf = (resolved) => Option$1.getOrElse(Option$1.filter(Option$1.fromUndefinedOr(resolved["survivorsPriorReport"]), Predicate$1.isString), () => DEFAULT_SURVIVORS_PRIOR_REPORT);
5043
5149
  const readPriorReport = (priorReportPath) => Effect$1.flatMap(FileSystem.FileSystem, (fs) => fs.readFileString(priorReportPath).pipe(Effect$1.map((text) => ({
@@ -5060,14 +5166,11 @@ const readSourceFile = (file) => Effect$1.flatMap(FileSystem.FileSystem, (fs) =>
5060
5166
  }))));
5061
5167
  const SOURCE_HASH_CONCURRENCY = 24;
5062
5168
  const currentSourceHashesFor = (files) => Effect$1.map(Effect$1.forEach(files, (file) => Effect$1.map(readSourceFile(file), (content) => [file, hashContent(content)]), { concurrency: SOURCE_HASH_CONCURRENCY }), (pairs) => Object.fromEntries(pairs));
5063
- Sandwich.named("stryker.survivors_admission")((input) => Effect$1.gen(function* () {
5064
- const resolvedOptions = yield* resolveSurvivorsRunOptions(input.cliOptions, input.mode);
5065
- const priorReportPath = priorReportPathOf(resolvedOptions);
5066
- const relativize = (fileName) => RelativeNormalizedFileName.fromAbsolute(fileName, input.basePath).fileName;
5067
- const resolveAbsolutePath = resolveAbsolutePathOf(input.basePath);
5068
- const read = yield* readPriorReport(priorReportPath);
5069
- const sourceContentHashes = yield* currentSourceHashesFor(priorReportFileKeys(read.raw));
5070
- return yield* Boolean$1.match(read.found, {
5169
+ const survivorsRawOf = (input) => {
5170
+ const { read, resolvedOptions, priorReportPath, basePath, sourceContentHashes } = input;
5171
+ const relativize = (fileName) => RelativeNormalizedFileName.fromAbsolute(fileName, basePath).fileName;
5172
+ const resolveAbsolutePath = resolveAbsolutePathOf(basePath);
5173
+ return Boolean$1.match(read.found, {
5071
5174
  onFalse: () => Effect$1.succeed({
5072
5175
  currentConfig: resolvedOptions,
5073
5176
  frameworkVersion: StrykerPackage.version,
@@ -5095,6 +5198,22 @@ Sandwich.named("stryker.survivors_admission")((input) => Effect$1.gen(function*
5095
5198
  })
5096
5199
  }))
5097
5200
  });
5201
+ };
5202
+ Sandwich.named("stryker.survivors_admission")((input) => Effect$1.gen(function* () {
5203
+ const resolvedOptions = yield* resolveSurvivorsRunOptions({
5204
+ cliOptions: input.cliOptions,
5205
+ mode: input.mode
5206
+ });
5207
+ const priorReportPath = priorReportPathOf(resolvedOptions);
5208
+ const read = yield* readPriorReport(priorReportPath);
5209
+ const sourceContentHashes = yield* currentSourceHashesFor(priorReportFileKeys(read.raw));
5210
+ return yield* survivorsRawOf({
5211
+ read,
5212
+ resolvedOptions,
5213
+ priorReportPath,
5214
+ basePath: input.basePath,
5215
+ sourceContentHashes
5216
+ });
5098
5217
  })).decide(admitSurvivorsRun).write({
5099
5218
  Admitted: (admitted, raw) => Effect$1.map(S.decodeEffect(Admitted)(admitted), (admission) => ({
5100
5219
  admission,
@@ -5490,7 +5609,7 @@ const emitHelpEnvelope = (stream, help) => Queue.offer(stream.queue, HelpRendere
5490
5609
  const helpPayload = (ok, captured) => Option$1.filter(Option$1.some(captured), () => ok.help || captured.length > 0);
5491
5610
  const emitNullScoreVerdictWhenOpen = (stream, mode, basePath, pathService) => Effect$1.andThen(stream.isOpen, (open) => Boolean$1.match(open, {
5492
5611
  onTrue: () => Effect$1.gen(function* () {
5493
- const defaults = yield* StrykerConfig.defaultOptions;
5612
+ const defaults = yield* defaultOptions;
5494
5613
  yield* emitNullScoreVerdict({
5495
5614
  stream,
5496
5615
  mode,
@@ -5612,6 +5731,10 @@ var DryRunError = class extends S.TaggedError()("DryRunError", {
5612
5731
  stage: S.Literals(["dryRun", "dryRunNoTests"]),
5613
5732
  reason: S.String
5614
5733
  }) {};
5734
+ var FailedTestSummary = class extends S.Class("FailedTestSummary")({
5735
+ name: S.String,
5736
+ failureMessage: S.String
5737
+ }) {};
5615
5738
  var DryRunCommand = class extends S.TaggedClass()("DryRunCommand", {
5616
5739
  status: S.Literals([
5617
5740
  "Complete",
@@ -5620,6 +5743,7 @@ var DryRunCommand = class extends S.TaggedClass()("DryRunCommand", {
5620
5743
  ]),
5621
5744
  testCount: S.Finite,
5622
5745
  failedTestCount: S.Finite,
5746
+ failedTests: S.Array(FailedTestSummary),
5623
5747
  allowEmpty: S.Boolean,
5624
5748
  errorMessage: S.optional(S.String),
5625
5749
  reason: S.optional(S.String)
@@ -5637,7 +5761,8 @@ var DryRunPassed = class extends S.TaggedClass()("DryRunPassed", { testCount: S.
5637
5761
  };
5638
5762
  var DryRunFailed = class extends S.TaggedClass()("DryRunFailed", {
5639
5763
  testCount: S.Finite,
5640
- failedTestCount: S.Finite
5764
+ failedTestCount: S.Finite,
5765
+ failedTests: S.Array(FailedTestSummary)
5641
5766
  }) {
5642
5767
  [DryRunDecisionTypeId] = DryRunDecisionTypeId;
5643
5768
  };
@@ -5648,13 +5773,15 @@ const completeOutcomeOf = (command) => Match.value(command).pipe(Match.when({
5648
5773
  const decideComplete = (command) => Match.value({
5649
5774
  outcome: completeOutcomeOf(command),
5650
5775
  testCount: command.testCount,
5651
- failedTestCount: command.failedTestCount
5776
+ failedTestCount: command.failedTestCount,
5777
+ failedTests: command.failedTests
5652
5778
  }).pipe(Match.when({ outcome: "noTests" }, () => Result.fail(DryRunError.make({
5653
5779
  stage: "dryRunNoTests",
5654
5780
  reason: "No tests were executed. Stryker will exit prematurely. Please check your configuration."
5655
- }))), Match.when({ outcome: "failed" }, ({ testCount, failedTestCount }) => Result.succeed(DryRunFailed.make({
5781
+ }))), Match.when({ outcome: "failed" }, ({ testCount, failedTestCount, failedTests }) => Result.succeed(DryRunFailed.make({
5656
5782
  testCount,
5657
- failedTestCount
5783
+ failedTestCount,
5784
+ failedTests
5658
5785
  }))), Match.when({ outcome: "passed" }, ({ testCount }) => Result.succeed(DryRunPassed.make({ testCount }))), Match.exhaustive);
5659
5786
  const reasonOrDefault = (reason, fallback) => Match.value(reason).pipe(Match.when(void 0, () => fallback), Match.orElse((present) => present));
5660
5787
  const decide$5 = (command) => Match.value(command.status).pipe(Match.when("Error", () => Result.fail(DryRunError.make({
@@ -5704,7 +5831,43 @@ var PluginLoadRefusedError = class extends Schema.TaggedError()("PluginLoadRefus
5704
5831
  }
5705
5832
  };
5706
5833
  //#endregion
5707
- //#region src/TestRunner.resource.ts
5834
+ //#region src/Sandbox.handle.ts
5835
+ const TypeId$3 = Symbol.for("~systemfsoftware/stryker-js/Sandbox");
5836
+ const SandboxHandle = Handle.make()(TypeId$3);
5837
+ SandboxHandle.is;
5838
+ const sandboxFileNameOf = (fileMap, fileName) => Match.value(fileMap.get(fileName)).pipe(Match.when(Predicate$1.isString, (sandboxFileName) => Result.succeed(sandboxFileName)), Match.orElse(() => Result.fail(StrykerError.make({ message: `Cannot find sandbox file for ${fileName}` }))));
5839
+ const withoutLeadingSeparator = (suffix) => Boolean$1.match(suffix.startsWith("/"), {
5840
+ onTrue: () => suffix.slice(1),
5841
+ onFalse: () => suffix
5842
+ });
5843
+ const relativeToBase = (resolvedSandbox, resolvedWorking, base, pathService) => {
5844
+ const trimmed = withoutLeadingSeparator(resolvedSandbox.slice(resolvedWorking.length));
5845
+ return Boolean$1.match(trimmed.length === 0, {
5846
+ onTrue: () => base,
5847
+ onFalse: () => pathService.join(base, trimmed)
5848
+ });
5849
+ };
5850
+ const originalFileNameOf = (sandboxFileName, workingDirectory, base, pathService) => {
5851
+ const resolvedSandbox = pathService.resolve(sandboxFileName);
5852
+ const resolvedWorking = pathService.resolve(workingDirectory);
5853
+ return Boolean$1.match(resolvedSandbox.startsWith(resolvedWorking), {
5854
+ onTrue: () => relativeToBase(resolvedSandbox, resolvedWorking, base, pathService),
5855
+ onFalse: () => resolvedSandbox.replace(resolvedWorking, base)
5856
+ });
5857
+ };
5858
+ const make$1 = (options) => SandboxHandle.make({ workingDirectory: options.workingDirectory }, {
5859
+ fileMap: options.fileMap,
5860
+ basePath: options.basePath,
5861
+ pathService: options.pathService
5862
+ });
5863
+ const sandboxFileFor = dual(2, (self, fileName) => sandboxFileNameOf(SandboxHandle.slot(self).fileMap, fileName));
5864
+ const originalFileFor = dual(2, (self, sandboxFileName) => {
5865
+ const slot = SandboxHandle.slot(self);
5866
+ return originalFileNameOf(sandboxFileName, self.workingDirectory, slot.basePath, slot.pathService);
5867
+ });
5868
+ //#endregion
5869
+ //#region src/TestRunner.blueprint.ts
5870
+ const TypeId$2 = Symbol.for("~systemfsoftware/stryker-js/TestRunner");
5708
5871
  const toRunnerBootFailure = (runnerName) => (error) => Match.value(error).pipe(Match.tag("WorkerBootTimeoutError", (timeout) => TestRunner_exports.TestRunnerFailed.make({
5709
5872
  runnerName,
5710
5873
  phase: "init",
@@ -5727,7 +5890,7 @@ const toRunnerFailure = (runnerName, phase) => (error) => Match.value(error).pip
5727
5890
  * `Pool.invalidate` and the crash-retry combinator can only act on a failure they
5728
5891
  * can see.
5729
5892
  */
5730
- const makeChildProcessTestRunner = (params) => Effect$1.gen(function* () {
5893
+ const scopedOf = (params) => Effect$1.gen(function* () {
5731
5894
  const runnerName = Match.value(params.options.testRunner).pipe(Match.when(Options_exports.isCustomTestRunner, (runner) => runner.plugin), Match.orElse((name) => name));
5732
5895
  const execArgv = Match.value(params.options.testRunner).pipe(Match.when(Options_exports.isCustomTestRunner, (runner) => Match.value(runner.nodeArgs).pipe(Match.when(Match.undefined, () => params.options.testRunnerNodeArgs), Match.orElse((args) => args))), Match.orElse(() => params.options.testRunnerNodeArgs));
5733
5896
  const client = yield* makeWorkerClient({
@@ -5750,6 +5913,11 @@ const makeChildProcessTestRunner = (params) => Effect$1.gen(function* () {
5750
5913
  mutantRun: (options) => client.mutantRun({ options }).pipe(Effect$1.mapError(toRunnerFailure(runnerName, "mutantRun")))
5751
5914
  });
5752
5915
  });
5916
+ const TestRunners = Blueprint.make()(TypeId$2).steps({
5917
+ steps: {},
5918
+ targets: { scoped: scopedOf }
5919
+ });
5920
+ const makeChildProcessTestRunner = (params) => TestRunners.of(params).scoped;
5753
5921
  const commandRunnerEffect = (context) => ChildProcessSpawner.ChildProcessSpawner.pipe(Effect$1.map((spawner) => commandRunner(context, spawner).pipe(withTimeout, withRetry)));
5754
5922
  const inProcessRunner = (context) => Match.value(context.options.testRunner).pipe(Match.when(isCommandRunner, () => Option$1.some(commandRunnerEffect(context))), Match.when(isVmRunner, () => Option$1.some(vmTestRunner({
5755
5923
  testFiles: context.testFiles,
@@ -5911,8 +6079,8 @@ const resolveConfiguredPlugin = Workflow.make({
5911
6079
  decide: decide$4
5912
6080
  });
5913
6081
  //#endregion
5914
- //#region src/run/dry-run.cell.ts
5915
- const sandboxPathsOf = (sandbox, fileNames) => Result.all(fileNames.map((fileName) => sandbox.sandboxFileFor(fileName)));
6082
+ //#region src/run/dry-run.parts.ts
6083
+ const sandboxPathsOf = (sandbox, fileNames) => Result.all(fileNames.map((fileName) => sandboxFileFor(sandbox, fileName)));
5916
6084
  const configuredPluginOf$1 = (configured) => Match.value(configured).pipe(Match.when(Options_exports.isCustomTestRunner, (custom) => ConfiguredPluginModulePath.make({ modulePath: custom.plugin })), Match.orElse((name) => ConfiguredPluginName.make({ name })));
5917
6085
  const workerSpawnOf$1 = (stage, loaded, kind, configured) => Effect$1.mapError(Effect$1.fromResult(resolveConfiguredPlugin(WorkerSpawnCommand.make({
5918
6086
  sources: loaded.pluginSources,
@@ -5936,11 +6104,16 @@ const resolveDryRunFiles = (command) => Effect$1.fromResult(buildDryRunFiles(com
5936
6104
  reason: "Failed to resolve sandbox file",
5937
6105
  cause
5938
6106
  })));
6107
+ const failedTestSummariesOf = (tests) => tests.filter((test) => test.status === "failed").map((test) => FailedTestSummary.make({
6108
+ name: test.name,
6109
+ failureMessage: test.failureMessage
6110
+ }));
5939
6111
  const commandEncodedComplete = (complete, allowEmpty) => ({
5940
6112
  _tag: "DryRunCommand",
5941
6113
  status: "Complete",
5942
6114
  testCount: complete.tests.length,
5943
6115
  failedTestCount: complete.tests.filter((test) => test.status === "failed").length,
6116
+ failedTests: failedTestSummariesOf(complete.tests),
5944
6117
  allowEmpty
5945
6118
  });
5946
6119
  const commandEncodedFailed = (failed, allowEmpty) => ({
@@ -5948,6 +6121,7 @@ const commandEncodedFailed = (failed, allowEmpty) => ({
5948
6121
  status: "Error",
5949
6122
  testCount: 0,
5950
6123
  failedTestCount: 0,
6124
+ failedTests: [],
5951
6125
  allowEmpty,
5952
6126
  errorMessage: failed.errorMessage
5953
6127
  });
@@ -5956,6 +6130,7 @@ const commandEncodedTimedOut = (timedOut, allowEmpty) => ({
5956
6130
  status: "Timeout",
5957
6131
  testCount: 0,
5958
6132
  failedTestCount: 0,
6133
+ failedTests: [],
5959
6134
  allowEmpty,
5960
6135
  ...Option$1.match(Option$1.fromNullishOr(timedOut.reason), {
5961
6136
  onNone: () => ({}),
@@ -5987,7 +6162,7 @@ const totalTestTime = (tests) => tests.reduce((total, test) => total + test.time
5987
6162
  const overheadMillisOf = (grossMillis, tests) => Math.max(0, grossMillis - totalTestTime(tests));
5988
6163
  const withOriginalFileName = (test, prev) => Match.value(test.fileName).pipe(Match.when(Predicate$1.isString, (fileName) => ({
5989
6164
  ...test,
5990
- fileName: prev.sandbox.originalFileFor(fileName)
6165
+ fileName: originalFileFor(prev.sandbox, fileName)
5991
6166
  })), Match.orElse(() => test));
5992
6167
  const withOriginalFileNames = (tests, prev) => tests.map((test) => withOriginalFileName(test, prev));
5993
6168
  const ZERO = 0;
@@ -6110,20 +6285,32 @@ const writeDryRunPassed = (raw) => withPhaseSpan("dryRun", {}, () => Effect$1.ge
6110
6285
  yield* phaseEntered("dry-run");
6111
6286
  return yield* completeDryRunPassed(raw);
6112
6287
  }));
6113
- const writeDryRunFailed = (raw, testCount, failedTestCount) => withPhaseSpan("dryRun", {}, () => Effect$1.gen(function* () {
6288
+ const FAILED_TESTS_REASON = "There were failed tests in the initial test run.";
6289
+ const failedTestsDetail = (failedTests) => failedTests.map((test) => ` ${test.name}${test.failureMessage.length > 0 ? `: ${test.failureMessage}` : ""}`).join("\n");
6290
+ const reasonWithFailedTests = (detail) => detail.length > 0 ? `${FAILED_TESTS_REASON}\n${detail}` : FAILED_TESTS_REASON;
6291
+ const writeDryRunFailed = ({ testCount, failedTestCount, failedTests }) => withPhaseSpan("dryRun", {}, () => Effect$1.gen(function* () {
6114
6292
  yield* phaseEntered("dry-run");
6293
+ const detail = failedTestsDetail(failedTests);
6294
+ yield* Effect$1.logError(`Initial test run failed. ${failedTestCount} of ${testCount} test(s) failed:\n${detail}`);
6115
6295
  return yield* StageError.make({
6116
6296
  stage: "dryRun",
6117
- reason: "There were failed tests in the initial test run.",
6297
+ reason: reasonWithFailedTests(detail),
6118
6298
  cause: DryRunFailed.make({
6119
6299
  testCount,
6120
- failedTestCount
6300
+ failedTestCount,
6301
+ failedTests
6121
6302
  })
6122
6303
  });
6123
6304
  }));
6305
+ //#endregion
6306
+ //#region src/run/dry-run.cell.ts
6124
6307
  const dryRunCell = Sandwich.named("stryker.dry_run")(readDryRun).decide(dryRun).write({
6125
6308
  DryRunPassed: (_decision, raw) => writeDryRunPassed(raw),
6126
- DryRunFailed: ({ testCount, failedTestCount }, raw) => writeDryRunFailed(raw, testCount, failedTestCount),
6309
+ DryRunFailed: ({ testCount, failedTestCount, failedTests }, _raw) => writeDryRunFailed({
6310
+ testCount,
6311
+ failedTestCount,
6312
+ failedTests
6313
+ }),
6127
6314
  DryRunError: ({ stage, reason }) => Effect$1.fail(StageError.make({
6128
6315
  stage,
6129
6316
  reason,
@@ -6406,37 +6593,6 @@ function buildErrorMessage({ type, sourceText, position }) {
6406
6593
  return `Cannot parse JSONC: unexpected token "${token}" in JSONC at position ${position}`;
6407
6594
  }
6408
6595
  //#endregion
6409
- //#region src/Sandbox.handle.ts
6410
- const TypeId$1 = Symbol.for("@systemfsoftware/stryker-js/SandboxHandle");
6411
- const sandboxFileNameOf = (fileMap, fileName) => Match.value(fileMap.get(fileName)).pipe(Match.when(Predicate.isString, (sandboxFileName) => Result.succeed(sandboxFileName)), Match.orElse(() => Result.fail(StrykerError.make({ message: `Cannot find sandbox file for ${fileName}` }))));
6412
- const withoutLeadingSeparator = (suffix) => Boolean.match(suffix.startsWith("/"), {
6413
- onTrue: () => suffix.slice(1),
6414
- onFalse: () => suffix
6415
- });
6416
- const relativeToBase = (resolvedSandbox, resolvedWorking, base, pathService) => {
6417
- const trimmed = withoutLeadingSeparator(resolvedSandbox.slice(resolvedWorking.length));
6418
- return Boolean.match(trimmed.length === 0, {
6419
- onTrue: () => base,
6420
- onFalse: () => pathService.join(base, trimmed)
6421
- });
6422
- };
6423
- const originalFileNameOf = (sandboxFileName, workingDirectory, base, pathService) => {
6424
- const resolvedSandbox = pathService.resolve(sandboxFileName);
6425
- const resolvedWorking = pathService.resolve(workingDirectory);
6426
- return Boolean.match(resolvedSandbox.startsWith(resolvedWorking), {
6427
- onTrue: () => relativeToBase(resolvedSandbox, resolvedWorking, base, pathService),
6428
- onFalse: () => resolvedSandbox.replace(resolvedWorking, base)
6429
- });
6430
- };
6431
- const make$1 = (options) => {
6432
- const handle = {
6433
- workingDirectory: options.workingDirectory,
6434
- sandboxFileFor: (fileName) => sandboxFileNameOf(options.fileMap, fileName),
6435
- originalFileFor: (sandboxFileName) => originalFileNameOf(sandboxFileName, options.workingDirectory, options.basePath, options.pathService)
6436
- };
6437
- return Object.assign(handle, { [TypeId$1]: TypeId$1 });
6438
- };
6439
- //#endregion
6440
6596
  //#region src/Sandbox.schema.ts
6441
6597
  /**
6442
6598
  * Sandbox.schema — declarations for the Sandbox capability.
@@ -6463,7 +6619,7 @@ const TsConfigSchema = Schema.StructWithRest(Schema.Struct({
6463
6619
  /** A tsconfig `extends` entry list: the array form of `extends`. */
6464
6620
  const ExtendsArraySchema = Schema.Array(Schema.String);
6465
6621
  //#endregion
6466
- //#region src/Sandbox.resource.ts
6622
+ //#region src/Sandbox.blueprint.ts
6467
6623
  const combinePreprocessors = (preprocessors) => (project) => Effect$1.forEach(preprocessors, (pre) => pre(project), { discard: true });
6468
6624
  const mergeUpdatedFile = (project, updated) => {
6469
6625
  MutableHashMap.set(project.files, updated.name, updated);
@@ -6723,13 +6879,13 @@ const symlinkNodeModules = (options, workingDirectory, basePath, pathService) =>
6723
6879
  onFalse: () => Effect$1.void
6724
6880
  });
6725
6881
  });
6726
- const acquireSandbox = (state) => Effect$1.gen(function* () {
6727
- const { options, project, workingDirectory, backupDirectory, basePath } = state.spec;
6882
+ const acquireSandbox = (spec) => Effect$1.gen(function* () {
6883
+ const { options, project, workingDirectory, backupDirectory, basePath } = spec;
6728
6884
  yield* Scope.Scope;
6729
6885
  const pathService = yield* Path.Path;
6730
6886
  yield* announceSandbox(options, workingDirectory, backupDirectory, basePath, pathService);
6731
6887
  yield* Effect$1.when(restoreOriginalFiles(workingDirectory, backupDirectory, basePath), Effect$1.succeed(hasBackupToRestore(options, backupDirectory)));
6732
- yield* combinePreprocessors([createPreprocessor(options, basePath, state.spec.formatRegistry), ...state.preprocessors])(project).pipe(Effect$1.mapError((cause) => StrykerError.make({
6888
+ yield* combinePreprocessors([createPreprocessor(options, basePath, spec.formatRegistry), ...spec.preprocessors])(project).pipe(Effect$1.mapError((cause) => StrykerError.make({
6733
6889
  message: "Sandbox preprocessor failed",
6734
6890
  cause
6735
6891
  })));
@@ -6754,31 +6910,22 @@ const acquireSandbox = (state) => Effect$1.gen(function* () {
6754
6910
  pathService
6755
6911
  });
6756
6912
  });
6757
- const TypeId = Symbol.for("@systemfsoftware/stryker-js/Sandbox");
6758
- const makeProto = (state) => {
6759
- return {
6760
- [TypeId]: TypeId,
6761
- spec: state.spec,
6762
- ...Prototype,
6763
- withPreprocessor(preprocessor) {
6764
- return makeProto({
6765
- spec: state.spec,
6766
- preprocessors: [...state.preprocessors, preprocessor]
6767
- });
6768
- },
6769
- get scoped() {
6770
- return acquireSandbox(state);
6771
- },
6772
- layer(service) {
6773
- return Layer.effect(service)(acquireSandbox(state));
6774
- }
6775
- };
6776
- };
6777
- const make = (spec) => makeProto({
6778
- spec,
6913
+ const TypeId$1 = Symbol.for("~systemfsoftware/stryker-js/Sandbox");
6914
+ const Sandboxes = Blueprint.make()(TypeId$1).steps({
6915
+ steps: { withPreprocessor: (spec, preprocessor) => ({
6916
+ ...spec,
6917
+ preprocessors: [...spec.preprocessors, preprocessor]
6918
+ }) },
6919
+ targets: {
6920
+ scoped: (spec) => acquireSandbox(spec),
6921
+ layer: (spec) => (service) => Layer.effect(service)(acquireSandbox(spec))
6922
+ }
6923
+ });
6924
+ const make = (spec) => Sandboxes.of({
6925
+ ...spec,
6779
6926
  preprocessors: []
6780
6927
  });
6781
- dual(2, (self, preprocessor) => self.withPreprocessor(preprocessor));
6928
+ Sandboxes.operations.withPreprocessor;
6782
6929
  const makeSandbox = (input) => make(input).scoped;
6783
6930
  //#endregion
6784
6931
  //#region src/run/explain-file-skip.workflow.ts
@@ -6847,13 +6994,13 @@ const explainFileSkip = Workflow.make({
6847
6994
  decide: (command) => Match.value(skipKnownOrUnknownOf(explainedOf(command))).pipe(Match.tag("SkipKnownExplained", (known) => Result.succeed(known)), Match.tag("SkipUnknownExplained", (unknown) => Result.succeed(unknown)), Match.exhaustive)
6848
6995
  });
6849
6996
  //#endregion
6850
- //#region src/run/instrument.cell.ts
6851
- const offerSkipsIfAny = (skipped, claimants) => Boolean$1.match(skipped.length === 0, {
6997
+ //#region src/run/instrument.parts.ts
6998
+ const offerSkipsIfAny = (input) => Boolean$1.match(input.skipped.length === 0, {
6852
6999
  onTrue: () => Effect$1.void,
6853
7000
  onFalse: () => Effect$1.gen(function* () {
6854
- const files = skipped.map((skip) => Result.match(explainFileSkip(ExplainFileSkipCommand.make({
7001
+ const files = input.skipped.map((skip) => Result.match(explainFileSkip(ExplainFileSkipCommand.make({
6855
7002
  extension: skip.extension,
6856
- claimants: [...claimants]
7003
+ claimants: [...input.claimants]
6857
7004
  })), {
6858
7005
  onFailure: absurd,
6859
7006
  onSuccess: (explained) => ({
@@ -6866,11 +7013,40 @@ const offerSkipsIfAny = (skipped, claimants) => Boolean$1.match(skipped.length =
6866
7013
  yield* Queue.offer(queue, SkippedReported.make({ files }));
6867
7014
  })
6868
7015
  });
7016
+ const sandboxDirectoriesOf = (input) => Boolean$1.match(input.command.options.inPlace, {
7017
+ onTrue: () => ({
7018
+ workingDirectory: input.basePath,
7019
+ backupDirectory: input.command.temporaryDirectoryPath
7020
+ }),
7021
+ onFalse: () => ({
7022
+ workingDirectory: input.command.temporaryDirectoryPath,
7023
+ backupDirectory: ""
7024
+ })
7025
+ });
7026
+ const mergeInstrumentedFile = (input) => {
7027
+ const files = MutableHashMap.fromIterable(input.project.files);
7028
+ MutableHashMap.set(files, input.file.name, input.file);
7029
+ const filesToMutate = MutableHashMap.fromIterable(input.project.filesToMutate);
7030
+ Boolean$1.match(input.file.mutate !== false, {
7031
+ onTrue: () => MutableHashMap.set(filesToMutate, input.file.name, input.file),
7032
+ onFalse: () => MutableHashMap.remove(filesToMutate, input.file.name)
7033
+ });
7034
+ return {
7035
+ ...input.project,
7036
+ files,
7037
+ filesToMutate
7038
+ };
7039
+ };
7040
+ //#endregion
7041
+ //#region src/run/instrument.cell.ts
6869
7042
  const enteringInstrumentPhase = (raw, body) => withPhaseSpan("instrument", { fileCount: raw.filesToMutate.length }, () => Effect$1.gen(function* () {
6870
7043
  yield* phaseEntered("instrument");
6871
7044
  return yield* body;
6872
7045
  }));
6873
- const writeInstrument = (raw) => enteringInstrumentPhase(raw, Effect$1.as(offerSkipsIfAny(raw.instrumentResult.skipped, raw.prev.frameworkClaimants), {
7046
+ const writeInstrument = (raw) => enteringInstrumentPhase(raw, Effect$1.as(offerSkipsIfAny({
7047
+ skipped: raw.instrumentResult.skipped,
7048
+ claimants: raw.prev.frameworkClaimants
7049
+ }), {
6874
7050
  ...raw.prev,
6875
7051
  project: raw.instrumentedProject,
6876
7052
  mutants: raw.instrumentResult.mutants,
@@ -6880,37 +7056,13 @@ const writeInstrument = (raw) => enteringInstrumentPhase(raw, Effect$1.as(offerS
6880
7056
  checkers: raw.concurrency.checkers
6881
7057
  }
6882
7058
  }));
6883
- const sandboxDirectoriesOf = (command, basePath) => Boolean$1.match(command.options.inPlace, {
6884
- onTrue: () => ({
6885
- workingDirectory: basePath,
6886
- backupDirectory: command.temporaryDirectoryPath
6887
- }),
6888
- onFalse: () => ({
6889
- workingDirectory: command.temporaryDirectoryPath,
6890
- backupDirectory: ""
6891
- })
6892
- });
6893
- const mergeInstrumentedFile = (project, file) => {
6894
- const files = MutableHashMap.fromIterable(project.files);
6895
- MutableHashMap.set(files, file.name, file);
6896
- const filesToMutate = MutableHashMap.fromIterable(project.filesToMutate);
6897
- Boolean$1.match(file.mutate !== false, {
6898
- onTrue: () => MutableHashMap.set(filesToMutate, file.name, file),
6899
- onFalse: () => MutableHashMap.remove(filesToMutate, file.name)
6900
- });
6901
- return {
6902
- ...project,
6903
- files,
6904
- filesToMutate
6905
- };
6906
- };
6907
- const withInstrumentedFiles = (project, instrumented) => Arr.reduce([...instrumented], project, (current, { name, content }) => Option$1.match(MutableHashMap.get(current.files, name), {
6908
- onNone: () => current,
6909
- onSome: (existing) => mergeInstrumentedFile(current, {
7059
+ const withInstrumentedFiles = (project, instrumented) => Arr.reduce([...instrumented], project, (current, { name, content }) => Option$1.getOrElse(Option$1.map(MutableHashMap.get(current.files, name), (existing) => mergeInstrumentedFile({
7060
+ project: current,
7061
+ file: {
6910
7062
  ...existing,
6911
7063
  content
6912
- })
6913
- }));
7064
+ }
7065
+ })), () => current));
6914
7066
  const instrumentCell = Sandwich.named("stryker.instrument")((command) => Effect$1.gen(function* () {
6915
7067
  yield* Scope.Scope;
6916
7068
  const env = yield* RunEnvironment;
@@ -6934,7 +7086,10 @@ const instrumentCell = Sandwich.named("stryker.instrument")((command) => Effect$
6934
7086
  cause
6935
7087
  })));
6936
7088
  const instrumentedProject = withInstrumentedFiles(command.project, instrumentResult.files);
6937
- const directories = sandboxDirectoriesOf(command, env.basePath);
7089
+ const directories = sandboxDirectoriesOf({
7090
+ command,
7091
+ basePath: env.basePath
7092
+ });
6938
7093
  const sandbox = yield* makeSandbox({
6939
7094
  options: command.options,
6940
7095
  project: instrumentedProject,
@@ -7028,13 +7183,18 @@ const admitMutationTest = Workflow.make({
7028
7183
  decide: decide$2
7029
7184
  });
7030
7185
  //#endregion
7031
- //#region src/Checker/Checker.resource.ts
7186
+ //#region src/Checker/Checker.blueprint.ts
7187
+ const TypeId = Symbol.for("~systemfsoftware/stryker-js/CheckerBlueprint");
7032
7188
  const checkerProcessCrashes = Metric.counter("stryker.checker.process_crashes", {
7033
7189
  description: "Checker worker processes that never became usable",
7034
7190
  incremental: true
7035
7191
  });
7036
7192
  const TEMP_DIR_PREFIX = "stryker-checker-";
7037
7193
  const nodeArgsOf = (options) => Match.value(options.checkers[0]?.nodeArgs).pipe(Match.when(Match.undefined, () => options.checkerNodeArgs), Match.orElse((args) => args));
7194
+ const serviceOf = (handle) => ({
7195
+ check: (checkerName, mutants) => check(handle, checkerName, mutants),
7196
+ group: (checkerName, mutants) => group(handle, checkerName, mutants)
7197
+ });
7038
7198
  const acquire = (spec) => Effect$1.gen(function* () {
7039
7199
  const client = yield* makeWorkerClient({
7040
7200
  rpcs: Plugin_exports.CheckerRpcs,
@@ -7044,9 +7204,13 @@ const acquire = (spec) => Effect$1.gen(function* () {
7044
7204
  execArgv: [...nodeArgsOf(spec.options)],
7045
7205
  tempDirPrefix: TEMP_DIR_PREFIX
7046
7206
  }).pipe(Effect$1.mapError((error) => Match.value(error).pipe(Match.tag("ChildProcessCrashedError", "OutOfMemoryError", (crash) => crash), Match.tag("WorkerBootTimeoutError", () => connectionCrashed(`Checker worker failed to start: its boot window closed before it accepted the RPC connection`)), Match.exhaustive)), Effect$1.tapError(() => Metric.update(checkerProcessCrashes, 1)));
7047
- return makeCheckerHandle(client);
7207
+ return serviceOf(makeCheckerHandle(client));
7208
+ });
7209
+ const Checkers = Blueprint.make()(TypeId).steps({
7210
+ steps: {},
7211
+ targets: { scoped: acquire }
7048
7212
  });
7049
- const scoped = (spec) => acquire(spec);
7213
+ const scoped = (spec) => Checkers.of(spec).scoped;
7050
7214
  //#endregion
7051
7215
  //#region src/incremental-diff.workflow.ts
7052
7216
  const REMEMBERED_STATUS = /* @__PURE__ */ new Set([
@@ -7351,7 +7515,7 @@ const planMutantTests = Workflow.make({
7351
7515
  decide
7352
7516
  });
7353
7517
  //#endregion
7354
- //#region src/run/mutation-test.cell.ts
7518
+ //#region src/run/mutation-test.parts.ts
7355
7519
  const relativeFileNameOf = (fileName, basePath) => RelativeNormalizedFileName.fromAbsolute(fileName, basePath).fileName;
7356
7520
  const readCurrentRelativeFiles = (project, basePath) => Effect$1.gen(function* () {
7357
7521
  const entries = yield* (yield* ProjectFiles).readAllOriginal(MutableHashMap.values(project.files));
@@ -7368,7 +7532,7 @@ const reportingInputOf = (prev, env, results) => ({
7368
7532
  reporterStage: prev.reporterStage,
7369
7533
  formatRegistry: prev.formatRegistry
7370
7534
  });
7371
- const sandboxFilePairsOf = (sandbox, fileNames) => Result.all(fileNames.map((fileName) => Result.map(sandbox.sandboxFileFor(fileName), (sandboxFileName) => [fileName, sandboxFileName])));
7535
+ const sandboxFilePairsOf = (sandbox, fileNames) => Result.all(fileNames.map((fileName) => Result.map(sandboxFileFor(sandbox, fileName), (sandboxFileName) => [fileName, sandboxFileName])));
7372
7536
  const sandboxFilesOf = (sandbox, fileNames) => Effect$1.fromResult(sandboxFilePairsOf(sandbox, fileNames)).pipe(Effect$1.mapError((cause) => StageError.make({
7373
7537
  stage: "mutationTest",
7374
7538
  reason: "Failed to resolve sandbox file",
@@ -7676,7 +7840,7 @@ const stopWallClock = (result) => Boolean$1.match(wallClockTimeoutStopsRun(resul
7676
7840
  })),
7677
7841
  onFalse: () => Effect$1.void
7678
7842
  });
7679
- const writeMutationTestNoTests = () => Effect$1.gen(function* () {
7843
+ const writeMutationTestNoTests = Effect$1.gen(function* () {
7680
7844
  const env = yield* RunEnvironment;
7681
7845
  const now = yield* Clock.currentTimeMillis;
7682
7846
  const elapsed = Duration.millis(now - env.runStartedAt);
@@ -7687,7 +7851,7 @@ const writeMutationTestNoTests = () => Effect$1.gen(function* () {
7687
7851
  verdict: null
7688
7852
  };
7689
7853
  });
7690
- const writeMutationTestDryRunOnly = () => Effect$1.gen(function* () {
7854
+ const writeMutationTestDryRunOnly = Effect$1.gen(function* () {
7691
7855
  yield* phaseEntered("mutation-test");
7692
7856
  yield* Effect$1.logInfo("The dry-run has been completed successfully. No mutations have been executed.");
7693
7857
  return {
@@ -7879,11 +8043,18 @@ const writeMutationTestProceed = (raw) => Effect$1.gen(function* () {
7879
8043
  yield* Effect$1.logInfo(`Done in ${Duration.format(elapsed)}.`);
7880
8044
  return outcomeResult;
7881
8045
  }).pipe(Effect$1.mapError((cause) => mapMutationTestCause(cause)));
7882
- const writeMutationTestOutcome = (raw, outcome) => withPhaseSpan("mutationTest", {
8046
+ const writeMutationTestOutcome = ({ raw, outcome }) => withPhaseSpan("mutationTest", {
7883
8047
  mutantCount: raw.prev.mutants.length,
7884
8048
  skippedMutantCount: partitionPlannable(raw.prev.mutants).dropped.length,
7885
8049
  testCount: raw.prev.dryRunResult.tests.length
7886
8050
  }, () => outcome);
8051
+ const mapMutationTestCause = (cause) => Match.value({ cause }).pipe(Match.when({ cause: isStageError }, ({ cause }) => cause), Match.orElse(({ cause }) => StageError.make({
8052
+ stage: "mutationTest",
8053
+ reason: "Mutation testing failed",
8054
+ cause
8055
+ })));
8056
+ //#endregion
8057
+ //#region src/run/mutation-test.cell.ts
7887
8058
  const mutationTestCell$1 = Sandwich.named("stryker.mutation_test")((command) => Effect$1.gen(function* () {
7888
8059
  yield* Scope.Scope;
7889
8060
  const prev = command;
@@ -7896,9 +8067,18 @@ const mutationTestCell$1 = Sandwich.named("stryker.mutation_test")((command) =>
7896
8067
  prev
7897
8068
  };
7898
8069
  })).decide(admitMutationTest).write({
7899
- MutationTestDryRunOnly: (_decision, raw) => writeMutationTestOutcome(raw, writeMutationTestDryRunOnly()),
7900
- MutationTestNoTests: (_decision, raw) => writeMutationTestOutcome(raw, writeMutationTestNoTests()),
7901
- MutationTestProceed: (_decision, raw) => writeMutationTestOutcome(raw, writeMutationTestProceed(raw)),
8070
+ MutationTestDryRunOnly: (_decision, raw) => writeMutationTestOutcome({
8071
+ raw,
8072
+ outcome: writeMutationTestDryRunOnly
8073
+ }),
8074
+ MutationTestNoTests: (_decision, raw) => writeMutationTestOutcome({
8075
+ raw,
8076
+ outcome: writeMutationTestNoTests
8077
+ }),
8078
+ MutationTestProceed: (_decision, raw) => writeMutationTestOutcome({
8079
+ raw,
8080
+ outcome: writeMutationTestProceed(raw)
8081
+ }),
7902
8082
  MutationTestError: ({ stage, reason }) => Effect$1.fail(StageError.make({
7903
8083
  stage,
7904
8084
  reason,
@@ -7912,11 +8092,6 @@ const mutationTestCell$1 = Sandwich.named("stryker.mutation_test")((command) =>
7912
8092
  reason: issue
7913
8093
  }))
7914
8094
  });
7915
- const mapMutationTestCause = (cause) => Match.value({ cause }).pipe(Match.when({ cause: isStageError }, ({ cause }) => cause), Match.orElse(({ cause }) => StageError.make({
7916
- stage: "mutationTest",
7917
- reason: "Mutation testing failed",
7918
- cause
7919
- })));
7920
8095
  //#endregion
7921
8096
  //#region src/framework-claimant.service.ts
7922
8097
  const dependencyNamesOf = (dependencies) => Object.keys(dependencies ?? {});
@@ -8463,24 +8638,48 @@ const planPrepare = Workflow.make({
8463
8638
  decide: (decoded) => Match.value(decoded.mode).pipe(Match.when("human", () => Result.succeed(HumanReporters.make({ reporters: decoded.reporters }))), Match.when("machine", () => Result.succeed(MachineReporters.make({ reporters: decoded.reporters }))), Match.exhaustive)
8464
8639
  });
8465
8640
  //#endregion
8641
+ //#region src/run/prepare.parts.ts
8642
+ const announceSummary = (input) => Match.value(input.env.resolvedMode.mode).pipe(Match.when("human", () => announceHumanSummary({
8643
+ allowConsoleColors: input.env.allowConsoleColors,
8644
+ summary: input.summary
8645
+ })), Match.orElse(() => Effect$1.logInfo(input.summary)));
8646
+ const announceHumanSummary = (input) => Boolean$1.match(input.allowConsoleColors, {
8647
+ onTrue: () => Console.log(`${AnsiCode.fields.green.literal}${input.summary}${AnsiCode.fields.reset.literal}`),
8648
+ onFalse: () => Console.log(input.summary)
8649
+ });
8650
+ const STREAM_REPORTER = "progress-stream";
8651
+ const HUMAN_REPORTER = "clear-text";
8652
+ const STDOUT_REPORTERS = {
8653
+ "clear-text": true,
8654
+ "progress": true
8655
+ };
8656
+ const asHumanReporter = (name) => {
8657
+ if (name === STREAM_REPORTER) return HUMAN_REPORTER;
8658
+ return name;
8659
+ };
8660
+ const selectReporters = dual(2, (configured, mode) => Match.value(mode).pipe(Match.when("human", () => [...new Set(configured.map(asHumanReporter))]), Match.when("machine", () => {
8661
+ const permitted = configured.filter((name) => STDOUT_REPORTERS[name] !== true);
8662
+ return Match.value(permitted.includes(STREAM_REPORTER)).pipe(Match.when(true, () => permitted), Match.when(false, () => [...permitted, STREAM_REPORTER]), Match.exhaustive);
8663
+ }), Match.exhaustive));
8664
+ const failOnEmptyProject = (fileCount) => Match.value(fileCount).pipe(Match.when(0, () => Effect$1.fail(StageError.make({
8665
+ stage: "prepare",
8666
+ reason: "No input files found.",
8667
+ cause: PrepareError.make({
8668
+ stage: "prepare",
8669
+ reason: "No input files found."
8670
+ })
8671
+ }))), Match.orElse(() => Effect$1.void));
8672
+ //#endregion
8466
8673
  //#region src/run/prepare.cell.ts
8467
8674
  const NO_PLUGIN_DESCRIPTORS = [];
8468
8675
  const schemaPropertiesOf = (document) => Option$1.getOrElse(Option$1.fromNullishOr(document.properties), () => ({}));
8469
- const buildMergedSchema = (core, contributions) => Boolean$1.match(contributions.length === 0, {
8470
- onTrue: () => core,
8471
- onFalse: () => ({
8472
- ...core,
8473
- properties: contributions.reduce((merged, contribution) => ({
8474
- ...merged,
8475
- ...schemaPropertiesOf(contribution)
8476
- }), schemaPropertiesOf(core))
8477
- })
8478
- });
8479
- const announceSummary = (env, summary) => Match.value(env.resolvedMode.mode).pipe(Match.when("human", () => announceHumanSummary(env.allowConsoleColors, summary)), Match.orElse(() => Effect$1.logInfo(summary)));
8480
- const announceHumanSummary = (allowConsoleColors, summary) => Boolean$1.match(allowConsoleColors, {
8481
- onTrue: () => Console.log(`${AnsiCode.fields.green.literal}${summary}${AnsiCode.fields.reset.literal}`),
8482
- onFalse: () => Console.log(summary)
8483
- });
8676
+ const buildMergedSchema = (core, contributions) => contributions.reduce((merged, contribution) => ({
8677
+ ...merged,
8678
+ properties: {
8679
+ ...schemaPropertiesOf(merged),
8680
+ ...schemaPropertiesOf(contribution)
8681
+ }
8682
+ }), core);
8484
8683
  const readPrepare = (command) => Effect$1.gen(function* () {
8485
8684
  yield* Scope.Scope;
8486
8685
  const env = yield* RunEnvironment;
@@ -8531,9 +8730,10 @@ const readPrepare = (command) => Effect$1.gen(function* () {
8531
8730
  }])]);
8532
8731
  const frameworkClaimants = yield* installedFrameworkClaimants(env.basePath);
8533
8732
  return {
8733
+ now: yield* Clock.currentTimeMillis,
8534
8734
  mode: env.resolvedMode.mode,
8535
8735
  reporters: [...options.reporters],
8536
- fileCount: MutableHashMap.size(command.project.files),
8736
+ fileCount: pipe(command.project.files, MutableHashMap.size),
8537
8737
  availableReporters: [...HashMap.values(reporterChoicesByName)].map((choice) => choice.name),
8538
8738
  env,
8539
8739
  queue,
@@ -8548,22 +8748,17 @@ const readPrepare = (command) => Effect$1.gen(function* () {
8548
8748
  };
8549
8749
  });
8550
8750
  const writePrepare = (reporters, raw) => withPhaseSpan("prepare", {}, (span) => Effect$1.gen(function* () {
8551
- const mutateCount = MutableHashMap.size(raw.project.filesToMutate);
8552
- yield* announceSummary(raw.env, `Found ${mutateCount} of ${MutableHashMap.size(raw.project.files)} file(s) to be mutated.`);
8751
+ const mutateCount = pipe(raw.project.filesToMutate, MutableHashMap.size);
8752
+ yield* announceSummary({
8753
+ env: raw.env,
8754
+ summary: `Found ${mutateCount} of ${pipe(raw.project.files, MutableHashMap.size)} file(s) to be mutated.`
8755
+ });
8553
8756
  yield* validateReporterNames(raw.options.reporters, [...HashMap.values(raw.reporterChoicesByName)].map((choice) => choice.name)).pipe(Effect$1.mapError((cause) => StageError.make({
8554
8757
  stage: "prepare",
8555
8758
  reason: cause.message,
8556
8759
  cause
8557
8760
  })));
8558
- const failOnEmptyProject = (fileCount) => Match.value(fileCount).pipe(Match.when(0, () => Effect$1.fail(StageError.make({
8559
- stage: "prepare",
8560
- reason: "No input files found.",
8561
- cause: PrepareError.make({
8562
- stage: "prepare",
8563
- reason: "No input files found."
8564
- })
8565
- }))), Match.orElse(() => Effect$1.void));
8566
- yield* failOnEmptyProject(raw.project.files.pipe(MutableHashMap.size));
8761
+ yield* failOnEmptyProject(pipe(raw.project.files, MutableHashMap.size));
8567
8762
  const temporaryDirectoryPath = yield* Effect$1.map(Layer.build(TemporaryDirectory.layer(raw.options)), (temporaryDirectory) => Context.get(temporaryDirectory, TemporaryDirectory).path).pipe(Effect$1.mapError((cause) => StageError.make({
8568
8763
  stage: "prepare",
8569
8764
  reason: "Failed to create temporary directory",
@@ -8572,7 +8767,7 @@ const writePrepare = (reporters, raw) => withPhaseSpan("prepare", {}, (span) =>
8572
8767
  const reporterInputs = yield* reporterInputsOf(reporters, raw.reporterChoicesByName, raw.loaded, raw.env.basePath, raw.options);
8573
8768
  const reporterInit = yield* currentReporterInit(span);
8574
8769
  const reporterStage = yield* attachReporterFactories(reporterInputs, raw.options, reporterInit);
8575
- const now = yield* Clock.currentTimeMillis;
8770
+ const { now } = raw;
8576
8771
  yield* Queue.offer(raw.queue, PhaseEntered.make({
8577
8772
  phase: "prepare",
8578
8773
  elapsedMs: now - raw.env.runStartedAt
@@ -8588,20 +8783,6 @@ const writePrepare = (reporters, raw) => withPhaseSpan("prepare", {}, (span) =>
8588
8783
  frameworkClaimants: raw.frameworkClaimants
8589
8784
  };
8590
8785
  }));
8591
- const STREAM_REPORTER = "progress-stream";
8592
- const HUMAN_REPORTER = "clear-text";
8593
- const STDOUT_REPORTERS = {
8594
- "clear-text": true,
8595
- "progress": true
8596
- };
8597
- const asHumanReporter = (name) => {
8598
- if (name === STREAM_REPORTER) return HUMAN_REPORTER;
8599
- return name;
8600
- };
8601
- const selectReporters = dual(2, (configured, mode) => Match.value(mode).pipe(Match.when("human", () => [...new Set(configured.map(asHumanReporter))]), Match.when("machine", () => {
8602
- const permitted = configured.filter((name) => STDOUT_REPORTERS[name] !== true);
8603
- return Match.value(permitted.includes(STREAM_REPORTER)).pipe(Match.when(true, () => permitted), Match.when(false, () => [...permitted, STREAM_REPORTER]), Match.exhaustive);
8604
- }), Match.exhaustive));
8605
8786
  const prepareCell = Sandwich.named("stryker.prepare")(readPrepare).decide(planPrepare).write({
8606
8787
  HumanReporters: ({ reporters }, raw) => writePrepare(reporters, raw),
8607
8788
  MachineReporters: ({ reporters }, raw) => writePrepare(reporters, raw),
@@ -8636,4 +8817,4 @@ const strykerCell = dual((args) => Predicate$1.isObject(args[0]), (options, targ
8636
8817
  })
8637
8818
  })), Effect$1.scoped));
8638
8819
  //#endregion
8639
- export { ImportedModuleSchema as $, VerdictMutant as A, FileMatcher as B, readConfig as C, RunEvents as D, IdGenerator as E, makeWorkerClient as F, ConfigFileUnsupportedError as G, ConfigFileInvalidError as H, WorkerLauncher as I, ExtendsStepDone as J, ConfigDocumentSchema as K, make$2 as L, MetricsResultFromReport as M, reporterWorkerFactory as N, RunIdentity as O, spawnReporterWorker as P, ExtendsStepStateSchema as Q, StrykerError as R, mergeConfigs as S, RunEnvironment as T, ConfigFileNotFoundError as U, ConfigError as V, ConfigFileUnreadableError as W, ExtendsStepRefused as X, ExtendsStepRead as Y, ExtendsStepResolve as Z, describeErrors as _, RunEventDrainLive as a, survivorsPriorReport as at, initialExtendsStepState as b, isVmRunner as c, OutOfMemoryError as ct, nodePlatformLayer as d, CheckerSkippedRequested as dt, MergeCommand as et, layerWorkerProtocol as f, decideExtendsStep as g, classifyWorkerExit as h, RunEventDrain as i, forkOptionsSchema as it, VerdictThresholds as j, VerdictEnvelope as k, vmTestRunner as l, WorkerBootTimeoutError as lt, ClassifyWorkerExitDecision as m, strykerCell as n, ReadConfigCommand as nt, makeRunEventStream as o, checkGroupedPlans as ot, ClassifyWorkerExitCommand as p, ExtendsStepDocumentSchema as q, buildTestRunner as r, extendsPropertySchema as rt, RunEventWireLine as s, ChildProcessCrashedError as st, mutationTestCell as t, MergeResult as tt, IncrementalReportSchema as u, CheckerAnsweredUnrequested as ut, forkCoreSchema as v, validateOptions as w, loadConfigCell as x, importModule as y, isCommandRunner as z };
8820
+ export { ExtendsStepResolve as $, VerdictMutant as A, FileMatcher as B, mergeConfigs as C, RunEvents as D, IdGenerator as E, makeWorkerClient as F, ConfigFileUnsupportedError as G, ConfigFileInvalidError as H, WorkerLauncher as I, ConfigDocumentSchema as J, createDefaultOptions as K, make$2 as L, MetricsResultFromReport as M, reporterWorkerFactory as N, RunIdentity as O, spawnReporterWorker as P, ExtendsStepRefused as Q, StrykerError as R, initialExtendsStepState as S, RunEnvironment as T, ConfigFileNotFoundError as U, ConfigError as V, ConfigFileUnreadableError as W, ExtendsStepDone as X, ExtendsStepDocumentSchema as Y, ExtendsStepRead as Z, readConfig as _, RunEventDrainLive as a, extendsPropertySchema as at, forkCoreSchema as b, isVmRunner as c, checkGroupedPlans as ct, nodePlatformLayer as d, WorkerBootTimeoutError as dt, ExtendsStepStateSchema as et, layerWorkerProtocol as f, CheckerAnsweredUnrequested as ft, loadConfigCell as g, classifyWorkerExit as h, RunEventDrain as i, ReadConfigCommand as it, VerdictThresholds as j, VerdictEnvelope as k, vmTestRunner as l, ChildProcessCrashedError as lt, ClassifyWorkerExitDecision as m, strykerCell as n, MergeCommand as nt, makeRunEventStream as o, forkOptionsSchema as ot, ClassifyWorkerExitCommand as p, CheckerSkippedRequested as pt, defaultOptions as q, buildTestRunner as r, MergeResult as rt, RunEventWireLine as s, survivorsPriorReport as st, mutationTestCell as t, ImportedModuleSchema as tt, IncrementalReportSchema as u, OutOfMemoryError as ut, decideExtendsStep as v, validateOptions as w, importModule as x, describeErrors as y, isCommandRunner as z };