@savvy-web/silk 3.2.2 → 3.2.4

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.
@@ -172,27 +172,6 @@ const SilkChangesetConfigFile = effect.Schema.Struct({
172
172
  ...ChangesetConfigFile.fields,
173
173
  _isSilk: effect.Schema.Boolean.pipe(effect.Schema.withDecodingDefaultType(effect.Effect.succeed(true)), effect.Schema.withConstructorDefault(effect.Effect.succeed(true)))
174
174
  });
175
- /**
176
- * Versioning strategy classification for a workspace.
177
- *
178
- * @remarks
179
- * - `"single"` — one publishable package; a single version tag is used.
180
- * - `"fixed-group"` — all publishable packages are in the same changesets fixed group.
181
- * - `"independent"` — multiple publishable packages with independent version bumps.
182
- *
183
- * @since 0.1.0
184
- * @public
185
- */
186
- const VersioningStrategyType = effect.Schema.Literals([
187
- "single",
188
- "fixed-group",
189
- "independent"
190
- ]);
191
- effect.Schema.Struct({
192
- type: VersioningStrategyType,
193
- fixedGroups: effect.Schema.Array(effect.Schema.Array(effect.Schema.String)),
194
- publishablePackages: effect.Schema.Array(effect.Schema.String)
195
- });
196
175
  //#endregion
197
176
  //#region ../silk-effects/dist/dev/pkg/services/ChangesetConfigReader.js
198
177
  /**
@@ -2353,7 +2332,7 @@ var GlobSet = class GlobSet extends effect.Schema.Class("GlobSet")(effect.Schema
2353
2332
  }
2354
2333
  };
2355
2334
  //#endregion
2356
- //#region ../../node_modules/.pnpm/@effected+lockfiles@0.1.10_@effected+jsonc@0.5.1_effect@4.0.0-beta.101__@effected+npm@0_baf93f2c33d0504f713f685ac5710e50/node_modules/@effected/lockfiles/BunExtension.js
2335
+ //#region ../../node_modules/.pnpm/@effected+lockfiles@0.2.1_@effected+jsonc@0.5.1_effect@4.0.0-beta.101__@effected+npm@0._44d8f67a8ab767df898f59f0e01343be/node_modules/@effected/lockfiles/BunExtension.js
2357
2336
  /**
2358
2337
  * Extension data specific to bun lockfiles, attached to `Lockfile.extension`
2359
2338
  * when the format is `"bun"`.
@@ -2374,7 +2353,7 @@ var BunExtension = class extends effect.Schema.Class("BunExtension")({
2374
2353
  trustedDependencies: effect.Schema.optionalKey(effect.Schema.Array(effect.Schema.String))
2375
2354
  }) {};
2376
2355
  //#endregion
2377
- //#region ../../node_modules/.pnpm/@effected+npm@0.3.1_@effected+semver@0.2.1_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/npm/CatalogResolver.js
2356
+ //#region ../../node_modules/.pnpm/@effected+npm@0.5.0_@effected+semver@0.2.1_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/npm/CatalogResolver.js
2378
2357
  /**
2379
2358
  * Contract for resolving pnpm `catalog:` dependency specifiers to concrete
2380
2359
  * version ranges.
@@ -2420,7 +2399,7 @@ var CatalogResolver = class CatalogResolver extends effect.Context.Service()("@e
2420
2399
  static noop = effect.Layer.succeed(CatalogResolver, { rangeOf: () => effect.Effect.succeed(effect.Option.none()) });
2421
2400
  };
2422
2401
  //#endregion
2423
- //#region ../../node_modules/.pnpm/@effected+npm@0.3.1_@effected+semver@0.2.1_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/npm/WorkspaceResolver.js
2402
+ //#region ../../node_modules/.pnpm/@effected+npm@0.5.0_@effected+semver@0.2.1_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/npm/WorkspaceResolver.js
2424
2403
  /**
2425
2404
  * Raised when a `catalog:` or `workspace:` specifier cannot be resolved
2426
2405
  * because the resolution mechanism itself failed — not for an ordinary
@@ -2481,7 +2460,7 @@ var WorkspaceResolver = class WorkspaceResolver extends effect.Context.Service()
2481
2460
  static noop = effect.Layer.succeed(WorkspaceResolver, { versionOf: () => effect.Effect.succeed(effect.Option.none()) });
2482
2461
  };
2483
2462
  //#endregion
2484
- //#region ../../node_modules/.pnpm/@effected+npm@0.3.1_@effected+semver@0.2.1_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/npm/CatalogAssemblyError.js
2463
+ //#region ../../node_modules/.pnpm/@effected+npm@0.5.0_@effected+semver@0.2.1_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/npm/CatalogAssemblyError.js
2485
2464
  /**
2486
2465
  * Raised when a workspace's catalogs cannot be assembled — a `pnpm-workspace.yaml`
2487
2466
  * that is unreadable or not valid YAML, a root `package.json` `workspaces` field
@@ -2525,7 +2504,7 @@ var CatalogAssemblyError = class extends effect.Schema.TaggedErrorClass()("Catal
2525
2504
  }
2526
2505
  };
2527
2506
  //#endregion
2528
- //#region ../../node_modules/.pnpm/@effected+npm@0.3.1_@effected+semver@0.2.1_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/npm/DependencySection.js
2507
+ //#region ../../node_modules/.pnpm/@effected+npm@0.5.0_@effected+semver@0.2.1_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/npm/DependencySection.js
2529
2508
  /**
2530
2509
  * The short dependency kind: which dependency map an entry came from, named the
2531
2510
  * way consumers branch on it.
@@ -4026,7 +4005,7 @@ const isComparatorSetSubset = (sub, sup) => {
4026
4005
  return true;
4027
4006
  };
4028
4007
  //#endregion
4029
- //#region ../../node_modules/.pnpm/@effected+npm@0.3.1_@effected+semver@0.2.1_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/npm/DependencySpecifier.js
4008
+ //#region ../../node_modules/.pnpm/@effected+npm@0.5.0_@effected+semver@0.2.1_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/npm/DependencySpecifier.js
4030
4009
  /**
4031
4010
  * Indicates that a string could not be parsed as a valid dependency specifier.
4032
4011
  *
@@ -4233,7 +4212,7 @@ const DependencySpecifier = Object.assign(brandedSpecifier, {
4233
4212
  FromString: fromString
4234
4213
  });
4235
4214
  //#endregion
4236
- //#region ../../node_modules/.pnpm/@effected+npm@0.3.1_@effected+semver@0.2.1_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/npm/IntegrityHash.js
4215
+ //#region ../../node_modules/.pnpm/@effected+npm@0.5.0_@effected+semver@0.2.1_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/npm/IntegrityHash.js
4237
4216
  const SRI_RE = /^(sha1|sha256|sha384|sha512)-[A-Za-z0-9+/]+={0,2}$/;
4238
4217
  const COREPACK_RE = /^(sha1|sha256|sha384|sha512)\.[0-9a-f]+$/;
4239
4218
  const YARN_RE = /^[0-9]+(c[0-9]+)?\/[0-9a-f]+$/;
@@ -4285,8 +4264,166 @@ const IntegrityHash = Object.assign(brandedIntegrity, {
4285
4264
  algorithmOf,
4286
4265
  decode: decode$2
4287
4266
  });
4267
+ effect.Schema.Literals([
4268
+ "npm",
4269
+ "pnpm",
4270
+ "yarn",
4271
+ "bun"
4272
+ ]);
4273
+ /** The argv prefixes for each launcher. The one place this knowledge lives. */
4274
+ const PREFIXES = {
4275
+ npm: {
4276
+ prefix: [
4277
+ "npx",
4278
+ "--no",
4279
+ "--"
4280
+ ],
4281
+ dlxPrefix: ["npx"]
4282
+ },
4283
+ pnpm: {
4284
+ prefix: ["pnpm", "exec"],
4285
+ dlxPrefix: ["pnpm", "dlx"]
4286
+ },
4287
+ yarn: {
4288
+ prefix: ["yarn", "exec"],
4289
+ dlxPrefix: ["yarn", "dlx"]
4290
+ },
4291
+ bun: {
4292
+ prefix: [
4293
+ "bun",
4294
+ "x",
4295
+ "--no-install"
4296
+ ],
4297
+ dlxPrefix: ["bun", "x"]
4298
+ }
4299
+ };
4300
+ /**
4301
+ * How to run a project-local binary here.
4302
+ *
4303
+ * @remarks
4304
+ * This is the whole of what tool discovery needs from a workspace: an argv
4305
+ * prefix and a directory to run it in. It deliberately carries no workspace
4306
+ * root, no manifest and no package-manager semantics — `label` is for
4307
+ * reporting only, and nothing in this package branches on it.
4308
+ *
4309
+ * @public
4310
+ */
4311
+ var ExecContext = class extends effect.Schema.Class("ExecContext")({
4312
+ /** Human label of the launcher, e.g. `"pnpm"`. Reporting only. */
4313
+ label: effect.Schema.String,
4314
+ /** argv prefix that runs a project-local binary, e.g. `["pnpm", "exec"]`. */
4315
+ prefix: effect.Schema.Array(effect.Schema.String),
4316
+ /** argv prefix that fetch-and-runs a package binary, e.g. `["pnpm", "dlx"]`. */
4317
+ dlxPrefix: effect.Schema.Array(effect.Schema.String),
4318
+ /** Directory the prefix must run in. Omitted means "wherever the caller is". */
4319
+ directory: effect.Schema.optionalKey(effect.Schema.String)
4320
+ }) {
4321
+ /** Prefixes `command` with `prefix` and applies `directory`, returning a core `Command`. */
4322
+ apply(command) {
4323
+ return this.withPrefix(command, this.prefix);
4324
+ }
4325
+ /** As {@link ExecContext.apply}, using `dlxPrefix` — the fetch-and-run launcher. */
4326
+ applyDlx(command) {
4327
+ return this.withPrefix(command, this.dlxPrefix);
4328
+ }
4329
+ /**
4330
+ * Core's `prefix` and `setCwd` both return NEW commands, so the caller's
4331
+ * value is never mutated.
4332
+ */
4333
+ withPrefix(command, prefix) {
4334
+ const [head, ...rest] = prefix;
4335
+ const prefixed = head === void 0 ? command : effect_unstable_process.ChildProcess.prefix(command, head, rest);
4336
+ return this.directory === void 0 ? prefixed : effect_unstable_process.ChildProcess.setCwd(prefixed, this.directory);
4337
+ }
4338
+ };
4339
+ /**
4340
+ * The project-local execution context could not be determined.
4341
+ *
4342
+ * @remarks
4343
+ * A *mechanism* failure — an unreadable manifest, a detection error. "There is
4344
+ * no project-local way to run tools here" is `Option.none()`, never this error:
4345
+ * the same `None`-is-success convention `@effected/npm`'s resolver contracts
4346
+ * use, so an implementation never has to decide whether absence is exceptional.
4347
+ *
4348
+ * @public
4349
+ */
4350
+ var LocalExecError = class extends effect.Schema.TaggedErrorClass()("LocalExecError", {
4351
+ /** The directory whose context could not be determined, when one is known. */
4352
+ directory: effect.Schema.optionalKey(effect.Schema.String),
4353
+ /** The underlying failure. */
4354
+ cause: effect.Schema.optionalKey(effect.Schema.Defect())
4355
+ }) {
4356
+ get message() {
4357
+ return this.directory === void 0 ? "Could not determine the project-local execution context" : `Could not determine the project-local execution context for ${this.directory}`;
4358
+ }
4359
+ };
4360
+ /**
4361
+ * Contract: how to run a project-local binary in this project.
4362
+ *
4363
+ * @remarks
4364
+ * **This is an inverted contract.** Tool discovery needs package-manager
4365
+ * detection and workspace-root resolution, both of which live in the
4366
+ * integrated-tier `@effected/workspaces`. Depending on it directly would make
4367
+ * this package integrated too — and, through the planned `@effected/npm` edge,
4368
+ * would drag `npm`, `lockfiles` and `package-json` up a tier with it. So this
4369
+ * package declares the narrow contract and `@effected/workspaces` ships the
4370
+ * layer that implements it, exactly as `@effected/npm` owns `CatalogResolver`
4371
+ * and workspaces implements that.
4372
+ *
4373
+ * A consumer with no monorepo never needs that implementation:
4374
+ * {@link LocalExec.layerNone} (global-only) and {@link LocalExec.layerFor}
4375
+ * (a known package manager) are one-liners.
4376
+ *
4377
+ * @public
4378
+ */
4379
+ var LocalExec = class LocalExec extends effect.Context.Service()("@effected/commands/LocalExec") {
4380
+ /** The exec and dlx argv prefixes for a launcher — the single home of that knowledge. */
4381
+ static prefixes = (launcher) => PREFIXES[launcher];
4382
+ /**
4383
+ * No project-local execution context: every tool resolves globally.
4384
+ *
4385
+ * @remarks
4386
+ * The right wiring for a GitHub Action or any single-package checkout, and
4387
+ * the reason such a consumer never installs `@effected/workspaces`.
4388
+ */
4389
+ static layerNone = effect.Layer.succeed(this, { context: effect.Effect.succeed(effect.Option.none()) });
4390
+ /** A context for a known package manager, from the static prefix table. */
4391
+ static layerFor = (launcher, options) => {
4392
+ const { prefix, dlxPrefix } = PREFIXES[launcher];
4393
+ return LocalExec.layerContext(ExecContext.make({
4394
+ label: launcher,
4395
+ prefix,
4396
+ dlxPrefix,
4397
+ ...options?.directory === void 0 ? {} : { directory: options.directory }
4398
+ }));
4399
+ };
4400
+ /** A caller-supplied context, answered verbatim. */
4401
+ static layerContext = (context) => effect.Layer.succeed(LocalExec, { context: effect.Effect.succeed(effect.Option.some(context)) });
4402
+ /**
4403
+ * An in-memory test double.
4404
+ *
4405
+ * @remarks
4406
+ * Unlike most `makeTest` doubles in the kit, the unstubbed default here is
4407
+ * **honest rather than loud**: `Option.none()` is a real, correct answer
4408
+ * ("no project-local context"), so a test that does not care about local
4409
+ * resolution gets the global-only behavior instead of a defect.
4410
+ */
4411
+ static makeTest = (overrides = {}) => ({
4412
+ context: effect.Effect.succeed(effect.Option.none()),
4413
+ ...overrides
4414
+ });
4415
+ /**
4416
+ * {@link LocalExec.makeTest} behind `Layer.succeed`.
4417
+ *
4418
+ * @remarks
4419
+ * A parameterized layer factory mints a fresh reference per call and layers
4420
+ * memoize by reference — bind the result to a `const` rather than calling it
4421
+ * at each composition site.
4422
+ */
4423
+ static layerTest = (overrides = {}) => effect.Layer.succeed(LocalExec, LocalExec.makeTest(overrides));
4424
+ };
4288
4425
  //#endregion
4289
- //#region ../../node_modules/.pnpm/@effected+npm@0.3.1_@effected+semver@0.2.1_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/npm/ReleaseAgeGate.js
4426
+ //#region ../../node_modules/.pnpm/@effected+npm@0.5.0_@effected+semver@0.2.1_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/npm/ReleaseAgeGate.js
4290
4427
  const MS_PER_MINUTE = 6e4;
4291
4428
  /**
4292
4429
  * A source's partial contribution to a {@link ReleaseAgeGate}: the effective
@@ -4374,7 +4511,9 @@ var ReleaseAgeGate = class ReleaseAgeGate extends effect.Schema.Class("ReleaseAg
4374
4511
  * Combine partial contributions from multiple sources into one effective
4375
4512
  * gate: **strictest age wins** (the maximum of the contributed ages,
4376
4513
  * clamped to be non-negative) and the exclude sets **union** (deduplicated,
4377
- * insertion order preserved). A contribution's absent field adds nothing; a
4514
+ * lexicographically sorted a canonical wire form, so the combined gate is
4515
+ * deterministic regardless of the order contributions arrive in). A
4516
+ * contribution's absent field adds nothing; a
4378
4517
  * negative or non-finite contributed age is ignored by the clamp. With no
4379
4518
  * contributions (or only empty ones) the result is the inert zero gate
4380
4519
  * (`ageMinutes: 0`, `exclude: []`).
@@ -4388,7 +4527,7 @@ var ReleaseAgeGate = class ReleaseAgeGate extends effect.Schema.Class("ReleaseAg
4388
4527
  static combine(...contributions) {
4389
4528
  const ages = contributions.map((contribution) => contribution.ageMinutes).filter((age) => typeof age === "number" && Number.isFinite(age));
4390
4529
  const ageMinutes = ages.length > 0 ? Math.max(0, ...ages) : 0;
4391
- const exclude = [...new Set(contributions.flatMap((contribution) => contribution.exclude ?? []))];
4530
+ const exclude = [...new Set(contributions.flatMap((contribution) => contribution.exclude ?? []))].sort();
4392
4531
  return ReleaseAgeGate.make({
4393
4532
  ageMinutes,
4394
4533
  exclude
@@ -4454,7 +4593,7 @@ var ReleaseAgeGate = class ReleaseAgeGate extends effect.Schema.Class("ReleaseAg
4454
4593
  }
4455
4594
  };
4456
4595
  //#endregion
4457
- //#region ../../node_modules/.pnpm/@effected+lockfiles@0.1.10_@effected+jsonc@0.5.1_effect@4.0.0-beta.101__@effected+npm@0_baf93f2c33d0504f713f685ac5710e50/node_modules/@effected/lockfiles/ImporterDependency.js
4596
+ //#region ../../node_modules/.pnpm/@effected+lockfiles@0.2.1_@effected+jsonc@0.5.1_effect@4.0.0-beta.101__@effected+npm@0._44d8f67a8ab767df898f59f0e01343be/node_modules/@effected/lockfiles/ImporterDependency.js
4458
4597
  /**
4459
4598
  * One declared dependency of one workspace importer, as the lockfile records it.
4460
4599
  *
@@ -4465,11 +4604,20 @@ var ReleaseAgeGate = class ReleaseAgeGate extends effect.Schema.Class("ReleaseAg
4465
4604
  * `ClassifiedSpecifier` (`catalog:` / `workspace:` / range / dist-tag / raw),
4466
4605
  * while encoding round-trips the **exact original string byte-for-byte** — the
4467
4606
  * guarantee a before/after lockfile diff relies on.
4468
- * - `version` — the concrete resolved version, **populated by pnpm only**. pnpm
4469
- * records `{ specifier, version }` per importer dependency; bun and npm record
4470
- * resolved versions on their package entries instead, so for those formats
4471
- * `version` is absent and a consumer joins by `name` against
4472
- * `Lockfile.packages`.
4607
+ * - `version` — the concrete resolved version, **populated by pnpm only**:
4608
+ * comparable across refs and printable. pnpm records `{ specifier, version }`
4609
+ * per importer dependency, and the parser splits pnpm's peer-disambiguation
4610
+ * suffix off into `peerSuffix`, so `version` is always the plain version or
4611
+ * a non-registry resolution (`link:../utils`, `file:...`), passed through
4612
+ * verbatim. bun and npm record resolved versions on their package entries
4613
+ * instead, so for those formats `version` is absent and a consumer joins by
4614
+ * `name` against `Lockfile.packages`.
4615
+ * - `peerSuffix` — pnpm's peer-disambiguation context: the raw parenthesized
4616
+ * chain the lockfile recorded after the version, e.g.
4617
+ * `(effect@4.0.0-beta.101)(ioredis@5.11.1(supports-color@8.1.1))`. Present
4618
+ * only when the lockfile recorded one — never for suffix-free pnpm entries,
4619
+ * and never for the other formats, which do not record peer context per
4620
+ * importer dependency.
4473
4621
  * - `depType` — which dependency map declared it, spelled with `@effected/npm`'s
4474
4622
  * kit-wide `DependencyField` vocabulary.
4475
4623
  *
@@ -4479,10 +4627,11 @@ var ImporterDependency = class extends effect.Schema.Class("ImporterDependency")
4479
4627
  name: effect.Schema.NonEmptyString,
4480
4628
  specifier: DependencySpecifier.FromString,
4481
4629
  version: effect.Schema.optionalKey(effect.Schema.String),
4630
+ peerSuffix: effect.Schema.optionalKey(effect.Schema.String),
4482
4631
  depType: DependencyField
4483
4632
  }) {};
4484
4633
  //#endregion
4485
- //#region ../../node_modules/.pnpm/@effected+lockfiles@0.1.10_@effected+jsonc@0.5.1_effect@4.0.0-beta.101__@effected+npm@0_baf93f2c33d0504f713f685ac5710e50/node_modules/@effected/lockfiles/LockfileImporter.js
4634
+ //#region ../../node_modules/.pnpm/@effected+lockfiles@0.2.1_@effected+jsonc@0.5.1_effect@4.0.0-beta.101__@effected+npm@0._44d8f67a8ab767df898f59f0e01343be/node_modules/@effected/lockfiles/LockfileImporter.js
4486
4635
  /**
4487
4636
  * One workspace importer's declared dependencies, as the lockfile records them.
4488
4637
  *
@@ -4506,7 +4655,7 @@ var LockfileImporter = class extends effect.Schema.Class("LockfileImporter")({
4506
4655
  dependencies: effect.Schema.Array(ImporterDependency)
4507
4656
  }) {};
4508
4657
  //#endregion
4509
- //#region ../../node_modules/.pnpm/@effected+lockfiles@0.1.10_@effected+jsonc@0.5.1_effect@4.0.0-beta.101__@effected+npm@0_baf93f2c33d0504f713f685ac5710e50/node_modules/@effected/lockfiles/ResolvedPackage.js
4658
+ //#region ../../node_modules/.pnpm/@effected+lockfiles@0.2.1_@effected+jsonc@0.5.1_effect@4.0.0-beta.101__@effected+npm@0._44d8f67a8ab767df898f59f0e01343be/node_modules/@effected/lockfiles/ResolvedPackage.js
4510
4659
  const EMPTY_DEPENDENCIES = {};
4511
4660
  /**
4512
4661
  * A package resolved from a lockfile.
@@ -4541,7 +4690,7 @@ var ResolvedPackage = class extends effect.Schema.Class("ResolvedPackage")({
4541
4690
  dependencies: effect.Schema.Record(effect.Schema.String, effect.Schema.String).pipe(effect.Schema.withDecodingDefaultKey(effect.Effect.succeed(EMPTY_DEPENDENCIES)), effect.Schema.withConstructorDefault(effect.Effect.succeed(EMPTY_DEPENDENCIES)))
4542
4691
  }) {};
4543
4692
  //#endregion
4544
- //#region ../../node_modules/.pnpm/@effected+lockfiles@0.1.10_@effected+jsonc@0.5.1_effect@4.0.0-beta.101__@effected+npm@0_baf93f2c33d0504f713f685ac5710e50/node_modules/@effected/lockfiles/WorkspaceDependency.js
4693
+ //#region ../../node_modules/.pnpm/@effected+lockfiles@0.2.1_@effected+jsonc@0.5.1_effect@4.0.0-beta.101__@effected+npm@0._44d8f67a8ab767df898f59f0e01343be/node_modules/@effected/lockfiles/WorkspaceDependency.js
4545
4694
  /**
4546
4695
  * A directed dependency edge between two workspace packages as recorded in
4547
4696
  * the lockfile.
@@ -4563,7 +4712,7 @@ var WorkspaceDependency = class extends effect.Schema.Class("WorkspaceDependency
4563
4712
  constraint: effect.Schema.String
4564
4713
  }) {};
4565
4714
  //#endregion
4566
- //#region ../../node_modules/.pnpm/@effected+lockfiles@0.1.10_@effected+jsonc@0.5.1_effect@4.0.0-beta.101__@effected+npm@0_baf93f2c33d0504f713f685ac5710e50/node_modules/@effected/lockfiles/PnpmExtension.js
4715
+ //#region ../../node_modules/.pnpm/@effected+lockfiles@0.2.1_@effected+jsonc@0.5.1_effect@4.0.0-beta.101__@effected+npm@0._44d8f67a8ab767df898f59f0e01343be/node_modules/@effected/lockfiles/PnpmExtension.js
4567
4716
  /**
4568
4717
  * Extension data specific to pnpm lockfiles, attached to `Lockfile.extension`
4569
4718
  * when the format is `"pnpm"`.
@@ -4588,7 +4737,7 @@ var PnpmExtension = class extends effect.Schema.Class("PnpmExtension")({
4588
4737
  }))
4589
4738
  }) {};
4590
4739
  //#endregion
4591
- //#region ../../node_modules/.pnpm/@effected+lockfiles@0.1.10_@effected+jsonc@0.5.1_effect@4.0.0-beta.101__@effected+npm@0_baf93f2c33d0504f713f685ac5710e50/node_modules/@effected/lockfiles/LockfileFormat.js
4740
+ //#region ../../node_modules/.pnpm/@effected+lockfiles@0.2.1_@effected+jsonc@0.5.1_effect@4.0.0-beta.101__@effected+npm@0._44d8f67a8ab767df898f59f0e01343be/node_modules/@effected/lockfiles/LockfileFormat.js
4592
4741
  /**
4593
4742
  * The lockfile formats this package parses: bun's `bun.lock` (JSONC), npm's
4594
4743
  * `package-lock.json` (v2/v3 JSON), pnpm's `pnpm-lock.yaml` and yarn Berry's
@@ -4622,7 +4771,7 @@ const FILENAMES = {
4622
4771
  */
4623
4772
  const filenameFor = (format) => FILENAMES[format];
4624
4773
  //#endregion
4625
- //#region ../../node_modules/.pnpm/@effected+lockfiles@0.1.10_@effected+jsonc@0.5.1_effect@4.0.0-beta.101__@effected+npm@0_baf93f2c33d0504f713f685ac5710e50/node_modules/@effected/lockfiles/internal/shared.js
4774
+ //#region ../../node_modules/.pnpm/@effected+lockfiles@0.2.1_@effected+jsonc@0.5.1_effect@4.0.0-beta.101__@effected+npm@0._44d8f67a8ab767df898f59f0e01343be/node_modules/@effected/lockfiles/internal/shared.js
4626
4775
  /**
4627
4776
  * The four dependency sections of a manifest, in a stable order — the shared
4628
4777
  * dependency-sections table (v3's `DEP_SECTIONS`). Each entry is both the
@@ -4661,22 +4810,54 @@ const toIntegrityHash = (raw) => {
4661
4810
  };
4662
4811
  const decodeSpecifier = effect.Schema.decodeUnknownExit(DependencySpecifier.FromString);
4663
4812
  /**
4813
+ * Split pnpm's peer-disambiguation suffix off a recorded string: everything
4814
+ * from the first `(` on is suffix, since package names and versions never
4815
+ * contain `(`. Handles both shapes pnpm records — a bare version
4816
+ * (`"1.0.0(effect@4.0.0)"`, importer entries) and a `name@version` snapshot key
4817
+ * (`"fdir@6.5.0(picomatch@4.0.4)"`). A string with no `(` — including
4818
+ * `link:...` / `file:...` resolutions — passes through untouched. So does a
4819
+ * protocol-bearing string (a `:` ahead of the first `(`), where a parenthesis
4820
+ * is path or URL text rather than a peer suffix: pnpm attaches suffixes to
4821
+ * registry versions only. This is the single stripping implementation — do not
4822
+ * hand-roll an `indexOf("(")` split elsewhere.
4823
+ *
4824
+ * @internal
4825
+ */
4826
+ const splitPeerSuffix = (raw) => {
4827
+ const parenIndex = raw.indexOf("(");
4828
+ if (parenIndex === -1) return { plain: raw };
4829
+ if (raw.lastIndexOf(":", parenIndex) !== -1) return { plain: raw };
4830
+ return {
4831
+ plain: raw.slice(0, parenIndex),
4832
+ peerSuffix: raw.slice(parenIndex)
4833
+ };
4834
+ };
4835
+ /**
4664
4836
  * Build one {@link ImporterDependency}, decoding the raw specifier string into
4665
4837
  * the `@effected/npm` `ClassifiedSpecifier` tagged union. Returns `undefined`
4666
4838
  * — a skip, never a throw — when the name is empty or the specifier does not
4667
4839
  * classify (e.g. an empty specifier), per the total-string-surgery discipline.
4668
4840
  *
4841
+ * A pnpm-recorded version is normalized through {@link splitPeerSuffix}: the
4842
+ * `version` field carries the plain version and the split-off peer chain lands
4843
+ * in `peerSuffix`. A version that is *only* a peer chain (empty plain part) is
4844
+ * treated as no concrete version — a skip of both fields, never a throw.
4845
+ *
4669
4846
  * @internal
4670
4847
  */
4671
4848
  const buildImporterDependency = (name, specifier, depType, version) => {
4672
4849
  if (name === "") return void 0;
4673
4850
  const exit = decodeSpecifier(specifier);
4674
4851
  if (effect.Exit.isFailure(exit)) return void 0;
4852
+ const resolved = version !== void 0 && version !== "" ? splitPeerSuffix(version) : void 0;
4675
4853
  return ImporterDependency.make({
4676
4854
  name,
4677
4855
  specifier: exit.value,
4678
4856
  depType,
4679
- ...version !== void 0 && version !== "" ? { version } : {}
4857
+ ...resolved !== void 0 && resolved.plain !== "" ? {
4858
+ version: resolved.plain,
4859
+ ...resolved.peerSuffix !== void 0 ? { peerSuffix: resolved.peerSuffix } : {}
4860
+ } : {}
4680
4861
  });
4681
4862
  };
4682
4863
  /**
@@ -6521,7 +6702,7 @@ var JsoncModifier = class {
6521
6702
  });
6522
6703
  };
6523
6704
  //#endregion
6524
- //#region ../../node_modules/.pnpm/@effected+lockfiles@0.1.10_@effected+jsonc@0.5.1_effect@4.0.0-beta.101__@effected+npm@0_baf93f2c33d0504f713f685ac5710e50/node_modules/@effected/lockfiles/internal/bun.js
6705
+ //#region ../../node_modules/.pnpm/@effected+lockfiles@0.2.1_@effected+jsonc@0.5.1_effect@4.0.0-beta.101__@effected+npm@0._44d8f67a8ab767df898f59f0e01343be/node_modules/@effected/lockfiles/internal/bun.js
6525
6706
  const DepRecord$2 = effect.Schema.optionalKey(effect.Schema.Record(effect.Schema.String, effect.Schema.String));
6526
6707
  const BunWorkspaceEntry = effect.Schema.Struct({
6527
6708
  name: effect.Schema.optionalKey(effect.Schema.String),
@@ -6614,7 +6795,7 @@ const toFields$3 = (raw) => effect.Effect.gen(function* () {
6614
6795
  };
6615
6796
  });
6616
6797
  //#endregion
6617
- //#region ../../node_modules/.pnpm/@effected+lockfiles@0.1.10_@effected+jsonc@0.5.1_effect@4.0.0-beta.101__@effected+npm@0_baf93f2c33d0504f713f685ac5710e50/node_modules/@effected/lockfiles/internal/npm.js
6798
+ //#region ../../node_modules/.pnpm/@effected+lockfiles@0.2.1_@effected+jsonc@0.5.1_effect@4.0.0-beta.101__@effected+npm@0._44d8f67a8ab767df898f59f0e01343be/node_modules/@effected/lockfiles/internal/npm.js
6618
6799
  const DepRecord$1 = effect.Schema.optionalKey(effect.Schema.Record(effect.Schema.String, effect.Schema.String));
6619
6800
  const NpmPackageEntry = effect.Schema.Struct({
6620
6801
  name: effect.Schema.optionalKey(effect.Schema.String),
@@ -6712,7 +6893,7 @@ const toFields$2 = (raw) => effect.Effect.gen(function* () {
6712
6893
  };
6713
6894
  });
6714
6895
  //#endregion
6715
- //#region ../../node_modules/.pnpm/@effected+yaml@0.5.1_effect@4.0.0-beta.101/node_modules/@effected/yaml/YamlNode.js
6896
+ //#region ../../node_modules/.pnpm/@effected+yaml@0.6.0_effect@4.0.0-beta.101/node_modules/@effected/yaml/YamlNode.js
6716
6897
  /**
6717
6898
  * YAML scalar presentation styles.
6718
6899
  *
@@ -7114,7 +7295,7 @@ function nodeToValue(node, anchors, budget, counting = false) {
7114
7295
  return null;
7115
7296
  }
7116
7297
  //#endregion
7117
- //#region ../../node_modules/.pnpm/@effected+yaml@0.5.1_effect@4.0.0-beta.101/node_modules/@effected/yaml/internal/diagnostics.js
7298
+ //#region ../../node_modules/.pnpm/@effected+yaml@0.6.0_effect@4.0.0-beta.101/node_modules/@effected/yaml/internal/diagnostics.js
7118
7299
  /** Error codes emitted by the lexer stage. */
7119
7300
  const YAML_LEX_ERROR_CODES = [
7120
7301
  "UnexpectedCharacter",
@@ -7192,7 +7373,7 @@ function isFatalCode(code) {
7192
7373
  return FATAL_CODES.has(code);
7193
7374
  }
7194
7375
  //#endregion
7195
- //#region ../../node_modules/.pnpm/@effected+yaml@0.5.1_effect@4.0.0-beta.101/node_modules/@effected/yaml/YamlDiagnostic.js
7376
+ //#region ../../node_modules/.pnpm/@effected+yaml@0.6.0_effect@4.0.0-beta.101/node_modules/@effected/yaml/YamlDiagnostic.js
7196
7377
  /**
7197
7378
  * Error codes emitted by the lexer stage.
7198
7379
  *
@@ -7313,7 +7494,7 @@ function lineChar(text, offset) {
7313
7494
  };
7314
7495
  }
7315
7496
  //#endregion
7316
- //#region ../../node_modules/.pnpm/@effected+yaml@0.5.1_effect@4.0.0-beta.101/node_modules/@effected/yaml/internal/composer/anchors.js
7497
+ //#region ../../node_modules/.pnpm/@effected+yaml@0.6.0_effect@4.0.0-beta.101/node_modules/@effected/yaml/internal/composer/anchors.js
7317
7498
  /**
7318
7499
  * Check if a pending anchor is being applied to an alias node (invalid in YAML 1.2 §3.2.2).
7319
7500
  * Aliases represent references to existing anchored nodes and cannot have their own anchors.
@@ -7406,7 +7587,7 @@ function collectAnchors(node, anchors) {
7406
7587
  }
7407
7588
  }
7408
7589
  //#endregion
7409
- //#region ../../node_modules/.pnpm/@effected+yaml@0.5.1_effect@4.0.0-beta.101/node_modules/@effected/yaml/internal/lexer.js
7590
+ //#region ../../node_modules/.pnpm/@effected+yaml@0.6.0_effect@4.0.0-beta.101/node_modules/@effected/yaml/internal/lexer.js
7410
7591
  /**
7411
7592
  * Create a new YAML scanner for the given source text.
7412
7593
  *
@@ -8363,7 +8544,7 @@ function lexAll(text) {
8363
8544
  return tokens;
8364
8545
  }
8365
8546
  //#endregion
8366
- //#region ../../node_modules/.pnpm/@effected+yaml@0.5.1_effect@4.0.0-beta.101/node_modules/@effected/yaml/internal/cst-parser.js
8547
+ //#region ../../node_modules/.pnpm/@effected+yaml@0.6.0_effect@4.0.0-beta.101/node_modules/@effected/yaml/internal/cst-parser.js
8367
8548
  /**
8368
8549
  * Hardening: cap CST nesting so hostile inputs cannot overflow the stack
8369
8550
  * while the tree is being BUILT. Set slightly above the composer's
@@ -9075,7 +9256,7 @@ function parseCSTAll(text) {
9075
9256
  return parseDocuments(lexAll(text), text);
9076
9257
  }
9077
9258
  //#endregion
9078
- //#region ../../node_modules/.pnpm/@effected+yaml@0.5.1_effect@4.0.0-beta.101/node_modules/@effected/yaml/internal/composer/state.js
9259
+ //#region ../../node_modules/.pnpm/@effected+yaml@0.6.0_effect@4.0.0-beta.101/node_modules/@effected/yaml/internal/composer/state.js
9079
9260
  let lineStartsText;
9080
9261
  let lineStartsCache = [];
9081
9262
  function getLineStarts(text) {
@@ -9181,7 +9362,7 @@ function exitNesting(state) {
9181
9362
  state.depth--;
9182
9363
  }
9183
9364
  //#endregion
9184
- //#region ../../node_modules/.pnpm/@effected+yaml@0.5.1_effect@4.0.0-beta.101/node_modules/@effected/yaml/internal/composer/tags.js
9365
+ //#region ../../node_modules/.pnpm/@effected+yaml@0.6.0_effect@4.0.0-beta.101/node_modules/@effected/yaml/internal/composer/tags.js
9185
9366
  /**
9186
9367
  * Resolve a tag shorthand using the document's %TAG directives.
9187
9368
  * For example, with `%TAG !! tag:example.com,2000:app/`, the tag `!!int`
@@ -9267,7 +9448,7 @@ function validateTagHandlesInDocument(docCst, state) {
9267
9448
  }
9268
9449
  }
9269
9450
  //#endregion
9270
- //#region ../../node_modules/.pnpm/@effected+yaml@0.5.1_effect@4.0.0-beta.101/node_modules/@effected/yaml/internal/composer/scalars.js
9451
+ //#region ../../node_modules/.pnpm/@effected+yaml@0.6.0_effect@4.0.0-beta.101/node_modules/@effected/yaml/internal/composer/scalars.js
9271
9452
  const NULL_RE$1 = /^(?:null|Null|NULL|~)$/;
9272
9453
  const TRUE_RE$1 = /^(?:true|True|TRUE)$/;
9273
9454
  const FALSE_RE$1 = /^(?:false|False|FALSE)$/;
@@ -10145,7 +10326,7 @@ function shouldPreserveRaw(rawValue, value) {
10145
10326
  return false;
10146
10327
  }
10147
10328
  //#endregion
10148
- //#region ../../node_modules/.pnpm/@effected+yaml@0.5.1_effect@4.0.0-beta.101/node_modules/@effected/yaml/internal/composer/block.js
10329
+ //#region ../../node_modules/.pnpm/@effected+yaml@0.6.0_effect@4.0.0-beta.101/node_modules/@effected/yaml/internal/composer/block.js
10149
10330
  /**
10150
10331
  * Compose a block map from its CST children, with an optional external first key.
10151
10332
  *
@@ -11293,7 +11474,7 @@ function composeFlatBlockMap(children, startIdx, parentCst, state, externalFirst
11293
11474
  return map;
11294
11475
  }
11295
11476
  //#endregion
11296
- //#region ../../node_modules/.pnpm/@effected+yaml@0.5.1_effect@4.0.0-beta.101/node_modules/@effected/yaml/internal/composer/flow.js
11477
+ //#region ../../node_modules/.pnpm/@effected+yaml@0.6.0_effect@4.0.0-beta.101/node_modules/@effected/yaml/internal/composer/flow.js
11297
11478
  /**
11298
11479
  * Validate that flow collection entries are separated by commas.
11299
11480
  *
@@ -11685,7 +11866,7 @@ function composeFlowSeqInner(cst, state, meta, parentBlockColumn) {
11685
11866
  return seq;
11686
11867
  }
11687
11868
  //#endregion
11688
- //#region ../../node_modules/.pnpm/@effected+yaml@0.5.1_effect@4.0.0-beta.101/node_modules/@effected/yaml/internal/composer/document.js
11869
+ //#region ../../node_modules/.pnpm/@effected+yaml@0.6.0_effect@4.0.0-beta.101/node_modules/@effected/yaml/internal/composer/document.js
11689
11870
  /** The flow-composer dispatch wired into every state this module creates. */
11690
11871
  const FLOW = {
11691
11872
  composeFlowMap,
@@ -12351,7 +12532,7 @@ function composeAllDocuments(text, options) {
12351
12532
  };
12352
12533
  }
12353
12534
  //#endregion
12354
- //#region ../../node_modules/.pnpm/@effected+yaml@0.5.1_effect@4.0.0-beta.101/node_modules/@effected/yaml/internal/fold.js
12535
+ //#region ../../node_modules/.pnpm/@effected+yaml@0.6.0_effect@4.0.0-beta.101/node_modules/@effected/yaml/internal/fold.js
12355
12536
  /**
12356
12537
  * Column-based line folding for a single logical scalar line (YAML 1.2 flow
12357
12538
  * folding, §7.3 / §8.2.1). Breaks the content at "safe" single-space
@@ -12587,7 +12768,7 @@ function renderBlockFolded(s, indent) {
12587
12768
  return `>${indentIndicator}${chomp}\n${outputLines.join("\n")}`;
12588
12769
  }
12589
12770
  //#endregion
12590
- //#region ../../node_modules/.pnpm/@effected+yaml@0.5.1_effect@4.0.0-beta.101/node_modules/@effected/yaml/internal/stringifier.js
12771
+ //#region ../../node_modules/.pnpm/@effected+yaml@0.6.0_effect@4.0.0-beta.101/node_modules/@effected/yaml/internal/stringifier.js
12591
12772
  /**
12592
12773
  * Thrown by the stringifier on its failure paths (circular references). The
12593
12774
  * facade catches this and materializes the public stringify error.
@@ -13536,7 +13717,7 @@ function deepEqualValues(a, b) {
13536
13717
  return false;
13537
13718
  }
13538
13719
  //#endregion
13539
- //#region ../../node_modules/.pnpm/@effected+lockfiles@0.1.10_@effected+jsonc@0.5.1_effect@4.0.0-beta.101__@effected+npm@0_baf93f2c33d0504f713f685ac5710e50/node_modules/@effected/lockfiles/internal/documents.js
13720
+ //#region ../../node_modules/.pnpm/@effected+lockfiles@0.2.1_@effected+jsonc@0.5.1_effect@4.0.0-beta.101__@effected+npm@0._44d8f67a8ab767df898f59f0e01343be/node_modules/@effected/lockfiles/internal/documents.js
13540
13721
  /**
13541
13722
  * An empty YAML document composes to `null` (`Yaml.parseAll("")` is `[null]`,
13542
13723
  * and the trailing document of an env-only `pnpm-lock.yaml` is `null` too).
@@ -13606,7 +13787,7 @@ const selectSoleDocument = (content) => effect.Effect.gen(function* () {
13606
13787
  };
13607
13788
  });
13608
13789
  //#endregion
13609
- //#region ../../node_modules/.pnpm/@effected+lockfiles@0.1.10_@effected+jsonc@0.5.1_effect@4.0.0-beta.101__@effected+npm@0_baf93f2c33d0504f713f685ac5710e50/node_modules/@effected/lockfiles/internal/pnpm.js
13790
+ //#region ../../node_modules/.pnpm/@effected+lockfiles@0.2.1_@effected+jsonc@0.5.1_effect@4.0.0-beta.101__@effected+npm@0._44d8f67a8ab767df898f59f0e01343be/node_modules/@effected/lockfiles/internal/pnpm.js
13610
13791
  const PnpmImporterDeps = effect.Schema.optionalKey(effect.Schema.Record(effect.Schema.String, effect.Schema.Struct({
13611
13792
  specifier: effect.Schema.String,
13612
13793
  version: effect.Schema.String
@@ -13703,8 +13884,7 @@ const toFields$1 = (raw) => effect.Effect.gen(function* () {
13703
13884
  }));
13704
13885
  }
13705
13886
  if (raw.packages) for (const [key, pkg] of Object.entries(raw.packages)) {
13706
- const parenIndex = key.indexOf("(");
13707
- const bare = parenIndex === -1 ? key : key.slice(0, parenIndex);
13887
+ const { plain: bare } = splitPeerSuffix(key);
13708
13888
  const atIndex = bare.lastIndexOf("@");
13709
13889
  if (atIndex <= 0) continue;
13710
13890
  const name = bare.slice(0, atIndex);
@@ -13732,7 +13912,7 @@ const toFields$1 = (raw) => effect.Effect.gen(function* () {
13732
13912
  };
13733
13913
  });
13734
13914
  //#endregion
13735
- //#region ../../node_modules/.pnpm/@effected+lockfiles@0.1.10_@effected+jsonc@0.5.1_effect@4.0.0-beta.101__@effected+npm@0_baf93f2c33d0504f713f685ac5710e50/node_modules/@effected/lockfiles/internal/yarn.js
13915
+ //#region ../../node_modules/.pnpm/@effected+lockfiles@0.2.1_@effected+jsonc@0.5.1_effect@4.0.0-beta.101__@effected+npm@0._44d8f67a8ab767df898f59f0e01343be/node_modules/@effected/lockfiles/internal/yarn.js
13736
13916
  const YarnLockfileRaw = effect.Schema.Record(effect.Schema.String, effect.Schema.Unknown);
13737
13917
  const DepRecord = effect.Schema.optionalKey(effect.Schema.Record(effect.Schema.String, effect.Schema.String));
13738
13918
  const YarnEntry = effect.Schema.Struct({
@@ -13855,7 +14035,7 @@ const cleanYarnDeps = (deps) => {
13855
14035
  return Object.fromEntries(Object.entries(deps).map(([name, value]) => [name, value.startsWith("npm:") ? value.slice(4) : value]));
13856
14036
  };
13857
14037
  //#endregion
13858
- //#region ../../node_modules/.pnpm/@effected+lockfiles@0.1.10_@effected+jsonc@0.5.1_effect@4.0.0-beta.101__@effected+npm@0_baf93f2c33d0504f713f685ac5710e50/node_modules/@effected/lockfiles/Lockfile.js
14038
+ //#region ../../node_modules/.pnpm/@effected+lockfiles@0.2.1_@effected+jsonc@0.5.1_effect@4.0.0-beta.101__@effected+npm@0._44d8f67a8ab767df898f59f0e01343be/node_modules/@effected/lockfiles/Lockfile.js
13859
14039
  const EMPTY_IMPORTERS = [];
13860
14040
  /**
13861
14041
  * Failure of `Lockfile.parse`: the given content is not a valid lockfile of
@@ -14099,7 +14279,7 @@ var Lockfile = class Lockfile extends effect.Schema.Class("Lockfile")({
14099
14279
  }
14100
14280
  };
14101
14281
  //#endregion
14102
- //#region ../../node_modules/.pnpm/@effected+lockfiles@0.1.10_@effected+jsonc@0.5.1_effect@4.0.0-beta.101__@effected+npm@0_baf93f2c33d0504f713f685ac5710e50/node_modules/@effected/lockfiles/LockfileIntegrity.js
14282
+ //#region ../../node_modules/.pnpm/@effected+lockfiles@0.2.1_@effected+jsonc@0.5.1_effect@4.0.0-beta.101__@effected+npm@0._44d8f67a8ab767df898f59f0e01343be/node_modules/@effected/lockfiles/LockfileIntegrity.js
14103
14283
  /**
14104
14284
  * The minimal manifest shape {@link LockfileIntegrity.compare} checks a
14105
14285
  * lockfile against: a package name plus the four optional dependency maps.
@@ -14215,7 +14395,7 @@ var LockfileIntegrity = class LockfileIntegrity extends effect.Schema.Class("Loc
14215
14395
  }
14216
14396
  };
14217
14397
  //#endregion
14218
- //#region ../../node_modules/.pnpm/@effected+package-json@0.5.1_effect@4.0.0-beta.101/node_modules/@effected/package-json/Dependency.js
14398
+ //#region ../../node_modules/.pnpm/@effected+package-json@0.6.0_effect@4.0.0-beta.101/node_modules/@effected/package-json/Dependency.js
14219
14399
  /**
14220
14400
  * A resolved dependency entry pairing a package name with its version
14221
14401
  * specifier and the `kind` of map it came from (`@effected/npm`'s
@@ -14279,7 +14459,7 @@ var Dependency = class extends effect.Schema.Class("Dependency")({
14279
14459
  }
14280
14460
  };
14281
14461
  //#endregion
14282
- //#region ../../node_modules/.pnpm/@effected+package-json@0.5.1_effect@4.0.0-beta.101/node_modules/@effected/package-json/DevEngines.js
14462
+ //#region ../../node_modules/.pnpm/@effected+package-json@0.6.0_effect@4.0.0-beta.101/node_modules/@effected/package-json/DevEngines.js
14283
14463
  /**
14284
14464
  * A single `devEngines` constraint with a name and optional `version` / `onFail`.
14285
14465
  *
@@ -15834,7 +16014,7 @@ effect.Schema.String.pipe(effect.Schema.decodeTo(SpdxExpressionUnion, effect.Sch
15834
16014
  encode: (expression) => effect.Effect.succeed(serialize$1(expression))
15835
16015
  })));
15836
16016
  //#endregion
15837
- //#region ../../node_modules/.pnpm/@effected+package-json@0.5.1_effect@4.0.0-beta.101/node_modules/@effected/package-json/License.js
16017
+ //#region ../../node_modules/.pnpm/@effected+package-json@0.6.0_effect@4.0.0-beta.101/node_modules/@effected/package-json/License.js
15838
16018
  /**
15839
16019
  * Indicates that a string is not a valid SPDX license identifier or expression.
15840
16020
  *
@@ -15869,7 +16049,7 @@ const isValidSpdx = (value) => {
15869
16049
  */
15870
16050
  const SpdxLicense = effect.Schema.String.pipe(effect.Schema.check(effect.Schema.makeFilter((value) => isValidSpdx(value) ? void 0 : "Expected a valid SPDX license expression")), effect.Schema.brand("SpdxLicense"));
15871
16051
  //#endregion
15872
- //#region ../../node_modules/.pnpm/@effected+package-json@0.5.1_effect@4.0.0-beta.101/node_modules/@effected/package-json/PackageManager.js
16052
+ //#region ../../node_modules/.pnpm/@effected+package-json@0.6.0_effect@4.0.0-beta.101/node_modules/@effected/package-json/PackageManager.js
15873
16053
  const PACKAGE_MANAGER_RE = /^([a-z]+)@(\d+\.\d+\.\d+(?:-[a-zA-Z0-9._-]+)?)(?:\+(.+))?$/;
15874
16054
  /**
15875
16055
  * The `packageManager` field only ever carries corepack's `<algo>.<hex>`
@@ -15927,7 +16107,7 @@ var PackageManager = class PackageManager extends effect.Schema.Class("PackageMa
15927
16107
  }
15928
16108
  };
15929
16109
  //#endregion
15930
- //#region ../../node_modules/.pnpm/@effected+package-json@0.5.1_effect@4.0.0-beta.101/node_modules/@effected/package-json/PackageName.js
16110
+ //#region ../../node_modules/.pnpm/@effected+package-json@0.6.0_effect@4.0.0-beta.101/node_modules/@effected/package-json/PackageName.js
15931
16111
  /**
15932
16112
  * Indicates that a string could not be used as a valid npm package name.
15933
16113
  *
@@ -15985,7 +16165,7 @@ const PackageName = Object.assign(effect.Schema.Union([ScopedPackageName, Unscop
15985
16165
  isScoped
15986
16166
  });
15987
16167
  //#endregion
15988
- //#region ../../node_modules/.pnpm/@effected+package-json@0.5.1_effect@4.0.0-beta.101/node_modules/@effected/package-json/Person.js
16168
+ //#region ../../node_modules/.pnpm/@effected+package-json@0.6.0_effect@4.0.0-beta.101/node_modules/@effected/package-json/Person.js
15989
16169
  const parsePersonString = (input) => {
15990
16170
  const emailMatch = input.match(/<([^>]+)>/);
15991
16171
  const urlMatch = input.match(/\(([^)]+)\)/);
@@ -16016,10 +16196,11 @@ const KNOWN_KEYS = /* @__PURE__ */ new Set([
16016
16196
  "url"
16017
16197
  ]);
16018
16198
  const sameRest = (a, b) => JSON.stringify(a ?? {}) === JSON.stringify(b ?? {});
16199
+ const isShorthandExpressible = (person) => person.rest === void 0 || Object.keys(person.rest).length === 0;
16019
16200
  const isFaithful = (wire, person) => {
16020
16201
  if (typeof wire === "string") {
16021
16202
  const parsed = parsePersonString(wire);
16022
- return parsed.name === person.name && parsed.email === person.email && parsed.url === person.url;
16203
+ return parsed.name === person.name && parsed.email === person.email && parsed.url === person.url && isShorthandExpressible(person);
16023
16204
  }
16024
16205
  const rest = restOf(wire);
16025
16206
  return wire.name === person.name && wire.email === person.email && wire.url === person.url && sameRest(rest, person.rest);
@@ -16108,7 +16289,9 @@ var Person = class Person extends effect.Schema.Class("Person")({
16108
16289
  decode: (input) => typeof input === "string" ? rememberWire(parsePersonString(input), input) : input,
16109
16290
  encode: (person) => {
16110
16291
  const wire = wireForms.get(person);
16111
- return typeof wire === "string" && isFaithful(wire, person) ? wire : person;
16292
+ if (typeof wire !== "string") return person;
16293
+ if (isFaithful(wire, person)) return wire;
16294
+ return isShorthandExpressible(person) ? serializePerson(person) : person;
16112
16295
  }
16113
16296
  })));
16114
16297
  /**
@@ -16128,7 +16311,182 @@ var Person = class Person extends effect.Schema.Class("Person")({
16128
16311
  }
16129
16312
  };
16130
16313
  //#endregion
16131
- //#region ../../node_modules/.pnpm/@effected+package-json@0.5.1_effect@4.0.0-beta.101/node_modules/@effected/package-json/internal/format.js
16314
+ //#region ../../node_modules/.pnpm/@effected+package-json@0.6.0_effect@4.0.0-beta.101/node_modules/@effected/package-json/Repository.js
16315
+ /** The shorthand hosts npm resolves without a scheme. */
16316
+ const SHORTHAND_HOSTS = /* @__PURE__ */ new Map([
16317
+ ["github", "https://github.com"],
16318
+ ["gitlab", "https://gitlab.com"],
16319
+ ["bitbucket", "https://bitbucket.org"]
16320
+ ]);
16321
+ /** `owner/name`, the bare GitHub shorthand. Deliberately strict about segment shape. */
16322
+ const BARE_SHORTHAND = /^[\w.-]+\/[\w.-]+$/;
16323
+ /** `github:owner/name`, `gist:id`, … */
16324
+ const PREFIXED_SHORTHAND = /^([a-z]+):(.+)$/;
16325
+ /** The scp-like form git accepts: `git@host:owner/name.git`. */
16326
+ const SCP_LIKE = /^(?:([\w.-]+)@)?([\w.-]+):(.+)$/;
16327
+ const stripGitSuffix = (value) => value.endsWith(".git") ? value.slice(0, -4) : value;
16328
+ /**
16329
+ * The browsable `https://host/path` form of a repository reference, or none
16330
+ * when the value is not one this model recognizes.
16331
+ *
16332
+ * Total by construction: `repository` is caller data, and a value we cannot
16333
+ * interpret is a missing answer rather than a failure.
16334
+ */
16335
+ const browseUrlOf = (raw) => {
16336
+ const url = raw.trim();
16337
+ if (url === "") return effect.Option.none();
16338
+ if (BARE_SHORTHAND.test(url)) return effect.Option.some(`https://github.com/${url}`);
16339
+ const prefixed = PREFIXED_SHORTHAND.exec(url);
16340
+ if (prefixed !== null) {
16341
+ const [, scheme, rest] = prefixed;
16342
+ if (scheme === "gist") return effect.Option.some(`https://gist.github.com/${stripGitSuffix(rest ?? "")}`);
16343
+ const host = SHORTHAND_HOSTS.get(scheme ?? "");
16344
+ if (host !== void 0) return effect.Option.some(`${host}/${stripGitSuffix(rest ?? "")}`);
16345
+ }
16346
+ const withoutGitPlus = url.startsWith("git+") ? url.slice(4) : url;
16347
+ const schemeMatch = /^([a-z][a-z0-9+.-]*):\/\/(.*)$/i.exec(withoutGitPlus);
16348
+ if (schemeMatch !== null) {
16349
+ const withoutCredentials = (schemeMatch[2] ?? "").replace(/^[^/@]+@/, "");
16350
+ return withoutCredentials === "" ? effect.Option.none() : effect.Option.some(`https://${stripGitSuffix(withoutCredentials)}`);
16351
+ }
16352
+ const scp = SCP_LIKE.exec(withoutGitPlus);
16353
+ if (scp !== null) {
16354
+ const [, , host, path] = scp;
16355
+ if (host !== void 0 && path !== void 0 && path !== "") return effect.Option.some(`https://${host}/${stripGitSuffix(path)}`);
16356
+ }
16357
+ return effect.Option.none();
16358
+ };
16359
+ const repositoryWires = /* @__PURE__ */ new WeakMap();
16360
+ const bugsWires = /* @__PURE__ */ new WeakMap();
16361
+ const KNOWN_REPOSITORY_KEYS = /* @__PURE__ */ new Set([
16362
+ "type",
16363
+ "url",
16364
+ "directory"
16365
+ ]);
16366
+ const KNOWN_BUGS_KEYS = /* @__PURE__ */ new Set(["url", "email"]);
16367
+ /**
16368
+ * Where a package's source lives.
16369
+ *
16370
+ * @remarks
16371
+ * `url` is **verbatim** — exactly the string the manifest carried, shorthand
16372
+ * and all. Normalization is offered through {@link Repository.browseUrl} and
16373
+ * {@link Repository.gitUrl}, so reading a manifest never rewrites it and a
16374
+ * caller that wants the original still has it.
16375
+ *
16376
+ * @example
16377
+ * ```ts
16378
+ * // "effected/kit" → https://github.com/effected/kit
16379
+ * // "git@github.com:effected/kit.git" → https://github.com/effected/kit
16380
+ * ```
16381
+ *
16382
+ * @public
16383
+ */
16384
+ var Repository = class Repository extends effect.Schema.Class("Repository")({
16385
+ /** The `type` field, when the object form carried one (`"git"`, …). */
16386
+ type: effect.Schema.optionalKey(effect.Schema.String),
16387
+ /** The reference exactly as written: a shorthand, a git URL, or an https URL. */
16388
+ url: effect.Schema.String,
16389
+ /** The subdirectory within the repository, for a monorepo member. */
16390
+ directory: effect.Schema.optionalKey(effect.Schema.String),
16391
+ /** Keys outside the documented set, preserved so encoding does not drop them. */
16392
+ rest: effect.Schema.optionalKey(effect.Schema.Record(effect.Schema.String, effect.Schema.Unknown))
16393
+ }) {
16394
+ /**
16395
+ * The browsable `https://` URL, or `Option.none()` when `url` is not a form
16396
+ * this model recognizes.
16397
+ */
16398
+ get browseUrl() {
16399
+ return browseUrlOf(this.url);
16400
+ }
16401
+ /** The canonical https clone URL, or none when it cannot be derived. */
16402
+ get gitUrl() {
16403
+ return effect.Option.map(this.browseUrl, (url) => `${url}.git`);
16404
+ }
16405
+ /**
16406
+ * The `repository` field: the shorthand string or the object form, always
16407
+ * decoded to a {@link Repository}, and always re-encoded in the form it was
16408
+ * read from.
16409
+ */
16410
+ static FromValue = effect.Schema.Union([effect.Schema.Record(effect.Schema.String, effect.Schema.Unknown), effect.Schema.String]).pipe(effect.Schema.decodeTo(effect.Schema.instanceOf(Repository), effect.SchemaTransformation.transform({
16411
+ decode: (input) => {
16412
+ if (typeof input === "string") {
16413
+ const repository = Repository.make({ url: input });
16414
+ repositoryWires.set(repository, input);
16415
+ return repository;
16416
+ }
16417
+ const rest = {};
16418
+ for (const [key, value] of Object.entries(input)) if (!KNOWN_REPOSITORY_KEYS.has(key)) rest[key] = value;
16419
+ const repository = Repository.make({
16420
+ url: typeof input.url === "string" ? input.url : "",
16421
+ ...typeof input.type === "string" && { type: input.type },
16422
+ ...typeof input.directory === "string" && { directory: input.directory },
16423
+ ...Object.keys(rest).length > 0 && { rest }
16424
+ });
16425
+ repositoryWires.set(repository, input);
16426
+ return repository;
16427
+ },
16428
+ encode: (repository) => {
16429
+ const wire = repositoryWires.get(repository);
16430
+ if (typeof wire === "string" && wire === repository.url) return wire;
16431
+ if (wire !== void 0 && typeof wire !== "string") return wire;
16432
+ return {
16433
+ ...repository.type !== void 0 && { type: repository.type },
16434
+ url: repository.url,
16435
+ ...repository.directory !== void 0 && { directory: repository.directory },
16436
+ ...repository.rest
16437
+ };
16438
+ }
16439
+ })));
16440
+ };
16441
+ /**
16442
+ * Where to report problems with a package.
16443
+ *
16444
+ * @remarks
16445
+ * npm permits a bare URL string, or an object with `url`, `email`, or both —
16446
+ * an email-only entry is legal, which is why `url` is optional.
16447
+ *
16448
+ * @public
16449
+ */
16450
+ var Bugs = class Bugs extends effect.Schema.Class("Bugs")({
16451
+ /** The issue-tracker URL. */
16452
+ url: effect.Schema.optionalKey(effect.Schema.String),
16453
+ /** The address to mail instead of, or alongside, filing an issue. */
16454
+ email: effect.Schema.optionalKey(effect.Schema.String),
16455
+ /** Keys outside the documented set, preserved so encoding does not drop them. */
16456
+ rest: effect.Schema.optionalKey(effect.Schema.Record(effect.Schema.String, effect.Schema.Unknown))
16457
+ }) {
16458
+ /** The `bugs` field: a URL string or the object form. */
16459
+ static FromValue = effect.Schema.Union([effect.Schema.Record(effect.Schema.String, effect.Schema.Unknown), effect.Schema.String]).pipe(effect.Schema.decodeTo(effect.Schema.instanceOf(Bugs), effect.SchemaTransformation.transform({
16460
+ decode: (input) => {
16461
+ if (typeof input === "string") {
16462
+ const bugs = Bugs.make({ url: input });
16463
+ bugsWires.set(bugs, input);
16464
+ return bugs;
16465
+ }
16466
+ const rest = {};
16467
+ for (const [key, value] of Object.entries(input)) if (!KNOWN_BUGS_KEYS.has(key)) rest[key] = value;
16468
+ const bugs = Bugs.make({
16469
+ ...typeof input.url === "string" && { url: input.url },
16470
+ ...typeof input.email === "string" && { email: input.email },
16471
+ ...Object.keys(rest).length > 0 && { rest }
16472
+ });
16473
+ bugsWires.set(bugs, input);
16474
+ return bugs;
16475
+ },
16476
+ encode: (bugs) => {
16477
+ const wire = bugsWires.get(bugs);
16478
+ if (typeof wire === "string" && wire === bugs.url && bugs.email === void 0) return wire;
16479
+ if (wire !== void 0 && typeof wire !== "string") return wire;
16480
+ return {
16481
+ ...bugs.url !== void 0 && { url: bugs.url },
16482
+ ...bugs.email !== void 0 && { email: bugs.email },
16483
+ ...bugs.rest
16484
+ };
16485
+ }
16486
+ })));
16487
+ };
16488
+ //#endregion
16489
+ //#region ../../node_modules/.pnpm/@effected+package-json@0.6.0_effect@4.0.0-beta.101/node_modules/@effected/package-json/internal/format.js
16132
16490
  const KEY_INDEX = new Map([
16133
16491
  "$schema",
16134
16492
  "name",
@@ -16351,7 +16709,7 @@ const renderJson = (raw, options) => {
16351
16709
  return options.newline ? `${json}\n` : json;
16352
16710
  };
16353
16711
  //#endregion
16354
- //#region ../../node_modules/.pnpm/@effected+package-json@0.5.1_effect@4.0.0-beta.101/node_modules/@effected/package-json/Package.js
16712
+ //#region ../../node_modules/.pnpm/@effected+package-json@0.6.0_effect@4.0.0-beta.101/node_modules/@effected/package-json/Package.js
16355
16713
  const toHashMap = effect.SchemaTransformation.transform({
16356
16714
  decode: (record) => effect.HashMap.fromIterable(Object.entries(record)),
16357
16715
  encode: (map) => Object.fromEntries(effect.HashMap.toEntries(map))
@@ -16401,14 +16759,7 @@ const PublishConfigField = effect.Schema.Record(effect.Schema.String, effect.Sch
16401
16759
  * @public
16402
16760
  */
16403
16761
  const PeerDependenciesMetaField = effect.Schema.Record(effect.Schema.String, effect.Schema.Struct({ optional: effect.Schema.optionalKey(effect.Schema.Boolean) }));
16404
- /**
16405
- * The `repository` field: a shorthand string or an object (with `type` / `url` /
16406
- * `directory` and any extensions preserved). Not meant to be referenced
16407
- * directly.
16408
- *
16409
- * @public
16410
- */
16411
- const RepositoryField = effect.Schema.Union([effect.Schema.String, effect.Schema.Record(effect.Schema.String, effect.Schema.Unknown)]);
16762
+ effect.Schema.Union([effect.Schema.String, effect.Schema.Record(effect.Schema.String, effect.Schema.Unknown)]);
16412
16763
  /**
16413
16764
  * Indicates that a JSON value could not be decoded into a valid {@link Package}.
16414
16765
  *
@@ -16483,7 +16834,11 @@ var Package = class Package extends effect.Schema.Class("Package")({
16483
16834
  license: effect.Schema.optionalKey(SpdxLicense),
16484
16835
  author: effect.Schema.optionalKey(Person.FromValue),
16485
16836
  contributors: effect.Schema.optionalKey(effect.Schema.Array(Person.FromValue)),
16486
- repository: effect.Schema.optionalKey(RepositoryField),
16837
+ maintainers: effect.Schema.optionalKey(effect.Schema.Array(Person.FromValue)),
16838
+ keywords: effect.Schema.optionalKey(effect.Schema.Array(effect.Schema.String)),
16839
+ repository: effect.Schema.optionalKey(Repository.FromValue),
16840
+ bugs: effect.Schema.optionalKey(Bugs.FromValue),
16841
+ homepage: effect.Schema.optionalKey(effect.Schema.String),
16487
16842
  dependencies: DependencyMapField,
16488
16843
  devDependencies: DependencyMapField,
16489
16844
  peerDependencies: DependencyMapField,
@@ -16669,7 +17024,7 @@ var Package = class Package extends effect.Schema.Class("Package")({
16669
17024
  }
16670
17025
  };
16671
17026
  //#endregion
16672
- //#region ../../node_modules/.pnpm/@effected+workspaces@0.7.0_@effected+jsonc@0.5.1_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/WorkspacePackage.js
17027
+ //#region ../../node_modules/.pnpm/@effected+workspaces@0.9.0_@effected+jsonc@0.5.1_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/WorkspacePackage.js
16673
17028
  const EMPTY$1 = Object.freeze(Object.create(null));
16674
17029
  const EMPTY_MANIFEST = Object.freeze(Object.create(null));
16675
17030
  /**
@@ -16948,7 +17303,7 @@ var WorkspacePackage = class WorkspacePackage extends effect.Schema.Class("Works
16948
17303
  }
16949
17304
  };
16950
17305
  //#endregion
16951
- //#region ../../node_modules/.pnpm/@effected+walker@0.3.2_@effected+glob@0.2.1_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/walker/Descend.js
17306
+ //#region ../../node_modules/.pnpm/@effected+walker@0.3.3_@effected+glob@0.2.1_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/walker/Descend.js
16952
17307
  /**
16953
17308
  * Typed failure raised by {@link descend}: a directory mid-walk was unreadable
16954
17309
  * (under `onUnreadable: "fail"`), or the walk descended past `maxDepth`. Depth
@@ -17083,7 +17438,7 @@ const descend = effect.Effect.fn("Walker.descend")(function* (pattern, options)
17083
17438
  return results;
17084
17439
  });
17085
17440
  //#endregion
17086
- //#region ../../node_modules/.pnpm/@effected+walker@0.3.2_@effected+glob@0.2.1_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/walker/Expand.js
17441
+ //#region ../../node_modules/.pnpm/@effected+walker@0.3.3_@effected+glob@0.2.1_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/walker/Expand.js
17087
17442
  /**
17088
17443
  * Typed failure raised by {@link compileAndExpand}: the single error the
17089
17444
  * compile+expand recipe fails with, so a caller catches one tag rather than
@@ -17173,31 +17528,7 @@ const compileAndExpand = effect.Effect.fn("Walker.compileAndExpand")(function* (
17173
17528
  })));
17174
17529
  });
17175
17530
  //#endregion
17176
- //#region ../../node_modules/.pnpm/@effected+walker@0.3.2_@effected+glob@0.2.1_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/walker/Walker.js
17177
- /**
17178
- * Ascend from `start` toward the filesystem root, yielding each directory,
17179
- * nearest first.
17180
- *
17181
- * @remarks
17182
- * Lexical, not physical: `Path.dirname` does not resolve symlinks, so ascending
17183
- * out of a symlinked directory follows the path you were given rather than the
17184
- * real filesystem parent. That is deliberate — config discovery wants the file
17185
- * nearest the path the user named.
17186
- *
17187
- * Bounded twice over: `dirname` is a fixpoint at the root, and `maxDepth` guards
17188
- * a pathological `Path` implementation that never reaches one.
17189
- *
17190
- * `stopAt` is compared in normalized form — see {@link AscendOptions.stopAt}.
17191
- * Raw string equality made the ceiling fail OPEN: an unnormalized ceiling
17192
- * matched nothing and the ascent ran silently to the filesystem root, which is
17193
- * the unbounded walk the option exists to prevent, with no error to notice it
17194
- * by. A relative ceiling **dies** for the same reason — resolving one against
17195
- * `process.cwd()` would reintroduce the silent-wrong-walk failure through a
17196
- * different door. See {@link AscendOptions.stopAt} for why that is a defect
17197
- * rather than a typed error; the error channel stays `never`.
17198
- *
17199
- * @public
17200
- */
17531
+ //#region ../../node_modules/.pnpm/@effected+walker@0.3.3_@effected+glob@0.2.1_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/walker/Walker.js
17201
17532
  const ascend = (start, options) => effect.Effect.gen(function* () {
17202
17533
  const path = yield* effect.Path.Path;
17203
17534
  const maxDepth = options?.maxDepth ?? 256;
@@ -17215,66 +17546,83 @@ const ascend = (start, options) => effect.Effect.gen(function* () {
17215
17546
  }
17216
17547
  return dirs;
17217
17548
  });
17218
- /**
17219
- * The first candidate whose `predicate` reports true, or `Option.none()`.
17220
- *
17221
- * @remarks
17222
- * Each predicate is absorbed **individually**: a failure on one candidate is
17223
- * treated as "this candidate did not match" and the scan continues. One
17224
- * unreadable ancestor must never abort the walk, or a permission error deep in
17225
- * the tree would hide a valid root above it. Not-found and cannot-look are
17226
- * therefore indistinguishable to the caller; discovery is best-effort.
17227
- *
17228
- * `Effect.catch` catches failures, **not defects**. A predicate that throws is
17229
- * programmer error and surfaces as a defect. Do not change this to
17230
- * `Effect.catchCause` — the distinction is load-bearing.
17231
- *
17232
- * @public
17233
- */
17234
17549
  const firstMatch = (candidates, predicate) => effect.Effect.gen(function* () {
17235
17550
  for (const candidate of candidates) if (yield* effect.Effect.catch(predicate(candidate), () => effect.Effect.succeed(false))) return effect.Option.some(candidate);
17236
17551
  return effect.Option.none();
17237
17552
  });
17238
- /**
17239
- * The first existing path among the candidates `candidatesFor` produces for each
17240
- * directory in `dirs`, scanned in order. Nearer directories win.
17241
- *
17242
- * @remarks
17243
- * Candidates materialize up front, bounded by `dirs.length × candidatesFor`'s
17244
- * output — a few hundred strings under the default `maxDepth`.
17245
- *
17246
- * @public
17247
- */
17248
17553
  const findUpward = (dirs, candidatesFor) => effect.Effect.gen(function* () {
17249
17554
  const fs = yield* effect.FileSystem.FileSystem;
17250
17555
  const candidates = [];
17251
17556
  for (const dir of dirs) candidates.push(...candidatesFor(dir));
17252
17557
  return yield* firstMatch(candidates, (candidate) => fs.exists(candidate));
17253
17558
  });
17254
- /**
17255
- * The first directory in `dirs` that `isRoot` accepts.
17256
- *
17257
- * @remarks
17258
- * `firstMatch` over the directories themselves — the candidate expansion is the
17259
- * identity. `isRoot` is a caller-supplied marker test (a `.git` entry, a
17260
- * `pnpm-workspace.yaml`), and its failures are absorbed per directory.
17261
- *
17262
- * @public
17263
- */
17264
17559
  const findRoot$1 = (dirs, isRoot) => firstMatch(dirs, isRoot);
17265
17560
  /**
17266
17561
  * Upward path traversal primitives.
17267
17562
  *
17268
17563
  * @public
17269
17564
  */
17270
- const Walker$1 = {
17271
- ascend,
17272
- firstMatch,
17273
- findUpward,
17274
- findRoot: findRoot$1
17565
+ var Walker$1 = class {
17566
+ constructor() {}
17567
+ /**
17568
+ * Ascend from `start` toward the filesystem root, yielding each directory,
17569
+ * nearest first.
17570
+ *
17571
+ * @remarks
17572
+ * Lexical, not physical: `Path.dirname` does not resolve symlinks, so ascending
17573
+ * out of a symlinked directory follows the path you were given rather than the
17574
+ * real filesystem parent. That is deliberate — config discovery wants the file
17575
+ * nearest the path the user named.
17576
+ *
17577
+ * Bounded twice over: `dirname` is a fixpoint at the root, and `maxDepth` guards
17578
+ * a pathological `Path` implementation that never reaches one.
17579
+ *
17580
+ * `stopAt` is compared in normalized form — see {@link AscendOptions.stopAt}.
17581
+ * Raw string equality made the ceiling fail OPEN: an unnormalized ceiling
17582
+ * matched nothing and the ascent ran silently to the filesystem root, which is
17583
+ * the unbounded walk the option exists to prevent, with no error to notice it
17584
+ * by. A relative ceiling **dies** for the same reason — resolving one against
17585
+ * `process.cwd()` would reintroduce the silent-wrong-walk failure through a
17586
+ * different door. See {@link AscendOptions.stopAt} for why that is a defect
17587
+ * rather than a typed error; the error channel stays `never`.
17588
+ */
17589
+ static ascend = ascend;
17590
+ /**
17591
+ * The first candidate whose `predicate` reports true, or `Option.none()`.
17592
+ *
17593
+ * @remarks
17594
+ * Each predicate is absorbed **individually**: a failure on one candidate is
17595
+ * treated as "this candidate did not match" and the scan continues. One
17596
+ * unreadable ancestor must never abort the walk, or a permission error deep in
17597
+ * the tree would hide a valid root above it. Not-found and cannot-look are
17598
+ * therefore indistinguishable to the caller; discovery is best-effort.
17599
+ *
17600
+ * `Effect.catch` catches failures, **not defects**. A predicate that throws is
17601
+ * programmer error and surfaces as a defect. Do not change this to
17602
+ * `Effect.catchCause` — the distinction is load-bearing.
17603
+ */
17604
+ static firstMatch = firstMatch;
17605
+ /**
17606
+ * The first existing path among the candidates `candidatesFor` produces for each
17607
+ * directory in `dirs`, scanned in order. Nearer directories win.
17608
+ *
17609
+ * @remarks
17610
+ * Candidates materialize up front, bounded by `dirs.length × candidatesFor`'s
17611
+ * output — a few hundred strings under the default `maxDepth`.
17612
+ */
17613
+ static findUpward = findUpward;
17614
+ /**
17615
+ * The first directory in `dirs` that `isRoot` accepts.
17616
+ *
17617
+ * @remarks
17618
+ * `firstMatch` over the directories themselves — the candidate expansion is the
17619
+ * identity. `isRoot` is a caller-supplied marker test (a `.git` entry, a
17620
+ * `pnpm-workspace.yaml`), and its failures are absorbed per directory.
17621
+ */
17622
+ static findRoot = findRoot$1;
17275
17623
  };
17276
17624
  //#endregion
17277
- //#region ../../node_modules/.pnpm/@effected+workspaces@0.7.0_@effected+jsonc@0.5.1_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/WorkspaceRoot.js
17625
+ //#region ../../node_modules/.pnpm/@effected+workspaces@0.9.0_@effected+jsonc@0.5.1_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/WorkspaceRoot.js
17278
17626
  /**
17279
17627
  * The marker filenames {@link WorkspaceRoot} probes for, in priority order.
17280
17628
  *
@@ -17461,7 +17809,7 @@ var WorkspaceRoot = class WorkspaceRoot extends effect.Context.Service()("@effec
17461
17809
  static layerTest = (root) => effect.Layer.effect(WorkspaceRoot, WorkspaceRoot.makeTest(root)).pipe(effect.Layer.provide(effect.Path.layer));
17462
17810
  };
17463
17811
  //#endregion
17464
- //#region ../../node_modules/.pnpm/@effected+workspaces@0.7.0_@effected+jsonc@0.5.1_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/internal/limits.js
17812
+ //#region ../../node_modules/.pnpm/@effected+workspaces@0.9.0_@effected+jsonc@0.5.1_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/internal/limits.js
17465
17813
  /**
17466
17814
  * Hard ceiling on directories the enumerator will visit for one pattern set.
17467
17815
  * Guards the pathological case a depth cap alone does not: a wide, shallow
@@ -17479,7 +17827,7 @@ const MAX_ENUMERATION_ENTRIES = 1e5;
17479
17827
  */
17480
17828
  const PRUNED_DIRECTORIES = /* @__PURE__ */ new Set([".git", "node_modules"]);
17481
17829
  //#endregion
17482
- //#region ../../node_modules/.pnpm/@effected+workspaces@0.7.0_@effected+jsonc@0.5.1_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/internal/traverse.js
17830
+ //#region ../../node_modules/.pnpm/@effected+workspaces@0.9.0_@effected+jsonc@0.5.1_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/internal/traverse.js
17483
17831
  /** Directory names never descended into. */
17484
17832
  const isPruned = (entry) => PRUNED_DIRECTORIES.has(entry);
17485
17833
  /** Join root-relative POSIX segments; `""` is the root itself. */
@@ -17569,7 +17917,7 @@ var Traversal = class {
17569
17917
  }
17570
17918
  };
17571
17919
  //#endregion
17572
- //#region ../../node_modules/.pnpm/@effected+workspaces@0.7.0_@effected+jsonc@0.5.1_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/internal/enumerate.js
17920
+ //#region ../../node_modules/.pnpm/@effected+workspaces@0.9.0_@effected+jsonc@0.5.1_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/internal/enumerate.js
17573
17921
  /** Strip a trailing slash from `GlobPattern.enumerationPrefix` to get a relative directory. */
17574
17922
  const baseOf = (pattern) => pattern.enumerationPrefix.replace(/\/$/, "");
17575
17923
  /**
@@ -17639,7 +17987,7 @@ const enumerate = (root, globs, options) => effect.Effect.gen(function* () {
17639
17987
  return results;
17640
17988
  });
17641
17989
  //#endregion
17642
- //#region ../../node_modules/.pnpm/@effected+workspaces@0.7.0_@effected+jsonc@0.5.1_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/internal/patterns.js
17990
+ //#region ../../node_modules/.pnpm/@effected+workspaces@0.9.0_@effected+jsonc@0.5.1_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/internal/patterns.js
17643
17991
  const stringsOf = (value) => Array.isArray(value) ? value.filter((entry) => typeof entry === "string") : void 0;
17644
17992
  /** The `packages:` list of a `pnpm-workspace.yaml` document. Total on a parsed document. */
17645
17993
  const pnpmPatternsOf = (document) => {
@@ -17696,7 +18044,7 @@ const readPatterns = (root) => effect.Effect.gen(function* () {
17696
18044
  return manifestPatternsOf(manifest);
17697
18045
  });
17698
18046
  //#endregion
17699
- //#region ../../node_modules/.pnpm/@effected+workspaces@0.7.0_@effected+jsonc@0.5.1_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/WorkspaceDiscovery.js
18047
+ //#region ../../node_modules/.pnpm/@effected+workspaces@0.9.0_@effected+jsonc@0.5.1_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/WorkspaceDiscovery.js
17700
18048
  /**
17701
18049
  * Raised when a workspace member's `package.json` cannot be read, parsed, or
17702
18050
  * used — it is missing, malformed, or lacks a `name` or `version`.
@@ -18130,7 +18478,7 @@ var WorkspaceDiscovery = class WorkspaceDiscovery extends effect.Context.Service
18130
18478
  };
18131
18479
  const isStringRecord$2 = (value) => value !== null && typeof value === "object" && !Array.isArray(value) && Object.values(value).every((entry) => typeof entry === "string");
18132
18480
  //#endregion
18133
- //#region ../../node_modules/.pnpm/@effected+workspaces@0.7.0_@effected+jsonc@0.5.1_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/DependencyGraph.js
18481
+ //#region ../../node_modules/.pnpm/@effected+workspaces@0.9.0_@effected+jsonc@0.5.1_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/DependencyGraph.js
18134
18482
  /**
18135
18483
  * Raised when the workspace dependency graph cannot be topologically ordered
18136
18484
  * because it contains a cycle.
@@ -18365,7 +18713,7 @@ const kahn = (edges) => {
18365
18713
  };
18366
18714
  };
18367
18715
  //#endregion
18368
- //#region ../../node_modules/.pnpm/@effected+git@0.4.2_effect@4.0.0-beta.101/node_modules/@effected/git/GitCommand.js
18716
+ //#region ../../node_modules/.pnpm/@effected+git@0.5.1_effect@4.0.0-beta.101/node_modules/@effected/git/GitCommand.js
18369
18717
  /**
18370
18718
  * Builds a `git` `ChildProcess.StandardCommand` with the argv this package
18371
18719
  * classifies against.
@@ -18388,25 +18736,7 @@ const git = (args) => effect_unstable_process.ChildProcess.make("git", args, {
18388
18736
  env: { LC_ALL: "C" },
18389
18737
  extendEnv: true
18390
18738
  });
18391
- /**
18392
- * `git show <ref>:<path>` — the contents of `path` as it existed at `ref`,
18393
- * without checking anything out.
18394
- *
18395
- * @public
18396
- */
18397
18739
  const show = (ref, path) => git(["show", `${ref}:${path}`]);
18398
- /**
18399
- * `git ls-tree -r -z <ref> [-- <pathspec>...]` — every path in the tree at
18400
- * `ref`, recursively, NUL-terminated, optionally scoped to `pathspec`.
18401
- *
18402
- * @remarks
18403
- * `-z` is load-bearing: git paths may themselves contain newlines, so the
18404
- * caller must split on `"\0"`, never on `"\n"`. When `pathspec` is provided,
18405
- * a literal `--` separator is inserted before the pathspec entries to prevent
18406
- * git from interpreting pathspec values as options.
18407
- *
18408
- * @public
18409
- */
18410
18740
  const lsTree = (ref, pathspec = []) => git([
18411
18741
  "ls-tree",
18412
18742
  "-r",
@@ -18414,48 +18744,16 @@ const lsTree = (ref, pathspec = []) => git([
18414
18744
  ref,
18415
18745
  ...pathspec.length > 0 ? ["--", ...pathspec] : []
18416
18746
  ]);
18417
- /**
18418
- * `git cat-file -e <ref>` — checks whether `ref` resolves to an existing
18419
- * object, without printing it. A non-zero exit means the ref does not exist.
18420
- *
18421
- * @public
18422
- */
18423
18747
  const refExists = (ref) => git([
18424
18748
  "cat-file",
18425
18749
  "-e",
18426
18750
  ref
18427
18751
  ]);
18428
- /**
18429
- * `git merge-base <a> <b>` — the best common ancestor commit of `a` and `b`.
18430
- *
18431
- * @public
18432
- */
18433
18752
  const mergeBase = (a, b) => git([
18434
18753
  "merge-base",
18435
18754
  a,
18436
18755
  b
18437
18756
  ]);
18438
- /**
18439
- * `git diff --name-only -z [--relative] <base>...<head>` — the paths that
18440
- * differ between the merge base of `base` and `head`, and `head` itself,
18441
- * NUL-terminated.
18442
- *
18443
- * @remarks
18444
- * `-z` is load-bearing here too, for the same reason as {@link GitCommand.lsTree}: split
18445
- * the output on `"\0"`, never on `"\n"`.
18446
- *
18447
- * The relative flag is **explicit in both branches** — `--relative` when
18448
- * `relative` is true, `--no-relative` when false — never omitted. git honors a
18449
- * configured `diff.relative=true` when no flag is passed, so an omitted flag
18450
- * would silently yield cwd-relative paths on such a machine even for
18451
- * `relative: false`, misaligning with {@link GitCommand.untrackedFiles}'s
18452
- * repo-root base and breaking `Git.workingChanges`' dedup in a nested workspace.
18453
- * `--relative` scopes the report to `cwd` (a workspace nested inside a larger
18454
- * repository); `--no-relative` overrides any `diff.relative` config and reports
18455
- * paths from the repository top-level.
18456
- *
18457
- * @public
18458
- */
18459
18757
  const changedFiles = (base, head, relative = false) => git([
18460
18758
  "diff",
18461
18759
  "--name-only",
@@ -18463,35 +18761,12 @@ const changedFiles = (base, head, relative = false) => git([
18463
18761
  relative ? "--relative" : "--no-relative",
18464
18762
  `${base}...${head}`
18465
18763
  ]);
18466
- /**
18467
- * `git diff --name-only -z (--relative | --no-relative)` — the paths with
18468
- * unstaged working-tree changes (the working tree against the index),
18469
- * NUL-terminated.
18470
- *
18471
- * @remarks
18472
- * `relative` behaves as it does for {@link GitCommand.changedFiles}, including the
18473
- * explicit-flag-in-both-branches rule: `--no-relative` is passed for
18474
- * `relative: false` so a configured `diff.relative=true` cannot silently make the
18475
- * output cwd-relative.
18476
- *
18477
- * @public
18478
- */
18479
18764
  const unstagedChanges = (relative = false) => git([
18480
18765
  "diff",
18481
18766
  "--name-only",
18482
18767
  "-z",
18483
18768
  relative ? "--relative" : "--no-relative"
18484
18769
  ]);
18485
- /**
18486
- * `git diff --name-only -z (--relative | --no-relative) --cached` — the paths
18487
- * staged for the next commit (the index against `HEAD`), NUL-terminated.
18488
- *
18489
- * @remarks
18490
- * `relative` behaves as it does for {@link GitCommand.changedFiles}, including the
18491
- * explicit `--no-relative` on the `relative: false` branch.
18492
- *
18493
- * @public
18494
- */
18495
18770
  const stagedChanges = (relative = false) => git([
18496
18771
  "diff",
18497
18772
  "--name-only",
@@ -18499,19 +18774,6 @@ const stagedChanges = (relative = false) => git([
18499
18774
  relative ? "--relative" : "--no-relative",
18500
18775
  "--cached"
18501
18776
  ]);
18502
- /**
18503
- * `git ls-files --others --exclude-standard -z [--full-name]` — the untracked
18504
- * paths git is not ignoring, NUL-terminated.
18505
- *
18506
- * @remarks
18507
- * `ls-files` reports paths relative to `cwd` by default, matching the
18508
- * `--relative` diffs. When `relative` is `false`, `--full-name` makes it emit
18509
- * repo-root-relative paths instead, so the untracked half shares a base with the
18510
- * un-`--relative` diffs — otherwise `Git.workingChanges`'s union would dedup two
18511
- * spellings of one file from a nested `cwd`.
18512
- *
18513
- * @public
18514
- */
18515
18777
  const untrackedFiles = (relative = false) => git([
18516
18778
  "ls-files",
18517
18779
  "--others",
@@ -18519,35 +18781,16 @@ const untrackedFiles = (relative = false) => git([
18519
18781
  "-z",
18520
18782
  ...relative ? [] : ["--full-name"]
18521
18783
  ]);
18522
- /**
18523
- * `git rev-parse --verify <ref>` — resolves `ref` to its full object id, or
18524
- * fails if `ref` does not resolve.
18525
- *
18526
- * @public
18527
- */
18528
18784
  const revParse = (ref) => git([
18529
18785
  "rev-parse",
18530
18786
  "--verify",
18531
18787
  ref
18532
18788
  ]);
18533
- /**
18534
- * Mutating: `git checkout [--detach] <ref>` — moves the working tree (and, for
18535
- * a branch ref, `HEAD`) to `ref`. When `detach` is true, checks out the ref in
18536
- * detached-HEAD state.
18537
- *
18538
- * @public
18539
- */
18540
18789
  const checkout = (ref, detach = false) => git([
18541
18790
  "checkout",
18542
18791
  ...detach ? ["--detach"] : [],
18543
18792
  ref
18544
18793
  ]);
18545
- /**
18546
- * Mutating: `git fetch [--depth <n>] <remote> [tag] <ref>` — fetches the given
18547
- * ref from a remote, optionally with a depth limit and the `tag` keyword.
18548
- *
18549
- * @public
18550
- */
18551
18794
  const fetch$1 = (remote, ref, depth, tag = false) => git([
18552
18795
  "fetch",
18553
18796
  ...depth !== void 0 ? ["--depth", String(depth)] : [],
@@ -18555,14 +18798,6 @@ const fetch$1 = (remote, ref, depth, tag = false) => git([
18555
18798
  ...tag ? ["tag"] : [],
18556
18799
  ref
18557
18800
  ]);
18558
- /**
18559
- * Mutating: `git submodule update [--init] [--depth <n>] [-- <paths>...]` — updates
18560
- * registered submodules, optionally initializing them, with an optional depth limit,
18561
- * and scoped to specific paths. The literal `--` separator makes the pathspec
18562
- * injection-safe by construction.
18563
- *
18564
- * @public
18565
- */
18566
18801
  const submoduleUpdate = (init = false, depth, paths = []) => git([
18567
18802
  "submodule",
18568
18803
  "update",
@@ -18570,13 +18805,6 @@ const submoduleUpdate = (init = false, depth, paths = []) => git([
18570
18805
  ...depth !== void 0 ? ["--depth", String(depth)] : [],
18571
18806
  ...paths.length > 0 ? ["--", ...paths] : []
18572
18807
  ]);
18573
- /**
18574
- * Mutating: `git submodule add [--depth <n>] -- <url> <path>` — registers and
18575
- * initializes a new submodule. The literal `--` separator makes the url and path
18576
- * injection-safe by construction.
18577
- *
18578
- * @public
18579
- */
18580
18808
  const submoduleAdd = (url, path, depth) => git([
18581
18809
  "submodule",
18582
18810
  "add",
@@ -18585,57 +18813,23 @@ const submoduleAdd = (url, path, depth) => git([
18585
18813
  url,
18586
18814
  path
18587
18815
  ]);
18588
- /**
18589
- * Mutating: `git sparse-checkout set (--cone | --no-cone) <patterns...>` — configures
18590
- * which paths are checked out in a sparse repository. The cone flag is explicit in both
18591
- * branches — `--cone` when `cone` is true, `--no-cone` when false — to prevent git's
18592
- * default from silently changing the behavior.
18593
- *
18594
- * @public
18595
- */
18596
18816
  const sparseCheckoutSet = (patterns, cone) => git([
18597
18817
  "sparse-checkout",
18598
18818
  "set",
18599
18819
  cone ? "--cone" : "--no-cone",
18600
18820
  ...patterns
18601
18821
  ]);
18602
- /**
18603
- * Mutating: `git config [-f <file>] <key> <value>` — writes a configuration value,
18604
- * optionally into an explicit configuration file (e.g., `.gitmodules`).
18605
- *
18606
- * @public
18607
- */
18608
18822
  const configSet = (key, value, file) => git([
18609
18823
  "config",
18610
18824
  ...file !== void 0 ? ["-f", file] : [],
18611
18825
  key,
18612
18826
  value
18613
18827
  ]);
18614
- /**
18615
- * Mutating: `git add -- <paths...>` — stages the given paths for commit. The literal
18616
- * `--` separator makes the pathspec injection-safe by construction.
18617
- *
18618
- * @public
18619
- */
18620
18828
  const add = (paths) => git([
18621
18829
  "add",
18622
18830
  "--",
18623
18831
  ...paths
18624
18832
  ]);
18625
- /**
18626
- * `git diff --name-status -z (--relative | --no-relative) [<base> | <base>...<head>]`
18627
- * — the changed paths WITH their one-letter status codes, NUL-terminated.
18628
- *
18629
- * @remarks
18630
- * With `head` omitted this is the single-argument diff form: the working tree
18631
- * (staged + unstaged) against `base` — NOT a two-ref range. With `head`
18632
- * present it is the familiar `base...head` merge-base form, matching
18633
- * {@link GitCommand.changedFiles}. `-z` and the explicit relative flag follow
18634
- * the same rules as {@link GitCommand.changedFiles}. In `-z` mode a rename or
18635
- * copy entry is THREE NUL tokens: `R<score>`, the old path, the new path.
18636
- *
18637
- * @public
18638
- */
18639
18833
  const nameStatus = (base, head, relative = false) => git([
18640
18834
  "diff",
18641
18835
  "--name-status",
@@ -18643,103 +18837,34 @@ const nameStatus = (base, head, relative = false) => git([
18643
18837
  relative ? "--relative" : "--no-relative",
18644
18838
  head === void 0 ? base : `${base}...${head}`
18645
18839
  ]);
18646
- /**
18647
- * `git symbolic-ref --quiet --short refs/remotes/<remote>/HEAD` — the name of
18648
- * the default branch on the given remote, or empty string / exit 1 if unset.
18649
- *
18650
- * @remarks
18651
- * `--quiet` suppresses error messages; the exit code alone signals success
18652
- * (0) or "symbolic-ref does not exist" (1). The contract is "does the remote
18653
- * have a HEAD?" — an unset symbolic ref exits 1 silently, which `Git.defaultBranch`
18654
- * degrades to `Option.none()` rather than a typed error. `symbolic-ref` is a
18655
- * purely local ref lookup; it never touches the network.
18656
- *
18657
- * @public
18658
- */
18659
18840
  const defaultBranch = (remote = "origin") => git([
18660
18841
  "symbolic-ref",
18661
18842
  "--quiet",
18662
18843
  "--short",
18663
18844
  `refs/remotes/${remote}/HEAD`
18664
18845
  ]);
18665
- /**
18666
- * `git rev-parse --abbrev-ref HEAD` — the name of the branch `HEAD` is
18667
- * pointing to.
18668
- *
18669
- * @remarks
18670
- * Returns `"HEAD"` (detached state), `"<branch>"` (an attached branch), or
18671
- * fails if the repository has no commits.
18672
- *
18673
- * @public
18674
- */
18675
18846
  const currentBranch = () => git([
18676
18847
  "rev-parse",
18677
18848
  "--abbrev-ref",
18678
18849
  "HEAD"
18679
18850
  ]);
18680
- /**
18681
- * `git rev-parse --show-toplevel` — the filesystem path to the root of the
18682
- * enclosing git repository.
18683
- *
18684
- * @public
18685
- */
18686
18851
  const repoRoot = () => git(["rev-parse", "--show-toplevel"]);
18687
- /**
18688
- * `git log -1 --format=%H%x00%G?%x00%B <ref>` — a NUL-separated triple: the
18689
- * full commit hash, the GPG trust level, and the full commit body (message),
18690
- * all untrimmed.
18691
- *
18692
- * @remarks
18693
- * `%H` is the full object id (40-char sha1, or sha256 if configured).
18694
- * `%x00` is a literal NUL byte (the separator). `%G?` is the GPG trust level
18695
- * (`G` = good signature, `B` = bad, `U` = untrusted, `X` = expired, `Y` =
18696
- * expired key, `R` = revoked key, `E` = error, or `N` = not signed).
18697
- * `%B` is the full body, **untrimmed** — it includes leading/trailing
18698
- * whitespace — so the caller must decide whether to trim it. Splits on the
18699
- * two `\x00` bytes to extract all three values.
18700
- *
18701
- * @public
18702
- */
18703
18852
  const commitInfo = (ref = "HEAD") => git([
18704
18853
  "log",
18705
18854
  "-1",
18706
18855
  "--format=%H%x00%G?%x00%B",
18707
18856
  ref
18708
18857
  ]);
18709
- /**
18710
- * `git config --get <key>` — the value of the given git config key, or empty
18711
- * string / exit 1 if unset.
18712
- *
18713
- * @public
18714
- */
18715
18858
  const configGet = (key) => git([
18716
18859
  "config",
18717
18860
  "--get",
18718
18861
  key
18719
18862
  ]);
18720
- /**
18721
- * `git remote get-url <remote>` — the fetch URL of the given remote. A
18722
- * missing remote exits non-zero with a "No such remote" stderr shape, which
18723
- * the `Git` service degrades to `Option.none`, never a typed error.
18724
- *
18725
- * @public
18726
- */
18727
18863
  const remoteUrl = (remote = "origin") => git([
18728
18864
  "remote",
18729
18865
  "get-url",
18730
18866
  remote
18731
18867
  ]);
18732
- /**
18733
- * `git status --porcelain -z` — the porcelain (stable, machine-readable) short
18734
- * status of every modified file in the working tree, NUL-terminated.
18735
- *
18736
- * @remarks
18737
- * `-z` is load-bearing here too, for the same reason as
18738
- * {@link GitCommand.lsTree}: split the output on `"\0"`, never on `"\n"`.
18739
- * Each entry is a pair of status codes followed by a space and the path.
18740
- *
18741
- * @public
18742
- */
18743
18868
  const status = () => git([
18744
18869
  "status",
18745
18870
  "--porcelain",
@@ -18757,34 +18882,210 @@ const status = () => git([
18757
18882
  *
18758
18883
  * @public
18759
18884
  */
18760
- const GitCommand = {
18761
- show,
18762
- lsTree,
18763
- refExists,
18764
- mergeBase,
18765
- changedFiles,
18766
- unstagedChanges,
18767
- stagedChanges,
18768
- untrackedFiles,
18769
- revParse,
18770
- checkout,
18771
- fetch: fetch$1,
18772
- submoduleUpdate,
18773
- submoduleAdd,
18774
- sparseCheckoutSet,
18775
- configSet,
18776
- add,
18777
- nameStatus,
18778
- defaultBranch,
18779
- currentBranch,
18780
- repoRoot,
18781
- commitInfo,
18782
- configGet,
18783
- remoteUrl,
18784
- status
18885
+ var GitCommand = class {
18886
+ constructor() {}
18887
+ /**
18888
+ * `git show <ref>:<path>` — the contents of `path` as it existed at `ref`,
18889
+ * without checking anything out.
18890
+ */
18891
+ static show = show;
18892
+ /**
18893
+ * `git ls-tree -r -z <ref> [-- <pathspec>...]` — every path in the tree at
18894
+ * `ref`, recursively, NUL-terminated, optionally scoped to `pathspec`.
18895
+ *
18896
+ * @remarks
18897
+ * `-z` is load-bearing: git paths may themselves contain newlines, so the
18898
+ * caller must split on `"\0"`, never on `"\n"`. When `pathspec` is provided,
18899
+ * a literal `--` separator is inserted before the pathspec entries to prevent
18900
+ * git from interpreting pathspec values as options.
18901
+ */
18902
+ static lsTree = lsTree;
18903
+ /**
18904
+ * `git cat-file -e <ref>` — checks whether `ref` resolves to an existing
18905
+ * object, without printing it. A non-zero exit means the ref does not exist.
18906
+ */
18907
+ static refExists = refExists;
18908
+ /**
18909
+ * `git merge-base <a> <b>` — the best common ancestor commit of `a` and `b`.
18910
+ */
18911
+ static mergeBase = mergeBase;
18912
+ /**
18913
+ * `git diff --name-only -z [--relative] <base>...<head>` — the paths that
18914
+ * differ between the merge base of `base` and `head`, and `head` itself,
18915
+ * NUL-terminated.
18916
+ *
18917
+ * @remarks
18918
+ * `-z` is load-bearing here too, for the same reason as {@link GitCommand.lsTree}: split
18919
+ * the output on `"\0"`, never on `"\n"`.
18920
+ *
18921
+ * The relative flag is **explicit in both branches** — `--relative` when
18922
+ * `relative` is true, `--no-relative` when false — never omitted. git honors a
18923
+ * configured `diff.relative=true` when no flag is passed, so an omitted flag
18924
+ * would silently yield cwd-relative paths on such a machine even for
18925
+ * `relative: false`, misaligning with {@link GitCommand.untrackedFiles}'s
18926
+ * repo-root base and breaking `Git.workingChanges`' dedup in a nested workspace.
18927
+ * `--relative` scopes the report to `cwd` (a workspace nested inside a larger
18928
+ * repository); `--no-relative` overrides any `diff.relative` config and reports
18929
+ * paths from the repository top-level.
18930
+ */
18931
+ static changedFiles = changedFiles;
18932
+ /**
18933
+ * `git diff --name-only -z (--relative | --no-relative)` — the paths with
18934
+ * unstaged working-tree changes (the working tree against the index),
18935
+ * NUL-terminated.
18936
+ *
18937
+ * @remarks
18938
+ * `relative` behaves as it does for {@link GitCommand.changedFiles}, including the
18939
+ * explicit-flag-in-both-branches rule: `--no-relative` is passed for
18940
+ * `relative: false` so a configured `diff.relative=true` cannot silently make the
18941
+ * output cwd-relative.
18942
+ */
18943
+ static unstagedChanges = unstagedChanges;
18944
+ /**
18945
+ * `git diff --name-only -z (--relative | --no-relative) --cached` — the paths
18946
+ * staged for the next commit (the index against `HEAD`), NUL-terminated.
18947
+ *
18948
+ * @remarks
18949
+ * `relative` behaves as it does for {@link GitCommand.changedFiles}, including the
18950
+ * explicit `--no-relative` on the `relative: false` branch.
18951
+ */
18952
+ static stagedChanges = stagedChanges;
18953
+ /**
18954
+ * `git ls-files --others --exclude-standard -z [--full-name]` — the untracked
18955
+ * paths git is not ignoring, NUL-terminated.
18956
+ *
18957
+ * @remarks
18958
+ * `ls-files` reports paths relative to `cwd` by default, matching the
18959
+ * `--relative` diffs. When `relative` is `false`, `--full-name` makes it emit
18960
+ * repo-root-relative paths instead, so the untracked half shares a base with the
18961
+ * un-`--relative` diffs — otherwise `Git.workingChanges`'s union would dedup two
18962
+ * spellings of one file from a nested `cwd`.
18963
+ */
18964
+ static untrackedFiles = untrackedFiles;
18965
+ /**
18966
+ * `git rev-parse --verify <ref>` — resolves `ref` to its full object id, or
18967
+ * fails if `ref` does not resolve.
18968
+ */
18969
+ static revParse = revParse;
18970
+ /**
18971
+ * Mutating: `git checkout [--detach] <ref>` — moves the working tree (and, for
18972
+ * a branch ref, `HEAD`) to `ref`. When `detach` is true, checks out the ref in
18973
+ * detached-HEAD state.
18974
+ */
18975
+ static checkout = checkout;
18976
+ /**
18977
+ * Mutating: `git fetch [--depth <n>] <remote> [tag] <ref>` — fetches the given
18978
+ * ref from a remote, optionally with a depth limit and the `tag` keyword.
18979
+ */
18980
+ static fetch = fetch$1;
18981
+ /**
18982
+ * Mutating: `git submodule update [--init] [--depth <n>] [-- <paths>...]` — updates
18983
+ * registered submodules, optionally initializing them, with an optional depth limit,
18984
+ * and scoped to specific paths. The literal `--` separator makes the pathspec
18985
+ * injection-safe by construction.
18986
+ */
18987
+ static submoduleUpdate = submoduleUpdate;
18988
+ /**
18989
+ * Mutating: `git submodule add [--depth <n>] -- <url> <path>` — registers and
18990
+ * initializes a new submodule. The literal `--` separator makes the url and path
18991
+ * injection-safe by construction.
18992
+ */
18993
+ static submoduleAdd = submoduleAdd;
18994
+ /**
18995
+ * Mutating: `git sparse-checkout set (--cone | --no-cone) <patterns...>` — configures
18996
+ * which paths are checked out in a sparse repository. The cone flag is explicit in both
18997
+ * branches — `--cone` when `cone` is true, `--no-cone` when false — to prevent git's
18998
+ * default from silently changing the behavior.
18999
+ */
19000
+ static sparseCheckoutSet = sparseCheckoutSet;
19001
+ /**
19002
+ * Mutating: `git config [-f <file>] <key> <value>` — writes a configuration value,
19003
+ * optionally into an explicit configuration file (e.g., `.gitmodules`).
19004
+ */
19005
+ static configSet = configSet;
19006
+ /**
19007
+ * Mutating: `git add -- <paths...>` — stages the given paths for commit. The literal
19008
+ * `--` separator makes the pathspec injection-safe by construction.
19009
+ */
19010
+ static add = add;
19011
+ /**
19012
+ * `git diff --name-status -z (--relative | --no-relative) [<base> | <base>...<head>]`
19013
+ * — the changed paths WITH their one-letter status codes, NUL-terminated.
19014
+ *
19015
+ * @remarks
19016
+ * With `head` omitted this is the single-argument diff form: the working tree
19017
+ * (staged + unstaged) against `base` — NOT a two-ref range. With `head`
19018
+ * present it is the familiar `base...head` merge-base form, matching
19019
+ * {@link GitCommand.changedFiles}. `-z` and the explicit relative flag follow
19020
+ * the same rules as {@link GitCommand.changedFiles}. In `-z` mode a rename or
19021
+ * copy entry is THREE NUL tokens: `R<score>`, the old path, the new path.
19022
+ */
19023
+ static nameStatus = nameStatus;
19024
+ /**
19025
+ * `git symbolic-ref --quiet --short refs/remotes/<remote>/HEAD` — the name of
19026
+ * the default branch on the given remote, or empty string / exit 1 if unset.
19027
+ *
19028
+ * @remarks
19029
+ * `--quiet` suppresses error messages; the exit code alone signals success
19030
+ * (0) or "symbolic-ref does not exist" (1). The contract is "does the remote
19031
+ * have a HEAD?" — an unset symbolic ref exits 1 silently, which `Git.defaultBranch`
19032
+ * degrades to `Option.none()` rather than a typed error. `symbolic-ref` is a
19033
+ * purely local ref lookup; it never touches the network.
19034
+ */
19035
+ static defaultBranch = defaultBranch;
19036
+ /**
19037
+ * `git rev-parse --abbrev-ref HEAD` — the name of the branch `HEAD` is
19038
+ * pointing to.
19039
+ *
19040
+ * @remarks
19041
+ * Returns `"HEAD"` (detached state), `"<branch>"` (an attached branch), or
19042
+ * fails if the repository has no commits.
19043
+ */
19044
+ static currentBranch = currentBranch;
19045
+ /**
19046
+ * `git rev-parse --show-toplevel` — the filesystem path to the root of the
19047
+ * enclosing git repository.
19048
+ */
19049
+ static repoRoot = repoRoot;
19050
+ /**
19051
+ * `git log -1 --format=%H%x00%G?%x00%B <ref>` — a NUL-separated triple: the
19052
+ * full commit hash, the GPG trust level, and the full commit body (message),
19053
+ * all untrimmed.
19054
+ *
19055
+ * @remarks
19056
+ * `%H` is the full object id (40-char sha1, or sha256 if configured).
19057
+ * `%x00` is a literal NUL byte (the separator). `%G?` is the GPG trust level
19058
+ * (`G` = good signature, `B` = bad, `U` = untrusted, `X` = expired, `Y` =
19059
+ * expired key, `R` = revoked key, `E` = error, or `N` = not signed).
19060
+ * `%B` is the full body, **untrimmed** — it includes leading/trailing
19061
+ * whitespace — so the caller must decide whether to trim it. Splits on the
19062
+ * two `\x00` bytes to extract all three values.
19063
+ */
19064
+ static commitInfo = commitInfo;
19065
+ /**
19066
+ * `git config --get <key>` — the value of the given git config key, or empty
19067
+ * string / exit 1 if unset.
19068
+ */
19069
+ static configGet = configGet;
19070
+ /**
19071
+ * `git remote get-url <remote>` — the fetch URL of the given remote. A
19072
+ * missing remote exits non-zero with a "No such remote" stderr shape, which
19073
+ * the `Git` service degrades to `Option.none`, never a typed error.
19074
+ */
19075
+ static remoteUrl = remoteUrl;
19076
+ /**
19077
+ * `git status --porcelain -z` — the porcelain (stable, machine-readable) short
19078
+ * status of every modified file in the working tree, NUL-terminated.
19079
+ *
19080
+ * @remarks
19081
+ * `-z` is load-bearing here too, for the same reason as
19082
+ * {@link GitCommand.lsTree}: split the output on `"\0"`, never on `"\n"`.
19083
+ * Each entry is a pair of status codes followed by a space and the path.
19084
+ */
19085
+ static status = status;
18785
19086
  };
18786
19087
  //#endregion
18787
- //#region ../../node_modules/.pnpm/@effected+git@0.4.2_effect@4.0.0-beta.101/node_modules/@effected/git/internal/run.js
19088
+ //#region ../../node_modules/.pnpm/@effected+git@0.5.1_effect@4.0.0-beta.101/node_modules/@effected/git/internal/run.js
18788
19089
  /**
18789
19090
  * Spawns `command` and collects its stdout, stderr, and exit code as a single
18790
19091
  * triple.
@@ -18811,7 +19112,7 @@ const runCollected = (command) => effect.Effect.scoped(effect.Effect.gen(functio
18811
19112
  };
18812
19113
  }));
18813
19114
  //#endregion
18814
- //#region ../../node_modules/.pnpm/@effected+git@0.4.2_effect@4.0.0-beta.101/node_modules/@effected/git/Git.js
19115
+ //#region ../../node_modules/.pnpm/@effected+git@0.5.1_effect@4.0.0-beta.101/node_modules/@effected/git/Git.js
18815
19116
  /** git's own ceiling: a run that has not answered in 30s is not going to. */
18816
19117
  const GIT_TIMEOUT = effect.Duration.seconds(30);
18817
19118
  /**
@@ -19698,6 +19999,12 @@ const make = (spawner) => {
19698
19999
  };
19699
20000
  };
19700
20001
  /**
20002
+ * The default for every {@link Git.makeTest} method a test did not stub: a
20003
+ * defect naming the method, so an unexercised call fails loudly instead of
20004
+ * succeeding with a lie or failing with a dishonest typed error.
20005
+ */
20006
+ const notStubbed = (method) => () => effect.Effect.die(/* @__PURE__ */ new Error(`Git.makeTest: ${method}() was called but not stubbed — no honest default exists for a test double; pass a \`${method}\` override.`));
20007
+ /**
19701
20008
  * Typed git introspection over core's `ChildProcessSpawner`: read a
19702
20009
  * repository's state at any ref without checking it out, plus the mutating
19703
20010
  * tier (`checkout`, `fetch`, `fetchAny`, `submoduleUpdate`, `submoduleAdd`,
@@ -19720,15 +20027,102 @@ const make = (spawner) => {
19720
20027
  *
19721
20028
  * @public
19722
20029
  */
19723
- var Git = class extends effect.Context.Service()("@effected/git/Git") {
20030
+ var Git = class Git extends effect.Context.Service()("@effected/git/Git") {
19724
20031
  /** Resolves `ChildProcessSpawner` once, at construction — every method's `R` is `never`. */
19725
20032
  static layer = effect.Layer.effect(this, effect.Effect.gen(function* () {
19726
20033
  const spawner = yield* effect_unstable_process.ChildProcessSpawner.ChildProcessSpawner;
19727
20034
  return make(spawner);
19728
20035
  }));
20036
+ /**
20037
+ * An in-memory test double of the service shape: stub only the methods the
20038
+ * test exercises, every other method **dies** with a defect naming itself.
20039
+ *
20040
+ * @remarks
20041
+ * Unlike `WorkspaceDiscovery.makeTest`, **no method here has an honest
20042
+ * default** — the shape is twenty-six unrelated git operations, and a
20043
+ * fabricated answer for any of them (an empty tree, a made-up sha, a silent
20044
+ * no-op `checkout`) would leak into consumer logic as fact. So every
20045
+ * unstubbed method fails loudly as a defect
20046
+ * (`Git.makeTest: <name>() was called but not stubbed`) rather than
20047
+ * succeeding with a lie or failing with a dishonest typed error — which is
20048
+ * also what makes the double a proof that a test touches *nothing but* the
20049
+ * methods it stubbed.
20050
+ *
20051
+ * The double deliberately models **none** of the live service's semantics:
20052
+ * no stderr classification, no option-injection guard (an option-like ref a
20053
+ * stub accepts would be refused live), no `LC_ALL=C` pinning, no timeout,
20054
+ * and no `./`-vs-bare path resolution on `show` — a stub answers exactly
20055
+ * what it is told and nothing else. A suite exercising any of those wants
20056
+ * `Git.layer` over a mocked `ChildProcessSpawner` (or real git) instead.
20057
+ *
20058
+ * @example
20059
+ * ```ts
20060
+ * import { Git } from "@effected/git";
20061
+ * import { Effect, Option } from "effect";
20062
+ *
20063
+ * const double = Git.makeTest({
20064
+ * show: (_cwd, _ref, path) =>
20065
+ * Effect.succeed(path === "./package.json" ? Option.some("{}") : Option.none()),
20066
+ * });
20067
+ * // `double.show(...)` answers; `double.status(...)` dies, named.
20068
+ * ```
20069
+ */
20070
+ static makeTest = (overrides = {}) => ({
20071
+ show: notStubbed("show"),
20072
+ lsTree: notStubbed("lsTree"),
20073
+ refExists: notStubbed("refExists"),
20074
+ mergeBase: notStubbed("mergeBase"),
20075
+ changedFiles: notStubbed("changedFiles"),
20076
+ workingChanges: notStubbed("workingChanges"),
20077
+ revParse: notStubbed("revParse"),
20078
+ checkout: notStubbed("checkout"),
20079
+ fetch: notStubbed("fetch"),
20080
+ fetchAny: notStubbed("fetchAny"),
20081
+ submoduleUpdate: notStubbed("submoduleUpdate"),
20082
+ submoduleAdd: notStubbed("submoduleAdd"),
20083
+ sparseCheckoutSet: notStubbed("sparseCheckoutSet"),
20084
+ configSet: notStubbed("configSet"),
20085
+ add: notStubbed("add"),
20086
+ nameStatus: notStubbed("nameStatus"),
20087
+ unstagedChanges: notStubbed("unstagedChanges"),
20088
+ stagedChanges: notStubbed("stagedChanges"),
20089
+ untrackedFiles: notStubbed("untrackedFiles"),
20090
+ defaultBranch: notStubbed("defaultBranch"),
20091
+ currentBranch: notStubbed("currentBranch"),
20092
+ repoRoot: notStubbed("repoRoot"),
20093
+ configGet: notStubbed("configGet"),
20094
+ remoteUrl: notStubbed("remoteUrl"),
20095
+ commitInfo: notStubbed("commitInfo"),
20096
+ status: notStubbed("status"),
20097
+ ...overrides
20098
+ });
20099
+ /**
20100
+ * The test layer: {@link Git.makeTest} behind `Layer.succeed`, so a suite
20101
+ * provides only the methods it exercises.
20102
+ *
20103
+ * @remarks
20104
+ * A parameterized layer factory mints a **fresh reference per call**, and
20105
+ * layers memoize by reference — bind the result to a `const` and reuse it
20106
+ * rather than calling `layerTest(...)` at each composition site.
20107
+ *
20108
+ * @example
20109
+ * ```ts
20110
+ * import { Git, LsTreeEntry } from "@effected/git";
20111
+ * import { Effect } from "effect";
20112
+ *
20113
+ * const TestGit = Git.layerTest({
20114
+ * lsTree: () =>
20115
+ * Effect.succeed([
20116
+ * LsTreeEntry.make({ mode: "100644", type: "blob", oid: "0".repeat(40), path: "package.json" }),
20117
+ * ]),
20118
+ * });
20119
+ * // program.pipe(Effect.provide(TestGit))
20120
+ * ```
20121
+ */
20122
+ static layerTest = (overrides = {}) => effect.Layer.succeed(Git, Git.makeTest(overrides));
19729
20123
  };
19730
20124
  //#endregion
19731
- //#region ../../node_modules/.pnpm/@effected+workspaces@0.7.0_@effected+jsonc@0.5.1_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/ChangeDetector.js
20125
+ //#region ../../node_modules/.pnpm/@effected+workspaces@0.9.0_@effected+jsonc@0.5.1_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/ChangeDetector.js
19732
20126
  /**
19733
20127
  * Which git refs to compare, and whether to fold in the working tree.
19734
20128
  *
@@ -19980,7 +20374,7 @@ function resolveFromCatalog(catalogs, wantedDependency) {
19980
20374
  };
19981
20375
  }
19982
20376
  //#endregion
19983
- //#region ../../node_modules/.pnpm/@effected+workspaces@0.7.0_@effected+jsonc@0.5.1_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/internal/catalogs.js
20377
+ //#region ../../node_modules/.pnpm/@effected+workspaces@0.9.0_@effected+jsonc@0.5.1_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/internal/catalogs.js
19984
20378
  /** Project a pnpm-workspace manifest's `catalog` / `catalogs` fields into a `Catalogs` map. */
19985
20379
  const inlineCatalogs = (manifest) => {
19986
20380
  if (manifest.catalog === void 0 && manifest.catalogs === void 0) return {};
@@ -20044,7 +20438,7 @@ const rangeOf = (catalogs, dependency, specifier) => {
20044
20438
  });
20045
20439
  };
20046
20440
  //#endregion
20047
- //#region ../../node_modules/.pnpm/@effected+workspaces@0.7.0_@effected+jsonc@0.5.1_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/ConfigDependencyHooks.js
20441
+ //#region ../../node_modules/.pnpm/@effected+workspaces@0.9.0_@effected+jsonc@0.5.1_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/ConfigDependencyHooks.js
20048
20442
  /** Whether `value` is a non-null, non-array object. */
20049
20443
  const isObject$2 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
20050
20444
  /**
@@ -20230,7 +20624,7 @@ var ConfigDependencyHooks = class ConfigDependencyHooks extends effect.Context.S
20230
20624
  }) });
20231
20625
  };
20232
20626
  //#endregion
20233
- //#region ../../node_modules/.pnpm/@effected+workspaces@0.7.0_@effected+jsonc@0.5.1_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/PackageManagerName.js
20627
+ //#region ../../node_modules/.pnpm/@effected+workspaces@0.9.0_@effected+jsonc@0.5.1_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/PackageManagerName.js
20234
20628
  /**
20235
20629
  * The four package managers this package understands.
20236
20630
  *
@@ -20331,7 +20725,11 @@ const CHECKED = [
20331
20725
  "bun.lock",
20332
20726
  "bun.lockb",
20333
20727
  "yarn.lock",
20334
- "package.json#workspaces"
20728
+ "package.json#workspaces",
20729
+ "pnpm-lock.yaml",
20730
+ "package-lock.json",
20731
+ "package.json#packageManager",
20732
+ "package.json#devEngines.packageManager"
20335
20733
  ];
20336
20734
  /**
20337
20735
  * Detects which package manager owns a workspace root.
@@ -20445,7 +20843,8 @@ var PackageManagerDetector = class PackageManagerDetector extends effect.Context
20445
20843
  version: versionFor(hints, "pnpm"),
20446
20844
  runtime: "node"
20447
20845
  });
20448
- if (((yield* has(root, "bun.lock")) || (yield* has(root, "bun.lockb"))) && namesManager(hints, "bun")) return DetectedPackageManager.make({
20846
+ const bunLock = (yield* has(root, "bun.lock")) || (yield* has(root, "bun.lockb"));
20847
+ if (bunLock && namesManager(hints, "bun")) return DetectedPackageManager.make({
20449
20848
  name: "bun",
20450
20849
  version: versionFor(hints, "bun"),
20451
20850
  runtime: "bun"
@@ -20461,6 +20860,35 @@ var PackageManagerDetector = class PackageManagerDetector extends effect.Context
20461
20860
  version: versionFor(hints, "npm"),
20462
20861
  runtime: "node"
20463
20862
  });
20863
+ if (yield* has(root, "pnpm-lock.yaml")) return DetectedPackageManager.make({
20864
+ name: "pnpm",
20865
+ version: versionFor(hints, "pnpm"),
20866
+ runtime: "node"
20867
+ });
20868
+ if (bunLock && namesManager(hints, "bun")) return DetectedPackageManager.make({
20869
+ name: "bun",
20870
+ version: versionFor(hints, "bun"),
20871
+ runtime: "bun"
20872
+ });
20873
+ if ((yield* has(root, "yarn.lock")) && namesManager(hints, "yarn")) return DetectedPackageManager.make({
20874
+ name: "yarn",
20875
+ version: versionFor(hints, "yarn"),
20876
+ runtime: "node"
20877
+ });
20878
+ if (yield* has(root, "package-lock.json")) return DetectedPackageManager.make({
20879
+ name: "npm",
20880
+ version: versionFor(hints, "npm"),
20881
+ runtime: "node"
20882
+ });
20883
+ const declared = declaredName(hints);
20884
+ if (effect.Option.isSome(declared)) {
20885
+ const name = declared.value;
20886
+ if (name === "pnpm" || name === "npm" || name === "yarn" || name === "bun") return DetectedPackageManager.make({
20887
+ name,
20888
+ version: versionFor(hints, name),
20889
+ runtime: name === "bun" ? "bun" : "node"
20890
+ });
20891
+ }
20464
20892
  return yield* effect.Effect.fail(new PackageManagerDetectionError({
20465
20893
  root,
20466
20894
  checked: CHECKED
@@ -20470,9 +20898,56 @@ var PackageManagerDetector = class PackageManagerDetector extends effect.Context
20470
20898
  });
20471
20899
  /** The live layer. */
20472
20900
  static layer = effect.Layer.effect(PackageManagerDetector, PackageManagerDetector.make);
20901
+ /**
20902
+ * The sanctioned in-memory double.
20903
+ *
20904
+ * @remarks
20905
+ * **`detect` has no honest default, so an unstubbed call dies** — the
20906
+ * `WorkspaceDiscovery.info` posture, for the same reason. A stand-in that
20907
+ * answered `"pnpm"` would hand a consumer a fact nothing established, and it
20908
+ * would contradict the very service it stands in for: the live detector's
20909
+ * defining property is that it [refuses to
20910
+ * guess](https://github.com/spencerbeggs/effected) when no evidence matches.
20911
+ * A double that guesses is worse than no double.
20912
+ *
20913
+ * Failing typed would be the subtler mistake: `PackageManagerDetectionError`
20914
+ * reads as a legitimate "no manager here" answer, so a consumer would branch
20915
+ * on it and proceed, never learning that the test simply forgot to stub.
20916
+ *
20917
+ * @param overrides - Members to supply; anything omitted dies on use.
20918
+ *
20919
+ * @example
20920
+ * ```ts
20921
+ * import { DetectedPackageManager, PackageManagerDetector } from "@effected/workspaces";
20922
+ * import { Effect, Option } from "effect";
20923
+ *
20924
+ * const TestDetector = PackageManagerDetector.layerTest({
20925
+ * detect: () =>
20926
+ * Effect.succeed(
20927
+ * DetectedPackageManager.make({ name: "pnpm", version: Option.none(), runtime: "node" }),
20928
+ * ),
20929
+ * });
20930
+ * ```
20931
+ */
20932
+ static makeTest = (overrides = {}) => ({
20933
+ detect: () => effect.Effect.die(/* @__PURE__ */ new Error("PackageManagerDetector.makeTest: detect() was called but not stubbed — no honest default DetectedPackageManager exists for a test double; pass a `detect` override.")),
20934
+ ...overrides
20935
+ });
20936
+ /**
20937
+ * {@link PackageManagerDetector.makeTest} behind `Layer.succeed`.
20938
+ *
20939
+ * @remarks
20940
+ * A parameterized layer factory mints a **fresh reference per call**, and
20941
+ * layers memoize by reference — bind the result to a `const` and reuse it
20942
+ * rather than calling `layerTest(...)` at each composition site.
20943
+ *
20944
+ * Pairs with `WorkspaceRoot.layerTest` and `WorkspaceDiscovery.layerTest` to
20945
+ * stand up the whole discovery path with no filesystem at all.
20946
+ */
20947
+ static layerTest = (overrides = {}) => effect.Layer.succeed(PackageManagerDetector, PackageManagerDetector.makeTest(overrides));
20473
20948
  };
20474
20949
  //#endregion
20475
- //#region ../../node_modules/.pnpm/@effected+workspaces@0.7.0_@effected+jsonc@0.5.1_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/LockfileReader.js
20950
+ //#region ../../node_modules/.pnpm/@effected+workspaces@0.9.0_@effected+jsonc@0.5.1_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/LockfileReader.js
20476
20951
  /**
20477
20952
  * Raised when the workspace's lockfile cannot be read off disk.
20478
20953
  *
@@ -20495,6 +20970,8 @@ var LockfileReadError = class extends effect.Schema.TaggedErrorClass()("Lockfile
20495
20970
  return `Cannot read ${this.format} lockfile at ${this.lockfilePath}`;
20496
20971
  }
20497
20972
  };
20973
+ /** A defect naming the unstubbed test-double method — a test-wiring mistake, not a typed failure. */
20974
+ const unstubbed$2 = (method) => effect.Effect.die(/* @__PURE__ */ new Error(`LockfileReader.makeTest: ${method}() was called but not stubbed — pass a \`${method}\` override.`));
20498
20975
  /**
20499
20976
  * Reads and parses the workspace's lockfile.
20500
20977
  *
@@ -20580,9 +21057,77 @@ var LockfileReader = class LockfileReader extends effect.Context.Service()("@eff
20580
21057
  * `const` and reuse it.
20581
21058
  */
20582
21059
  static layer = (options) => effect.Layer.effect(LockfileReader, LockfileReader.make(options));
21060
+ /**
21061
+ * A test double satisfying the full {@link LockfileReaderShape} with no
21062
+ * filesystem, root walk, or package-manager detection.
21063
+ *
21064
+ * @remarks
21065
+ * There is **no honest default lockfile**: an empty one that looks like a
21066
+ * legitimate answer is indistinguishable from "this workspace resolves
21067
+ * nothing" — the silent-empty failure class this package documents on the
21068
+ * live paths — so `read` **dies** with an instructive defect until stubbed.
21069
+ *
21070
+ * The one derivation mirrors `WorkspaceDiscovery.makeTest`'s
21071
+ * derived-from-the-primary rule: when a `read` override is supplied,
21072
+ * `resolvedVersion` answers as the live service does — the **first** entry
21073
+ * of `lockfile.packagesNamed(name)` in lockfile order, `Option.none()` on a
21074
+ * miss — so the two stay consistent by construction. `integrity` is **not**
21075
+ * derivable: the live method compares the lockfile against the workspace
21076
+ * manifests discovery enumerates, and the double has no discovery to ask, so
21077
+ * it dies unless stubbed.
21078
+ *
21079
+ * `refresh` defaults to `Effect.void` honestly: the live contract is "drop
21080
+ * the memoized read so the next call re-reads", and this double memoizes
21081
+ * nothing — every `read()` call re-invokes the override — so there is
21082
+ * nothing to drop and the no-op is truthful, the same reasoning as
21083
+ * `WorkspaceDiscovery.makeTest`'s `refresh`.
21084
+ *
21085
+ * @example
21086
+ * ```ts
21087
+ * import { Lockfile } from "@effected/lockfiles";
21088
+ * import { LockfileReader } from "@effected/workspaces";
21089
+ * import { Effect } from "effect";
21090
+ *
21091
+ * const double = LockfileReader.makeTest({
21092
+ * read: () =>
21093
+ * Effect.succeed(
21094
+ * Lockfile.make({ format: "pnpm", lockfileVersion: "9.0", packages: [], workspaceDependencies: [] }),
21095
+ * ),
21096
+ * });
21097
+ * // `resolvedVersion` now answers consistently from that lockfile.
21098
+ * ```
21099
+ */
21100
+ static makeTest = (overrides = {}) => {
21101
+ const read = overrides.read;
21102
+ return {
21103
+ read: () => unstubbed$2("read"),
21104
+ resolvedVersion: read !== void 0 ? (packageName) => effect.Effect.map(read(), (lockfile) => effect.Option.fromUndefinedOr(lockfile.packagesNamed(packageName)[0])) : () => unstubbed$2("resolvedVersion"),
21105
+ integrity: () => unstubbed$2("integrity"),
21106
+ refresh: () => effect.Effect.void,
21107
+ ...overrides
21108
+ };
21109
+ };
21110
+ /**
21111
+ * The test layer: {@link LockfileReader.makeTest} behind `Layer.succeed`, so
21112
+ * a suite provides only the methods it exercises.
21113
+ *
21114
+ * @remarks
21115
+ * A parameterized layer factory mints a **fresh reference per call**, and
21116
+ * layers memoize by reference — bind the result to a `const` and reuse it
21117
+ * rather than calling `layerTest(...)` at each composition site.
21118
+ *
21119
+ * @example
21120
+ * ```ts
21121
+ * import { LockfileReader } from "@effected/workspaces";
21122
+ *
21123
+ * const TestLockfiles = LockfileReader.layerTest();
21124
+ * // program.pipe(Effect.provide(TestLockfiles)) — dies loudly if touched.
21125
+ * ```
21126
+ */
21127
+ static layerTest = (overrides = {}) => effect.Layer.succeed(LockfileReader, LockfileReader.makeTest(overrides));
20583
21128
  };
20584
21129
  //#endregion
20585
- //#region ../../node_modules/.pnpm/@effected+workspaces@0.7.0_@effected+jsonc@0.5.1_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/Publishability.js
21130
+ //#region ../../node_modules/.pnpm/@effected+workspaces@0.9.0_@effected+jsonc@0.5.1_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/Publishability.js
20586
21131
  /** The public npm registry, used when `publishConfig.registry` says nothing. */
20587
21132
  const DEFAULT_REGISTRY = "https://registry.npmjs.org/";
20588
21133
  /**
@@ -20666,9 +21211,35 @@ var PublishTarget = class extends effect.Schema.Class("PublishTarget")({
20666
21211
  *
20667
21212
  * @public
20668
21213
  */
20669
- var PublishabilityDetector = class PublishabilityDetector extends effect.Context.Service()("@effected/workspaces/PublishabilityDetector") {
20670
- /** Standard npm publishing semantics. Pure — no filesystem, no platform services. */
20671
- static layer = effect.Layer.succeed(PublishabilityDetector, { detect: (pkg) => effect.Effect.sync(() => {
21214
+ var PublishabilityDetector = class extends effect.Context.Service()("@effected/workspaces/PublishabilityDetector") {
21215
+ /**
21216
+ * Standard npm publishing semantics, **as a value**. Pure no filesystem,
21217
+ * no platform services.
21218
+ *
21219
+ * @remarks
21220
+ * Exposed as a shape and not only as a layer, because a consumer composing
21221
+ * *around* these rules cannot reach them through a layer without re-entering
21222
+ * the very tag it is replacing. `@savvy-web/silk-effects` had to write
21223
+ * `Effect.provide(PublishabilityDetector, PublishabilityDetector.layer)`
21224
+ * **inside its own implementation of that tag** to get at this function for
21225
+ * its pass-through branch; with the value exposed that becomes
21226
+ * `PublishabilityDetector.npm.detect(pkg)`.
21227
+ *
21228
+ * @example
21229
+ * ```ts
21230
+ * import { PublishabilityDetector } from "@effected/workspaces";
21231
+ * import { Effect, Layer } from "effect";
21232
+ *
21233
+ * // A policy that defers to npm semantics for everything it does not veto.
21234
+ * const withVeto = Layer.succeed(PublishabilityDetector, {
21235
+ * detect: (pkg) =>
21236
+ * pkg.name.endsWith("-private")
21237
+ * ? Effect.succeed([])
21238
+ * : PublishabilityDetector.npm.detect(pkg),
21239
+ * });
21240
+ * ```
21241
+ */
21242
+ static npm = { detect: (pkg) => effect.Effect.sync(() => {
20672
21243
  const config = pkg.publishConfig;
20673
21244
  const access = config?.access;
20674
21245
  if (pkg.private && access === void 0) return [];
@@ -20679,10 +21250,36 @@ var PublishabilityDetector = class PublishabilityDetector extends effect.Context
20679
21250
  access: access ?? "public",
20680
21251
  provenance: false
20681
21252
  })];
20682
- }) });
21253
+ }) };
21254
+ /** Nothing publishes. */
21255
+ static none = { detect: () => effect.Effect.succeed([]) };
21256
+ /**
21257
+ * {@link PublishabilityDetector.npm} as a layer.
21258
+ *
21259
+ * @remarks
21260
+ * Named for its policy rather than called `layer`, deliberately. **No
21261
+ * composite in this package provides a publishability detector**: a
21262
+ * `Workspaces.layer()` that quietly supplied npm semantics made the choice
21263
+ * invisible, and worse, made a naively-ordered override lose to it in
21264
+ * silence — `Layer.mergeAll(myDetector, Workspaces.layer())` resolved to the
21265
+ * default, because `mergeAll` is last-wins. For a service that decides
21266
+ * whether a package publishes and to which registry, that silent revert was
21267
+ * the worst available failure. The requirement now sits in `R`, so the
21268
+ * choice is made once, explicitly, and unmade wiring does not compile.
21269
+ */
21270
+ static layerNpm = effect.Layer.succeed(this, this.npm);
21271
+ /**
21272
+ * {@link PublishabilityDetector.none} as a layer: a workspace where nothing
21273
+ * publishes.
21274
+ *
21275
+ * @remarks
21276
+ * For dry runs, and for a release tool whose configuration disables
21277
+ * publishing wholesale — silk's changeset `mode: "none"` is exactly this.
21278
+ */
21279
+ static layerNone = effect.Layer.succeed(this, this.none);
20683
21280
  };
20684
21281
  //#endregion
20685
- //#region ../../node_modules/.pnpm/@effected+workspaces@0.7.0_@effected+jsonc@0.5.1_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/internal/importerVersions.js
21282
+ //#region ../../node_modules/.pnpm/@effected+workspaces@0.9.0_@effected+jsonc@0.5.1_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/internal/importerVersions.js
20686
21283
  /**
20687
21284
  * Strip pnpm's peer-disambiguation suffix from a recorded importer version.
20688
21285
  *
@@ -20768,7 +21365,7 @@ const unanimousVersionOf = (index, dependency) => {
20768
21365
  return agreed;
20769
21366
  };
20770
21367
  //#endregion
20771
- //#region ../../node_modules/.pnpm/@effected+workspaces@0.7.0_@effected+jsonc@0.5.1_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/WorkspaceCatalogs.js
21368
+ //#region ../../node_modules/.pnpm/@effected+workspaces@0.9.0_@effected+jsonc@0.5.1_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/WorkspaceCatalogs.js
20772
21369
  /**
20773
21370
  * An immutable, fully-normalized catalog collection — the one catalog
20774
21371
  * resolution semantic in the package.
@@ -21044,6 +21641,8 @@ const validatePnpmWorkspaceCatalogs = (document) => {
21044
21641
  catalogs: "catalogs"
21045
21642
  }));
21046
21643
  };
21644
+ /** A defect naming the unstubbed test-double method — a test-wiring mistake, not a typed failure. */
21645
+ const unstubbed$1 = (method) => effect.Effect.die(/* @__PURE__ */ new Error(`WorkspaceCatalogs.makeTest: ${method}() was called but not stubbed — pass a \`${method}\` override.`));
21047
21646
  /**
21048
21647
  * Assembles a workspace's catalogs, package-manager-aware.
21049
21648
  *
@@ -21187,6 +21786,70 @@ var WorkspaceCatalogs = class WorkspaceCatalogs extends effect.Context.Service()
21187
21786
  */
21188
21787
  static layerWithConfigDependencies = (options) => effect.Layer.effect(WorkspaceCatalogs, WorkspaceCatalogs.make(options)).pipe(effect.Layer.provide(ConfigDependencyHooks.layerLive));
21189
21788
  /**
21789
+ * A test double satisfying the full {@link WorkspaceCatalogsShape} with no
21790
+ * filesystem, lockfile read, or hook replay.
21791
+ *
21792
+ * @remarks
21793
+ * There is **no honest default catalog set**: an empty `CatalogSet` that
21794
+ * looks like a legitimate answer is the "every dependency looks newly added"
21795
+ * failure class the live assembler hard-fails to prevent, so every method
21796
+ * **dies** with an instructive defect until stubbed — a test-wiring mistake
21797
+ * fails loudly as a defect rather than succeeding with a lie or failing with
21798
+ * a dishonest typed error.
21799
+ *
21800
+ * The one derivation mirrors `WorkspaceDiscovery.makeTest`'s
21801
+ * derived-from-the-primary rule: when a `set` override is supplied,
21802
+ * `resolveSpecifier` answers from that `CatalogSet`'s own
21803
+ * {@link CatalogSet.resolveSpecifier} — exactly what the live service runs
21804
+ * over its assembled set — so the two stay consistent by construction.
21805
+ * `releaseAgeGate` and `importerVersions` are **not** derivable from a
21806
+ * catalog set (the gate comes from release-age keys and hook contributions,
21807
+ * the importer index from the lockfile's importer blocks — neither is in a
21808
+ * `CatalogSet`) and always die unless stubbed.
21809
+ *
21810
+ * @example
21811
+ * ```ts
21812
+ * import { CatalogSet, WorkspaceCatalogs } from "@effected/workspaces";
21813
+ * import { Effect } from "effect";
21814
+ *
21815
+ * const double = WorkspaceCatalogs.makeTest({
21816
+ * set: () => Effect.succeed(CatalogSet.fromCatalogs({ default: { effect: "4.0.0" } })),
21817
+ * });
21818
+ * // `resolveSpecifier` now answers consistently from that set.
21819
+ * ```
21820
+ */
21821
+ static makeTest = (overrides = {}) => {
21822
+ const set = overrides.set;
21823
+ return {
21824
+ set: () => unstubbed$1("set"),
21825
+ resolveSpecifier: set !== void 0 ? (dependency, specifier) => effect.Effect.map(set(), (catalogs) => catalogs.resolveSpecifier(dependency, specifier)) : () => unstubbed$1("resolveSpecifier"),
21826
+ releaseAgeGate: () => unstubbed$1("releaseAgeGate"),
21827
+ importerVersions: () => unstubbed$1("importerVersions"),
21828
+ ...overrides
21829
+ };
21830
+ };
21831
+ /**
21832
+ * The test layer: {@link WorkspaceCatalogs.makeTest} behind `Layer.succeed`,
21833
+ * so a suite provides only the methods it exercises.
21834
+ *
21835
+ * @remarks
21836
+ * A parameterized layer factory mints a **fresh reference per call**, and
21837
+ * layers memoize by reference — bind the result to a `const` and reuse it
21838
+ * rather than calling `layerTest(...)` at each composition site.
21839
+ *
21840
+ * @example
21841
+ * ```ts
21842
+ * import { CatalogSet, WorkspaceCatalogs } from "@effected/workspaces";
21843
+ * import { Effect } from "effect";
21844
+ *
21845
+ * const TestCatalogs = WorkspaceCatalogs.layerTest({
21846
+ * set: () => Effect.succeed(CatalogSet.empty()),
21847
+ * });
21848
+ * // program.pipe(Effect.provide(TestCatalogs))
21849
+ * ```
21850
+ */
21851
+ static layerTest = (overrides = {}) => effect.Layer.succeed(WorkspaceCatalogs, WorkspaceCatalogs.makeTest(overrides));
21852
+ /**
21190
21853
  * The real implementation of `@effected/npm`'s `CatalogResolver` contract —
21191
21854
  * the one `@effected/package-json` declares but cannot fill.
21192
21855
  *
@@ -21211,7 +21874,7 @@ var WorkspaceCatalogs = class WorkspaceCatalogs extends effect.Context.Service()
21211
21874
  }));
21212
21875
  };
21213
21876
  //#endregion
21214
- //#region ../../node_modules/.pnpm/@effected+workspaces@0.7.0_@effected+jsonc@0.5.1_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/WorkspaceStateSnapshot.js
21877
+ //#region ../../node_modules/.pnpm/@effected+workspaces@0.9.0_@effected+jsonc@0.5.1_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/WorkspaceStateSnapshot.js
21215
21878
  const EMPTY = Object.freeze(Object.create(null));
21216
21879
  const DependencyMap = effect.Schema.Record(effect.Schema.String, effect.Schema.String).pipe(effect.Schema.withDecodingDefaultKey(effect.Effect.succeed(EMPTY)), effect.Schema.withConstructorDefault(effect.Effect.succeed(EMPTY)));
21217
21880
  /**
@@ -21434,7 +22097,7 @@ var WorkspaceStateSnapshot = class extends effect.Schema.Class("WorkspaceStateSn
21434
22097
  }
21435
22098
  };
21436
22099
  //#endregion
21437
- //#region ../../node_modules/.pnpm/@effected+workspaces@0.7.0_@effected+jsonc@0.5.1_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/WorkspaceSnapshots.js
22100
+ //#region ../../node_modules/.pnpm/@effected+workspaces@0.9.0_@effected+jsonc@0.5.1_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/WorkspaceSnapshots.js
21438
22101
  /** Whether `value` is a non-null, non-array object. */
21439
22102
  const isObject = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
21440
22103
  /** Whether every value in a record is a string — a usable dependency map. */
@@ -21493,6 +22156,8 @@ const EMPTY_LOCKFILE_RECORD = {
21493
22156
  catalogs: CatalogSet.empty(),
21494
22157
  importerVersions: {}
21495
22158
  };
22159
+ /** A defect naming the unstubbed test-double method — a test-wiring mistake, not a typed failure. */
22160
+ const unstubbed = (method) => effect.Effect.die(/* @__PURE__ */ new Error(`WorkspaceSnapshots.makeTest: ${method}() was called but not stubbed — pass a \`${method}\` override.`));
21496
22161
  /**
21497
22162
  * Reads workspace state at a git ref with no checkout, and the live worktree.
21498
22163
  *
@@ -21639,144 +22304,306 @@ var WorkspaceSnapshots = class WorkspaceSnapshots extends effect.Context.Service
21639
22304
  * `const` and reuse it, or layer memoization does not apply.
21640
22305
  */
21641
22306
  static layer = (options) => effect.Layer.effect(WorkspaceSnapshots, WorkspaceSnapshots.make(options));
22307
+ /**
22308
+ * A test double satisfying the full {@link WorkspaceSnapshotsShape} with no
22309
+ * git, filesystem, discovery, or catalog assembly.
22310
+ *
22311
+ * @remarks
22312
+ * There are **no honest defaults and no derivations** here: `at(ref)` and
22313
+ * `worktree()` are two independent reads of two different sources (a git ref
22314
+ * vs. the live tree), so neither can be honestly derived from the other, and
22315
+ * a fabricated empty {@link WorkspaceStateSnapshot} on either side of a
22316
+ * before/after diff reads as every dependency newly added or removed — the
22317
+ * exact silent-empty failure class this package documents on the live paths.
22318
+ * Both methods therefore **die** with an instructive defect until stubbed; a
22319
+ * test-wiring mistake fails loudly as a defect rather than succeeding with a
22320
+ * lie.
22321
+ *
22322
+ * @example
22323
+ * ```ts
22324
+ * import { CatalogSet, WorkspaceSnapshots, WorkspaceStateSnapshot } from "@effected/workspaces";
22325
+ * import { Effect } from "effect";
22326
+ *
22327
+ * const empty = WorkspaceStateSnapshot.make({
22328
+ * packages: [],
22329
+ * catalogs: CatalogSet.empty(),
22330
+ * importerVersions: {},
22331
+ * });
22332
+ * const double = WorkspaceSnapshots.makeTest({
22333
+ * at: () => Effect.succeed(empty),
22334
+ * worktree: () => Effect.succeed(empty),
22335
+ * });
22336
+ * ```
22337
+ */
22338
+ static makeTest = (overrides = {}) => ({
22339
+ at: () => unstubbed("at"),
22340
+ worktree: () => unstubbed("worktree"),
22341
+ ...overrides
22342
+ });
22343
+ /**
22344
+ * The test layer: {@link WorkspaceSnapshots.makeTest} behind `Layer.succeed`,
22345
+ * so a suite provides only the methods it exercises.
22346
+ *
22347
+ * @remarks
22348
+ * A parameterized layer factory mints a **fresh reference per call**, and
22349
+ * layers memoize by reference — bind the result to a `const` and reuse it
22350
+ * rather than calling `layerTest(...)` at each composition site.
22351
+ *
22352
+ * @example
22353
+ * ```ts
22354
+ * import { CatalogSet, WorkspaceSnapshots, WorkspaceStateSnapshot } from "@effected/workspaces";
22355
+ * import { Effect } from "effect";
22356
+ *
22357
+ * const TestSnapshots = WorkspaceSnapshots.layerTest({
22358
+ * worktree: () =>
22359
+ * Effect.succeed(
22360
+ * WorkspaceStateSnapshot.make({ packages: [], catalogs: CatalogSet.empty(), importerVersions: {} }),
22361
+ * ),
22362
+ * });
22363
+ * // program.pipe(Effect.provide(TestSnapshots))
22364
+ * ```
22365
+ */
22366
+ static layerTest = (overrides = {}) => effect.Layer.succeed(WorkspaceSnapshots, WorkspaceSnapshots.makeTest(overrides));
21642
22367
  };
21643
22368
  //#endregion
21644
- //#region ../../node_modules/.pnpm/@effected+workspaces@0.7.0_@effected+jsonc@0.5.1_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/Workspaces.js
21645
- /**
21646
- * Every service that needs only a filesystem: root, package-manager detection,
21647
- * discovery, lockfile reading, catalogs and publishability.
21648
- *
21649
- * @remarks
21650
- * Requires core `FileSystem` and `Path`, which the consumer provides at the
21651
- * edge (`@effect/platform-node`, `@effect/platform-bun`, or a test's
21652
- * `FileSystem.layerNoop`).
21653
- *
21654
- * **Bind the result to a `const`.** This is a parameterized factory and layers
21655
- * memoize by reference, so calling it twice builds everything twice.
21656
- *
21657
- * @example
21658
- * ```ts
21659
- * import { Workspaces } from "@effected/workspaces";
21660
- * import { Layer } from "effect";
21661
- *
21662
- * const WorkspacesLayer = Workspaces.layer();
21663
- * const AppLayer = Layer.provide(WorkspacesLayer, PlatformLayer);
21664
- * ```
21665
- *
21666
- * @public
21667
- */
22369
+ //#region ../../node_modules/.pnpm/@effected+workspaces@0.9.0_@effected+jsonc@0.5.1_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/Workspaces.js
21668
22370
  const compose = (options, catalogsFactory) => {
21669
22371
  const roots = WorkspaceRoot.layer;
21670
22372
  const detector = PackageManagerDetector.layer;
21671
22373
  const discovery = WorkspaceDiscovery.layer(options).pipe(effect.Layer.provide(roots));
21672
22374
  const lockfiles = LockfileReader.layer(options).pipe(effect.Layer.provide(roots), effect.Layer.provide(detector), effect.Layer.provide(discovery));
21673
22375
  const catalogs = catalogsFactory(options).pipe(effect.Layer.provide(roots), effect.Layer.provide(lockfiles));
21674
- return effect.Layer.mergeAll(roots, detector, discovery, lockfiles, catalogs, PublishabilityDetector.layer);
22376
+ return effect.Layer.mergeAll(roots, detector, discovery, lockfiles, catalogs);
21675
22377
  };
21676
22378
  const layer = (options) => compose(options, WorkspaceCatalogs.layer);
21677
- /**
21678
- * The git-free composite plus {@link ChangeDetector} and
21679
- * {@link WorkspaceSnapshots}, over `@effected/git`'s `Git` service.
21680
- *
21681
- * @remarks
21682
- * The extra requirement is core's `ChildProcessSpawner` (behind `Git`), which
21683
- * is why it is a separate layer rather than a flag: a consumer that never
21684
- * detects changes or reads at a ref should not have to be able to spawn a
21685
- * subprocess. The consumer provides `ChildProcessSpawner` once at the edge
21686
- * (`@effect/platform-node`'s `NodeServices.layer`); a test provides
21687
- * `Layer.succeed(Git, …)` and needs no repository on disk.
21688
- *
21689
- * @public
21690
- */
21691
22379
  const layerWithGit = (options) => {
21692
22380
  const core = layer(options);
21693
22381
  const git = Git.layer;
21694
22382
  return effect.Layer.mergeAll(core, git, ChangeDetector.layer.pipe(effect.Layer.provide(git), effect.Layer.provide(core)), WorkspaceSnapshots.layer(options).pipe(effect.Layer.provide(git), effect.Layer.provide(core)));
21695
22383
  };
21696
- /**
21697
- * The two `@effected/npm` resolver contracts, implemented for real.
21698
- *
21699
- * @remarks
21700
- * Provide this alongside `@effected/package-json`'s `Package.resolve` and a
21701
- * manifest's `catalog:` and `workspace:` specifiers resolve against the actual
21702
- * workspace instead of the no-op layers' `Option.none()`.
21703
- *
21704
- * @example
21705
- * ```ts
21706
- * import { Package } from "@effected/package-json";
21707
- * import { Workspaces } from "@effected/workspaces";
21708
- * import { Layer } from "effect";
21709
- *
21710
- * const WorkspacesLayer = Workspaces.layer();
21711
- * const Resolvers = Workspaces.resolvers.pipe(Layer.provide(WorkspacesLayer));
21712
- * ```
21713
- *
21714
- * @public
21715
- */
21716
22384
  const resolvers = effect.Layer.mergeAll(WorkspaceCatalogs.catalogResolver, WorkspaceDiscovery.workspaceResolver);
21717
- /**
21718
- * The git-free composite, but with catalog assembly that **replays config
21719
- * dependency `pnpmfile.cjs` hooks** — {@link WorkspaceCatalogs.layerWithConfigDependencies}
21720
- * in place of the default no-op catalogs layer.
21721
- *
21722
- * @remarks
21723
- * Identical requirement set to {@link Workspaces.layer}; the only difference is
21724
- * that config-dependency code is executed in process. Opt in deliberately — the
21725
- * default {@link Workspaces.layer} never executes config-dependency code.
21726
- *
21727
- * **Bind the result to a `const`.**
21728
- *
21729
- * @public
21730
- */
21731
22385
  const layerWithConfigDependencies = (options) => compose(options, WorkspaceCatalogs.layerWithConfigDependencies);
21732
- /**
21733
- * The one-call resolver factory: {@link Workspaces.resolvers} pre-wired over
21734
- * {@link Workspaces.layerWithConfigDependencies}, so the two `@effected/npm`
21735
- * contracts (`CatalogResolver`, `WorkspaceResolver`) need only a platform
21736
- * (`FileSystem` + `Path`) from the consumer.
21737
- *
21738
- * @remarks
21739
- * This is deliberately a **parameterized layer function, and the fresh layer
21740
- * per call is the feature**: layers memoize by reference, so each call mints
21741
- * an unmemoized layer whose root discovery re-runs — including a per-call
21742
- * `process.cwd()` read when `options.cwd` is omitted. A build tool that
21743
- * changes directory between manifests gets a correct re-discovery each time
21744
- * precisely because nothing is shared across calls. When you *want* sharing,
21745
- * bind one call's result to a `const` and provide that; the memoization rule
21746
- * is unchanged, this factory just refuses to hide it.
21747
- *
21748
- * Catalog assembly replays config-dependency `pnpmfile` hooks (the
21749
- * `layerWithConfigDependencies` path) — the semantics a real pnpm install
21750
- * has. Compose {@link Workspaces.resolvers} with {@link Workspaces.layer}
21751
- * yourself if config-dependency code must not run in process.
21752
- *
21753
- * @example
21754
- * ```ts
21755
- * import { Workspaces } from "@effected/workspaces";
21756
- * import { Effect } from "effect";
21757
- *
21758
- * const program = doSomethingWithResolvers.pipe(
21759
- * Effect.provide(Workspaces.resolverLayer()),
21760
- * );
21761
- * ```
21762
- *
21763
- * @public
21764
- */
21765
22386
  const resolverLayer = (options) => resolvers.pipe(effect.Layer.provide(layerWithConfigDependencies(options)));
22387
+ const resolveManifest = effect.Effect.fn("Workspaces.resolveManifest")(function* (manifest, options) {
22388
+ return yield* manifest.resolve().pipe(effect.Effect.provide(resolverLayer(options)));
22389
+ });
22390
+ const localExecLayer = (options) => effect.Layer.effect(LocalExec, effect.Effect.gen(function* () {
22391
+ const roots = yield* WorkspaceRoot;
22392
+ const detector = yield* PackageManagerDetector;
22393
+ return { context: effect.Effect.gen(function* () {
22394
+ const cwd = options?.cwd ?? globalThis.process?.cwd?.() ?? "/";
22395
+ const root = yield* roots.find(cwd).pipe(effect.Effect.asSome, effect.Effect.orElseSucceed(effect.Option.none));
22396
+ if (effect.Option.isNone(root)) return effect.Option.none();
22397
+ const detected = yield* detector.detect(root.value).pipe(effect.Effect.asSome, effect.Effect.catchTag("PackageManagerDetectionError", () => effect.Effect.succeed(effect.Option.none())), effect.Effect.mapError((cause) => new LocalExecError({
22398
+ directory: root.value,
22399
+ cause
22400
+ })));
22401
+ if (effect.Option.isNone(detected)) return effect.Option.none();
22402
+ const { prefix, dlxPrefix } = LocalExec.prefixes(detected.value.name);
22403
+ return effect.Option.some(ExecContext.make({
22404
+ label: detected.value.name,
22405
+ prefix,
22406
+ dlxPrefix,
22407
+ directory: root.value
22408
+ }));
22409
+ }) };
22410
+ }));
21766
22411
  /**
21767
22412
  * The composite layers.
21768
22413
  *
21769
22414
  * @public
21770
22415
  */
21771
- const Workspaces = {
21772
- layer,
21773
- layerWithConfigDependencies,
21774
- layerWithGit,
21775
- resolveManifest: effect.Effect.fn("Workspaces.resolveManifest")(function* (manifest, options) {
21776
- return yield* manifest.resolve().pipe(effect.Effect.provide(resolverLayer(options)));
21777
- }),
21778
- resolverLayer,
21779
- resolvers
22416
+ var Workspaces = class {
22417
+ constructor() {}
22418
+ /**
22419
+ * Every service that needs only a filesystem: root, package-manager
22420
+ * detection, discovery, lockfile reading, catalogs and publishability.
22421
+ *
22422
+ * @remarks
22423
+ * Requires core `FileSystem` and `Path`, which the consumer provides at the
22424
+ * edge (`@effect/platform-node`, `@effect/platform-bun`, or a test's
22425
+ * `FileSystem.layerNoop`).
22426
+ *
22427
+ * **Bind the result to a `const`.** This is a parameterized factory and
22428
+ * layers memoize by reference, so calling it twice builds everything twice.
22429
+ *
22430
+ * @example
22431
+ * ```ts
22432
+ * import { Workspaces } from "@effected/workspaces";
22433
+ * import { Layer } from "effect";
22434
+ *
22435
+ * const WorkspacesLayer = Workspaces.layer();
22436
+ * const AppLayer = Layer.provide(WorkspacesLayer, PlatformLayer);
22437
+ * ```
22438
+ */
22439
+ static layer = layer;
22440
+ /**
22441
+ * The git-free composite, but with catalog assembly that **replays config
22442
+ * dependency `pnpmfile.cjs` hooks** —
22443
+ * {@link WorkspaceCatalogs.layerWithConfigDependencies} in place of the
22444
+ * default no-op catalogs layer.
22445
+ *
22446
+ * @remarks
22447
+ * Identical requirement set to {@link Workspaces.layer}; the only
22448
+ * difference is that config-dependency code is executed in process. Opt in
22449
+ * deliberately — the default {@link Workspaces.layer} never executes
22450
+ * config-dependency code.
22451
+ *
22452
+ * **Bind the result to a `const`.**
22453
+ */
22454
+ static layerWithConfigDependencies = layerWithConfigDependencies;
22455
+ /**
22456
+ * The git-free composite plus {@link ChangeDetector} and
22457
+ * {@link WorkspaceSnapshots}, over `@effected/git`'s `Git` service.
22458
+ *
22459
+ * @remarks
22460
+ * The extra requirement is core's `ChildProcessSpawner` (behind `Git`),
22461
+ * which is why it is a separate layer rather than a flag: a consumer that
22462
+ * never detects changes or reads at a ref should not have to be able to
22463
+ * spawn a subprocess. The consumer provides `ChildProcessSpawner` once at
22464
+ * the edge (`@effect/platform-node`'s `NodeServices.layer`); a test
22465
+ * provides `Layer.succeed(Git, …)` and needs no repository on disk.
22466
+ */
22467
+ static layerWithGit = layerWithGit;
22468
+ /**
22469
+ * This package's implementation of `@effected/commands`' `LocalExec`
22470
+ * contract: how to run a project-local binary here.
22471
+ *
22472
+ * @remarks
22473
+ * **An inverted contract, the `@effected/npm` `CatalogResolver`
22474
+ * precedent.** Tool discovery needs package-manager detection and
22475
+ * workspace-root resolution, both of which live here — but a direct edge
22476
+ * from `@effected/commands` to this package would make that boundary-tier
22477
+ * package integrated, and through the planned `npm` → `commands` edge
22478
+ * would drag `npm`, `lockfiles` (pure!) and `package-json` up a tier with
22479
+ * it. So `commands` declares the narrow contract and we ship the layer.
22480
+ *
22481
+ * **The argv knowledge is not duplicated.** `LocalExec.prefixes(name)` is
22482
+ * the one home of the four managers' `exec`/`dlx` prefixes; this layer
22483
+ * detects *which* manager owns the directory and asks `commands` what that
22484
+ * manager's argv looks like. Neither package reimplements the other's
22485
+ * half.
22486
+ *
22487
+ * **`None` is success.** Outside any workspace — and inside one whose
22488
+ * manager cannot be identified — the answer is `Option.none()`: "there is
22489
+ * no project-local way to run tools here" is an ordinary fact, not an
22490
+ * exceptional one, and a consumer running in a bare directory should not
22491
+ * have to catch an error to learn it. The contract's typed
22492
+ * `LocalExecError` is reserved for **mechanism** failure — a manifest that
22493
+ * exists but cannot be read or parsed, which means something is broken
22494
+ * rather than absent. That is npm's resolver convention, adopted
22495
+ * verbatim.
22496
+ *
22497
+ * `directory` is the resolved **workspace root**, not the caller's cwd: a
22498
+ * project-local launcher has to run where the workspace is.
22499
+ *
22500
+ * A consumer with no monorepo never needs this layer, and therefore never
22501
+ * installs this package — `LocalExec.layerNone` and `LocalExec.layerFor`
22502
+ * are one-liners in `@effected/commands`.
22503
+ *
22504
+ * **Bind the result to a `const`** — a parameterized layer factory mints a
22505
+ * fresh reference per call and layers memoize by reference.
22506
+ *
22507
+ * @example
22508
+ * ```ts
22509
+ * import { ToolDiscovery } from "@effected/commands";
22510
+ * import { Workspaces } from "@effected/workspaces";
22511
+ * import { Layer } from "effect";
22512
+ *
22513
+ * const AppLayer = ToolDiscovery.layer.pipe(
22514
+ * Layer.provide(Workspaces.localExecLayer()),
22515
+ * Layer.provide(Workspaces.layer()),
22516
+ * Layer.provide(NodeServices.layer),
22517
+ * );
22518
+ * ```
22519
+ */
22520
+ static localExecLayer = localExecLayer;
22521
+ /**
22522
+ * Resolve every `catalog:` and `workspace:` specifier in one `Manifest`
22523
+ * against the real workspace, in one call — the 90% path. Decode stays at
22524
+ * the consumer's edge: build the `Manifest` with `Manifest.decode` (from
22525
+ * `@effected/npm`), hand it here, and get a new `Manifest` back with
22526
+ * concrete ranges; `toRecord()` returns to the wire shape.
22527
+ *
22528
+ * @remarks
22529
+ * Composes `manifest.resolve()` with a fresh {@link Workspaces.resolverLayer}
22530
+ * per call, so the workspace root is re-discovered from `options.cwd` (or
22531
+ * the current `process.cwd()`) on every invocation. Consumers processing
22532
+ * many manifests should check `manifest.needsResolution` first and skip
22533
+ * the call entirely when no dependency field carries a
22534
+ * `catalog:`/`workspace:` specifier — that predicate is pure and avoids
22535
+ * catalog assembly altogether.
22536
+ *
22537
+ * A specifier the workspace cannot answer fails typed as
22538
+ * `UnresolvedDependencyError`; assembly and mechanism failures surface as
22539
+ * `CatalogAssemblyError` / `DependencyResolutionError`.
22540
+ *
22541
+ * @example
22542
+ * ```ts
22543
+ * import { Manifest } from "@effected/npm";
22544
+ * import { Workspaces } from "@effected/workspaces";
22545
+ * import { Effect } from "effect";
22546
+ *
22547
+ * const program = Effect.gen(function* () {
22548
+ * const manifest = yield* Manifest.decode({ dependencies: { effect: "catalog:" } });
22549
+ * const resolved = manifest.needsResolution ? yield* Workspaces.resolveManifest(manifest) : manifest;
22550
+ * return resolved.toRecord();
22551
+ * });
22552
+ * ```
22553
+ */
22554
+ static resolveManifest = resolveManifest;
22555
+ /**
22556
+ * The one-call resolver factory: {@link Workspaces.resolvers} pre-wired
22557
+ * over {@link Workspaces.layerWithConfigDependencies}, so the two
22558
+ * `@effected/npm` contracts (`CatalogResolver`, `WorkspaceResolver`) need
22559
+ * only a platform (`FileSystem` + `Path`) from the consumer.
22560
+ *
22561
+ * @remarks
22562
+ * This is deliberately a **parameterized layer function, and the fresh
22563
+ * layer per call is the feature**: layers memoize by reference, so each
22564
+ * call mints an unmemoized layer whose root discovery re-runs — including
22565
+ * a per-call `process.cwd()` read when `options.cwd` is omitted. A build
22566
+ * tool that changes directory between manifests gets a correct
22567
+ * re-discovery each time precisely because nothing is shared across
22568
+ * calls. When you *want* sharing, bind one call's result to a `const` and
22569
+ * provide that; the memoization rule is unchanged, this factory just
22570
+ * refuses to hide it.
22571
+ *
22572
+ * Catalog assembly replays config-dependency `pnpmfile` hooks (the
22573
+ * `layerWithConfigDependencies` path) — the semantics a real pnpm install
22574
+ * has. Compose {@link Workspaces.resolvers} with {@link Workspaces.layer}
22575
+ * yourself if config-dependency code must not run in process.
22576
+ *
22577
+ * @example
22578
+ * ```ts
22579
+ * import { Workspaces } from "@effected/workspaces";
22580
+ * import { Effect } from "effect";
22581
+ *
22582
+ * const program = doSomethingWithResolvers.pipe(
22583
+ * Effect.provide(Workspaces.resolverLayer()),
22584
+ * );
22585
+ * ```
22586
+ */
22587
+ static resolverLayer = resolverLayer;
22588
+ /**
22589
+ * The two `@effected/npm` resolver contracts, implemented for real.
22590
+ *
22591
+ * @remarks
22592
+ * Provide this alongside `@effected/package-json`'s `Package.resolve` and
22593
+ * a manifest's `catalog:` and `workspace:` specifiers resolve against the
22594
+ * actual workspace instead of the no-op layers' `Option.none()`.
22595
+ *
22596
+ * @example
22597
+ * ```ts
22598
+ * import { Package } from "@effected/package-json";
22599
+ * import { Workspaces } from "@effected/workspaces";
22600
+ * import { Layer } from "effect";
22601
+ *
22602
+ * const WorkspacesLayer = Workspaces.layer();
22603
+ * const Resolvers = Workspaces.resolvers.pipe(Layer.provide(WorkspacesLayer));
22604
+ * ```
22605
+ */
22606
+ static resolvers = resolvers;
21780
22607
  };
21781
22608
  //#endregion
21782
22609
  //#region ../silk-effects/dist/dev/pkg/services/SilkPublishability.js
@@ -22025,7 +22852,7 @@ effect.Layer.effect(PublishabilityDetector, effect.Effect.gen(function* () {
22025
22852
  const PublishabilityDetectorAdaptiveLive = effect.Layer.effect(PublishabilityDetector, effect.Effect.gen(function* () {
22026
22853
  const fs = yield* effect.FileSystem.FileSystem;
22027
22854
  const config = yield* ChangesetConfig;
22028
- const vanilla = yield* effect.Effect.provide(PublishabilityDetector, PublishabilityDetector.layer);
22855
+ const vanilla = PublishabilityDetector.npm;
22029
22856
  return { detect: (pkg) => effect.Effect.gen(function* () {
22030
22857
  const root = pkg.workspaceRoot;
22031
22858
  if (yield* config.isIgnored(pkg.name, root)) return [];
@@ -22747,7 +23574,6 @@ const MarkdownParseErrorBase = effect.Data.TaggedError("MarkdownParseError");
22747
23574
  * );
22748
23575
  * ```
22749
23576
  *
22750
- * @see {@link MarkdownService} for the Effect service that may produce this error
22751
23577
  *
22752
23578
  * @public
22753
23579
  */
@@ -23939,7 +24765,7 @@ var GitHubService = class extends effect.Context.Service()("GitHubService") {};
23939
24765
  * @remarks
23940
24766
  * This layer is used by the `\@savvy-web/changesets/changelog` entry point
23941
24767
  * to resolve commit hashes into PR numbers and author attribution. It is
23942
- * composed with {@link MarkdownLive} in the changelog formatter's
24768
+ * used by the changelog formatter's
23943
24769
  * `MainLayer`.
23944
24770
  *
23945
24771
  * @example
@@ -24008,6 +24834,277 @@ function makeGitHubTest(responses) {
24008
24834
  } });
24009
24835
  }
24010
24836
  //#endregion
24837
+ //#region ../silk-effects/dist/dev/pkg/changesets/schemas/primitives.js
24838
+ /**
24839
+ * Primitive reusable schemas for common constrained types.
24840
+ *
24841
+ * @remarks
24842
+ * These schemas serve as building blocks for more complex schemas throughout
24843
+ * the \@savvy-web/changesets package. They encode common constraints
24844
+ * (non-empty strings, positive integers) as Effect Schemas so that validation
24845
+ * is enforced at system boundaries.
24846
+ *
24847
+ * @see {@link https://effect.website/docs/schema/introduction | Effect Schema documentation}
24848
+ *
24849
+ */
24850
+ /**
24851
+ * A non-empty string schema.
24852
+ *
24853
+ * @remarks
24854
+ * Validates that a string has at least one character. Used as the base
24855
+ * constraint for package names, dependency identifiers, and other fields
24856
+ * that must not be blank.
24857
+ *
24858
+ * @example
24859
+ * ```typescript
24860
+ * import { Schema } from "effect";
24861
+ * import { NonEmptyString } from "@savvy-web/changesets";
24862
+ *
24863
+ * // Succeeds — non-empty string
24864
+ * const name = Schema.decodeUnknownSync(NonEmptyString)("react");
24865
+ *
24866
+ * // Throws ParseError — empty string
24867
+ * Schema.decodeUnknownSync(NonEmptyString)("");
24868
+ * ```
24869
+ *
24870
+ * @see {@link ChangesetSummarySchema} for a length-bounded variant used for changeset summaries
24871
+ *
24872
+ * @public
24873
+ */
24874
+ const NonEmptyString = effect.Schema.String.check(effect.Schema.isMinLength(1));
24875
+ /**
24876
+ * A positive integer schema.
24877
+ *
24878
+ * @remarks
24879
+ * Validates that a number is both an integer and strictly greater than zero.
24880
+ * Used as the base constraint for GitHub issue numbers and similar
24881
+ * identifiers that must be positive whole numbers.
24882
+ *
24883
+ * @example
24884
+ * ```typescript
24885
+ * import { Schema } from "effect";
24886
+ * import { PositiveInteger } from "@savvy-web/changesets";
24887
+ *
24888
+ * // Succeeds — positive integer
24889
+ * const issueNum = Schema.decodeUnknownSync(PositiveInteger)(42);
24890
+ *
24891
+ * // Throws ParseError — zero is not positive
24892
+ * Schema.decodeUnknownSync(PositiveInteger)(0);
24893
+ *
24894
+ * // Throws ParseError — floats are not integers
24895
+ * Schema.decodeUnknownSync(PositiveInteger)(3.14);
24896
+ * ```
24897
+ *
24898
+ * @see {@link IssueNumberSchema} which builds on this for GitHub issue/PR numbers
24899
+ *
24900
+ * @public
24901
+ */
24902
+ const PositiveInteger = effect.Schema.Number.check(effect.Schema.isInt(), effect.Schema.isGreaterThan(0));
24903
+ //#endregion
24904
+ //#region ../silk-effects/dist/dev/pkg/changesets/schemas/dependency-table.js
24905
+ /**
24906
+ * Effect schemas for structured dependency table entries.
24907
+ *
24908
+ * @remarks
24909
+ * These schemas define the canonical representation for dependency
24910
+ * changes tracked as markdown tables in changeset files and CHANGELOGs.
24911
+ * The table format provides a richer view than {@link DependencyUpdateSchema}
24912
+ * by supporting singular dependency type names, workspace/config types,
24913
+ * and explicit add/update/remove actions.
24914
+ *
24915
+ * A dependency table row looks like this in a CHANGELOG:
24916
+ *
24917
+ * | Dependency | Type | Action | From | To |
24918
+ * |---|---|---|---|---|
24919
+ * | effect | dependency | updated | 3.18.0 | 3.19.1 |
24920
+ *
24921
+ * @see {@link DependencyUpdateSchema} for the simpler Changesets API format
24922
+ * @see {@link https://effect.website/docs/schema/introduction | Effect Schema documentation}
24923
+ *
24924
+ */
24925
+ /**
24926
+ * Valid dependency table actions.
24927
+ *
24928
+ * @remarks
24929
+ * Represents the three possible operations on a dependency: `"added"` for
24930
+ * new dependencies, `"updated"` for version changes, and `"removed"` for
24931
+ * deletions. Used in the "Action" column of dependency tables.
24932
+ *
24933
+ * @example
24934
+ * ```typescript
24935
+ * import { Schema } from "effect";
24936
+ * import { DependencyActionSchema } from "@savvy-web/changesets";
24937
+ * import type { DependencyAction } from "@savvy-web/changesets";
24938
+ *
24939
+ * const action: DependencyAction = Schema.decodeUnknownSync(DependencyActionSchema)("updated");
24940
+ * ```
24941
+ *
24942
+ * @public
24943
+ */
24944
+ const DependencyActionSchema = effect.Schema.Literals([
24945
+ "added",
24946
+ "updated",
24947
+ "removed"
24948
+ ]);
24949
+ /**
24950
+ * Extended dependency types for table format.
24951
+ *
24952
+ * @remarks
24953
+ * Unlike {@link DependencyTypeSchema} (which uses plural npm field names like
24954
+ * `"dependencies"`), this schema uses singular forms (`"dependency"`) and adds
24955
+ * two additional types: `"workspace"` for monorepo workspace references and
24956
+ * `"config"` for configuration toolchain updates (e.g., ESLint, TypeScript).
24957
+ *
24958
+ * @example
24959
+ * ```typescript
24960
+ * import { Schema } from "effect";
24961
+ * import { DependencyTableTypeSchema } from "@savvy-web/changesets";
24962
+ * import type { DependencyTableType } from "@savvy-web/changesets";
24963
+ *
24964
+ * const tableType: DependencyTableType = Schema.decodeUnknownSync(
24965
+ * DependencyTableTypeSchema
24966
+ * )("workspace");
24967
+ * ```
24968
+ *
24969
+ * @see {@link DependencyTypeSchema} for the plural npm-field variant
24970
+ *
24971
+ * @public
24972
+ */
24973
+ const DependencyTableTypeSchema = effect.Schema.Literals([
24974
+ "dependency",
24975
+ "devDependency",
24976
+ "peerDependency",
24977
+ "optionalDependency",
24978
+ "workspace",
24979
+ "config"
24980
+ ]);
24981
+ /**
24982
+ * The canonical accepted-value pattern for a dependency-table From/To cell:
24983
+ * the em-dash sentinel (U+2014), a bare/`~`/`^` semver, or — as a last-resort
24984
+ * fallback when a `catalog:`/`workspace:` specifier could not be resolved to a
24985
+ * concrete version — a pnpm protocol string. Non-overlapping alternatives keep
24986
+ * this free of polynomial backtracking (CodeQL).
24987
+ *
24988
+ * @public
24989
+ */
24990
+ const VERSION_RE = /^(\u2014|[~^]?\d+\.\d+\.\d+(?:[-+.][\w.+-]+)?|(?:catalog|workspace|npm|jsr|file|link|portal):[^\s|]+)$/;
24991
+ /**
24992
+ * Version string or em dash (U+2014) sentinel for added/removed entries.
24993
+ *
24994
+ * @remarks
24995
+ * Accepts either a semver-like version string (with optional `~` or `^`
24996
+ * prefix and pre-release/build suffixes) or the em dash character `\u2014`
24997
+ * which serves as a sentinel: the "From" column uses `\u2014` for newly
24998
+ * added dependencies, and the "To" column uses it for removed ones.
24999
+ *
25000
+ * @example
25001
+ * ```typescript
25002
+ * import { Schema } from "effect";
25003
+ * import { VersionOrEmptySchema } from "@savvy-web/changesets";
25004
+ *
25005
+ * // Succeeds — semver version
25006
+ * Schema.decodeUnknownSync(VersionOrEmptySchema)("^3.19.1");
25007
+ *
25008
+ * // Succeeds — em dash sentinel for "no version"
25009
+ * Schema.decodeUnknownSync(VersionOrEmptySchema)("\u2014");
25010
+ *
25011
+ * // Throws ParseError — arbitrary text
25012
+ * Schema.decodeUnknownSync(VersionOrEmptySchema)("latest");
25013
+ * ```
25014
+ *
25015
+ * @public
25016
+ */
25017
+ const VersionOrEmptySchema = effect.Schema.String.check(effect.Schema.isPattern(VERSION_RE));
25018
+ /**
25019
+ * Schema for a single dependency table row.
25020
+ *
25021
+ * @remarks
25022
+ * Represents one row of a dependency update table in a CHANGELOG.
25023
+ * Each row captures the dependency name, its type, the change action,
25024
+ * and the "from" and "to" version strings. For added dependencies the
25025
+ * `from` field is an em dash; for removed dependencies the `to` field
25026
+ * is an em dash.
25027
+ *
25028
+ * @example
25029
+ * ```typescript
25030
+ * import { Schema } from "effect";
25031
+ * import { DependencyTableRowSchema } from "@savvy-web/changesets";
25032
+ * import type { DependencyTableRow } from "@savvy-web/changesets";
25033
+ *
25034
+ * const row: DependencyTableRow = Schema.decodeUnknownSync(DependencyTableRowSchema)({
25035
+ * dependency: "effect",
25036
+ * type: "dependency",
25037
+ * action: "updated",
25038
+ * from: "3.18.0",
25039
+ * to: "3.19.1",
25040
+ * });
25041
+ *
25042
+ * // Newly added dependency — "from" is em dash
25043
+ * const addedRow: DependencyTableRow = Schema.decodeUnknownSync(DependencyTableRowSchema)({
25044
+ * dependency: "@effect/cli",
25045
+ * type: "dependency",
25046
+ * action: "added",
25047
+ * from: "\u2014",
25048
+ * to: "0.50.0",
25049
+ * });
25050
+ * ```
25051
+ *
25052
+ * @see {@link DependencyTableRow} for the inferred TypeScript type
25053
+ * @see {@link DependencyTableSchema} for a non-empty array of rows
25054
+ *
25055
+ * @public
25056
+ */
25057
+ const DependencyTableRowSchema = effect.Schema.Struct({
25058
+ /** Package or toolchain name. */
25059
+ dependency: NonEmptyString,
25060
+ /** Dependency type. */
25061
+ type: DependencyTableTypeSchema,
25062
+ /** Change action. */
25063
+ action: DependencyActionSchema,
25064
+ /** Previous version (em dash for added). */
25065
+ from: VersionOrEmptySchema,
25066
+ /** New version (em dash for removed). */
25067
+ to: VersionOrEmptySchema
25068
+ });
25069
+ /**
25070
+ * Schema for a dependency table (non-empty array of rows).
25071
+ *
25072
+ * @remarks
25073
+ * Validates that the table contains at least one row. Used to represent
25074
+ * the full dependency update table in a changeset or CHANGELOG entry.
25075
+ *
25076
+ * @example
25077
+ * ```typescript
25078
+ * import { Schema } from "effect";
25079
+ * import { DependencyTableSchema } from "@savvy-web/changesets";
25080
+ *
25081
+ * const table = Schema.decodeUnknownSync(DependencyTableSchema)([
25082
+ * {
25083
+ * dependency: "effect",
25084
+ * type: "dependency",
25085
+ * action: "updated",
25086
+ * from: "3.18.0",
25087
+ * to: "3.19.1",
25088
+ * },
25089
+ * {
25090
+ * dependency: "typescript",
25091
+ * type: "config",
25092
+ * action: "updated",
25093
+ * from: "5.6.0",
25094
+ * to: "5.7.2",
25095
+ * },
25096
+ * ]);
25097
+ *
25098
+ * // Throws ParseError — empty array
25099
+ * Schema.decodeUnknownSync(DependencyTableSchema)([]);
25100
+ * ```
25101
+ *
25102
+ * @see {@link DependencyTableRowSchema} for the individual row schema
25103
+ *
25104
+ * @public
25105
+ */
25106
+ const DependencyTableSchema = effect.Schema.Array(DependencyTableRowSchema).check(effect.Schema.isMinLength(1));
25107
+ //#endregion
24011
25108
  //#region ../../node_modules/.pnpm/ccount@2.0.1/node_modules/ccount/index.js
24012
25109
  /**
24013
25110
  * Count how often a character (or substring) is used in a string.
@@ -43477,365 +44574,6 @@ function stringifyMarkdown(tree) {
43477
44574
  return createRemarkProcessor().stringify(tree);
43478
44575
  }
43479
44576
  //#endregion
43480
- //#region ../silk-effects/dist/dev/pkg/changesets/services/markdown.js
43481
- /**
43482
- * Markdown service for parsing and stringifying mdast trees.
43483
- *
43484
- * Defines the {@link MarkdownService} Effect service tag and the
43485
- * {@link MarkdownLive | production layer} backed by the remark/unified
43486
- * pipeline. This service provides a pure, side-effect-free interface to
43487
- * markdown parsing and stringification used throughout the changelog
43488
- * formatter and remark transform pipeline.
43489
- *
43490
- * @remarks
43491
- * The service wraps the `remark-pipeline` utility functions (`parseMarkdown`
43492
- * and `stringifyMarkdown`) behind an Effect interface. The `parse` operation
43493
- * returns an mdast `Root` node; the `stringify` operation serializes an
43494
- * mdast `Root` back to a markdown string. Both operations are synchronous
43495
- * under the hood but are lifted into `Effect.sync` for composability.
43496
- *
43497
- * @see {@link MarkdownService} for the Effect service tag
43498
- * @see {@link MarkdownServiceShape} for the service interface
43499
- * @see {@link MarkdownLive} for the production layer
43500
- */
43501
- /**
43502
- * Effect service tag for markdown parsing and stringification.
43503
- *
43504
- * Provides dependency-injected access to markdown parse/stringify operations.
43505
- * Use `yield* MarkdownService` inside an `Effect.gen` block to obtain the
43506
- * service instance.
43507
- *
43508
- * @remarks
43509
- * This tag follows the standard Effect `Context.Service` pattern. The
43510
- * {@link MarkdownLive} layer provides the default implementation backed by
43511
- * the remark/unified pipeline. For testing, you can supply a custom layer
43512
- * via `Layer.succeed(MarkdownService, { parse: ..., stringify: ... })`.
43513
- *
43514
- * @example
43515
- * ```typescript
43516
- * import { Effect } from "effect";
43517
- * import { MarkdownService, MarkdownLive } from "\@savvy-web/changesets";
43518
- *
43519
- * const program = Effect.gen(function* () {
43520
- * const md = yield* MarkdownService;
43521
- * const tree = yield* md.parse("# Hello\n\nWorld");
43522
- * const output = yield* md.stringify(tree);
43523
- * console.log(output); // "# Hello\n\nWorld\n"
43524
- * });
43525
- *
43526
- * Effect.runPromise(program.pipe(Effect.provide(MarkdownLive)));
43527
- * ```
43528
- *
43529
- * @see {@link MarkdownServiceShape} for the service interface
43530
- * @see {@link MarkdownLive} for the production layer
43531
- *
43532
- * @public
43533
- */
43534
- var MarkdownService = class extends effect.Context.Service()("MarkdownService") {};
43535
- /**
43536
- * Production layer for {@link MarkdownService}.
43537
- *
43538
- * Wraps the remark-pipeline utility functions (`parseMarkdown` and
43539
- * `stringifyMarkdown`) in `Effect.sync` for use in Effect programs.
43540
- * Both operations are synchronous and infallible.
43541
- *
43542
- * @remarks
43543
- * This layer is composed with {@link GitHubLive} in the
43544
- * `\@savvy-web/changesets/changelog` entry point to form the `MainLayer`
43545
- * that powers the Changesets API integration.
43546
- *
43547
- * @example
43548
- * ```typescript
43549
- * import { Effect, Layer } from "effect";
43550
- * import { MarkdownService, MarkdownLive } from "\@savvy-web/changesets";
43551
- *
43552
- * const program = Effect.gen(function* () {
43553
- * const md = yield* MarkdownService;
43554
- * const tree = yield* md.parse("**bold** text");
43555
- * return yield* md.stringify(tree);
43556
- * });
43557
- *
43558
- * Effect.runPromise(program.pipe(Effect.provide(MarkdownLive)));
43559
- * ```
43560
- *
43561
- * @public
43562
- */
43563
- const MarkdownLive = effect.Layer.succeed(MarkdownService, {
43564
- parse: (content) => effect.Effect.sync(() => parseMarkdown(content)),
43565
- stringify: (tree) => effect.Effect.sync(() => stringifyMarkdown(tree))
43566
- });
43567
- //#endregion
43568
- //#region ../silk-effects/dist/dev/pkg/changesets/schemas/primitives.js
43569
- /**
43570
- * Primitive reusable schemas for common constrained types.
43571
- *
43572
- * @remarks
43573
- * These schemas serve as building blocks for more complex schemas throughout
43574
- * the \@savvy-web/changesets package. They encode common constraints
43575
- * (non-empty strings, positive integers) as Effect Schemas so that validation
43576
- * is enforced at system boundaries.
43577
- *
43578
- * @see {@link https://effect.website/docs/schema/introduction | Effect Schema documentation}
43579
- *
43580
- */
43581
- /**
43582
- * A non-empty string schema.
43583
- *
43584
- * @remarks
43585
- * Validates that a string has at least one character. Used as the base
43586
- * constraint for package names, dependency identifiers, and other fields
43587
- * that must not be blank.
43588
- *
43589
- * @example
43590
- * ```typescript
43591
- * import { Schema } from "effect";
43592
- * import { NonEmptyString } from "@savvy-web/changesets";
43593
- *
43594
- * // Succeeds — non-empty string
43595
- * const name = Schema.decodeUnknownSync(NonEmptyString)("react");
43596
- *
43597
- * // Throws ParseError — empty string
43598
- * Schema.decodeUnknownSync(NonEmptyString)("");
43599
- * ```
43600
- *
43601
- * @see {@link ChangesetSummarySchema} for a length-bounded variant used for changeset summaries
43602
- *
43603
- * @public
43604
- */
43605
- const NonEmptyString = effect.Schema.String.check(effect.Schema.isMinLength(1));
43606
- /**
43607
- * A positive integer schema.
43608
- *
43609
- * @remarks
43610
- * Validates that a number is both an integer and strictly greater than zero.
43611
- * Used as the base constraint for GitHub issue numbers and similar
43612
- * identifiers that must be positive whole numbers.
43613
- *
43614
- * @example
43615
- * ```typescript
43616
- * import { Schema } from "effect";
43617
- * import { PositiveInteger } from "@savvy-web/changesets";
43618
- *
43619
- * // Succeeds — positive integer
43620
- * const issueNum = Schema.decodeUnknownSync(PositiveInteger)(42);
43621
- *
43622
- * // Throws ParseError — zero is not positive
43623
- * Schema.decodeUnknownSync(PositiveInteger)(0);
43624
- *
43625
- * // Throws ParseError — floats are not integers
43626
- * Schema.decodeUnknownSync(PositiveInteger)(3.14);
43627
- * ```
43628
- *
43629
- * @see {@link IssueNumberSchema} which builds on this for GitHub issue/PR numbers
43630
- *
43631
- * @public
43632
- */
43633
- const PositiveInteger = effect.Schema.Number.check(effect.Schema.isInt(), effect.Schema.isGreaterThan(0));
43634
- //#endregion
43635
- //#region ../silk-effects/dist/dev/pkg/changesets/schemas/dependency-table.js
43636
- /**
43637
- * Effect schemas for structured dependency table entries.
43638
- *
43639
- * @remarks
43640
- * These schemas define the canonical representation for dependency
43641
- * changes tracked as markdown tables in changeset files and CHANGELOGs.
43642
- * The table format provides a richer view than {@link DependencyUpdateSchema}
43643
- * by supporting singular dependency type names, workspace/config types,
43644
- * and explicit add/update/remove actions.
43645
- *
43646
- * A dependency table row looks like this in a CHANGELOG:
43647
- *
43648
- * | Dependency | Type | Action | From | To |
43649
- * |---|---|---|---|---|
43650
- * | effect | dependency | updated | 3.18.0 | 3.19.1 |
43651
- *
43652
- * @see {@link DependencyUpdateSchema} for the simpler Changesets API format
43653
- * @see {@link https://effect.website/docs/schema/introduction | Effect Schema documentation}
43654
- *
43655
- */
43656
- /**
43657
- * Valid dependency table actions.
43658
- *
43659
- * @remarks
43660
- * Represents the three possible operations on a dependency: `"added"` for
43661
- * new dependencies, `"updated"` for version changes, and `"removed"` for
43662
- * deletions. Used in the "Action" column of dependency tables.
43663
- *
43664
- * @example
43665
- * ```typescript
43666
- * import { Schema } from "effect";
43667
- * import { DependencyActionSchema } from "@savvy-web/changesets";
43668
- * import type { DependencyAction } from "@savvy-web/changesets";
43669
- *
43670
- * const action: DependencyAction = Schema.decodeUnknownSync(DependencyActionSchema)("updated");
43671
- * ```
43672
- *
43673
- * @public
43674
- */
43675
- const DependencyActionSchema = effect.Schema.Literals([
43676
- "added",
43677
- "updated",
43678
- "removed"
43679
- ]);
43680
- /**
43681
- * Extended dependency types for table format.
43682
- *
43683
- * @remarks
43684
- * Unlike {@link DependencyTypeSchema} (which uses plural npm field names like
43685
- * `"dependencies"`), this schema uses singular forms (`"dependency"`) and adds
43686
- * two additional types: `"workspace"` for monorepo workspace references and
43687
- * `"config"` for configuration toolchain updates (e.g., ESLint, TypeScript).
43688
- *
43689
- * @example
43690
- * ```typescript
43691
- * import { Schema } from "effect";
43692
- * import { DependencyTableTypeSchema } from "@savvy-web/changesets";
43693
- * import type { DependencyTableType } from "@savvy-web/changesets";
43694
- *
43695
- * const tableType: DependencyTableType = Schema.decodeUnknownSync(
43696
- * DependencyTableTypeSchema
43697
- * )("workspace");
43698
- * ```
43699
- *
43700
- * @see {@link DependencyTypeSchema} for the plural npm-field variant
43701
- *
43702
- * @public
43703
- */
43704
- const DependencyTableTypeSchema = effect.Schema.Literals([
43705
- "dependency",
43706
- "devDependency",
43707
- "peerDependency",
43708
- "optionalDependency",
43709
- "workspace",
43710
- "config"
43711
- ]);
43712
- /**
43713
- * The canonical accepted-value pattern for a dependency-table From/To cell:
43714
- * the em-dash sentinel (U+2014), a bare/`~`/`^` semver, or — as a last-resort
43715
- * fallback when a `catalog:`/`workspace:` specifier could not be resolved to a
43716
- * concrete version — a pnpm protocol string. Non-overlapping alternatives keep
43717
- * this free of polynomial backtracking (CodeQL).
43718
- *
43719
- * @public
43720
- */
43721
- const VERSION_RE = /^(\u2014|[~^]?\d+\.\d+\.\d+(?:[-+.][\w.+-]+)?|(?:catalog|workspace|npm|jsr|file|link|portal):[^\s|]+)$/;
43722
- /**
43723
- * Version string or em dash (U+2014) sentinel for added/removed entries.
43724
- *
43725
- * @remarks
43726
- * Accepts either a semver-like version string (with optional `~` or `^`
43727
- * prefix and pre-release/build suffixes) or the em dash character `\u2014`
43728
- * which serves as a sentinel: the "From" column uses `\u2014` for newly
43729
- * added dependencies, and the "To" column uses it for removed ones.
43730
- *
43731
- * @example
43732
- * ```typescript
43733
- * import { Schema } from "effect";
43734
- * import { VersionOrEmptySchema } from "@savvy-web/changesets";
43735
- *
43736
- * // Succeeds — semver version
43737
- * Schema.decodeUnknownSync(VersionOrEmptySchema)("^3.19.1");
43738
- *
43739
- * // Succeeds — em dash sentinel for "no version"
43740
- * Schema.decodeUnknownSync(VersionOrEmptySchema)("\u2014");
43741
- *
43742
- * // Throws ParseError — arbitrary text
43743
- * Schema.decodeUnknownSync(VersionOrEmptySchema)("latest");
43744
- * ```
43745
- *
43746
- * @public
43747
- */
43748
- const VersionOrEmptySchema = effect.Schema.String.check(effect.Schema.isPattern(VERSION_RE));
43749
- /**
43750
- * Schema for a single dependency table row.
43751
- *
43752
- * @remarks
43753
- * Represents one row of a dependency update table in a CHANGELOG.
43754
- * Each row captures the dependency name, its type, the change action,
43755
- * and the "from" and "to" version strings. For added dependencies the
43756
- * `from` field is an em dash; for removed dependencies the `to` field
43757
- * is an em dash.
43758
- *
43759
- * @example
43760
- * ```typescript
43761
- * import { Schema } from "effect";
43762
- * import { DependencyTableRowSchema } from "@savvy-web/changesets";
43763
- * import type { DependencyTableRow } from "@savvy-web/changesets";
43764
- *
43765
- * const row: DependencyTableRow = Schema.decodeUnknownSync(DependencyTableRowSchema)({
43766
- * dependency: "effect",
43767
- * type: "dependency",
43768
- * action: "updated",
43769
- * from: "3.18.0",
43770
- * to: "3.19.1",
43771
- * });
43772
- *
43773
- * // Newly added dependency — "from" is em dash
43774
- * const addedRow: DependencyTableRow = Schema.decodeUnknownSync(DependencyTableRowSchema)({
43775
- * dependency: "@effect/cli",
43776
- * type: "dependency",
43777
- * action: "added",
43778
- * from: "\u2014",
43779
- * to: "0.50.0",
43780
- * });
43781
- * ```
43782
- *
43783
- * @see {@link DependencyTableRow} for the inferred TypeScript type
43784
- * @see {@link DependencyTableSchema} for a non-empty array of rows
43785
- *
43786
- * @public
43787
- */
43788
- const DependencyTableRowSchema = effect.Schema.Struct({
43789
- /** Package or toolchain name. */
43790
- dependency: NonEmptyString,
43791
- /** Dependency type. */
43792
- type: DependencyTableTypeSchema,
43793
- /** Change action. */
43794
- action: DependencyActionSchema,
43795
- /** Previous version (em dash for added). */
43796
- from: VersionOrEmptySchema,
43797
- /** New version (em dash for removed). */
43798
- to: VersionOrEmptySchema
43799
- });
43800
- /**
43801
- * Schema for a dependency table (non-empty array of rows).
43802
- *
43803
- * @remarks
43804
- * Validates that the table contains at least one row. Used to represent
43805
- * the full dependency update table in a changeset or CHANGELOG entry.
43806
- *
43807
- * @example
43808
- * ```typescript
43809
- * import { Schema } from "effect";
43810
- * import { DependencyTableSchema } from "@savvy-web/changesets";
43811
- *
43812
- * const table = Schema.decodeUnknownSync(DependencyTableSchema)([
43813
- * {
43814
- * dependency: "effect",
43815
- * type: "dependency",
43816
- * action: "updated",
43817
- * from: "3.18.0",
43818
- * to: "3.19.1",
43819
- * },
43820
- * {
43821
- * dependency: "typescript",
43822
- * type: "config",
43823
- * action: "updated",
43824
- * from: "5.6.0",
43825
- * to: "5.7.2",
43826
- * },
43827
- * ]);
43828
- *
43829
- * // Throws ParseError — empty array
43830
- * Schema.decodeUnknownSync(DependencyTableSchema)([]);
43831
- * ```
43832
- *
43833
- * @see {@link DependencyTableRowSchema} for the individual row schema
43834
- *
43835
- * @public
43836
- */
43837
- const DependencyTableSchema = effect.Schema.Array(DependencyTableRowSchema).check(effect.Schema.isMinLength(1));
43838
- //#endregion
43839
44577
  //#region ../silk-effects/dist/dev/pkg/changesets/utils/dependency-table.js
43840
44578
  /**
43841
44579
  * Dependency table utilities for parsing, serializing, collapsing, and sorting
@@ -44997,8 +45735,7 @@ function getReleaseLine(changeset, versionType, options) {
44997
45735
  * @remarks
44998
45736
  * The module composes two Effect programs — {@link getReleaseLine} and
44999
45737
  * {@link getDependencyReleaseLine} — and runs each through
45000
- * `Effect.runPromise` with a merged layer of {@link GitHubLive} (for commit
45001
- * metadata) and {@link MarkdownLive} (for mdast parsing). Options are
45738
+ * `Effect.runPromise` with {@link GitHubLive} (for commit metadata). Options are
45002
45739
  * validated at the boundary via `validateChangesetOptions` before being
45003
45740
  * passed to the formatters.
45004
45741
  *
@@ -45038,16 +45775,16 @@ function getReleaseLine(changeset, versionType, options) {
45038
45775
  * @see {@link getDependencyReleaseLine} in `./getDependencyReleaseLine.ts` for dependency table formatting
45039
45776
  */
45040
45777
  /**
45041
- * Combined layer providing all services needed by the formatters.
45778
+ * The layer providing every service the formatters need.
45042
45779
  *
45043
- * Merges {@link GitHubLive} and {@link MarkdownLive} into a single layer
45044
- * that satisfies the environment requirements of both `getReleaseLine`
45045
- * (which needs `GitHubService` and `MarkdownService`) and
45046
- * `getDependencyReleaseLine` (which needs `GitHubService`).
45780
+ * {@link GitHubLive} satisfies the requirements of both `getReleaseLine` and
45781
+ * `getDependencyReleaseLine`, which each need only `GitHubService`. Markdown
45782
+ * parsing is not a layer: the formatters call the remark pipeline's
45783
+ * `parseMarkdown` / `stringifyMarkdown` functions directly.
45047
45784
  *
45048
45785
  * @internal
45049
45786
  */
45050
- const MainLayer = effect.Layer.mergeAll(GitHubLive, MarkdownLive);
45787
+ const MainLayer = GitHubLive;
45051
45788
  /**
45052
45789
  * Changesets API `ChangelogFunctions` implementation.
45053
45790
  *
@@ -45088,8 +45825,7 @@ const changelogFunctions$1 = {
45088
45825
  * Delegates to the Changesets-compatible `getReleaseLine` and
45089
45826
  * `getDependencyReleaseLine` functions. Internally, these use the
45090
45827
  * {@link ChangelogService} Effect service layer, which coordinates
45091
- * the {@link GitHubService} (for commit/PR metadata) and
45092
- * {@link MarkdownService} (for AST manipulation) to produce
45828
+ * the {@link GitHubService} (for commit/PR metadata) to produce
45093
45829
  * structured changelog entries.
45094
45830
  *
45095
45831
  * @remarks
@@ -46779,20 +47515,25 @@ function readRawPackageJson(fs, pkgDir) {
46779
47515
  }
46780
47516
  /**
46781
47517
  * Build resolved scopes from the discovered workspace packages, keeping only
46782
- * those that are a release surface (declare publishConfig that yields at least
46783
- * one publish target). Used both when `.changeset/config.json` declares no
46784
- * explicit `packages` record AND to augment an explicit record with the
46785
- * remaining workspace packages it does not list (so the record annotates the
46786
- * listed packages without shrinking the release surface). The changeset
46787
- * `ignore` list is intentionally NOT consulted here an ignored package still
46788
- * declares publishConfig and remains a valid changeset target.
46789
- */
46790
- function buildFallbackScopes(fs, workspaces) {
47518
+ * those that are a release surface: a package that declares publishConfig
47519
+ * yielding at least one publish target, OR when the changeset config sets
47520
+ * `privatePackages.version: true` (`versionPrivate`) any workspace package
47521
+ * at all, since changesets versions private packages too in that mode (#360:
47522
+ * a private single-root repo with `privatePackages.version: true` previously
47523
+ * produced an empty release surface and left every file unmapped). Used both
47524
+ * when `.changeset/config.json` declares no explicit `packages` record AND to
47525
+ * augment an explicit record with the remaining workspace packages it does
47526
+ * not list (so the record annotates the listed packages without shrinking the
47527
+ * release surface). The changeset `ignore` list is intentionally NOT
47528
+ * consulted here — an ignored package still declares publishConfig and
47529
+ * remains a valid changeset target.
47530
+ */
47531
+ function buildFallbackScopes(fs, workspaces, versionPrivate) {
46791
47532
  return effect.Effect.forEach(workspaces, (ws) => effect.Effect.gen(function* () {
46792
47533
  const raw = yield* readRawPackageJson(fs, ws.path);
46793
47534
  if (raw === null) return [];
46794
47535
  const binding = yield* readTargetsBinding(fs, ws.path);
46795
- if (SilkPublishability.detect(ws.name, raw, binding).length === 0) return [];
47536
+ if (SilkPublishability.detect(ws.name, raw, binding).length === 0 && !versionPrivate) return [];
46796
47537
  return [{
46797
47538
  name: ws.name,
46798
47539
  workspaceDir: ws.path,
@@ -46898,6 +47639,8 @@ function makeShape$3(reader, discovery, fs) {
46898
47639
  version: w.version
46899
47640
  }));
46900
47641
  const hasExplicitPackages = Object.keys(decodedOptions.packages ?? {}).length > 0;
47642
+ const privatePackages = config.privatePackages;
47643
+ const versionPrivate = privatePackages !== void 0 && privatePackages !== false && privatePackages.version === true;
46901
47644
  let scopes;
46902
47645
  if (hasExplicitPackages) {
46903
47646
  const explicitScopes = yield* buildResolvedScopes({
@@ -46913,9 +47656,9 @@ function makeShape$3(reader, discovery, fs) {
46913
47656
  throw e;
46914
47657
  }
46915
47658
  const explicitNames = new Set(explicitScopes.map((s) => s.name));
46916
- const discoveredScopes = yield* buildFallbackScopes(fs, workspaces.filter((w) => !explicitNames.has(w.name)));
47659
+ const discoveredScopes = yield* buildFallbackScopes(fs, workspaces.filter((w) => !explicitNames.has(w.name)), versionPrivate);
46917
47660
  scopes = [...explicitScopes, ...discoveredScopes];
46918
- } else scopes = yield* buildFallbackScopes(fs, workspaces);
47661
+ } else scopes = yield* buildFallbackScopes(fs, workspaces, versionPrivate);
46919
47662
  const inspected = {
46920
47663
  configPath,
46921
47664
  projectDir,
@@ -46949,12 +47692,19 @@ function makeShape$3(reader, discovery, fs) {
46949
47692
  function classifyOne(inspected, path) {
46950
47693
  const abs = (0, node_path.resolve)(inspected.projectDir, path);
46951
47694
  let bestWorkspace = null;
46952
- for (const s of inspected.packages) if (isInside(s.workspaceDir, abs)) {
46953
- const depth = s.workspaceDir.length;
46954
- if (!bestWorkspace || depth > bestWorkspace.depth) bestWorkspace = {
46955
- pkg: s.name,
46956
- depth
46957
- };
47695
+ let rootScope = null;
47696
+ for (const s of inspected.packages) {
47697
+ if (s.workspaceDir === inspected.projectDir) {
47698
+ rootScope = s.name;
47699
+ continue;
47700
+ }
47701
+ if (isInside(s.workspaceDir, abs)) {
47702
+ const depth = s.workspaceDir.length;
47703
+ if (!bestWorkspace || depth > bestWorkspace.depth) bestWorkspace = {
47704
+ pkg: s.name,
47705
+ depth
47706
+ };
47707
+ }
46958
47708
  }
46959
47709
  if (bestWorkspace) return {
46960
47710
  path,
@@ -46981,6 +47731,11 @@ function classifyOne(inspected, path) {
46981
47731
  glob: vf.glob
46982
47732
  }
46983
47733
  };
47734
+ if (rootScope && isInside(inspected.projectDir, abs)) return {
47735
+ path,
47736
+ package: rootScope,
47737
+ reason: "workspace"
47738
+ };
46984
47739
  return {
46985
47740
  path,
46986
47741
  package: null,
@@ -47192,7 +47947,7 @@ function makeBranchAnalyzerTest(fixed) {
47192
47947
  * ```typescript
47193
47948
  * import { Effect } from "effect";
47194
47949
  * import type { ChangesetOptions } from "\@savvy-web/changesets";
47195
- * import { ChangelogService, GitHubLive, MarkdownLive } from "\@savvy-web/changesets";
47950
+ * import { ChangelogService, GitHubLive } from "\@savvy-web/changesets";
47196
47951
  *
47197
47952
  * const program = Effect.gen(function* () {
47198
47953
  * const changelog = yield* ChangelogService;
@@ -66000,9 +66755,7 @@ const changelogFunctions = (/* @__PURE__ */ __exportAll({
66000
66755
  MaintenanceNotePlugin: () => MaintenanceNotePlugin,
66001
66756
  MaintenanceReasonSchema: () => MaintenanceReasonSchema,
66002
66757
  MaintenanceTriggerSchema: () => MaintenanceTriggerSchema,
66003
- MarkdownLive: () => MarkdownLive,
66004
66758
  MarkdownParseError: () => MarkdownParseError,
66005
- MarkdownService: () => MarkdownService,
66006
66759
  MarkdownlintContentStructureRule: () => ContentStructureRule,
66007
66760
  MarkdownlintDependencyTableFormatRule: () => DependencyTableFormatRule,
66008
66761
  MarkdownlintHeadingHierarchyRule: () => HeadingHierarchyRule,