@systemfsoftware/stryker-js 17.0.2 → 22.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.
package/dist/index.mjs CHANGED
@@ -1,18 +1,19 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-8H4AJuhK.mjs";
2
- import { i as Mutant_exports, l as Report_exports, n as mergeConfigs } from "./merge-config-ruui2TPS.mjs";
3
- import { $ as WorkerLauncher, A as classifyWorkerExit, At as OutOfMemoryError, B as SurvivorRef, C as nodePlatformLayer, Ct as MergeResult, D as git_diff_schema_exports, Dt as survivorsPriorReport, E as git_diff_service_exports, Et as forkOptionsSchema, F as readConfig, Ft as CheckerAnsweredUnrequested, G as generateRunId, H as RunEvents, I as RunEnvironment, It as CheckerSkippedRequested, J as metricsResultFromFiles, K as VerdictEnvelope, L as IdGenerator, M as loadConfigCell, Mt as OutputMode_exports, N as describeErrors, Nt as RunEvent_exports$1, O as ClassifyWorkerExitCommand, Ot as checkGroupedPlans, P as forkCoreSchema, Pt as SpanTaxonomy_exports, Q as makeWorkerClient, R as surfacedSurvivorsOf, S as IncrementalReportSchema, St as MergeCommand, T as GitDiff, Tt as extendsPropertySchema, U as RunIdentity, V as StrykerPackage, W as buildVerdictEnvelope, X as reporterWorkerFactory, Y as MetricsResultFromReport, Z as spawnReporterWorker, _ as isCommandRunner, _t as defaultOptions, a as MachineConsole, at as initialExtendsStepState, b as readProjectCell, bt as ExtendsStepStateSchema, c as prepareCell, ct as ExtendsStepRead, d as buildTestRunner, dt as ConfigError, et as make, f as makeChildProcessTestRunner, ft as ConfigFileInvalidError, g as vmTestRunnerConfig, gt as createDefaultOptions, h as vmRunnerPluginUrl, ht as ConfigFileUnsupportedError, i as makeRunEventStream, it as importModule, j as validateOptions, jt as WorkerBootTimeoutError, k as ClassifyWorkerExitDecision, kt as ChildProcessCrashedError, l as mutantDetailEventsOf, lt as ExtendsStepRefused, m as testRunnerConfigOf, mt as ConfigFileUnreadableError, n as RunEventDrain, nt as FileMatcher, o as HtmlReporter_exports, ot as StrykerError, p as isVmRunner, pt as ConfigFileNotFoundError, q as staticVerdictOf, r as RunEventDrainLive, rt as decideExtendsStep, s as mutationTestCell, st as ExtendsStepDone, t as strykerCell, tt as ReproducerSchema, u as instrumentCell, ut as ExtendsStepResolve, v as import_closure_cell_exports, vt as ConfigDocumentSchema, w as layerWorkerProtocol, wt as ReadConfigCommand, x as concurrencyCell, xt as ImportedModuleSchema, y as relativeNormalizedFileName, yt as ExtendsStepDocumentSchema, z as SurfacingFields } from "./run-stages-DnDU_wrY.mjs";
2
+ import { i as Mutant_exports, l as Report_exports, n as mergeConfigs } from "./merge-config-BWQeU3-p.mjs";
3
+ import { $ as IncrementalReportSchema, $t as checkCell, A as optionalField, At as ExtendsStepDone, B as nodePlatformLayer, Bt as createDefaultOptions, C as offerSkipsIfAny, Ct as WorkerLauncher, D as dryRunChoiceOf, Dt as importModule, E as reusedTestCoverage, Et as decideExtendsStep, F as diffScopeDecisionOf, Ft as ConfigError, G as git_diff_service_exports, Gt as ImportedModuleSchema, H as SourceParser, Ht as ConfigDocumentSchema, I as DryRunCoverageReused, It as ConfigFileInvalidError, J as git_diff_schema_exports, Jt as ReadConfigCommand, K as ChangedSince, Kt as MergeCommand, L as scoped$1, Lt as ConfigFileNotFoundError, M as relativeNormalizedFileName, Mt as ExtendsStepRefused, N as requireDryRun, Nt as ExtendsStepResolve, O as requireDryRunCommandOf, Ot as initialExtendsStepState, P as readProjectCell, Pt as FileMatcher, Q as classifyWorkerExit, Qt as groupCell, R as makeCheckerPoolHandle, Rt as ConfigFileUnreadableError, S as instrumentFiles, St as makeWorkerClient, T as readIncrementalReuse, Tt as ReproducerSchema, U as source_parser_service_exports, Ut as ExtendsStepDocumentSchema, V as layerWorkerProtocol, Vt as defaultOptions, W as GitDiff, Wt as ExtendsStepStateSchema, X as ClassifyWorkerExitCommand, Xt as forkOptionsSchema, Y as EmptyDirectory, Yt as extendsPropertySchema, Z as ClassifyWorkerExitDecision, Zt as survivorsPriorReport, _ as testRunnerConfigOf, _t as metricsResultFromFiles, a as HtmlReporter_exports, an as ShardPlan, at as RunEnvironment, b as planPrepare, bt as spawnReporterWorker, c as instrumentCell, cn as SpanTaxonomy_exports, ct as SurfacingFields, d as isCommandRunner, dn as CheckerSkippedRequested, dt as RunEvents, en as ChildProcessCrashedError, et as validateOptions, f as mutantDetailEventsOf, ft as RunIdentity, g as isVmRunner, gt as staticVerdictOf, h as readPrepare, ht as VerdictEnvelope, i as MachineConsole, in as RunEvent_exports$1, it as readConfig, j as import_closure_cell_exports, jt as ExtendsStepRead, k as incrementalReportTextsOf, kt as StrykerError, l as buildTestRunner, ln as CheckerAnsweredUnrequested, lt as SurvivorRef, m as admitPreparedProject, mt as generateRunId, n as RunEventDrain, nn as WorkerBootTimeoutError, nt as describeErrors, o as mutationTestCell, on as ShardPlanVersion, ot as IdGenerator, p as concurrencyCell, pt as buildVerdictEnvelope, q as WholeProject, qt as MergeResult, r as makeRunEventStream, rn as OutputMode_exports, rt as forkCoreSchema, s as prepareCell, sn as ShardProject, st as surfacedSurvivorsOf, t as strykerCell, tn as OutOfMemoryError, tt as loadConfigCell, u as makeChildProcessTestRunner, un as CheckerIgnoredWithoutRule, ut as StrykerPackage, v as vmRunnerPluginUrl, vt as MetricsResultFromReport, w as planInstrumentation, wt as make, x as enteringInstrumentPhase, xt as withPhaseSpan, y as vmTestRunnerConfig, yt as reporterWorkerFactory, z as programDigestOf, zt as ConfigFileUnsupportedError } from "./run-stages-BnFibYAg.mjs";
4
4
  import { n as StageError } from "./Run.schema-DuaneDGd.mjs";
5
- import { Cell, Sandwich, Workflow } from "@systemfsoftware/effect-cell-types";
5
+ import { Blueprint, Cell, Handle, Sandwich, Workflow } from "@systemfsoftware/effect-cell-types";
6
6
  import * as S from "effect/Schema";
7
+ import * as Arr from "effect/Array";
8
+ import * as Effect from "effect/Effect";
7
9
  import * as Option from "effect/Option";
10
+ import { dual } from "effect/Function";
8
11
  import * as Context from "effect/Context";
9
- import * as Effect from "effect/Effect";
10
12
  import * as Boolean from "effect/Boolean";
11
- import * as Arr from "effect/Array";
12
13
  import * as Match from "effect/Match";
13
14
  import * as Result from "effect/Result";
14
- import { dual } from "effect/Function";
15
15
  import "effect/Cause";
16
+ import * as Record from "effect/Record";
16
17
  import * as FileSystem from "effect/FileSystem";
17
18
  import * as Path from "effect/Path";
18
19
  import * as Stream from "effect/Stream";
@@ -20,8 +21,10 @@ import * as Clock from "effect/Clock";
20
21
  import * as Layer from "effect/Layer";
21
22
  import * as Queue from "effect/Queue";
22
23
  import "effect/Scope";
24
+ import * as MutableHashMap from "effect/MutableHashMap";
23
25
  import * as SocketServer from "effect/socket/SocketServer";
24
26
  import * as Fiber from "effect/Fiber";
27
+ import * as HashSet from "effect/HashSet";
25
28
  import * as DateTime from "effect/DateTime";
26
29
  import * as Ref from "effect/Ref";
27
30
  import * as Stdio from "effect/Stdio";
@@ -29,12 +32,20 @@ import { NodeSocketServer } from "@effect/platform-node";
29
32
  import * as ChildProcessSpawner from "effect/process/ChildProcessSpawner";
30
33
  import * as FiberSet from "effect/FiberSet";
31
34
  import * as Socket from "effect/socket/Socket";
35
+ import "effect/Console";
32
36
  import { McpProtocol, McpServer, Tool, Toolkit } from "effect/ai";
37
+ //#region src/Checker/Checker.cell.ts
38
+ const checkGroupedCell = groupCell.pipe(Cell.flatMap((groups) => Cell.mapInput(Cell.collect(checkCell, (perGroup) => perGroup.flat()), (input) => groups.map((group) => ({
39
+ ...input,
40
+ plans: group
41
+ })))));
42
+ //#endregion
33
43
  //#region src/Checker/mod.ts
34
44
  var Checker_exports = /* @__PURE__ */ __exportAll({
35
45
  CheckerAnsweredUnrequested: () => CheckerAnsweredUnrequested,
46
+ CheckerIgnoredWithoutRule: () => CheckerIgnoredWithoutRule,
36
47
  CheckerSkippedRequested: () => CheckerSkippedRequested,
37
- checkGroupedPlans: () => checkGroupedPlans
48
+ checkGroupedCell: () => checkGroupedCell
38
49
  });
39
50
  //#endregion
40
51
  //#region src/Configuration/mod.ts
@@ -72,15 +83,587 @@ var Configuration_exports = /* @__PURE__ */ __exportAll({
72
83
  validateOptions: () => validateOptions
73
84
  });
74
85
  //#endregion
86
+ //#region src/plan-request.schema.ts
87
+ const CostsFieldSchema = S.StructWithRest(S.Struct({ costs: S.Record(S.String, S.Struct({
88
+ predictedMs: S.Finite,
89
+ actualMs: S.NullOr(S.Finite)
90
+ })).pipe(S.optional) }), [S.Record(S.String, S.Json)]);
91
+ const CompileErrorProbeSchema = S.Struct({ files: S.Record(S.String, S.Struct({ mutants: S.Array(S.Struct({ status: S.String })) })) });
92
+ var PlanShardsRefused = class extends S.TaggedError()("PlanShardsRefused", { detail: S.String }) {
93
+ exitClass = "ConfigError";
94
+ next = "Pass --target-seconds above 0 and --max-shards of 1 or more, and name each project directory once in --projects.";
95
+ get reason() {
96
+ return `stryker plan: the planner refused its input: ${this.detail}. ${this.next}`;
97
+ }
98
+ get message() {
99
+ return this.reason;
100
+ }
101
+ };
102
+ //#endregion
103
+ //#region src/plan-shards.workflow.ts
104
+ const { ceil, max, min, sign } = Math;
105
+ const MAX_COST_MS = Number.MAX_SAFE_INTEGER;
106
+ const CostMs = S.Finite.pipe(S.check(S.isBetween({
107
+ minimum: 0,
108
+ maximum: MAX_COST_MS
109
+ })));
110
+ const PositiveSeconds = S.Finite.pipe(S.check(S.isGreaterThan(0)));
111
+ const PositiveInt = S.Int.pipe(S.check(S.isGreaterThanOrEqualTo(1)));
112
+ const PlannedMutant = S.Struct({
113
+ project: S.String,
114
+ id: Mutant_exports.MutantId,
115
+ costMs: CostMs,
116
+ dependsOnDryRun: S.Boolean,
117
+ placementKey: S.optional(Mutant_exports.MutantId)
118
+ });
119
+ const mutantKeyOf = (mutant) => `\u0000${mutant.project}\u0000${mutant.id}`;
120
+ const plannedMutantsAreDistinct = S.makeFilter((mutants) => Boolean.match(new Set(mutants.map(mutantKeyOf)).size === mutants.length, {
121
+ onTrue: () => void 0,
122
+ onFalse: () => "two planned mutants share a project and a mutant id"
123
+ }), { arbitraryConstraint: { uniqueBy: mutantKeyOf } });
124
+ const PlannedMutants = S.Array(PlannedMutant).check(plannedMutantsAreDistinct);
125
+ var PlanShardsCommand = class extends S.TaggedClass()("PlanShardsCommand", {
126
+ targetSeconds: PositiveSeconds,
127
+ maxShards: S.optional(PositiveInt),
128
+ mutants: PlannedMutants,
129
+ dryRunCosts: S.Record(S.String, CostMs)
130
+ }) {
131
+ static [Workflow.InstrumentationBrand] = {};
132
+ };
133
+ const ShardPlanTypeId = Symbol.for("@systemfsoftware/stryker-js/PlannedShards");
134
+ var PlannedShard = class extends S.TaggedClass()("PlannedShard", {
135
+ index: S.Int,
136
+ count: S.Int,
137
+ predictedSeconds: Report_exports.NonNegativeFinite,
138
+ projects: S.Array(ShardProject)
139
+ }) {
140
+ [ShardPlanTypeId] = ShardPlanTypeId;
141
+ };
142
+ const compareText = (left, right) => sign(Number(left > right) - Number(left < right));
143
+ const compareProjectThenId = (left, right) => Boolean.match(compareText(left.project, right.project) === 0, {
144
+ onTrue: () => compareText(left.id, right.id),
145
+ onFalse: () => compareText(left.project, right.project)
146
+ });
147
+ const totalCostMsOf = (mutants) => mutants.reduce((total, mutant) => total + mutant.costMs, 0);
148
+ const dryRunCostOf = (command, project) => Option.getOrElse(Record.get(command.dryRunCosts, project), () => 0);
149
+ const dependentProjectsOf = (command) => {
150
+ const byProject = command.mutants.reduce((accumulated, mutant) => Boolean.match(mutant.dependsOnDryRun, {
151
+ onTrue: () => Record.set(accumulated, mutant.project, [...Option.getOrElse(Record.get(accumulated, mutant.project), () => []), mutant]),
152
+ onFalse: () => accumulated
153
+ }), {});
154
+ return [...Record.toEntries(byProject)].sort(([left], [right]) => compareText(left, right)).map(([project, mutants]) => ({
155
+ project,
156
+ dependentCostMs: totalCostMsOf(mutants),
157
+ dryRunCostMs: dryRunCostOf(command, project),
158
+ mutants
159
+ }));
160
+ };
161
+ const dryRunBinsNeededOf = (project, targetMs) => {
162
+ const remainingMs = targetMs - project.dryRunCostMs;
163
+ return Boolean.match(remainingMs > 0, {
164
+ onTrue: () => max(1, ceil(project.dependentCostMs / remainingMs)),
165
+ onFalse: () => Number.POSITIVE_INFINITY
166
+ });
167
+ };
168
+ const plannedLoadMsOf = (command, projects, targetMs) => totalCostMsOf(command.mutants) + projects.reduce((total, project) => {
169
+ const bins = dryRunBinsNeededOf(project, targetMs);
170
+ return Boolean.match(Number.isFinite(bins), {
171
+ onTrue: () => total + bins * project.dryRunCostMs,
172
+ onFalse: () => total
173
+ });
174
+ }, 0);
175
+ const neededShardsOf = (command, loadMs) => max(1, ceil(loadMs / 1e3 / command.targetSeconds));
176
+ const cappedShardsOf = (command, loadMs) => Option.match(Option.fromUndefinedOr(command.maxShards), {
177
+ onNone: () => neededShardsOf(command, loadMs),
178
+ onSome: (maxShards) => max(1, min(maxShards, neededShardsOf(command, loadMs)))
179
+ });
180
+ const shardCountOf = (command, loadMs) => min(cappedShardsOf(command, loadMs), max(command.mutants.length, 1));
181
+ const EMPTY_BIN = {
182
+ mutants: [],
183
+ load: 0
184
+ };
185
+ const emptyBins = (count) => Array.from({ length: count }, () => ({
186
+ mutants: [],
187
+ load: 0
188
+ }));
189
+ const indicesOf = (count) => Array.from({ length: count }, (_unused, index) => index);
190
+ const loadAt = (bins, index) => Option.getOrElse(Option.fromUndefinedOr(bins[index]), () => EMPTY_BIN).load;
191
+ const leastLoadedOf = (bins, indices) => indices.reduce((best, index) => Boolean.match(loadAt(bins, index) < loadAt(bins, best), {
192
+ onTrue: () => index,
193
+ onFalse: () => best
194
+ }), Option.getOrElse(Option.fromUndefinedOr(indices[0]), () => 0));
195
+ const compareLoadedBins = (left, right) => sign(sign(left.load - right.load) * 2 + sign(left.index - right.index));
196
+ const leastLoadedIndicesOf = (bins, count) => indicesOf(bins.length).map((index) => ({
197
+ index,
198
+ load: loadAt(bins, index)
199
+ })).sort(compareLoadedBins).slice(0, count).map((entry) => entry.index);
200
+ const placementKeyOf$1 = (mutant) => Option.getOrElse(Option.fromUndefinedOr(mutant.placementKey), () => mutantKeyOf(mutant));
201
+ const projectOfGroup = (members) => Option.match(Arr.head(members), {
202
+ onNone: () => "",
203
+ onSome: (head) => head.project
204
+ });
205
+ const placementGroupsOf = (mutants) => Record.toEntries(Arr.groupBy(mutants, placementKeyOf$1)).map(([key, members]) => {
206
+ const sorted = [...members].sort(compareProjectThenId);
207
+ return {
208
+ key,
209
+ project: projectOfGroup(sorted),
210
+ mutants: sorted,
211
+ costMs: totalCostMsOf(sorted),
212
+ dependsOnDryRun: sorted.some((mutant) => mutant.dependsOnDryRun)
213
+ };
214
+ });
215
+ const compareGroupsCostliestFirst = (left, right) => Boolean.match(left.costMs === right.costMs, {
216
+ onTrue: () => Boolean.match(compareText(left.project, right.project) === 0, {
217
+ onTrue: () => compareText(left.key, right.key),
218
+ onFalse: () => compareText(left.project, right.project)
219
+ }),
220
+ onFalse: () => sign(right.costMs - left.costMs)
221
+ });
222
+ const withGroupIn = (bins, index, group) => bins.map((bin, at) => Boolean.match(at === index, {
223
+ onTrue: () => ({
224
+ mutants: [...bin.mutants, ...group.mutants],
225
+ load: bin.load + group.costMs
226
+ }),
227
+ onFalse: () => bin
228
+ }));
229
+ const reservedBin = (bins, index, costMs) => bins.map((bin, at) => Boolean.match(at === index, {
230
+ onTrue: () => ({
231
+ mutants: bin.mutants,
232
+ load: bin.load + costMs
233
+ }),
234
+ onFalse: () => bin
235
+ }));
236
+ const projectsOf$1 = (mutants) => {
237
+ const byProject = mutants.reduce((accumulated, mutant) => Record.set(accumulated, mutant.project, [...Option.getOrElse(Record.get(accumulated, mutant.project), () => []), mutant.id]), {});
238
+ return [...Record.toEntries(byProject)].sort(([left], [right]) => compareText(left, right)).map(([project, ids]) => ({
239
+ project,
240
+ mutants: [...ids].sort(compareText)
241
+ }));
242
+ };
243
+ const shardsOf = (command) => {
244
+ const targetMs = command.targetSeconds * 1e3;
245
+ const dependentProjects = dependentProjectsOf(command);
246
+ const count = shardCountOf(command, plannedLoadMsOf(command, dependentProjects, targetMs));
247
+ const reserved = dependentProjects.reduce((accumulated, project) => {
248
+ const indices = leastLoadedIndicesOf(accumulated.bins, min(dryRunBinsNeededOf(project, targetMs), count));
249
+ return {
250
+ bins: indices.reduce((bins, index) => reservedBin(bins, index, project.dryRunCostMs), accumulated.bins),
251
+ indicesByProject: {
252
+ ...accumulated.indicesByProject,
253
+ [project.project]: indices
254
+ }
255
+ };
256
+ }, {
257
+ bins: emptyBins(count),
258
+ indicesByProject: {}
259
+ });
260
+ const groups = placementGroupsOf(command.mutants);
261
+ const withDependents = groups.filter((group) => group.dependsOnDryRun).sort(compareGroupsCostliestFirst).reduce((bins, group) => withGroupIn(bins, leastLoadedOf(bins, Option.getOrElse(Record.get(reserved.indicesByProject, group.project), () => indicesOf(count))), group), reserved.bins);
262
+ return groups.filter((group) => Boolean.not(group.dependsOnDryRun)).sort(compareGroupsCostliestFirst).reduce((bins, group) => withGroupIn(bins, leastLoadedOf(bins, indicesOf(bins.length)), group), withDependents).map((bin, index) => PlannedShard.make({
263
+ index: index + 1,
264
+ count,
265
+ predictedSeconds: bin.load / 1e3,
266
+ projects: projectsOf$1(bin.mutants)
267
+ }));
268
+ };
269
+ const planShards = Workflow.make({
270
+ command: PlanShardsCommand,
271
+ decision: S.Array(PlannedShard),
272
+ error: S.Never,
273
+ decide: (command) => Result.succeed(shardsOf(command))
274
+ });
275
+ //#endregion
276
+ //#region src/project-directory.ts
277
+ const projectsOf = (projects) => Option.getOrElse(Option.filter(Option.fromUndefinedOr(projects), Arr.isReadonlyArrayNonEmpty), () => ["."]);
278
+ const inProjectDirectory = (directory, body) => Effect.suspend(() => {
279
+ const previous = globalThis.process.cwd();
280
+ return Effect.acquireUseRelease(Effect.sync(() => globalThis.process.chdir(directory)), () => body, () => Effect.sync(() => globalThis.process.chdir(previous)));
281
+ });
282
+ /**
283
+ * Runs `body` once per `--projects` entry, one at a time, with the process
284
+ * working directory switched to that entry, because config discovery reads
285
+ * the working directory. No entries means the working directory alone.
286
+ */
287
+ const forEachProjectDirectory = dual(2, (projects, body) => Effect.forEach(projectsOf(projects), (directory) => inProjectDirectory(directory, body(directory)), { concurrency: 1 }));
288
+ //#endregion
289
+ //#region src/run/plan-instrument.cell.ts
290
+ const gatherPlanInstrument = Effect.fn(SpanTaxonomy_exports.Spans.instrumentGather.name)(function* (command) {
291
+ const { filesToMutate, instrumentResult, instrumentedProject } = yield* instrumentFiles(command);
292
+ return {
293
+ _tag: "InstrumentCommand",
294
+ fileCount: filesToMutate.length,
295
+ inPlace: command.options.inPlace,
296
+ pluginCount: command.loadedPlugins.pluginModulePaths.length,
297
+ prev: command,
298
+ instrumentedProject,
299
+ instrumentResult,
300
+ mutants: instrumentResult.mutants
301
+ };
302
+ });
303
+ const readPlanInstrument = (command) => enteringInstrumentPhase(command.project.filesToMutate.size, gatherPlanInstrument(command));
304
+ const writePlanInstrument = (raw) => Effect.as(offerSkipsIfAny({
305
+ skipped: raw.instrumentResult.skipped,
306
+ claimants: raw.prev.frameworkClaimants
307
+ }), {
308
+ project: raw.instrumentedProject,
309
+ mutants: raw.mutants,
310
+ options: raw.prev.options,
311
+ incrementalReportDiscard: raw.prev.incrementalReportDiscard
312
+ });
313
+ const planInstrumentCell = Sandwich.named(SpanTaxonomy_exports.Spans.instrument.name)(readPlanInstrument).decide(planInstrumentation).write({
314
+ InPlaceInstrument: (_decision, raw) => writePlanInstrument(raw),
315
+ EphemeralInstrument: (_decision, raw) => writePlanInstrument(raw),
316
+ CommandRejected: ({ issue }) => Effect.fail(StageError.make({
317
+ stage: "instrument",
318
+ reason: issue
319
+ }))
320
+ });
321
+ //#endregion
322
+ //#region src/run/plan-prepare.cell.ts
323
+ const writePrepareForInstrument = (raw) => withPhaseSpan(SpanTaxonomy_exports.Spans.preparePhase, {}, () => Effect.gen(function* () {
324
+ yield* admitPreparedProject(raw);
325
+ yield* Queue.offer(raw.queue, RunEvent_exports$1.PhaseEntered.make({
326
+ phase: "prepare",
327
+ elapsedMs: raw.now - raw.env.runStartedAt
328
+ }));
329
+ return {
330
+ project: raw.project,
331
+ loadedPlugins: raw.loaded,
332
+ ignorers: raw.ignorers,
333
+ mutatorCatalogs: raw.mutatorCatalogs,
334
+ mutatorSelection: raw.mutatorSelection,
335
+ formatRegistry: raw.formatRegistry,
336
+ options: raw.options,
337
+ frameworkClaimants: raw.frameworkClaimants,
338
+ incrementalReportDiscard: raw.incrementalReportDiscard
339
+ };
340
+ }));
341
+ const prepareForInstrumentCell = Sandwich.named(SpanTaxonomy_exports.Spans.prepare.name)(readPrepare).decide(planPrepare).write({
342
+ HumanReporters: (_decision, raw) => writePrepareForInstrument(raw),
343
+ MachineReporters: (_decision, raw) => writePrepareForInstrument(raw),
344
+ CommandRejected: ({ issue }) => Effect.fail(StageError.make({
345
+ stage: "prepare",
346
+ reason: issue
347
+ }))
348
+ });
349
+ //#endregion
350
+ //#region src/plan-request.cell.ts
351
+ const DEFAULT_MUTANT_COST_MS = 1e3;
352
+ const prepareStageCell = Cell.andThen(Cell.andThen(loadConfigCell, readProjectCell), prepareForInstrumentCell);
353
+ const planStageCell = Cell.andThen(prepareStageCell, (prepared) => Cell.map(planInstrumentCell, (done) => ({
354
+ prepared,
355
+ done
356
+ })));
357
+ const namedCostsOf = (costs) => Object.fromEntries(Object.entries(costs).flatMap(([mutantId, entry]) => Option.toArray(Option.map(Option.orElse(Option.fromNullishOr(entry.actualMs), () => Option.fromNullishOr(entry.predictedMs)), (costMs) => [mutantId, costMs]))));
358
+ const reportCostsOf = (texts) => texts.reduce((accumulated, text) => Option.match(S.decodeOption(S.fromJsonString(CostsFieldSchema))(text), {
359
+ onNone: () => accumulated,
360
+ onSome: (decoded) => Option.match(Option.fromUndefinedOr(decoded.costs), {
361
+ onNone: () => accumulated,
362
+ onSome: (costs) => ({
363
+ ...namedCostsOf(costs),
364
+ ...accumulated
365
+ })
366
+ })
367
+ }), {});
368
+ const testsTimeOf = (tests) => tests.reduce((total, test) => total + test.timeSpentMs, 0);
369
+ const runsWholeSuite = (testCoverage, mutantId) => Option.match(Option.fromNullishOr(testCoverage.staticCoverage), {
370
+ onNone: () => true,
371
+ onSome: (staticCoverage) => Option.getOrElse(Option.fromUndefinedOr(staticCoverage[mutantId]), () => 0) > 0
372
+ });
373
+ const coveringCostOf = (coverage, testCoverage, mutantId) => Option.orElse(Option.map(Option.filter(Option.map(MutableHashMap.get(testCoverage.testsByMutantId, mutantId), (tests) => testsTimeOf([...tests])), (millis) => millis > 0), (millis) => millis + coverage.timeOverheadMs), () => Option.filter(Option.some(testsTimeOf(coverage.tests) + coverage.timeOverheadMs), () => runsWholeSuite(testCoverage, mutantId)));
374
+ const costOf = (mutantId, reportCosts, coverage, testCoverage) => Option.getOrElse(Option.orElse(Record.get(reportCosts, mutantId), () => Option.flatMap(coverage, (present) => coveringCostOf(present, testCoverage, mutantId))), () => DEFAULT_MUTANT_COST_MS);
375
+ const emptyTestCoverage = () => ({
376
+ testsByMutantId: MutableHashMap.empty(),
377
+ testsById: MutableHashMap.empty(),
378
+ staticCoverage: void 0,
379
+ hitsByMutantId: MutableHashMap.empty(),
380
+ dryRunCoverage: void 0
381
+ });
382
+ const dependentMutantIdsOf = (decision) => Match.value(decision).pipe(Match.tag("DryRunNeeded", (needed) => needed.dependentMutantIds), Match.tag("DryRunSkippable", () => []), Match.exhaustive);
383
+ const labelOf = (path, basePath, project) => {
384
+ const relative = path.relative(basePath, project).replace(/\\/g, "/");
385
+ return relative.length === 0 ? "." : relative;
386
+ };
387
+ const reportHoldsCompileErrorRecord = (text) => Option.exists(S.decodeOption(S.fromJsonString(CompileErrorProbeSchema))(text), (report) => Object.values(report.files).some((file) => file.mutants.some((mutant) => mutant.status === "CompileError")));
388
+ const programDigestAtPlanTime = ({ texts, context, options, loadedPlugins, project }) => Boolean.match(Boolean.and(Boolean.not(options.inPlace), texts.some(reportHoldsCompileErrorRecord)), {
389
+ onTrue: () => Effect.gen(function* () {
390
+ const pool = yield* scoped$1({
391
+ options,
392
+ loadedPlugins,
393
+ size: 1,
394
+ workingDirectory: project
395
+ });
396
+ return yield* Option.match(Option.fromNullishOr(pool), {
397
+ onNone: () => Effect.as(Effect.void, void 0),
398
+ onSome: (present) => programDigestOf(makeCheckerPoolHandle(present), project)
399
+ });
400
+ }).pipe(Effect.provide(context), Effect.scoped),
401
+ onFalse: () => Effect.as(Effect.void, void 0)
402
+ });
403
+ const projectDiffOf = (path, planRoot, project, diff) => {
404
+ const fromProject = (file) => path.relative(project, path.resolve(planRoot, file)).replace(/\\/g, "/");
405
+ return {
406
+ ...diff,
407
+ hunks: diff.hunks.map((hunk) => ({
408
+ ...hunk,
409
+ file: fromProject(hunk.file)
410
+ })),
411
+ untrackedFiles: diff.untrackedFiles.map(fromProject)
412
+ };
413
+ };
414
+ const stageCliOptionsOf = (since, full) => Option.match(Option.fromUndefinedOr(since), {
415
+ onNone: () => ({ force: full }),
416
+ onSome: (present) => ({
417
+ force: full,
418
+ since: present
419
+ })
420
+ });
421
+ const plannedDiffOf = (path, planDiff, project) => Option.match(planDiff.diff, {
422
+ onNone: () => WholeProject.make({}),
423
+ onSome: (diff) => ChangedSince.make({ diff: projectDiffOf(path, planDiff.root, project, diff) })
424
+ });
425
+ const resolvedSinceOf = (planDiff) => Option.getOrUndefined(Option.map(planDiff.diff, (diff) => diff.ref));
426
+ const subsumedOf = (mutant) => Option.filter(Option.fromUndefinedOr(mutant.subsumption), S.is(Mutant_exports.Subsumed));
427
+ const dominatorIdsOf = (mutants) => new Set(mutants.flatMap((mutant) => Option.match(subsumedOf(mutant), {
428
+ onNone: () => [],
429
+ onSome: (subsumed) => subsumed.dominators
430
+ })));
431
+ const placementKeyOf = (dominatorIds, mutant) => Option.getOrUndefined(Option.orElse(Option.map(subsumedOf(mutant), (subsumed) => subsumed.dominators[0]), () => Option.liftPredicate(mutant.id, (id) => dominatorIds.has(id))));
432
+ const planProject = (request, channel, labelBase, planDiff, directory) => Effect.gen(function* () {
433
+ const fs = yield* FileSystem.FileSystem;
434
+ const path = yield* Path.Path;
435
+ const basePath = channel.environment.basePath;
436
+ const project = yield* fs.realPath(path.resolve(basePath, directory));
437
+ const env = {
438
+ ...channel.environment.host.env,
439
+ basePath: project
440
+ };
441
+ const context = yield* Layer.build(RunEnvironment.layerStage(env, channel.environment.host.events));
442
+ const stageInput = {
443
+ cliOptions: stageCliOptionsOf(resolvedSinceOf(planDiff), request.full),
444
+ targetMutatePatterns: void 0,
445
+ plannedDiff: plannedDiffOf(path, planDiff, project)
446
+ };
447
+ const { prepared, done } = yield* Cell.provideContext(planStageCell, context).run(stageInput);
448
+ const texts = yield* incrementalReportTextsOf({
449
+ basePath: project,
450
+ options: done.options
451
+ });
452
+ const dryRunChoice = yield* dryRunChoiceOf(done, project, texts);
453
+ const coverage = dryRunChoice.prior;
454
+ const testCoverage = Option.match(coverage, {
455
+ onNone: emptyTestCoverage,
456
+ onSome: reusedTestCoverage
457
+ });
458
+ const reportCosts = reportCostsOf(texts);
459
+ const label = labelOf(path, labelBase, project);
460
+ const programDigest = yield* programDigestAtPlanTime({
461
+ texts,
462
+ context,
463
+ options: done.options,
464
+ loadedPlugins: prepared.loadedPlugins,
465
+ project
466
+ });
467
+ const reuse = yield* readIncrementalReuse({
468
+ project: done.project,
469
+ currentMutants: [...done.mutants],
470
+ testCoverage,
471
+ basePath: project,
472
+ force: request.full,
473
+ options: done.options,
474
+ globalTestInputs: Option.map(coverage, (present) => [...present.globalTestInputs]).pipe(Option.getOrElse(() => [])),
475
+ observedModules: Option.getOrUndefined(Option.map(coverage, (present) => present.testFileModules)),
476
+ originalFileOf: (file) => path.resolve(file),
477
+ programDigestOf: Effect.succeed(programDigest)
478
+ });
479
+ const dryRunDecision = Result.getOrElse(requireDryRun(requireDryRunCommandOf({
480
+ options: done.options,
481
+ mutants: [...reuse.mutants, ...reuse.rememberedResults],
482
+ texts,
483
+ kept: dryRunChoice.kept
484
+ })), (neverError) => neverError);
485
+ const dependentIds = HashSet.fromIterable(dependentMutantIdsOf(dryRunDecision));
486
+ const dryRunCostMs = Boolean.match(S.is(DryRunCoverageReused)(dryRunChoice.decision), {
487
+ onTrue: () => 0,
488
+ onFalse: () => Option.getOrElse(Option.map(coverage, (present) => testsTimeOf(present.tests) + present.timeOverheadMs), () => DEFAULT_MUTANT_COST_MS)
489
+ });
490
+ const dominatorIds = dominatorIdsOf(reuse.mutants);
491
+ return {
492
+ label,
493
+ mutants: [...reuse.mutants.map((mutant) => ({
494
+ id: mutant.id,
495
+ costMs: costOf(mutant.id, reportCosts, coverage, testCoverage),
496
+ dependsOnDryRun: HashSet.has(dependentIds, mutant.id),
497
+ ...optionalField("placementKey", placementKeyOf(dominatorIds, mutant))
498
+ })), ...reuse.rememberedResults.map((mutant) => ({
499
+ id: mutant.id,
500
+ costMs: 0,
501
+ dependsOnDryRun: HashSet.has(dependentIds, mutant.id),
502
+ ...optionalField("placementKey", placementKeyOf(dominatorIds, mutant))
503
+ }))],
504
+ files: [...HashSet.fromIterable([...reuse.mutants, ...reuse.rememberedResults].map((mutant) => path.resolve(project, mutant.fileName)))].sort(),
505
+ dryRunCostMs,
506
+ reuse: {
507
+ reused: reuse.rememberedResults.length,
508
+ ran: reuse.mutants.length,
509
+ refused: reuse.refusalCounts,
510
+ ...done.incrementalReportDiscard === void 0 ? {} : { discard: done.incrementalReportDiscard }
511
+ }
512
+ };
513
+ }).pipe(Effect.orDie);
514
+ const planScopeOf = (diff, planned, basePath) => Option.match(diff, {
515
+ onNone: () => Effect.succeed({ _tag: "Unscoped" }),
516
+ onSome: (present) => Effect.gen(function* () {
517
+ const path = yield* Path.Path;
518
+ const git = yield* GitDiff;
519
+ const root = yield* git.toplevel(basePath);
520
+ const files = [...HashSet.fromIterable(planned.flatMap((entry) => entry.files.map((file) => path.relative(root, file).replace(/\\/g, "/"))))].sort();
521
+ const sources = yield* git.sourceDigest({
522
+ cwd: basePath,
523
+ paths: files
524
+ });
525
+ return Match.value(diffScopeDecisionOf(present)).pipe(Match.tag("DiffScoped", () => ({
526
+ _tag: "DiffScoped",
527
+ base: present.base,
528
+ head: present.head,
529
+ sources,
530
+ files
531
+ })), Match.tag("FullScope", (full) => ({
532
+ _tag: "FullScope",
533
+ base: present.base,
534
+ head: present.head,
535
+ sources,
536
+ files,
537
+ reason: full.reason
538
+ })), Match.exhaustive);
539
+ })
540
+ });
541
+ const assemblePlan = (request, scope, planned, dryRunCosts) => Effect.map(PlanShardsCommand.makeEffect({
542
+ targetSeconds: request.targetSeconds,
543
+ maxShards: request.maxShards,
544
+ mutants: planned.map((mutant) => ({ ...mutant })),
545
+ dryRunCosts
546
+ }).pipe(Effect.mapError((issue) => PlanShardsRefused.make({ detail: new S.SchemaError(issue).message }))), (command) => shardPlanOf(request, scope, Result.getOrElse(planShards(command), (neverError) => neverError)));
547
+ const shardPlanOf = (request, scope, shards) => ({
548
+ version: ShardPlanVersion.literal,
549
+ scope,
550
+ targetSeconds: request.targetSeconds,
551
+ shards: shards.map((shard) => ({
552
+ index: shard.index,
553
+ count: shard.count,
554
+ predictedSeconds: shard.predictedSeconds,
555
+ projects: shard.projects.map((entry) => ({
556
+ project: entry.project,
557
+ mutants: [...entry.mutants]
558
+ }))
559
+ })),
560
+ matrix: { include: shards.map((shard) => ({
561
+ shard: `${shard.index}/${shard.count}`,
562
+ predictedSeconds: shard.predictedSeconds
563
+ })) }
564
+ });
565
+ const writePlan = (request, channel, plan) => Effect.gen(function* () {
566
+ const fs = yield* FileSystem.FileSystem;
567
+ const path = yield* Path.Path;
568
+ const text = yield* Effect.orDie(S.encodeEffect(S.fromJsonString(ShardPlan, { space: 2 }))(plan));
569
+ return yield* Option.match(Option.fromUndefinedOr(request.out), {
570
+ onNone: () => Effect.sync(() => channel.environment.console.log(text)),
571
+ onSome: (out) => Effect.gen(function* () {
572
+ const target = path.resolve(channel.environment.basePath, out);
573
+ yield* fs.makeDirectory(path.dirname(target), { recursive: true });
574
+ yield* fs.writeFileString(target, text);
575
+ })
576
+ });
577
+ }).pipe(Effect.orDie);
578
+ const labelBaseOf = (path, basePath, out) => Option.getOrElse(Option.map(Option.fromUndefinedOr(out), (present) => path.dirname(path.resolve(basePath, present))), () => basePath);
579
+ const planReuseRowOf = (entry) => RunEvent_exports$1.PlanProjectReuse.make({
580
+ project: entry.label,
581
+ reused: entry.reuse.reused,
582
+ ran: entry.reuse.ran,
583
+ refused: entry.reuse.refused,
584
+ ...Option.match(Option.fromUndefinedOr(entry.reuse.discard), {
585
+ onNone: () => ({}),
586
+ onSome: (discard) => ({ discard: RunEvent_exports$1.PlanReportDiscard.make({
587
+ reason: discard.reason,
588
+ expected: discard.expected,
589
+ ...Option.match(Option.fromUndefinedOr(discard.actual), {
590
+ onNone: () => ({}),
591
+ onSome: (actual) => ({ actual })
592
+ })
593
+ }) })
594
+ })
595
+ });
596
+ const planDiffOf = (since, basePath) => Effect.gen(function* () {
597
+ const fs = yield* FileSystem.FileSystem;
598
+ const root = yield* Effect.orDie(fs.realPath(basePath));
599
+ return {
600
+ root,
601
+ diff: yield* Option.match(Option.fromUndefinedOr(since), {
602
+ onNone: () => Effect.succeedNone,
603
+ onSome: (ref) => Effect.asSome(Effect.flatMap(GitDiff, (git) => git.changedSince({
604
+ cwd: root,
605
+ ref
606
+ })))
607
+ })
608
+ };
609
+ });
610
+ const rootOptionsOf = (request, channel) => Effect.gen(function* () {
611
+ const env = {
612
+ ...channel.environment.host.env,
613
+ basePath: channel.environment.basePath
614
+ };
615
+ const context = yield* Layer.build(RunEnvironment.layerStage(env, channel.environment.host.events));
616
+ return (yield* Cell.provideContext(loadConfigCell, context).run({
617
+ cliOptions: stageCliOptionsOf(request.since, request.full),
618
+ targetMutatePatterns: void 0
619
+ })).options;
620
+ }).pipe(Effect.orDie);
621
+ const realProjectOf = (fs, path, basePath, directory) => {
622
+ const resolved = path.resolve(basePath, directory);
623
+ return fs.realPath(resolved).pipe(Effect.orElseSucceed(() => resolved));
624
+ };
625
+ const distinctProjectsOf = (basePath, projects) => Effect.gen(function* () {
626
+ const fs = yield* FileSystem.FileSystem;
627
+ const path = yield* Path.Path;
628
+ const keyed = yield* Effect.forEach(Option.getOrElse(Option.fromUndefinedOr(projects), () => []), (directory) => Effect.map(realProjectOf(fs, path, basePath, directory), (real) => ({
629
+ directory,
630
+ real
631
+ })));
632
+ return Arr.dedupeWith(keyed, (left, right) => left.real === right.real).map((entry) => entry.directory);
633
+ });
634
+ const planRequest = ({ request, channel }) => Effect.gen(function* () {
635
+ const path = yield* Path.Path;
636
+ const labelBase = labelBaseOf(path, channel.environment.basePath, request.out);
637
+ const rootOptions = yield* rootOptionsOf(request, channel);
638
+ const resolvedSince = Option.getOrUndefined(Option.orElse(Option.fromUndefinedOr(request.since), () => Option.fromUndefinedOr(rootOptions.since)));
639
+ const planDiff = yield* planDiffOf(resolvedSince, channel.environment.basePath);
640
+ const planned = yield* forEachProjectDirectory(yield* distinctProjectsOf(channel.environment.basePath, request.projects), (directory) => planProject(request, channel, labelBase, planDiff, directory));
641
+ const scheduled = planned.flatMap((entry) => entry.mutants.map((mutant) => ({
642
+ project: entry.label,
643
+ ...mutant
644
+ })));
645
+ const dryRunCosts = Object.fromEntries(planned.map((entry) => [entry.label, entry.dryRunCostMs]));
646
+ const scope = yield* planScopeOf(planDiff.diff, planned, channel.environment.basePath);
647
+ const plan = yield* assemblePlan(request, scope, scheduled, dryRunCosts);
648
+ yield* Queue.offer(channel.environment.host.events, RunEvent_exports$1.PlanKnown.make({
649
+ total: scheduled.length,
650
+ shardPlan: plan,
651
+ projects: planned.map(planReuseRowOf)
652
+ }));
653
+ yield* writePlan(request, channel, plan).pipe(Effect.orDie);
654
+ }).pipe(Effect.scoped);
655
+ //#endregion
75
656
  //#region src/Engine/mod.ts
76
657
  var Engine_exports = /* @__PURE__ */ __exportAll({
77
658
  IdGenerator: () => IdGenerator,
78
659
  IncrementalReportSchema: () => IncrementalReportSchema,
660
+ PlanShardsRefused: () => PlanShardsRefused,
79
661
  RunEnvironment: () => RunEnvironment,
80
662
  StageError: () => StageError,
81
663
  StrykerError: () => StrykerError,
82
664
  mutationTestCell: () => mutationTestCell,
83
665
  nodePlatformLayer: () => nodePlatformLayer,
666
+ planRequest: () => planRequest,
84
667
  strykerCell: () => strykerCell
85
668
  });
86
669
  //#endregion
@@ -278,7 +861,8 @@ const priorMutantsOf = (text, basePath) => Option.match(S.decodeOption(S.fromJso
278
861
  mutatorName: Mutant_exports.MutatorName.make(mutant.mutatorName),
279
862
  replacement: mutant.replacement ?? mutant.mutatorName,
280
863
  location: mutant.location,
281
- relativeFileName
864
+ relativeFileName,
865
+ probeEligibility: Mutant_exports.Unprobed.make({ reason: "not-decided" })
282
866
  }));
283
867
  })
284
868
  });
@@ -343,7 +927,9 @@ const engineDependencies = [
343
927
  Path.Path,
344
928
  Stdio.Stdio,
345
929
  ChildProcessSpawner.ChildProcessSpawner,
930
+ EmptyDirectory,
346
931
  GitDiff,
932
+ SourceParser,
347
933
  WorkerLauncher
348
934
  ];
349
935
  const ListSurvivors = Tool.make("list_survivors", {
@@ -379,6 +965,25 @@ const ReportUsefulness = Tool.make("report_usefulness", {
379
965
  });
380
966
  const mcpToolkit = Toolkit.make(ListSurvivors, ShowMutant, RerunMutant, ReportUsefulness);
381
967
  //#endregion
968
+ //#region src/Mcp/rerun-stage.handle.ts
969
+ const TypeId$1 = Symbol.for("~systemfsoftware/stryker-js/Mcp/RerunStage");
970
+ const RerunStageHandle = Handle.make()(TypeId$1);
971
+ RerunStageHandle.is;
972
+ const makeRerunStageHandle = (stage) => RerunStageHandle.make({}, stage);
973
+ const run = dual(3, (handle, cell, input) => Cell.provideContext(cell, RerunStageHandle.slot(handle)).run(input));
974
+ //#endregion
975
+ //#region src/Mcp/rerun-stage.blueprint.ts
976
+ const TypeId = Symbol.for("~systemfsoftware/stryker-js/Mcp/RerunStageBlueprint");
977
+ const acquire = Effect.fnUntraced(function* (spec) {
978
+ const stage = yield* Layer.build(Layer.merge(RunEnvironment.layerStage(spec.environment, spec.events), MachineConsole.layerCapture.pipe(Layer.provide(MachineConsole.layer))));
979
+ return makeRerunStageHandle(stage);
980
+ });
981
+ const RerunStages = Blueprint.make()(TypeId).steps({
982
+ steps: {},
983
+ targets: { scoped: acquire }
984
+ });
985
+ const scoped = (spec) => RerunStages.of(spec).scoped;
986
+ //#endregion
382
987
  //#region src/Mcp/mcp-server.cell.ts
383
988
  const MCP_RUN_ID = RunEvent_exports$1.RunId.make("01ARZ3NDEKTSV4RRFFQ69G5FAM");
384
989
  const REPRODUCERS_FILE = "reports/mutation/reproducers.json";
@@ -431,11 +1036,13 @@ const runRestricted = (basePath, options) => Effect.gen(function* () {
431
1036
  builtinReporters: {},
432
1037
  allowConsoleColors: false
433
1038
  };
434
- const runLayer = Layer.merge(RunEnvironment.stage(environment, queue), MachineConsole.captureLayer.pipe(Layer.provide(MachineConsole.layer)));
435
- return yield* mutationTestCell.run({
1039
+ return yield* Effect.scoped(Effect.flatMap(scoped({
1040
+ environment,
1041
+ events: queue
1042
+ }), run(mutationTestCell, {
436
1043
  cliOptions: options,
437
1044
  targetMutatePatterns: void 0
438
- }).pipe(Effect.provide(runLayer), Effect.scoped, Effect.orDie);
1045
+ }))).pipe(Effect.orDie);
439
1046
  });
440
1047
  const NO_RESULTS = {
441
1048
  results: [],
@@ -485,12 +1092,14 @@ const handlers = (basePath) => mcpToolkit.toLayer({
485
1092
  reason: reason ?? null
486
1093
  })
487
1094
  });
488
- const mcpServerLayer = ({ basePath }) => Layer.merge(McpServer.layerStdio({
1095
+ const provideEngineToRequests = McpServer.middleware()(Effect.map(Effect.context(), (context) => (effect) => Effect.provideContext(effect, context)));
1096
+ const mcpServerLayer = ({ basePath }) => McpServer.layerStdio({
489
1097
  name: "stryker",
490
1098
  version: StrykerPackage.version,
491
1099
  instructions: MCP_SERVER_INSTRUCTIONS,
492
- protocols: [McpProtocol.v2025_06_18]
493
- }), McpServer.toolkit(mcpToolkit)).pipe(Layer.provide(handlers(basePath)), Layer.provide(MachineConsole.layer));
1100
+ protocols: [McpProtocol.v2025_06_18],
1101
+ registrations: McpServer.toolkit(mcpToolkit).pipe(Layer.provide(provideEngineToRequests.layer), Layer.provide(handlers(basePath)))
1102
+ }).pipe(Layer.provide(MachineConsole.layer));
494
1103
  //#endregion
495
1104
  //#region src/Mcp/mod.ts
496
1105
  var Mcp_exports = /* @__PURE__ */ __exportAll({
@@ -520,7 +1129,6 @@ var Plugin_exports = /* @__PURE__ */ __exportAll({
520
1129
  var RunEvent_exports = /* @__PURE__ */ __exportAll({
521
1130
  MetricsResultFromReport: () => MetricsResultFromReport,
522
1131
  RunEventDrain: () => RunEventDrain,
523
- RunEventDrainLive: () => RunEventDrainLive,
524
1132
  RunEvents: () => RunEvents,
525
1133
  RunIdentity: () => RunIdentity,
526
1134
  VerdictEnvelope: () => VerdictEnvelope,
@@ -964,7 +1572,7 @@ const withEngine = (consume, use) => Effect.gen(function* () {
964
1572
  const events = yield* Queue.bounded(RunEvent_exports$1.RunEvent.QUEUE_BOUND);
965
1573
  const consumer = yield* Stream.fromQueue(events).pipe(Stream.runForEach(consume), Effect.forkChild);
966
1574
  return yield* Effect.scoped(Effect.gen(function* () {
967
- const context = yield* Layer.build(RunEnvironment.stage(env, events));
1575
+ const context = yield* Layer.build(RunEnvironment.layerStage(env, events));
968
1576
  return yield* use({
969
1577
  env,
970
1578
  context
@@ -1196,4 +1804,4 @@ var Worker_exports = /* @__PURE__ */ __exportAll({
1196
1804
  makeWorkerClient: () => makeWorkerClient
1197
1805
  });
1198
1806
  //#endregion
1199
- export { Checker_exports as Checker, Configuration_exports as Configuration, Engine_exports as Engine, git_diff_service_exports as GitDiff, git_diff_schema_exports as GitDiffSchema, import_closure_cell_exports as ImportClosure, Mcp_exports as Mcp, Plugin_exports as Plugin, RunEvent_exports as RunEvent, Serve_exports as Serve, Worker_exports as Worker };
1807
+ export { Checker_exports as Checker, Configuration_exports as Configuration, Engine_exports as Engine, git_diff_service_exports as GitDiff, git_diff_schema_exports as GitDiffSchema, import_closure_cell_exports as ImportClosure, Mcp_exports as Mcp, Plugin_exports as Plugin, RunEvent_exports as RunEvent, Serve_exports as Serve, source_parser_service_exports as SourceParser, Worker_exports as Worker };