@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.
@@ -173,37 +173,6 @@ const SilkChangesetConfigFile = Schema.Struct({
173
173
  ...ChangesetConfigFile.fields,
174
174
  _isSilk: Schema.Boolean.pipe(Schema.withDecodingDefaultType(Effect.succeed(true)), Schema.withConstructorDefault(Effect.succeed(true)))
175
175
  });
176
- /**
177
- * Versioning strategy classification for a workspace.
178
- *
179
- * @remarks
180
- * - `"single"` — one publishable package; a single version tag is used.
181
- * - `"fixed-group"` — all publishable packages are in the same changesets fixed group.
182
- * - `"independent"` — multiple publishable packages with independent version bumps.
183
- *
184
- * @since 0.1.0
185
- * @public
186
- */
187
- const VersioningStrategyType = Schema.Literals([
188
- "single",
189
- "fixed-group",
190
- "independent"
191
- ]);
192
- /**
193
- * Output of the versioning strategy detection, combining the strategy type with group metadata.
194
- *
195
- * @remarks
196
- * Produced by `VersioningStrategy.detect` and consumed by `TagStrategy.determine`
197
- * to decide on the appropriate git-tag format.
198
- *
199
- * @since 0.1.0
200
- * @public
201
- */
202
- const VersioningStrategyResult = Schema.Struct({
203
- type: VersioningStrategyType,
204
- fixedGroups: Schema.Array(Schema.Array(Schema.String)),
205
- publishablePackages: Schema.Array(Schema.String)
206
- });
207
176
 
208
177
  //#endregion
209
178
  //#region ../silk-effects/dist/dev/pkg/services/ChangesetConfigReader.js
@@ -2381,7 +2350,7 @@ var GlobSet = class GlobSet extends Schema.Class("GlobSet")(Schema.Struct({ patt
2381
2350
  };
2382
2351
 
2383
2352
  //#endregion
2384
- //#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
2353
+ //#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
2385
2354
  /**
2386
2355
  * Extension data specific to bun lockfiles, attached to `Lockfile.extension`
2387
2356
  * when the format is `"bun"`.
@@ -2403,7 +2372,7 @@ var BunExtension = class extends Schema.Class("BunExtension")({
2403
2372
  }) {};
2404
2373
 
2405
2374
  //#endregion
2406
- //#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
2375
+ //#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
2407
2376
  /**
2408
2377
  * Contract for resolving pnpm `catalog:` dependency specifiers to concrete
2409
2378
  * version ranges.
@@ -2450,7 +2419,7 @@ var CatalogResolver = class CatalogResolver extends Context.Service()("@effected
2450
2419
  };
2451
2420
 
2452
2421
  //#endregion
2453
- //#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
2422
+ //#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
2454
2423
  /**
2455
2424
  * Raised when a `catalog:` or `workspace:` specifier cannot be resolved
2456
2425
  * because the resolution mechanism itself failed — not for an ordinary
@@ -2512,7 +2481,7 @@ var WorkspaceResolver = class WorkspaceResolver extends Context.Service()("@effe
2512
2481
  };
2513
2482
 
2514
2483
  //#endregion
2515
- //#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
2484
+ //#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
2516
2485
  /**
2517
2486
  * Raised when a workspace's catalogs cannot be assembled — a `pnpm-workspace.yaml`
2518
2487
  * that is unreadable or not valid YAML, a root `package.json` `workspaces` field
@@ -2557,7 +2526,7 @@ var CatalogAssemblyError = class extends Schema.TaggedErrorClass()("CatalogAssem
2557
2526
  };
2558
2527
 
2559
2528
  //#endregion
2560
- //#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
2529
+ //#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
2561
2530
  /**
2562
2531
  * The short dependency kind: which dependency map an entry came from, named the
2563
2532
  * way consumers branch on it.
@@ -4067,7 +4036,7 @@ const isComparatorSetSubset = (sub, sup) => {
4067
4036
  };
4068
4037
 
4069
4038
  //#endregion
4070
- //#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
4039
+ //#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
4071
4040
  /**
4072
4041
  * Indicates that a string could not be parsed as a valid dependency specifier.
4073
4042
  *
@@ -4275,7 +4244,7 @@ const DependencySpecifier = Object.assign(brandedSpecifier, {
4275
4244
  });
4276
4245
 
4277
4246
  //#endregion
4278
- //#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
4247
+ //#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
4279
4248
  const SRI_RE = /^(sha1|sha256|sha384|sha512)-[A-Za-z0-9+/]+={0,2}$/;
4280
4249
  const COREPACK_RE = /^(sha1|sha256|sha384|sha512)\.[0-9a-f]+$/;
4281
4250
  const YARN_RE = /^[0-9]+(c[0-9]+)?\/[0-9a-f]+$/;
@@ -4329,7 +4298,180 @@ const IntegrityHash = Object.assign(brandedIntegrity, {
4329
4298
  });
4330
4299
 
4331
4300
  //#endregion
4332
- //#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
4301
+ //#region ../../node_modules/.pnpm/@effected+commands@0.1.0_effect@4.0.0-beta.101/node_modules/@effected/commands/LocalExec.js
4302
+ /**
4303
+ * The package managers whose project-local exec argv this package knows.
4304
+ *
4305
+ * @remarks
4306
+ * Structurally identical to `@effected/workspaces`' `PackageManagerName` and
4307
+ * assigns freely to and from it — deliberately **not** an import, because this
4308
+ * package takes no `@effected` edges. The names are a four-value literal; the
4309
+ * *detection* of which one owns a directory is what
4310
+ * `@effected/workspaces` contributes, through {@link LocalExec}.
4311
+ *
4312
+ * @public
4313
+ */
4314
+ const Launcher = Schema.Literals([
4315
+ "npm",
4316
+ "pnpm",
4317
+ "yarn",
4318
+ "bun"
4319
+ ]);
4320
+ /** The argv prefixes for each launcher. The one place this knowledge lives. */
4321
+ const PREFIXES = {
4322
+ npm: {
4323
+ prefix: [
4324
+ "npx",
4325
+ "--no",
4326
+ "--"
4327
+ ],
4328
+ dlxPrefix: ["npx"]
4329
+ },
4330
+ pnpm: {
4331
+ prefix: ["pnpm", "exec"],
4332
+ dlxPrefix: ["pnpm", "dlx"]
4333
+ },
4334
+ yarn: {
4335
+ prefix: ["yarn", "exec"],
4336
+ dlxPrefix: ["yarn", "dlx"]
4337
+ },
4338
+ bun: {
4339
+ prefix: [
4340
+ "bun",
4341
+ "x",
4342
+ "--no-install"
4343
+ ],
4344
+ dlxPrefix: ["bun", "x"]
4345
+ }
4346
+ };
4347
+ /**
4348
+ * How to run a project-local binary here.
4349
+ *
4350
+ * @remarks
4351
+ * This is the whole of what tool discovery needs from a workspace: an argv
4352
+ * prefix and a directory to run it in. It deliberately carries no workspace
4353
+ * root, no manifest and no package-manager semantics — `label` is for
4354
+ * reporting only, and nothing in this package branches on it.
4355
+ *
4356
+ * @public
4357
+ */
4358
+ var ExecContext = class extends Schema.Class("ExecContext")({
4359
+ /** Human label of the launcher, e.g. `"pnpm"`. Reporting only. */
4360
+ label: Schema.String,
4361
+ /** argv prefix that runs a project-local binary, e.g. `["pnpm", "exec"]`. */
4362
+ prefix: Schema.Array(Schema.String),
4363
+ /** argv prefix that fetch-and-runs a package binary, e.g. `["pnpm", "dlx"]`. */
4364
+ dlxPrefix: Schema.Array(Schema.String),
4365
+ /** Directory the prefix must run in. Omitted means "wherever the caller is". */
4366
+ directory: Schema.optionalKey(Schema.String)
4367
+ }) {
4368
+ /** Prefixes `command` with `prefix` and applies `directory`, returning a core `Command`. */
4369
+ apply(command) {
4370
+ return this.withPrefix(command, this.prefix);
4371
+ }
4372
+ /** As {@link ExecContext.apply}, using `dlxPrefix` — the fetch-and-run launcher. */
4373
+ applyDlx(command) {
4374
+ return this.withPrefix(command, this.dlxPrefix);
4375
+ }
4376
+ /**
4377
+ * Core's `prefix` and `setCwd` both return NEW commands, so the caller's
4378
+ * value is never mutated.
4379
+ */
4380
+ withPrefix(command, prefix) {
4381
+ const [head, ...rest] = prefix;
4382
+ const prefixed = head === void 0 ? command : ChildProcess.prefix(command, head, rest);
4383
+ return this.directory === void 0 ? prefixed : ChildProcess.setCwd(prefixed, this.directory);
4384
+ }
4385
+ };
4386
+ /**
4387
+ * The project-local execution context could not be determined.
4388
+ *
4389
+ * @remarks
4390
+ * A *mechanism* failure — an unreadable manifest, a detection error. "There is
4391
+ * no project-local way to run tools here" is `Option.none()`, never this error:
4392
+ * the same `None`-is-success convention `@effected/npm`'s resolver contracts
4393
+ * use, so an implementation never has to decide whether absence is exceptional.
4394
+ *
4395
+ * @public
4396
+ */
4397
+ var LocalExecError = class extends Schema.TaggedErrorClass()("LocalExecError", {
4398
+ /** The directory whose context could not be determined, when one is known. */
4399
+ directory: Schema.optionalKey(Schema.String),
4400
+ /** The underlying failure. */
4401
+ cause: Schema.optionalKey(Schema.Defect())
4402
+ }) {
4403
+ get message() {
4404
+ return this.directory === void 0 ? "Could not determine the project-local execution context" : `Could not determine the project-local execution context for ${this.directory}`;
4405
+ }
4406
+ };
4407
+ /**
4408
+ * Contract: how to run a project-local binary in this project.
4409
+ *
4410
+ * @remarks
4411
+ * **This is an inverted contract.** Tool discovery needs package-manager
4412
+ * detection and workspace-root resolution, both of which live in the
4413
+ * integrated-tier `@effected/workspaces`. Depending on it directly would make
4414
+ * this package integrated too — and, through the planned `@effected/npm` edge,
4415
+ * would drag `npm`, `lockfiles` and `package-json` up a tier with it. So this
4416
+ * package declares the narrow contract and `@effected/workspaces` ships the
4417
+ * layer that implements it, exactly as `@effected/npm` owns `CatalogResolver`
4418
+ * and workspaces implements that.
4419
+ *
4420
+ * A consumer with no monorepo never needs that implementation:
4421
+ * {@link LocalExec.layerNone} (global-only) and {@link LocalExec.layerFor}
4422
+ * (a known package manager) are one-liners.
4423
+ *
4424
+ * @public
4425
+ */
4426
+ var LocalExec = class LocalExec extends Context.Service()("@effected/commands/LocalExec") {
4427
+ /** The exec and dlx argv prefixes for a launcher — the single home of that knowledge. */
4428
+ static prefixes = (launcher) => PREFIXES[launcher];
4429
+ /**
4430
+ * No project-local execution context: every tool resolves globally.
4431
+ *
4432
+ * @remarks
4433
+ * The right wiring for a GitHub Action or any single-package checkout, and
4434
+ * the reason such a consumer never installs `@effected/workspaces`.
4435
+ */
4436
+ static layerNone = Layer.succeed(this, { context: Effect.succeed(Option.none()) });
4437
+ /** A context for a known package manager, from the static prefix table. */
4438
+ static layerFor = (launcher, options) => {
4439
+ const { prefix, dlxPrefix } = PREFIXES[launcher];
4440
+ return LocalExec.layerContext(ExecContext.make({
4441
+ label: launcher,
4442
+ prefix,
4443
+ dlxPrefix,
4444
+ ...options?.directory === void 0 ? {} : { directory: options.directory }
4445
+ }));
4446
+ };
4447
+ /** A caller-supplied context, answered verbatim. */
4448
+ static layerContext = (context) => Layer.succeed(LocalExec, { context: Effect.succeed(Option.some(context)) });
4449
+ /**
4450
+ * An in-memory test double.
4451
+ *
4452
+ * @remarks
4453
+ * Unlike most `makeTest` doubles in the kit, the unstubbed default here is
4454
+ * **honest rather than loud**: `Option.none()` is a real, correct answer
4455
+ * ("no project-local context"), so a test that does not care about local
4456
+ * resolution gets the global-only behavior instead of a defect.
4457
+ */
4458
+ static makeTest = (overrides = {}) => ({
4459
+ context: Effect.succeed(Option.none()),
4460
+ ...overrides
4461
+ });
4462
+ /**
4463
+ * {@link LocalExec.makeTest} behind `Layer.succeed`.
4464
+ *
4465
+ * @remarks
4466
+ * A parameterized layer factory mints a fresh reference per call and layers
4467
+ * memoize by reference — bind the result to a `const` rather than calling it
4468
+ * at each composition site.
4469
+ */
4470
+ static layerTest = (overrides = {}) => Layer.succeed(LocalExec, LocalExec.makeTest(overrides));
4471
+ };
4472
+
4473
+ //#endregion
4474
+ //#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
4333
4475
  const MS_PER_MINUTE = 6e4;
4334
4476
  /**
4335
4477
  * A source's partial contribution to a {@link ReleaseAgeGate}: the effective
@@ -4417,7 +4559,9 @@ var ReleaseAgeGate = class ReleaseAgeGate extends Schema.Class("ReleaseAgeGate")
4417
4559
  * Combine partial contributions from multiple sources into one effective
4418
4560
  * gate: **strictest age wins** (the maximum of the contributed ages,
4419
4561
  * clamped to be non-negative) and the exclude sets **union** (deduplicated,
4420
- * insertion order preserved). A contribution's absent field adds nothing; a
4562
+ * lexicographically sorted a canonical wire form, so the combined gate is
4563
+ * deterministic regardless of the order contributions arrive in). A
4564
+ * contribution's absent field adds nothing; a
4421
4565
  * negative or non-finite contributed age is ignored by the clamp. With no
4422
4566
  * contributions (or only empty ones) the result is the inert zero gate
4423
4567
  * (`ageMinutes: 0`, `exclude: []`).
@@ -4431,7 +4575,7 @@ var ReleaseAgeGate = class ReleaseAgeGate extends Schema.Class("ReleaseAgeGate")
4431
4575
  static combine(...contributions) {
4432
4576
  const ages = contributions.map((contribution) => contribution.ageMinutes).filter((age) => typeof age === "number" && Number.isFinite(age));
4433
4577
  const ageMinutes = ages.length > 0 ? Math.max(0, ...ages) : 0;
4434
- const exclude = [...new Set(contributions.flatMap((contribution) => contribution.exclude ?? []))];
4578
+ const exclude = [...new Set(contributions.flatMap((contribution) => contribution.exclude ?? []))].sort();
4435
4579
  return ReleaseAgeGate.make({
4436
4580
  ageMinutes,
4437
4581
  exclude
@@ -4498,7 +4642,7 @@ var ReleaseAgeGate = class ReleaseAgeGate extends Schema.Class("ReleaseAgeGate")
4498
4642
  };
4499
4643
 
4500
4644
  //#endregion
4501
- //#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
4645
+ //#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
4502
4646
  /**
4503
4647
  * One declared dependency of one workspace importer, as the lockfile records it.
4504
4648
  *
@@ -4509,11 +4653,20 @@ var ReleaseAgeGate = class ReleaseAgeGate extends Schema.Class("ReleaseAgeGate")
4509
4653
  * `ClassifiedSpecifier` (`catalog:` / `workspace:` / range / dist-tag / raw),
4510
4654
  * while encoding round-trips the **exact original string byte-for-byte** — the
4511
4655
  * guarantee a before/after lockfile diff relies on.
4512
- * - `version` — the concrete resolved version, **populated by pnpm only**. pnpm
4513
- * records `{ specifier, version }` per importer dependency; bun and npm record
4514
- * resolved versions on their package entries instead, so for those formats
4515
- * `version` is absent and a consumer joins by `name` against
4516
- * `Lockfile.packages`.
4656
+ * - `version` — the concrete resolved version, **populated by pnpm only**:
4657
+ * comparable across refs and printable. pnpm records `{ specifier, version }`
4658
+ * per importer dependency, and the parser splits pnpm's peer-disambiguation
4659
+ * suffix off into `peerSuffix`, so `version` is always the plain version or
4660
+ * a non-registry resolution (`link:../utils`, `file:...`), passed through
4661
+ * verbatim. bun and npm record resolved versions on their package entries
4662
+ * instead, so for those formats `version` is absent and a consumer joins by
4663
+ * `name` against `Lockfile.packages`.
4664
+ * - `peerSuffix` — pnpm's peer-disambiguation context: the raw parenthesized
4665
+ * chain the lockfile recorded after the version, e.g.
4666
+ * `(effect@4.0.0-beta.101)(ioredis@5.11.1(supports-color@8.1.1))`. Present
4667
+ * only when the lockfile recorded one — never for suffix-free pnpm entries,
4668
+ * and never for the other formats, which do not record peer context per
4669
+ * importer dependency.
4517
4670
  * - `depType` — which dependency map declared it, spelled with `@effected/npm`'s
4518
4671
  * kit-wide `DependencyField` vocabulary.
4519
4672
  *
@@ -4523,11 +4676,12 @@ var ImporterDependency = class extends Schema.Class("ImporterDependency")({
4523
4676
  name: Schema.NonEmptyString,
4524
4677
  specifier: DependencySpecifier.FromString,
4525
4678
  version: Schema.optionalKey(Schema.String),
4679
+ peerSuffix: Schema.optionalKey(Schema.String),
4526
4680
  depType: DependencyField
4527
4681
  }) {};
4528
4682
 
4529
4683
  //#endregion
4530
- //#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
4684
+ //#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
4531
4685
  /**
4532
4686
  * One workspace importer's declared dependencies, as the lockfile records them.
4533
4687
  *
@@ -4552,7 +4706,7 @@ var LockfileImporter = class extends Schema.Class("LockfileImporter")({
4552
4706
  }) {};
4553
4707
 
4554
4708
  //#endregion
4555
- //#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
4709
+ //#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
4556
4710
  const EMPTY_DEPENDENCIES = {};
4557
4711
  /**
4558
4712
  * A package resolved from a lockfile.
@@ -4588,7 +4742,7 @@ var ResolvedPackage = class extends Schema.Class("ResolvedPackage")({
4588
4742
  }) {};
4589
4743
 
4590
4744
  //#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/WorkspaceDependency.js
4745
+ //#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
4592
4746
  /**
4593
4747
  * A directed dependency edge between two workspace packages as recorded in
4594
4748
  * the lockfile.
@@ -4611,7 +4765,7 @@ var WorkspaceDependency = class extends Schema.Class("WorkspaceDependency")({
4611
4765
  }) {};
4612
4766
 
4613
4767
  //#endregion
4614
- //#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
4768
+ //#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
4615
4769
  /**
4616
4770
  * Extension data specific to pnpm lockfiles, attached to `Lockfile.extension`
4617
4771
  * when the format is `"pnpm"`.
@@ -4637,7 +4791,7 @@ var PnpmExtension = class extends Schema.Class("PnpmExtension")({
4637
4791
  }) {};
4638
4792
 
4639
4793
  //#endregion
4640
- //#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
4794
+ //#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
4641
4795
  /**
4642
4796
  * The lockfile formats this package parses: bun's `bun.lock` (JSONC), npm's
4643
4797
  * `package-lock.json` (v2/v3 JSON), pnpm's `pnpm-lock.yaml` and yarn Berry's
@@ -4672,7 +4826,7 @@ const FILENAMES = {
4672
4826
  const filenameFor = (format) => FILENAMES[format];
4673
4827
 
4674
4828
  //#endregion
4675
- //#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
4829
+ //#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
4676
4830
  /**
4677
4831
  * The four dependency sections of a manifest, in a stable order — the shared
4678
4832
  * dependency-sections table (v3's `DEP_SECTIONS`). Each entry is both the
@@ -4711,22 +4865,54 @@ const toIntegrityHash = (raw) => {
4711
4865
  };
4712
4866
  const decodeSpecifier = Schema.decodeUnknownExit(DependencySpecifier.FromString);
4713
4867
  /**
4868
+ * Split pnpm's peer-disambiguation suffix off a recorded string: everything
4869
+ * from the first `(` on is suffix, since package names and versions never
4870
+ * contain `(`. Handles both shapes pnpm records — a bare version
4871
+ * (`"1.0.0(effect@4.0.0)"`, importer entries) and a `name@version` snapshot key
4872
+ * (`"fdir@6.5.0(picomatch@4.0.4)"`). A string with no `(` — including
4873
+ * `link:...` / `file:...` resolutions — passes through untouched. So does a
4874
+ * protocol-bearing string (a `:` ahead of the first `(`), where a parenthesis
4875
+ * is path or URL text rather than a peer suffix: pnpm attaches suffixes to
4876
+ * registry versions only. This is the single stripping implementation — do not
4877
+ * hand-roll an `indexOf("(")` split elsewhere.
4878
+ *
4879
+ * @internal
4880
+ */
4881
+ const splitPeerSuffix = (raw) => {
4882
+ const parenIndex = raw.indexOf("(");
4883
+ if (parenIndex === -1) return { plain: raw };
4884
+ if (raw.lastIndexOf(":", parenIndex) !== -1) return { plain: raw };
4885
+ return {
4886
+ plain: raw.slice(0, parenIndex),
4887
+ peerSuffix: raw.slice(parenIndex)
4888
+ };
4889
+ };
4890
+ /**
4714
4891
  * Build one {@link ImporterDependency}, decoding the raw specifier string into
4715
4892
  * the `@effected/npm` `ClassifiedSpecifier` tagged union. Returns `undefined`
4716
4893
  * — a skip, never a throw — when the name is empty or the specifier does not
4717
4894
  * classify (e.g. an empty specifier), per the total-string-surgery discipline.
4718
4895
  *
4896
+ * A pnpm-recorded version is normalized through {@link splitPeerSuffix}: the
4897
+ * `version` field carries the plain version and the split-off peer chain lands
4898
+ * in `peerSuffix`. A version that is *only* a peer chain (empty plain part) is
4899
+ * treated as no concrete version — a skip of both fields, never a throw.
4900
+ *
4719
4901
  * @internal
4720
4902
  */
4721
4903
  const buildImporterDependency = (name, specifier, depType, version) => {
4722
4904
  if (name === "") return void 0;
4723
4905
  const exit = decodeSpecifier(specifier);
4724
4906
  if (Exit.isFailure(exit)) return void 0;
4907
+ const resolved = version !== void 0 && version !== "" ? splitPeerSuffix(version) : void 0;
4725
4908
  return ImporterDependency.make({
4726
4909
  name,
4727
4910
  specifier: exit.value,
4728
4911
  depType,
4729
- ...version !== void 0 && version !== "" ? { version } : {}
4912
+ ...resolved !== void 0 && resolved.plain !== "" ? {
4913
+ version: resolved.plain,
4914
+ ...resolved.peerSuffix !== void 0 ? { peerSuffix: resolved.peerSuffix } : {}
4915
+ } : {}
4730
4916
  });
4731
4917
  };
4732
4918
  /**
@@ -6614,7 +6800,7 @@ var JsoncModifier = class {
6614
6800
  };
6615
6801
 
6616
6802
  //#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/bun.js
6803
+ //#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
6618
6804
  const DepRecord$2 = Schema.optionalKey(Schema.Record(Schema.String, Schema.String));
6619
6805
  const BunWorkspaceEntry = Schema.Struct({
6620
6806
  name: Schema.optionalKey(Schema.String),
@@ -6708,7 +6894,7 @@ const toFields$3 = (raw) => Effect.gen(function* () {
6708
6894
  });
6709
6895
 
6710
6896
  //#endregion
6711
- //#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
6897
+ //#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
6712
6898
  const DepRecord$1 = Schema.optionalKey(Schema.Record(Schema.String, Schema.String));
6713
6899
  const NpmPackageEntry = Schema.Struct({
6714
6900
  name: Schema.optionalKey(Schema.String),
@@ -6807,7 +6993,7 @@ const toFields$2 = (raw) => Effect.gen(function* () {
6807
6993
  });
6808
6994
 
6809
6995
  //#endregion
6810
- //#region ../../node_modules/.pnpm/@effected+yaml@0.5.1_effect@4.0.0-beta.101/node_modules/@effected/yaml/YamlNode.js
6996
+ //#region ../../node_modules/.pnpm/@effected+yaml@0.6.0_effect@4.0.0-beta.101/node_modules/@effected/yaml/YamlNode.js
6811
6997
  /**
6812
6998
  * YAML scalar presentation styles.
6813
6999
  *
@@ -7210,7 +7396,7 @@ function nodeToValue(node, anchors, budget, counting = false) {
7210
7396
  }
7211
7397
 
7212
7398
  //#endregion
7213
- //#region ../../node_modules/.pnpm/@effected+yaml@0.5.1_effect@4.0.0-beta.101/node_modules/@effected/yaml/internal/diagnostics.js
7399
+ //#region ../../node_modules/.pnpm/@effected+yaml@0.6.0_effect@4.0.0-beta.101/node_modules/@effected/yaml/internal/diagnostics.js
7214
7400
  /** Error codes emitted by the lexer stage. */
7215
7401
  const YAML_LEX_ERROR_CODES = [
7216
7402
  "UnexpectedCharacter",
@@ -7289,7 +7475,7 @@ function isFatalCode(code) {
7289
7475
  }
7290
7476
 
7291
7477
  //#endregion
7292
- //#region ../../node_modules/.pnpm/@effected+yaml@0.5.1_effect@4.0.0-beta.101/node_modules/@effected/yaml/YamlDiagnostic.js
7478
+ //#region ../../node_modules/.pnpm/@effected+yaml@0.6.0_effect@4.0.0-beta.101/node_modules/@effected/yaml/YamlDiagnostic.js
7293
7479
  /**
7294
7480
  * Error codes emitted by the lexer stage.
7295
7481
  *
@@ -7411,7 +7597,7 @@ function lineChar(text, offset) {
7411
7597
  }
7412
7598
 
7413
7599
  //#endregion
7414
- //#region ../../node_modules/.pnpm/@effected+yaml@0.5.1_effect@4.0.0-beta.101/node_modules/@effected/yaml/internal/composer/anchors.js
7600
+ //#region ../../node_modules/.pnpm/@effected+yaml@0.6.0_effect@4.0.0-beta.101/node_modules/@effected/yaml/internal/composer/anchors.js
7415
7601
  /**
7416
7602
  * Check if a pending anchor is being applied to an alias node (invalid in YAML 1.2 §3.2.2).
7417
7603
  * Aliases represent references to existing anchored nodes and cannot have their own anchors.
@@ -7505,7 +7691,7 @@ function collectAnchors(node, anchors) {
7505
7691
  }
7506
7692
 
7507
7693
  //#endregion
7508
- //#region ../../node_modules/.pnpm/@effected+yaml@0.5.1_effect@4.0.0-beta.101/node_modules/@effected/yaml/internal/lexer.js
7694
+ //#region ../../node_modules/.pnpm/@effected+yaml@0.6.0_effect@4.0.0-beta.101/node_modules/@effected/yaml/internal/lexer.js
7509
7695
  /**
7510
7696
  * Create a new YAML scanner for the given source text.
7511
7697
  *
@@ -8463,7 +8649,7 @@ function lexAll(text) {
8463
8649
  }
8464
8650
 
8465
8651
  //#endregion
8466
- //#region ../../node_modules/.pnpm/@effected+yaml@0.5.1_effect@4.0.0-beta.101/node_modules/@effected/yaml/internal/cst-parser.js
8652
+ //#region ../../node_modules/.pnpm/@effected+yaml@0.6.0_effect@4.0.0-beta.101/node_modules/@effected/yaml/internal/cst-parser.js
8467
8653
  /**
8468
8654
  * Hardening: cap CST nesting so hostile inputs cannot overflow the stack
8469
8655
  * while the tree is being BUILT. Set slightly above the composer's
@@ -9176,7 +9362,7 @@ function parseCSTAll(text) {
9176
9362
  }
9177
9363
 
9178
9364
  //#endregion
9179
- //#region ../../node_modules/.pnpm/@effected+yaml@0.5.1_effect@4.0.0-beta.101/node_modules/@effected/yaml/internal/composer/state.js
9365
+ //#region ../../node_modules/.pnpm/@effected+yaml@0.6.0_effect@4.0.0-beta.101/node_modules/@effected/yaml/internal/composer/state.js
9180
9366
  let lineStartsText;
9181
9367
  let lineStartsCache = [];
9182
9368
  function getLineStarts(text) {
@@ -9283,7 +9469,7 @@ function exitNesting(state) {
9283
9469
  }
9284
9470
 
9285
9471
  //#endregion
9286
- //#region ../../node_modules/.pnpm/@effected+yaml@0.5.1_effect@4.0.0-beta.101/node_modules/@effected/yaml/internal/composer/tags.js
9472
+ //#region ../../node_modules/.pnpm/@effected+yaml@0.6.0_effect@4.0.0-beta.101/node_modules/@effected/yaml/internal/composer/tags.js
9287
9473
  /**
9288
9474
  * Resolve a tag shorthand using the document's %TAG directives.
9289
9475
  * For example, with `%TAG !! tag:example.com,2000:app/`, the tag `!!int`
@@ -9370,7 +9556,7 @@ function validateTagHandlesInDocument(docCst, state) {
9370
9556
  }
9371
9557
 
9372
9558
  //#endregion
9373
- //#region ../../node_modules/.pnpm/@effected+yaml@0.5.1_effect@4.0.0-beta.101/node_modules/@effected/yaml/internal/composer/scalars.js
9559
+ //#region ../../node_modules/.pnpm/@effected+yaml@0.6.0_effect@4.0.0-beta.101/node_modules/@effected/yaml/internal/composer/scalars.js
9374
9560
  const NULL_RE$1 = /^(?:null|Null|NULL|~)$/;
9375
9561
  const TRUE_RE$1 = /^(?:true|True|TRUE)$/;
9376
9562
  const FALSE_RE$1 = /^(?:false|False|FALSE)$/;
@@ -10249,7 +10435,7 @@ function shouldPreserveRaw(rawValue, value) {
10249
10435
  }
10250
10436
 
10251
10437
  //#endregion
10252
- //#region ../../node_modules/.pnpm/@effected+yaml@0.5.1_effect@4.0.0-beta.101/node_modules/@effected/yaml/internal/composer/block.js
10438
+ //#region ../../node_modules/.pnpm/@effected+yaml@0.6.0_effect@4.0.0-beta.101/node_modules/@effected/yaml/internal/composer/block.js
10253
10439
  /**
10254
10440
  * Compose a block map from its CST children, with an optional external first key.
10255
10441
  *
@@ -11398,7 +11584,7 @@ function composeFlatBlockMap(children, startIdx, parentCst, state, externalFirst
11398
11584
  }
11399
11585
 
11400
11586
  //#endregion
11401
- //#region ../../node_modules/.pnpm/@effected+yaml@0.5.1_effect@4.0.0-beta.101/node_modules/@effected/yaml/internal/composer/flow.js
11587
+ //#region ../../node_modules/.pnpm/@effected+yaml@0.6.0_effect@4.0.0-beta.101/node_modules/@effected/yaml/internal/composer/flow.js
11402
11588
  /**
11403
11589
  * Validate that flow collection entries are separated by commas.
11404
11590
  *
@@ -11791,7 +11977,7 @@ function composeFlowSeqInner(cst, state, meta, parentBlockColumn) {
11791
11977
  }
11792
11978
 
11793
11979
  //#endregion
11794
- //#region ../../node_modules/.pnpm/@effected+yaml@0.5.1_effect@4.0.0-beta.101/node_modules/@effected/yaml/internal/composer/document.js
11980
+ //#region ../../node_modules/.pnpm/@effected+yaml@0.6.0_effect@4.0.0-beta.101/node_modules/@effected/yaml/internal/composer/document.js
11795
11981
  /** The flow-composer dispatch wired into every state this module creates. */
11796
11982
  const FLOW = {
11797
11983
  composeFlowMap,
@@ -12458,7 +12644,7 @@ function composeAllDocuments(text, options) {
12458
12644
  }
12459
12645
 
12460
12646
  //#endregion
12461
- //#region ../../node_modules/.pnpm/@effected+yaml@0.5.1_effect@4.0.0-beta.101/node_modules/@effected/yaml/internal/fold.js
12647
+ //#region ../../node_modules/.pnpm/@effected+yaml@0.6.0_effect@4.0.0-beta.101/node_modules/@effected/yaml/internal/fold.js
12462
12648
  /**
12463
12649
  * Column-based line folding for a single logical scalar line (YAML 1.2 flow
12464
12650
  * folding, §7.3 / §8.2.1). Breaks the content at "safe" single-space
@@ -12695,7 +12881,7 @@ function renderBlockFolded(s, indent) {
12695
12881
  }
12696
12882
 
12697
12883
  //#endregion
12698
- //#region ../../node_modules/.pnpm/@effected+yaml@0.5.1_effect@4.0.0-beta.101/node_modules/@effected/yaml/internal/stringifier.js
12884
+ //#region ../../node_modules/.pnpm/@effected+yaml@0.6.0_effect@4.0.0-beta.101/node_modules/@effected/yaml/internal/stringifier.js
12699
12885
  /**
12700
12886
  * Thrown by the stringifier on its failure paths (circular references). The
12701
12887
  * facade catches this and materializes the public stringify error.
@@ -13067,7 +13253,7 @@ function stringifyValue(value, options) {
13067
13253
  }
13068
13254
 
13069
13255
  //#endregion
13070
- //#region ../../node_modules/.pnpm/@effected+yaml@0.5.1_effect@4.0.0-beta.101/node_modules/@effected/yaml/Yaml.js
13256
+ //#region ../../node_modules/.pnpm/@effected+yaml@0.6.0_effect@4.0.0-beta.101/node_modules/@effected/yaml/Yaml.js
13071
13257
  /**
13072
13258
  * Options controlling parse behavior. All fields are omissible; absent fields
13073
13259
  * resolve to `strict` `true`, `maxAliasCount` `100` (the alias-based
@@ -13719,7 +13905,7 @@ function deepEqualValues(a, b) {
13719
13905
  }
13720
13906
 
13721
13907
  //#endregion
13722
- //#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
13908
+ //#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
13723
13909
  /**
13724
13910
  * An empty YAML document composes to `null` (`Yaml.parseAll("")` is `[null]`,
13725
13911
  * and the trailing document of an env-only `pnpm-lock.yaml` is `null` too).
@@ -13790,7 +13976,7 @@ const selectSoleDocument = (content) => Effect.gen(function* () {
13790
13976
  });
13791
13977
 
13792
13978
  //#endregion
13793
- //#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
13979
+ //#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
13794
13980
  const PnpmImporterDeps = Schema.optionalKey(Schema.Record(Schema.String, Schema.Struct({
13795
13981
  specifier: Schema.String,
13796
13982
  version: Schema.String
@@ -13887,8 +14073,7 @@ const toFields$1 = (raw) => Effect.gen(function* () {
13887
14073
  }));
13888
14074
  }
13889
14075
  if (raw.packages) for (const [key, pkg] of Object.entries(raw.packages)) {
13890
- const parenIndex = key.indexOf("(");
13891
- const bare = parenIndex === -1 ? key : key.slice(0, parenIndex);
14076
+ const { plain: bare } = splitPeerSuffix(key);
13892
14077
  const atIndex = bare.lastIndexOf("@");
13893
14078
  if (atIndex <= 0) continue;
13894
14079
  const name = bare.slice(0, atIndex);
@@ -13917,7 +14102,7 @@ const toFields$1 = (raw) => Effect.gen(function* () {
13917
14102
  });
13918
14103
 
13919
14104
  //#endregion
13920
- //#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
14105
+ //#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
13921
14106
  const YarnLockfileRaw = Schema.Record(Schema.String, Schema.Unknown);
13922
14107
  const DepRecord = Schema.optionalKey(Schema.Record(Schema.String, Schema.String));
13923
14108
  const YarnEntry = Schema.Struct({
@@ -14041,7 +14226,7 @@ const cleanYarnDeps = (deps) => {
14041
14226
  };
14042
14227
 
14043
14228
  //#endregion
14044
- //#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
14229
+ //#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
14045
14230
  const EMPTY_IMPORTERS = [];
14046
14231
  /**
14047
14232
  * Failure of `Lockfile.parse`: the given content is not a valid lockfile of
@@ -14286,7 +14471,7 @@ var Lockfile = class Lockfile extends Schema.Class("Lockfile")({
14286
14471
  };
14287
14472
 
14288
14473
  //#endregion
14289
- //#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
14474
+ //#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
14290
14475
  /**
14291
14476
  * The minimal manifest shape {@link LockfileIntegrity.compare} checks a
14292
14477
  * lockfile against: a package name plus the four optional dependency maps.
@@ -14403,7 +14588,7 @@ var LockfileIntegrity = class LockfileIntegrity extends Schema.Class("LockfileIn
14403
14588
  };
14404
14589
 
14405
14590
  //#endregion
14406
- //#region ../../node_modules/.pnpm/@effected+package-json@0.5.1_effect@4.0.0-beta.101/node_modules/@effected/package-json/Dependency.js
14591
+ //#region ../../node_modules/.pnpm/@effected+package-json@0.6.0_effect@4.0.0-beta.101/node_modules/@effected/package-json/Dependency.js
14407
14592
  /**
14408
14593
  * A resolved dependency entry pairing a package name with its version
14409
14594
  * specifier and the `kind` of map it came from (`@effected/npm`'s
@@ -14468,7 +14653,7 @@ var Dependency = class extends Schema.Class("Dependency")({
14468
14653
  };
14469
14654
 
14470
14655
  //#endregion
14471
- //#region ../../node_modules/.pnpm/@effected+package-json@0.5.1_effect@4.0.0-beta.101/node_modules/@effected/package-json/DevEngines.js
14656
+ //#region ../../node_modules/.pnpm/@effected+package-json@0.6.0_effect@4.0.0-beta.101/node_modules/@effected/package-json/DevEngines.js
14472
14657
  /**
14473
14658
  * A single `devEngines` constraint with a name and optional `version` / `onFail`.
14474
14659
  *
@@ -16066,7 +16251,7 @@ const SpdxExpression = {
16066
16251
  };
16067
16252
 
16068
16253
  //#endregion
16069
- //#region ../../node_modules/.pnpm/@effected+package-json@0.5.1_effect@4.0.0-beta.101/node_modules/@effected/package-json/License.js
16254
+ //#region ../../node_modules/.pnpm/@effected+package-json@0.6.0_effect@4.0.0-beta.101/node_modules/@effected/package-json/License.js
16070
16255
  /**
16071
16256
  * Indicates that a string is not a valid SPDX license identifier or expression.
16072
16257
  *
@@ -16102,7 +16287,7 @@ const isValidSpdx = (value) => {
16102
16287
  const SpdxLicense = Schema.String.pipe(Schema.check(Schema.makeFilter((value) => isValidSpdx(value) ? void 0 : "Expected a valid SPDX license expression")), Schema.brand("SpdxLicense"));
16103
16288
 
16104
16289
  //#endregion
16105
- //#region ../../node_modules/.pnpm/@effected+package-json@0.5.1_effect@4.0.0-beta.101/node_modules/@effected/package-json/PackageManager.js
16290
+ //#region ../../node_modules/.pnpm/@effected+package-json@0.6.0_effect@4.0.0-beta.101/node_modules/@effected/package-json/PackageManager.js
16106
16291
  const PACKAGE_MANAGER_RE = /^([a-z]+)@(\d+\.\d+\.\d+(?:-[a-zA-Z0-9._-]+)?)(?:\+(.+))?$/;
16107
16292
  /**
16108
16293
  * The `packageManager` field only ever carries corepack's `<algo>.<hex>`
@@ -16161,7 +16346,7 @@ var PackageManager = class PackageManager extends Schema.Class("PackageManager")
16161
16346
  };
16162
16347
 
16163
16348
  //#endregion
16164
- //#region ../../node_modules/.pnpm/@effected+package-json@0.5.1_effect@4.0.0-beta.101/node_modules/@effected/package-json/PackageName.js
16349
+ //#region ../../node_modules/.pnpm/@effected+package-json@0.6.0_effect@4.0.0-beta.101/node_modules/@effected/package-json/PackageName.js
16165
16350
  /**
16166
16351
  * Indicates that a string could not be used as a valid npm package name.
16167
16352
  *
@@ -16220,7 +16405,7 @@ const PackageName = Object.assign(Schema.Union([ScopedPackageName, UnscopedPacka
16220
16405
  });
16221
16406
 
16222
16407
  //#endregion
16223
- //#region ../../node_modules/.pnpm/@effected+package-json@0.5.1_effect@4.0.0-beta.101/node_modules/@effected/package-json/Person.js
16408
+ //#region ../../node_modules/.pnpm/@effected+package-json@0.6.0_effect@4.0.0-beta.101/node_modules/@effected/package-json/Person.js
16224
16409
  const parsePersonString = (input) => {
16225
16410
  const emailMatch = input.match(/<([^>]+)>/);
16226
16411
  const urlMatch = input.match(/\(([^)]+)\)/);
@@ -16251,10 +16436,11 @@ const KNOWN_KEYS = /* @__PURE__ */ new Set([
16251
16436
  "url"
16252
16437
  ]);
16253
16438
  const sameRest = (a, b) => JSON.stringify(a ?? {}) === JSON.stringify(b ?? {});
16439
+ const isShorthandExpressible = (person) => person.rest === void 0 || Object.keys(person.rest).length === 0;
16254
16440
  const isFaithful = (wire, person) => {
16255
16441
  if (typeof wire === "string") {
16256
16442
  const parsed = parsePersonString(wire);
16257
- return parsed.name === person.name && parsed.email === person.email && parsed.url === person.url;
16443
+ return parsed.name === person.name && parsed.email === person.email && parsed.url === person.url && isShorthandExpressible(person);
16258
16444
  }
16259
16445
  const rest = restOf(wire);
16260
16446
  return wire.name === person.name && wire.email === person.email && wire.url === person.url && sameRest(rest, person.rest);
@@ -16343,7 +16529,9 @@ var Person = class Person extends Schema.Class("Person")({
16343
16529
  decode: (input) => typeof input === "string" ? rememberWire(parsePersonString(input), input) : input,
16344
16530
  encode: (person) => {
16345
16531
  const wire = wireForms.get(person);
16346
- return typeof wire === "string" && isFaithful(wire, person) ? wire : person;
16532
+ if (typeof wire !== "string") return person;
16533
+ if (isFaithful(wire, person)) return wire;
16534
+ return isShorthandExpressible(person) ? serializePerson(person) : person;
16347
16535
  }
16348
16536
  })));
16349
16537
  /**
@@ -16364,7 +16552,183 @@ var Person = class Person extends Schema.Class("Person")({
16364
16552
  };
16365
16553
 
16366
16554
  //#endregion
16367
- //#region ../../node_modules/.pnpm/@effected+package-json@0.5.1_effect@4.0.0-beta.101/node_modules/@effected/package-json/internal/format.js
16555
+ //#region ../../node_modules/.pnpm/@effected+package-json@0.6.0_effect@4.0.0-beta.101/node_modules/@effected/package-json/Repository.js
16556
+ /** The shorthand hosts npm resolves without a scheme. */
16557
+ const SHORTHAND_HOSTS = /* @__PURE__ */ new Map([
16558
+ ["github", "https://github.com"],
16559
+ ["gitlab", "https://gitlab.com"],
16560
+ ["bitbucket", "https://bitbucket.org"]
16561
+ ]);
16562
+ /** `owner/name`, the bare GitHub shorthand. Deliberately strict about segment shape. */
16563
+ const BARE_SHORTHAND = /^[\w.-]+\/[\w.-]+$/;
16564
+ /** `github:owner/name`, `gist:id`, … */
16565
+ const PREFIXED_SHORTHAND = /^([a-z]+):(.+)$/;
16566
+ /** The scp-like form git accepts: `git@host:owner/name.git`. */
16567
+ const SCP_LIKE = /^(?:([\w.-]+)@)?([\w.-]+):(.+)$/;
16568
+ const stripGitSuffix = (value) => value.endsWith(".git") ? value.slice(0, -4) : value;
16569
+ /**
16570
+ * The browsable `https://host/path` form of a repository reference, or none
16571
+ * when the value is not one this model recognizes.
16572
+ *
16573
+ * Total by construction: `repository` is caller data, and a value we cannot
16574
+ * interpret is a missing answer rather than a failure.
16575
+ */
16576
+ const browseUrlOf = (raw) => {
16577
+ const url = raw.trim();
16578
+ if (url === "") return Option.none();
16579
+ if (BARE_SHORTHAND.test(url)) return Option.some(`https://github.com/${url}`);
16580
+ const prefixed = PREFIXED_SHORTHAND.exec(url);
16581
+ if (prefixed !== null) {
16582
+ const [, scheme, rest] = prefixed;
16583
+ if (scheme === "gist") return Option.some(`https://gist.github.com/${stripGitSuffix(rest ?? "")}`);
16584
+ const host = SHORTHAND_HOSTS.get(scheme ?? "");
16585
+ if (host !== void 0) return Option.some(`${host}/${stripGitSuffix(rest ?? "")}`);
16586
+ }
16587
+ const withoutGitPlus = url.startsWith("git+") ? url.slice(4) : url;
16588
+ const schemeMatch = /^([a-z][a-z0-9+.-]*):\/\/(.*)$/i.exec(withoutGitPlus);
16589
+ if (schemeMatch !== null) {
16590
+ const withoutCredentials = (schemeMatch[2] ?? "").replace(/^[^/@]+@/, "");
16591
+ return withoutCredentials === "" ? Option.none() : Option.some(`https://${stripGitSuffix(withoutCredentials)}`);
16592
+ }
16593
+ const scp = SCP_LIKE.exec(withoutGitPlus);
16594
+ if (scp !== null) {
16595
+ const [, , host, path] = scp;
16596
+ if (host !== void 0 && path !== void 0 && path !== "") return Option.some(`https://${host}/${stripGitSuffix(path)}`);
16597
+ }
16598
+ return Option.none();
16599
+ };
16600
+ const repositoryWires = /* @__PURE__ */ new WeakMap();
16601
+ const bugsWires = /* @__PURE__ */ new WeakMap();
16602
+ const KNOWN_REPOSITORY_KEYS = /* @__PURE__ */ new Set([
16603
+ "type",
16604
+ "url",
16605
+ "directory"
16606
+ ]);
16607
+ const KNOWN_BUGS_KEYS = /* @__PURE__ */ new Set(["url", "email"]);
16608
+ /**
16609
+ * Where a package's source lives.
16610
+ *
16611
+ * @remarks
16612
+ * `url` is **verbatim** — exactly the string the manifest carried, shorthand
16613
+ * and all. Normalization is offered through {@link Repository.browseUrl} and
16614
+ * {@link Repository.gitUrl}, so reading a manifest never rewrites it and a
16615
+ * caller that wants the original still has it.
16616
+ *
16617
+ * @example
16618
+ * ```ts
16619
+ * // "effected/kit" → https://github.com/effected/kit
16620
+ * // "git@github.com:effected/kit.git" → https://github.com/effected/kit
16621
+ * ```
16622
+ *
16623
+ * @public
16624
+ */
16625
+ var Repository = class Repository extends Schema.Class("Repository")({
16626
+ /** The `type` field, when the object form carried one (`"git"`, …). */
16627
+ type: Schema.optionalKey(Schema.String),
16628
+ /** The reference exactly as written: a shorthand, a git URL, or an https URL. */
16629
+ url: Schema.String,
16630
+ /** The subdirectory within the repository, for a monorepo member. */
16631
+ directory: Schema.optionalKey(Schema.String),
16632
+ /** Keys outside the documented set, preserved so encoding does not drop them. */
16633
+ rest: Schema.optionalKey(Schema.Record(Schema.String, Schema.Unknown))
16634
+ }) {
16635
+ /**
16636
+ * The browsable `https://` URL, or `Option.none()` when `url` is not a form
16637
+ * this model recognizes.
16638
+ */
16639
+ get browseUrl() {
16640
+ return browseUrlOf(this.url);
16641
+ }
16642
+ /** The canonical https clone URL, or none when it cannot be derived. */
16643
+ get gitUrl() {
16644
+ return Option.map(this.browseUrl, (url) => `${url}.git`);
16645
+ }
16646
+ /**
16647
+ * The `repository` field: the shorthand string or the object form, always
16648
+ * decoded to a {@link Repository}, and always re-encoded in the form it was
16649
+ * read from.
16650
+ */
16651
+ static FromValue = Schema.Union([Schema.Record(Schema.String, Schema.Unknown), Schema.String]).pipe(Schema.decodeTo(Schema.instanceOf(Repository), SchemaTransformation.transform({
16652
+ decode: (input) => {
16653
+ if (typeof input === "string") {
16654
+ const repository = Repository.make({ url: input });
16655
+ repositoryWires.set(repository, input);
16656
+ return repository;
16657
+ }
16658
+ const rest = {};
16659
+ for (const [key, value] of Object.entries(input)) if (!KNOWN_REPOSITORY_KEYS.has(key)) rest[key] = value;
16660
+ const repository = Repository.make({
16661
+ url: typeof input.url === "string" ? input.url : "",
16662
+ ...typeof input.type === "string" && { type: input.type },
16663
+ ...typeof input.directory === "string" && { directory: input.directory },
16664
+ ...Object.keys(rest).length > 0 && { rest }
16665
+ });
16666
+ repositoryWires.set(repository, input);
16667
+ return repository;
16668
+ },
16669
+ encode: (repository) => {
16670
+ const wire = repositoryWires.get(repository);
16671
+ if (typeof wire === "string" && wire === repository.url) return wire;
16672
+ if (wire !== void 0 && typeof wire !== "string") return wire;
16673
+ return {
16674
+ ...repository.type !== void 0 && { type: repository.type },
16675
+ url: repository.url,
16676
+ ...repository.directory !== void 0 && { directory: repository.directory },
16677
+ ...repository.rest
16678
+ };
16679
+ }
16680
+ })));
16681
+ };
16682
+ /**
16683
+ * Where to report problems with a package.
16684
+ *
16685
+ * @remarks
16686
+ * npm permits a bare URL string, or an object with `url`, `email`, or both —
16687
+ * an email-only entry is legal, which is why `url` is optional.
16688
+ *
16689
+ * @public
16690
+ */
16691
+ var Bugs = class Bugs extends Schema.Class("Bugs")({
16692
+ /** The issue-tracker URL. */
16693
+ url: Schema.optionalKey(Schema.String),
16694
+ /** The address to mail instead of, or alongside, filing an issue. */
16695
+ email: Schema.optionalKey(Schema.String),
16696
+ /** Keys outside the documented set, preserved so encoding does not drop them. */
16697
+ rest: Schema.optionalKey(Schema.Record(Schema.String, Schema.Unknown))
16698
+ }) {
16699
+ /** The `bugs` field: a URL string or the object form. */
16700
+ static FromValue = Schema.Union([Schema.Record(Schema.String, Schema.Unknown), Schema.String]).pipe(Schema.decodeTo(Schema.instanceOf(Bugs), SchemaTransformation.transform({
16701
+ decode: (input) => {
16702
+ if (typeof input === "string") {
16703
+ const bugs = Bugs.make({ url: input });
16704
+ bugsWires.set(bugs, input);
16705
+ return bugs;
16706
+ }
16707
+ const rest = {};
16708
+ for (const [key, value] of Object.entries(input)) if (!KNOWN_BUGS_KEYS.has(key)) rest[key] = value;
16709
+ const bugs = Bugs.make({
16710
+ ...typeof input.url === "string" && { url: input.url },
16711
+ ...typeof input.email === "string" && { email: input.email },
16712
+ ...Object.keys(rest).length > 0 && { rest }
16713
+ });
16714
+ bugsWires.set(bugs, input);
16715
+ return bugs;
16716
+ },
16717
+ encode: (bugs) => {
16718
+ const wire = bugsWires.get(bugs);
16719
+ if (typeof wire === "string" && wire === bugs.url && bugs.email === void 0) return wire;
16720
+ if (wire !== void 0 && typeof wire !== "string") return wire;
16721
+ return {
16722
+ ...bugs.url !== void 0 && { url: bugs.url },
16723
+ ...bugs.email !== void 0 && { email: bugs.email },
16724
+ ...bugs.rest
16725
+ };
16726
+ }
16727
+ })));
16728
+ };
16729
+
16730
+ //#endregion
16731
+ //#region ../../node_modules/.pnpm/@effected+package-json@0.6.0_effect@4.0.0-beta.101/node_modules/@effected/package-json/internal/format.js
16368
16732
  const KEY_INDEX = new Map([
16369
16733
  "$schema",
16370
16734
  "name",
@@ -16588,7 +16952,7 @@ const renderJson = (raw, options) => {
16588
16952
  };
16589
16953
 
16590
16954
  //#endregion
16591
- //#region ../../node_modules/.pnpm/@effected+package-json@0.5.1_effect@4.0.0-beta.101/node_modules/@effected/package-json/Package.js
16955
+ //#region ../../node_modules/.pnpm/@effected+package-json@0.6.0_effect@4.0.0-beta.101/node_modules/@effected/package-json/Package.js
16592
16956
  const toHashMap = SchemaTransformation.transform({
16593
16957
  decode: (record) => HashMap.fromIterable(Object.entries(record)),
16594
16958
  encode: (map) => Object.fromEntries(HashMap.toEntries(map))
@@ -16639,9 +17003,12 @@ const PublishConfigField = Schema.Record(Schema.String, Schema.Unknown);
16639
17003
  */
16640
17004
  const PeerDependenciesMetaField = Schema.Record(Schema.String, Schema.Struct({ optional: Schema.optionalKey(Schema.Boolean) }));
16641
17005
  /**
16642
- * The `repository` field: a shorthand string or an object (with `type` / `url` /
16643
- * `directory` and any extensions preserved). Not meant to be referenced
16644
- * directly.
17006
+ * The `repository` field's raw wire shape: a shorthand string or an object.
17007
+ *
17008
+ * @deprecated Superseded by {@link Repository.FromValue}, which decodes both
17009
+ * encodings into a typed {@link Repository} with normalization getters and
17010
+ * round-trips the original form. Kept as a named type for consumers that were
17011
+ * matching on the raw union; it is no longer what `Package.repository` uses.
16645
17012
  *
16646
17013
  * @public
16647
17014
  */
@@ -16720,7 +17087,11 @@ var Package = class Package extends Schema.Class("Package")({
16720
17087
  license: Schema.optionalKey(SpdxLicense),
16721
17088
  author: Schema.optionalKey(Person.FromValue),
16722
17089
  contributors: Schema.optionalKey(Schema.Array(Person.FromValue)),
16723
- repository: Schema.optionalKey(RepositoryField),
17090
+ maintainers: Schema.optionalKey(Schema.Array(Person.FromValue)),
17091
+ keywords: Schema.optionalKey(Schema.Array(Schema.String)),
17092
+ repository: Schema.optionalKey(Repository.FromValue),
17093
+ bugs: Schema.optionalKey(Bugs.FromValue),
17094
+ homepage: Schema.optionalKey(Schema.String),
16724
17095
  dependencies: DependencyMapField,
16725
17096
  devDependencies: DependencyMapField,
16726
17097
  peerDependencies: DependencyMapField,
@@ -16907,7 +17278,7 @@ var Package = class Package extends Schema.Class("Package")({
16907
17278
  };
16908
17279
 
16909
17280
  //#endregion
16910
- //#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
17281
+ //#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
16911
17282
  const EMPTY$1 = Object.freeze(Object.create(null));
16912
17283
  const EMPTY_MANIFEST = Object.freeze(Object.create(null));
16913
17284
  /**
@@ -17187,7 +17558,7 @@ var WorkspacePackage = class WorkspacePackage extends Schema.Class("WorkspacePac
17187
17558
  };
17188
17559
 
17189
17560
  //#endregion
17190
- //#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
17561
+ //#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
17191
17562
  /**
17192
17563
  * Typed failure raised by {@link descend}: a directory mid-walk was unreadable
17193
17564
  * (under `onUnreadable: "fail"`), or the walk descended past `maxDepth`. Depth
@@ -17323,7 +17694,7 @@ const descend = Effect.fn("Walker.descend")(function* (pattern, options) {
17323
17694
  });
17324
17695
 
17325
17696
  //#endregion
17326
- //#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
17697
+ //#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
17327
17698
  /**
17328
17699
  * Typed failure raised by {@link compileAndExpand}: the single error the
17329
17700
  * compile+expand recipe fails with, so a caller catches one tag rather than
@@ -17414,31 +17785,7 @@ const compileAndExpand = Effect.fn("Walker.compileAndExpand")(function* (pattern
17414
17785
  });
17415
17786
 
17416
17787
  //#endregion
17417
- //#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
17418
- /**
17419
- * Ascend from `start` toward the filesystem root, yielding each directory,
17420
- * nearest first.
17421
- *
17422
- * @remarks
17423
- * Lexical, not physical: `Path.dirname` does not resolve symlinks, so ascending
17424
- * out of a symlinked directory follows the path you were given rather than the
17425
- * real filesystem parent. That is deliberate — config discovery wants the file
17426
- * nearest the path the user named.
17427
- *
17428
- * Bounded twice over: `dirname` is a fixpoint at the root, and `maxDepth` guards
17429
- * a pathological `Path` implementation that never reaches one.
17430
- *
17431
- * `stopAt` is compared in normalized form — see {@link AscendOptions.stopAt}.
17432
- * Raw string equality made the ceiling fail OPEN: an unnormalized ceiling
17433
- * matched nothing and the ascent ran silently to the filesystem root, which is
17434
- * the unbounded walk the option exists to prevent, with no error to notice it
17435
- * by. A relative ceiling **dies** for the same reason — resolving one against
17436
- * `process.cwd()` would reintroduce the silent-wrong-walk failure through a
17437
- * different door. See {@link AscendOptions.stopAt} for why that is a defect
17438
- * rather than a typed error; the error channel stays `never`.
17439
- *
17440
- * @public
17441
- */
17788
+ //#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
17442
17789
  const ascend = (start, options) => Effect.gen(function* () {
17443
17790
  const path = yield* Path.Path;
17444
17791
  const maxDepth = options?.maxDepth ?? 256;
@@ -17456,67 +17803,84 @@ const ascend = (start, options) => Effect.gen(function* () {
17456
17803
  }
17457
17804
  return dirs;
17458
17805
  });
17459
- /**
17460
- * The first candidate whose `predicate` reports true, or `Option.none()`.
17461
- *
17462
- * @remarks
17463
- * Each predicate is absorbed **individually**: a failure on one candidate is
17464
- * treated as "this candidate did not match" and the scan continues. One
17465
- * unreadable ancestor must never abort the walk, or a permission error deep in
17466
- * the tree would hide a valid root above it. Not-found and cannot-look are
17467
- * therefore indistinguishable to the caller; discovery is best-effort.
17468
- *
17469
- * `Effect.catch` catches failures, **not defects**. A predicate that throws is
17470
- * programmer error and surfaces as a defect. Do not change this to
17471
- * `Effect.catchCause` — the distinction is load-bearing.
17472
- *
17473
- * @public
17474
- */
17475
17806
  const firstMatch = (candidates, predicate) => Effect.gen(function* () {
17476
17807
  for (const candidate of candidates) if (yield* Effect.catch(predicate(candidate), () => Effect.succeed(false))) return Option.some(candidate);
17477
17808
  return Option.none();
17478
17809
  });
17479
- /**
17480
- * The first existing path among the candidates `candidatesFor` produces for each
17481
- * directory in `dirs`, scanned in order. Nearer directories win.
17482
- *
17483
- * @remarks
17484
- * Candidates materialize up front, bounded by `dirs.length × candidatesFor`'s
17485
- * output — a few hundred strings under the default `maxDepth`.
17486
- *
17487
- * @public
17488
- */
17489
17810
  const findUpward = (dirs, candidatesFor) => Effect.gen(function* () {
17490
17811
  const fs = yield* FileSystem.FileSystem;
17491
17812
  const candidates = [];
17492
17813
  for (const dir of dirs) candidates.push(...candidatesFor(dir));
17493
17814
  return yield* firstMatch(candidates, (candidate) => fs.exists(candidate));
17494
17815
  });
17495
- /**
17496
- * The first directory in `dirs` that `isRoot` accepts.
17497
- *
17498
- * @remarks
17499
- * `firstMatch` over the directories themselves — the candidate expansion is the
17500
- * identity. `isRoot` is a caller-supplied marker test (a `.git` entry, a
17501
- * `pnpm-workspace.yaml`), and its failures are absorbed per directory.
17502
- *
17503
- * @public
17504
- */
17505
17816
  const findRoot$1 = (dirs, isRoot) => firstMatch(dirs, isRoot);
17506
17817
  /**
17507
17818
  * Upward path traversal primitives.
17508
17819
  *
17509
17820
  * @public
17510
17821
  */
17511
- const Walker$1 = {
17512
- ascend,
17513
- firstMatch,
17514
- findUpward,
17515
- findRoot: findRoot$1
17822
+ var Walker$1 = class {
17823
+ constructor() {}
17824
+ /**
17825
+ * Ascend from `start` toward the filesystem root, yielding each directory,
17826
+ * nearest first.
17827
+ *
17828
+ * @remarks
17829
+ * Lexical, not physical: `Path.dirname` does not resolve symlinks, so ascending
17830
+ * out of a symlinked directory follows the path you were given rather than the
17831
+ * real filesystem parent. That is deliberate — config discovery wants the file
17832
+ * nearest the path the user named.
17833
+ *
17834
+ * Bounded twice over: `dirname` is a fixpoint at the root, and `maxDepth` guards
17835
+ * a pathological `Path` implementation that never reaches one.
17836
+ *
17837
+ * `stopAt` is compared in normalized form — see {@link AscendOptions.stopAt}.
17838
+ * Raw string equality made the ceiling fail OPEN: an unnormalized ceiling
17839
+ * matched nothing and the ascent ran silently to the filesystem root, which is
17840
+ * the unbounded walk the option exists to prevent, with no error to notice it
17841
+ * by. A relative ceiling **dies** for the same reason — resolving one against
17842
+ * `process.cwd()` would reintroduce the silent-wrong-walk failure through a
17843
+ * different door. See {@link AscendOptions.stopAt} for why that is a defect
17844
+ * rather than a typed error; the error channel stays `never`.
17845
+ */
17846
+ static ascend = ascend;
17847
+ /**
17848
+ * The first candidate whose `predicate` reports true, or `Option.none()`.
17849
+ *
17850
+ * @remarks
17851
+ * Each predicate is absorbed **individually**: a failure on one candidate is
17852
+ * treated as "this candidate did not match" and the scan continues. One
17853
+ * unreadable ancestor must never abort the walk, or a permission error deep in
17854
+ * the tree would hide a valid root above it. Not-found and cannot-look are
17855
+ * therefore indistinguishable to the caller; discovery is best-effort.
17856
+ *
17857
+ * `Effect.catch` catches failures, **not defects**. A predicate that throws is
17858
+ * programmer error and surfaces as a defect. Do not change this to
17859
+ * `Effect.catchCause` — the distinction is load-bearing.
17860
+ */
17861
+ static firstMatch = firstMatch;
17862
+ /**
17863
+ * The first existing path among the candidates `candidatesFor` produces for each
17864
+ * directory in `dirs`, scanned in order. Nearer directories win.
17865
+ *
17866
+ * @remarks
17867
+ * Candidates materialize up front, bounded by `dirs.length × candidatesFor`'s
17868
+ * output — a few hundred strings under the default `maxDepth`.
17869
+ */
17870
+ static findUpward = findUpward;
17871
+ /**
17872
+ * The first directory in `dirs` that `isRoot` accepts.
17873
+ *
17874
+ * @remarks
17875
+ * `firstMatch` over the directories themselves — the candidate expansion is the
17876
+ * identity. `isRoot` is a caller-supplied marker test (a `.git` entry, a
17877
+ * `pnpm-workspace.yaml`), and its failures are absorbed per directory.
17878
+ */
17879
+ static findRoot = findRoot$1;
17516
17880
  };
17517
17881
 
17518
17882
  //#endregion
17519
- //#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
17883
+ //#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
17520
17884
  /**
17521
17885
  * The marker filenames {@link WorkspaceRoot} probes for, in priority order.
17522
17886
  *
@@ -17704,7 +18068,7 @@ var WorkspaceRoot = class WorkspaceRoot extends Context.Service()("@effected/wor
17704
18068
  };
17705
18069
 
17706
18070
  //#endregion
17707
- //#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
18071
+ //#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
17708
18072
  /**
17709
18073
  * Hard ceiling on directories the enumerator will visit for one pattern set.
17710
18074
  * Guards the pathological case a depth cap alone does not: a wide, shallow
@@ -17723,7 +18087,7 @@ const MAX_ENUMERATION_ENTRIES = 1e5;
17723
18087
  const PRUNED_DIRECTORIES = /* @__PURE__ */ new Set([".git", "node_modules"]);
17724
18088
 
17725
18089
  //#endregion
17726
- //#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
18090
+ //#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
17727
18091
  /** Directory names never descended into. */
17728
18092
  const isPruned = (entry) => PRUNED_DIRECTORIES.has(entry);
17729
18093
  /** Join root-relative POSIX segments; `""` is the root itself. */
@@ -17814,7 +18178,7 @@ var Traversal = class {
17814
18178
  };
17815
18179
 
17816
18180
  //#endregion
17817
- //#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
18181
+ //#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
17818
18182
  /** Strip a trailing slash from `GlobPattern.enumerationPrefix` to get a relative directory. */
17819
18183
  const baseOf = (pattern) => pattern.enumerationPrefix.replace(/\/$/, "");
17820
18184
  /**
@@ -17885,7 +18249,7 @@ const enumerate = (root, globs, options) => Effect.gen(function* () {
17885
18249
  });
17886
18250
 
17887
18251
  //#endregion
17888
- //#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
18252
+ //#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
17889
18253
  const stringsOf = (value) => Array.isArray(value) ? value.filter((entry) => typeof entry === "string") : void 0;
17890
18254
  /** The `packages:` list of a `pnpm-workspace.yaml` document. Total on a parsed document. */
17891
18255
  const pnpmPatternsOf = (document) => {
@@ -17943,7 +18307,7 @@ const readPatterns = (root) => Effect.gen(function* () {
17943
18307
  });
17944
18308
 
17945
18309
  //#endregion
17946
- //#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
18310
+ //#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
17947
18311
  /**
17948
18312
  * Raised when a workspace member's `package.json` cannot be read, parsed, or
17949
18313
  * used — it is missing, malformed, or lacks a `name` or `version`.
@@ -18378,7 +18742,7 @@ var WorkspaceDiscovery = class WorkspaceDiscovery extends Context.Service()("@ef
18378
18742
  const isStringRecord$2 = (value) => value !== null && typeof value === "object" && !Array.isArray(value) && Object.values(value).every((entry) => typeof entry === "string");
18379
18743
 
18380
18744
  //#endregion
18381
- //#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
18745
+ //#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
18382
18746
  /**
18383
18747
  * Raised when the workspace dependency graph cannot be topologically ordered
18384
18748
  * because it contains a cycle.
@@ -18614,7 +18978,7 @@ const kahn = (edges) => {
18614
18978
  };
18615
18979
 
18616
18980
  //#endregion
18617
- //#region ../../node_modules/.pnpm/@effected+git@0.4.2_effect@4.0.0-beta.101/node_modules/@effected/git/GitCommand.js
18981
+ //#region ../../node_modules/.pnpm/@effected+git@0.5.1_effect@4.0.0-beta.101/node_modules/@effected/git/GitCommand.js
18618
18982
  /**
18619
18983
  * Builds a `git` `ChildProcess.StandardCommand` with the argv this package
18620
18984
  * classifies against.
@@ -18637,25 +19001,7 @@ const git = (args) => ChildProcess.make("git", args, {
18637
19001
  env: { LC_ALL: "C" },
18638
19002
  extendEnv: true
18639
19003
  });
18640
- /**
18641
- * `git show <ref>:<path>` — the contents of `path` as it existed at `ref`,
18642
- * without checking anything out.
18643
- *
18644
- * @public
18645
- */
18646
19004
  const show = (ref, path) => git(["show", `${ref}:${path}`]);
18647
- /**
18648
- * `git ls-tree -r -z <ref> [-- <pathspec>...]` — every path in the tree at
18649
- * `ref`, recursively, NUL-terminated, optionally scoped to `pathspec`.
18650
- *
18651
- * @remarks
18652
- * `-z` is load-bearing: git paths may themselves contain newlines, so the
18653
- * caller must split on `"\0"`, never on `"\n"`. When `pathspec` is provided,
18654
- * a literal `--` separator is inserted before the pathspec entries to prevent
18655
- * git from interpreting pathspec values as options.
18656
- *
18657
- * @public
18658
- */
18659
19005
  const lsTree = (ref, pathspec = []) => git([
18660
19006
  "ls-tree",
18661
19007
  "-r",
@@ -18663,48 +19009,16 @@ const lsTree = (ref, pathspec = []) => git([
18663
19009
  ref,
18664
19010
  ...pathspec.length > 0 ? ["--", ...pathspec] : []
18665
19011
  ]);
18666
- /**
18667
- * `git cat-file -e <ref>` — checks whether `ref` resolves to an existing
18668
- * object, without printing it. A non-zero exit means the ref does not exist.
18669
- *
18670
- * @public
18671
- */
18672
19012
  const refExists = (ref) => git([
18673
19013
  "cat-file",
18674
19014
  "-e",
18675
19015
  ref
18676
19016
  ]);
18677
- /**
18678
- * `git merge-base <a> <b>` — the best common ancestor commit of `a` and `b`.
18679
- *
18680
- * @public
18681
- */
18682
19017
  const mergeBase = (a, b) => git([
18683
19018
  "merge-base",
18684
19019
  a,
18685
19020
  b
18686
19021
  ]);
18687
- /**
18688
- * `git diff --name-only -z [--relative] <base>...<head>` — the paths that
18689
- * differ between the merge base of `base` and `head`, and `head` itself,
18690
- * NUL-terminated.
18691
- *
18692
- * @remarks
18693
- * `-z` is load-bearing here too, for the same reason as {@link GitCommand.lsTree}: split
18694
- * the output on `"\0"`, never on `"\n"`.
18695
- *
18696
- * The relative flag is **explicit in both branches** — `--relative` when
18697
- * `relative` is true, `--no-relative` when false — never omitted. git honors a
18698
- * configured `diff.relative=true` when no flag is passed, so an omitted flag
18699
- * would silently yield cwd-relative paths on such a machine even for
18700
- * `relative: false`, misaligning with {@link GitCommand.untrackedFiles}'s
18701
- * repo-root base and breaking `Git.workingChanges`' dedup in a nested workspace.
18702
- * `--relative` scopes the report to `cwd` (a workspace nested inside a larger
18703
- * repository); `--no-relative` overrides any `diff.relative` config and reports
18704
- * paths from the repository top-level.
18705
- *
18706
- * @public
18707
- */
18708
19022
  const changedFiles = (base, head, relative = false) => git([
18709
19023
  "diff",
18710
19024
  "--name-only",
@@ -18712,35 +19026,12 @@ const changedFiles = (base, head, relative = false) => git([
18712
19026
  relative ? "--relative" : "--no-relative",
18713
19027
  `${base}...${head}`
18714
19028
  ]);
18715
- /**
18716
- * `git diff --name-only -z (--relative | --no-relative)` — the paths with
18717
- * unstaged working-tree changes (the working tree against the index),
18718
- * NUL-terminated.
18719
- *
18720
- * @remarks
18721
- * `relative` behaves as it does for {@link GitCommand.changedFiles}, including the
18722
- * explicit-flag-in-both-branches rule: `--no-relative` is passed for
18723
- * `relative: false` so a configured `diff.relative=true` cannot silently make the
18724
- * output cwd-relative.
18725
- *
18726
- * @public
18727
- */
18728
19029
  const unstagedChanges = (relative = false) => git([
18729
19030
  "diff",
18730
19031
  "--name-only",
18731
19032
  "-z",
18732
19033
  relative ? "--relative" : "--no-relative"
18733
19034
  ]);
18734
- /**
18735
- * `git diff --name-only -z (--relative | --no-relative) --cached` — the paths
18736
- * staged for the next commit (the index against `HEAD`), NUL-terminated.
18737
- *
18738
- * @remarks
18739
- * `relative` behaves as it does for {@link GitCommand.changedFiles}, including the
18740
- * explicit `--no-relative` on the `relative: false` branch.
18741
- *
18742
- * @public
18743
- */
18744
19035
  const stagedChanges = (relative = false) => git([
18745
19036
  "diff",
18746
19037
  "--name-only",
@@ -18748,19 +19039,6 @@ const stagedChanges = (relative = false) => git([
18748
19039
  relative ? "--relative" : "--no-relative",
18749
19040
  "--cached"
18750
19041
  ]);
18751
- /**
18752
- * `git ls-files --others --exclude-standard -z [--full-name]` — the untracked
18753
- * paths git is not ignoring, NUL-terminated.
18754
- *
18755
- * @remarks
18756
- * `ls-files` reports paths relative to `cwd` by default, matching the
18757
- * `--relative` diffs. When `relative` is `false`, `--full-name` makes it emit
18758
- * repo-root-relative paths instead, so the untracked half shares a base with the
18759
- * un-`--relative` diffs — otherwise `Git.workingChanges`'s union would dedup two
18760
- * spellings of one file from a nested `cwd`.
18761
- *
18762
- * @public
18763
- */
18764
19042
  const untrackedFiles = (relative = false) => git([
18765
19043
  "ls-files",
18766
19044
  "--others",
@@ -18768,35 +19046,16 @@ const untrackedFiles = (relative = false) => git([
18768
19046
  "-z",
18769
19047
  ...relative ? [] : ["--full-name"]
18770
19048
  ]);
18771
- /**
18772
- * `git rev-parse --verify <ref>` — resolves `ref` to its full object id, or
18773
- * fails if `ref` does not resolve.
18774
- *
18775
- * @public
18776
- */
18777
19049
  const revParse = (ref) => git([
18778
19050
  "rev-parse",
18779
19051
  "--verify",
18780
19052
  ref
18781
19053
  ]);
18782
- /**
18783
- * Mutating: `git checkout [--detach] <ref>` — moves the working tree (and, for
18784
- * a branch ref, `HEAD`) to `ref`. When `detach` is true, checks out the ref in
18785
- * detached-HEAD state.
18786
- *
18787
- * @public
18788
- */
18789
19054
  const checkout = (ref, detach = false) => git([
18790
19055
  "checkout",
18791
19056
  ...detach ? ["--detach"] : [],
18792
19057
  ref
18793
19058
  ]);
18794
- /**
18795
- * Mutating: `git fetch [--depth <n>] <remote> [tag] <ref>` — fetches the given
18796
- * ref from a remote, optionally with a depth limit and the `tag` keyword.
18797
- *
18798
- * @public
18799
- */
18800
19059
  const fetch$1 = (remote, ref, depth, tag = false) => git([
18801
19060
  "fetch",
18802
19061
  ...depth !== void 0 ? ["--depth", String(depth)] : [],
@@ -18804,14 +19063,6 @@ const fetch$1 = (remote, ref, depth, tag = false) => git([
18804
19063
  ...tag ? ["tag"] : [],
18805
19064
  ref
18806
19065
  ]);
18807
- /**
18808
- * Mutating: `git submodule update [--init] [--depth <n>] [-- <paths>...]` — updates
18809
- * registered submodules, optionally initializing them, with an optional depth limit,
18810
- * and scoped to specific paths. The literal `--` separator makes the pathspec
18811
- * injection-safe by construction.
18812
- *
18813
- * @public
18814
- */
18815
19066
  const submoduleUpdate = (init = false, depth, paths = []) => git([
18816
19067
  "submodule",
18817
19068
  "update",
@@ -18819,13 +19070,6 @@ const submoduleUpdate = (init = false, depth, paths = []) => git([
18819
19070
  ...depth !== void 0 ? ["--depth", String(depth)] : [],
18820
19071
  ...paths.length > 0 ? ["--", ...paths] : []
18821
19072
  ]);
18822
- /**
18823
- * Mutating: `git submodule add [--depth <n>] -- <url> <path>` — registers and
18824
- * initializes a new submodule. The literal `--` separator makes the url and path
18825
- * injection-safe by construction.
18826
- *
18827
- * @public
18828
- */
18829
19073
  const submoduleAdd = (url, path, depth) => git([
18830
19074
  "submodule",
18831
19075
  "add",
@@ -18834,57 +19078,23 @@ const submoduleAdd = (url, path, depth) => git([
18834
19078
  url,
18835
19079
  path
18836
19080
  ]);
18837
- /**
18838
- * Mutating: `git sparse-checkout set (--cone | --no-cone) <patterns...>` — configures
18839
- * which paths are checked out in a sparse repository. The cone flag is explicit in both
18840
- * branches — `--cone` when `cone` is true, `--no-cone` when false — to prevent git's
18841
- * default from silently changing the behavior.
18842
- *
18843
- * @public
18844
- */
18845
19081
  const sparseCheckoutSet = (patterns, cone) => git([
18846
19082
  "sparse-checkout",
18847
19083
  "set",
18848
19084
  cone ? "--cone" : "--no-cone",
18849
19085
  ...patterns
18850
19086
  ]);
18851
- /**
18852
- * Mutating: `git config [-f <file>] <key> <value>` — writes a configuration value,
18853
- * optionally into an explicit configuration file (e.g., `.gitmodules`).
18854
- *
18855
- * @public
18856
- */
18857
19087
  const configSet = (key, value, file) => git([
18858
19088
  "config",
18859
19089
  ...file !== void 0 ? ["-f", file] : [],
18860
19090
  key,
18861
19091
  value
18862
19092
  ]);
18863
- /**
18864
- * Mutating: `git add -- <paths...>` — stages the given paths for commit. The literal
18865
- * `--` separator makes the pathspec injection-safe by construction.
18866
- *
18867
- * @public
18868
- */
18869
19093
  const add = (paths) => git([
18870
19094
  "add",
18871
19095
  "--",
18872
19096
  ...paths
18873
19097
  ]);
18874
- /**
18875
- * `git diff --name-status -z (--relative | --no-relative) [<base> | <base>...<head>]`
18876
- * — the changed paths WITH their one-letter status codes, NUL-terminated.
18877
- *
18878
- * @remarks
18879
- * With `head` omitted this is the single-argument diff form: the working tree
18880
- * (staged + unstaged) against `base` — NOT a two-ref range. With `head`
18881
- * present it is the familiar `base...head` merge-base form, matching
18882
- * {@link GitCommand.changedFiles}. `-z` and the explicit relative flag follow
18883
- * the same rules as {@link GitCommand.changedFiles}. In `-z` mode a rename or
18884
- * copy entry is THREE NUL tokens: `R<score>`, the old path, the new path.
18885
- *
18886
- * @public
18887
- */
18888
19098
  const nameStatus = (base, head, relative = false) => git([
18889
19099
  "diff",
18890
19100
  "--name-status",
@@ -18892,103 +19102,34 @@ const nameStatus = (base, head, relative = false) => git([
18892
19102
  relative ? "--relative" : "--no-relative",
18893
19103
  head === void 0 ? base : `${base}...${head}`
18894
19104
  ]);
18895
- /**
18896
- * `git symbolic-ref --quiet --short refs/remotes/<remote>/HEAD` — the name of
18897
- * the default branch on the given remote, or empty string / exit 1 if unset.
18898
- *
18899
- * @remarks
18900
- * `--quiet` suppresses error messages; the exit code alone signals success
18901
- * (0) or "symbolic-ref does not exist" (1). The contract is "does the remote
18902
- * have a HEAD?" — an unset symbolic ref exits 1 silently, which `Git.defaultBranch`
18903
- * degrades to `Option.none()` rather than a typed error. `symbolic-ref` is a
18904
- * purely local ref lookup; it never touches the network.
18905
- *
18906
- * @public
18907
- */
18908
19105
  const defaultBranch = (remote = "origin") => git([
18909
19106
  "symbolic-ref",
18910
19107
  "--quiet",
18911
19108
  "--short",
18912
19109
  `refs/remotes/${remote}/HEAD`
18913
19110
  ]);
18914
- /**
18915
- * `git rev-parse --abbrev-ref HEAD` — the name of the branch `HEAD` is
18916
- * pointing to.
18917
- *
18918
- * @remarks
18919
- * Returns `"HEAD"` (detached state), `"<branch>"` (an attached branch), or
18920
- * fails if the repository has no commits.
18921
- *
18922
- * @public
18923
- */
18924
19111
  const currentBranch = () => git([
18925
19112
  "rev-parse",
18926
19113
  "--abbrev-ref",
18927
19114
  "HEAD"
18928
19115
  ]);
18929
- /**
18930
- * `git rev-parse --show-toplevel` — the filesystem path to the root of the
18931
- * enclosing git repository.
18932
- *
18933
- * @public
18934
- */
18935
19116
  const repoRoot = () => git(["rev-parse", "--show-toplevel"]);
18936
- /**
18937
- * `git log -1 --format=%H%x00%G?%x00%B <ref>` — a NUL-separated triple: the
18938
- * full commit hash, the GPG trust level, and the full commit body (message),
18939
- * all untrimmed.
18940
- *
18941
- * @remarks
18942
- * `%H` is the full object id (40-char sha1, or sha256 if configured).
18943
- * `%x00` is a literal NUL byte (the separator). `%G?` is the GPG trust level
18944
- * (`G` = good signature, `B` = bad, `U` = untrusted, `X` = expired, `Y` =
18945
- * expired key, `R` = revoked key, `E` = error, or `N` = not signed).
18946
- * `%B` is the full body, **untrimmed** — it includes leading/trailing
18947
- * whitespace — so the caller must decide whether to trim it. Splits on the
18948
- * two `\x00` bytes to extract all three values.
18949
- *
18950
- * @public
18951
- */
18952
19117
  const commitInfo = (ref = "HEAD") => git([
18953
19118
  "log",
18954
19119
  "-1",
18955
19120
  "--format=%H%x00%G?%x00%B",
18956
19121
  ref
18957
19122
  ]);
18958
- /**
18959
- * `git config --get <key>` — the value of the given git config key, or empty
18960
- * string / exit 1 if unset.
18961
- *
18962
- * @public
18963
- */
18964
19123
  const configGet = (key) => git([
18965
19124
  "config",
18966
19125
  "--get",
18967
19126
  key
18968
19127
  ]);
18969
- /**
18970
- * `git remote get-url <remote>` — the fetch URL of the given remote. A
18971
- * missing remote exits non-zero with a "No such remote" stderr shape, which
18972
- * the `Git` service degrades to `Option.none`, never a typed error.
18973
- *
18974
- * @public
18975
- */
18976
19128
  const remoteUrl = (remote = "origin") => git([
18977
19129
  "remote",
18978
19130
  "get-url",
18979
19131
  remote
18980
19132
  ]);
18981
- /**
18982
- * `git status --porcelain -z` — the porcelain (stable, machine-readable) short
18983
- * status of every modified file in the working tree, NUL-terminated.
18984
- *
18985
- * @remarks
18986
- * `-z` is load-bearing here too, for the same reason as
18987
- * {@link GitCommand.lsTree}: split the output on `"\0"`, never on `"\n"`.
18988
- * Each entry is a pair of status codes followed by a space and the path.
18989
- *
18990
- * @public
18991
- */
18992
19133
  const status = () => git([
18993
19134
  "status",
18994
19135
  "--porcelain",
@@ -19006,35 +19147,211 @@ const status = () => git([
19006
19147
  *
19007
19148
  * @public
19008
19149
  */
19009
- const GitCommand = {
19010
- show,
19011
- lsTree,
19012
- refExists,
19013
- mergeBase,
19014
- changedFiles,
19015
- unstagedChanges,
19016
- stagedChanges,
19017
- untrackedFiles,
19018
- revParse,
19019
- checkout,
19020
- fetch: fetch$1,
19021
- submoduleUpdate,
19022
- submoduleAdd,
19023
- sparseCheckoutSet,
19024
- configSet,
19025
- add,
19026
- nameStatus,
19027
- defaultBranch,
19028
- currentBranch,
19029
- repoRoot,
19030
- commitInfo,
19031
- configGet,
19032
- remoteUrl,
19033
- status
19150
+ var GitCommand = class {
19151
+ constructor() {}
19152
+ /**
19153
+ * `git show <ref>:<path>` — the contents of `path` as it existed at `ref`,
19154
+ * without checking anything out.
19155
+ */
19156
+ static show = show;
19157
+ /**
19158
+ * `git ls-tree -r -z <ref> [-- <pathspec>...]` — every path in the tree at
19159
+ * `ref`, recursively, NUL-terminated, optionally scoped to `pathspec`.
19160
+ *
19161
+ * @remarks
19162
+ * `-z` is load-bearing: git paths may themselves contain newlines, so the
19163
+ * caller must split on `"\0"`, never on `"\n"`. When `pathspec` is provided,
19164
+ * a literal `--` separator is inserted before the pathspec entries to prevent
19165
+ * git from interpreting pathspec values as options.
19166
+ */
19167
+ static lsTree = lsTree;
19168
+ /**
19169
+ * `git cat-file -e <ref>` — checks whether `ref` resolves to an existing
19170
+ * object, without printing it. A non-zero exit means the ref does not exist.
19171
+ */
19172
+ static refExists = refExists;
19173
+ /**
19174
+ * `git merge-base <a> <b>` — the best common ancestor commit of `a` and `b`.
19175
+ */
19176
+ static mergeBase = mergeBase;
19177
+ /**
19178
+ * `git diff --name-only -z [--relative] <base>...<head>` — the paths that
19179
+ * differ between the merge base of `base` and `head`, and `head` itself,
19180
+ * NUL-terminated.
19181
+ *
19182
+ * @remarks
19183
+ * `-z` is load-bearing here too, for the same reason as {@link GitCommand.lsTree}: split
19184
+ * the output on `"\0"`, never on `"\n"`.
19185
+ *
19186
+ * The relative flag is **explicit in both branches** — `--relative` when
19187
+ * `relative` is true, `--no-relative` when false — never omitted. git honors a
19188
+ * configured `diff.relative=true` when no flag is passed, so an omitted flag
19189
+ * would silently yield cwd-relative paths on such a machine even for
19190
+ * `relative: false`, misaligning with {@link GitCommand.untrackedFiles}'s
19191
+ * repo-root base and breaking `Git.workingChanges`' dedup in a nested workspace.
19192
+ * `--relative` scopes the report to `cwd` (a workspace nested inside a larger
19193
+ * repository); `--no-relative` overrides any `diff.relative` config and reports
19194
+ * paths from the repository top-level.
19195
+ */
19196
+ static changedFiles = changedFiles;
19197
+ /**
19198
+ * `git diff --name-only -z (--relative | --no-relative)` — the paths with
19199
+ * unstaged working-tree changes (the working tree against the index),
19200
+ * NUL-terminated.
19201
+ *
19202
+ * @remarks
19203
+ * `relative` behaves as it does for {@link GitCommand.changedFiles}, including the
19204
+ * explicit-flag-in-both-branches rule: `--no-relative` is passed for
19205
+ * `relative: false` so a configured `diff.relative=true` cannot silently make the
19206
+ * output cwd-relative.
19207
+ */
19208
+ static unstagedChanges = unstagedChanges;
19209
+ /**
19210
+ * `git diff --name-only -z (--relative | --no-relative) --cached` — the paths
19211
+ * staged for the next commit (the index against `HEAD`), NUL-terminated.
19212
+ *
19213
+ * @remarks
19214
+ * `relative` behaves as it does for {@link GitCommand.changedFiles}, including the
19215
+ * explicit `--no-relative` on the `relative: false` branch.
19216
+ */
19217
+ static stagedChanges = stagedChanges;
19218
+ /**
19219
+ * `git ls-files --others --exclude-standard -z [--full-name]` — the untracked
19220
+ * paths git is not ignoring, NUL-terminated.
19221
+ *
19222
+ * @remarks
19223
+ * `ls-files` reports paths relative to `cwd` by default, matching the
19224
+ * `--relative` diffs. When `relative` is `false`, `--full-name` makes it emit
19225
+ * repo-root-relative paths instead, so the untracked half shares a base with the
19226
+ * un-`--relative` diffs — otherwise `Git.workingChanges`'s union would dedup two
19227
+ * spellings of one file from a nested `cwd`.
19228
+ */
19229
+ static untrackedFiles = untrackedFiles;
19230
+ /**
19231
+ * `git rev-parse --verify <ref>` — resolves `ref` to its full object id, or
19232
+ * fails if `ref` does not resolve.
19233
+ */
19234
+ static revParse = revParse;
19235
+ /**
19236
+ * Mutating: `git checkout [--detach] <ref>` — moves the working tree (and, for
19237
+ * a branch ref, `HEAD`) to `ref`. When `detach` is true, checks out the ref in
19238
+ * detached-HEAD state.
19239
+ */
19240
+ static checkout = checkout;
19241
+ /**
19242
+ * Mutating: `git fetch [--depth <n>] <remote> [tag] <ref>` — fetches the given
19243
+ * ref from a remote, optionally with a depth limit and the `tag` keyword.
19244
+ */
19245
+ static fetch = fetch$1;
19246
+ /**
19247
+ * Mutating: `git submodule update [--init] [--depth <n>] [-- <paths>...]` — updates
19248
+ * registered submodules, optionally initializing them, with an optional depth limit,
19249
+ * and scoped to specific paths. The literal `--` separator makes the pathspec
19250
+ * injection-safe by construction.
19251
+ */
19252
+ static submoduleUpdate = submoduleUpdate;
19253
+ /**
19254
+ * Mutating: `git submodule add [--depth <n>] -- <url> <path>` — registers and
19255
+ * initializes a new submodule. The literal `--` separator makes the url and path
19256
+ * injection-safe by construction.
19257
+ */
19258
+ static submoduleAdd = submoduleAdd;
19259
+ /**
19260
+ * Mutating: `git sparse-checkout set (--cone | --no-cone) <patterns...>` — configures
19261
+ * which paths are checked out in a sparse repository. The cone flag is explicit in both
19262
+ * branches — `--cone` when `cone` is true, `--no-cone` when false — to prevent git's
19263
+ * default from silently changing the behavior.
19264
+ */
19265
+ static sparseCheckoutSet = sparseCheckoutSet;
19266
+ /**
19267
+ * Mutating: `git config [-f <file>] <key> <value>` — writes a configuration value,
19268
+ * optionally into an explicit configuration file (e.g., `.gitmodules`).
19269
+ */
19270
+ static configSet = configSet;
19271
+ /**
19272
+ * Mutating: `git add -- <paths...>` — stages the given paths for commit. The literal
19273
+ * `--` separator makes the pathspec injection-safe by construction.
19274
+ */
19275
+ static add = add;
19276
+ /**
19277
+ * `git diff --name-status -z (--relative | --no-relative) [<base> | <base>...<head>]`
19278
+ * — the changed paths WITH their one-letter status codes, NUL-terminated.
19279
+ *
19280
+ * @remarks
19281
+ * With `head` omitted this is the single-argument diff form: the working tree
19282
+ * (staged + unstaged) against `base` — NOT a two-ref range. With `head`
19283
+ * present it is the familiar `base...head` merge-base form, matching
19284
+ * {@link GitCommand.changedFiles}. `-z` and the explicit relative flag follow
19285
+ * the same rules as {@link GitCommand.changedFiles}. In `-z` mode a rename or
19286
+ * copy entry is THREE NUL tokens: `R<score>`, the old path, the new path.
19287
+ */
19288
+ static nameStatus = nameStatus;
19289
+ /**
19290
+ * `git symbolic-ref --quiet --short refs/remotes/<remote>/HEAD` — the name of
19291
+ * the default branch on the given remote, or empty string / exit 1 if unset.
19292
+ *
19293
+ * @remarks
19294
+ * `--quiet` suppresses error messages; the exit code alone signals success
19295
+ * (0) or "symbolic-ref does not exist" (1). The contract is "does the remote
19296
+ * have a HEAD?" — an unset symbolic ref exits 1 silently, which `Git.defaultBranch`
19297
+ * degrades to `Option.none()` rather than a typed error. `symbolic-ref` is a
19298
+ * purely local ref lookup; it never touches the network.
19299
+ */
19300
+ static defaultBranch = defaultBranch;
19301
+ /**
19302
+ * `git rev-parse --abbrev-ref HEAD` — the name of the branch `HEAD` is
19303
+ * pointing to.
19304
+ *
19305
+ * @remarks
19306
+ * Returns `"HEAD"` (detached state), `"<branch>"` (an attached branch), or
19307
+ * fails if the repository has no commits.
19308
+ */
19309
+ static currentBranch = currentBranch;
19310
+ /**
19311
+ * `git rev-parse --show-toplevel` — the filesystem path to the root of the
19312
+ * enclosing git repository.
19313
+ */
19314
+ static repoRoot = repoRoot;
19315
+ /**
19316
+ * `git log -1 --format=%H%x00%G?%x00%B <ref>` — a NUL-separated triple: the
19317
+ * full commit hash, the GPG trust level, and the full commit body (message),
19318
+ * all untrimmed.
19319
+ *
19320
+ * @remarks
19321
+ * `%H` is the full object id (40-char sha1, or sha256 if configured).
19322
+ * `%x00` is a literal NUL byte (the separator). `%G?` is the GPG trust level
19323
+ * (`G` = good signature, `B` = bad, `U` = untrusted, `X` = expired, `Y` =
19324
+ * expired key, `R` = revoked key, `E` = error, or `N` = not signed).
19325
+ * `%B` is the full body, **untrimmed** — it includes leading/trailing
19326
+ * whitespace — so the caller must decide whether to trim it. Splits on the
19327
+ * two `\x00` bytes to extract all three values.
19328
+ */
19329
+ static commitInfo = commitInfo;
19330
+ /**
19331
+ * `git config --get <key>` — the value of the given git config key, or empty
19332
+ * string / exit 1 if unset.
19333
+ */
19334
+ static configGet = configGet;
19335
+ /**
19336
+ * `git remote get-url <remote>` — the fetch URL of the given remote. A
19337
+ * missing remote exits non-zero with a "No such remote" stderr shape, which
19338
+ * the `Git` service degrades to `Option.none`, never a typed error.
19339
+ */
19340
+ static remoteUrl = remoteUrl;
19341
+ /**
19342
+ * `git status --porcelain -z` — the porcelain (stable, machine-readable) short
19343
+ * status of every modified file in the working tree, NUL-terminated.
19344
+ *
19345
+ * @remarks
19346
+ * `-z` is load-bearing here too, for the same reason as
19347
+ * {@link GitCommand.lsTree}: split the output on `"\0"`, never on `"\n"`.
19348
+ * Each entry is a pair of status codes followed by a space and the path.
19349
+ */
19350
+ static status = status;
19034
19351
  };
19035
19352
 
19036
19353
  //#endregion
19037
- //#region ../../node_modules/.pnpm/@effected+git@0.4.2_effect@4.0.0-beta.101/node_modules/@effected/git/internal/run.js
19354
+ //#region ../../node_modules/.pnpm/@effected+git@0.5.1_effect@4.0.0-beta.101/node_modules/@effected/git/internal/run.js
19038
19355
  /**
19039
19356
  * Spawns `command` and collects its stdout, stderr, and exit code as a single
19040
19357
  * triple.
@@ -19062,7 +19379,7 @@ const runCollected = (command) => Effect.scoped(Effect.gen(function* () {
19062
19379
  }));
19063
19380
 
19064
19381
  //#endregion
19065
- //#region ../../node_modules/.pnpm/@effected+git@0.4.2_effect@4.0.0-beta.101/node_modules/@effected/git/Git.js
19382
+ //#region ../../node_modules/.pnpm/@effected+git@0.5.1_effect@4.0.0-beta.101/node_modules/@effected/git/Git.js
19066
19383
  /** git's own ceiling: a run that has not answered in 30s is not going to. */
19067
19384
  const GIT_TIMEOUT = Duration.seconds(30);
19068
19385
  /**
@@ -19949,6 +20266,12 @@ const make = (spawner) => {
19949
20266
  };
19950
20267
  };
19951
20268
  /**
20269
+ * The default for every {@link Git.makeTest} method a test did not stub: a
20270
+ * defect naming the method, so an unexercised call fails loudly instead of
20271
+ * succeeding with a lie or failing with a dishonest typed error.
20272
+ */
20273
+ const notStubbed = (method) => () => 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.`));
20274
+ /**
19952
20275
  * Typed git introspection over core's `ChildProcessSpawner`: read a
19953
20276
  * repository's state at any ref without checking it out, plus the mutating
19954
20277
  * tier (`checkout`, `fetch`, `fetchAny`, `submoduleUpdate`, `submoduleAdd`,
@@ -19971,16 +20294,103 @@ const make = (spawner) => {
19971
20294
  *
19972
20295
  * @public
19973
20296
  */
19974
- var Git = class extends Context.Service()("@effected/git/Git") {
20297
+ var Git = class Git extends Context.Service()("@effected/git/Git") {
19975
20298
  /** Resolves `ChildProcessSpawner` once, at construction — every method's `R` is `never`. */
19976
20299
  static layer = Layer.effect(this, Effect.gen(function* () {
19977
20300
  const spawner = yield* ChildProcessSpawner.ChildProcessSpawner;
19978
20301
  return make(spawner);
19979
20302
  }));
20303
+ /**
20304
+ * An in-memory test double of the service shape: stub only the methods the
20305
+ * test exercises, every other method **dies** with a defect naming itself.
20306
+ *
20307
+ * @remarks
20308
+ * Unlike `WorkspaceDiscovery.makeTest`, **no method here has an honest
20309
+ * default** — the shape is twenty-six unrelated git operations, and a
20310
+ * fabricated answer for any of them (an empty tree, a made-up sha, a silent
20311
+ * no-op `checkout`) would leak into consumer logic as fact. So every
20312
+ * unstubbed method fails loudly as a defect
20313
+ * (`Git.makeTest: <name>() was called but not stubbed`) rather than
20314
+ * succeeding with a lie or failing with a dishonest typed error — which is
20315
+ * also what makes the double a proof that a test touches *nothing but* the
20316
+ * methods it stubbed.
20317
+ *
20318
+ * The double deliberately models **none** of the live service's semantics:
20319
+ * no stderr classification, no option-injection guard (an option-like ref a
20320
+ * stub accepts would be refused live), no `LC_ALL=C` pinning, no timeout,
20321
+ * and no `./`-vs-bare path resolution on `show` — a stub answers exactly
20322
+ * what it is told and nothing else. A suite exercising any of those wants
20323
+ * `Git.layer` over a mocked `ChildProcessSpawner` (or real git) instead.
20324
+ *
20325
+ * @example
20326
+ * ```ts
20327
+ * import { Git } from "@effected/git";
20328
+ * import { Effect, Option } from "effect";
20329
+ *
20330
+ * const double = Git.makeTest({
20331
+ * show: (_cwd, _ref, path) =>
20332
+ * Effect.succeed(path === "./package.json" ? Option.some("{}") : Option.none()),
20333
+ * });
20334
+ * // `double.show(...)` answers; `double.status(...)` dies, named.
20335
+ * ```
20336
+ */
20337
+ static makeTest = (overrides = {}) => ({
20338
+ show: notStubbed("show"),
20339
+ lsTree: notStubbed("lsTree"),
20340
+ refExists: notStubbed("refExists"),
20341
+ mergeBase: notStubbed("mergeBase"),
20342
+ changedFiles: notStubbed("changedFiles"),
20343
+ workingChanges: notStubbed("workingChanges"),
20344
+ revParse: notStubbed("revParse"),
20345
+ checkout: notStubbed("checkout"),
20346
+ fetch: notStubbed("fetch"),
20347
+ fetchAny: notStubbed("fetchAny"),
20348
+ submoduleUpdate: notStubbed("submoduleUpdate"),
20349
+ submoduleAdd: notStubbed("submoduleAdd"),
20350
+ sparseCheckoutSet: notStubbed("sparseCheckoutSet"),
20351
+ configSet: notStubbed("configSet"),
20352
+ add: notStubbed("add"),
20353
+ nameStatus: notStubbed("nameStatus"),
20354
+ unstagedChanges: notStubbed("unstagedChanges"),
20355
+ stagedChanges: notStubbed("stagedChanges"),
20356
+ untrackedFiles: notStubbed("untrackedFiles"),
20357
+ defaultBranch: notStubbed("defaultBranch"),
20358
+ currentBranch: notStubbed("currentBranch"),
20359
+ repoRoot: notStubbed("repoRoot"),
20360
+ configGet: notStubbed("configGet"),
20361
+ remoteUrl: notStubbed("remoteUrl"),
20362
+ commitInfo: notStubbed("commitInfo"),
20363
+ status: notStubbed("status"),
20364
+ ...overrides
20365
+ });
20366
+ /**
20367
+ * The test layer: {@link Git.makeTest} behind `Layer.succeed`, so a suite
20368
+ * provides only the methods it exercises.
20369
+ *
20370
+ * @remarks
20371
+ * A parameterized layer factory mints a **fresh reference per call**, and
20372
+ * layers memoize by reference — bind the result to a `const` and reuse it
20373
+ * rather than calling `layerTest(...)` at each composition site.
20374
+ *
20375
+ * @example
20376
+ * ```ts
20377
+ * import { Git, LsTreeEntry } from "@effected/git";
20378
+ * import { Effect } from "effect";
20379
+ *
20380
+ * const TestGit = Git.layerTest({
20381
+ * lsTree: () =>
20382
+ * Effect.succeed([
20383
+ * LsTreeEntry.make({ mode: "100644", type: "blob", oid: "0".repeat(40), path: "package.json" }),
20384
+ * ]),
20385
+ * });
20386
+ * // program.pipe(Effect.provide(TestGit))
20387
+ * ```
20388
+ */
20389
+ static layerTest = (overrides = {}) => Layer.succeed(Git, Git.makeTest(overrides));
19980
20390
  };
19981
20391
 
19982
20392
  //#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/ChangeDetector.js
20393
+ //#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
19984
20394
  /**
19985
20395
  * Which git refs to compare, and whether to fold in the working tree.
19986
20396
  *
@@ -20262,7 +20672,7 @@ function resolveFromCatalog(catalogs, wantedDependency) {
20262
20672
  }
20263
20673
 
20264
20674
  //#endregion
20265
- //#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
20675
+ //#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
20266
20676
  /** Project a pnpm-workspace manifest's `catalog` / `catalogs` fields into a `Catalogs` map. */
20267
20677
  const inlineCatalogs = (manifest) => {
20268
20678
  if (manifest.catalog === void 0 && manifest.catalogs === void 0) return {};
@@ -20327,7 +20737,7 @@ const rangeOf = (catalogs, dependency, specifier) => {
20327
20737
  };
20328
20738
 
20329
20739
  //#endregion
20330
- //#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
20740
+ //#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
20331
20741
  /** Whether `value` is a non-null, non-array object. */
20332
20742
  const isObject$2 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
20333
20743
  /**
@@ -20514,7 +20924,7 @@ var ConfigDependencyHooks = class ConfigDependencyHooks extends Context.Service(
20514
20924
  };
20515
20925
 
20516
20926
  //#endregion
20517
- //#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
20927
+ //#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
20518
20928
  /**
20519
20929
  * The four package managers this package understands.
20520
20930
  *
@@ -20615,7 +21025,11 @@ const CHECKED = [
20615
21025
  "bun.lock",
20616
21026
  "bun.lockb",
20617
21027
  "yarn.lock",
20618
- "package.json#workspaces"
21028
+ "package.json#workspaces",
21029
+ "pnpm-lock.yaml",
21030
+ "package-lock.json",
21031
+ "package.json#packageManager",
21032
+ "package.json#devEngines.packageManager"
20619
21033
  ];
20620
21034
  /**
20621
21035
  * Detects which package manager owns a workspace root.
@@ -20729,7 +21143,8 @@ var PackageManagerDetector = class PackageManagerDetector extends Context.Servic
20729
21143
  version: versionFor(hints, "pnpm"),
20730
21144
  runtime: "node"
20731
21145
  });
20732
- if (((yield* has(root, "bun.lock")) || (yield* has(root, "bun.lockb"))) && namesManager(hints, "bun")) return DetectedPackageManager.make({
21146
+ const bunLock = (yield* has(root, "bun.lock")) || (yield* has(root, "bun.lockb"));
21147
+ if (bunLock && namesManager(hints, "bun")) return DetectedPackageManager.make({
20733
21148
  name: "bun",
20734
21149
  version: versionFor(hints, "bun"),
20735
21150
  runtime: "bun"
@@ -20745,6 +21160,35 @@ var PackageManagerDetector = class PackageManagerDetector extends Context.Servic
20745
21160
  version: versionFor(hints, "npm"),
20746
21161
  runtime: "node"
20747
21162
  });
21163
+ if (yield* has(root, "pnpm-lock.yaml")) return DetectedPackageManager.make({
21164
+ name: "pnpm",
21165
+ version: versionFor(hints, "pnpm"),
21166
+ runtime: "node"
21167
+ });
21168
+ if (bunLock && namesManager(hints, "bun")) return DetectedPackageManager.make({
21169
+ name: "bun",
21170
+ version: versionFor(hints, "bun"),
21171
+ runtime: "bun"
21172
+ });
21173
+ if ((yield* has(root, "yarn.lock")) && namesManager(hints, "yarn")) return DetectedPackageManager.make({
21174
+ name: "yarn",
21175
+ version: versionFor(hints, "yarn"),
21176
+ runtime: "node"
21177
+ });
21178
+ if (yield* has(root, "package-lock.json")) return DetectedPackageManager.make({
21179
+ name: "npm",
21180
+ version: versionFor(hints, "npm"),
21181
+ runtime: "node"
21182
+ });
21183
+ const declared = declaredName(hints);
21184
+ if (Option.isSome(declared)) {
21185
+ const name = declared.value;
21186
+ if (name === "pnpm" || name === "npm" || name === "yarn" || name === "bun") return DetectedPackageManager.make({
21187
+ name,
21188
+ version: versionFor(hints, name),
21189
+ runtime: name === "bun" ? "bun" : "node"
21190
+ });
21191
+ }
20748
21192
  return yield* Effect.fail(new PackageManagerDetectionError({
20749
21193
  root,
20750
21194
  checked: CHECKED
@@ -20754,10 +21198,57 @@ var PackageManagerDetector = class PackageManagerDetector extends Context.Servic
20754
21198
  });
20755
21199
  /** The live layer. */
20756
21200
  static layer = Layer.effect(PackageManagerDetector, PackageManagerDetector.make);
21201
+ /**
21202
+ * The sanctioned in-memory double.
21203
+ *
21204
+ * @remarks
21205
+ * **`detect` has no honest default, so an unstubbed call dies** — the
21206
+ * `WorkspaceDiscovery.info` posture, for the same reason. A stand-in that
21207
+ * answered `"pnpm"` would hand a consumer a fact nothing established, and it
21208
+ * would contradict the very service it stands in for: the live detector's
21209
+ * defining property is that it [refuses to
21210
+ * guess](https://github.com/spencerbeggs/effected) when no evidence matches.
21211
+ * A double that guesses is worse than no double.
21212
+ *
21213
+ * Failing typed would be the subtler mistake: `PackageManagerDetectionError`
21214
+ * reads as a legitimate "no manager here" answer, so a consumer would branch
21215
+ * on it and proceed, never learning that the test simply forgot to stub.
21216
+ *
21217
+ * @param overrides - Members to supply; anything omitted dies on use.
21218
+ *
21219
+ * @example
21220
+ * ```ts
21221
+ * import { DetectedPackageManager, PackageManagerDetector } from "@effected/workspaces";
21222
+ * import { Effect, Option } from "effect";
21223
+ *
21224
+ * const TestDetector = PackageManagerDetector.layerTest({
21225
+ * detect: () =>
21226
+ * Effect.succeed(
21227
+ * DetectedPackageManager.make({ name: "pnpm", version: Option.none(), runtime: "node" }),
21228
+ * ),
21229
+ * });
21230
+ * ```
21231
+ */
21232
+ static makeTest = (overrides = {}) => ({
21233
+ detect: () => 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.")),
21234
+ ...overrides
21235
+ });
21236
+ /**
21237
+ * {@link PackageManagerDetector.makeTest} behind `Layer.succeed`.
21238
+ *
21239
+ * @remarks
21240
+ * A parameterized layer factory mints a **fresh reference per call**, and
21241
+ * layers memoize by reference — bind the result to a `const` and reuse it
21242
+ * rather than calling `layerTest(...)` at each composition site.
21243
+ *
21244
+ * Pairs with `WorkspaceRoot.layerTest` and `WorkspaceDiscovery.layerTest` to
21245
+ * stand up the whole discovery path with no filesystem at all.
21246
+ */
21247
+ static layerTest = (overrides = {}) => Layer.succeed(PackageManagerDetector, PackageManagerDetector.makeTest(overrides));
20757
21248
  };
20758
21249
 
20759
21250
  //#endregion
20760
- //#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
21251
+ //#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
20761
21252
  /**
20762
21253
  * Raised when the workspace's lockfile cannot be read off disk.
20763
21254
  *
@@ -20780,6 +21271,8 @@ var LockfileReadError = class extends Schema.TaggedErrorClass()("LockfileReadErr
20780
21271
  return `Cannot read ${this.format} lockfile at ${this.lockfilePath}`;
20781
21272
  }
20782
21273
  };
21274
+ /** A defect naming the unstubbed test-double method — a test-wiring mistake, not a typed failure. */
21275
+ const unstubbed$2 = (method) => Effect.die(/* @__PURE__ */ new Error(`LockfileReader.makeTest: ${method}() was called but not stubbed — pass a \`${method}\` override.`));
20783
21276
  /**
20784
21277
  * Reads and parses the workspace's lockfile.
20785
21278
  *
@@ -20865,10 +21358,78 @@ var LockfileReader = class LockfileReader extends Context.Service()("@effected/w
20865
21358
  * `const` and reuse it.
20866
21359
  */
20867
21360
  static layer = (options) => Layer.effect(LockfileReader, LockfileReader.make(options));
21361
+ /**
21362
+ * A test double satisfying the full {@link LockfileReaderShape} with no
21363
+ * filesystem, root walk, or package-manager detection.
21364
+ *
21365
+ * @remarks
21366
+ * There is **no honest default lockfile**: an empty one that looks like a
21367
+ * legitimate answer is indistinguishable from "this workspace resolves
21368
+ * nothing" — the silent-empty failure class this package documents on the
21369
+ * live paths — so `read` **dies** with an instructive defect until stubbed.
21370
+ *
21371
+ * The one derivation mirrors `WorkspaceDiscovery.makeTest`'s
21372
+ * derived-from-the-primary rule: when a `read` override is supplied,
21373
+ * `resolvedVersion` answers as the live service does — the **first** entry
21374
+ * of `lockfile.packagesNamed(name)` in lockfile order, `Option.none()` on a
21375
+ * miss — so the two stay consistent by construction. `integrity` is **not**
21376
+ * derivable: the live method compares the lockfile against the workspace
21377
+ * manifests discovery enumerates, and the double has no discovery to ask, so
21378
+ * it dies unless stubbed.
21379
+ *
21380
+ * `refresh` defaults to `Effect.void` honestly: the live contract is "drop
21381
+ * the memoized read so the next call re-reads", and this double memoizes
21382
+ * nothing — every `read()` call re-invokes the override — so there is
21383
+ * nothing to drop and the no-op is truthful, the same reasoning as
21384
+ * `WorkspaceDiscovery.makeTest`'s `refresh`.
21385
+ *
21386
+ * @example
21387
+ * ```ts
21388
+ * import { Lockfile } from "@effected/lockfiles";
21389
+ * import { LockfileReader } from "@effected/workspaces";
21390
+ * import { Effect } from "effect";
21391
+ *
21392
+ * const double = LockfileReader.makeTest({
21393
+ * read: () =>
21394
+ * Effect.succeed(
21395
+ * Lockfile.make({ format: "pnpm", lockfileVersion: "9.0", packages: [], workspaceDependencies: [] }),
21396
+ * ),
21397
+ * });
21398
+ * // `resolvedVersion` now answers consistently from that lockfile.
21399
+ * ```
21400
+ */
21401
+ static makeTest = (overrides = {}) => {
21402
+ const read = overrides.read;
21403
+ return {
21404
+ read: () => unstubbed$2("read"),
21405
+ resolvedVersion: read !== void 0 ? (packageName) => Effect.map(read(), (lockfile) => Option.fromUndefinedOr(lockfile.packagesNamed(packageName)[0])) : () => unstubbed$2("resolvedVersion"),
21406
+ integrity: () => unstubbed$2("integrity"),
21407
+ refresh: () => Effect.void,
21408
+ ...overrides
21409
+ };
21410
+ };
21411
+ /**
21412
+ * The test layer: {@link LockfileReader.makeTest} behind `Layer.succeed`, so
21413
+ * a suite provides only the methods it exercises.
21414
+ *
21415
+ * @remarks
21416
+ * A parameterized layer factory mints a **fresh reference per call**, and
21417
+ * layers memoize by reference — bind the result to a `const` and reuse it
21418
+ * rather than calling `layerTest(...)` at each composition site.
21419
+ *
21420
+ * @example
21421
+ * ```ts
21422
+ * import { LockfileReader } from "@effected/workspaces";
21423
+ *
21424
+ * const TestLockfiles = LockfileReader.layerTest();
21425
+ * // program.pipe(Effect.provide(TestLockfiles)) — dies loudly if touched.
21426
+ * ```
21427
+ */
21428
+ static layerTest = (overrides = {}) => Layer.succeed(LockfileReader, LockfileReader.makeTest(overrides));
20868
21429
  };
20869
21430
 
20870
21431
  //#endregion
20871
- //#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
21432
+ //#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
20872
21433
  /** The public npm registry, used when `publishConfig.registry` says nothing. */
20873
21434
  const DEFAULT_REGISTRY = "https://registry.npmjs.org/";
20874
21435
  /**
@@ -20952,9 +21513,35 @@ var PublishTarget = class extends Schema.Class("PublishTarget")({
20952
21513
  *
20953
21514
  * @public
20954
21515
  */
20955
- var PublishabilityDetector = class PublishabilityDetector extends Context.Service()("@effected/workspaces/PublishabilityDetector") {
20956
- /** Standard npm publishing semantics. Pure — no filesystem, no platform services. */
20957
- static layer = Layer.succeed(PublishabilityDetector, { detect: (pkg) => Effect.sync(() => {
21516
+ var PublishabilityDetector = class extends Context.Service()("@effected/workspaces/PublishabilityDetector") {
21517
+ /**
21518
+ * Standard npm publishing semantics, **as a value**. Pure no filesystem,
21519
+ * no platform services.
21520
+ *
21521
+ * @remarks
21522
+ * Exposed as a shape and not only as a layer, because a consumer composing
21523
+ * *around* these rules cannot reach them through a layer without re-entering
21524
+ * the very tag it is replacing. `@savvy-web/silk-effects` had to write
21525
+ * `Effect.provide(PublishabilityDetector, PublishabilityDetector.layer)`
21526
+ * **inside its own implementation of that tag** to get at this function for
21527
+ * its pass-through branch; with the value exposed that becomes
21528
+ * `PublishabilityDetector.npm.detect(pkg)`.
21529
+ *
21530
+ * @example
21531
+ * ```ts
21532
+ * import { PublishabilityDetector } from "@effected/workspaces";
21533
+ * import { Effect, Layer } from "effect";
21534
+ *
21535
+ * // A policy that defers to npm semantics for everything it does not veto.
21536
+ * const withVeto = Layer.succeed(PublishabilityDetector, {
21537
+ * detect: (pkg) =>
21538
+ * pkg.name.endsWith("-private")
21539
+ * ? Effect.succeed([])
21540
+ * : PublishabilityDetector.npm.detect(pkg),
21541
+ * });
21542
+ * ```
21543
+ */
21544
+ static npm = { detect: (pkg) => Effect.sync(() => {
20958
21545
  const config = pkg.publishConfig;
20959
21546
  const access = config?.access;
20960
21547
  if (pkg.private && access === void 0) return [];
@@ -20965,11 +21552,37 @@ var PublishabilityDetector = class PublishabilityDetector extends Context.Servic
20965
21552
  access: access ?? "public",
20966
21553
  provenance: false
20967
21554
  })];
20968
- }) });
21555
+ }) };
21556
+ /** Nothing publishes. */
21557
+ static none = { detect: () => Effect.succeed([]) };
21558
+ /**
21559
+ * {@link PublishabilityDetector.npm} as a layer.
21560
+ *
21561
+ * @remarks
21562
+ * Named for its policy rather than called `layer`, deliberately. **No
21563
+ * composite in this package provides a publishability detector**: a
21564
+ * `Workspaces.layer()` that quietly supplied npm semantics made the choice
21565
+ * invisible, and worse, made a naively-ordered override lose to it in
21566
+ * silence — `Layer.mergeAll(myDetector, Workspaces.layer())` resolved to the
21567
+ * default, because `mergeAll` is last-wins. For a service that decides
21568
+ * whether a package publishes and to which registry, that silent revert was
21569
+ * the worst available failure. The requirement now sits in `R`, so the
21570
+ * choice is made once, explicitly, and unmade wiring does not compile.
21571
+ */
21572
+ static layerNpm = Layer.succeed(this, this.npm);
21573
+ /**
21574
+ * {@link PublishabilityDetector.none} as a layer: a workspace where nothing
21575
+ * publishes.
21576
+ *
21577
+ * @remarks
21578
+ * For dry runs, and for a release tool whose configuration disables
21579
+ * publishing wholesale — silk's changeset `mode: "none"` is exactly this.
21580
+ */
21581
+ static layerNone = Layer.succeed(this, this.none);
20969
21582
  };
20970
21583
 
20971
21584
  //#endregion
20972
- //#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
21585
+ //#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
20973
21586
  /**
20974
21587
  * Strip pnpm's peer-disambiguation suffix from a recorded importer version.
20975
21588
  *
@@ -21056,7 +21669,7 @@ const unanimousVersionOf = (index, dependency) => {
21056
21669
  };
21057
21670
 
21058
21671
  //#endregion
21059
- //#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
21672
+ //#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
21060
21673
  /**
21061
21674
  * An immutable, fully-normalized catalog collection — the one catalog
21062
21675
  * resolution semantic in the package.
@@ -21332,6 +21945,8 @@ const validatePnpmWorkspaceCatalogs = (document) => {
21332
21945
  catalogs: "catalogs"
21333
21946
  }));
21334
21947
  };
21948
+ /** A defect naming the unstubbed test-double method — a test-wiring mistake, not a typed failure. */
21949
+ const unstubbed$1 = (method) => Effect.die(/* @__PURE__ */ new Error(`WorkspaceCatalogs.makeTest: ${method}() was called but not stubbed — pass a \`${method}\` override.`));
21335
21950
  /**
21336
21951
  * Assembles a workspace's catalogs, package-manager-aware.
21337
21952
  *
@@ -21475,6 +22090,70 @@ var WorkspaceCatalogs = class WorkspaceCatalogs extends Context.Service()("@effe
21475
22090
  */
21476
22091
  static layerWithConfigDependencies = (options) => Layer.effect(WorkspaceCatalogs, WorkspaceCatalogs.make(options)).pipe(Layer.provide(ConfigDependencyHooks.layerLive));
21477
22092
  /**
22093
+ * A test double satisfying the full {@link WorkspaceCatalogsShape} with no
22094
+ * filesystem, lockfile read, or hook replay.
22095
+ *
22096
+ * @remarks
22097
+ * There is **no honest default catalog set**: an empty `CatalogSet` that
22098
+ * looks like a legitimate answer is the "every dependency looks newly added"
22099
+ * failure class the live assembler hard-fails to prevent, so every method
22100
+ * **dies** with an instructive defect until stubbed — a test-wiring mistake
22101
+ * fails loudly as a defect rather than succeeding with a lie or failing with
22102
+ * a dishonest typed error.
22103
+ *
22104
+ * The one derivation mirrors `WorkspaceDiscovery.makeTest`'s
22105
+ * derived-from-the-primary rule: when a `set` override is supplied,
22106
+ * `resolveSpecifier` answers from that `CatalogSet`'s own
22107
+ * {@link CatalogSet.resolveSpecifier} — exactly what the live service runs
22108
+ * over its assembled set — so the two stay consistent by construction.
22109
+ * `releaseAgeGate` and `importerVersions` are **not** derivable from a
22110
+ * catalog set (the gate comes from release-age keys and hook contributions,
22111
+ * the importer index from the lockfile's importer blocks — neither is in a
22112
+ * `CatalogSet`) and always die unless stubbed.
22113
+ *
22114
+ * @example
22115
+ * ```ts
22116
+ * import { CatalogSet, WorkspaceCatalogs } from "@effected/workspaces";
22117
+ * import { Effect } from "effect";
22118
+ *
22119
+ * const double = WorkspaceCatalogs.makeTest({
22120
+ * set: () => Effect.succeed(CatalogSet.fromCatalogs({ default: { effect: "4.0.0" } })),
22121
+ * });
22122
+ * // `resolveSpecifier` now answers consistently from that set.
22123
+ * ```
22124
+ */
22125
+ static makeTest = (overrides = {}) => {
22126
+ const set = overrides.set;
22127
+ return {
22128
+ set: () => unstubbed$1("set"),
22129
+ resolveSpecifier: set !== void 0 ? (dependency, specifier) => Effect.map(set(), (catalogs) => catalogs.resolveSpecifier(dependency, specifier)) : () => unstubbed$1("resolveSpecifier"),
22130
+ releaseAgeGate: () => unstubbed$1("releaseAgeGate"),
22131
+ importerVersions: () => unstubbed$1("importerVersions"),
22132
+ ...overrides
22133
+ };
22134
+ };
22135
+ /**
22136
+ * The test layer: {@link WorkspaceCatalogs.makeTest} behind `Layer.succeed`,
22137
+ * so a suite provides only the methods it exercises.
22138
+ *
22139
+ * @remarks
22140
+ * A parameterized layer factory mints a **fresh reference per call**, and
22141
+ * layers memoize by reference — bind the result to a `const` and reuse it
22142
+ * rather than calling `layerTest(...)` at each composition site.
22143
+ *
22144
+ * @example
22145
+ * ```ts
22146
+ * import { CatalogSet, WorkspaceCatalogs } from "@effected/workspaces";
22147
+ * import { Effect } from "effect";
22148
+ *
22149
+ * const TestCatalogs = WorkspaceCatalogs.layerTest({
22150
+ * set: () => Effect.succeed(CatalogSet.empty()),
22151
+ * });
22152
+ * // program.pipe(Effect.provide(TestCatalogs))
22153
+ * ```
22154
+ */
22155
+ static layerTest = (overrides = {}) => Layer.succeed(WorkspaceCatalogs, WorkspaceCatalogs.makeTest(overrides));
22156
+ /**
21478
22157
  * The real implementation of `@effected/npm`'s `CatalogResolver` contract —
21479
22158
  * the one `@effected/package-json` declares but cannot fill.
21480
22159
  *
@@ -21500,7 +22179,7 @@ var WorkspaceCatalogs = class WorkspaceCatalogs extends Context.Service()("@effe
21500
22179
  };
21501
22180
 
21502
22181
  //#endregion
21503
- //#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
22182
+ //#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
21504
22183
  const EMPTY = Object.freeze(Object.create(null));
21505
22184
  const DependencyMap = Schema.Record(Schema.String, Schema.String).pipe(Schema.withDecodingDefaultKey(Effect.succeed(EMPTY)), Schema.withConstructorDefault(Effect.succeed(EMPTY)));
21506
22185
  /**
@@ -21724,7 +22403,7 @@ var WorkspaceStateSnapshot = class extends Schema.Class("WorkspaceStateSnapshot"
21724
22403
  };
21725
22404
 
21726
22405
  //#endregion
21727
- //#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
22406
+ //#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
21728
22407
  /** Whether `value` is a non-null, non-array object. */
21729
22408
  const isObject = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
21730
22409
  /** Whether every value in a record is a string — a usable dependency map. */
@@ -21783,6 +22462,8 @@ const EMPTY_LOCKFILE_RECORD = {
21783
22462
  catalogs: CatalogSet.empty(),
21784
22463
  importerVersions: {}
21785
22464
  };
22465
+ /** A defect naming the unstubbed test-double method — a test-wiring mistake, not a typed failure. */
22466
+ const unstubbed = (method) => Effect.die(/* @__PURE__ */ new Error(`WorkspaceSnapshots.makeTest: ${method}() was called but not stubbed — pass a \`${method}\` override.`));
21786
22467
  /**
21787
22468
  * Reads workspace state at a git ref with no checkout, and the live worktree.
21788
22469
  *
@@ -21929,145 +22610,307 @@ var WorkspaceSnapshots = class WorkspaceSnapshots extends Context.Service()("@ef
21929
22610
  * `const` and reuse it, or layer memoization does not apply.
21930
22611
  */
21931
22612
  static layer = (options) => Layer.effect(WorkspaceSnapshots, WorkspaceSnapshots.make(options));
22613
+ /**
22614
+ * A test double satisfying the full {@link WorkspaceSnapshotsShape} with no
22615
+ * git, filesystem, discovery, or catalog assembly.
22616
+ *
22617
+ * @remarks
22618
+ * There are **no honest defaults and no derivations** here: `at(ref)` and
22619
+ * `worktree()` are two independent reads of two different sources (a git ref
22620
+ * vs. the live tree), so neither can be honestly derived from the other, and
22621
+ * a fabricated empty {@link WorkspaceStateSnapshot} on either side of a
22622
+ * before/after diff reads as every dependency newly added or removed — the
22623
+ * exact silent-empty failure class this package documents on the live paths.
22624
+ * Both methods therefore **die** with an instructive defect until stubbed; a
22625
+ * test-wiring mistake fails loudly as a defect rather than succeeding with a
22626
+ * lie.
22627
+ *
22628
+ * @example
22629
+ * ```ts
22630
+ * import { CatalogSet, WorkspaceSnapshots, WorkspaceStateSnapshot } from "@effected/workspaces";
22631
+ * import { Effect } from "effect";
22632
+ *
22633
+ * const empty = WorkspaceStateSnapshot.make({
22634
+ * packages: [],
22635
+ * catalogs: CatalogSet.empty(),
22636
+ * importerVersions: {},
22637
+ * });
22638
+ * const double = WorkspaceSnapshots.makeTest({
22639
+ * at: () => Effect.succeed(empty),
22640
+ * worktree: () => Effect.succeed(empty),
22641
+ * });
22642
+ * ```
22643
+ */
22644
+ static makeTest = (overrides = {}) => ({
22645
+ at: () => unstubbed("at"),
22646
+ worktree: () => unstubbed("worktree"),
22647
+ ...overrides
22648
+ });
22649
+ /**
22650
+ * The test layer: {@link WorkspaceSnapshots.makeTest} behind `Layer.succeed`,
22651
+ * so a suite provides only the methods it exercises.
22652
+ *
22653
+ * @remarks
22654
+ * A parameterized layer factory mints a **fresh reference per call**, and
22655
+ * layers memoize by reference — bind the result to a `const` and reuse it
22656
+ * rather than calling `layerTest(...)` at each composition site.
22657
+ *
22658
+ * @example
22659
+ * ```ts
22660
+ * import { CatalogSet, WorkspaceSnapshots, WorkspaceStateSnapshot } from "@effected/workspaces";
22661
+ * import { Effect } from "effect";
22662
+ *
22663
+ * const TestSnapshots = WorkspaceSnapshots.layerTest({
22664
+ * worktree: () =>
22665
+ * Effect.succeed(
22666
+ * WorkspaceStateSnapshot.make({ packages: [], catalogs: CatalogSet.empty(), importerVersions: {} }),
22667
+ * ),
22668
+ * });
22669
+ * // program.pipe(Effect.provide(TestSnapshots))
22670
+ * ```
22671
+ */
22672
+ static layerTest = (overrides = {}) => Layer.succeed(WorkspaceSnapshots, WorkspaceSnapshots.makeTest(overrides));
21932
22673
  };
21933
22674
 
21934
22675
  //#endregion
21935
- //#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
21936
- /**
21937
- * Every service that needs only a filesystem: root, package-manager detection,
21938
- * discovery, lockfile reading, catalogs and publishability.
21939
- *
21940
- * @remarks
21941
- * Requires core `FileSystem` and `Path`, which the consumer provides at the
21942
- * edge (`@effect/platform-node`, `@effect/platform-bun`, or a test's
21943
- * `FileSystem.layerNoop`).
21944
- *
21945
- * **Bind the result to a `const`.** This is a parameterized factory and layers
21946
- * memoize by reference, so calling it twice builds everything twice.
21947
- *
21948
- * @example
21949
- * ```ts
21950
- * import { Workspaces } from "@effected/workspaces";
21951
- * import { Layer } from "effect";
21952
- *
21953
- * const WorkspacesLayer = Workspaces.layer();
21954
- * const AppLayer = Layer.provide(WorkspacesLayer, PlatformLayer);
21955
- * ```
21956
- *
21957
- * @public
21958
- */
22676
+ //#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
21959
22677
  const compose = (options, catalogsFactory) => {
21960
22678
  const roots = WorkspaceRoot.layer;
21961
22679
  const detector = PackageManagerDetector.layer;
21962
22680
  const discovery = WorkspaceDiscovery.layer(options).pipe(Layer.provide(roots));
21963
22681
  const lockfiles = LockfileReader.layer(options).pipe(Layer.provide(roots), Layer.provide(detector), Layer.provide(discovery));
21964
22682
  const catalogs = catalogsFactory(options).pipe(Layer.provide(roots), Layer.provide(lockfiles));
21965
- return Layer.mergeAll(roots, detector, discovery, lockfiles, catalogs, PublishabilityDetector.layer);
22683
+ return Layer.mergeAll(roots, detector, discovery, lockfiles, catalogs);
21966
22684
  };
21967
22685
  const layer = (options) => compose(options, WorkspaceCatalogs.layer);
21968
- /**
21969
- * The git-free composite plus {@link ChangeDetector} and
21970
- * {@link WorkspaceSnapshots}, over `@effected/git`'s `Git` service.
21971
- *
21972
- * @remarks
21973
- * The extra requirement is core's `ChildProcessSpawner` (behind `Git`), which
21974
- * is why it is a separate layer rather than a flag: a consumer that never
21975
- * detects changes or reads at a ref should not have to be able to spawn a
21976
- * subprocess. The consumer provides `ChildProcessSpawner` once at the edge
21977
- * (`@effect/platform-node`'s `NodeServices.layer`); a test provides
21978
- * `Layer.succeed(Git, …)` and needs no repository on disk.
21979
- *
21980
- * @public
21981
- */
21982
22686
  const layerWithGit = (options) => {
21983
22687
  const core = layer(options);
21984
22688
  const git = Git.layer;
21985
22689
  return Layer.mergeAll(core, git, ChangeDetector.layer.pipe(Layer.provide(git), Layer.provide(core)), WorkspaceSnapshots.layer(options).pipe(Layer.provide(git), Layer.provide(core)));
21986
22690
  };
21987
- /**
21988
- * The two `@effected/npm` resolver contracts, implemented for real.
21989
- *
21990
- * @remarks
21991
- * Provide this alongside `@effected/package-json`'s `Package.resolve` and a
21992
- * manifest's `catalog:` and `workspace:` specifiers resolve against the actual
21993
- * workspace instead of the no-op layers' `Option.none()`.
21994
- *
21995
- * @example
21996
- * ```ts
21997
- * import { Package } from "@effected/package-json";
21998
- * import { Workspaces } from "@effected/workspaces";
21999
- * import { Layer } from "effect";
22000
- *
22001
- * const WorkspacesLayer = Workspaces.layer();
22002
- * const Resolvers = Workspaces.resolvers.pipe(Layer.provide(WorkspacesLayer));
22003
- * ```
22004
- *
22005
- * @public
22006
- */
22007
22691
  const resolvers = Layer.mergeAll(WorkspaceCatalogs.catalogResolver, WorkspaceDiscovery.workspaceResolver);
22008
- /**
22009
- * The git-free composite, but with catalog assembly that **replays config
22010
- * dependency `pnpmfile.cjs` hooks** — {@link WorkspaceCatalogs.layerWithConfigDependencies}
22011
- * in place of the default no-op catalogs layer.
22012
- *
22013
- * @remarks
22014
- * Identical requirement set to {@link Workspaces.layer}; the only difference is
22015
- * that config-dependency code is executed in process. Opt in deliberately — the
22016
- * default {@link Workspaces.layer} never executes config-dependency code.
22017
- *
22018
- * **Bind the result to a `const`.**
22019
- *
22020
- * @public
22021
- */
22022
22692
  const layerWithConfigDependencies = (options) => compose(options, WorkspaceCatalogs.layerWithConfigDependencies);
22023
- /**
22024
- * The one-call resolver factory: {@link Workspaces.resolvers} pre-wired over
22025
- * {@link Workspaces.layerWithConfigDependencies}, so the two `@effected/npm`
22026
- * contracts (`CatalogResolver`, `WorkspaceResolver`) need only a platform
22027
- * (`FileSystem` + `Path`) from the consumer.
22028
- *
22029
- * @remarks
22030
- * This is deliberately a **parameterized layer function, and the fresh layer
22031
- * per call is the feature**: layers memoize by reference, so each call mints
22032
- * an unmemoized layer whose root discovery re-runs — including a per-call
22033
- * `process.cwd()` read when `options.cwd` is omitted. A build tool that
22034
- * changes directory between manifests gets a correct re-discovery each time
22035
- * precisely because nothing is shared across calls. When you *want* sharing,
22036
- * bind one call's result to a `const` and provide that; the memoization rule
22037
- * is unchanged, this factory just refuses to hide it.
22038
- *
22039
- * Catalog assembly replays config-dependency `pnpmfile` hooks (the
22040
- * `layerWithConfigDependencies` path) — the semantics a real pnpm install
22041
- * has. Compose {@link Workspaces.resolvers} with {@link Workspaces.layer}
22042
- * yourself if config-dependency code must not run in process.
22043
- *
22044
- * @example
22045
- * ```ts
22046
- * import { Workspaces } from "@effected/workspaces";
22047
- * import { Effect } from "effect";
22048
- *
22049
- * const program = doSomethingWithResolvers.pipe(
22050
- * Effect.provide(Workspaces.resolverLayer()),
22051
- * );
22052
- * ```
22053
- *
22054
- * @public
22055
- */
22056
22693
  const resolverLayer = (options) => resolvers.pipe(Layer.provide(layerWithConfigDependencies(options)));
22694
+ const resolveManifest = Effect.fn("Workspaces.resolveManifest")(function* (manifest, options) {
22695
+ return yield* manifest.resolve().pipe(Effect.provide(resolverLayer(options)));
22696
+ });
22697
+ const localExecLayer = (options) => Layer.effect(LocalExec, Effect.gen(function* () {
22698
+ const roots = yield* WorkspaceRoot;
22699
+ const detector = yield* PackageManagerDetector;
22700
+ return { context: Effect.gen(function* () {
22701
+ const cwd = options?.cwd ?? globalThis.process?.cwd?.() ?? "/";
22702
+ const root = yield* roots.find(cwd).pipe(Effect.asSome, Effect.orElseSucceed(Option.none));
22703
+ if (Option.isNone(root)) return Option.none();
22704
+ const detected = yield* detector.detect(root.value).pipe(Effect.asSome, Effect.catchTag("PackageManagerDetectionError", () => Effect.succeed(Option.none())), Effect.mapError((cause) => new LocalExecError({
22705
+ directory: root.value,
22706
+ cause
22707
+ })));
22708
+ if (Option.isNone(detected)) return Option.none();
22709
+ const { prefix, dlxPrefix } = LocalExec.prefixes(detected.value.name);
22710
+ return Option.some(ExecContext.make({
22711
+ label: detected.value.name,
22712
+ prefix,
22713
+ dlxPrefix,
22714
+ directory: root.value
22715
+ }));
22716
+ }) };
22717
+ }));
22057
22718
  /**
22058
22719
  * The composite layers.
22059
22720
  *
22060
22721
  * @public
22061
22722
  */
22062
- const Workspaces = {
22063
- layer,
22064
- layerWithConfigDependencies,
22065
- layerWithGit,
22066
- resolveManifest: Effect.fn("Workspaces.resolveManifest")(function* (manifest, options) {
22067
- return yield* manifest.resolve().pipe(Effect.provide(resolverLayer(options)));
22068
- }),
22069
- resolverLayer,
22070
- resolvers
22723
+ var Workspaces = class {
22724
+ constructor() {}
22725
+ /**
22726
+ * Every service that needs only a filesystem: root, package-manager
22727
+ * detection, discovery, lockfile reading, catalogs and publishability.
22728
+ *
22729
+ * @remarks
22730
+ * Requires core `FileSystem` and `Path`, which the consumer provides at the
22731
+ * edge (`@effect/platform-node`, `@effect/platform-bun`, or a test's
22732
+ * `FileSystem.layerNoop`).
22733
+ *
22734
+ * **Bind the result to a `const`.** This is a parameterized factory and
22735
+ * layers memoize by reference, so calling it twice builds everything twice.
22736
+ *
22737
+ * @example
22738
+ * ```ts
22739
+ * import { Workspaces } from "@effected/workspaces";
22740
+ * import { Layer } from "effect";
22741
+ *
22742
+ * const WorkspacesLayer = Workspaces.layer();
22743
+ * const AppLayer = Layer.provide(WorkspacesLayer, PlatformLayer);
22744
+ * ```
22745
+ */
22746
+ static layer = layer;
22747
+ /**
22748
+ * The git-free composite, but with catalog assembly that **replays config
22749
+ * dependency `pnpmfile.cjs` hooks** —
22750
+ * {@link WorkspaceCatalogs.layerWithConfigDependencies} in place of the
22751
+ * default no-op catalogs layer.
22752
+ *
22753
+ * @remarks
22754
+ * Identical requirement set to {@link Workspaces.layer}; the only
22755
+ * difference is that config-dependency code is executed in process. Opt in
22756
+ * deliberately — the default {@link Workspaces.layer} never executes
22757
+ * config-dependency code.
22758
+ *
22759
+ * **Bind the result to a `const`.**
22760
+ */
22761
+ static layerWithConfigDependencies = layerWithConfigDependencies;
22762
+ /**
22763
+ * The git-free composite plus {@link ChangeDetector} and
22764
+ * {@link WorkspaceSnapshots}, over `@effected/git`'s `Git` service.
22765
+ *
22766
+ * @remarks
22767
+ * The extra requirement is core's `ChildProcessSpawner` (behind `Git`),
22768
+ * which is why it is a separate layer rather than a flag: a consumer that
22769
+ * never detects changes or reads at a ref should not have to be able to
22770
+ * spawn a subprocess. The consumer provides `ChildProcessSpawner` once at
22771
+ * the edge (`@effect/platform-node`'s `NodeServices.layer`); a test
22772
+ * provides `Layer.succeed(Git, …)` and needs no repository on disk.
22773
+ */
22774
+ static layerWithGit = layerWithGit;
22775
+ /**
22776
+ * This package's implementation of `@effected/commands`' `LocalExec`
22777
+ * contract: how to run a project-local binary here.
22778
+ *
22779
+ * @remarks
22780
+ * **An inverted contract, the `@effected/npm` `CatalogResolver`
22781
+ * precedent.** Tool discovery needs package-manager detection and
22782
+ * workspace-root resolution, both of which live here — but a direct edge
22783
+ * from `@effected/commands` to this package would make that boundary-tier
22784
+ * package integrated, and through the planned `npm` → `commands` edge
22785
+ * would drag `npm`, `lockfiles` (pure!) and `package-json` up a tier with
22786
+ * it. So `commands` declares the narrow contract and we ship the layer.
22787
+ *
22788
+ * **The argv knowledge is not duplicated.** `LocalExec.prefixes(name)` is
22789
+ * the one home of the four managers' `exec`/`dlx` prefixes; this layer
22790
+ * detects *which* manager owns the directory and asks `commands` what that
22791
+ * manager's argv looks like. Neither package reimplements the other's
22792
+ * half.
22793
+ *
22794
+ * **`None` is success.** Outside any workspace — and inside one whose
22795
+ * manager cannot be identified — the answer is `Option.none()`: "there is
22796
+ * no project-local way to run tools here" is an ordinary fact, not an
22797
+ * exceptional one, and a consumer running in a bare directory should not
22798
+ * have to catch an error to learn it. The contract's typed
22799
+ * `LocalExecError` is reserved for **mechanism** failure — a manifest that
22800
+ * exists but cannot be read or parsed, which means something is broken
22801
+ * rather than absent. That is npm's resolver convention, adopted
22802
+ * verbatim.
22803
+ *
22804
+ * `directory` is the resolved **workspace root**, not the caller's cwd: a
22805
+ * project-local launcher has to run where the workspace is.
22806
+ *
22807
+ * A consumer with no monorepo never needs this layer, and therefore never
22808
+ * installs this package — `LocalExec.layerNone` and `LocalExec.layerFor`
22809
+ * are one-liners in `@effected/commands`.
22810
+ *
22811
+ * **Bind the result to a `const`** — a parameterized layer factory mints a
22812
+ * fresh reference per call and layers memoize by reference.
22813
+ *
22814
+ * @example
22815
+ * ```ts
22816
+ * import { ToolDiscovery } from "@effected/commands";
22817
+ * import { Workspaces } from "@effected/workspaces";
22818
+ * import { Layer } from "effect";
22819
+ *
22820
+ * const AppLayer = ToolDiscovery.layer.pipe(
22821
+ * Layer.provide(Workspaces.localExecLayer()),
22822
+ * Layer.provide(Workspaces.layer()),
22823
+ * Layer.provide(NodeServices.layer),
22824
+ * );
22825
+ * ```
22826
+ */
22827
+ static localExecLayer = localExecLayer;
22828
+ /**
22829
+ * Resolve every `catalog:` and `workspace:` specifier in one `Manifest`
22830
+ * against the real workspace, in one call — the 90% path. Decode stays at
22831
+ * the consumer's edge: build the `Manifest` with `Manifest.decode` (from
22832
+ * `@effected/npm`), hand it here, and get a new `Manifest` back with
22833
+ * concrete ranges; `toRecord()` returns to the wire shape.
22834
+ *
22835
+ * @remarks
22836
+ * Composes `manifest.resolve()` with a fresh {@link Workspaces.resolverLayer}
22837
+ * per call, so the workspace root is re-discovered from `options.cwd` (or
22838
+ * the current `process.cwd()`) on every invocation. Consumers processing
22839
+ * many manifests should check `manifest.needsResolution` first and skip
22840
+ * the call entirely when no dependency field carries a
22841
+ * `catalog:`/`workspace:` specifier — that predicate is pure and avoids
22842
+ * catalog assembly altogether.
22843
+ *
22844
+ * A specifier the workspace cannot answer fails typed as
22845
+ * `UnresolvedDependencyError`; assembly and mechanism failures surface as
22846
+ * `CatalogAssemblyError` / `DependencyResolutionError`.
22847
+ *
22848
+ * @example
22849
+ * ```ts
22850
+ * import { Manifest } from "@effected/npm";
22851
+ * import { Workspaces } from "@effected/workspaces";
22852
+ * import { Effect } from "effect";
22853
+ *
22854
+ * const program = Effect.gen(function* () {
22855
+ * const manifest = yield* Manifest.decode({ dependencies: { effect: "catalog:" } });
22856
+ * const resolved = manifest.needsResolution ? yield* Workspaces.resolveManifest(manifest) : manifest;
22857
+ * return resolved.toRecord();
22858
+ * });
22859
+ * ```
22860
+ */
22861
+ static resolveManifest = resolveManifest;
22862
+ /**
22863
+ * The one-call resolver factory: {@link Workspaces.resolvers} pre-wired
22864
+ * over {@link Workspaces.layerWithConfigDependencies}, so the two
22865
+ * `@effected/npm` contracts (`CatalogResolver`, `WorkspaceResolver`) need
22866
+ * only a platform (`FileSystem` + `Path`) from the consumer.
22867
+ *
22868
+ * @remarks
22869
+ * This is deliberately a **parameterized layer function, and the fresh
22870
+ * layer per call is the feature**: layers memoize by reference, so each
22871
+ * call mints an unmemoized layer whose root discovery re-runs — including
22872
+ * a per-call `process.cwd()` read when `options.cwd` is omitted. A build
22873
+ * tool that changes directory between manifests gets a correct
22874
+ * re-discovery each time precisely because nothing is shared across
22875
+ * calls. When you *want* sharing, bind one call's result to a `const` and
22876
+ * provide that; the memoization rule is unchanged, this factory just
22877
+ * refuses to hide it.
22878
+ *
22879
+ * Catalog assembly replays config-dependency `pnpmfile` hooks (the
22880
+ * `layerWithConfigDependencies` path) — the semantics a real pnpm install
22881
+ * has. Compose {@link Workspaces.resolvers} with {@link Workspaces.layer}
22882
+ * yourself if config-dependency code must not run in process.
22883
+ *
22884
+ * @example
22885
+ * ```ts
22886
+ * import { Workspaces } from "@effected/workspaces";
22887
+ * import { Effect } from "effect";
22888
+ *
22889
+ * const program = doSomethingWithResolvers.pipe(
22890
+ * Effect.provide(Workspaces.resolverLayer()),
22891
+ * );
22892
+ * ```
22893
+ */
22894
+ static resolverLayer = resolverLayer;
22895
+ /**
22896
+ * The two `@effected/npm` resolver contracts, implemented for real.
22897
+ *
22898
+ * @remarks
22899
+ * Provide this alongside `@effected/package-json`'s `Package.resolve` and
22900
+ * a manifest's `catalog:` and `workspace:` specifiers resolve against the
22901
+ * actual workspace instead of the no-op layers' `Option.none()`.
22902
+ *
22903
+ * @example
22904
+ * ```ts
22905
+ * import { Package } from "@effected/package-json";
22906
+ * import { Workspaces } from "@effected/workspaces";
22907
+ * import { Layer } from "effect";
22908
+ *
22909
+ * const WorkspacesLayer = Workspaces.layer();
22910
+ * const Resolvers = Workspaces.resolvers.pipe(Layer.provide(WorkspacesLayer));
22911
+ * ```
22912
+ */
22913
+ static resolvers = resolvers;
22071
22914
  };
22072
22915
 
22073
22916
  //#endregion
@@ -22326,7 +23169,7 @@ const SilkPublishabilityDetectorLive = Layer.effect(PublishabilityDetector, Effe
22326
23169
  const PublishabilityDetectorAdaptiveLive = Layer.effect(PublishabilityDetector, Effect.gen(function* () {
22327
23170
  const fs = yield* FileSystem.FileSystem;
22328
23171
  const config = yield* ChangesetConfig;
22329
- const vanilla = yield* Effect.provide(PublishabilityDetector, PublishabilityDetector.layer);
23172
+ const vanilla = PublishabilityDetector.npm;
22330
23173
  return { detect: (pkg) => Effect.gen(function* () {
22331
23174
  const root = pkg.workspaceRoot;
22332
23175
  if (yield* config.isIgnored(pkg.name, root)) return [];
@@ -23052,7 +23895,6 @@ const MarkdownParseErrorBase = Data.TaggedError("MarkdownParseError");
23052
23895
  * );
23053
23896
  * ```
23054
23897
  *
23055
- * @see {@link MarkdownService} for the Effect service that may produce this error
23056
23898
  *
23057
23899
  * @public
23058
23900
  */
@@ -24254,7 +25096,7 @@ var GitHubService = class extends Context.Service()("GitHubService") {};
24254
25096
  * @remarks
24255
25097
  * This layer is used by the `\@savvy-web/changesets/changelog` entry point
24256
25098
  * to resolve commit hashes into PR numbers and author attribution. It is
24257
- * composed with {@link MarkdownLive} in the changelog formatter's
25099
+ * used by the changelog formatter's
24258
25100
  * `MainLayer`.
24259
25101
  *
24260
25102
  * @example
@@ -24323,6 +25165,279 @@ function makeGitHubTest(responses) {
24323
25165
  } });
24324
25166
  }
24325
25167
 
25168
+ //#endregion
25169
+ //#region ../silk-effects/dist/dev/pkg/changesets/schemas/primitives.js
25170
+ /**
25171
+ * Primitive reusable schemas for common constrained types.
25172
+ *
25173
+ * @remarks
25174
+ * These schemas serve as building blocks for more complex schemas throughout
25175
+ * the \@savvy-web/changesets package. They encode common constraints
25176
+ * (non-empty strings, positive integers) as Effect Schemas so that validation
25177
+ * is enforced at system boundaries.
25178
+ *
25179
+ * @see {@link https://effect.website/docs/schema/introduction | Effect Schema documentation}
25180
+ *
25181
+ */
25182
+ /**
25183
+ * A non-empty string schema.
25184
+ *
25185
+ * @remarks
25186
+ * Validates that a string has at least one character. Used as the base
25187
+ * constraint for package names, dependency identifiers, and other fields
25188
+ * that must not be blank.
25189
+ *
25190
+ * @example
25191
+ * ```typescript
25192
+ * import { Schema } from "effect";
25193
+ * import { NonEmptyString } from "@savvy-web/changesets";
25194
+ *
25195
+ * // Succeeds — non-empty string
25196
+ * const name = Schema.decodeUnknownSync(NonEmptyString)("react");
25197
+ *
25198
+ * // Throws ParseError — empty string
25199
+ * Schema.decodeUnknownSync(NonEmptyString)("");
25200
+ * ```
25201
+ *
25202
+ * @see {@link ChangesetSummarySchema} for a length-bounded variant used for changeset summaries
25203
+ *
25204
+ * @public
25205
+ */
25206
+ const NonEmptyString = Schema.String.check(Schema.isMinLength(1));
25207
+ /**
25208
+ * A positive integer schema.
25209
+ *
25210
+ * @remarks
25211
+ * Validates that a number is both an integer and strictly greater than zero.
25212
+ * Used as the base constraint for GitHub issue numbers and similar
25213
+ * identifiers that must be positive whole numbers.
25214
+ *
25215
+ * @example
25216
+ * ```typescript
25217
+ * import { Schema } from "effect";
25218
+ * import { PositiveInteger } from "@savvy-web/changesets";
25219
+ *
25220
+ * // Succeeds — positive integer
25221
+ * const issueNum = Schema.decodeUnknownSync(PositiveInteger)(42);
25222
+ *
25223
+ * // Throws ParseError — zero is not positive
25224
+ * Schema.decodeUnknownSync(PositiveInteger)(0);
25225
+ *
25226
+ * // Throws ParseError — floats are not integers
25227
+ * Schema.decodeUnknownSync(PositiveInteger)(3.14);
25228
+ * ```
25229
+ *
25230
+ * @see {@link IssueNumberSchema} which builds on this for GitHub issue/PR numbers
25231
+ *
25232
+ * @public
25233
+ */
25234
+ const PositiveInteger = Schema.Number.check(Schema.isInt(), Schema.isGreaterThan(0));
25235
+
25236
+ //#endregion
25237
+ //#region ../silk-effects/dist/dev/pkg/changesets/schemas/dependency-table.js
25238
+ /**
25239
+ * Effect schemas for structured dependency table entries.
25240
+ *
25241
+ * @remarks
25242
+ * These schemas define the canonical representation for dependency
25243
+ * changes tracked as markdown tables in changeset files and CHANGELOGs.
25244
+ * The table format provides a richer view than {@link DependencyUpdateSchema}
25245
+ * by supporting singular dependency type names, workspace/config types,
25246
+ * and explicit add/update/remove actions.
25247
+ *
25248
+ * A dependency table row looks like this in a CHANGELOG:
25249
+ *
25250
+ * | Dependency | Type | Action | From | To |
25251
+ * |---|---|---|---|---|
25252
+ * | effect | dependency | updated | 3.18.0 | 3.19.1 |
25253
+ *
25254
+ * @see {@link DependencyUpdateSchema} for the simpler Changesets API format
25255
+ * @see {@link https://effect.website/docs/schema/introduction | Effect Schema documentation}
25256
+ *
25257
+ */
25258
+ /**
25259
+ * Valid dependency table actions.
25260
+ *
25261
+ * @remarks
25262
+ * Represents the three possible operations on a dependency: `"added"` for
25263
+ * new dependencies, `"updated"` for version changes, and `"removed"` for
25264
+ * deletions. Used in the "Action" column of dependency tables.
25265
+ *
25266
+ * @example
25267
+ * ```typescript
25268
+ * import { Schema } from "effect";
25269
+ * import { DependencyActionSchema } from "@savvy-web/changesets";
25270
+ * import type { DependencyAction } from "@savvy-web/changesets";
25271
+ *
25272
+ * const action: DependencyAction = Schema.decodeUnknownSync(DependencyActionSchema)("updated");
25273
+ * ```
25274
+ *
25275
+ * @public
25276
+ */
25277
+ const DependencyActionSchema = Schema.Literals([
25278
+ "added",
25279
+ "updated",
25280
+ "removed"
25281
+ ]);
25282
+ /**
25283
+ * Extended dependency types for table format.
25284
+ *
25285
+ * @remarks
25286
+ * Unlike {@link DependencyTypeSchema} (which uses plural npm field names like
25287
+ * `"dependencies"`), this schema uses singular forms (`"dependency"`) and adds
25288
+ * two additional types: `"workspace"` for monorepo workspace references and
25289
+ * `"config"` for configuration toolchain updates (e.g., ESLint, TypeScript).
25290
+ *
25291
+ * @example
25292
+ * ```typescript
25293
+ * import { Schema } from "effect";
25294
+ * import { DependencyTableTypeSchema } from "@savvy-web/changesets";
25295
+ * import type { DependencyTableType } from "@savvy-web/changesets";
25296
+ *
25297
+ * const tableType: DependencyTableType = Schema.decodeUnknownSync(
25298
+ * DependencyTableTypeSchema
25299
+ * )("workspace");
25300
+ * ```
25301
+ *
25302
+ * @see {@link DependencyTypeSchema} for the plural npm-field variant
25303
+ *
25304
+ * @public
25305
+ */
25306
+ const DependencyTableTypeSchema = Schema.Literals([
25307
+ "dependency",
25308
+ "devDependency",
25309
+ "peerDependency",
25310
+ "optionalDependency",
25311
+ "workspace",
25312
+ "config"
25313
+ ]);
25314
+ /**
25315
+ * The canonical accepted-value pattern for a dependency-table From/To cell:
25316
+ * the em-dash sentinel (U+2014), a bare/`~`/`^` semver, or — as a last-resort
25317
+ * fallback when a `catalog:`/`workspace:` specifier could not be resolved to a
25318
+ * concrete version — a pnpm protocol string. Non-overlapping alternatives keep
25319
+ * this free of polynomial backtracking (CodeQL).
25320
+ *
25321
+ * @public
25322
+ */
25323
+ const VERSION_RE = /^(\u2014|[~^]?\d+\.\d+\.\d+(?:[-+.][\w.+-]+)?|(?:catalog|workspace|npm|jsr|file|link|portal):[^\s|]+)$/;
25324
+ /**
25325
+ * Version string or em dash (U+2014) sentinel for added/removed entries.
25326
+ *
25327
+ * @remarks
25328
+ * Accepts either a semver-like version string (with optional `~` or `^`
25329
+ * prefix and pre-release/build suffixes) or the em dash character `\u2014`
25330
+ * which serves as a sentinel: the "From" column uses `\u2014` for newly
25331
+ * added dependencies, and the "To" column uses it for removed ones.
25332
+ *
25333
+ * @example
25334
+ * ```typescript
25335
+ * import { Schema } from "effect";
25336
+ * import { VersionOrEmptySchema } from "@savvy-web/changesets";
25337
+ *
25338
+ * // Succeeds — semver version
25339
+ * Schema.decodeUnknownSync(VersionOrEmptySchema)("^3.19.1");
25340
+ *
25341
+ * // Succeeds — em dash sentinel for "no version"
25342
+ * Schema.decodeUnknownSync(VersionOrEmptySchema)("\u2014");
25343
+ *
25344
+ * // Throws ParseError — arbitrary text
25345
+ * Schema.decodeUnknownSync(VersionOrEmptySchema)("latest");
25346
+ * ```
25347
+ *
25348
+ * @public
25349
+ */
25350
+ const VersionOrEmptySchema = Schema.String.check(Schema.isPattern(VERSION_RE));
25351
+ /**
25352
+ * Schema for a single dependency table row.
25353
+ *
25354
+ * @remarks
25355
+ * Represents one row of a dependency update table in a CHANGELOG.
25356
+ * Each row captures the dependency name, its type, the change action,
25357
+ * and the "from" and "to" version strings. For added dependencies the
25358
+ * `from` field is an em dash; for removed dependencies the `to` field
25359
+ * is an em dash.
25360
+ *
25361
+ * @example
25362
+ * ```typescript
25363
+ * import { Schema } from "effect";
25364
+ * import { DependencyTableRowSchema } from "@savvy-web/changesets";
25365
+ * import type { DependencyTableRow } from "@savvy-web/changesets";
25366
+ *
25367
+ * const row: DependencyTableRow = Schema.decodeUnknownSync(DependencyTableRowSchema)({
25368
+ * dependency: "effect",
25369
+ * type: "dependency",
25370
+ * action: "updated",
25371
+ * from: "3.18.0",
25372
+ * to: "3.19.1",
25373
+ * });
25374
+ *
25375
+ * // Newly added dependency — "from" is em dash
25376
+ * const addedRow: DependencyTableRow = Schema.decodeUnknownSync(DependencyTableRowSchema)({
25377
+ * dependency: "@effect/cli",
25378
+ * type: "dependency",
25379
+ * action: "added",
25380
+ * from: "\u2014",
25381
+ * to: "0.50.0",
25382
+ * });
25383
+ * ```
25384
+ *
25385
+ * @see {@link DependencyTableRow} for the inferred TypeScript type
25386
+ * @see {@link DependencyTableSchema} for a non-empty array of rows
25387
+ *
25388
+ * @public
25389
+ */
25390
+ const DependencyTableRowSchema = Schema.Struct({
25391
+ /** Package or toolchain name. */
25392
+ dependency: NonEmptyString,
25393
+ /** Dependency type. */
25394
+ type: DependencyTableTypeSchema,
25395
+ /** Change action. */
25396
+ action: DependencyActionSchema,
25397
+ /** Previous version (em dash for added). */
25398
+ from: VersionOrEmptySchema,
25399
+ /** New version (em dash for removed). */
25400
+ to: VersionOrEmptySchema
25401
+ });
25402
+ /**
25403
+ * Schema for a dependency table (non-empty array of rows).
25404
+ *
25405
+ * @remarks
25406
+ * Validates that the table contains at least one row. Used to represent
25407
+ * the full dependency update table in a changeset or CHANGELOG entry.
25408
+ *
25409
+ * @example
25410
+ * ```typescript
25411
+ * import { Schema } from "effect";
25412
+ * import { DependencyTableSchema } from "@savvy-web/changesets";
25413
+ *
25414
+ * const table = Schema.decodeUnknownSync(DependencyTableSchema)([
25415
+ * {
25416
+ * dependency: "effect",
25417
+ * type: "dependency",
25418
+ * action: "updated",
25419
+ * from: "3.18.0",
25420
+ * to: "3.19.1",
25421
+ * },
25422
+ * {
25423
+ * dependency: "typescript",
25424
+ * type: "config",
25425
+ * action: "updated",
25426
+ * from: "5.6.0",
25427
+ * to: "5.7.2",
25428
+ * },
25429
+ * ]);
25430
+ *
25431
+ * // Throws ParseError — empty array
25432
+ * Schema.decodeUnknownSync(DependencyTableSchema)([]);
25433
+ * ```
25434
+ *
25435
+ * @see {@link DependencyTableRowSchema} for the individual row schema
25436
+ *
25437
+ * @public
25438
+ */
25439
+ const DependencyTableSchema = Schema.Array(DependencyTableRowSchema).check(Schema.isMinLength(1));
25440
+
24326
25441
  //#endregion
24327
25442
  //#region ../../node_modules/.pnpm/ccount@2.0.1/node_modules/ccount/index.js
24328
25443
  /**
@@ -43965,368 +45080,6 @@ function stringifyMarkdown(tree) {
43965
45080
  return createRemarkProcessor().stringify(tree);
43966
45081
  }
43967
45082
 
43968
- //#endregion
43969
- //#region ../silk-effects/dist/dev/pkg/changesets/services/markdown.js
43970
- /**
43971
- * Markdown service for parsing and stringifying mdast trees.
43972
- *
43973
- * Defines the {@link MarkdownService} Effect service tag and the
43974
- * {@link MarkdownLive | production layer} backed by the remark/unified
43975
- * pipeline. This service provides a pure, side-effect-free interface to
43976
- * markdown parsing and stringification used throughout the changelog
43977
- * formatter and remark transform pipeline.
43978
- *
43979
- * @remarks
43980
- * The service wraps the `remark-pipeline` utility functions (`parseMarkdown`
43981
- * and `stringifyMarkdown`) behind an Effect interface. The `parse` operation
43982
- * returns an mdast `Root` node; the `stringify` operation serializes an
43983
- * mdast `Root` back to a markdown string. Both operations are synchronous
43984
- * under the hood but are lifted into `Effect.sync` for composability.
43985
- *
43986
- * @see {@link MarkdownService} for the Effect service tag
43987
- * @see {@link MarkdownServiceShape} for the service interface
43988
- * @see {@link MarkdownLive} for the production layer
43989
- */
43990
- /**
43991
- * Effect service tag for markdown parsing and stringification.
43992
- *
43993
- * Provides dependency-injected access to markdown parse/stringify operations.
43994
- * Use `yield* MarkdownService` inside an `Effect.gen` block to obtain the
43995
- * service instance.
43996
- *
43997
- * @remarks
43998
- * This tag follows the standard Effect `Context.Service` pattern. The
43999
- * {@link MarkdownLive} layer provides the default implementation backed by
44000
- * the remark/unified pipeline. For testing, you can supply a custom layer
44001
- * via `Layer.succeed(MarkdownService, { parse: ..., stringify: ... })`.
44002
- *
44003
- * @example
44004
- * ```typescript
44005
- * import { Effect } from "effect";
44006
- * import { MarkdownService, MarkdownLive } from "\@savvy-web/changesets";
44007
- *
44008
- * const program = Effect.gen(function* () {
44009
- * const md = yield* MarkdownService;
44010
- * const tree = yield* md.parse("# Hello\n\nWorld");
44011
- * const output = yield* md.stringify(tree);
44012
- * console.log(output); // "# Hello\n\nWorld\n"
44013
- * });
44014
- *
44015
- * Effect.runPromise(program.pipe(Effect.provide(MarkdownLive)));
44016
- * ```
44017
- *
44018
- * @see {@link MarkdownServiceShape} for the service interface
44019
- * @see {@link MarkdownLive} for the production layer
44020
- *
44021
- * @public
44022
- */
44023
- var MarkdownService = class extends Context.Service()("MarkdownService") {};
44024
- /**
44025
- * Production layer for {@link MarkdownService}.
44026
- *
44027
- * Wraps the remark-pipeline utility functions (`parseMarkdown` and
44028
- * `stringifyMarkdown`) in `Effect.sync` for use in Effect programs.
44029
- * Both operations are synchronous and infallible.
44030
- *
44031
- * @remarks
44032
- * This layer is composed with {@link GitHubLive} in the
44033
- * `\@savvy-web/changesets/changelog` entry point to form the `MainLayer`
44034
- * that powers the Changesets API integration.
44035
- *
44036
- * @example
44037
- * ```typescript
44038
- * import { Effect, Layer } from "effect";
44039
- * import { MarkdownService, MarkdownLive } from "\@savvy-web/changesets";
44040
- *
44041
- * const program = Effect.gen(function* () {
44042
- * const md = yield* MarkdownService;
44043
- * const tree = yield* md.parse("**bold** text");
44044
- * return yield* md.stringify(tree);
44045
- * });
44046
- *
44047
- * Effect.runPromise(program.pipe(Effect.provide(MarkdownLive)));
44048
- * ```
44049
- *
44050
- * @public
44051
- */
44052
- const MarkdownLive = Layer.succeed(MarkdownService, {
44053
- parse: (content) => Effect.sync(() => parseMarkdown(content)),
44054
- stringify: (tree) => Effect.sync(() => stringifyMarkdown(tree))
44055
- });
44056
-
44057
- //#endregion
44058
- //#region ../silk-effects/dist/dev/pkg/changesets/schemas/primitives.js
44059
- /**
44060
- * Primitive reusable schemas for common constrained types.
44061
- *
44062
- * @remarks
44063
- * These schemas serve as building blocks for more complex schemas throughout
44064
- * the \@savvy-web/changesets package. They encode common constraints
44065
- * (non-empty strings, positive integers) as Effect Schemas so that validation
44066
- * is enforced at system boundaries.
44067
- *
44068
- * @see {@link https://effect.website/docs/schema/introduction | Effect Schema documentation}
44069
- *
44070
- */
44071
- /**
44072
- * A non-empty string schema.
44073
- *
44074
- * @remarks
44075
- * Validates that a string has at least one character. Used as the base
44076
- * constraint for package names, dependency identifiers, and other fields
44077
- * that must not be blank.
44078
- *
44079
- * @example
44080
- * ```typescript
44081
- * import { Schema } from "effect";
44082
- * import { NonEmptyString } from "@savvy-web/changesets";
44083
- *
44084
- * // Succeeds — non-empty string
44085
- * const name = Schema.decodeUnknownSync(NonEmptyString)("react");
44086
- *
44087
- * // Throws ParseError — empty string
44088
- * Schema.decodeUnknownSync(NonEmptyString)("");
44089
- * ```
44090
- *
44091
- * @see {@link ChangesetSummarySchema} for a length-bounded variant used for changeset summaries
44092
- *
44093
- * @public
44094
- */
44095
- const NonEmptyString = Schema.String.check(Schema.isMinLength(1));
44096
- /**
44097
- * A positive integer schema.
44098
- *
44099
- * @remarks
44100
- * Validates that a number is both an integer and strictly greater than zero.
44101
- * Used as the base constraint for GitHub issue numbers and similar
44102
- * identifiers that must be positive whole numbers.
44103
- *
44104
- * @example
44105
- * ```typescript
44106
- * import { Schema } from "effect";
44107
- * import { PositiveInteger } from "@savvy-web/changesets";
44108
- *
44109
- * // Succeeds — positive integer
44110
- * const issueNum = Schema.decodeUnknownSync(PositiveInteger)(42);
44111
- *
44112
- * // Throws ParseError — zero is not positive
44113
- * Schema.decodeUnknownSync(PositiveInteger)(0);
44114
- *
44115
- * // Throws ParseError — floats are not integers
44116
- * Schema.decodeUnknownSync(PositiveInteger)(3.14);
44117
- * ```
44118
- *
44119
- * @see {@link IssueNumberSchema} which builds on this for GitHub issue/PR numbers
44120
- *
44121
- * @public
44122
- */
44123
- const PositiveInteger = Schema.Number.check(Schema.isInt(), Schema.isGreaterThan(0));
44124
-
44125
- //#endregion
44126
- //#region ../silk-effects/dist/dev/pkg/changesets/schemas/dependency-table.js
44127
- /**
44128
- * Effect schemas for structured dependency table entries.
44129
- *
44130
- * @remarks
44131
- * These schemas define the canonical representation for dependency
44132
- * changes tracked as markdown tables in changeset files and CHANGELOGs.
44133
- * The table format provides a richer view than {@link DependencyUpdateSchema}
44134
- * by supporting singular dependency type names, workspace/config types,
44135
- * and explicit add/update/remove actions.
44136
- *
44137
- * A dependency table row looks like this in a CHANGELOG:
44138
- *
44139
- * | Dependency | Type | Action | From | To |
44140
- * |---|---|---|---|---|
44141
- * | effect | dependency | updated | 3.18.0 | 3.19.1 |
44142
- *
44143
- * @see {@link DependencyUpdateSchema} for the simpler Changesets API format
44144
- * @see {@link https://effect.website/docs/schema/introduction | Effect Schema documentation}
44145
- *
44146
- */
44147
- /**
44148
- * Valid dependency table actions.
44149
- *
44150
- * @remarks
44151
- * Represents the three possible operations on a dependency: `"added"` for
44152
- * new dependencies, `"updated"` for version changes, and `"removed"` for
44153
- * deletions. Used in the "Action" column of dependency tables.
44154
- *
44155
- * @example
44156
- * ```typescript
44157
- * import { Schema } from "effect";
44158
- * import { DependencyActionSchema } from "@savvy-web/changesets";
44159
- * import type { DependencyAction } from "@savvy-web/changesets";
44160
- *
44161
- * const action: DependencyAction = Schema.decodeUnknownSync(DependencyActionSchema)("updated");
44162
- * ```
44163
- *
44164
- * @public
44165
- */
44166
- const DependencyActionSchema = Schema.Literals([
44167
- "added",
44168
- "updated",
44169
- "removed"
44170
- ]);
44171
- /**
44172
- * Extended dependency types for table format.
44173
- *
44174
- * @remarks
44175
- * Unlike {@link DependencyTypeSchema} (which uses plural npm field names like
44176
- * `"dependencies"`), this schema uses singular forms (`"dependency"`) and adds
44177
- * two additional types: `"workspace"` for monorepo workspace references and
44178
- * `"config"` for configuration toolchain updates (e.g., ESLint, TypeScript).
44179
- *
44180
- * @example
44181
- * ```typescript
44182
- * import { Schema } from "effect";
44183
- * import { DependencyTableTypeSchema } from "@savvy-web/changesets";
44184
- * import type { DependencyTableType } from "@savvy-web/changesets";
44185
- *
44186
- * const tableType: DependencyTableType = Schema.decodeUnknownSync(
44187
- * DependencyTableTypeSchema
44188
- * )("workspace");
44189
- * ```
44190
- *
44191
- * @see {@link DependencyTypeSchema} for the plural npm-field variant
44192
- *
44193
- * @public
44194
- */
44195
- const DependencyTableTypeSchema = Schema.Literals([
44196
- "dependency",
44197
- "devDependency",
44198
- "peerDependency",
44199
- "optionalDependency",
44200
- "workspace",
44201
- "config"
44202
- ]);
44203
- /**
44204
- * The canonical accepted-value pattern for a dependency-table From/To cell:
44205
- * the em-dash sentinel (U+2014), a bare/`~`/`^` semver, or — as a last-resort
44206
- * fallback when a `catalog:`/`workspace:` specifier could not be resolved to a
44207
- * concrete version — a pnpm protocol string. Non-overlapping alternatives keep
44208
- * this free of polynomial backtracking (CodeQL).
44209
- *
44210
- * @public
44211
- */
44212
- const VERSION_RE = /^(\u2014|[~^]?\d+\.\d+\.\d+(?:[-+.][\w.+-]+)?|(?:catalog|workspace|npm|jsr|file|link|portal):[^\s|]+)$/;
44213
- /**
44214
- * Version string or em dash (U+2014) sentinel for added/removed entries.
44215
- *
44216
- * @remarks
44217
- * Accepts either a semver-like version string (with optional `~` or `^`
44218
- * prefix and pre-release/build suffixes) or the em dash character `\u2014`
44219
- * which serves as a sentinel: the "From" column uses `\u2014` for newly
44220
- * added dependencies, and the "To" column uses it for removed ones.
44221
- *
44222
- * @example
44223
- * ```typescript
44224
- * import { Schema } from "effect";
44225
- * import { VersionOrEmptySchema } from "@savvy-web/changesets";
44226
- *
44227
- * // Succeeds — semver version
44228
- * Schema.decodeUnknownSync(VersionOrEmptySchema)("^3.19.1");
44229
- *
44230
- * // Succeeds — em dash sentinel for "no version"
44231
- * Schema.decodeUnknownSync(VersionOrEmptySchema)("\u2014");
44232
- *
44233
- * // Throws ParseError — arbitrary text
44234
- * Schema.decodeUnknownSync(VersionOrEmptySchema)("latest");
44235
- * ```
44236
- *
44237
- * @public
44238
- */
44239
- const VersionOrEmptySchema = Schema.String.check(Schema.isPattern(VERSION_RE));
44240
- /**
44241
- * Schema for a single dependency table row.
44242
- *
44243
- * @remarks
44244
- * Represents one row of a dependency update table in a CHANGELOG.
44245
- * Each row captures the dependency name, its type, the change action,
44246
- * and the "from" and "to" version strings. For added dependencies the
44247
- * `from` field is an em dash; for removed dependencies the `to` field
44248
- * is an em dash.
44249
- *
44250
- * @example
44251
- * ```typescript
44252
- * import { Schema } from "effect";
44253
- * import { DependencyTableRowSchema } from "@savvy-web/changesets";
44254
- * import type { DependencyTableRow } from "@savvy-web/changesets";
44255
- *
44256
- * const row: DependencyTableRow = Schema.decodeUnknownSync(DependencyTableRowSchema)({
44257
- * dependency: "effect",
44258
- * type: "dependency",
44259
- * action: "updated",
44260
- * from: "3.18.0",
44261
- * to: "3.19.1",
44262
- * });
44263
- *
44264
- * // Newly added dependency — "from" is em dash
44265
- * const addedRow: DependencyTableRow = Schema.decodeUnknownSync(DependencyTableRowSchema)({
44266
- * dependency: "@effect/cli",
44267
- * type: "dependency",
44268
- * action: "added",
44269
- * from: "\u2014",
44270
- * to: "0.50.0",
44271
- * });
44272
- * ```
44273
- *
44274
- * @see {@link DependencyTableRow} for the inferred TypeScript type
44275
- * @see {@link DependencyTableSchema} for a non-empty array of rows
44276
- *
44277
- * @public
44278
- */
44279
- const DependencyTableRowSchema = Schema.Struct({
44280
- /** Package or toolchain name. */
44281
- dependency: NonEmptyString,
44282
- /** Dependency type. */
44283
- type: DependencyTableTypeSchema,
44284
- /** Change action. */
44285
- action: DependencyActionSchema,
44286
- /** Previous version (em dash for added). */
44287
- from: VersionOrEmptySchema,
44288
- /** New version (em dash for removed). */
44289
- to: VersionOrEmptySchema
44290
- });
44291
- /**
44292
- * Schema for a dependency table (non-empty array of rows).
44293
- *
44294
- * @remarks
44295
- * Validates that the table contains at least one row. Used to represent
44296
- * the full dependency update table in a changeset or CHANGELOG entry.
44297
- *
44298
- * @example
44299
- * ```typescript
44300
- * import { Schema } from "effect";
44301
- * import { DependencyTableSchema } from "@savvy-web/changesets";
44302
- *
44303
- * const table = Schema.decodeUnknownSync(DependencyTableSchema)([
44304
- * {
44305
- * dependency: "effect",
44306
- * type: "dependency",
44307
- * action: "updated",
44308
- * from: "3.18.0",
44309
- * to: "3.19.1",
44310
- * },
44311
- * {
44312
- * dependency: "typescript",
44313
- * type: "config",
44314
- * action: "updated",
44315
- * from: "5.6.0",
44316
- * to: "5.7.2",
44317
- * },
44318
- * ]);
44319
- *
44320
- * // Throws ParseError — empty array
44321
- * Schema.decodeUnknownSync(DependencyTableSchema)([]);
44322
- * ```
44323
- *
44324
- * @see {@link DependencyTableRowSchema} for the individual row schema
44325
- *
44326
- * @public
44327
- */
44328
- const DependencyTableSchema = Schema.Array(DependencyTableRowSchema).check(Schema.isMinLength(1));
44329
-
44330
45083
  //#endregion
44331
45084
  //#region ../silk-effects/dist/dev/pkg/changesets/utils/dependency-table.js
44332
45085
  /**
@@ -45499,8 +46252,7 @@ function getReleaseLine(changeset, versionType, options) {
45499
46252
  * @remarks
45500
46253
  * The module composes two Effect programs — {@link getReleaseLine} and
45501
46254
  * {@link getDependencyReleaseLine} — and runs each through
45502
- * `Effect.runPromise` with a merged layer of {@link GitHubLive} (for commit
45503
- * metadata) and {@link MarkdownLive} (for mdast parsing). Options are
46255
+ * `Effect.runPromise` with {@link GitHubLive} (for commit metadata). Options are
45504
46256
  * validated at the boundary via `validateChangesetOptions` before being
45505
46257
  * passed to the formatters.
45506
46258
  *
@@ -45540,16 +46292,16 @@ function getReleaseLine(changeset, versionType, options) {
45540
46292
  * @see {@link getDependencyReleaseLine} in `./getDependencyReleaseLine.ts` for dependency table formatting
45541
46293
  */
45542
46294
  /**
45543
- * Combined layer providing all services needed by the formatters.
46295
+ * The layer providing every service the formatters need.
45544
46296
  *
45545
- * Merges {@link GitHubLive} and {@link MarkdownLive} into a single layer
45546
- * that satisfies the environment requirements of both `getReleaseLine`
45547
- * (which needs `GitHubService` and `MarkdownService`) and
45548
- * `getDependencyReleaseLine` (which needs `GitHubService`).
46297
+ * {@link GitHubLive} satisfies the requirements of both `getReleaseLine` and
46298
+ * `getDependencyReleaseLine`, which each need only `GitHubService`. Markdown
46299
+ * parsing is not a layer: the formatters call the remark pipeline's
46300
+ * `parseMarkdown` / `stringifyMarkdown` functions directly.
45549
46301
  *
45550
46302
  * @internal
45551
46303
  */
45552
- const MainLayer = Layer.mergeAll(GitHubLive, MarkdownLive);
46304
+ const MainLayer = GitHubLive;
45553
46305
  /**
45554
46306
  * Changesets API `ChangelogFunctions` implementation.
45555
46307
  *
@@ -45591,8 +46343,7 @@ const changelogFunctions = {
45591
46343
  * Delegates to the Changesets-compatible `getReleaseLine` and
45592
46344
  * `getDependencyReleaseLine` functions. Internally, these use the
45593
46345
  * {@link ChangelogService} Effect service layer, which coordinates
45594
- * the {@link GitHubService} (for commit/PR metadata) and
45595
- * {@link MarkdownService} (for AST manipulation) to produce
46346
+ * the {@link GitHubService} (for commit/PR metadata) to produce
45596
46347
  * structured changelog entries.
45597
46348
  *
45598
46349
  * @remarks
@@ -47304,20 +48055,25 @@ function readRawPackageJson(fs, pkgDir) {
47304
48055
  }
47305
48056
  /**
47306
48057
  * Build resolved scopes from the discovered workspace packages, keeping only
47307
- * those that are a release surface (declare publishConfig that yields at least
47308
- * one publish target). Used both when `.changeset/config.json` declares no
47309
- * explicit `packages` record AND to augment an explicit record with the
47310
- * remaining workspace packages it does not list (so the record annotates the
47311
- * listed packages without shrinking the release surface). The changeset
47312
- * `ignore` list is intentionally NOT consulted here an ignored package still
47313
- * declares publishConfig and remains a valid changeset target.
47314
- */
47315
- function buildFallbackScopes(fs, workspaces) {
48058
+ * those that are a release surface: a package that declares publishConfig
48059
+ * yielding at least one publish target, OR when the changeset config sets
48060
+ * `privatePackages.version: true` (`versionPrivate`) any workspace package
48061
+ * at all, since changesets versions private packages too in that mode (#360:
48062
+ * a private single-root repo with `privatePackages.version: true` previously
48063
+ * produced an empty release surface and left every file unmapped). Used both
48064
+ * when `.changeset/config.json` declares no explicit `packages` record AND to
48065
+ * augment an explicit record with the remaining workspace packages it does
48066
+ * not list (so the record annotates the listed packages without shrinking the
48067
+ * release surface). The changeset `ignore` list is intentionally NOT
48068
+ * consulted here — an ignored package still declares publishConfig and
48069
+ * remains a valid changeset target.
48070
+ */
48071
+ function buildFallbackScopes(fs, workspaces, versionPrivate) {
47316
48072
  return Effect.forEach(workspaces, (ws) => Effect.gen(function* () {
47317
48073
  const raw = yield* readRawPackageJson(fs, ws.path);
47318
48074
  if (raw === null) return [];
47319
48075
  const binding = yield* readTargetsBinding(fs, ws.path);
47320
- if (SilkPublishability.detect(ws.name, raw, binding).length === 0) return [];
48076
+ if (SilkPublishability.detect(ws.name, raw, binding).length === 0 && !versionPrivate) return [];
47321
48077
  return [{
47322
48078
  name: ws.name,
47323
48079
  workspaceDir: ws.path,
@@ -47423,6 +48179,8 @@ function makeShape$3(reader, discovery, fs) {
47423
48179
  version: w.version
47424
48180
  }));
47425
48181
  const hasExplicitPackages = Object.keys(decodedOptions.packages ?? {}).length > 0;
48182
+ const privatePackages = config.privatePackages;
48183
+ const versionPrivate = privatePackages !== void 0 && privatePackages !== false && privatePackages.version === true;
47426
48184
  let scopes;
47427
48185
  if (hasExplicitPackages) {
47428
48186
  const explicitScopes = yield* buildResolvedScopes({
@@ -47438,9 +48196,9 @@ function makeShape$3(reader, discovery, fs) {
47438
48196
  throw e;
47439
48197
  }
47440
48198
  const explicitNames = new Set(explicitScopes.map((s) => s.name));
47441
- const discoveredScopes = yield* buildFallbackScopes(fs, workspaces.filter((w) => !explicitNames.has(w.name)));
48199
+ const discoveredScopes = yield* buildFallbackScopes(fs, workspaces.filter((w) => !explicitNames.has(w.name)), versionPrivate);
47442
48200
  scopes = [...explicitScopes, ...discoveredScopes];
47443
- } else scopes = yield* buildFallbackScopes(fs, workspaces);
48201
+ } else scopes = yield* buildFallbackScopes(fs, workspaces, versionPrivate);
47444
48202
  const inspected = {
47445
48203
  configPath,
47446
48204
  projectDir,
@@ -47474,12 +48232,19 @@ function makeShape$3(reader, discovery, fs) {
47474
48232
  function classifyOne(inspected, path) {
47475
48233
  const abs = resolve(inspected.projectDir, path);
47476
48234
  let bestWorkspace = null;
47477
- for (const s of inspected.packages) if (isInside(s.workspaceDir, abs)) {
47478
- const depth = s.workspaceDir.length;
47479
- if (!bestWorkspace || depth > bestWorkspace.depth) bestWorkspace = {
47480
- pkg: s.name,
47481
- depth
47482
- };
48235
+ let rootScope = null;
48236
+ for (const s of inspected.packages) {
48237
+ if (s.workspaceDir === inspected.projectDir) {
48238
+ rootScope = s.name;
48239
+ continue;
48240
+ }
48241
+ if (isInside(s.workspaceDir, abs)) {
48242
+ const depth = s.workspaceDir.length;
48243
+ if (!bestWorkspace || depth > bestWorkspace.depth) bestWorkspace = {
48244
+ pkg: s.name,
48245
+ depth
48246
+ };
48247
+ }
47483
48248
  }
47484
48249
  if (bestWorkspace) return {
47485
48250
  path,
@@ -47506,6 +48271,11 @@ function classifyOne(inspected, path) {
47506
48271
  glob: vf.glob
47507
48272
  }
47508
48273
  };
48274
+ if (rootScope && isInside(inspected.projectDir, abs)) return {
48275
+ path,
48276
+ package: rootScope,
48277
+ reason: "workspace"
48278
+ };
47509
48279
  return {
47510
48280
  path,
47511
48281
  package: null,
@@ -47719,7 +48489,7 @@ function makeBranchAnalyzerTest(fixed) {
47719
48489
  * ```typescript
47720
48490
  * import { Effect } from "effect";
47721
48491
  * import type { ChangesetOptions } from "\@savvy-web/changesets";
47722
- * import { ChangelogService, GitHubLive, MarkdownLive } from "\@savvy-web/changesets";
48492
+ * import { ChangelogService, GitHubLive } from "\@savvy-web/changesets";
47723
48493
  *
47724
48494
  * const program = Effect.gen(function* () {
47725
48495
  * const changelog = yield* ChangelogService;
@@ -66689,9 +67459,7 @@ var changesets_exports = /* @__PURE__ */ __exportAll({
66689
67459
  MaintenanceNotePlugin: () => MaintenanceNotePlugin,
66690
67460
  MaintenanceReasonSchema: () => MaintenanceReasonSchema,
66691
67461
  MaintenanceTriggerSchema: () => MaintenanceTriggerSchema,
66692
- MarkdownLive: () => MarkdownLive,
66693
67462
  MarkdownParseError: () => MarkdownParseError,
66694
- MarkdownService: () => MarkdownService,
66695
67463
  MarkdownlintContentStructureRule: () => ContentStructureRule$1,
66696
67464
  MarkdownlintDependencyTableFormatRule: () => DependencyTableFormatRule$1,
66697
67465
  MarkdownlintHeadingHierarchyRule: () => HeadingHierarchyRule$1,