@savvy-web/silk 3.4.2 → 3.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2391,7 +2391,7 @@ var BunExtension = class extends effect.Schema.Class("BunExtension")({
2391
2391
  *
2392
2392
  * @public
2393
2393
  */
2394
- var CatalogResolver$1 = class CatalogResolver extends effect.Context.Service()("@effected/npm/CatalogResolver") {
2394
+ var CatalogResolver = class CatalogResolver extends effect.Context.Service()("@effected/npm/CatalogResolver") {
2395
2395
  /**
2396
2396
  * No-op default: `rangeOf` always succeeds with `Option.none()`, never
2397
2397
  * consulting an actual catalog. A pure `Layer.succeed`, bound to a const
@@ -2415,7 +2415,7 @@ var CatalogResolver$1 = class CatalogResolver extends effect.Context.Service()("
2415
2415
  *
2416
2416
  * @public
2417
2417
  */
2418
- var DependencyResolutionError$1 = class extends effect.Schema.TaggedErrorClass()("DependencyResolutionError", {
2418
+ var DependencyResolutionError = class extends effect.Schema.TaggedErrorClass()("DependencyResolutionError", {
2419
2419
  specifier: effect.Schema.String,
2420
2420
  cause: effect.Schema.Defect()
2421
2421
  }) {
@@ -2453,7 +2453,7 @@ var DependencyResolutionError$1 = class extends effect.Schema.TaggedErrorClass()
2453
2453
  *
2454
2454
  * @public
2455
2455
  */
2456
- var WorkspaceResolver$1 = class WorkspaceResolver extends effect.Context.Service()("@effected/npm/WorkspaceResolver") {
2456
+ var WorkspaceResolver = class WorkspaceResolver extends effect.Context.Service()("@effected/npm/WorkspaceResolver") {
2457
2457
  /**
2458
2458
  * No-op default: `versionOf` always succeeds with `Option.none()`, never
2459
2459
  * consulting an actual workspace. A pure `Layer.succeed`, bound to a
@@ -2505,7 +2505,15 @@ var CatalogAssemblyError = class extends effect.Schema.TaggedErrorClass()("Catal
2505
2505
  return `Failed to assemble catalogs from ${this.source} ${this.path}`;
2506
2506
  }
2507
2507
  };
2508
- effect.Schema.Literals([
2508
+ //#endregion
2509
+ //#region ../../node_modules/.pnpm/@effected+npm@0.8.3_@effected+semver@0.3.2_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/npm/DependencySection.js
2510
+ /**
2511
+ * The short dependency kind: which dependency map an entry came from, named the
2512
+ * way consumers branch on it.
2513
+ *
2514
+ * @public
2515
+ */
2516
+ const DependencyKind = effect.Schema.Literals([
2509
2517
  "prod",
2510
2518
  "dev",
2511
2519
  "peer",
@@ -2517,7 +2525,7 @@ effect.Schema.Literals([
2517
2525
  *
2518
2526
  * @public
2519
2527
  */
2520
- const DependencyField$1 = effect.Schema.Literals([
2528
+ const DependencyField = effect.Schema.Literals([
2521
2529
  "dependencies",
2522
2530
  "devDependencies",
2523
2531
  "peerDependencies",
@@ -2904,7 +2912,7 @@ const parseRangeComparators = (s) => {
2904
2912
  * Parse a range expression into comparator sets (OR of ANDs). The empty
2905
2913
  * string parses as the match-all range.
2906
2914
  */
2907
- const parseRange$2 = (raw) => {
2915
+ const parseRange$1 = (raw) => {
2908
2916
  const trimmed = raw.trim();
2909
2917
  if (trimmed.length === 0) return {
2910
2918
  ok: true,
@@ -3803,7 +3811,7 @@ sets: effect.Schema.Array(effect.Schema.Array(Comparator)) }) {
3803
3811
  */
3804
3812
  static FromString = effect.Schema.String.pipe(effect.Schema.decodeTo(Range, effect.SchemaTransformation.transformOrFail({
3805
3813
  decode: (input) => {
3806
- const result = parseRange$2(input);
3814
+ const result = parseRange$1(input);
3807
3815
  return result.ok ? effect.Effect.succeed({ sets: normalizeSets(result.value) }) : effect.Effect.fail(new effect.SchemaIssue.InvalidValue(effect.Option.some(input), { message: `Invalid range expression: "${result.input}" at position ${result.position}` }));
3808
3816
  },
3809
3817
  encode: (parts) => effect.Effect.succeed(formatRange(parts.sets))
@@ -3834,7 +3842,7 @@ sets: effect.Schema.Array(effect.Schema.Array(Comparator)) }) {
3834
3842
  * with {@link InvalidRangeError}.
3835
3843
  */
3836
3844
  static parseResult(input) {
3837
- const result = parseRange$2(input);
3845
+ const result = parseRange$1(input);
3838
3846
  if (!result.ok) return effect.Result.fail(new InvalidRangeError({
3839
3847
  input: result.input,
3840
3848
  position: result.position
@@ -4122,50 +4130,50 @@ const isComparatorSetSubset = (sub, sup) => {
4122
4130
  *
4123
4131
  * @public
4124
4132
  */
4125
- var InvalidDependencySpecifierError$1 = class extends effect.Schema.TaggedErrorClass()("InvalidDependencySpecifierError", {
4133
+ var InvalidDependencySpecifierError = class extends effect.Schema.TaggedErrorClass()("InvalidDependencySpecifierError", {
4126
4134
  /** The raw input string that failed validation. */
4127
4135
  input: effect.Schema.String }) {
4128
4136
  get message() {
4129
4137
  return `Invalid dependency specifier "${this.input}": not a recognized specifier`;
4130
4138
  }
4131
4139
  };
4132
- const CATALOG_PREFIX$1 = "catalog:";
4133
- const WORKSPACE_PREFIX$1 = "workspace:";
4134
- const isBarePath$1 = (value) => value.startsWith("./") || value.startsWith("../") || value.startsWith("~/") || value.startsWith("/");
4135
- const isGitHubShorthand$1 = (value) => !value.startsWith(".") && !value.startsWith("~") && !value.startsWith("/") && /^[a-zA-Z0-9_.-]+\/[a-zA-Z0-9_.-]+(#.*)?$/.test(value);
4136
- const isGit$1 = (value) => value.startsWith("git+") || value.startsWith("git://") || value.startsWith("github:") || value.startsWith("gist:") || value.startsWith("bitbucket:") || value.startsWith("gitlab:") || isGitHubShorthand$1(value);
4137
- const isLocal$1 = (value) => value.startsWith("file:") || value.startsWith("link:") || value.startsWith("portal:") || isBarePath$1(value);
4138
- const isLink$1 = (value) => value.startsWith("link:");
4139
- const isPortal$1 = (value) => value.startsWith("portal:");
4140
- const isCatalog$1 = (value) => value.startsWith(CATALOG_PREFIX$1);
4141
- const isWorkspace$1 = (value) => value.startsWith(WORKSPACE_PREFIX$1);
4142
- const isUrl$2 = (value) => value.startsWith("http://") || value.startsWith("https://");
4143
- const parseRange$1 = (value) => {
4140
+ const CATALOG_PREFIX = "catalog:";
4141
+ const WORKSPACE_PREFIX = "workspace:";
4142
+ const isBarePath = (value) => value.startsWith("./") || value.startsWith("../") || value.startsWith("~/") || value.startsWith("/");
4143
+ const isGitHubShorthand = (value) => !value.startsWith(".") && !value.startsWith("~") && !value.startsWith("/") && /^[a-zA-Z0-9_.-]+\/[a-zA-Z0-9_.-]+(#.*)?$/.test(value);
4144
+ const isGit = (value) => value.startsWith("git+") || value.startsWith("git://") || value.startsWith("github:") || value.startsWith("gist:") || value.startsWith("bitbucket:") || value.startsWith("gitlab:") || isGitHubShorthand(value);
4145
+ const isLocal = (value) => value.startsWith("file:") || value.startsWith("link:") || value.startsWith("portal:") || isBarePath(value);
4146
+ const isLink = (value) => value.startsWith("link:");
4147
+ const isPortal = (value) => value.startsWith("portal:");
4148
+ const isCatalog = (value) => value.startsWith(CATALOG_PREFIX);
4149
+ const isWorkspace = (value) => value.startsWith(WORKSPACE_PREFIX);
4150
+ const isUrl$1 = (value) => value.startsWith("http://") || value.startsWith("https://");
4151
+ const parseRange = (value) => {
4144
4152
  const exit = effect.Schema.decodeUnknownExit(Range$2.FromString)(value);
4145
4153
  return effect.Exit.isSuccess(exit) ? effect.Option.some(exit.value) : effect.Option.none();
4146
4154
  };
4147
- const isRange$1 = (value) => effect.Option.isSome(parseRange$1(value));
4148
- const protocolOf$1 = (value) => {
4149
- if (value.startsWith(CATALOG_PREFIX$1)) return "catalog";
4150
- if (value.startsWith(WORKSPACE_PREFIX$1)) return "workspace";
4155
+ const isRange = (value) => effect.Option.isSome(parseRange(value));
4156
+ const protocolOf = (value) => {
4157
+ if (value.startsWith(CATALOG_PREFIX)) return "catalog";
4158
+ if (value.startsWith(WORKSPACE_PREFIX)) return "workspace";
4151
4159
  if (value.startsWith("link:")) return "link";
4152
4160
  if (value.startsWith("portal:")) return "portal";
4153
- if (value.startsWith("file:") || isBarePath$1(value)) return "file";
4161
+ if (value.startsWith("file:") || isBarePath(value)) return "file";
4154
4162
  if (value.startsWith("npm:")) return "npm";
4155
- if (isGit$1(value)) return "git";
4156
- if (isUrl$2(value)) return "url";
4157
- if (isRange$1(value)) return "range";
4163
+ if (isGit(value)) return "git";
4164
+ if (isUrl$1(value)) return "url";
4165
+ if (isRange(value)) return "range";
4158
4166
  if (/^[a-zA-Z][a-zA-Z0-9._-]*$/.test(value)) return "tag";
4159
4167
  return "unknown";
4160
4168
  };
4161
- const isTag$1 = (value) => protocolOf$1(value) === "tag";
4162
- const catalogNameOf$2 = (specifier) => {
4163
- if (!isCatalog$1(specifier)) return effect.Option.none();
4169
+ const isTag = (value) => protocolOf(value) === "tag";
4170
+ const catalogNameOf$1 = (specifier) => {
4171
+ if (!isCatalog(specifier)) return effect.Option.none();
4164
4172
  const rest = specifier.slice(8).trim();
4165
4173
  return rest.length === 0 ? effect.Option.none() : effect.Option.some(rest);
4166
4174
  };
4167
- const projectRangeModifier$1 = (range, version) => range === "*" || range === "" ? version : range === "~" ? `~${version}` : range === "^" ? `^${version}` : range;
4168
- const splitWorkspaceRest$1 = (rest) => {
4175
+ const projectRangeModifier = (range, version) => range === "*" || range === "" ? version : range === "~" ? `~${version}` : range === "^" ? `^${version}` : range;
4176
+ const splitWorkspaceRest = (rest) => {
4169
4177
  const at = rest.lastIndexOf("@");
4170
4178
  return at > 0 ? {
4171
4179
  target: rest.slice(0, at),
@@ -4175,15 +4183,15 @@ const splitWorkspaceRest$1 = (rest) => {
4175
4183
  range: rest
4176
4184
  };
4177
4185
  };
4178
- const projectWorkspaceRange$1 = (rest, version) => {
4179
- const { target, range } = splitWorkspaceRest$1(rest);
4180
- const projected = projectRangeModifier$1(range, version);
4186
+ const projectWorkspaceRange = (rest, version) => {
4187
+ const { target, range } = splitWorkspaceRest(rest);
4188
+ const projected = projectRangeModifier(range, version);
4181
4189
  return target === void 0 ? projected : `npm:${target}@${projected}`;
4182
4190
  };
4183
- const resolveWorkspace$1 = (specifier, version) => isWorkspace$1(specifier) ? projectWorkspaceRange$1(specifier.slice(10), version) : specifier;
4184
- const workspaceTargetOf$1 = (specifier) => {
4185
- if (!isWorkspace$1(specifier)) return effect.Option.none();
4186
- const { target } = splitWorkspaceRest$1(specifier.slice(10));
4191
+ const resolveWorkspace = (specifier, version) => isWorkspace(specifier) ? projectWorkspaceRange(specifier.slice(10), version) : specifier;
4192
+ const workspaceTargetOf = (specifier) => {
4193
+ if (!isWorkspace(specifier)) return effect.Option.none();
4194
+ const { target } = splitWorkspaceRest(specifier.slice(10));
4187
4195
  return target === void 0 ? effect.Option.none() : effect.Option.some(target);
4188
4196
  };
4189
4197
  /**
@@ -4193,14 +4201,14 @@ const workspaceTargetOf$1 = (specifier) => {
4193
4201
  *
4194
4202
  * @public
4195
4203
  */
4196
- const isValidDependencySpecifier$1 = (value) => value.length > 0 && protocolOf$1(value) !== "unknown";
4204
+ const isValidDependencySpecifier = (value) => value.length > 0 && protocolOf(value) !== "unknown";
4197
4205
  /**
4198
4206
  * A `catalog:` reference. `name` carries the catalog name, or `Option.none()`
4199
4207
  * for the default catalog (`catalog:`).
4200
4208
  *
4201
4209
  * @public
4202
4210
  */
4203
- var CatalogSpecifier$1 = class extends effect.Schema.TaggedClass()("catalog", {
4211
+ var CatalogSpecifier = class extends effect.Schema.TaggedClass()("catalog", {
4204
4212
  /** The original specifier string. */
4205
4213
  raw: effect.Schema.String,
4206
4214
  /** The catalog name, or `Option.none()` for the default catalog. */
@@ -4212,7 +4220,7 @@ var CatalogSpecifier$1 = class extends effect.Schema.TaggedClass()("catalog", {
4212
4220
  *
4213
4221
  * @public
4214
4222
  */
4215
- var WorkspaceSpecifier$1 = class extends effect.Schema.TaggedClass()("workspace", {
4223
+ var WorkspaceSpecifier = class extends effect.Schema.TaggedClass()("workspace", {
4216
4224
  /** The original specifier string. */
4217
4225
  raw: effect.Schema.String,
4218
4226
  /** The part after `workspace:` (e.g. `*`, `^1.2.3`, or an alias form). */
@@ -4236,7 +4244,7 @@ var WorkspaceSpecifier$1 = class extends effect.Schema.TaggedClass()("workspace"
4236
4244
  * specifier points at (the alias target's version for the alias form).
4237
4245
  */
4238
4246
  resolve(version) {
4239
- return projectWorkspaceRange$1(this.range, version);
4247
+ return projectWorkspaceRange(this.range, version);
4240
4248
  }
4241
4249
  };
4242
4250
  /**
@@ -4244,7 +4252,7 @@ var WorkspaceSpecifier$1 = class extends effect.Schema.TaggedClass()("workspace"
4244
4252
  *
4245
4253
  * @public
4246
4254
  */
4247
- var RangeSpecifier$1 = class extends effect.Schema.TaggedClass()("range", {
4255
+ var RangeSpecifier = class extends effect.Schema.TaggedClass()("range", {
4248
4256
  /** The original specifier string. */
4249
4257
  raw: effect.Schema.String }) {};
4250
4258
  /**
@@ -4252,7 +4260,7 @@ raw: effect.Schema.String }) {};
4252
4260
  *
4253
4261
  * @public
4254
4262
  */
4255
- var DistTagSpecifier$1 = class extends effect.Schema.TaggedClass()("dist-tag", {
4263
+ var DistTagSpecifier = class extends effect.Schema.TaggedClass()("dist-tag", {
4256
4264
  /** The original specifier string (also the tag name). */
4257
4265
  raw: effect.Schema.String }) {};
4258
4266
  /**
@@ -4261,35 +4269,35 @@ raw: effect.Schema.String }) {};
4261
4269
  *
4262
4270
  * @public
4263
4271
  */
4264
- var RawSpecifier$1 = class extends effect.Schema.TaggedClass()("raw", {
4272
+ var RawSpecifier = class extends effect.Schema.TaggedClass()("raw", {
4265
4273
  /** The original specifier string. */
4266
4274
  raw: effect.Schema.String }) {};
4267
- const Classified$1 = effect.Schema.Union([
4268
- CatalogSpecifier$1,
4269
- WorkspaceSpecifier$1,
4270
- RangeSpecifier$1,
4271
- DistTagSpecifier$1,
4272
- RawSpecifier$1
4275
+ const Classified = effect.Schema.Union([
4276
+ CatalogSpecifier,
4277
+ WorkspaceSpecifier,
4278
+ RangeSpecifier,
4279
+ DistTagSpecifier,
4280
+ RawSpecifier
4273
4281
  ]);
4274
- const classify$2 = (value) => {
4275
- if (isCatalog$1(value)) return CatalogSpecifier$1.make({
4282
+ const classify$1 = (value) => {
4283
+ if (isCatalog(value)) return CatalogSpecifier.make({
4276
4284
  raw: value,
4277
- name: catalogNameOf$2(value)
4285
+ name: catalogNameOf$1(value)
4278
4286
  });
4279
- if (isWorkspace$1(value)) return WorkspaceSpecifier$1.make({
4287
+ if (isWorkspace(value)) return WorkspaceSpecifier.make({
4280
4288
  raw: value,
4281
4289
  range: value.slice(10)
4282
4290
  });
4283
- if (isRange$1(value)) return RangeSpecifier$1.make({ raw: value });
4284
- if (isTag$1(value)) return DistTagSpecifier$1.make({ raw: value });
4285
- return RawSpecifier$1.make({ raw: value });
4291
+ if (isRange(value)) return RangeSpecifier.make({ raw: value });
4292
+ if (isTag(value)) return DistTagSpecifier.make({ raw: value });
4293
+ return RawSpecifier.make({ raw: value });
4286
4294
  };
4287
- const fromString$1 = effect.Schema.String.pipe(effect.Schema.decodeTo(Classified$1, effect.SchemaTransformation.transformOrFail({
4288
- decode: (input) => isValidDependencySpecifier$1(input) ? effect.Effect.succeed(classify$2(input)) : effect.Effect.fail(new effect.SchemaIssue.InvalidValue(effect.Option.some(input), { message: `Invalid dependency specifier: "${input}"` })),
4295
+ const fromString = effect.Schema.String.pipe(effect.Schema.decodeTo(Classified, effect.SchemaTransformation.transformOrFail({
4296
+ decode: (input) => isValidDependencySpecifier(input) ? effect.Effect.succeed(classify$1(input)) : effect.Effect.fail(new effect.SchemaIssue.InvalidValue(effect.Option.some(input), { message: `Invalid dependency specifier: "${input}"` })),
4289
4297
  encode: (classified) => effect.Effect.succeed(classified.raw)
4290
4298
  })));
4291
- const brandedSpecifier$1 = effect.Schema.String.pipe(effect.Schema.check(effect.Schema.makeFilter((value) => isValidDependencySpecifier$1(value) ? void 0 : "Expected a valid dependency specifier")), effect.Schema.brand("DependencySpecifier"));
4292
- const decode$5 = (input) => effect.Schema.decodeUnknownEffect(brandedSpecifier$1)(input).pipe(effect.Effect.mapError(() => new InvalidDependencySpecifierError$1({ input })));
4299
+ const brandedSpecifier = effect.Schema.String.pipe(effect.Schema.check(effect.Schema.makeFilter((value) => isValidDependencySpecifier(value) ? void 0 : "Expected a valid dependency specifier")), effect.Schema.brand("DependencySpecifier"));
4300
+ const decode$3 = (input) => effect.Schema.decodeUnknownEffect(brandedSpecifier)(input).pipe(effect.Effect.mapError(() => new InvalidDependencySpecifierError({ input })));
4293
4301
  /**
4294
4302
  * A valid dependency version specifier, carrying the protocol taxonomy statics
4295
4303
  * (`DependencySpecifier.protocolOf` and friends) that classify any specifier
@@ -4300,43 +4308,43 @@ const decode$5 = (input) => effect.Schema.decodeUnknownEffect(brandedSpecifier$1
4300
4308
  *
4301
4309
  * @public
4302
4310
  */
4303
- const DependencySpecifier$1 = Object.assign(brandedSpecifier$1, {
4304
- protocolOf: protocolOf$1,
4305
- parseRange: parseRange$1,
4306
- isRange: isRange$1,
4307
- isTag: isTag$1,
4308
- isGit: isGit$1,
4309
- isUrl: isUrl$2,
4310
- isLocal: isLocal$1,
4311
- isLink: isLink$1,
4312
- isPortal: isPortal$1,
4313
- isCatalog: isCatalog$1,
4314
- isWorkspace: isWorkspace$1,
4315
- catalogNameOf: catalogNameOf$2,
4316
- resolveWorkspace: resolveWorkspace$1,
4317
- workspaceTargetOf: workspaceTargetOf$1,
4318
- isValid: isValidDependencySpecifier$1,
4319
- decode: decode$5,
4320
- FromString: fromString$1
4311
+ const DependencySpecifier = Object.assign(brandedSpecifier, {
4312
+ protocolOf,
4313
+ parseRange,
4314
+ isRange,
4315
+ isTag,
4316
+ isGit,
4317
+ isUrl: isUrl$1,
4318
+ isLocal,
4319
+ isLink,
4320
+ isPortal,
4321
+ isCatalog,
4322
+ isWorkspace,
4323
+ catalogNameOf: catalogNameOf$1,
4324
+ resolveWorkspace,
4325
+ workspaceTargetOf,
4326
+ isValid: isValidDependencySpecifier,
4327
+ decode: decode$3,
4328
+ FromString: fromString
4321
4329
  });
4322
4330
  //#endregion
4323
4331
  //#region ../../node_modules/.pnpm/@effected+npm@0.8.3_@effected+semver@0.3.2_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/npm/IntegrityHash.js
4324
- const SRI_RE$1 = /^(sha1|sha256|sha384|sha512)-[A-Za-z0-9+/]+={0,2}$/;
4325
- const COREPACK_RE$1 = /^(sha1|sha224|sha256|sha384|sha512)\.[0-9a-f]+$/;
4326
- const YARN_RE$1 = /^[0-9]+(c[0-9]+)?\/[0-9a-f]+$/;
4327
- const isSri$1 = (value) => SRI_RE$1.test(value);
4328
- const isCorepack$1 = (value) => COREPACK_RE$1.test(value);
4329
- const isYarnChecksum$1 = (value) => YARN_RE$1.test(value);
4332
+ const SRI_RE = /^(sha1|sha256|sha384|sha512)-[A-Za-z0-9+/]+={0,2}$/;
4333
+ const COREPACK_RE = /^(sha1|sha224|sha256|sha384|sha512)\.[0-9a-f]+$/;
4334
+ const YARN_RE = /^[0-9]+(c[0-9]+)?\/[0-9a-f]+$/;
4335
+ const isSri = (value) => SRI_RE.test(value);
4336
+ const isCorepack = (value) => COREPACK_RE.test(value);
4337
+ const isYarnChecksum = (value) => YARN_RE.test(value);
4330
4338
  /**
4331
4339
  * Whether a string is a valid integrity hash in the SRI (`<algo>-<base64>`),
4332
4340
  * corepack (`<algo>.<hex>`) or yarn (`<cachekey>/<hex>`) form.
4333
4341
  *
4334
4342
  * @public
4335
4343
  */
4336
- const isValidIntegrityHash$1 = (value) => isSri$1(value) || isCorepack$1(value) || isYarnChecksum$1(value);
4337
- const algorithmOf$1 = (value) => {
4338
- if (isSri$1(value)) return effect.Option.some(value.slice(0, value.indexOf("-")));
4339
- if (isCorepack$1(value)) return effect.Option.some(value.slice(0, value.indexOf(".")));
4344
+ const isValidIntegrityHash = (value) => isSri(value) || isCorepack(value) || isYarnChecksum(value);
4345
+ const algorithmOf = (value) => {
4346
+ if (isSri(value)) return effect.Option.some(value.slice(0, value.indexOf("-")));
4347
+ if (isCorepack(value)) return effect.Option.some(value.slice(0, value.indexOf(".")));
4340
4348
  return effect.Option.none();
4341
4349
  };
4342
4350
  /**
@@ -4347,15 +4355,15 @@ const algorithmOf$1 = (value) => {
4347
4355
  *
4348
4356
  * @public
4349
4357
  */
4350
- var InvalidIntegrityHashError$1 = class extends effect.Schema.TaggedErrorClass()("InvalidIntegrityHashError", {
4358
+ var InvalidIntegrityHashError = class extends effect.Schema.TaggedErrorClass()("InvalidIntegrityHashError", {
4351
4359
  /** The raw input string that failed validation. */
4352
4360
  input: effect.Schema.String }) {
4353
4361
  get message() {
4354
4362
  return `Invalid integrity hash "${this.input}": expected an SRI (<algo>-<base64>), corepack (<algo>.<hex>) or yarn (<cachekey>/<hex>) form`;
4355
4363
  }
4356
4364
  };
4357
- const brandedIntegrity$1 = effect.Schema.String.pipe(effect.Schema.check(effect.Schema.makeFilter((value) => isValidIntegrityHash$1(value) ? void 0 : "Expected an SRI, corepack or yarn integrity hash")), effect.Schema.brand("IntegrityHash"));
4358
- const decode$4 = (input) => effect.Schema.decodeUnknownEffect(brandedIntegrity$1)(input).pipe(effect.Effect.mapError(() => new InvalidIntegrityHashError$1({ input })));
4365
+ const brandedIntegrity = effect.Schema.String.pipe(effect.Schema.check(effect.Schema.makeFilter((value) => isValidIntegrityHash(value) ? void 0 : "Expected an SRI, corepack or yarn integrity hash")), effect.Schema.brand("IntegrityHash"));
4366
+ const decode$2 = (input) => effect.Schema.decodeUnknownEffect(brandedIntegrity)(input).pipe(effect.Effect.mapError(() => new InvalidIntegrityHashError({ input })));
4359
4367
  /**
4360
4368
  * A subresource-integrity hash, covering the SRI (`sha512-<base64>`), corepack
4361
4369
  * (`sha512.<hex>`) and yarn (`10c0/<hex>`) textual forms, carrying taxonomy
@@ -4364,15 +4372,66 @@ const decode$4 = (input) => effect.Schema.decodeUnknownEffect(brandedIntegrity$1
4364
4372
  *
4365
4373
  * @public
4366
4374
  */
4367
- const IntegrityHash$1 = Object.assign(brandedIntegrity$1, {
4368
- isSri: isSri$1,
4369
- isCorepack: isCorepack$1,
4370
- isYarnChecksum: isYarnChecksum$1,
4371
- isValid: isValidIntegrityHash$1,
4372
- algorithmOf: algorithmOf$1,
4373
- decode: decode$4
4375
+ const IntegrityHash = Object.assign(brandedIntegrity, {
4376
+ isSri,
4377
+ isCorepack,
4378
+ isYarnChecksum,
4379
+ isValid: isValidIntegrityHash,
4380
+ algorithmOf,
4381
+ decode: decode$2
4374
4382
  });
4375
- brandedIntegrity$1.pipe(effect.Schema.check(effect.Schema.makeFilter((value) => isCorepack$1(value) ? void 0 : "Expected a corepack (<algo>.<hex>) integrity hash")));
4383
+ /**
4384
+ * {@link (IntegrityHash:variable)} narrowed to the corepack `<algo>.<hex>` form
4385
+ * — `sha512.deadbeef`, and corepack's own sha224 default pins
4386
+ * (`sha224.877304e3…`). An SRI (`sha512-<base64>`) or yarn (`10c0/<hex>`)
4387
+ * hash, both valid `IntegrityHash` values, fails this schema.
4388
+ *
4389
+ * @remarks
4390
+ * The corepack pin tail (`<name>@<version>+<integrity>`) is the one place the
4391
+ * kit meets this form, and two schemas name it: `PackageManagerPin.integrity`
4392
+ * here and `@effected/package-json`'s `PackageManager.integrity`. Both consume
4393
+ * **this** schema — the restriction existed privately in each module until they
4394
+ * were consolidated, and a private copy is exactly how the two drift (the
4395
+ * widening that admitted sha224 had to be made twice).
4396
+ *
4397
+ * It decodes to the same {@link IntegrityHashBrand} the unrestricted schema
4398
+ * does, so a corepack-validated value assigns anywhere an `IntegrityHash` is
4399
+ * expected; there is no second brand. Reach for
4400
+ * `IntegrityHash.isCorepack(value)` to ask the same question about a raw
4401
+ * string without decoding.
4402
+ *
4403
+ * That single brand is also why sharing this schema is not type-enforced, and
4404
+ * the consequence is sharper than it looks: a `Schema.check` is **erased from
4405
+ * the built type**, so this schema and the unrestricted one are the same
4406
+ * declared type. A consumer that quietly reverts to a private copy compiles
4407
+ * clean, and — if the copy is faithful — passes every rejection test too.
4408
+ * Neither `tsc` nor behaviour can see the re-fork.
4409
+ *
4410
+ * What does see it is **object identity**, so each consumer's suite asserts
4411
+ * that its field schema IS this export:
4412
+ * `PackageManagerPin.fields.integrity.schema === CorepackIntegrityHash` (an
4413
+ * `optionalKey` field keeps the inner schema on `.schema`), and
4414
+ * `PackageManager.fields.integrity.value === CorepackIntegrityHash` on the
4415
+ * `@effected/package-json` side (a `Schema.Option` keeps it on `.value`). Both
4416
+ * assertions carry a control against the unrestricted brand, so they discriminate
4417
+ * rather than passing on any schema at all. That identity assertion is the only
4418
+ * thing standing between the two surfaces and a silent re-fork; do not replace
4419
+ * it with a behavioural test, which cannot fail.
4420
+ *
4421
+ * @example
4422
+ * ```ts
4423
+ * import { CorepackIntegrityHash } from "@effected/npm";
4424
+ * import { Schema } from "effect";
4425
+ *
4426
+ * const decode = Schema.decodeUnknownExit(CorepackIntegrityHash);
4427
+ *
4428
+ * decode("sha512.deadbeef"); // success
4429
+ * decode("sha512-3q2+7w=="); // failure — SRI form
4430
+ * ```
4431
+ *
4432
+ * @public
4433
+ */
4434
+ const CorepackIntegrityHash = brandedIntegrity.pipe(effect.Schema.check(effect.Schema.makeFilter((value) => isCorepack(value) ? void 0 : "Expected a corepack (<algo>.<hex>) integrity hash")));
4376
4435
  effect.Schema.Literals([
4377
4436
  "npm",
4378
4437
  "pnpm",
@@ -5441,10 +5500,10 @@ var ReleaseAgeGate = class ReleaseAgeGate extends effect.Schema.Class("ReleaseAg
5441
5500
  */
5442
5501
  var ImporterDependency = class extends effect.Schema.Class("ImporterDependency")({
5443
5502
  name: effect.Schema.NonEmptyString,
5444
- specifier: DependencySpecifier$1.FromString,
5503
+ specifier: DependencySpecifier.FromString,
5445
5504
  version: effect.Schema.optionalKey(effect.Schema.String),
5446
5505
  peerSuffix: effect.Schema.optionalKey(effect.Schema.String),
5447
- depType: DependencyField$1
5506
+ depType: DependencyField
5448
5507
  }) {};
5449
5508
  //#endregion
5450
5509
  //#region ../../node_modules/.pnpm/@effected+lockfiles@0.3.2_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__@effected+npm@0._3c1784fba62fde9a5bac4cf15387fd04/node_modules/@effected/lockfiles/LockfileImporter.js
@@ -5500,7 +5559,7 @@ const EMPTY_DEPENDENCIES = {};
5500
5559
  var ResolvedPackage = class extends effect.Schema.Class("ResolvedPackage")({
5501
5560
  name: effect.Schema.NonEmptyString,
5502
5561
  version: effect.Schema.String,
5503
- integrity: effect.Schema.optionalKey(IntegrityHash$1),
5562
+ integrity: effect.Schema.optionalKey(IntegrityHash),
5504
5563
  isWorkspace: effect.Schema.Boolean,
5505
5564
  relativePath: effect.Schema.optionalKey(effect.Schema.String),
5506
5565
  dependencies: effect.Schema.Record(effect.Schema.String, effect.Schema.String).pipe(effect.Schema.withDecodingDefaultKey(effect.Effect.succeed(EMPTY_DEPENDENCIES)), effect.Schema.withConstructorDefault(effect.Effect.succeed(EMPTY_DEPENDENCIES)))
@@ -5524,7 +5583,7 @@ var ResolvedPackage = class extends effect.Schema.Class("ResolvedPackage")({
5524
5583
  var WorkspaceDependency = class extends effect.Schema.Class("WorkspaceDependency")({
5525
5584
  from: effect.Schema.NonEmptyString,
5526
5585
  to: effect.Schema.NonEmptyString,
5527
- depType: DependencyField$1,
5586
+ depType: DependencyField,
5528
5587
  constraint: effect.Schema.String
5529
5588
  }) {};
5530
5589
  //#endregion
@@ -5626,9 +5685,9 @@ const DEP_TYPES = [
5626
5685
  */
5627
5686
  const toIntegrityHash = (raw) => {
5628
5687
  if (raw === void 0) return effect.Effect.succeed(void 0);
5629
- return effect.Schema.decodeUnknownEffect(IntegrityHash$1)(raw).pipe(effect.Effect.mapError(validationFailure));
5688
+ return effect.Schema.decodeUnknownEffect(IntegrityHash)(raw).pipe(effect.Effect.mapError(validationFailure));
5630
5689
  };
5631
- const decodeSpecifier = effect.Schema.decodeUnknownExit(DependencySpecifier$1.FromString);
5690
+ const decodeSpecifier = effect.Schema.decodeUnknownExit(DependencySpecifier.FromString);
5632
5691
  /**
5633
5692
  * Split pnpm's peer-disambiguation suffix off a recorded string: everything
5634
5693
  * from the first `(` on is suffix, since package names and versions never
@@ -15145,7 +15204,7 @@ var LockfileIntegrity = class LockfileIntegrity extends effect.Schema.Class("Loc
15145
15204
  dependency: effect.Schema.String,
15146
15205
  constraint: effect.Schema.String,
15147
15206
  resolved: effect.Schema.String,
15148
- depType: DependencyField$1
15207
+ depType: DependencyField
15149
15208
  }))
15150
15209
  }) {
15151
15210
  /**
@@ -15213,514 +15272,97 @@ var LockfileIntegrity = class LockfileIntegrity extends effect.Schema.Class("Loc
15213
15272
  }
15214
15273
  };
15215
15274
  //#endregion
15216
- //#region ../../node_modules/.pnpm/@effected+npm@0.8.2_@effected+semver@0.3.2_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/npm/CatalogResolver.js
15275
+ //#region ../../node_modules/.pnpm/@effected+package-json@0.7.3_effect@4.0.0-beta.101/node_modules/@effected/package-json/Dependency.js
15217
15276
  /**
15218
- * Contract for resolving pnpm `catalog:` dependency specifiers to concrete
15219
- * version ranges.
15220
- *
15221
- * `rangeOf` takes a package name and an optional catalog name
15222
- * (`Option.none()` selects the default catalog) and returns the configured
15223
- * range as `Option.some`, or `Option.none()` when the specifier is absent
15224
- * from the catalog. By convention the error channel is reserved for a
15225
- * failure in the resolution mechanism itself — an unmatched package or
15226
- * catalog name is an `Option.none()` success, never an error. A failure to
15227
- * *assemble* the catalogs (an unreadable or malformed catalog source)
15228
- * surfaces typed as a {@link CatalogAssemblyError}; any other mechanism
15229
- * failure is a {@link DependencyResolutionError}.
15230
- *
15231
- * This is a contract-only service: {@link CatalogResolver.noop} is the sole
15232
- * implementation this package ships, and it resolves nothing. Real consumers
15233
- * (e.g. `@effected/workspaces`) provide a working implementation at the
15234
- * application boundary.
15235
- *
15236
- * @example
15237
- * ```ts
15238
- * import { Effect, Option } from "effect";
15239
- * import { CatalogResolver } from "@effected/npm";
15240
- *
15241
- * const program = Effect.gen(function* () {
15242
- * const resolver = yield* CatalogResolver;
15243
- * return yield* resolver.rangeOf("effect", Option.none());
15244
- * });
15245
- *
15246
- * Effect.runPromise(Effect.provide(program, CatalogResolver.noop));
15247
- * // => Option.none()
15248
- * ```
15277
+ * A resolved dependency entry pairing a package name with its version
15278
+ * specifier and the `kind` of map it came from (`@effected/npm`'s
15279
+ * `DependencyKind`). The protocol predicates delegate to `DependencySpecifier`.
15249
15280
  *
15250
15281
  * @public
15251
15282
  */
15252
- var CatalogResolver = class CatalogResolver extends effect.Context.Service()("@effected/npm/CatalogResolver") {
15253
- /**
15254
- * No-op default: `rangeOf` always succeeds with `Option.none()`, never
15255
- * consulting an actual catalog. A pure `Layer.succeed`, bound to a const
15256
- * so it memoizes by reference — the layer is built once, not once per
15257
- * reference to `CatalogResolver.noop`.
15258
- */
15259
- static noop = effect.Layer.succeed(CatalogResolver, { rangeOf: () => effect.Effect.succeed(effect.Option.none()) });
15260
- };
15261
- effect.Schema.TaggedErrorClass()("DependencyResolutionError", {
15283
+ var Dependency = class extends effect.Schema.Class("Dependency")({
15284
+ /** The package name. */
15285
+ name: effect.Schema.String,
15286
+ /** The raw version specifier. */
15262
15287
  specifier: effect.Schema.String,
15263
- cause: effect.Schema.Defect()
15264
- });
15265
- /**
15266
- * Contract for resolving pnpm `workspace:` dependency specifiers to concrete
15267
- * versions.
15268
- *
15269
- * `versionOf` takes a workspace package name and returns its concrete
15270
- * version (the range modifier stripped) as `Option.some`, or
15271
- * `Option.none()` when the name is not a known workspace member.
15272
- *
15273
- * This is a contract-only service: {@link WorkspaceResolver.noop} is the
15274
- * sole implementation this package ships, and it resolves nothing. Real
15275
- * consumers (e.g. `@effected/workspaces`) provide a working implementation
15276
- * at the application boundary.
15277
- *
15278
- * @example
15279
- * ```ts
15280
- * import { Effect } from "effect";
15281
- * import { WorkspaceResolver } from "@effected/npm";
15282
- *
15283
- * const program = Effect.gen(function* () {
15284
- * const resolver = yield* WorkspaceResolver;
15285
- * return yield* resolver.versionOf("@effected/semver");
15286
- * });
15287
- *
15288
- * Effect.runPromise(Effect.provide(program, WorkspaceResolver.noop));
15289
- * // => Option.none()
15290
- * ```
15291
- *
15292
- * @public
15293
- */
15294
- var WorkspaceResolver = class WorkspaceResolver extends effect.Context.Service()("@effected/npm/WorkspaceResolver") {
15295
- /**
15296
- * No-op default: `versionOf` always succeeds with `Option.none()`, never
15297
- * consulting an actual workspace. A pure `Layer.succeed`, bound to a
15298
- * const so it memoizes by reference.
15299
- */
15300
- static noop = effect.Layer.succeed(WorkspaceResolver, { versionOf: () => effect.Effect.succeed(effect.Option.none()) });
15301
- };
15302
- //#endregion
15303
- //#region ../../node_modules/.pnpm/@effected+npm@0.8.2_@effected+semver@0.3.2_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/npm/DependencySection.js
15304
- /**
15305
- * The short dependency kind: which dependency map an entry came from, named the
15306
- * way consumers branch on it.
15307
- *
15308
- * @public
15309
- */
15310
- const DependencyKind = effect.Schema.Literals([
15311
- "prod",
15312
- "dev",
15313
- "peer",
15314
- "optional"
15315
- ]);
15316
- effect.Schema.Literals([
15317
- "dependencies",
15318
- "devDependencies",
15319
- "peerDependencies",
15320
- "optionalDependencies"
15321
- ]);
15322
- Object.fromEntries(Object.entries({
15323
- prod: "dependencies",
15324
- dev: "devDependencies",
15325
- peer: "peerDependencies",
15326
- optional: "optionalDependencies"
15327
- }).map(([kind, field]) => [field, kind]));
15328
- //#endregion
15329
- //#region ../../node_modules/.pnpm/@effected+npm@0.8.2_@effected+semver@0.3.2_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/npm/DependencySpecifier.js
15330
- /**
15331
- * Indicates that a string could not be parsed as a valid dependency specifier.
15332
- *
15333
- * Raised by {@link DependencySpecifier.decode}. The offending string is
15334
- * preserved on `input`.
15335
- *
15336
- * @public
15337
- */
15338
- var InvalidDependencySpecifierError = class extends effect.Schema.TaggedErrorClass()("InvalidDependencySpecifierError", {
15339
- /** The raw input string that failed validation. */
15340
- input: effect.Schema.String }) {
15341
- get message() {
15342
- return `Invalid dependency specifier "${this.input}": not a recognized specifier`;
15343
- }
15344
- };
15345
- const CATALOG_PREFIX = "catalog:";
15346
- const WORKSPACE_PREFIX = "workspace:";
15347
- const isBarePath = (value) => value.startsWith("./") || value.startsWith("../") || value.startsWith("~/") || value.startsWith("/");
15348
- const isGitHubShorthand = (value) => !value.startsWith(".") && !value.startsWith("~") && !value.startsWith("/") && /^[a-zA-Z0-9_.-]+\/[a-zA-Z0-9_.-]+(#.*)?$/.test(value);
15349
- const isGit = (value) => value.startsWith("git+") || value.startsWith("git://") || value.startsWith("github:") || value.startsWith("gist:") || value.startsWith("bitbucket:") || value.startsWith("gitlab:") || isGitHubShorthand(value);
15350
- const isLocal = (value) => value.startsWith("file:") || value.startsWith("link:") || value.startsWith("portal:") || isBarePath(value);
15351
- const isLink = (value) => value.startsWith("link:");
15352
- const isPortal = (value) => value.startsWith("portal:");
15353
- const isCatalog = (value) => value.startsWith(CATALOG_PREFIX);
15354
- const isWorkspace = (value) => value.startsWith(WORKSPACE_PREFIX);
15355
- const isUrl$1 = (value) => value.startsWith("http://") || value.startsWith("https://");
15356
- const parseRange = (value) => {
15357
- const exit = effect.Schema.decodeUnknownExit(Range$2.FromString)(value);
15358
- return effect.Exit.isSuccess(exit) ? effect.Option.some(exit.value) : effect.Option.none();
15359
- };
15360
- const isRange = (value) => effect.Option.isSome(parseRange(value));
15361
- const protocolOf = (value) => {
15362
- if (value.startsWith(CATALOG_PREFIX)) return "catalog";
15363
- if (value.startsWith(WORKSPACE_PREFIX)) return "workspace";
15364
- if (value.startsWith("link:")) return "link";
15365
- if (value.startsWith("portal:")) return "portal";
15366
- if (value.startsWith("file:") || isBarePath(value)) return "file";
15367
- if (value.startsWith("npm:")) return "npm";
15368
- if (isGit(value)) return "git";
15369
- if (isUrl$1(value)) return "url";
15370
- if (isRange(value)) return "range";
15371
- if (/^[a-zA-Z][a-zA-Z0-9._-]*$/.test(value)) return "tag";
15372
- return "unknown";
15373
- };
15374
- const isTag = (value) => protocolOf(value) === "tag";
15375
- const catalogNameOf$1 = (specifier) => {
15376
- if (!isCatalog(specifier)) return effect.Option.none();
15377
- const rest = specifier.slice(8).trim();
15378
- return rest.length === 0 ? effect.Option.none() : effect.Option.some(rest);
15379
- };
15380
- const projectRangeModifier = (range, version) => range === "*" || range === "" ? version : range === "~" ? `~${version}` : range === "^" ? `^${version}` : range;
15381
- const splitWorkspaceRest = (rest) => {
15382
- const at = rest.lastIndexOf("@");
15383
- return at > 0 ? {
15384
- target: rest.slice(0, at),
15385
- range: rest.slice(at + 1)
15386
- } : {
15387
- target: void 0,
15388
- range: rest
15389
- };
15390
- };
15391
- const projectWorkspaceRange = (rest, version) => {
15392
- const { target, range } = splitWorkspaceRest(rest);
15393
- const projected = projectRangeModifier(range, version);
15394
- return target === void 0 ? projected : `npm:${target}@${projected}`;
15395
- };
15396
- const resolveWorkspace = (specifier, version) => isWorkspace(specifier) ? projectWorkspaceRange(specifier.slice(10), version) : specifier;
15397
- const workspaceTargetOf = (specifier) => {
15398
- if (!isWorkspace(specifier)) return effect.Option.none();
15399
- const { target } = splitWorkspaceRest(specifier.slice(10));
15400
- return target === void 0 ? effect.Option.none() : effect.Option.some(target);
15401
- };
15402
- /**
15403
- * Whether a string is a recognized dependency specifier: a semver range, exact
15404
- * version, dist-tag, URL, git ref, GitHub shorthand, file path, or an
15405
- * `npm:` / `catalog:` / `workspace:` protocol.
15406
- *
15407
- * @public
15408
- */
15409
- const isValidDependencySpecifier = (value) => value.length > 0 && protocolOf(value) !== "unknown";
15410
- /**
15411
- * A `catalog:` reference. `name` carries the catalog name, or `Option.none()`
15412
- * for the default catalog (`catalog:`).
15413
- *
15414
- * @public
15415
- */
15416
- var CatalogSpecifier = class extends effect.Schema.TaggedClass()("catalog", {
15417
- /** The original specifier string. */
15418
- raw: effect.Schema.String,
15419
- /** The catalog name, or `Option.none()` for the default catalog. */
15420
- name: effect.Schema.Option(effect.Schema.String)
15421
- }) {};
15422
- /**
15423
- * A `workspace:` reference. `range` carries the part after `workspace:` — a
15424
- * range modifier (`*`, `^`, `~`), a concrete range, or an alias form.
15425
- *
15426
- * @public
15427
- */
15428
- var WorkspaceSpecifier = class extends effect.Schema.TaggedClass()("workspace", {
15429
- /** The original specifier string. */
15430
- raw: effect.Schema.String,
15431
- /** The part after `workspace:` (e.g. `*`, `^1.2.3`, or an alias form). */
15432
- range: effect.Schema.String
15288
+ /** Which dependency map this entry came from. */
15289
+ kind: DependencyKind,
15290
+ /** For `peer` dependencies, whether the peer is optional (from `peerDependenciesMeta`). */
15291
+ isOptional: effect.Schema.optionalKey(effect.Schema.Boolean)
15433
15292
  }) {
15434
- /**
15435
- * The pnpm publish-time projection of this specifier against a concrete
15436
- * workspace version: `*` (or an empty range) becomes `version`, `~` becomes
15437
- * `~version`, `^` becomes `^version`, and a pinned range passes through
15438
- * unchanged. The alias form (`workspace:<name>@<range>`) becomes pnpm's
15439
- * publish-time aliased dependency `npm:<name>@<projected>`, with the range
15440
- * modifier projected the same way — `version` must then be the TARGET
15441
- * package's version (see `DependencySpecifier.workspaceTargetOf`).
15442
- *
15443
- * @remarks
15444
- * The same projection as `DependencySpecifier.resolveWorkspace`, applied to
15445
- * this instance's already-extracted `range`; the two share one internal
15446
- * implementation.
15447
- *
15448
- * @param version - The concrete version of the workspace package the
15449
- * specifier points at (the alias target's version for the alias form).
15450
- */
15451
- resolve(version) {
15452
- return projectWorkspaceRange(this.range, version);
15293
+ /** The classified protocol, or `None` for an empty specifier. */
15294
+ get protocol() {
15295
+ return this.specifier.length === 0 ? effect.Option.none() : effect.Option.some(DependencySpecifier.protocolOf(this.specifier));
15296
+ }
15297
+ /** Parse the specifier as a semver `Range`, `None` when it is not a range. */
15298
+ get range() {
15299
+ return DependencySpecifier.parseRange(this.specifier);
15300
+ }
15301
+ /** Whether the specifier points to a local path. */
15302
+ get isLocal() {
15303
+ return DependencySpecifier.isLocal(this.specifier);
15304
+ }
15305
+ /** Whether the specifier uses the `link:` protocol. */
15306
+ get isLink() {
15307
+ return DependencySpecifier.isLink(this.specifier);
15308
+ }
15309
+ /** Whether the specifier uses the `portal:` protocol. */
15310
+ get isPortal() {
15311
+ return DependencySpecifier.isPortal(this.specifier);
15312
+ }
15313
+ /** Whether the specifier uses the `catalog:` protocol. */
15314
+ get isCatalog() {
15315
+ return DependencySpecifier.isCatalog(this.specifier);
15316
+ }
15317
+ /** Whether the specifier uses the `workspace:` protocol. */
15318
+ get isWorkspace() {
15319
+ return DependencySpecifier.isWorkspace(this.specifier);
15320
+ }
15321
+ /** Whether the specifier is an unresolved `catalog:` or `workspace:` protocol. */
15322
+ get isUnresolved() {
15323
+ return this.isCatalog || this.isWorkspace;
15324
+ }
15325
+ /** Whether the specifier resolves to a git source. */
15326
+ get isGit() {
15327
+ return DependencySpecifier.isGit(this.specifier);
15328
+ }
15329
+ /** Whether the specifier is a parseable semver range. */
15330
+ get isRange() {
15331
+ return DependencySpecifier.isRange(this.specifier);
15332
+ }
15333
+ /** Whether the specifier is a dist-tag. */
15334
+ get isTag() {
15335
+ return DependencySpecifier.isTag(this.specifier);
15453
15336
  }
15454
15337
  };
15338
+ //#endregion
15339
+ //#region ../../node_modules/.pnpm/@effected+package-json@0.7.3_effect@4.0.0-beta.101/node_modules/@effected/package-json/DevEngines.js
15455
15340
  /**
15456
- * A plain semver range or exact version (e.g. `^1.2.3`, `1.x`, `>=1 <2`).
15457
- *
15458
- * @public
15459
- */
15460
- var RangeSpecifier = class extends effect.Schema.TaggedClass()("range", {
15461
- /** The original specifier string. */
15462
- raw: effect.Schema.String }) {};
15463
- /**
15464
- * A bare dist-tag (e.g. `latest`, `next`).
15341
+ * A single `devEngines` constraint with a name and optional `version` / `onFail`.
15465
15342
  *
15466
15343
  * @public
15467
15344
  */
15468
- var DistTagSpecifier = class extends effect.Schema.TaggedClass()("dist-tag", {
15469
- /** The original specifier string (also the tag name). */
15470
- raw: effect.Schema.String }) {};
15345
+ var DevEngine = class extends effect.Schema.Class("DevEngine")({
15346
+ /** The engine name (e.g. `node`, `pnpm`). */
15347
+ name: effect.Schema.String,
15348
+ /** The optional version constraint. */
15349
+ version: effect.Schema.optionalKey(effect.Schema.String),
15350
+ /** The optional behavior when the constraint is unmet. */
15351
+ onFail: effect.Schema.optionalKey(effect.Schema.Literals([
15352
+ "warn",
15353
+ "error",
15354
+ "ignore"
15355
+ ]))
15356
+ }) {};
15471
15357
  /**
15472
- * The honest fallback for `file:` / `link:` / `portal:` / git / URL / `npm:`
15473
- * forms this concept does not further interpret.
15358
+ * A `devEngines` constraint slot: a single {@link DevEngine} or an array of them.
15474
15359
  *
15475
15360
  * @public
15476
15361
  */
15477
- var RawSpecifier = class extends effect.Schema.TaggedClass()("raw", {
15478
- /** The original specifier string. */
15479
- raw: effect.Schema.String }) {};
15480
- const Classified = effect.Schema.Union([
15481
- CatalogSpecifier,
15482
- WorkspaceSpecifier,
15483
- RangeSpecifier,
15484
- DistTagSpecifier,
15485
- RawSpecifier
15486
- ]);
15487
- const classify$1 = (value) => {
15488
- if (isCatalog(value)) return CatalogSpecifier.make({
15489
- raw: value,
15490
- name: catalogNameOf$1(value)
15491
- });
15492
- if (isWorkspace(value)) return WorkspaceSpecifier.make({
15493
- raw: value,
15494
- range: value.slice(10)
15495
- });
15496
- if (isRange(value)) return RangeSpecifier.make({ raw: value });
15497
- if (isTag(value)) return DistTagSpecifier.make({ raw: value });
15498
- return RawSpecifier.make({ raw: value });
15499
- };
15500
- const fromString = effect.Schema.String.pipe(effect.Schema.decodeTo(Classified, effect.SchemaTransformation.transformOrFail({
15501
- decode: (input) => isValidDependencySpecifier(input) ? effect.Effect.succeed(classify$1(input)) : effect.Effect.fail(new effect.SchemaIssue.InvalidValue(effect.Option.some(input), { message: `Invalid dependency specifier: "${input}"` })),
15502
- encode: (classified) => effect.Effect.succeed(classified.raw)
15503
- })));
15504
- const brandedSpecifier = effect.Schema.String.pipe(effect.Schema.check(effect.Schema.makeFilter((value) => isValidDependencySpecifier(value) ? void 0 : "Expected a valid dependency specifier")), effect.Schema.brand("DependencySpecifier"));
15505
- const decode$3 = (input) => effect.Schema.decodeUnknownEffect(brandedSpecifier)(input).pipe(effect.Effect.mapError(() => new InvalidDependencySpecifierError({ input })));
15362
+ const DevEngineOrArray = effect.Schema.Union([DevEngine, effect.Schema.Array(DevEngine)]);
15506
15363
  /**
15507
- * A valid dependency version specifier, carrying the protocol taxonomy statics
15508
- * (`DependencySpecifier.protocolOf` and friends) that classify any specifier
15509
- * string, plus the {@link (DependencySpecifier:variable).FromString} codec that
15510
- * decodes a string into a {@link ClassifiedSpecifier} tagged union. Use it as a
15511
- * schema for a specifier field and reach for the statics to inspect a raw
15512
- * string.
15513
- *
15514
- * @public
15515
- */
15516
- const DependencySpecifier = Object.assign(brandedSpecifier, {
15517
- protocolOf,
15518
- parseRange,
15519
- isRange,
15520
- isTag,
15521
- isGit,
15522
- isUrl: isUrl$1,
15523
- isLocal,
15524
- isLink,
15525
- isPortal,
15526
- isCatalog,
15527
- isWorkspace,
15528
- catalogNameOf: catalogNameOf$1,
15529
- resolveWorkspace,
15530
- workspaceTargetOf,
15531
- isValid: isValidDependencySpecifier,
15532
- decode: decode$3,
15533
- FromString: fromString
15534
- });
15535
- //#endregion
15536
- //#region ../../node_modules/.pnpm/@effected+npm@0.8.2_@effected+semver@0.3.2_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/npm/IntegrityHash.js
15537
- const SRI_RE = /^(sha1|sha256|sha384|sha512)-[A-Za-z0-9+/]+={0,2}$/;
15538
- const COREPACK_RE = /^(sha1|sha224|sha256|sha384|sha512)\.[0-9a-f]+$/;
15539
- const YARN_RE = /^[0-9]+(c[0-9]+)?\/[0-9a-f]+$/;
15540
- const isSri = (value) => SRI_RE.test(value);
15541
- const isCorepack = (value) => COREPACK_RE.test(value);
15542
- const isYarnChecksum = (value) => YARN_RE.test(value);
15543
- /**
15544
- * Whether a string is a valid integrity hash in the SRI (`<algo>-<base64>`),
15545
- * corepack (`<algo>.<hex>`) or yarn (`<cachekey>/<hex>`) form.
15546
- *
15547
- * @public
15548
- */
15549
- const isValidIntegrityHash = (value) => isSri(value) || isCorepack(value) || isYarnChecksum(value);
15550
- const algorithmOf = (value) => {
15551
- if (isSri(value)) return effect.Option.some(value.slice(0, value.indexOf("-")));
15552
- if (isCorepack(value)) return effect.Option.some(value.slice(0, value.indexOf(".")));
15553
- return effect.Option.none();
15554
- };
15555
- /**
15556
- * Indicates that a string could not be parsed as a valid integrity hash.
15557
- *
15558
- * Raised by {@link IntegrityHash.decode}. The offending string is preserved on
15559
- * `input`.
15560
- *
15561
- * @public
15562
- */
15563
- var InvalidIntegrityHashError = class extends effect.Schema.TaggedErrorClass()("InvalidIntegrityHashError", {
15564
- /** The raw input string that failed validation. */
15565
- input: effect.Schema.String }) {
15566
- get message() {
15567
- return `Invalid integrity hash "${this.input}": expected an SRI (<algo>-<base64>), corepack (<algo>.<hex>) or yarn (<cachekey>/<hex>) form`;
15568
- }
15569
- };
15570
- const brandedIntegrity = effect.Schema.String.pipe(effect.Schema.check(effect.Schema.makeFilter((value) => isValidIntegrityHash(value) ? void 0 : "Expected an SRI, corepack or yarn integrity hash")), effect.Schema.brand("IntegrityHash"));
15571
- const decode$2 = (input) => effect.Schema.decodeUnknownEffect(brandedIntegrity)(input).pipe(effect.Effect.mapError(() => new InvalidIntegrityHashError({ input })));
15572
- Object.assign(brandedIntegrity, {
15573
- isSri,
15574
- isCorepack,
15575
- isYarnChecksum,
15576
- isValid: isValidIntegrityHash,
15577
- algorithmOf,
15578
- decode: decode$2
15579
- });
15580
- /**
15581
- * {@link (IntegrityHash:variable)} narrowed to the corepack `<algo>.<hex>` form
15582
- * — `sha512.deadbeef`, and corepack's own sha224 default pins
15583
- * (`sha224.877304e3…`). An SRI (`sha512-<base64>`) or yarn (`10c0/<hex>`)
15584
- * hash, both valid `IntegrityHash` values, fails this schema.
15585
- *
15586
- * @remarks
15587
- * The corepack pin tail (`<name>@<version>+<integrity>`) is the one place the
15588
- * kit meets this form, and two schemas name it: `PackageManagerPin.integrity`
15589
- * here and `@effected/package-json`'s `PackageManager.integrity`. Both consume
15590
- * **this** schema — the restriction existed privately in each module until they
15591
- * were consolidated, and a private copy is exactly how the two drift (the
15592
- * widening that admitted sha224 had to be made twice).
15593
- *
15594
- * It decodes to the same {@link IntegrityHashBrand} the unrestricted schema
15595
- * does, so a corepack-validated value assigns anywhere an `IntegrityHash` is
15596
- * expected; there is no second brand. Reach for
15597
- * `IntegrityHash.isCorepack(value)` to ask the same question about a raw
15598
- * string without decoding.
15599
- *
15600
- * That single brand is also why sharing this schema is not type-enforced, and
15601
- * the consequence is sharper than it looks: a `Schema.check` is **erased from
15602
- * the built type**, so this schema and the unrestricted one are the same
15603
- * declared type. A consumer that quietly reverts to a private copy compiles
15604
- * clean, and — if the copy is faithful — passes every rejection test too.
15605
- * Neither `tsc` nor behaviour can see the re-fork.
15606
- *
15607
- * What does see it is **object identity**, so each consumer's suite asserts
15608
- * that its field schema IS this export:
15609
- * `PackageManagerPin.fields.integrity.schema === CorepackIntegrityHash` (an
15610
- * `optionalKey` field keeps the inner schema on `.schema`), and
15611
- * `PackageManager.fields.integrity.value === CorepackIntegrityHash` on the
15612
- * `@effected/package-json` side (a `Schema.Option` keeps it on `.value`). Both
15613
- * assertions carry a control against the unrestricted brand, so they discriminate
15614
- * rather than passing on any schema at all. That identity assertion is the only
15615
- * thing standing between the two surfaces and a silent re-fork; do not replace
15616
- * it with a behavioural test, which cannot fail.
15617
- *
15618
- * @example
15619
- * ```ts
15620
- * import { CorepackIntegrityHash } from "@effected/npm";
15621
- * import { Schema } from "effect";
15622
- *
15623
- * const decode = Schema.decodeUnknownExit(CorepackIntegrityHash);
15624
- *
15625
- * decode("sha512.deadbeef"); // success
15626
- * decode("sha512-3q2+7w=="); // failure — SRI form
15627
- * ```
15628
- *
15629
- * @public
15630
- */
15631
- const CorepackIntegrityHash = brandedIntegrity.pipe(effect.Schema.check(effect.Schema.makeFilter((value) => isCorepack(value) ? void 0 : "Expected a corepack (<algo>.<hex>) integrity hash")));
15632
- //#endregion
15633
- //#region ../../node_modules/.pnpm/@effected+package-json@0.7.3_effect@4.0.0-beta.101/node_modules/@effected/package-json/Dependency.js
15634
- /**
15635
- * A resolved dependency entry pairing a package name with its version
15636
- * specifier and the `kind` of map it came from (`@effected/npm`'s
15637
- * `DependencyKind`). The protocol predicates delegate to `DependencySpecifier`.
15638
- *
15639
- * @public
15640
- */
15641
- var Dependency = class extends effect.Schema.Class("Dependency")({
15642
- /** The package name. */
15643
- name: effect.Schema.String,
15644
- /** The raw version specifier. */
15645
- specifier: effect.Schema.String,
15646
- /** Which dependency map this entry came from. */
15647
- kind: DependencyKind,
15648
- /** For `peer` dependencies, whether the peer is optional (from `peerDependenciesMeta`). */
15649
- isOptional: effect.Schema.optionalKey(effect.Schema.Boolean)
15650
- }) {
15651
- /** The classified protocol, or `None` for an empty specifier. */
15652
- get protocol() {
15653
- return this.specifier.length === 0 ? effect.Option.none() : effect.Option.some(DependencySpecifier.protocolOf(this.specifier));
15654
- }
15655
- /** Parse the specifier as a semver `Range`, `None` when it is not a range. */
15656
- get range() {
15657
- return DependencySpecifier.parseRange(this.specifier);
15658
- }
15659
- /** Whether the specifier points to a local path. */
15660
- get isLocal() {
15661
- return DependencySpecifier.isLocal(this.specifier);
15662
- }
15663
- /** Whether the specifier uses the `link:` protocol. */
15664
- get isLink() {
15665
- return DependencySpecifier.isLink(this.specifier);
15666
- }
15667
- /** Whether the specifier uses the `portal:` protocol. */
15668
- get isPortal() {
15669
- return DependencySpecifier.isPortal(this.specifier);
15670
- }
15671
- /** Whether the specifier uses the `catalog:` protocol. */
15672
- get isCatalog() {
15673
- return DependencySpecifier.isCatalog(this.specifier);
15674
- }
15675
- /** Whether the specifier uses the `workspace:` protocol. */
15676
- get isWorkspace() {
15677
- return DependencySpecifier.isWorkspace(this.specifier);
15678
- }
15679
- /** Whether the specifier is an unresolved `catalog:` or `workspace:` protocol. */
15680
- get isUnresolved() {
15681
- return this.isCatalog || this.isWorkspace;
15682
- }
15683
- /** Whether the specifier resolves to a git source. */
15684
- get isGit() {
15685
- return DependencySpecifier.isGit(this.specifier);
15686
- }
15687
- /** Whether the specifier is a parseable semver range. */
15688
- get isRange() {
15689
- return DependencySpecifier.isRange(this.specifier);
15690
- }
15691
- /** Whether the specifier is a dist-tag. */
15692
- get isTag() {
15693
- return DependencySpecifier.isTag(this.specifier);
15694
- }
15695
- };
15696
- //#endregion
15697
- //#region ../../node_modules/.pnpm/@effected+package-json@0.7.3_effect@4.0.0-beta.101/node_modules/@effected/package-json/DevEngines.js
15698
- /**
15699
- * A single `devEngines` constraint with a name and optional `version` / `onFail`.
15700
- *
15701
- * @public
15702
- */
15703
- var DevEngine = class extends effect.Schema.Class("DevEngine")({
15704
- /** The engine name (e.g. `node`, `pnpm`). */
15705
- name: effect.Schema.String,
15706
- /** The optional version constraint. */
15707
- version: effect.Schema.optionalKey(effect.Schema.String),
15708
- /** The optional behavior when the constraint is unmet. */
15709
- onFail: effect.Schema.optionalKey(effect.Schema.Literals([
15710
- "warn",
15711
- "error",
15712
- "ignore"
15713
- ]))
15714
- }) {};
15715
- /**
15716
- * A `devEngines` constraint slot: a single {@link DevEngine} or an array of them.
15717
- *
15718
- * @public
15719
- */
15720
- const DevEngineOrArray = effect.Schema.Union([DevEngine, effect.Schema.Array(DevEngine)]);
15721
- /**
15722
- * The `devEngines` field schema, modeling runtime and package-manager
15723
- * constraints as optional {@link DevEngine} slots.
15364
+ * The `devEngines` field schema, modeling runtime and package-manager
15365
+ * constraints as optional {@link DevEngine} slots.
15724
15366
  *
15725
15367
  * @public
15726
15368
  */
@@ -18313,7 +17955,7 @@ var Package = class Package extends effect.Schema.Class("Package")({
18313
17955
  }
18314
17956
  };
18315
17957
  //#endregion
18316
- //#region ../../node_modules/.pnpm/@effected+workspaces@0.10.0_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/WorkspacePackage.js
17958
+ //#region ../../node_modules/.pnpm/@effected+workspaces@0.10.2_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__@effected+semv_feff9e309e6abeafa28f7ea259b8a9bf/node_modules/@effected/workspaces/WorkspacePackage.js
18317
17959
  const EMPTY$1 = Object.freeze(Object.create(null));
18318
17960
  const EMPTY_MANIFEST = Object.freeze(Object.create(null));
18319
17961
  /**
@@ -18911,7 +18553,7 @@ var Walker$1 = class {
18911
18553
  static findRoot = findRoot$1;
18912
18554
  };
18913
18555
  //#endregion
18914
- //#region ../../node_modules/.pnpm/@effected+workspaces@0.10.0_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/WorkspaceRoot.js
18556
+ //#region ../../node_modules/.pnpm/@effected+workspaces@0.10.2_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__@effected+semv_feff9e309e6abeafa28f7ea259b8a9bf/node_modules/@effected/workspaces/WorkspaceRoot.js
18915
18557
  /**
18916
18558
  * The marker filenames {@link WorkspaceRoot} probes for, in priority order.
18917
18559
  *
@@ -19098,7 +18740,7 @@ var WorkspaceRoot = class WorkspaceRoot extends effect.Context.Service()("@effec
19098
18740
  static layerTest = (root) => effect.Layer.effect(WorkspaceRoot, WorkspaceRoot.makeTest(root)).pipe(effect.Layer.provide(effect.Path.layer));
19099
18741
  };
19100
18742
  //#endregion
19101
- //#region ../../node_modules/.pnpm/@effected+workspaces@0.10.0_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/internal/limits.js
18743
+ //#region ../../node_modules/.pnpm/@effected+workspaces@0.10.2_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__@effected+semv_feff9e309e6abeafa28f7ea259b8a9bf/node_modules/@effected/workspaces/internal/limits.js
19102
18744
  /**
19103
18745
  * Hard ceiling on directories the enumerator will visit for one pattern set.
19104
18746
  * Guards the pathological case a depth cap alone does not: a wide, shallow
@@ -19116,7 +18758,7 @@ const MAX_ENUMERATION_ENTRIES = 1e5;
19116
18758
  */
19117
18759
  const PRUNED_DIRECTORIES = /* @__PURE__ */ new Set([".git", "node_modules"]);
19118
18760
  //#endregion
19119
- //#region ../../node_modules/.pnpm/@effected+workspaces@0.10.0_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/internal/traverse.js
18761
+ //#region ../../node_modules/.pnpm/@effected+workspaces@0.10.2_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__@effected+semv_feff9e309e6abeafa28f7ea259b8a9bf/node_modules/@effected/workspaces/internal/traverse.js
19120
18762
  /** Directory names never descended into. */
19121
18763
  const isPruned = (entry) => PRUNED_DIRECTORIES.has(entry);
19122
18764
  /** Join root-relative POSIX segments; `""` is the root itself. */
@@ -19206,7 +18848,7 @@ var Traversal = class {
19206
18848
  }
19207
18849
  };
19208
18850
  //#endregion
19209
- //#region ../../node_modules/.pnpm/@effected+workspaces@0.10.0_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/internal/enumerate.js
18851
+ //#region ../../node_modules/.pnpm/@effected+workspaces@0.10.2_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__@effected+semv_feff9e309e6abeafa28f7ea259b8a9bf/node_modules/@effected/workspaces/internal/enumerate.js
19210
18852
  /** Strip a trailing slash from `GlobPattern.enumerationPrefix` to get a relative directory. */
19211
18853
  const baseOf = (pattern) => pattern.enumerationPrefix.replace(/\/$/, "");
19212
18854
  /**
@@ -19276,7 +18918,7 @@ const enumerate = (root, globs, options) => effect.Effect.gen(function* () {
19276
18918
  return results;
19277
18919
  });
19278
18920
  //#endregion
19279
- //#region ../../node_modules/.pnpm/@effected+workspaces@0.10.0_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/internal/patterns.js
18921
+ //#region ../../node_modules/.pnpm/@effected+workspaces@0.10.2_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__@effected+semv_feff9e309e6abeafa28f7ea259b8a9bf/node_modules/@effected/workspaces/internal/patterns.js
19280
18922
  const stringsOf = (value) => Array.isArray(value) ? value.filter((entry) => typeof entry === "string") : void 0;
19281
18923
  /** The `packages:` list of a `pnpm-workspace.yaml` document. Total on a parsed document. */
19282
18924
  const pnpmPatternsOf = (document) => {
@@ -19333,7 +18975,7 @@ const readPatterns = (root) => effect.Effect.gen(function* () {
19333
18975
  return manifestPatternsOf(manifest);
19334
18976
  });
19335
18977
  //#endregion
19336
- //#region ../../node_modules/.pnpm/@effected+workspaces@0.10.0_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/WorkspaceDiscovery.js
18978
+ //#region ../../node_modules/.pnpm/@effected+workspaces@0.10.2_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__@effected+semv_feff9e309e6abeafa28f7ea259b8a9bf/node_modules/@effected/workspaces/WorkspaceDiscovery.js
19337
18979
  /**
19338
18980
  * Raised when a workspace member's `package.json` cannot be read, parsed, or
19339
18981
  * used — it is missing, malformed, or lacks a `name` or `version`.
@@ -19770,7 +19412,7 @@ var WorkspaceDiscovery = class WorkspaceDiscovery extends effect.Context.Service
19770
19412
  * // `Package.resolve` now resolves `workspace:*` for real.
19771
19413
  * ```
19772
19414
  */
19773
- static workspaceResolver = effect.Layer.effect(WorkspaceResolver$1, effect.Effect.gen(function* () {
19415
+ static workspaceResolver = effect.Layer.effect(WorkspaceResolver, effect.Effect.gen(function* () {
19774
19416
  const discovery = yield* WorkspaceDiscovery;
19775
19417
  const versionIndexes = /* @__PURE__ */ new WeakMap();
19776
19418
  const versionsByName = (all) => {
@@ -19781,7 +19423,7 @@ var WorkspaceDiscovery = class WorkspaceDiscovery extends effect.Context.Service
19781
19423
  versionIndexes.set(all, index);
19782
19424
  return index;
19783
19425
  };
19784
- return { versionOf: (packageName) => discovery.listPackages().pipe(effect.Effect.map((all) => effect.Option.fromUndefinedOr(versionsByName(all).get(packageName))), effect.Effect.mapError((cause) => new DependencyResolutionError$1({
19426
+ return { versionOf: (packageName) => discovery.listPackages().pipe(effect.Effect.map((all) => effect.Option.fromUndefinedOr(versionsByName(all).get(packageName))), effect.Effect.mapError((cause) => new DependencyResolutionError({
19785
19427
  specifier: `workspace:${packageName}`,
19786
19428
  cause
19787
19429
  }))) };
@@ -19789,7 +19431,7 @@ var WorkspaceDiscovery = class WorkspaceDiscovery extends effect.Context.Service
19789
19431
  };
19790
19432
  const isStringRecord$2 = (value) => value !== null && typeof value === "object" && !Array.isArray(value) && Object.values(value).every((entry) => typeof entry === "string");
19791
19433
  //#endregion
19792
- //#region ../../node_modules/.pnpm/@effected+workspaces@0.10.0_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/DependencyGraph.js
19434
+ //#region ../../node_modules/.pnpm/@effected+workspaces@0.10.2_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__@effected+semv_feff9e309e6abeafa28f7ea259b8a9bf/node_modules/@effected/workspaces/DependencyGraph.js
19793
19435
  /**
19794
19436
  * Raised when the workspace dependency graph cannot be topologically ordered
19795
19437
  * because it contains a cycle.
@@ -20022,10 +19664,32 @@ const kahn = (edges) => {
20022
19664
  };
20023
19665
  };
20024
19666
  //#endregion
20025
- //#region ../../node_modules/.pnpm/@effected+git@0.5.2_effect@4.0.0-beta.101/node_modules/@effected/git/GitCommand.js
19667
+ //#region ../../node_modules/.pnpm/@effected+git@0.6.0_effect@4.0.0-beta.101/node_modules/@effected/git/GitCommand.js
19668
+ /** The mask every whole-value sensitive positional is replaced with. */
19669
+ const REDACTED = "<redacted>";
19670
+ const secretValue = (value) => ({
19671
+ redact: "value",
19672
+ value
19673
+ });
19674
+ const secretUrl = (value) => ({
19675
+ redact: "url",
19676
+ value
19677
+ });
20026
19678
  /**
20027
- * Builds a `git` `ChildProcess.StandardCommand` with the argv this package
20028
- * classifies against.
19679
+ * Masks the userinfo component of a URL (`scheme://user:token@host/...`
19680
+ * `scheme://<redacted>@host/...`). A value carrying no embedded userinfo — a
19681
+ * remote name, a credential-free URL, an scp-style `host:path` — passes
19682
+ * through untouched, so the common case stays fully debuggable.
19683
+ *
19684
+ * The userinfo match is greedy (`[^/]*@` — everything through the LAST `@`
19685
+ * before the first path slash): URL authorities split at the last `@`, so a
19686
+ * password containing a literal `@` (`user:p\@ss\@host/...`) must be
19687
+ * consumed whole or its tail would survive into `redactedArgs`.
19688
+ */
19689
+ const redactUrlUserinfo = (value) => value.replace(/^([a-z][a-z0-9+.-]*:\/\/)[^/]*@/i, `$1${REDACTED}@`);
19690
+ /**
19691
+ * Builds a `git` {@link GitInvocation} with the argv this package classifies
19692
+ * against.
20029
19693
  *
20030
19694
  * @remarks
20031
19695
  * `LC_ALL=C` is pinned on every invocation because git's stderr
@@ -20041,10 +19705,18 @@ const kahn = (edges) => {
20041
19705
  * the working directory per invocation via `ChildProcess.setCwd`, which
20042
19706
  * returns a new command and leaves this one unchanged.
20043
19707
  */
20044
- const git = (args) => effect_unstable_process.ChildProcess.make("git", args, {
20045
- env: { LC_ALL: "C" },
20046
- extendEnv: true
20047
- });
19708
+ const git = (args, stdin) => {
19709
+ const raw = args.map((arg) => typeof arg === "string" ? arg : arg.value);
19710
+ const redactedArgs = args.map((arg) => typeof arg === "string" ? arg : arg.redact === "value" ? REDACTED : redactUrlUserinfo(arg.value));
19711
+ return {
19712
+ command: effect_unstable_process.ChildProcess.make("git", raw, {
19713
+ env: { LC_ALL: "C" },
19714
+ extendEnv: true,
19715
+ ...stdin !== void 0 ? { stdin: effect.Stream.make(new TextEncoder().encode(stdin)) } : {}
19716
+ }),
19717
+ redactedArgs
19718
+ };
19719
+ };
20048
19720
  const show = (ref, path) => git(["show", `${ref}:${path}`]);
20049
19721
  const lsTree = (ref, pathspec = []) => git([
20050
19722
  "ls-tree",
@@ -20103,7 +19775,7 @@ const checkout = (ref, detach = false) => git([
20103
19775
  const fetch$1 = (remote, ref, depth, tag = false) => git([
20104
19776
  "fetch",
20105
19777
  ...depth !== void 0 ? ["--depth", String(depth)] : [],
20106
- remote,
19778
+ secretUrl(remote),
20107
19779
  ...tag ? ["tag"] : [],
20108
19780
  ref
20109
19781
  ]);
@@ -20119,7 +19791,7 @@ const submoduleAdd = (url, path, depth) => git([
20119
19791
  "add",
20120
19792
  ...depth !== void 0 ? ["--depth", String(depth)] : [],
20121
19793
  "--",
20122
- url,
19794
+ secretUrl(url),
20123
19795
  path
20124
19796
  ]);
20125
19797
  const sparseCheckoutSet = (patterns, cone) => git([
@@ -20132,13 +19804,55 @@ const configSet = (key, value, file) => git([
20132
19804
  "config",
20133
19805
  ...file !== void 0 ? ["-f", file] : [],
20134
19806
  key,
20135
- value
19807
+ secretValue(value)
20136
19808
  ]);
20137
19809
  const add = (paths) => git([
20138
19810
  "add",
20139
19811
  "--",
20140
19812
  ...paths
20141
19813
  ]);
19814
+ const reset = (mode = "mixed", ref) => git([
19815
+ "reset",
19816
+ `--${mode}`,
19817
+ ...ref !== void 0 ? [ref] : []
19818
+ ]);
19819
+ const clean = (directories = false, ignored = false, paths = []) => git([
19820
+ "clean",
19821
+ "--force",
19822
+ ...directories ? ["-d"] : [],
19823
+ ...ignored ? ["-x"] : [],
19824
+ ...paths.length > 0 ? ["--", ...paths] : []
19825
+ ]);
19826
+ const restore = (paths, source, staged = false, worktree = false) => git([
19827
+ "restore",
19828
+ ...source !== void 0 ? ["--source", source] : [],
19829
+ ...staged ? ["--staged"] : [],
19830
+ ...worktree ? ["--worktree"] : [],
19831
+ "--",
19832
+ ...paths
19833
+ ]);
19834
+ const branchCreate = (name, startPoint, checkout = false, force = false) => checkout ? git([
19835
+ "checkout",
19836
+ force ? "-B" : "-b",
19837
+ name,
19838
+ ...startPoint !== void 0 ? [startPoint] : []
19839
+ ]) : git([
19840
+ "branch",
19841
+ ...force ? ["-f"] : [],
19842
+ name,
19843
+ ...startPoint !== void 0 ? [startPoint] : []
19844
+ ]);
19845
+ const branchDelete = (name, force = false) => git([
19846
+ "branch",
19847
+ force ? "-D" : "-d",
19848
+ name
19849
+ ]);
19850
+ const isShallow = () => git(["rev-parse", "--is-shallow-repository"]);
19851
+ const fetchUnshallow = (remote = "origin") => git([
19852
+ "fetch",
19853
+ "--unshallow",
19854
+ secretUrl(remote)
19855
+ ]);
20142
19856
  const nameStatus = (base, head, relative = false) => git([
20143
19857
  "diff",
20144
19858
  "--name-status",
@@ -20179,37 +19893,273 @@ const status = () => git([
20179
19893
  "--porcelain",
20180
19894
  "-z"
20181
19895
  ]);
20182
- /**
20183
- * Pure constructors for the `git` `ChildProcess.Command` values this package
20184
- * spawns.
20185
- *
20186
- * @remarks
20187
- * Every constructor returns a cwd-less, argv-only `Command` — no spawning,
20188
- * no working directory baked in. `Git` applies the working directory per
20189
- * call with `ChildProcess.setCwd` and owns the actual spawn, timeout, and
20190
- * error classification.
20191
- *
20192
- * @public
20193
- */
20194
- var GitCommand = class {
20195
- constructor() {}
20196
- /**
20197
- * `git show <ref>:<path>` the contents of `path` as it existed at `ref`,
20198
- * without checking anything out.
20199
- */
20200
- static show = show;
20201
- /**
20202
- * `git ls-tree -r -z <ref> [-- <pathspec>...]` every path in the tree at
20203
- * `ref`, recursively, NUL-terminated, optionally scoped to `pathspec`.
20204
- *
20205
- * @remarks
20206
- * `-z` is load-bearing: git paths may themselves contain newlines, so the
20207
- * caller must split on `"\0"`, never on `"\n"`. When `pathspec` is provided,
20208
- * a literal `--` separator is inserted before the pathspec entries to prevent
20209
- * git from interpreting pathspec values as options.
20210
- */
20211
- static lsTree = lsTree;
20212
- /**
19896
+ const submoduleStatus = (paths = [], recursive = false) => git([
19897
+ "submodule",
19898
+ "status",
19899
+ ...recursive ? ["--recursive"] : [],
19900
+ ...paths.length > 0 ? ["--", ...paths] : []
19901
+ ]);
19902
+ const submoduleInit = (paths = []) => git([
19903
+ "submodule",
19904
+ "init",
19905
+ ...paths.length > 0 ? ["--", ...paths] : []
19906
+ ]);
19907
+ const submoduleDeinit = (paths, all = false, force = false) => git([
19908
+ "submodule",
19909
+ "deinit",
19910
+ ...force ? ["--force"] : [],
19911
+ ...all ? ["--all"] : ["--", ...paths]
19912
+ ]);
19913
+ const submoduleSync = (paths = [], recursive = false) => git([
19914
+ "submodule",
19915
+ "sync",
19916
+ ...recursive ? ["--recursive"] : [],
19917
+ ...paths.length > 0 ? ["--", ...paths] : []
19918
+ ]);
19919
+ const submoduleSetUrl = (path, url) => git([
19920
+ "submodule",
19921
+ "set-url",
19922
+ "--",
19923
+ path,
19924
+ secretUrl(url)
19925
+ ]);
19926
+ const submoduleSetBranch = (path, branch) => git([
19927
+ "submodule",
19928
+ "set-branch",
19929
+ ...branch === void 0 ? ["--default"] : ["--branch", branch],
19930
+ "--",
19931
+ path
19932
+ ]);
19933
+ const submoduleAbsorbgitdirs = (paths = []) => git([
19934
+ "submodule",
19935
+ "absorbgitdirs",
19936
+ ...paths.length > 0 ? ["--", ...paths] : []
19937
+ ]);
19938
+ const submoduleForeach = (command, recursive = false) => git([
19939
+ "submodule",
19940
+ "foreach",
19941
+ ...recursive ? ["--recursive"] : [],
19942
+ command
19943
+ ]);
19944
+ const lsRemote = (remote, heads = false, tags = false, patterns = []) => git([
19945
+ "ls-remote",
19946
+ ...heads ? ["--heads"] : [],
19947
+ ...tags ? ["--tags"] : [],
19948
+ secretUrl(remote),
19949
+ ...patterns
19950
+ ]);
19951
+ const remoteAdd = (name, url) => git([
19952
+ "remote",
19953
+ "add",
19954
+ name,
19955
+ secretUrl(url)
19956
+ ]);
19957
+ const remoteRemove = (name) => git([
19958
+ "remote",
19959
+ "remove",
19960
+ name
19961
+ ]);
19962
+ const remoteSetUrl = (name, url) => git([
19963
+ "remote",
19964
+ "set-url",
19965
+ name,
19966
+ secretUrl(url)
19967
+ ]);
19968
+ const stashRef = (index) => `stash@{${index}}`;
19969
+ const stashPush = (message, includeUntracked = false, paths = []) => git([
19970
+ "stash",
19971
+ "push",
19972
+ ...includeUntracked ? ["--include-untracked"] : [],
19973
+ ...message !== void 0 ? ["-m", message] : [],
19974
+ ...paths.length > 0 ? ["--", ...paths] : []
19975
+ ]);
19976
+ const stashPop = (index) => git([
19977
+ "stash",
19978
+ "pop",
19979
+ ...index !== void 0 ? [stashRef(index)] : []
19980
+ ]);
19981
+ const stashApply = (index) => git([
19982
+ "stash",
19983
+ "apply",
19984
+ ...index !== void 0 ? [stashRef(index)] : []
19985
+ ]);
19986
+ const stashDrop = (index) => git([
19987
+ "stash",
19988
+ "drop",
19989
+ ...index !== void 0 ? [stashRef(index)] : []
19990
+ ]);
19991
+ const stashList = () => git([
19992
+ "stash",
19993
+ "list",
19994
+ "-z",
19995
+ "--format=%gd%x1f%H%x1f%gs"
19996
+ ]);
19997
+ const branchList = (remotes = false, all = false) => git([
19998
+ "branch",
19999
+ "--list",
20000
+ ...all ? ["--all"] : remotes ? ["--remotes"] : [],
20001
+ "--format=%(HEAD)%00%(refname:short)%00%(objectname)"
20002
+ ]);
20003
+ const tagCreate = (name, ref, message, force = false) => git([
20004
+ "tag",
20005
+ ...force ? ["--force"] : [],
20006
+ ...message !== void 0 ? ["-m", message] : [],
20007
+ name,
20008
+ ...ref !== void 0 ? [ref] : []
20009
+ ]);
20010
+ const tagDelete = (name) => git([
20011
+ "tag",
20012
+ "--delete",
20013
+ name
20014
+ ]);
20015
+ const tagList = (pattern) => git([
20016
+ "tag",
20017
+ "--list",
20018
+ ...pattern !== void 0 ? [pattern] : []
20019
+ ]);
20020
+ const forEachRef = (patterns = []) => git([
20021
+ "for-each-ref",
20022
+ "--format=%(refname)%00%(objectname)%00%(objecttype)",
20023
+ ...patterns
20024
+ ]);
20025
+ const revList = (ref, limit, firstParent = false) => git([
20026
+ "rev-list",
20027
+ ...limit !== void 0 ? [`--max-count=${limit}`] : [],
20028
+ ...firstParent ? ["--first-parent"] : [],
20029
+ ref
20030
+ ]);
20031
+ const commit = (message, all = false, allowEmpty = false, amend = false, author) => git([
20032
+ "commit",
20033
+ ...all ? ["--all"] : [],
20034
+ ...allowEmpty ? ["--allow-empty"] : [],
20035
+ ...amend ? ["--amend"] : [],
20036
+ ...author !== void 0 ? [`--author=${author}`] : [],
20037
+ "-m",
20038
+ message
20039
+ ]);
20040
+ const push$1 = (remote, refspec, force = false, forceWithLease = false, tags = false, setUpstream = false) => git([
20041
+ "push",
20042
+ ...force ? ["--force"] : [],
20043
+ ...forceWithLease ? ["--force-with-lease"] : [],
20044
+ ...tags ? ["--tags"] : [],
20045
+ ...setUpstream ? ["--set-upstream"] : [],
20046
+ secretUrl(remote),
20047
+ ...refspec !== void 0 ? [refspec] : []
20048
+ ]);
20049
+ const pull = (remote, ref, rebase = false, ffOnly = false) => git([
20050
+ "pull",
20051
+ ...rebase ? ["--rebase"] : [],
20052
+ ...ffOnly ? ["--ff-only"] : [],
20053
+ secretUrl(remote),
20054
+ ...ref !== void 0 ? [ref] : []
20055
+ ]);
20056
+ const configList = (file) => git([
20057
+ "config",
20058
+ ...file !== void 0 ? ["-f", file] : [],
20059
+ "--list",
20060
+ "-z"
20061
+ ]);
20062
+ const configGetAll = (key, file) => git([
20063
+ "config",
20064
+ ...file !== void 0 ? ["-f", file] : [],
20065
+ "--get-all",
20066
+ "-z",
20067
+ key
20068
+ ]);
20069
+ const configUnset = (key, file, all = false) => git([
20070
+ "config",
20071
+ ...file !== void 0 ? ["-f", file] : [],
20072
+ all ? "--unset-all" : "--unset",
20073
+ key
20074
+ ]);
20075
+ const rm = (paths, cached = false, recursive = false, force = false) => git([
20076
+ "rm",
20077
+ ...cached ? ["--cached"] : [],
20078
+ ...recursive ? ["-r"] : [],
20079
+ ...force ? ["--force"] : [],
20080
+ "--",
20081
+ ...paths
20082
+ ]);
20083
+ const mv = (source, destination, force = false) => git([
20084
+ "mv",
20085
+ ...force ? ["--force"] : [],
20086
+ "--",
20087
+ source,
20088
+ destination
20089
+ ]);
20090
+ const checkIgnore = (paths) => git([
20091
+ "check-ignore",
20092
+ "-z",
20093
+ "--stdin"
20094
+ ], paths.map((path) => `${path}\0`).join(""));
20095
+ const worktreeAdd = (path, ref, detach = false, force = false) => git([
20096
+ "worktree",
20097
+ "add",
20098
+ ...force ? ["--force"] : [],
20099
+ ...detach ? ["--detach"] : [],
20100
+ path,
20101
+ ...ref !== void 0 ? [ref] : []
20102
+ ]);
20103
+ const worktreeList = () => git([
20104
+ "worktree",
20105
+ "list",
20106
+ "--porcelain",
20107
+ "-z"
20108
+ ]);
20109
+ const worktreeRemove = (path, force = false) => git([
20110
+ "worktree",
20111
+ "remove",
20112
+ ...force ? ["--force"] : [],
20113
+ path
20114
+ ]);
20115
+ const lsFiles = (pathspec = []) => git([
20116
+ "ls-files",
20117
+ "--stage",
20118
+ "-z",
20119
+ ...pathspec.length > 0 ? ["--", ...pathspec] : []
20120
+ ]);
20121
+ /**
20122
+ * Pure constructors for the `git` {@link GitInvocation} values this package
20123
+ * spawns.
20124
+ *
20125
+ * @remarks
20126
+ * Every constructor returns a cwd-less, argv-only {@link GitInvocation} — no
20127
+ * spawning, no working directory baked in. `Git` applies the working
20128
+ * directory per call with `ChildProcess.setCwd` on `invocation.command` and
20129
+ * owns the actual spawn, timeout, and error classification.
20130
+ *
20131
+ * **Redaction policy.** A constructor whose argv carries a sensitive
20132
+ * positional — a config value (`configSet`), or a URL that may embed
20133
+ * userinfo (the remote of `fetch`, `fetchUnshallow`, `lsRemote`, `push` and
20134
+ * `pull`, and the url of `submoduleAdd`, `submoduleSetUrl`, `remoteAdd` and
20135
+ * `remoteSetUrl`) —
20136
+ * masks it in {@link GitInvocation.redactedArgs}: a config value becomes
20137
+ * `<redacted>` wholesale, a URL keeps everything but its `userinfo@`
20138
+ * component. The `Git` service persists only the redacted argv in error
20139
+ * values, and its span annotations carry stable identifiers only (`cwd`,
20140
+ * keys, paths, remote/ref names) — never config values, never URLs.
20141
+ *
20142
+ * @public
20143
+ */
20144
+ var GitCommand = class {
20145
+ constructor() {}
20146
+ /**
20147
+ * `git show <ref>:<path>` — the contents of `path` as it existed at `ref`,
20148
+ * without checking anything out.
20149
+ */
20150
+ static show = show;
20151
+ /**
20152
+ * `git ls-tree -r -z <ref> [-- <pathspec>...]` — every path in the tree at
20153
+ * `ref`, recursively, NUL-terminated, optionally scoped to `pathspec`.
20154
+ *
20155
+ * @remarks
20156
+ * `-z` is load-bearing: git paths may themselves contain newlines, so the
20157
+ * caller must split on `"\0"`, never on `"\n"`. When `pathspec` is provided,
20158
+ * a literal `--` separator is inserted before the pathspec entries to prevent
20159
+ * git from interpreting pathspec values as options.
20160
+ */
20161
+ static lsTree = lsTree;
20162
+ /**
20213
20163
  * `git cat-file -e <ref>` — checks whether `ref` resolves to an existing
20214
20164
  * object, without printing it. A non-zero exit means the ref does not exist.
20215
20165
  */
@@ -20285,9 +20235,106 @@ var GitCommand = class {
20285
20235
  /**
20286
20236
  * Mutating: `git fetch [--depth <n>] <remote> [tag] <ref>` — fetches the given
20287
20237
  * ref from a remote, optionally with a depth limit and the `tag` keyword.
20238
+ *
20239
+ * @remarks
20240
+ * `remote` may be a URL as well as a remote name; an embedded
20241
+ * `userinfo@` credential is masked in {@link GitInvocation.redactedArgs}.
20288
20242
  */
20289
20243
  static fetch = fetch$1;
20290
20244
  /**
20245
+ * Mutating: `git fetch --unshallow <remote>` — converts a shallow clone
20246
+ * into a complete one by fetching the missing history.
20247
+ *
20248
+ * @remarks
20249
+ * `--unshallow` is a distinct MODE, not a depth value: git rejects it
20250
+ * outright in a repository that is not shallow, with
20251
+ * `--unshallow on a complete repository does not make sense`, so it
20252
+ * cannot be expressed as `fetch`'s `depth` option. The caller decides
20253
+ * whether to run it — probe with `Git.isShallow` first.
20254
+ *
20255
+ * `remote` may be a URL as well as a remote name; an embedded `userinfo@`
20256
+ * credential is masked in {@link GitInvocation.redactedArgs}.
20257
+ */
20258
+ static fetchUnshallow = fetchUnshallow;
20259
+ /**
20260
+ * `git rev-parse --is-shallow-repository` — prints `true` when the
20261
+ * repository is a shallow clone, `false` otherwise.
20262
+ *
20263
+ * @remarks
20264
+ * A dedicated probe constructor, deliberately separate from
20265
+ * {@link GitCommand.revParse}: `revParse` takes a REF and resolves it,
20266
+ * while this takes nothing and answers a repository-shape question.
20267
+ * Folding the flag into `revParse` would make that constructor
20268
+ * sometimes-takes-a-ref, sometimes-takes-a-flag.
20269
+ */
20270
+ static isShallow = isShallow;
20271
+ /**
20272
+ * Mutating: `git reset --soft|--mixed|--hard [<ref>]` — moves `HEAD` (and,
20273
+ * per mode, the index and working tree) to `ref`.
20274
+ *
20275
+ * @remarks
20276
+ * The mode flag is always explicit — `--mixed` is emitted for the default
20277
+ * rather than omitted — so the argv states what runs. `ref` may be any
20278
+ * commit-ish, including a gitlink sha.
20279
+ */
20280
+ static reset = reset;
20281
+ /**
20282
+ * Mutating: `git clean --force [-d] [-x] [-- <paths>...]` — deletes
20283
+ * untracked files from the working tree.
20284
+ *
20285
+ * @remarks
20286
+ * `--force` is unconditional: this constructor exists so a consumer can
20287
+ * restore a tree to a known state (e.g. before retrying a non-idempotent
20288
+ * operation), and without `--force` git refuses to clean at all under the
20289
+ * default `clean.requireForce` config — a clean that silently did nothing
20290
+ * would hand the retry the same dirty tree. `-d` removes untracked
20291
+ * directories too; `-x` removes ignored files as well. The literal `--`
20292
+ * separator makes the optional pathspec injection-safe by construction.
20293
+ */
20294
+ static clean = clean;
20295
+ /**
20296
+ * Mutating: `git restore [--source <ref>] [--staged] [--worktree] -- <paths...>`
20297
+ * — restores the given paths from the index (or from `source`), the
20298
+ * `checkout -- <paths>`-shaped operation.
20299
+ *
20300
+ * @remarks
20301
+ * This is a separate constructor precisely because {@link GitCommand.checkout}'s
20302
+ * service guard refuses `--` and option-like refs by design — `restore` is
20303
+ * git's own verb for pathspec restoration, and its paths always sit behind
20304
+ * a literal `--`, so they are injection-safe by construction. With neither
20305
+ * `staged` nor `worktree` set, git defaults to restoring the working tree.
20306
+ */
20307
+ static restore = restore;
20308
+ /**
20309
+ * Mutating: `git branch [-f] <name> [<start-point>]`, or
20310
+ * `git checkout (-b | -B) <name> [<start-point>]` when `checkout` is true —
20311
+ * creates a branch, optionally from an explicit start point, optionally
20312
+ * switching to it, optionally force-resetting an existing branch.
20313
+ *
20314
+ * @remarks
20315
+ * Branch creation is a branch-member concern, NOT a widening of
20316
+ * {@link GitCommand.checkout}: `checkout`'s contract stays "move to an
20317
+ * existing ref" and its option-like-ref refusal stays intact. The `-b` /
20318
+ * `-B` here is this constructor's own literal, never caller data.
20319
+ *
20320
+ * `force` with `checkout` exists because the delete-then-create longhand
20321
+ * (`branch -D` swallowed, then `checkout -b`) papers over a real edge:
20322
+ * `git branch -D` refuses to delete the currently checked-out branch,
20323
+ * while `checkout -B` resets it fine — one invocation handles both
20324
+ * states.
20325
+ */
20326
+ static branchCreate = branchCreate;
20327
+ /**
20328
+ * Mutating: `git branch -d <name>` (or `-D` when `force` is true) —
20329
+ * deletes a local branch.
20330
+ *
20331
+ * @remarks
20332
+ * The default `-d` refuses to delete a branch not fully merged — a typed
20333
+ * failure, which is usually the honest answer. `force: true` emits `-D`
20334
+ * and deletes regardless.
20335
+ */
20336
+ static branchDelete = branchDelete;
20337
+ /**
20291
20338
  * Mutating: `git submodule update [--init] [--depth <n>] [-- <paths>...]` — updates
20292
20339
  * registered submodules, optionally initializing them, with an optional depth limit,
20293
20340
  * and scoped to specific paths. The literal `--` separator makes the pathspec
@@ -20298,6 +20345,10 @@ var GitCommand = class {
20298
20345
  * Mutating: `git submodule add [--depth <n>] -- <url> <path>` — registers and
20299
20346
  * initializes a new submodule. The literal `--` separator makes the url and path
20300
20347
  * injection-safe by construction.
20348
+ *
20349
+ * @remarks
20350
+ * An embedded `userinfo@` credential in `url` is masked in
20351
+ * {@link GitInvocation.redactedArgs}.
20301
20352
  */
20302
20353
  static submoduleAdd = submoduleAdd;
20303
20354
  /**
@@ -20310,6 +20361,13 @@ var GitCommand = class {
20310
20361
  /**
20311
20362
  * Mutating: `git config [-f <file>] <key> <value>` — writes a configuration value,
20312
20363
  * optionally into an explicit configuration file (e.g., `.gitmodules`).
20364
+ *
20365
+ * @remarks
20366
+ * `value` may be a secret (a token, a credential-bearing URL), so it is
20367
+ * masked wholesale — as `<redacted>` — in
20368
+ * {@link GitInvocation.redactedArgs}. The key and file stay visible: they
20369
+ * are stable identifiers, and they are what a caller debugging a failed
20370
+ * write actually needs.
20313
20371
  */
20314
20372
  static configSet = configSet;
20315
20373
  /**
@@ -20392,9 +20450,304 @@ var GitCommand = class {
20392
20450
  * Each entry is a pair of status codes followed by a space and the path.
20393
20451
  */
20394
20452
  static status = status;
20453
+ /**
20454
+ * `git submodule status [--recursive] [-- <paths>...]` — one line per
20455
+ * registered submodule: a state prefix, the checked-out (or gitlink) sha,
20456
+ * the path, and — when the submodule is initialized — a `git describe`
20457
+ * suffix in parentheses.
20458
+ *
20459
+ * @remarks
20460
+ * `git submodule status` has no `-z` mode, so its output is line-based —
20461
+ * the one path-emitting constructor in this package that cannot follow
20462
+ * the `-z` rule. A submodule path containing a newline would corrupt the
20463
+ * parse; accepted as a git-imposed limitation.
20464
+ */
20465
+ static submoduleStatus = submoduleStatus;
20466
+ /**
20467
+ * Mutating: `git submodule init [-- <paths>...]` — registers the
20468
+ * submodules from `.gitmodules` into `.git/config` (all of them, or only
20469
+ * `paths`), without cloning or checking anything out.
20470
+ */
20471
+ static submoduleInit = submoduleInit;
20472
+ /**
20473
+ * Mutating: `git submodule deinit [--force] (--all | -- <paths>...)` —
20474
+ * unregisters submodules: clears their working trees and removes their
20475
+ * `.git/config` registration. The literal `--` separator makes the
20476
+ * pathspec injection-safe by construction.
20477
+ */
20478
+ static submoduleDeinit = submoduleDeinit;
20479
+ /**
20480
+ * Mutating: `git submodule sync [--recursive] [-- <paths>...]` —
20481
+ * re-copies each submodule's URL from `.gitmodules` into `.git/config`
20482
+ * (and into the submodule's own `remote.origin.url`), so a `.gitmodules`
20483
+ * URL change actually reaches git's live configuration.
20484
+ */
20485
+ static submoduleSync = submoduleSync;
20486
+ /**
20487
+ * Mutating: `git submodule set-url -- <path> <url>` — rewrites the
20488
+ * submodule's URL in `.gitmodules` and synchronizes it into
20489
+ * `.git/config`. The literal `--` separator makes the path and url
20490
+ * injection-safe by construction.
20491
+ *
20492
+ * @remarks
20493
+ * An embedded `userinfo@` credential in `url` is masked in
20494
+ * {@link GitInvocation.redactedArgs}.
20495
+ */
20496
+ static submoduleSetUrl = submoduleSetUrl;
20497
+ /**
20498
+ * Mutating: `git submodule set-branch (--branch <branch> | --default) -- <path>`
20499
+ * — records (or clears, when `branch` is omitted) the branch a submodule
20500
+ * tracks in `.gitmodules`. The literal `--` separator makes the path
20501
+ * injection-safe by construction.
20502
+ */
20503
+ static submoduleSetBranch = submoduleSetBranch;
20504
+ /**
20505
+ * Mutating: `git submodule absorbgitdirs [-- <paths>...]` — moves each
20506
+ * submodule's embedded `.git` directory into the superproject's
20507
+ * `.git/modules/` and leaves a gitfile pointer behind.
20508
+ */
20509
+ static submoduleAbsorbgitdirs = submoduleAbsorbgitdirs;
20510
+ /**
20511
+ * Mutating: `git submodule foreach [--recursive] <command>` — runs a shell
20512
+ * command in every checked-out submodule. `command` is a single shell
20513
+ * string, evaluated by git in each submodule's directory; it can mutate
20514
+ * anything, which is why the constructor is marked mutating regardless of
20515
+ * what the command does.
20516
+ *
20517
+ * @remarks
20518
+ * This is the ONE constructor whose argument cannot be made injection-safe
20519
+ * by construction: git evaluates `command` with `sh -c`, so every character
20520
+ * of it is shell code — a `--` separator or quoting cannot help. Callers
20521
+ * must treat `command` as a trusted literal and never interpolate untrusted
20522
+ * data into it.
20523
+ */
20524
+ static submoduleForeach = submoduleForeach;
20525
+ /**
20526
+ * `git ls-remote [--heads] [--tags] <remote> [<patterns>...]` — the refs a
20527
+ * remote advertises (sha + refname), optionally filtered to branch heads,
20528
+ * tags, and/or shell-glob patterns.
20529
+ *
20530
+ * @remarks
20531
+ * A read that talks to the NETWORK, not to the local repository — the one
20532
+ * non-mutating constructor in this package that does. An embedded
20533
+ * `userinfo@` credential in `remote` is masked in
20534
+ * {@link GitInvocation.redactedArgs}. An annotated tag advertises two
20535
+ * entries: `refs/tags/<name>` (the tag object) and `refs/tags/<name>^{}`
20536
+ * (the peeled commit).
20537
+ */
20538
+ static lsRemote = lsRemote;
20539
+ /**
20540
+ * Mutating: `git remote add <name> <url>` — registers a new remote.
20541
+ *
20542
+ * @remarks
20543
+ * An embedded `userinfo@` credential in `url` is masked in
20544
+ * {@link GitInvocation.redactedArgs}.
20545
+ */
20546
+ static remoteAdd = remoteAdd;
20547
+ /**
20548
+ * Mutating: `git remote remove <name>` — deletes a remote and its
20549
+ * remote-tracking refs and configuration.
20550
+ */
20551
+ static remoteRemove = remoteRemove;
20552
+ /**
20553
+ * Mutating: `git remote set-url <name> <url>` — rewrites a remote's fetch
20554
+ * URL.
20555
+ *
20556
+ * @remarks
20557
+ * An embedded `userinfo@` credential in `url` is masked in
20558
+ * {@link GitInvocation.redactedArgs}.
20559
+ */
20560
+ static remoteSetUrl = remoteSetUrl;
20561
+ /**
20562
+ * Mutating: `git stash push [--include-untracked] [-m <message>] [-- <paths>...]`
20563
+ * — saves the working tree (and index) state onto the stash stack. The
20564
+ * literal `--` separator makes the optional pathspec injection-safe by
20565
+ * construction; the message rides behind `-m`, which git consumes as a
20566
+ * value even when it begins with `-`.
20567
+ */
20568
+ static stashPush = stashPush;
20569
+ /**
20570
+ * Mutating: `git stash pop [stash@{n}]` — applies a stash entry and drops
20571
+ * it on success. The stash ref is rendered from an INTEGER index by this
20572
+ * package, never caller text.
20573
+ */
20574
+ static stashPop = stashPop;
20575
+ /**
20576
+ * Mutating: `git stash apply [stash@{n}]` — applies a stash entry and
20577
+ * keeps it on the stack. The stash ref is rendered from an INTEGER index
20578
+ * by this package, never caller text.
20579
+ */
20580
+ static stashApply = stashApply;
20581
+ /**
20582
+ * Mutating: `git stash drop [stash@{n}]` — deletes a stash entry without
20583
+ * applying it. The stash ref is rendered from an INTEGER index by this
20584
+ * package, never caller text.
20585
+ */
20586
+ static stashDrop = stashDrop;
20587
+ /**
20588
+ * `git stash list -z --format=%gd%x1f%H%x1f%gs` — every stash entry as a
20589
+ * NUL-terminated record of unit-separated fields: the reflog selector
20590
+ * (`stash@{0}`), the stash commit sha, and the reflog subject.
20591
+ *
20592
+ * @remarks
20593
+ * The `%x1f` (ASCII unit separator) field separator plus `-z` record
20594
+ * terminator keeps the parse split-safe: a stash message cannot contain
20595
+ * either byte (reflog subjects are single-line).
20596
+ */
20597
+ static stashList = stashList;
20598
+ /**
20599
+ * `git branch --list [--remotes | --all] --format=%(HEAD)%00%(refname:short)%00%(objectname)`
20600
+ * — every branch as a NUL-separated triple: the current-branch marker, the
20601
+ * short name, and the tip sha.
20602
+ *
20603
+ * @remarks
20604
+ * Records are newline-separated, which is split-safe here: git refnames
20605
+ * cannot contain a newline (or a space), so the only NUL bytes are the
20606
+ * format's own field separators. `all` wins over `remotes` when both are
20607
+ * set.
20608
+ */
20609
+ static branchList = branchList;
20610
+ /**
20611
+ * Mutating: `git tag [--force] [-m <message>] <name> [<ref>]` — creates a
20612
+ * lightweight tag, or an annotated one when `message` is given (`-m`
20613
+ * implies `-a`).
20614
+ */
20615
+ static tagCreate = tagCreate;
20616
+ /** Mutating: `git tag --delete <name>` — deletes a local tag. */
20617
+ static tagDelete = tagDelete;
20618
+ /**
20619
+ * `git tag --list [<pattern>]` — tag names, optionally filtered by a
20620
+ * shell-glob pattern, one per line (refnames cannot contain newlines).
20621
+ */
20622
+ static tagList = tagList;
20623
+ /**
20624
+ * `git for-each-ref --format=%(refname)%00%(objectname)%00%(objecttype) [<patterns>...]`
20625
+ * — every matching ref as a NUL-separated triple: full refname, sha, and
20626
+ * object type.
20627
+ *
20628
+ * @remarks
20629
+ * The format is this package's own fixed triple — the parse contract and
20630
+ * the argv are decided together, so the format string is a constructor
20631
+ * literal, never caller data. An annotated tag's `objecttype` is `tag`
20632
+ * (the tag object), not `commit`.
20633
+ */
20634
+ static forEachRef = forEachRef;
20635
+ /**
20636
+ * `git rev-list [--max-count=<n>] [--first-parent] <ref-or-range>` — commit
20637
+ * shas reachable from the ref (or range, e.g. `main..feat`), newest first.
20638
+ */
20639
+ static revList = revList;
20640
+ /**
20641
+ * Mutating: `git commit [--all] [--allow-empty] [--amend] [--author=<author>] -m <message>`
20642
+ * — records a commit. The message always rides argv behind `-m` (git
20643
+ * consumes it as a value even when it begins with `-`); committer identity
20644
+ * comes from the caller's environment — this constructor sets no
20645
+ * `GIT_AUTHOR_*`/`GIT_COMMITTER_*` variables, and the optional `author`
20646
+ * override is the fused `--author=` form.
20647
+ */
20648
+ static commit = commit;
20649
+ /**
20650
+ * Mutating: `git push [--force | --force-with-lease] [--tags] [--set-upstream] <remote> [<refspec>]`
20651
+ * — updates remote refs.
20652
+ *
20653
+ * @remarks
20654
+ * `remote` may be a URL as well as a remote name; an embedded `userinfo@`
20655
+ * credential is masked in {@link GitInvocation.redactedArgs}.
20656
+ */
20657
+ static push = push$1;
20658
+ /**
20659
+ * Mutating: `git pull [--rebase] [--ff-only] <remote> [<ref>]` — fetches
20660
+ * and integrates.
20661
+ *
20662
+ * @remarks
20663
+ * `remote` may be a URL as well as a remote name; an embedded `userinfo@`
20664
+ * credential is masked in {@link GitInvocation.redactedArgs}.
20665
+ */
20666
+ static pull = pull;
20667
+ /**
20668
+ * `git config [-f <file>] --list -z` — every configuration entry in scope
20669
+ * (or in the given file only), NUL-terminated, the key separated from the
20670
+ * value by a newline within each record.
20671
+ *
20672
+ * @remarks
20673
+ * `-z` is load-bearing: a config VALUE may contain newlines; only the NUL
20674
+ * record terminator plus first-newline field split parses it losslessly.
20675
+ * A valueless key (git's boolean-true shorthand) emits no newline at all.
20676
+ */
20677
+ static configList = configList;
20678
+ /**
20679
+ * `git config [-f <file>] --get-all -z <key>` — every value of a
20680
+ * (possibly multi-valued) key, NUL-terminated. An unset key exits 1 with
20681
+ * silent stderr.
20682
+ */
20683
+ static configGetAll = configGetAll;
20684
+ /**
20685
+ * Mutating: `git config [-f <file>] (--unset | --unset-all) <key>` —
20686
+ * removes a key (or, with `all`, every value of a multi-valued key).
20687
+ *
20688
+ * @remarks
20689
+ * git exits 5, silently, when the key was not set — a loud failure by
20690
+ * this package's classification, deliberately: an unset that silently did
20691
+ * nothing is indistinguishable from one that worked.
20692
+ */
20693
+ static configUnset = configUnset;
20694
+ /**
20695
+ * Mutating: `git rm [--cached] [-r] [--force] -- <paths...>` — removes
20696
+ * paths from the index (and, without `cached`, the working tree). The
20697
+ * literal `--` separator makes the pathspec injection-safe by
20698
+ * construction.
20699
+ */
20700
+ static rm = rm;
20701
+ /**
20702
+ * Mutating: `git mv [--force] -- <source> <destination>` — moves or
20703
+ * renames a tracked path. The literal `--` separator makes both positionals
20704
+ * injection-safe by construction.
20705
+ */
20706
+ static mv = mv;
20707
+ /**
20708
+ * `git check-ignore -z --stdin` — which of the given paths git would
20709
+ * ignore, paths fed NUL-separated via stdin and answers returned
20710
+ * NUL-separated.
20711
+ *
20712
+ * @remarks
20713
+ * The `--stdin -z` form is the only fully robust one: `-z` without
20714
+ * `--stdin` is rejected by git outright, and the non-`-z` output C-quotes
20715
+ * special-character paths. Feeding paths via stdin also makes them
20716
+ * injection-safe by construction — nothing caller-controlled enters the
20717
+ * argv. When NO path is ignored, git exits 1 with silent stderr.
20718
+ */
20719
+ static checkIgnore = checkIgnore;
20720
+ /**
20721
+ * Mutating: `git worktree add [--force] [--detach] <path> [<ref>]` —
20722
+ * creates a linked working tree at `path`, checked out at `ref` (or the
20723
+ * branch named after `path`'s basename).
20724
+ */
20725
+ static worktreeAdd = worktreeAdd;
20726
+ /**
20727
+ * `git worktree list --porcelain -z` — every working tree as a block of
20728
+ * NUL-terminated attributes (`worktree <path>`, `HEAD <sha>`,
20729
+ * `branch <ref>` / `detached`, `bare`, `locked [<reason>]`,
20730
+ * `prunable [<reason>]`), blocks separated by an empty attribute.
20731
+ */
20732
+ static worktreeList = worktreeList;
20733
+ /** Mutating: `git worktree remove [--force] <path>` — removes a linked working tree. */
20734
+ static worktreeRemove = worktreeRemove;
20735
+ /**
20736
+ * `git ls-files --stage -z [-- <pathspec>...]` — every INDEX entry (mode,
20737
+ * oid, stage number, path), NUL-terminated, optionally scoped to
20738
+ * `pathspec`.
20739
+ *
20740
+ * @remarks
20741
+ * The index-side sibling of {@link GitCommand.lsTree}: `lsTree` reads a
20742
+ * COMMITTED tree at a ref, while this reads the staging area — the only
20743
+ * place a staged-but-uncommitted gitlink (`160000 <oid> 0 <path>`) is
20744
+ * visible. `-z` is load-bearing twice over: paths may contain newlines,
20745
+ * and the non-`-z` output C-quotes special-character paths.
20746
+ */
20747
+ static lsFiles = lsFiles;
20395
20748
  };
20396
20749
  //#endregion
20397
- //#region ../../node_modules/.pnpm/@effected+git@0.5.2_effect@4.0.0-beta.101/node_modules/@effected/git/internal/run.js
20750
+ //#region ../../node_modules/.pnpm/@effected+git@0.6.0_effect@4.0.0-beta.101/node_modules/@effected/git/internal/run.js
20398
20751
  /**
20399
20752
  * Spawns `command` and collects its stdout, stderr, and exit code as a single
20400
20753
  * triple.
@@ -20421,7 +20774,7 @@ const runCollected = (command) => effect.Effect.scoped(effect.Effect.gen(functio
20421
20774
  };
20422
20775
  }));
20423
20776
  //#endregion
20424
- //#region ../../node_modules/.pnpm/@effected+git@0.5.2_effect@4.0.0-beta.101/node_modules/@effected/git/Git.js
20777
+ //#region ../../node_modules/.pnpm/@effected+git@0.6.0_effect@4.0.0-beta.101/node_modules/@effected/git/Git.js
20425
20778
  /** git's own ceiling: a run that has not answered in 30s is not going to. */
20426
20779
  const GIT_TIMEOUT = effect.Duration.seconds(30);
20427
20780
  /**
@@ -20449,7 +20802,16 @@ var GitCommandError = class extends effect.Schema.TaggedErrorClass()("GitCommand
20449
20802
  * logic routes on this instead of matching `detail` prose.
20450
20803
  */
20451
20804
  kind: effect.Schema.Literals(["refused", "failed"]),
20452
- /** The argument vector, without the leading `git`. */
20805
+ /**
20806
+ * The REDACTED argument vector, without the leading `git`.
20807
+ *
20808
+ * Sensitive positionals — config values, a URL's embedded userinfo — are
20809
+ * already masked by the constructor's redaction mask before this error is
20810
+ * constructed (`configSet`'s value reads `<redacted>`; a
20811
+ * `https://user:token@host/...` remote keeps everything but its
20812
+ * `userinfo@`). The raw argv is never persisted in an error value, and
20813
+ * `message` renders this redacted vector.
20814
+ */
20453
20815
  args: effect.Schema.Array(effect.Schema.String),
20454
20816
  /** The working directory the command ran in. */
20455
20817
  cwd: effect.Schema.String,
@@ -20495,9 +20857,74 @@ var UnknownRefError = class extends effect.Schema.TaggedErrorClass()("UnknownRef
20495
20857
  }
20496
20858
  };
20497
20859
  /**
20498
- * One entry of a `git ls-tree` listing.
20860
+ * A `git push` was rejected because the remote ref has moved: the classic
20861
+ * non-fast-forward rejection (`fetch first` / `non-fast-forward`), or a
20862
+ * `--force-with-lease` lease failure (`stale info`).
20499
20863
  *
20500
- * @public
20864
+ * @remarks
20865
+ * The typed signal a fetch-then-retry (or rebase-then-retry) fallback
20866
+ * branches on — every other push failure stays a {@link GitCommandError}.
20867
+ * Only `Git.push` can fail with this error.
20868
+ *
20869
+ * @public
20870
+ */
20871
+ var NonFastForwardError = class extends effect.Schema.TaggedErrorClass()("NonFastForwardError", {
20872
+ /** The working directory the push ran in. */
20873
+ cwd: effect.Schema.String,
20874
+ /** The refspec that was rejected, when the caller passed one. */
20875
+ refspec: effect.Schema.optionalKey(effect.Schema.String)
20876
+ }) {
20877
+ /** Renders the rejected push into a one-line message. */
20878
+ get message() {
20879
+ return this.refspec !== void 0 ? `push of '${this.refspec}' rejected as non-fast-forward in ${this.cwd}` : `push rejected as non-fast-forward in ${this.cwd}`;
20880
+ }
20881
+ };
20882
+ /**
20883
+ * A merge-shaped operation (`pull`, `stash pop`, `stash apply`) stopped with
20884
+ * conflict markers in the working tree.
20885
+ *
20886
+ * @remarks
20887
+ * The typed signal a resolve-or-abort recovery branches on. The conflicted
20888
+ * state is REAL: git has already written conflict markers, and (for `pull`)
20889
+ * `MERGE_HEAD` is set — the caller owns resolving or aborting. Detection
20890
+ * matches git's conflict report, which lands on STDOUT for a merge and on
20891
+ * stderr for a rebase-mode pull; both streams are inspected.
20892
+ *
20893
+ * @public
20894
+ */
20895
+ var MergeConflictError = class extends effect.Schema.TaggedErrorClass()("MergeConflictError", {
20896
+ /** The working directory the merge ran in. */
20897
+ cwd: effect.Schema.String }) {
20898
+ /** Renders the conflicted merge into a one-line message. */
20899
+ get message() {
20900
+ return `merge conflict in ${this.cwd}: fix conflicts (or abort) before continuing`;
20901
+ }
20902
+ };
20903
+ /**
20904
+ * A merge-shaped operation refused to start because local modifications would
20905
+ * be overwritten — git's refusal reads
20906
+ * `Your local changes ... would be overwritten by merge`.
20907
+ *
20908
+ * @remarks
20909
+ * The typed "commit or stash first" signal. Unlike {@link MergeConflictError}
20910
+ * the working tree is UNTOUCHED — git aborted before changing anything.
20911
+ * Only the merge-shaped methods (`pull`, `stashPop`, `stashApply`) can fail
20912
+ * with this error.
20913
+ *
20914
+ * @public
20915
+ */
20916
+ var DirtyWorktreeError = class extends effect.Schema.TaggedErrorClass()("DirtyWorktreeError", {
20917
+ /** The working directory whose local changes blocked the operation. */
20918
+ cwd: effect.Schema.String }) {
20919
+ /** Renders the blocked operation into a one-line message. */
20920
+ get message() {
20921
+ return `local changes would be overwritten in ${this.cwd}: commit or stash them first`;
20922
+ }
20923
+ };
20924
+ /**
20925
+ * One entry of a `git ls-tree` listing.
20926
+ *
20927
+ * @public
20501
20928
  */
20502
20929
  var LsTreeEntry = class extends effect.Schema.Class("LsTreeEntry")({
20503
20930
  /** The entry's file mode, e.g. `100644`. */
@@ -20555,11 +20982,26 @@ const UNKNOWN_REF_PATTERNS = [
20555
20982
  "couldn't find remote ref"
20556
20983
  ];
20557
20984
  const ABSENT_AT_REF_PATTERNS = ["does not exist in", "exists on disk, but not in"];
20985
+ const PUSH_REJECTED_PATTERNS = [
20986
+ "non-fast-forward",
20987
+ "fetch first",
20988
+ "stale info"
20989
+ ];
20990
+ const MERGE_CONFLICT_PATTERNS = [
20991
+ "CONFLICT (",
20992
+ "Automatic merge failed",
20993
+ "could not apply"
20994
+ ];
20995
+ const DIRTY_WORKTREE_PATTERN = "would be overwritten by";
20558
20996
  const matchesAny = (stderr, patterns) => patterns.some((pattern) => stderr.includes(pattern));
20559
20997
  /**
20560
20998
  * Classifies one completed run (or spawn-level `PlatformError`) against
20561
20999
  * git's stderr taxonomy. Written once — every `Git` method funnels through
20562
21000
  * this before deciding its own return value.
21001
+ *
21002
+ * `args` is the invocation's REDACTED argv: it is the only argv this
21003
+ * function may persist into a `GitCommandError`, per the #86 redaction
21004
+ * policy.
20563
21005
  */
20564
21006
  const classify = (cwd, args, outcome, kind) => {
20565
21007
  if (outcome instanceof effect.PlatformError.PlatformError) {
@@ -20582,6 +21024,11 @@ const classify = (cwd, args, outcome, kind) => {
20582
21024
  };
20583
21025
  if (stderr.includes(NOT_A_REPOSITORY)) return { _tag: "notARepository" };
20584
21026
  if (matchesAny(stderr, UNKNOWN_REF_PATTERNS)) return { _tag: "unknownRef" };
21027
+ if (kind === "push" && stderr.includes("[rejected]") && matchesAny(stderr, PUSH_REJECTED_PATTERNS)) return { _tag: "nonFastForward" };
21028
+ if (kind === "merge") {
21029
+ if (stderr.includes(DIRTY_WORKTREE_PATTERN)) return { _tag: "dirtyWorktree" };
21030
+ if (matchesAny(stdout, MERGE_CONFLICT_PATTERNS) || matchesAny(stderr, MERGE_CONFLICT_PATTERNS)) return { _tag: "mergeConflict" };
21031
+ }
20585
21032
  if (kind === "quiet" && exitCode === 1 && stderr === "") return { _tag: "absent" };
20586
21033
  if (kind === "noSuchRemote" && stderr.includes("No such remote")) return { _tag: "absent" };
20587
21034
  if (kind === "show" && matchesAny(stderr, ABSENT_AT_REF_PATTERNS)) return { _tag: "absent" };
@@ -20598,13 +21045,19 @@ const classify = (cwd, args, outcome, kind) => {
20598
21045
  };
20599
21046
  };
20600
21047
  /**
20601
- * Runs `command`, classifies the outcome, and never fails: a spawn-level
20602
- * `PlatformError` and a per-run timeout are both absorbed into the
20603
- * `"failure"` classification rather than escaping the effect's error
20604
- * channel.
21048
+ * Runs an invocation's command in `cwd`, classifies the outcome, and never
21049
+ * fails: a spawn-level `PlatformError` and a per-run timeout are both
21050
+ * absorbed into the `"failure"` classification rather than escaping the
21051
+ * effect's error channel.
21052
+ *
21053
+ * The argv handed to `classify` — and therefore persisted into any
21054
+ * `GitCommandError` — is the invocation's REDACTED argv, never the raw one:
21055
+ * the redaction mask the pure constructor carries is applied here, at the
21056
+ * single classification choke point (the #86 redaction policy).
20605
21057
  */
20606
- const runClassified = (command, cwd, kind) => {
20607
- const args = effect_unstable_process.ChildProcess.isStandardCommand(command) ? command.args : [];
21058
+ const runClassified = (invocation, cwd, kind) => {
21059
+ const args = invocation.redactedArgs;
21060
+ const command = effect_unstable_process.ChildProcess.setCwd(invocation.command, cwd);
20608
21061
  return runCollected(command).pipe(effect.Effect.map((collected) => classify(cwd, args, collected, kind)), effect.Effect.catch((platformError) => effect.Effect.succeed(classify(cwd, args, platformError, kind))), effect.Effect.timeoutOrElse({
20609
21062
  duration: GIT_TIMEOUT,
20610
21063
  orElse: () => effect.Effect.succeed({
@@ -20636,414 +21089,1417 @@ const parseLsTree = (output) => parseNulSeparated(output).map((entry) => {
20636
21089
  oid: header[2] ?? "",
20637
21090
  path
20638
21091
  });
20639
- });
20640
- /** git's one-letter name-status codes, score digits stripped (`R100` → `R`). */
20641
- const NAME_STATUS_CODES = {
20642
- A: "added",
20643
- B: "broken",
20644
- C: "copied",
20645
- D: "deleted",
20646
- M: "modified",
20647
- R: "renamed",
20648
- T: "typeChanged",
20649
- U: "unmerged",
20650
- X: "unknown"
20651
- };
20652
- /**
20653
- * Parses `git diff --name-status -z` output. A plain entry is two NUL tokens
20654
- * (`<code>`, `<path>`); a rename/copy entry is three (`<R|C><score>`,
20655
- * `<oldPath>`, `<newPath>`), and only the code's first character carries the
20656
- * status — the similarity score digits are dropped.
20657
- */
20658
- const parseNameStatus = (output) => {
20659
- const tokens = output.split("\0");
20660
- const entries = [];
20661
- let index = 0;
20662
- while (index < tokens.length) {
20663
- const code = tokens[index] ?? "";
20664
- if (code === "") {
20665
- index += 1;
20666
- continue;
21092
+ });
21093
+ /** git's one-letter name-status codes, score digits stripped (`R100` → `R`). */
21094
+ const NAME_STATUS_CODES = {
21095
+ A: "added",
21096
+ B: "broken",
21097
+ C: "copied",
21098
+ D: "deleted",
21099
+ M: "modified",
21100
+ R: "renamed",
21101
+ T: "typeChanged",
21102
+ U: "unmerged",
21103
+ X: "unknown"
21104
+ };
21105
+ /**
21106
+ * Parses `git diff --name-status -z` output. A plain entry is two NUL tokens
21107
+ * (`<code>`, `<path>`); a rename/copy entry is three (`<R|C><score>`,
21108
+ * `<oldPath>`, `<newPath>`), and only the code's first character carries the
21109
+ * status — the similarity score digits are dropped.
21110
+ */
21111
+ const parseNameStatus = (output) => {
21112
+ const tokens = output.split("\0");
21113
+ const entries = [];
21114
+ let index = 0;
21115
+ while (index < tokens.length) {
21116
+ const code = tokens[index] ?? "";
21117
+ if (code === "") {
21118
+ index += 1;
21119
+ continue;
21120
+ }
21121
+ const letter = code.charAt(0);
21122
+ const status = NAME_STATUS_CODES[letter] ?? "unknown";
21123
+ if (letter === "R" || letter === "C") {
21124
+ entries.push(NameStatusEntry.make({
21125
+ status,
21126
+ path: tokens[index + 2] ?? "",
21127
+ oldPath: tokens[index + 1] ?? ""
21128
+ }));
21129
+ index += 3;
21130
+ } else {
21131
+ entries.push(NameStatusEntry.make({
21132
+ status,
21133
+ path: tokens[index + 1] ?? ""
21134
+ }));
21135
+ index += 2;
21136
+ }
21137
+ }
21138
+ return entries;
21139
+ };
21140
+ /**
21141
+ * The metadata of a single commit, read via `git log -1` with NUL-separated
21142
+ * `%H` / `%G?` / `%B` placeholders.
21143
+ *
21144
+ * @public
21145
+ */
21146
+ var CommitInfo = class extends effect.Schema.Class("CommitInfo")({
21147
+ /** The commit's full object id (`%H`). */
21148
+ sha: effect.Schema.String,
21149
+ /** git's `%G?` signature verdict: Good, Bad, Unknown validity, eXpired, expired-key (Y), Revoked, cannot-check (E), None. */
21150
+ signatureStatus: effect.Schema.Literals([
21151
+ "G",
21152
+ "B",
21153
+ "U",
21154
+ "X",
21155
+ "Y",
21156
+ "R",
21157
+ "E",
21158
+ "N"
21159
+ ]),
21160
+ /** The raw commit message (`%B`), untrimmed — includes git's trailing format newline. */
21161
+ message: effect.Schema.String
21162
+ }) {};
21163
+ /** One two-letter porcelain v1 status axis code. */
21164
+ const porcelainCode = effect.Schema.Literals([
21165
+ " ",
21166
+ "M",
21167
+ "T",
21168
+ "A",
21169
+ "D",
21170
+ "R",
21171
+ "C",
21172
+ "U",
21173
+ "?",
21174
+ "!"
21175
+ ]);
21176
+ /**
21177
+ * One entry of a `git status --porcelain -z` listing.
21178
+ *
21179
+ * @public
21180
+ */
21181
+ var StatusEntry = class extends effect.Schema.Class("StatusEntry")({
21182
+ /** The index-side status code (first porcelain column). */
21183
+ x: porcelainCode,
21184
+ /** The working-tree-side status code (second porcelain column). */
21185
+ y: porcelainCode,
21186
+ /** The entry's path — for a rename or copy, the NEW path. */
21187
+ path: effect.Schema.String,
21188
+ /** The original path; present only on rename/copy entries. */
21189
+ origPath: effect.Schema.optionalKey(effect.Schema.String)
21190
+ }) {
21191
+ /**
21192
+ * Renders this entry back to one porcelain-shaped line: `XY <path>`.
21193
+ *
21194
+ * @remarks
21195
+ * **The rename convention is decided here, once, for every consumer.** By
21196
+ * default a rename/copy entry renders its NEW path only — `path` IS the
21197
+ * entry's current path, the one a line-oriented downstream can actually
21198
+ * open — which is a deliberate divergence from git's own non-`-z`
21199
+ * rendering (`orig -> new`). The arrow form is ambiguous to naive
21200
+ * line/whitespace splitters (paths may contain spaces, or a literal
21201
+ * `" -> "`), so it is opt-in via `renames: "arrow"` for consumers that
21202
+ * want git parity.
21203
+ *
21204
+ * A second recorded divergence: git's non-`-z` porcelain C-quotes paths
21205
+ * containing special characters; this renderer emits paths raw. It exists
21206
+ * for whitespace-insensitive text consumers — a machine parser should
21207
+ * consume the decoded {@link StatusEntry} values (or `-z` output)
21208
+ * directly, never re-parse this rendering.
21209
+ */
21210
+ toLine(options) {
21211
+ const rendered = options?.renames === "arrow" && this.origPath !== void 0 ? `${this.origPath} -> ${this.path}` : this.path;
21212
+ return `${this.x}${this.y} ${rendered}`;
21213
+ }
21214
+ /**
21215
+ * Renders entries back to porcelain-shaped text: one {@link StatusEntry.toLine}
21216
+ * line per entry, newline-joined, no trailing newline.
21217
+ *
21218
+ * @remarks
21219
+ * The route back from `Git.status`'s parsed entries to line-oriented text,
21220
+ * so a consumer whose downstream contract is porcelain-shaped text does
21221
+ * not hand-roll its own renderer (and re-decide the rename convention —
21222
+ * see {@link StatusEntry.toLine} for that decision). An empty array
21223
+ * renders as the empty string.
21224
+ */
21225
+ static format = (entries, options) => entries.map((entry) => entry.toLine(options)).join("\n");
21226
+ };
21227
+ /**
21228
+ * Parses `git log -1 --format=%H%x00%G?%x00%B` output: exactly two NUL
21229
+ * separators, everything after the second is the raw message, untrimmed.
21230
+ * Only ever called on the successful output of this package's own format
21231
+ * string, so the separators are guaranteed present.
21232
+ */
21233
+ const parseCommitInfo = (output) => {
21234
+ const first = output.indexOf("\0");
21235
+ const second = output.indexOf("\0", first + 1);
21236
+ return CommitInfo.make({
21237
+ sha: output.slice(0, first),
21238
+ signatureStatus: output.slice(first + 1, second),
21239
+ message: output.slice(second + 1)
21240
+ });
21241
+ };
21242
+ /**
21243
+ * Parses `git status --porcelain -z` output: each entry is `XY <path>`, and a
21244
+ * rename/copy entry appends the ORIGINAL path as one extra NUL token AFTER
21245
+ * the new path — the opposite order from `diff --name-status`.
21246
+ */
21247
+ const parseStatus = (output) => {
21248
+ const tokens = output.split("\0");
21249
+ const entries = [];
21250
+ let index = 0;
21251
+ while (index < tokens.length) {
21252
+ const token = tokens[index] ?? "";
21253
+ if (token === "") {
21254
+ index += 1;
21255
+ continue;
21256
+ }
21257
+ const x = token.charAt(0);
21258
+ const y = token.charAt(1);
21259
+ const path = token.slice(3);
21260
+ if (x === "R" || x === "C" || y === "R" || y === "C") {
21261
+ entries.push(StatusEntry.make({
21262
+ x,
21263
+ y,
21264
+ path,
21265
+ origPath: tokens[index + 1] ?? ""
21266
+ }));
21267
+ index += 2;
21268
+ } else {
21269
+ entries.push(StatusEntry.make({
21270
+ x,
21271
+ y,
21272
+ path
21273
+ }));
21274
+ index += 1;
21275
+ }
21276
+ }
21277
+ return entries;
21278
+ };
21279
+ /**
21280
+ * One line of a `git submodule status` listing.
21281
+ *
21282
+ * @remarks
21283
+ * The `state` decodes git's one-character prefix: `" "` → `"current"` (the
21284
+ * checked-out commit matches the index gitlink), `"-"` → `"uninitialized"`,
21285
+ * `"+"` → `"outOfSync"` (the checked-out commit differs from the gitlink),
21286
+ * `"U"` → `"conflict"` (merge conflicts). `describe` carries the
21287
+ * parenthesized `git describe` suffix git appends for initialized
21288
+ * submodules.
21289
+ *
21290
+ * @public
21291
+ */
21292
+ var SubmoduleStatusEntry = class extends effect.Schema.Class("SubmoduleStatusEntry")({
21293
+ /** The decoded state prefix. */
21294
+ state: effect.Schema.Literals([
21295
+ "current",
21296
+ "uninitialized",
21297
+ "outOfSync",
21298
+ "conflict"
21299
+ ]),
21300
+ /** The submodule's checked-out (or, uninitialized, gitlink) commit sha. */
21301
+ sha: effect.Schema.String,
21302
+ /** The submodule's path relative to the superproject root. */
21303
+ path: effect.Schema.String,
21304
+ /** The `git describe` suffix, present only for initialized submodules. */
21305
+ describe: effect.Schema.optionalKey(effect.Schema.String)
21306
+ }) {};
21307
+ /**
21308
+ * Parses `git submodule status` output. Line-based — the one parser in this
21309
+ * package without a `-z` mode to lean on, because git does not offer one for
21310
+ * `submodule status`; a submodule path containing a newline (or a literal
21311
+ * ` (` suffix mimicking the describe parenthesis) would corrupt the parse.
21312
+ * Accepted as a git-imposed limitation.
21313
+ */
21314
+ const parseSubmoduleStatus = (output) => {
21315
+ const entries = [];
21316
+ for (const line of output.split("\n")) {
21317
+ const trimmedEnd = line.endsWith("\r") ? line.slice(0, -1) : line;
21318
+ if (trimmedEnd === "") continue;
21319
+ const prefix = trimmedEnd.charAt(0);
21320
+ const state = prefix === "-" ? "uninitialized" : prefix === "+" ? "outOfSync" : prefix === "U" ? "conflict" : "current";
21321
+ const rest = prefix === " " || prefix === "-" || prefix === "+" || prefix === "U" ? trimmedEnd.slice(1) : trimmedEnd;
21322
+ const shaEnd = rest.indexOf(" ");
21323
+ const sha = shaEnd === -1 ? rest : rest.slice(0, shaEnd);
21324
+ const remainder = shaEnd === -1 ? "" : rest.slice(shaEnd + 1);
21325
+ const describeStart = remainder.endsWith(")") ? remainder.lastIndexOf(" (") : -1;
21326
+ if (describeStart === -1) entries.push(SubmoduleStatusEntry.make({
21327
+ state,
21328
+ sha,
21329
+ path: remainder
21330
+ }));
21331
+ else entries.push(SubmoduleStatusEntry.make({
21332
+ state,
21333
+ sha,
21334
+ path: remainder.slice(0, describeStart),
21335
+ describe: remainder.slice(describeStart + 2, -1)
21336
+ }));
21337
+ }
21338
+ return entries;
21339
+ };
21340
+ /**
21341
+ * One ref a remote advertises, from `git ls-remote`.
21342
+ *
21343
+ * @remarks
21344
+ * `ref` is the FULL refname as advertised (`refs/heads/main`,
21345
+ * `refs/tags/v1`), including the `^{}` suffix on an annotated tag's peeled
21346
+ * entry — an annotated tag appears twice, once as the tag object and once
21347
+ * peeled to its commit.
21348
+ *
21349
+ * @public
21350
+ */
21351
+ var LsRemoteEntry = class LsRemoteEntry extends effect.Schema.Class("LsRemoteEntry")({
21352
+ /** The sha the advertised ref points at. */
21353
+ sha: effect.Schema.String,
21354
+ /** The full advertised refname, `^{}` peel suffix included. */
21355
+ ref: effect.Schema.String
21356
+ }) {
21357
+ /**
21358
+ * The human-facing short name of an advertised refname: the
21359
+ * `refs/heads/` / `refs/tags/` / `refs/remotes/` prefix and any `^{}`
21360
+ * peel suffix stripped (`refs/tags/v1^{}` → `v1`).
21361
+ */
21362
+ static shortName = (ref) => {
21363
+ const base = ref.endsWith("^{}") ? ref.slice(0, -3) : ref;
21364
+ for (const prefix of [
21365
+ "refs/heads/",
21366
+ "refs/tags/",
21367
+ "refs/remotes/"
21368
+ ]) if (base.startsWith(prefix)) return base.slice(prefix.length);
21369
+ return base;
21370
+ };
21371
+ /**
21372
+ * The entries whose short name is a NEAR MISS for `ref`: not an exact
21373
+ * match, but ending in `ref` right behind a separator (`@`, `/`, `-`,
21374
+ * `_`) — the monorepo-prefixed-tag case, where a caller asks for
21375
+ * `4.0.0-beta.101` and the remote advertises `effect@4.0.0-beta.101`.
21376
+ *
21377
+ * @remarks
21378
+ * A pure, decode-side helper for validate-before-mutate flows: run
21379
+ * `lsRemote`, look for the wanted ref, and when it is absent hand the
21380
+ * listing to this to compute a suggestion. Deliberately a helper on the
21381
+ * ENTRY value rather than behavior baked into the service — the service
21382
+ * returns the full listing and the caller owns the matching policy. An
21383
+ * annotated tag's peeled `^{}` entry shares its base short name, so a
21384
+ * near miss on such a tag can surface both of its entries.
21385
+ */
21386
+ static nearMatches = (entries, ref) => {
21387
+ const separators = [
21388
+ "@",
21389
+ "/",
21390
+ "-",
21391
+ "_"
21392
+ ];
21393
+ return entries.filter((entry) => {
21394
+ const short = LsRemoteEntry.shortName(entry.ref);
21395
+ if (short === ref || !short.endsWith(ref)) return false;
21396
+ return separators.includes(short.charAt(short.length - ref.length - 1));
21397
+ });
21398
+ };
21399
+ };
21400
+ /**
21401
+ * Parses `git ls-remote` output: one `<sha>\t<refname>` line per advertised
21402
+ * ref. Line-based deliberately — refnames cannot contain a newline (or a
21403
+ * tab), so the split is safe without a `-z` mode (which `ls-remote` does not
21404
+ * offer).
21405
+ */
21406
+ const parseLsRemote = (output) => output.split("\n").filter((line) => line.length > 0).map((line) => {
21407
+ const tabIndex = line.indexOf(" ");
21408
+ return LsRemoteEntry.make({
21409
+ sha: line.slice(0, tabIndex),
21410
+ ref: line.slice(tabIndex + 1)
21411
+ });
21412
+ });
21413
+ /**
21414
+ * One stash entry, from `git stash list`.
21415
+ *
21416
+ * @public
21417
+ */
21418
+ var StashEntry = class extends effect.Schema.Class("StashEntry")({
21419
+ /** The reflog selector (`stash@{0}`) — the index other stash methods take. */
21420
+ ref: effect.Schema.String,
21421
+ /** The stash commit's sha. */
21422
+ sha: effect.Schema.String,
21423
+ /** The reflog subject: `WIP on <branch>: ...` or `On <branch>: <message>`. */
21424
+ message: effect.Schema.String
21425
+ }) {};
21426
+ /**
21427
+ * Parses `git stash list -z --format=%gd%x1f%H%x1f%gs` output: NUL-terminated
21428
+ * records of unit-separated (`\x1f`) fields. Reflog subjects are single-line
21429
+ * and cannot contain either separator byte.
21430
+ */
21431
+ const parseStashList = (output) => parseNulSeparated(output).map((record) => {
21432
+ const [ref = "", sha = "", ...rest] = record.split("");
21433
+ return StashEntry.make({
21434
+ ref,
21435
+ sha,
21436
+ message: rest.join("")
21437
+ });
21438
+ });
21439
+ /**
21440
+ * One local (or remote-tracking) branch, from `git branch --list`.
21441
+ *
21442
+ * @public
21443
+ */
21444
+ var BranchEntry = class extends effect.Schema.Class("BranchEntry")({
21445
+ /** The short branch name (`main`, or `origin/main` for a remote branch). */
21446
+ name: effect.Schema.String,
21447
+ /** The branch tip's sha. */
21448
+ sha: effect.Schema.String,
21449
+ /** Whether this branch is checked out in the current working tree. */
21450
+ current: effect.Schema.Boolean
21451
+ }) {};
21452
+ /**
21453
+ * Parses `git branch --list --format=%(HEAD)%00%(refname:short)%00%(objectname)`
21454
+ * output: newline-separated records (refnames cannot contain newlines) of
21455
+ * NUL-separated fields. The `%(HEAD)` marker is `*` for the checked-out
21456
+ * branch; anything else (` `, or `+` for a branch checked out in a linked
21457
+ * worktree) is not-current.
21458
+ */
21459
+ const parseBranchList = (output) => output.split("\n").filter((line) => line.length > 0).map((line) => {
21460
+ const [marker = "", name = "", sha = ""] = line.split("\0");
21461
+ return BranchEntry.make({
21462
+ name,
21463
+ sha,
21464
+ current: marker === "*"
21465
+ });
21466
+ });
21467
+ /**
21468
+ * One ref, from `git for-each-ref`.
21469
+ *
21470
+ * @public
21471
+ */
21472
+ var RefEntry = class extends effect.Schema.Class("RefEntry")({
21473
+ /** The full refname (`refs/tags/v1`). */
21474
+ ref: effect.Schema.String,
21475
+ /** The sha of the object the ref points at. */
21476
+ sha: effect.Schema.String,
21477
+ /**
21478
+ * The pointed-at object's type. An annotated tag is `tag` (the tag
21479
+ * object itself, not its target commit).
21480
+ */
21481
+ objectType: effect.Schema.Literals([
21482
+ "commit",
21483
+ "tag",
21484
+ "tree",
21485
+ "blob"
21486
+ ])
21487
+ }) {};
21488
+ /**
21489
+ * Parses `git for-each-ref --format=%(refname)%00%(objectname)%00%(objecttype)`
21490
+ * output: newline-separated records (refnames cannot contain newlines) of
21491
+ * NUL-separated fields.
21492
+ */
21493
+ const parseForEachRef = (output) => output.split("\n").filter((line) => line.length > 0).map((line) => {
21494
+ const [ref = "", sha = "", objectType = "commit"] = line.split("\0");
21495
+ return RefEntry.make({
21496
+ ref,
21497
+ sha,
21498
+ objectType
21499
+ });
21500
+ });
21501
+ /**
21502
+ * One configuration entry, from `git config --list`.
21503
+ *
21504
+ * @public
21505
+ */
21506
+ var ConfigListEntry = class extends effect.Schema.Class("ConfigListEntry")({
21507
+ /** The canonical dotted key (`section.subsection.key`). */
21508
+ key: effect.Schema.String,
21509
+ /**
21510
+ * The raw value. A valueless key (git's boolean-true shorthand,
21511
+ * `[section]` + bare `key`) surfaces as the empty string — distinguish it
21512
+ * with `configGetAll` if the difference matters.
21513
+ */
21514
+ value: effect.Schema.String
21515
+ }) {};
21516
+ /**
21517
+ * Parses `git config --list -z` output: NUL-terminated records, key separated
21518
+ * from value by the FIRST newline (a config value may itself contain
21519
+ * newlines — the reason `-z` is load-bearing). A record with no newline is a
21520
+ * valueless boolean-shorthand key.
21521
+ */
21522
+ const parseConfigList = (output) => parseNulSeparated(output).map((record) => {
21523
+ const newlineIndex = record.indexOf("\n");
21524
+ return newlineIndex === -1 ? ConfigListEntry.make({
21525
+ key: record,
21526
+ value: ""
21527
+ }) : ConfigListEntry.make({
21528
+ key: record.slice(0, newlineIndex),
21529
+ value: record.slice(newlineIndex + 1)
21530
+ });
21531
+ });
21532
+ /**
21533
+ * One working tree, from `git worktree list --porcelain`.
21534
+ *
21535
+ * @public
21536
+ */
21537
+ var WorktreeEntry = class extends effect.Schema.Class("WorktreeEntry")({
21538
+ /** The working tree's absolute path. */
21539
+ path: effect.Schema.String,
21540
+ /** The checked-out commit sha; absent for a bare repository entry. */
21541
+ head: effect.Schema.optionalKey(effect.Schema.String),
21542
+ /** The checked-out branch's full refname; absent when detached or bare. */
21543
+ branch: effect.Schema.optionalKey(effect.Schema.String),
21544
+ /** Whether the working tree is in detached-HEAD state. */
21545
+ detached: effect.Schema.Boolean,
21546
+ /** Whether the entry is the bare repository itself. */
21547
+ bare: effect.Schema.Boolean,
21548
+ /** Present when the worktree is locked; holds the lock reason (possibly empty). */
21549
+ locked: effect.Schema.optionalKey(effect.Schema.String),
21550
+ /** Present when the worktree is prunable; holds the reason (possibly empty). */
21551
+ prunable: effect.Schema.optionalKey(effect.Schema.String)
21552
+ }) {};
21553
+ /**
21554
+ * Parses `git worktree list --porcelain -z` output: NUL-terminated attribute
21555
+ * lines, one blank attribute terminating each entry. Attribute vocabulary:
21556
+ * `worktree <path>`, `HEAD <sha>`, `branch <ref>`, and the flag/annotation
21557
+ * attributes `detached`, `bare`, `locked [<reason>]`, `prunable [<reason>]`.
21558
+ */
21559
+ const parseWorktreeList = (output) => {
21560
+ const entries = [];
21561
+ let path;
21562
+ let head;
21563
+ let branch;
21564
+ let detached = false;
21565
+ let bare = false;
21566
+ let locked;
21567
+ let prunable;
21568
+ const flush = () => {
21569
+ if (path !== void 0) entries.push(WorktreeEntry.make({
21570
+ path,
21571
+ detached,
21572
+ bare,
21573
+ ...head !== void 0 ? { head } : {},
21574
+ ...branch !== void 0 ? { branch } : {},
21575
+ ...locked !== void 0 ? { locked } : {},
21576
+ ...prunable !== void 0 ? { prunable } : {}
21577
+ }));
21578
+ path = void 0;
21579
+ head = void 0;
21580
+ branch = void 0;
21581
+ detached = false;
21582
+ bare = false;
21583
+ locked = void 0;
21584
+ prunable = void 0;
21585
+ };
21586
+ for (const attribute of output.split("\0")) if (attribute === "") flush();
21587
+ else if (attribute.startsWith("worktree ")) path = attribute.slice(9);
21588
+ else if (attribute.startsWith("HEAD ")) head = attribute.slice(5);
21589
+ else if (attribute.startsWith("branch ")) branch = attribute.slice(7);
21590
+ else if (attribute === "detached") detached = true;
21591
+ else if (attribute === "bare") bare = true;
21592
+ else if (attribute === "locked" || attribute.startsWith("locked ")) locked = attribute === "locked" ? "" : attribute.slice(7);
21593
+ else if (attribute === "prunable" || attribute.startsWith("prunable ")) prunable = attribute === "prunable" ? "" : attribute.slice(9);
21594
+ flush();
21595
+ return entries;
21596
+ };
21597
+ /**
21598
+ * One index (staging area) entry, from `git ls-files --stage`.
21599
+ *
21600
+ * @remarks
21601
+ * The index-side sibling of {@link LsTreeEntry}: this is the ONLY place a
21602
+ * staged-but-uncommitted gitlink (`mode` `160000`) is visible — `lsTree`
21603
+ * reads the committed tree and misses exactly that window.
21604
+ *
21605
+ * @public
21606
+ */
21607
+ var LsFilesEntry = class extends effect.Schema.Class("LsFilesEntry")({
21608
+ /** The entry's file mode, e.g. `100644` — `160000` for a gitlink. */
21609
+ mode: effect.Schema.String,
21610
+ /** The staged object id. */
21611
+ oid: effect.Schema.String,
21612
+ /** The merge stage: `0` normally; `1`/`2`/`3` during an unresolved merge. */
21613
+ stage: effect.Schema.Number,
21614
+ /** The entry's path, relative to `cwd`. May contain spaces or newlines. */
21615
+ path: effect.Schema.String
21616
+ }) {};
21617
+ /**
21618
+ * Parses `git ls-files --stage -z` output: each NUL-terminated entry is
21619
+ * `<mode> <oid> <stage>\t<path>`. `path` is everything after the first tab,
21620
+ * so a path containing spaces or newlines is preserved intact — the same
21621
+ * split rule as `parseLsTree`.
21622
+ */
21623
+ const parseLsFiles = (output) => parseNulSeparated(output).map((entry) => {
21624
+ const tabIndex = entry.indexOf(" ");
21625
+ const header = entry.slice(0, tabIndex).split(" ");
21626
+ return LsFilesEntry.make({
21627
+ mode: header[0] ?? "",
21628
+ oid: header[1] ?? "",
21629
+ stage: Number(header[2] ?? "0"),
21630
+ path: entry.slice(tabIndex + 1)
21631
+ });
21632
+ });
21633
+ /**
21634
+ * Refuse a caller-supplied ref or range that git would parse as an option.
21635
+ *
21636
+ * Refs are caller-controlled and land in git's argv as positional entries; a
21637
+ * value beginning with `-` is read as a flag instead — `checkout("-b")` would
21638
+ * CREATE a branch. A bare `--` separator is not a safe fix for every command
21639
+ * (it switches `checkout` into pathspec mode), so option-like values are
21640
+ * refused outright, before any spawn, as a typed {@link GitCommandError}.
21641
+ * `show`'s `path` needs no guard: it is fused after the ref into one
21642
+ * `ref:path` token, which cannot begin with `-` unless the ref does.
21643
+ *
21644
+ * `sensitive` values get the same check but a REDACTED report: a refused
21645
+ * sensitive positional (a `configSet` value) must not leak into
21646
+ * `GitCommandError.args`/`detail` any more than a spawned one may — the #86
21647
+ * redaction policy applies to guard rejections too.
21648
+ */
21649
+ const rejectOptionLikeRefs = (cwd, refs, sensitive = []) => {
21650
+ const offending = refs.find((ref) => ref.startsWith("-"));
21651
+ if (offending !== void 0) return effect.Effect.fail(new GitCommandError({
21652
+ kind: "refused",
21653
+ args: [offending],
21654
+ cwd,
21655
+ stderr: "",
21656
+ detail: `refused a ref argument git would parse as an option: ${JSON.stringify(offending)}`
21657
+ }));
21658
+ return sensitive.find((value) => value.startsWith("-")) === void 0 ? effect.Effect.void : effect.Effect.fail(new GitCommandError({
21659
+ kind: "refused",
21660
+ args: ["<redacted>"],
21661
+ cwd,
21662
+ stderr: "",
21663
+ detail: "refused a sensitive argument git would parse as an option (value redacted)"
21664
+ }));
21665
+ };
21666
+ /**
21667
+ * Refuse a caller-supplied numeric index/limit that is not a non-negative
21668
+ * integer.
21669
+ *
21670
+ * Every relational comparison against `NaN` is `false`, so a bare
21671
+ * `value < 0` guard admits `NaN` (and a fractional value truncates nothing —
21672
+ * it rides straight into the argv as `stash@{1.5}` / `--max-count=NaN`).
21673
+ * Integrality and range are therefore checked together, pre-spawn, as a
21674
+ * typed refusal.
21675
+ */
21676
+ const rejectNonNaturalNumber = (cwd, label, value) => value === void 0 || Number.isInteger(value) && value >= 0 ? effect.Effect.void : effect.Effect.fail(new GitCommandError({
21677
+ kind: "refused",
21678
+ args: [String(value)],
21679
+ cwd,
21680
+ stderr: "",
21681
+ detail: `refused ${label}: expected a non-negative integer, received ${value}`
21682
+ }));
21683
+ /** Builds the `Git.Service` shape over an already-resolved `ChildProcessSpawner`. */
21684
+ const make = (spawner) => {
21685
+ const runFor = (invocation, cwd, kind) => runClassified(invocation, cwd, kind).pipe(effect.Effect.provideService(effect_unstable_process.ChildProcessSpawner.ChildProcessSpawner, spawner));
21686
+ const show = effect.Effect.fn("Git.show")(function* (cwd, ref, path) {
21687
+ yield* effect.Effect.annotateCurrentSpan({
21688
+ cwd,
21689
+ ref,
21690
+ path
21691
+ });
21692
+ yield* rejectOptionLikeRefs(cwd, [ref]);
21693
+ const classified = yield* runFor(GitCommand.show(ref, path), cwd, "show");
21694
+ switch (classified._tag) {
21695
+ case "success": return effect.Option.some(classified.output);
21696
+ case "absent": return effect.Option.none();
21697
+ case "notARepository": return yield* effect.Effect.fail(new NotARepositoryError({ cwd }));
21698
+ case "unknownRef": return yield* effect.Effect.fail(new UnknownRefError({
21699
+ ref,
21700
+ cwd
21701
+ }));
21702
+ case "failure": return yield* effect.Effect.fail(classified.error);
21703
+ default: return yield* effect.Effect.die(`Git.show: unexpected classification "${classified._tag}"`);
21704
+ }
21705
+ });
21706
+ const lsTree = effect.Effect.fn("Git.lsTree")(function* (cwd, ref, options) {
21707
+ yield* effect.Effect.annotateCurrentSpan({
21708
+ cwd,
21709
+ ref
21710
+ });
21711
+ yield* rejectOptionLikeRefs(cwd, [ref]);
21712
+ const classified = yield* runFor(GitCommand.lsTree(ref, options?.pathspec ?? []), cwd, "generic");
21713
+ switch (classified._tag) {
21714
+ case "success": return parseLsTree(classified.output);
21715
+ case "notARepository": return yield* effect.Effect.fail(new NotARepositoryError({ cwd }));
21716
+ case "unknownRef": return yield* effect.Effect.fail(new UnknownRefError({
21717
+ ref,
21718
+ cwd
21719
+ }));
21720
+ case "failure": return yield* effect.Effect.fail(classified.error);
21721
+ default: return yield* effect.Effect.die(`Git.lsTree: unexpected classification "${classified._tag}"`);
21722
+ }
21723
+ });
21724
+ const refExists = effect.Effect.fn("Git.refExists")(function* (cwd, ref) {
21725
+ yield* effect.Effect.annotateCurrentSpan({
21726
+ cwd,
21727
+ ref
21728
+ });
21729
+ yield* rejectOptionLikeRefs(cwd, [ref]);
21730
+ const classified = yield* runFor(GitCommand.refExists(ref), cwd, "refExists");
21731
+ switch (classified._tag) {
21732
+ case "success": return true;
21733
+ case "refMissing": return false;
21734
+ case "unknownRef": return false;
21735
+ case "notARepository": return yield* effect.Effect.fail(new NotARepositoryError({ cwd }));
21736
+ case "failure": return yield* effect.Effect.fail(classified.error);
21737
+ default: return yield* effect.Effect.die(`Git.refExists: unexpected classification "${classified._tag}"`);
21738
+ }
21739
+ });
21740
+ const mergeBase = effect.Effect.fn("Git.mergeBase")(function* (cwd, a, b) {
21741
+ yield* effect.Effect.annotateCurrentSpan({
21742
+ cwd,
21743
+ a,
21744
+ b
21745
+ });
21746
+ yield* rejectOptionLikeRefs(cwd, [a, b]);
21747
+ const classified = yield* runFor(GitCommand.mergeBase(a, b), cwd, "generic");
21748
+ switch (classified._tag) {
21749
+ case "success": return classified.output.trim();
21750
+ case "notARepository": return yield* effect.Effect.fail(new NotARepositoryError({ cwd }));
21751
+ case "unknownRef": return yield* effect.Effect.fail(new UnknownRefError({
21752
+ ref: `${a}...${b}`,
21753
+ cwd
21754
+ }));
21755
+ case "failure": return yield* effect.Effect.fail(classified.error);
21756
+ default: return yield* effect.Effect.die(`Git.mergeBase: unexpected classification "${classified._tag}"`);
21757
+ }
21758
+ });
21759
+ const changedFiles = effect.Effect.fn("Git.changedFiles")(function* (cwd, options) {
21760
+ const relative = options.relative ?? false;
21761
+ yield* effect.Effect.annotateCurrentSpan({
21762
+ cwd,
21763
+ base: options.base,
21764
+ head: options.head,
21765
+ relative
21766
+ });
21767
+ yield* rejectOptionLikeRefs(cwd, [options.base, options.head]);
21768
+ const classified = yield* runFor(GitCommand.changedFiles(options.base, options.head, relative), cwd, "generic");
21769
+ switch (classified._tag) {
21770
+ case "success": return parseNulSeparated(classified.output);
21771
+ case "notARepository": return yield* effect.Effect.fail(new NotARepositoryError({ cwd }));
21772
+ case "unknownRef": return yield* effect.Effect.fail(new UnknownRefError({
21773
+ ref: `${options.base}...${options.head}`,
21774
+ cwd
21775
+ }));
21776
+ case "failure": return yield* effect.Effect.fail(classified.error);
21777
+ default: return yield* effect.Effect.die(`Git.changedFiles: unexpected classification "${classified._tag}"`);
21778
+ }
21779
+ });
21780
+ const collectPaths = (method, invocation, cwd) => effect.Effect.gen(function* () {
21781
+ const classified = yield* runFor(invocation, cwd, "generic");
21782
+ switch (classified._tag) {
21783
+ case "success": return parseNulSeparated(classified.output);
21784
+ case "notARepository": return yield* effect.Effect.fail(new NotARepositoryError({ cwd }));
21785
+ case "unknownRef": return yield* effect.Effect.fail(new UnknownRefError({
21786
+ ref: "working tree",
21787
+ cwd
21788
+ }));
21789
+ case "failure": return yield* effect.Effect.fail(classified.error);
21790
+ default: return yield* effect.Effect.die(`${method}: unexpected classification "${classified._tag}"`);
21791
+ }
21792
+ });
21793
+ const unstagedChanges = effect.Effect.fn("Git.unstagedChanges")(function* (cwd, options) {
21794
+ const relative = options?.relative ?? false;
21795
+ yield* effect.Effect.annotateCurrentSpan({
21796
+ cwd,
21797
+ relative
21798
+ });
21799
+ return yield* collectPaths("Git.unstagedChanges", GitCommand.unstagedChanges(relative), cwd);
21800
+ });
21801
+ const stagedChanges = effect.Effect.fn("Git.stagedChanges")(function* (cwd, options) {
21802
+ const relative = options?.relative ?? false;
21803
+ yield* effect.Effect.annotateCurrentSpan({
21804
+ cwd,
21805
+ relative
21806
+ });
21807
+ return yield* collectPaths("Git.stagedChanges", GitCommand.stagedChanges(relative), cwd);
21808
+ });
21809
+ const untrackedFiles = effect.Effect.fn("Git.untrackedFiles")(function* (cwd, options) {
21810
+ const relative = options?.relative ?? false;
21811
+ yield* effect.Effect.annotateCurrentSpan({
21812
+ cwd,
21813
+ relative
21814
+ });
21815
+ return yield* collectPaths("Git.untrackedFiles", GitCommand.untrackedFiles(relative), cwd);
21816
+ });
21817
+ const workingChanges = effect.Effect.fn("Git.workingChanges")(function* (cwd, options) {
21818
+ yield* effect.Effect.annotateCurrentSpan({
21819
+ cwd,
21820
+ relative: options?.relative ?? false
21821
+ });
21822
+ const unstaged = yield* unstagedChanges(cwd, options);
21823
+ const staged = yield* stagedChanges(cwd, options);
21824
+ const untracked = yield* untrackedFiles(cwd, options);
21825
+ return [.../* @__PURE__ */ new Set([
21826
+ ...unstaged,
21827
+ ...staged,
21828
+ ...untracked
21829
+ ])];
21830
+ });
21831
+ const nameStatus = effect.Effect.fn("Git.nameStatus")(function* (cwd, options) {
21832
+ const relative = options.relative ?? false;
21833
+ yield* effect.Effect.annotateCurrentSpan({
21834
+ cwd,
21835
+ base: options.base,
21836
+ head: options.head ?? "(working tree)",
21837
+ relative
21838
+ });
21839
+ yield* rejectOptionLikeRefs(cwd, options.head === void 0 ? [options.base] : [options.base, options.head]);
21840
+ const classified = yield* runFor(GitCommand.nameStatus(options.base, options.head, relative), cwd, "generic");
21841
+ switch (classified._tag) {
21842
+ case "success": return parseNameStatus(classified.output);
21843
+ case "notARepository": return yield* effect.Effect.fail(new NotARepositoryError({ cwd }));
21844
+ case "unknownRef": return yield* effect.Effect.fail(new UnknownRefError({
21845
+ ref: options.head === void 0 ? options.base : `${options.base}...${options.head}`,
21846
+ cwd
21847
+ }));
21848
+ case "failure": return yield* effect.Effect.fail(classified.error);
21849
+ default: return yield* effect.Effect.die(`Git.nameStatus: unexpected classification "${classified._tag}"`);
21850
+ }
21851
+ });
21852
+ const revParse = effect.Effect.fn("Git.revParse")(function* (cwd, ref) {
21853
+ yield* effect.Effect.annotateCurrentSpan({
21854
+ cwd,
21855
+ ref
21856
+ });
21857
+ yield* rejectOptionLikeRefs(cwd, [ref]);
21858
+ const classified = yield* runFor(GitCommand.revParse(ref), cwd, "generic");
21859
+ switch (classified._tag) {
21860
+ case "success": return classified.output.trim();
21861
+ case "notARepository": return yield* effect.Effect.fail(new NotARepositoryError({ cwd }));
21862
+ case "unknownRef": return yield* effect.Effect.fail(new UnknownRefError({
21863
+ ref,
21864
+ cwd
21865
+ }));
21866
+ case "failure": return yield* effect.Effect.fail(classified.error);
21867
+ default: return yield* effect.Effect.die(`Git.revParse: unexpected classification "${classified._tag}"`);
21868
+ }
21869
+ });
21870
+ const checkout = effect.Effect.fn("Git.checkout")(function* (cwd, ref, options) {
21871
+ const detach = options?.detach ?? false;
21872
+ yield* effect.Effect.annotateCurrentSpan({
21873
+ cwd,
21874
+ ref,
21875
+ detach
21876
+ });
21877
+ yield* rejectOptionLikeRefs(cwd, [ref]);
21878
+ const classified = yield* runFor(GitCommand.checkout(ref, detach), cwd, "generic");
21879
+ switch (classified._tag) {
21880
+ case "success": return;
21881
+ case "notARepository": return yield* effect.Effect.fail(new NotARepositoryError({ cwd }));
21882
+ case "unknownRef": return yield* effect.Effect.fail(new UnknownRefError({
21883
+ ref,
21884
+ cwd
21885
+ }));
21886
+ case "failure": return yield* effect.Effect.fail(classified.error);
21887
+ default: return yield* effect.Effect.die(`Git.checkout: unexpected classification "${classified._tag}"`);
21888
+ }
21889
+ });
21890
+ const reset = effect.Effect.fn("Git.reset")(function* (cwd, options) {
21891
+ const mode = options?.mode ?? "mixed";
21892
+ yield* effect.Effect.annotateCurrentSpan({
21893
+ cwd,
21894
+ mode,
21895
+ ref: options?.ref ?? "HEAD"
21896
+ });
21897
+ if (options?.ref !== void 0) yield* rejectOptionLikeRefs(cwd, [options.ref]);
21898
+ const classified = yield* runFor(GitCommand.reset(mode, options?.ref), cwd, "generic");
21899
+ switch (classified._tag) {
21900
+ case "success": return;
21901
+ case "notARepository": return yield* effect.Effect.fail(new NotARepositoryError({ cwd }));
21902
+ case "unknownRef": return yield* effect.Effect.fail(new UnknownRefError({
21903
+ ref: options?.ref ?? "HEAD",
21904
+ cwd
21905
+ }));
21906
+ case "failure": return yield* effect.Effect.fail(classified.error);
21907
+ default: return yield* effect.Effect.die(`Git.reset: unexpected classification "${classified._tag}"`);
21908
+ }
21909
+ });
21910
+ const clean = effect.Effect.fn("Git.clean")(function* (cwd, options) {
21911
+ const directories = options?.directories ?? false;
21912
+ const ignored = options?.ignored ?? false;
21913
+ yield* effect.Effect.annotateCurrentSpan({
21914
+ cwd,
21915
+ directories,
21916
+ ignored
21917
+ });
21918
+ const classified = yield* runFor(GitCommand.clean(directories, ignored, options?.paths ?? []), cwd, "generic");
21919
+ switch (classified._tag) {
21920
+ case "success": return;
21921
+ case "notARepository": return yield* effect.Effect.fail(new NotARepositoryError({ cwd }));
21922
+ case "unknownRef": return yield* effect.Effect.fail(new UnknownRefError({
21923
+ ref: "working tree",
21924
+ cwd
21925
+ }));
21926
+ case "failure": return yield* effect.Effect.fail(classified.error);
21927
+ default: return yield* effect.Effect.die(`Git.clean: unexpected classification "${classified._tag}"`);
21928
+ }
21929
+ });
21930
+ const restore = effect.Effect.fn("Git.restore")(function* (cwd, paths, options) {
21931
+ yield* effect.Effect.annotateCurrentSpan({
21932
+ cwd,
21933
+ count: paths.length,
21934
+ source: options?.source ?? "(index)"
21935
+ });
21936
+ if (options?.source !== void 0) yield* rejectOptionLikeRefs(cwd, [options.source]);
21937
+ const classified = yield* runFor(GitCommand.restore(paths, options?.source, options?.staged ?? false, options?.worktree ?? false), cwd, "generic");
21938
+ switch (classified._tag) {
21939
+ case "success": return;
21940
+ case "notARepository": return yield* effect.Effect.fail(new NotARepositoryError({ cwd }));
21941
+ case "unknownRef": return yield* effect.Effect.fail(new UnknownRefError({
21942
+ ref: options?.source ?? "working tree",
21943
+ cwd
21944
+ }));
21945
+ case "failure": return yield* effect.Effect.fail(classified.error);
21946
+ default: return yield* effect.Effect.die(`Git.restore: unexpected classification "${classified._tag}"`);
21947
+ }
21948
+ });
21949
+ const branchCreate = effect.Effect.fn("Git.branchCreate")(function* (cwd, name, options) {
21950
+ const checkoutBranch = options?.checkout ?? false;
21951
+ const force = options?.force ?? false;
21952
+ yield* effect.Effect.annotateCurrentSpan({
21953
+ cwd,
21954
+ name,
21955
+ startPoint: options?.startPoint ?? "HEAD",
21956
+ checkout: checkoutBranch,
21957
+ force
21958
+ });
21959
+ yield* rejectOptionLikeRefs(cwd, [name, ...options?.startPoint !== void 0 ? [options.startPoint] : []]);
21960
+ const classified = yield* runFor(GitCommand.branchCreate(name, options?.startPoint, checkoutBranch, force), cwd, "generic");
21961
+ switch (classified._tag) {
21962
+ case "success": return;
21963
+ case "notARepository": return yield* effect.Effect.fail(new NotARepositoryError({ cwd }));
21964
+ case "unknownRef": return yield* effect.Effect.fail(new UnknownRefError({
21965
+ ref: options?.startPoint ?? name,
21966
+ cwd
21967
+ }));
21968
+ case "failure": return yield* effect.Effect.fail(classified.error);
21969
+ default: return yield* effect.Effect.die(`Git.branchCreate: unexpected classification "${classified._tag}"`);
21970
+ }
21971
+ });
21972
+ const branchDelete = effect.Effect.fn("Git.branchDelete")(function* (cwd, name, options) {
21973
+ yield* effect.Effect.annotateCurrentSpan({
21974
+ cwd,
21975
+ name,
21976
+ force: options?.force ?? false
21977
+ });
21978
+ yield* rejectOptionLikeRefs(cwd, [name]);
21979
+ const classified = yield* runFor(GitCommand.branchDelete(name, options?.force ?? false), cwd, "generic");
21980
+ switch (classified._tag) {
21981
+ case "success": return;
21982
+ case "notARepository": return yield* effect.Effect.fail(new NotARepositoryError({ cwd }));
21983
+ case "unknownRef": return yield* effect.Effect.fail(new UnknownRefError({
21984
+ ref: name,
21985
+ cwd
21986
+ }));
21987
+ case "failure": return yield* effect.Effect.fail(classified.error);
21988
+ default: return yield* effect.Effect.die(`Git.branchDelete: unexpected classification "${classified._tag}"`);
21989
+ }
21990
+ });
21991
+ const isShallow = effect.Effect.fn("Git.isShallow")(function* (cwd) {
21992
+ yield* effect.Effect.annotateCurrentSpan({ cwd });
21993
+ const classified = yield* runFor(GitCommand.isShallow(), cwd, "generic");
21994
+ switch (classified._tag) {
21995
+ case "success": return classified.output.trim() === "true";
21996
+ case "notARepository": return yield* effect.Effect.fail(new NotARepositoryError({ cwd }));
21997
+ case "unknownRef": return yield* effect.Effect.fail(new UnknownRefError({
21998
+ ref: "HEAD",
21999
+ cwd
22000
+ }));
22001
+ case "failure": return yield* effect.Effect.fail(classified.error);
22002
+ default: return yield* effect.Effect.die(`Git.isShallow: unexpected classification "${classified._tag}"`);
22003
+ }
22004
+ });
22005
+ const fetchUnshallow = effect.Effect.fn("Git.fetchUnshallow")(function* (cwd, options) {
22006
+ const remote = options?.remote ?? "origin";
22007
+ yield* effect.Effect.annotateCurrentSpan({ cwd });
22008
+ yield* rejectOptionLikeRefs(cwd, [remote]);
22009
+ const classified = yield* runFor(GitCommand.fetchUnshallow(remote), cwd, "generic");
22010
+ switch (classified._tag) {
22011
+ case "success": return;
22012
+ case "notARepository": return yield* effect.Effect.fail(new NotARepositoryError({ cwd }));
22013
+ case "unknownRef": return yield* effect.Effect.fail(new UnknownRefError({
22014
+ ref: "--unshallow",
22015
+ cwd
22016
+ }));
22017
+ case "failure": return yield* effect.Effect.fail(classified.error);
22018
+ default: return yield* effect.Effect.die(`Git.fetchUnshallow: unexpected classification "${classified._tag}"`);
22019
+ }
22020
+ });
22021
+ const fetch = effect.Effect.fn("Git.fetch")(function* (cwd, options) {
22022
+ const remote = options.remote ?? "origin";
22023
+ const tag = options.tag ?? false;
22024
+ yield* effect.Effect.annotateCurrentSpan({
22025
+ cwd,
22026
+ ref: options.ref,
22027
+ tag
22028
+ });
22029
+ yield* rejectOptionLikeRefs(cwd, [remote, options.ref]);
22030
+ yield* rejectNonNaturalNumber(cwd, "a fetch depth", options.depth);
22031
+ const classified = yield* runFor(GitCommand.fetch(remote, options.ref, options.depth, tag), cwd, "generic");
22032
+ switch (classified._tag) {
22033
+ case "success": return;
22034
+ case "notARepository": return yield* effect.Effect.fail(new NotARepositoryError({ cwd }));
22035
+ case "unknownRef": return yield* effect.Effect.fail(new UnknownRefError({
22036
+ ref: options.ref,
22037
+ cwd
22038
+ }));
22039
+ case "failure": return yield* effect.Effect.fail(classified.error);
22040
+ default: return yield* effect.Effect.die(`Git.fetch: unexpected classification "${classified._tag}"`);
22041
+ }
22042
+ });
22043
+ const fetchAny = effect.Effect.fn("Git.fetchAny")(function* (cwd, options) {
22044
+ yield* effect.Effect.annotateCurrentSpan({
22045
+ cwd,
22046
+ ref: options.ref
22047
+ });
22048
+ return yield* fetch(cwd, {
22049
+ ...options,
22050
+ tag: true
22051
+ }).pipe(effect.Effect.catchTag(["UnknownRefError", "GitCommandError"], (error) => error._tag === "GitCommandError" && error.kind === "refused" ? effect.Effect.fail(error) : fetch(cwd, options)));
22052
+ });
22053
+ const submoduleUpdate = effect.Effect.fn("Git.submoduleUpdate")(function* (cwd, options) {
22054
+ const init = options?.init ?? false;
22055
+ yield* effect.Effect.annotateCurrentSpan({
22056
+ cwd,
22057
+ init
22058
+ });
22059
+ yield* rejectNonNaturalNumber(cwd, "a submodule update depth", options?.depth);
22060
+ const classified = yield* runFor(GitCommand.submoduleUpdate(init, options?.depth, options?.paths ?? []), cwd, "generic");
22061
+ switch (classified._tag) {
22062
+ case "success": return;
22063
+ case "notARepository": return yield* effect.Effect.fail(new NotARepositoryError({ cwd }));
22064
+ case "unknownRef": return yield* effect.Effect.fail(new UnknownRefError({
22065
+ ref: "submodule update",
22066
+ cwd
22067
+ }));
22068
+ case "failure": return yield* effect.Effect.fail(classified.error);
22069
+ default: return yield* effect.Effect.die(`Git.submoduleUpdate: unexpected classification "${classified._tag}"`);
22070
+ }
22071
+ });
22072
+ const submoduleAdd = effect.Effect.fn("Git.submoduleAdd")(function* (cwd, options) {
22073
+ yield* effect.Effect.annotateCurrentSpan({
22074
+ cwd,
22075
+ path: options.path
22076
+ });
22077
+ yield* rejectNonNaturalNumber(cwd, "a submodule add depth", options.depth);
22078
+ const classified = yield* runFor(GitCommand.submoduleAdd(options.url, options.path, options.depth), cwd, "generic");
22079
+ switch (classified._tag) {
22080
+ case "success": return;
22081
+ case "notARepository": return yield* effect.Effect.fail(new NotARepositoryError({ cwd }));
22082
+ case "unknownRef": return yield* effect.Effect.fail(new UnknownRefError({
22083
+ ref: options.path,
22084
+ cwd
22085
+ }));
22086
+ case "failure": return yield* effect.Effect.fail(classified.error);
22087
+ default: return yield* effect.Effect.die(`Git.submoduleAdd: unexpected classification "${classified._tag}"`);
22088
+ }
22089
+ });
22090
+ const sparseCheckoutSet = effect.Effect.fn("Git.sparseCheckoutSet")(function* (cwd, patterns, options) {
22091
+ yield* effect.Effect.annotateCurrentSpan({
22092
+ cwd,
22093
+ cone: options.cone
22094
+ });
22095
+ yield* rejectOptionLikeRefs(cwd, patterns);
22096
+ const classified = yield* runFor(GitCommand.sparseCheckoutSet(patterns, options.cone), cwd, "generic");
22097
+ switch (classified._tag) {
22098
+ case "success": return;
22099
+ case "notARepository": return yield* effect.Effect.fail(new NotARepositoryError({ cwd }));
22100
+ case "unknownRef": return yield* effect.Effect.fail(new UnknownRefError({
22101
+ ref: "sparse-checkout",
22102
+ cwd
22103
+ }));
22104
+ case "failure": return yield* effect.Effect.fail(classified.error);
22105
+ default: return yield* effect.Effect.die(`Git.sparseCheckoutSet: unexpected classification "${classified._tag}"`);
22106
+ }
22107
+ });
22108
+ const configSet = effect.Effect.fn("Git.configSet")(function* (cwd, key, value, options) {
22109
+ yield* effect.Effect.annotateCurrentSpan({
22110
+ cwd,
22111
+ key,
22112
+ file: options?.file ?? "(repository config)"
22113
+ });
22114
+ yield* rejectOptionLikeRefs(cwd, [key, ...options?.file !== void 0 ? [options.file] : []], [value]);
22115
+ const classified = yield* runFor(GitCommand.configSet(key, value, options?.file), cwd, "generic");
22116
+ switch (classified._tag) {
22117
+ case "success": return;
22118
+ case "notARepository": return yield* effect.Effect.fail(new NotARepositoryError({ cwd }));
22119
+ case "unknownRef": return yield* effect.Effect.fail(new UnknownRefError({
22120
+ ref: key,
22121
+ cwd
22122
+ }));
22123
+ case "failure": return yield* effect.Effect.fail(classified.error);
22124
+ default: return yield* effect.Effect.die(`Git.configSet: unexpected classification "${classified._tag}"`);
22125
+ }
22126
+ });
22127
+ const add = effect.Effect.fn("Git.add")(function* (cwd, paths) {
22128
+ yield* effect.Effect.annotateCurrentSpan({
22129
+ cwd,
22130
+ count: paths.length
22131
+ });
22132
+ const classified = yield* runFor(GitCommand.add(paths), cwd, "generic");
22133
+ switch (classified._tag) {
22134
+ case "success": return;
22135
+ case "notARepository": return yield* effect.Effect.fail(new NotARepositoryError({ cwd }));
22136
+ case "unknownRef": return yield* effect.Effect.fail(new UnknownRefError({
22137
+ ref: "working tree",
22138
+ cwd
22139
+ }));
22140
+ case "failure": return yield* effect.Effect.fail(classified.error);
22141
+ default: return yield* effect.Effect.die(`Git.add: unexpected classification "${classified._tag}"`);
22142
+ }
22143
+ });
22144
+ const defaultBranch = effect.Effect.fn("Git.defaultBranch")(function* (cwd, options) {
22145
+ const remote = options?.remote ?? "origin";
22146
+ yield* effect.Effect.annotateCurrentSpan({
22147
+ cwd,
22148
+ remote
22149
+ });
22150
+ yield* rejectOptionLikeRefs(cwd, [remote]);
22151
+ const classified = yield* runFor(GitCommand.defaultBranch(remote), cwd, "quiet");
22152
+ switch (classified._tag) {
22153
+ case "success": {
22154
+ const short = classified.output.trim();
22155
+ const prefix = `${remote}/`;
22156
+ return effect.Option.some(short.startsWith(prefix) ? short.slice(prefix.length) : short);
22157
+ }
22158
+ case "absent": return effect.Option.none();
22159
+ case "notARepository": return yield* effect.Effect.fail(new NotARepositoryError({ cwd }));
22160
+ case "unknownRef": return yield* effect.Effect.fail(new UnknownRefError({
22161
+ ref: `refs/remotes/${remote}/HEAD`,
22162
+ cwd
22163
+ }));
22164
+ case "failure": return yield* effect.Effect.fail(classified.error);
22165
+ default: return yield* effect.Effect.die(`Git.defaultBranch: unexpected classification "${classified._tag}"`);
22166
+ }
22167
+ });
22168
+ const currentBranch = effect.Effect.fn("Git.currentBranch")(function* (cwd) {
22169
+ yield* effect.Effect.annotateCurrentSpan({ cwd });
22170
+ const classified = yield* runFor(GitCommand.currentBranch(), cwd, "generic");
22171
+ switch (classified._tag) {
22172
+ case "success": {
22173
+ const name = classified.output.trim();
22174
+ return name === "HEAD" ? effect.Option.none() : effect.Option.some(name);
22175
+ }
22176
+ case "notARepository": return yield* effect.Effect.fail(new NotARepositoryError({ cwd }));
22177
+ case "unknownRef": return yield* effect.Effect.fail(new UnknownRefError({
22178
+ ref: "HEAD",
22179
+ cwd
22180
+ }));
22181
+ case "failure": return yield* effect.Effect.fail(classified.error);
22182
+ default: return yield* effect.Effect.die(`Git.currentBranch: unexpected classification "${classified._tag}"`);
22183
+ }
22184
+ });
22185
+ const repoRoot = effect.Effect.fn("Git.repoRoot")(function* (cwd) {
22186
+ yield* effect.Effect.annotateCurrentSpan({ cwd });
22187
+ const classified = yield* runFor(GitCommand.repoRoot(), cwd, "generic");
22188
+ switch (classified._tag) {
22189
+ case "success": return classified.output.trim();
22190
+ case "notARepository": return yield* effect.Effect.fail(new NotARepositoryError({ cwd }));
22191
+ case "unknownRef": return yield* effect.Effect.fail(new UnknownRefError({
22192
+ ref: "working tree",
22193
+ cwd
22194
+ }));
22195
+ case "failure": return yield* effect.Effect.fail(classified.error);
22196
+ default: return yield* effect.Effect.die(`Git.repoRoot: unexpected classification "${classified._tag}"`);
22197
+ }
22198
+ });
22199
+ const configGet = effect.Effect.fn("Git.configGet")(function* (cwd, key) {
22200
+ yield* effect.Effect.annotateCurrentSpan({
22201
+ cwd,
22202
+ key
22203
+ });
22204
+ yield* rejectOptionLikeRefs(cwd, [key]);
22205
+ const classified = yield* runFor(GitCommand.configGet(key), cwd, "quiet");
22206
+ switch (classified._tag) {
22207
+ case "success": return effect.Option.some(classified.output.trim());
22208
+ case "absent": return effect.Option.none();
22209
+ case "notARepository": return yield* effect.Effect.fail(new NotARepositoryError({ cwd }));
22210
+ case "unknownRef": return yield* effect.Effect.fail(new UnknownRefError({
22211
+ ref: key,
22212
+ cwd
22213
+ }));
22214
+ case "failure": return yield* effect.Effect.fail(classified.error);
22215
+ default: return yield* effect.Effect.die(`Git.configGet: unexpected classification "${classified._tag}"`);
22216
+ }
22217
+ });
22218
+ const remoteUrl = effect.Effect.fn("Git.remoteUrl")(function* (cwd, options) {
22219
+ const remote = options?.remote ?? "origin";
22220
+ yield* effect.Effect.annotateCurrentSpan({
22221
+ cwd,
22222
+ remote
22223
+ });
22224
+ yield* rejectOptionLikeRefs(cwd, [remote]);
22225
+ const classified = yield* runFor(GitCommand.remoteUrl(remote), cwd, "noSuchRemote");
22226
+ switch (classified._tag) {
22227
+ case "success": return effect.Option.some(classified.output.trim());
22228
+ case "absent": return effect.Option.none();
22229
+ case "notARepository": return yield* effect.Effect.fail(new NotARepositoryError({ cwd }));
22230
+ case "unknownRef": return yield* effect.Effect.fail(new UnknownRefError({
22231
+ ref: remote,
22232
+ cwd
22233
+ }));
22234
+ case "failure": return yield* effect.Effect.fail(classified.error);
22235
+ default: return yield* effect.Effect.die(`Git.remoteUrl: unexpected classification "${classified._tag}"`);
20667
22236
  }
20668
- const letter = code.charAt(0);
20669
- const status = NAME_STATUS_CODES[letter] ?? "unknown";
20670
- if (letter === "R" || letter === "C") {
20671
- entries.push(NameStatusEntry.make({
20672
- status,
20673
- path: tokens[index + 2] ?? "",
20674
- oldPath: tokens[index + 1] ?? ""
22237
+ });
22238
+ const commitInfo = effect.Effect.fn("Git.commitInfo")(function* (cwd, ref) {
22239
+ const target = ref ?? "HEAD";
22240
+ yield* effect.Effect.annotateCurrentSpan({
22241
+ cwd,
22242
+ ref: target
22243
+ });
22244
+ yield* rejectOptionLikeRefs(cwd, [target]);
22245
+ const classified = yield* runFor(GitCommand.commitInfo(target), cwd, "generic");
22246
+ switch (classified._tag) {
22247
+ case "success": return parseCommitInfo(classified.output);
22248
+ case "notARepository": return yield* effect.Effect.fail(new NotARepositoryError({ cwd }));
22249
+ case "unknownRef": return yield* effect.Effect.fail(new UnknownRefError({
22250
+ ref: target,
22251
+ cwd
20675
22252
  }));
20676
- index += 3;
20677
- } else {
20678
- entries.push(NameStatusEntry.make({
20679
- status,
20680
- path: tokens[index + 1] ?? ""
22253
+ case "failure": return yield* effect.Effect.fail(classified.error);
22254
+ default: return yield* effect.Effect.die(`Git.commitInfo: unexpected classification "${classified._tag}"`);
22255
+ }
22256
+ });
22257
+ const status = effect.Effect.fn("Git.status")(function* (cwd) {
22258
+ yield* effect.Effect.annotateCurrentSpan({ cwd });
22259
+ const classified = yield* runFor(GitCommand.status(), cwd, "generic");
22260
+ switch (classified._tag) {
22261
+ case "success": return parseStatus(classified.output);
22262
+ case "notARepository": return yield* effect.Effect.fail(new NotARepositoryError({ cwd }));
22263
+ case "unknownRef": return yield* effect.Effect.fail(new UnknownRefError({
22264
+ ref: "working tree",
22265
+ cwd
20681
22266
  }));
20682
- index += 2;
22267
+ case "failure": return yield* effect.Effect.fail(classified.error);
22268
+ default: return yield* effect.Effect.die(`Git.status: unexpected classification "${classified._tag}"`);
20683
22269
  }
20684
- }
20685
- return entries;
20686
- };
20687
- /**
20688
- * The metadata of a single commit, read via `git log -1` with NUL-separated
20689
- * `%H` / `%G?` / `%B` placeholders.
20690
- *
20691
- * @public
20692
- */
20693
- var CommitInfo = class extends effect.Schema.Class("CommitInfo")({
20694
- /** The commit's full object id (`%H`). */
20695
- sha: effect.Schema.String,
20696
- /** git's `%G?` signature verdict: Good, Bad, Unknown validity, eXpired, expired-key (Y), Revoked, cannot-check (E), None. */
20697
- signatureStatus: effect.Schema.Literals([
20698
- "G",
20699
- "B",
20700
- "U",
20701
- "X",
20702
- "Y",
20703
- "R",
20704
- "E",
20705
- "N"
20706
- ]),
20707
- /** The raw commit message (`%B`), untrimmed — includes git's trailing format newline. */
20708
- message: effect.Schema.String
20709
- }) {};
20710
- /** One two-letter porcelain v1 status axis code. */
20711
- const porcelainCode = effect.Schema.Literals([
20712
- " ",
20713
- "M",
20714
- "T",
20715
- "A",
20716
- "D",
20717
- "R",
20718
- "C",
20719
- "U",
20720
- "?",
20721
- "!"
20722
- ]);
20723
- /**
20724
- * One entry of a `git status --porcelain -z` listing.
20725
- *
20726
- * @public
20727
- */
20728
- var StatusEntry = class extends effect.Schema.Class("StatusEntry")({
20729
- /** The index-side status code (first porcelain column). */
20730
- x: porcelainCode,
20731
- /** The working-tree-side status code (second porcelain column). */
20732
- y: porcelainCode,
20733
- /** The entry's path — for a rename or copy, the NEW path. */
20734
- path: effect.Schema.String,
20735
- /** The original path; present only on rename/copy entries. */
20736
- origPath: effect.Schema.optionalKey(effect.Schema.String)
20737
- }) {};
20738
- /**
20739
- * Parses `git log -1 --format=%H%x00%G?%x00%B` output: exactly two NUL
20740
- * separators, everything after the second is the raw message, untrimmed.
20741
- * Only ever called on the successful output of this package's own format
20742
- * string, so the separators are guaranteed present.
20743
- */
20744
- const parseCommitInfo = (output) => {
20745
- const first = output.indexOf("\0");
20746
- const second = output.indexOf("\0", first + 1);
20747
- return CommitInfo.make({
20748
- sha: output.slice(0, first),
20749
- signatureStatus: output.slice(first + 1, second),
20750
- message: output.slice(second + 1)
20751
22270
  });
20752
- };
20753
- /**
20754
- * Parses `git status --porcelain -z` output: each entry is `XY <path>`, and a
20755
- * rename/copy entry appends the ORIGINAL path as one extra NUL token AFTER
20756
- * the new path — the opposite order from `diff --name-status`.
20757
- */
20758
- const parseStatus = (output) => {
20759
- const tokens = output.split("\0");
20760
- const entries = [];
20761
- let index = 0;
20762
- while (index < tokens.length) {
20763
- const token = tokens[index] ?? "";
20764
- if (token === "") {
20765
- index += 1;
20766
- continue;
22271
+ const submoduleStatus = effect.Effect.fn("Git.submoduleStatus")(function* (cwd, options) {
22272
+ yield* effect.Effect.annotateCurrentSpan({
22273
+ cwd,
22274
+ recursive: options?.recursive ?? false
22275
+ });
22276
+ const classified = yield* runFor(GitCommand.submoduleStatus(options?.paths ?? [], options?.recursive ?? false), cwd, "generic");
22277
+ switch (classified._tag) {
22278
+ case "success": return parseSubmoduleStatus(classified.output);
22279
+ case "notARepository": return yield* effect.Effect.fail(new NotARepositoryError({ cwd }));
22280
+ case "unknownRef": return yield* effect.Effect.fail(new UnknownRefError({
22281
+ ref: "submodule status",
22282
+ cwd
22283
+ }));
22284
+ case "failure": return yield* effect.Effect.fail(classified.error);
22285
+ default: return yield* effect.Effect.die(`Git.submoduleStatus: unexpected classification "${classified._tag}"`);
20767
22286
  }
20768
- const x = token.charAt(0);
20769
- const y = token.charAt(1);
20770
- const path = token.slice(3);
20771
- if (x === "R" || x === "C" || y === "R" || y === "C") {
20772
- entries.push(StatusEntry.make({
20773
- x,
20774
- y,
20775
- path,
20776
- origPath: tokens[index + 1] ?? ""
22287
+ });
22288
+ const submoduleInit = effect.Effect.fn("Git.submoduleInit")(function* (cwd, options) {
22289
+ yield* effect.Effect.annotateCurrentSpan({ cwd });
22290
+ const classified = yield* runFor(GitCommand.submoduleInit(options?.paths ?? []), cwd, "generic");
22291
+ switch (classified._tag) {
22292
+ case "success": return;
22293
+ case "notARepository": return yield* effect.Effect.fail(new NotARepositoryError({ cwd }));
22294
+ case "unknownRef": return yield* effect.Effect.fail(new UnknownRefError({
22295
+ ref: "submodule init",
22296
+ cwd
20777
22297
  }));
20778
- index += 2;
20779
- } else {
20780
- entries.push(StatusEntry.make({
20781
- x,
20782
- y,
20783
- path
22298
+ case "failure": return yield* effect.Effect.fail(classified.error);
22299
+ default: return yield* effect.Effect.die(`Git.submoduleInit: unexpected classification "${classified._tag}"`);
22300
+ }
22301
+ });
22302
+ const submoduleDeinit = effect.Effect.fn("Git.submoduleDeinit")(function* (cwd, options) {
22303
+ const paths = options.paths ?? [];
22304
+ const all = options.all ?? false;
22305
+ yield* effect.Effect.annotateCurrentSpan({
22306
+ cwd,
22307
+ all,
22308
+ count: paths.length
22309
+ });
22310
+ if (!all && paths.length === 0) return yield* effect.Effect.fail(new GitCommandError({
22311
+ kind: "refused",
22312
+ args: ["submodule", "deinit"],
22313
+ cwd,
22314
+ stderr: "",
22315
+ detail: "refused: submoduleDeinit needs either paths or all: true"
22316
+ }));
22317
+ const classified = yield* runFor(GitCommand.submoduleDeinit(paths, all, options.force ?? false), cwd, "generic");
22318
+ switch (classified._tag) {
22319
+ case "success": return;
22320
+ case "notARepository": return yield* effect.Effect.fail(new NotARepositoryError({ cwd }));
22321
+ case "unknownRef": return yield* effect.Effect.fail(new UnknownRefError({
22322
+ ref: "submodule deinit",
22323
+ cwd
20784
22324
  }));
20785
- index += 1;
22325
+ case "failure": return yield* effect.Effect.fail(classified.error);
22326
+ default: return yield* effect.Effect.die(`Git.submoduleDeinit: unexpected classification "${classified._tag}"`);
20786
22327
  }
20787
- }
20788
- return entries;
20789
- };
20790
- /**
20791
- * Refuse a caller-supplied ref or range that git would parse as an option.
20792
- *
20793
- * Refs are caller-controlled and land in git's argv as positional entries; a
20794
- * value beginning with `-` is read as a flag instead — `checkout("-b")` would
20795
- * CREATE a branch. A bare `--` separator is not a safe fix for every command
20796
- * (it switches `checkout` into pathspec mode), so option-like values are
20797
- * refused outright, before any spawn, as a typed {@link GitCommandError}.
20798
- * `show`'s `path` needs no guard: it is fused after the ref into one
20799
- * `ref:path` token, which cannot begin with `-` unless the ref does.
20800
- */
20801
- const rejectOptionLikeRefs = (cwd, refs) => {
20802
- const offending = refs.find((ref) => ref.startsWith("-"));
20803
- return offending === void 0 ? effect.Effect.void : effect.Effect.fail(new GitCommandError({
20804
- kind: "refused",
20805
- args: [offending],
20806
- cwd,
20807
- stderr: "",
20808
- detail: `refused a ref argument git would parse as an option: ${JSON.stringify(offending)}`
20809
- }));
20810
- };
20811
- /** Builds the `Git.Service` shape over an already-resolved `ChildProcessSpawner`. */
20812
- const make = (spawner) => {
20813
- const runFor = (command, cwd, kind) => runClassified(command, cwd, kind).pipe(effect.Effect.provideService(effect_unstable_process.ChildProcessSpawner.ChildProcessSpawner, spawner));
20814
- const show = effect.Effect.fn("Git.show")(function* (cwd, ref, path) {
22328
+ });
22329
+ const submoduleSync = effect.Effect.fn("Git.submoduleSync")(function* (cwd, options) {
20815
22330
  yield* effect.Effect.annotateCurrentSpan({
20816
22331
  cwd,
20817
- ref,
20818
- path
22332
+ recursive: options?.recursive ?? false
20819
22333
  });
20820
- yield* rejectOptionLikeRefs(cwd, [ref]);
20821
- const command = effect_unstable_process.ChildProcess.setCwd(GitCommand.show(ref, path), cwd);
20822
- const classified = yield* runFor(command, cwd, "show");
22334
+ const classified = yield* runFor(GitCommand.submoduleSync(options?.paths ?? [], options?.recursive ?? false), cwd, "generic");
20823
22335
  switch (classified._tag) {
20824
- case "success": return effect.Option.some(classified.output);
20825
- case "absent": return effect.Option.none();
22336
+ case "success": return;
20826
22337
  case "notARepository": return yield* effect.Effect.fail(new NotARepositoryError({ cwd }));
20827
22338
  case "unknownRef": return yield* effect.Effect.fail(new UnknownRefError({
20828
- ref,
22339
+ ref: "submodule sync",
20829
22340
  cwd
20830
22341
  }));
20831
22342
  case "failure": return yield* effect.Effect.fail(classified.error);
20832
- default: return yield* effect.Effect.die(`Git.show: unexpected classification "${classified._tag}"`);
22343
+ default: return yield* effect.Effect.die(`Git.submoduleSync: unexpected classification "${classified._tag}"`);
20833
22344
  }
20834
22345
  });
20835
- const lsTree = effect.Effect.fn("Git.lsTree")(function* (cwd, ref, options) {
22346
+ const submoduleSetUrl = effect.Effect.fn("Git.submoduleSetUrl")(function* (cwd, path, url) {
20836
22347
  yield* effect.Effect.annotateCurrentSpan({
20837
22348
  cwd,
20838
- ref
22349
+ path
20839
22350
  });
20840
- yield* rejectOptionLikeRefs(cwd, [ref]);
20841
- const command = effect_unstable_process.ChildProcess.setCwd(GitCommand.lsTree(ref, options?.pathspec ?? []), cwd);
20842
- const classified = yield* runFor(command, cwd, "generic");
22351
+ const classified = yield* runFor(GitCommand.submoduleSetUrl(path, url), cwd, "generic");
20843
22352
  switch (classified._tag) {
20844
- case "success": return parseLsTree(classified.output);
22353
+ case "success": return;
20845
22354
  case "notARepository": return yield* effect.Effect.fail(new NotARepositoryError({ cwd }));
20846
22355
  case "unknownRef": return yield* effect.Effect.fail(new UnknownRefError({
20847
- ref,
22356
+ ref: path,
20848
22357
  cwd
20849
22358
  }));
20850
22359
  case "failure": return yield* effect.Effect.fail(classified.error);
20851
- default: return yield* effect.Effect.die(`Git.lsTree: unexpected classification "${classified._tag}"`);
22360
+ default: return yield* effect.Effect.die(`Git.submoduleSetUrl: unexpected classification "${classified._tag}"`);
20852
22361
  }
20853
22362
  });
20854
- const refExists = effect.Effect.fn("Git.refExists")(function* (cwd, ref) {
22363
+ const submoduleSetBranch = effect.Effect.fn("Git.submoduleSetBranch")(function* (cwd, path, options) {
22364
+ const branch = options?.branch;
20855
22365
  yield* effect.Effect.annotateCurrentSpan({
20856
22366
  cwd,
20857
- ref
22367
+ path,
22368
+ branch: branch ?? "(default)"
20858
22369
  });
20859
- yield* rejectOptionLikeRefs(cwd, [ref]);
20860
- const command = effect_unstable_process.ChildProcess.setCwd(GitCommand.refExists(ref), cwd);
20861
- const classified = yield* runFor(command, cwd, "refExists");
22370
+ if (branch !== void 0) yield* rejectOptionLikeRefs(cwd, [branch]);
22371
+ const classified = yield* runFor(GitCommand.submoduleSetBranch(path, branch), cwd, "generic");
22372
+ switch (classified._tag) {
22373
+ case "success": return;
22374
+ case "notARepository": return yield* effect.Effect.fail(new NotARepositoryError({ cwd }));
22375
+ case "unknownRef": return yield* effect.Effect.fail(new UnknownRefError({
22376
+ ref: branch ?? path,
22377
+ cwd
22378
+ }));
22379
+ case "failure": return yield* effect.Effect.fail(classified.error);
22380
+ default: return yield* effect.Effect.die(`Git.submoduleSetBranch: unexpected classification "${classified._tag}"`);
22381
+ }
22382
+ });
22383
+ const submoduleAbsorbgitdirs = effect.Effect.fn("Git.submoduleAbsorbgitdirs")(function* (cwd, options) {
22384
+ yield* effect.Effect.annotateCurrentSpan({ cwd });
22385
+ const classified = yield* runFor(GitCommand.submoduleAbsorbgitdirs(options?.paths ?? []), cwd, "generic");
20862
22386
  switch (classified._tag) {
20863
- case "success": return true;
20864
- case "refMissing": return false;
20865
- case "unknownRef": return false;
22387
+ case "success": return;
20866
22388
  case "notARepository": return yield* effect.Effect.fail(new NotARepositoryError({ cwd }));
22389
+ case "unknownRef": return yield* effect.Effect.fail(new UnknownRefError({
22390
+ ref: "submodule absorbgitdirs",
22391
+ cwd
22392
+ }));
20867
22393
  case "failure": return yield* effect.Effect.fail(classified.error);
20868
- default: return yield* effect.Effect.die(`Git.refExists: unexpected classification "${classified._tag}"`);
22394
+ default: return yield* effect.Effect.die(`Git.submoduleAbsorbgitdirs: unexpected classification "${classified._tag}"`);
20869
22395
  }
20870
22396
  });
20871
- const mergeBase = effect.Effect.fn("Git.mergeBase")(function* (cwd, a, b) {
22397
+ const submoduleForeach = effect.Effect.fn("Git.submoduleForeach")(function* (cwd, command, options) {
20872
22398
  yield* effect.Effect.annotateCurrentSpan({
20873
22399
  cwd,
20874
- a,
20875
- b
22400
+ recursive: options?.recursive ?? false
20876
22401
  });
20877
- yield* rejectOptionLikeRefs(cwd, [a, b]);
20878
- const command = effect_unstable_process.ChildProcess.setCwd(GitCommand.mergeBase(a, b), cwd);
20879
- const classified = yield* runFor(command, cwd, "generic");
22402
+ yield* rejectOptionLikeRefs(cwd, [command]);
22403
+ const classified = yield* runFor(GitCommand.submoduleForeach(command, options?.recursive ?? false), cwd, "generic");
20880
22404
  switch (classified._tag) {
20881
- case "success": return classified.output.trim();
22405
+ case "success": return classified.output;
20882
22406
  case "notARepository": return yield* effect.Effect.fail(new NotARepositoryError({ cwd }));
20883
22407
  case "unknownRef": return yield* effect.Effect.fail(new UnknownRefError({
20884
- ref: `${a}...${b}`,
22408
+ ref: "submodule foreach",
20885
22409
  cwd
20886
22410
  }));
20887
22411
  case "failure": return yield* effect.Effect.fail(classified.error);
20888
- default: return yield* effect.Effect.die(`Git.mergeBase: unexpected classification "${classified._tag}"`);
22412
+ default: return yield* effect.Effect.die(`Git.submoduleForeach: unexpected classification "${classified._tag}"`);
20889
22413
  }
20890
22414
  });
20891
- const changedFiles = effect.Effect.fn("Git.changedFiles")(function* (cwd, options) {
20892
- const relative = options.relative ?? false;
20893
- yield* effect.Effect.annotateCurrentSpan({
20894
- cwd,
20895
- base: options.base,
20896
- head: options.head,
20897
- relative
20898
- });
20899
- yield* rejectOptionLikeRefs(cwd, [options.base, options.head]);
20900
- const command = effect_unstable_process.ChildProcess.setCwd(GitCommand.changedFiles(options.base, options.head, relative), cwd);
20901
- const classified = yield* runFor(command, cwd, "generic");
22415
+ const runVoid = (method, invocation, cwd, refLabel) => effect.Effect.gen(function* () {
22416
+ const classified = yield* runFor(invocation, cwd, "generic");
20902
22417
  switch (classified._tag) {
20903
- case "success": return parseNulSeparated(classified.output);
22418
+ case "success": return;
20904
22419
  case "notARepository": return yield* effect.Effect.fail(new NotARepositoryError({ cwd }));
20905
22420
  case "unknownRef": return yield* effect.Effect.fail(new UnknownRefError({
20906
- ref: `${options.base}...${options.head}`,
22421
+ ref: refLabel,
20907
22422
  cwd
20908
22423
  }));
20909
22424
  case "failure": return yield* effect.Effect.fail(classified.error);
20910
- default: return yield* effect.Effect.die(`Git.changedFiles: unexpected classification "${classified._tag}"`);
22425
+ default: return yield* effect.Effect.die(`${method}: unexpected classification "${classified._tag}"`);
20911
22426
  }
20912
22427
  });
20913
- const collectPaths = (method, command, cwd) => effect.Effect.gen(function* () {
20914
- const classified = yield* runFor(command, cwd, "generic");
22428
+ const runParsed = (method, invocation, cwd, refLabel, kind, parse, absent) => effect.Effect.gen(function* () {
22429
+ const classified = yield* runFor(invocation, cwd, kind);
20915
22430
  switch (classified._tag) {
20916
- case "success": return parseNulSeparated(classified.output);
22431
+ case "success": return parse(classified.output);
22432
+ case "absent":
22433
+ if (absent !== void 0) return absent();
22434
+ return yield* effect.Effect.die(`${method}: unexpected classification "absent"`);
20917
22435
  case "notARepository": return yield* effect.Effect.fail(new NotARepositoryError({ cwd }));
20918
22436
  case "unknownRef": return yield* effect.Effect.fail(new UnknownRefError({
20919
- ref: "working tree",
22437
+ ref: refLabel,
20920
22438
  cwd
20921
22439
  }));
20922
22440
  case "failure": return yield* effect.Effect.fail(classified.error);
20923
22441
  default: return yield* effect.Effect.die(`${method}: unexpected classification "${classified._tag}"`);
20924
22442
  }
20925
22443
  });
20926
- const unstagedChanges = effect.Effect.fn("Git.unstagedChanges")(function* (cwd, options) {
20927
- const relative = options?.relative ?? false;
20928
- yield* effect.Effect.annotateCurrentSpan({
20929
- cwd,
20930
- relative
20931
- });
20932
- return yield* collectPaths("Git.unstagedChanges", effect_unstable_process.ChildProcess.setCwd(GitCommand.unstagedChanges(relative), cwd), cwd);
20933
- });
20934
- const stagedChanges = effect.Effect.fn("Git.stagedChanges")(function* (cwd, options) {
20935
- const relative = options?.relative ?? false;
20936
- yield* effect.Effect.annotateCurrentSpan({
20937
- cwd,
20938
- relative
20939
- });
20940
- return yield* collectPaths("Git.stagedChanges", effect_unstable_process.ChildProcess.setCwd(GitCommand.stagedChanges(relative), cwd), cwd);
20941
- });
20942
- const untrackedFiles = effect.Effect.fn("Git.untrackedFiles")(function* (cwd, options) {
20943
- const relative = options?.relative ?? false;
22444
+ const lsRemote = effect.Effect.fn("Git.lsRemote")(function* (cwd, remote, options) {
20944
22445
  yield* effect.Effect.annotateCurrentSpan({
20945
22446
  cwd,
20946
- relative
22447
+ heads: options?.heads ?? false,
22448
+ tags: options?.tags ?? false,
22449
+ patterns: (options?.patterns ?? []).length
20947
22450
  });
20948
- return yield* collectPaths("Git.untrackedFiles", effect_unstable_process.ChildProcess.setCwd(GitCommand.untrackedFiles(relative), cwd), cwd);
22451
+ yield* rejectOptionLikeRefs(cwd, [remote, ...options?.patterns ?? []]);
22452
+ return yield* runParsed("Git.lsRemote", GitCommand.lsRemote(remote, options?.heads ?? false, options?.tags ?? false, options?.patterns ?? []), cwd, "ls-remote", "generic", parseLsRemote);
20949
22453
  });
20950
- const workingChanges = effect.Effect.fn("Git.workingChanges")(function* (cwd, options) {
22454
+ const remoteAdd = effect.Effect.fn("Git.remoteAdd")(function* (cwd, name, url) {
20951
22455
  yield* effect.Effect.annotateCurrentSpan({
20952
22456
  cwd,
20953
- relative: options?.relative ?? false
22457
+ name
20954
22458
  });
20955
- const unstaged = yield* unstagedChanges(cwd, options);
20956
- const staged = yield* stagedChanges(cwd, options);
20957
- const untracked = yield* untrackedFiles(cwd, options);
20958
- return [.../* @__PURE__ */ new Set([
20959
- ...unstaged,
20960
- ...staged,
20961
- ...untracked
20962
- ])];
22459
+ yield* rejectOptionLikeRefs(cwd, [name, url]);
22460
+ return yield* runVoid("Git.remoteAdd", GitCommand.remoteAdd(name, url), cwd, name);
20963
22461
  });
20964
- const nameStatus = effect.Effect.fn("Git.nameStatus")(function* (cwd, options) {
20965
- const relative = options.relative ?? false;
22462
+ const remoteRemove = effect.Effect.fn("Git.remoteRemove")(function* (cwd, name) {
20966
22463
  yield* effect.Effect.annotateCurrentSpan({
20967
22464
  cwd,
20968
- base: options.base,
20969
- head: options.head ?? "(working tree)",
20970
- relative
22465
+ name
20971
22466
  });
20972
- yield* rejectOptionLikeRefs(cwd, options.head === void 0 ? [options.base] : [options.base, options.head]);
20973
- const command = effect_unstable_process.ChildProcess.setCwd(GitCommand.nameStatus(options.base, options.head, relative), cwd);
20974
- const classified = yield* runFor(command, cwd, "generic");
20975
- switch (classified._tag) {
20976
- case "success": return parseNameStatus(classified.output);
20977
- case "notARepository": return yield* effect.Effect.fail(new NotARepositoryError({ cwd }));
20978
- case "unknownRef": return yield* effect.Effect.fail(new UnknownRefError({
20979
- ref: options.head === void 0 ? options.base : `${options.base}...${options.head}`,
20980
- cwd
20981
- }));
20982
- case "failure": return yield* effect.Effect.fail(classified.error);
20983
- default: return yield* effect.Effect.die(`Git.nameStatus: unexpected classification "${classified._tag}"`);
20984
- }
22467
+ yield* rejectOptionLikeRefs(cwd, [name]);
22468
+ return yield* runVoid("Git.remoteRemove", GitCommand.remoteRemove(name), cwd, name);
20985
22469
  });
20986
- const revParse = effect.Effect.fn("Git.revParse")(function* (cwd, ref) {
22470
+ const remoteSetUrl = effect.Effect.fn("Git.remoteSetUrl")(function* (cwd, name, url) {
20987
22471
  yield* effect.Effect.annotateCurrentSpan({
20988
22472
  cwd,
20989
- ref
22473
+ name
20990
22474
  });
20991
- yield* rejectOptionLikeRefs(cwd, [ref]);
20992
- const command = effect_unstable_process.ChildProcess.setCwd(GitCommand.revParse(ref), cwd);
20993
- const classified = yield* runFor(command, cwd, "generic");
20994
- switch (classified._tag) {
20995
- case "success": return classified.output.trim();
20996
- case "notARepository": return yield* effect.Effect.fail(new NotARepositoryError({ cwd }));
20997
- case "unknownRef": return yield* effect.Effect.fail(new UnknownRefError({
20998
- ref,
20999
- cwd
21000
- }));
21001
- case "failure": return yield* effect.Effect.fail(classified.error);
21002
- default: return yield* effect.Effect.die(`Git.revParse: unexpected classification "${classified._tag}"`);
21003
- }
22475
+ yield* rejectOptionLikeRefs(cwd, [name, url]);
22476
+ return yield* runVoid("Git.remoteSetUrl", GitCommand.remoteSetUrl(name, url), cwd, name);
21004
22477
  });
21005
- const checkout = effect.Effect.fn("Git.checkout")(function* (cwd, ref, options) {
21006
- const detach = options?.detach ?? false;
22478
+ const stashPush = effect.Effect.fn("Git.stashPush")(function* (cwd, options) {
21007
22479
  yield* effect.Effect.annotateCurrentSpan({
21008
22480
  cwd,
21009
- ref,
21010
- detach
22481
+ includeUntracked: options?.includeUntracked ?? false
21011
22482
  });
21012
- yield* rejectOptionLikeRefs(cwd, [ref]);
21013
- const command = effect_unstable_process.ChildProcess.setCwd(GitCommand.checkout(ref, detach), cwd);
21014
- const classified = yield* runFor(command, cwd, "generic");
21015
- switch (classified._tag) {
21016
- case "success": return;
21017
- case "notARepository": return yield* effect.Effect.fail(new NotARepositoryError({ cwd }));
21018
- case "unknownRef": return yield* effect.Effect.fail(new UnknownRefError({
21019
- ref,
21020
- cwd
21021
- }));
21022
- case "failure": return yield* effect.Effect.fail(classified.error);
21023
- default: return yield* effect.Effect.die(`Git.checkout: unexpected classification "${classified._tag}"`);
21024
- }
22483
+ return yield* runVoid("Git.stashPush", GitCommand.stashPush(options?.message, options?.includeUntracked ?? false, options?.paths ?? []), cwd, "stash");
21025
22484
  });
21026
- const fetch = effect.Effect.fn("Git.fetch")(function* (cwd, options) {
21027
- const remote = options.remote ?? "origin";
21028
- const tag = options.tag ?? false;
22485
+ const stashRestore = (method, invocation) => effect.Effect.fn(method)(function* (cwd, options) {
21029
22486
  yield* effect.Effect.annotateCurrentSpan({
21030
22487
  cwd,
21031
- remote,
21032
- ref: options.ref,
21033
- tag
22488
+ index: options?.index ?? 0
21034
22489
  });
21035
- yield* rejectOptionLikeRefs(cwd, [remote, options.ref]);
21036
- const command = effect_unstable_process.ChildProcess.setCwd(GitCommand.fetch(remote, options.ref, options.depth, tag), cwd);
21037
- const classified = yield* runFor(command, cwd, "generic");
22490
+ yield* rejectNonNaturalNumber(cwd, "a stash index", options?.index);
22491
+ const classified = yield* runFor(invocation(options?.index), cwd, "merge");
21038
22492
  switch (classified._tag) {
21039
22493
  case "success": return;
22494
+ case "dirtyWorktree": return yield* effect.Effect.fail(new DirtyWorktreeError({ cwd }));
22495
+ case "mergeConflict": return yield* effect.Effect.fail(new MergeConflictError({ cwd }));
21040
22496
  case "notARepository": return yield* effect.Effect.fail(new NotARepositoryError({ cwd }));
21041
22497
  case "unknownRef": return yield* effect.Effect.fail(new UnknownRefError({
21042
- ref: options.ref,
22498
+ ref: "stash",
21043
22499
  cwd
21044
22500
  }));
21045
22501
  case "failure": return yield* effect.Effect.fail(classified.error);
21046
- default: return yield* effect.Effect.die(`Git.fetch: unexpected classification "${classified._tag}"`);
22502
+ default: return yield* effect.Effect.die(`${method}: unexpected classification "${classified._tag}"`);
21047
22503
  }
21048
22504
  });
21049
22505
  return {
@@ -21056,254 +22512,235 @@ const make = (spawner) => {
21056
22512
  revParse,
21057
22513
  checkout,
21058
22514
  fetch,
21059
- fetchAny: effect.Effect.fn("Git.fetchAny")(function* (cwd, options) {
21060
- const remote = options.remote ?? "origin";
22515
+ fetchAny,
22516
+ fetchUnshallow,
22517
+ isShallow,
22518
+ reset,
22519
+ clean,
22520
+ restore,
22521
+ branchCreate,
22522
+ branchDelete,
22523
+ submoduleUpdate,
22524
+ submoduleAdd,
22525
+ submoduleStatus,
22526
+ submoduleInit,
22527
+ submoduleDeinit,
22528
+ submoduleSync,
22529
+ submoduleSetUrl,
22530
+ submoduleSetBranch,
22531
+ submoduleAbsorbgitdirs,
22532
+ submoduleForeach,
22533
+ sparseCheckoutSet,
22534
+ configSet,
22535
+ add,
22536
+ nameStatus,
22537
+ unstagedChanges,
22538
+ stagedChanges,
22539
+ untrackedFiles,
22540
+ defaultBranch,
22541
+ currentBranch,
22542
+ repoRoot,
22543
+ configGet,
22544
+ remoteUrl,
22545
+ commitInfo,
22546
+ status,
22547
+ lsRemote,
22548
+ remoteAdd,
22549
+ remoteRemove,
22550
+ remoteSetUrl,
22551
+ stashPush,
22552
+ stashPop: stashRestore("Git.stashPop", GitCommand.stashPop),
22553
+ stashApply: stashRestore("Git.stashApply", GitCommand.stashApply),
22554
+ stashDrop: effect.Effect.fn("Git.stashDrop")(function* (cwd, options) {
21061
22555
  yield* effect.Effect.annotateCurrentSpan({
21062
22556
  cwd,
21063
- remote,
21064
- ref: options.ref
22557
+ index: options?.index ?? 0
21065
22558
  });
21066
- return yield* fetch(cwd, {
21067
- ...options,
21068
- tag: true
21069
- }).pipe(effect.Effect.catchTag(["UnknownRefError", "GitCommandError"], (error) => error._tag === "GitCommandError" && error.kind === "refused" ? effect.Effect.fail(error) : fetch(cwd, options)));
22559
+ yield* rejectNonNaturalNumber(cwd, "a stash index", options?.index);
22560
+ return yield* runVoid("Git.stashDrop", GitCommand.stashDrop(options?.index), cwd, "stash");
21070
22561
  }),
21071
- submoduleUpdate: effect.Effect.fn("Git.submoduleUpdate")(function* (cwd, options) {
21072
- const init = options?.init ?? false;
22562
+ stashList: effect.Effect.fn("Git.stashList")(function* (cwd) {
22563
+ yield* effect.Effect.annotateCurrentSpan({ cwd });
22564
+ return yield* runParsed("Git.stashList", GitCommand.stashList(), cwd, "stash", "generic", parseStashList);
22565
+ }),
22566
+ branchList: effect.Effect.fn("Git.branchList")(function* (cwd, options) {
21073
22567
  yield* effect.Effect.annotateCurrentSpan({
21074
22568
  cwd,
21075
- init
22569
+ remotes: options?.remotes ?? false,
22570
+ all: options?.all ?? false
21076
22571
  });
21077
- const command = effect_unstable_process.ChildProcess.setCwd(GitCommand.submoduleUpdate(init, options?.depth, options?.paths ?? []), cwd);
21078
- const classified = yield* runFor(command, cwd, "generic");
21079
- switch (classified._tag) {
21080
- case "success": return;
21081
- case "notARepository": return yield* effect.Effect.fail(new NotARepositoryError({ cwd }));
21082
- case "unknownRef": return yield* effect.Effect.fail(new UnknownRefError({
21083
- ref: "submodule update",
21084
- cwd
21085
- }));
21086
- case "failure": return yield* effect.Effect.fail(classified.error);
21087
- default: return yield* effect.Effect.die(`Git.submoduleUpdate: unexpected classification "${classified._tag}"`);
21088
- }
22572
+ return yield* runParsed("Git.branchList", GitCommand.branchList(options?.remotes ?? false, options?.all ?? false), cwd, "branches", "generic", parseBranchList);
21089
22573
  }),
21090
- submoduleAdd: effect.Effect.fn("Git.submoduleAdd")(function* (cwd, options) {
22574
+ tagCreate: effect.Effect.fn("Git.tagCreate")(function* (cwd, name, options) {
21091
22575
  yield* effect.Effect.annotateCurrentSpan({
21092
22576
  cwd,
21093
- url: options.url,
21094
- path: options.path
22577
+ name,
22578
+ ref: options?.ref ?? "HEAD",
22579
+ force: options?.force ?? false
21095
22580
  });
21096
- const command = effect_unstable_process.ChildProcess.setCwd(GitCommand.submoduleAdd(options.url, options.path, options.depth), cwd);
21097
- const classified = yield* runFor(command, cwd, "generic");
21098
- switch (classified._tag) {
21099
- case "success": return;
21100
- case "notARepository": return yield* effect.Effect.fail(new NotARepositoryError({ cwd }));
21101
- case "unknownRef": return yield* effect.Effect.fail(new UnknownRefError({
21102
- ref: options.url,
21103
- cwd
21104
- }));
21105
- case "failure": return yield* effect.Effect.fail(classified.error);
21106
- default: return yield* effect.Effect.die(`Git.submoduleAdd: unexpected classification "${classified._tag}"`);
21107
- }
22581
+ yield* rejectOptionLikeRefs(cwd, [name, ...options?.ref !== void 0 ? [options.ref] : []]);
22582
+ return yield* runVoid("Git.tagCreate", GitCommand.tagCreate(name, options?.ref, options?.message, options?.force ?? false), cwd, options?.ref ?? name);
21108
22583
  }),
21109
- sparseCheckoutSet: effect.Effect.fn("Git.sparseCheckoutSet")(function* (cwd, patterns, options) {
22584
+ tagDelete: effect.Effect.fn("Git.tagDelete")(function* (cwd, name) {
21110
22585
  yield* effect.Effect.annotateCurrentSpan({
21111
22586
  cwd,
21112
- cone: options.cone
22587
+ name
21113
22588
  });
21114
- yield* rejectOptionLikeRefs(cwd, patterns);
21115
- const command = effect_unstable_process.ChildProcess.setCwd(GitCommand.sparseCheckoutSet(patterns, options.cone), cwd);
21116
- const classified = yield* runFor(command, cwd, "generic");
21117
- switch (classified._tag) {
21118
- case "success": return;
21119
- case "notARepository": return yield* effect.Effect.fail(new NotARepositoryError({ cwd }));
21120
- case "unknownRef": return yield* effect.Effect.fail(new UnknownRefError({
21121
- ref: "sparse-checkout",
21122
- cwd
21123
- }));
21124
- case "failure": return yield* effect.Effect.fail(classified.error);
21125
- default: return yield* effect.Effect.die(`Git.sparseCheckoutSet: unexpected classification "${classified._tag}"`);
21126
- }
22589
+ yield* rejectOptionLikeRefs(cwd, [name]);
22590
+ return yield* runVoid("Git.tagDelete", GitCommand.tagDelete(name), cwd, name);
22591
+ }),
22592
+ tagList: effect.Effect.fn("Git.tagList")(function* (cwd, options) {
22593
+ yield* effect.Effect.annotateCurrentSpan({ cwd });
22594
+ yield* rejectOptionLikeRefs(cwd, options?.pattern !== void 0 ? [options.pattern] : []);
22595
+ return yield* runParsed("Git.tagList", GitCommand.tagList(options?.pattern), cwd, "tags", "generic", (output) => output.split("\n").filter((line) => line.length > 0));
21127
22596
  }),
21128
- configSet: effect.Effect.fn("Git.configSet")(function* (cwd, key, value, options) {
22597
+ forEachRef: effect.Effect.fn("Git.forEachRef")(function* (cwd, options) {
21129
22598
  yield* effect.Effect.annotateCurrentSpan({
21130
22599
  cwd,
21131
- key,
21132
- file: options?.file ?? "(repository config)"
22600
+ patterns: (options?.patterns ?? []).length
21133
22601
  });
21134
- yield* rejectOptionLikeRefs(cwd, [
21135
- key,
21136
- value,
21137
- ...options?.file !== void 0 ? [options.file] : []
21138
- ]);
21139
- const command = effect_unstable_process.ChildProcess.setCwd(GitCommand.configSet(key, value, options?.file), cwd);
21140
- const classified = yield* runFor(command, cwd, "generic");
21141
- switch (classified._tag) {
21142
- case "success": return;
21143
- case "notARepository": return yield* effect.Effect.fail(new NotARepositoryError({ cwd }));
21144
- case "unknownRef": return yield* effect.Effect.fail(new UnknownRefError({
21145
- ref: key,
21146
- cwd
21147
- }));
21148
- case "failure": return yield* effect.Effect.fail(classified.error);
21149
- default: return yield* effect.Effect.die(`Git.configSet: unexpected classification "${classified._tag}"`);
21150
- }
22602
+ yield* rejectOptionLikeRefs(cwd, options?.patterns ?? []);
22603
+ return yield* runParsed("Git.forEachRef", GitCommand.forEachRef(options?.patterns ?? []), cwd, "for-each-ref", "generic", parseForEachRef);
21151
22604
  }),
21152
- add: effect.Effect.fn("Git.add")(function* (cwd, paths) {
22605
+ revList: effect.Effect.fn("Git.revList")(function* (cwd, ref, options) {
21153
22606
  yield* effect.Effect.annotateCurrentSpan({
21154
22607
  cwd,
21155
- count: paths.length
22608
+ ref,
22609
+ firstParent: options?.firstParent ?? false
21156
22610
  });
21157
- const command = effect_unstable_process.ChildProcess.setCwd(GitCommand.add(paths), cwd);
21158
- const classified = yield* runFor(command, cwd, "generic");
22611
+ yield* rejectOptionLikeRefs(cwd, [ref]);
22612
+ yield* rejectNonNaturalNumber(cwd, "a rev-list limit", options?.limit);
22613
+ return yield* runParsed("Git.revList", GitCommand.revList(ref, options?.limit, options?.firstParent ?? false), cwd, ref, "generic", (output) => output.split("\n").filter((line) => line.length > 0));
22614
+ }),
22615
+ commit: effect.Effect.fn("Git.commit")(function* (cwd, message, options) {
22616
+ yield* effect.Effect.annotateCurrentSpan({
22617
+ cwd,
22618
+ amend: options?.amend ?? false
22619
+ });
22620
+ return yield* runVoid("Git.commit", GitCommand.commit(message, options?.all ?? false, options?.allowEmpty ?? false, options?.amend ?? false, options?.author), cwd, "HEAD");
22621
+ }),
22622
+ push: effect.Effect.fn("Git.push")(function* (cwd, options) {
22623
+ const remote = options?.remote ?? "origin";
22624
+ yield* effect.Effect.annotateCurrentSpan({
22625
+ cwd,
22626
+ refspec: options?.refspec ?? "(current branch)",
22627
+ forceWithLease: options?.forceWithLease ?? false
22628
+ });
22629
+ yield* rejectOptionLikeRefs(cwd, [remote, ...options?.refspec !== void 0 ? [options.refspec] : []]);
22630
+ const classified = yield* runFor(GitCommand.push(remote, options?.refspec, options?.force ?? false, options?.forceWithLease ?? false, options?.tags ?? false, options?.setUpstream ?? false), cwd, "push");
21159
22631
  switch (classified._tag) {
21160
22632
  case "success": return;
22633
+ case "nonFastForward": return yield* effect.Effect.fail(new NonFastForwardError({
22634
+ cwd,
22635
+ ...options?.refspec !== void 0 ? { refspec: options.refspec } : {}
22636
+ }));
21161
22637
  case "notARepository": return yield* effect.Effect.fail(new NotARepositoryError({ cwd }));
21162
22638
  case "unknownRef": return yield* effect.Effect.fail(new UnknownRefError({
21163
- ref: "working tree",
22639
+ ref: options?.refspec ?? "HEAD",
21164
22640
  cwd
21165
22641
  }));
21166
22642
  case "failure": return yield* effect.Effect.fail(classified.error);
21167
- default: return yield* effect.Effect.die(`Git.add: unexpected classification "${classified._tag}"`);
22643
+ default: return yield* effect.Effect.die(`Git.push: unexpected classification "${classified._tag}"`);
21168
22644
  }
21169
22645
  }),
21170
- nameStatus,
21171
- unstagedChanges,
21172
- stagedChanges,
21173
- untrackedFiles,
21174
- defaultBranch: effect.Effect.fn("Git.defaultBranch")(function* (cwd, options) {
22646
+ pull: effect.Effect.fn("Git.pull")(function* (cwd, options) {
21175
22647
  const remote = options?.remote ?? "origin";
21176
22648
  yield* effect.Effect.annotateCurrentSpan({
21177
22649
  cwd,
21178
- remote
22650
+ ref: options?.ref ?? "(upstream)",
22651
+ rebase: options?.rebase ?? false
21179
22652
  });
21180
- yield* rejectOptionLikeRefs(cwd, [remote]);
21181
- const command = effect_unstable_process.ChildProcess.setCwd(GitCommand.defaultBranch(remote), cwd);
21182
- const classified = yield* runFor(command, cwd, "quiet");
22653
+ yield* rejectOptionLikeRefs(cwd, [remote, ...options?.ref !== void 0 ? [options.ref] : []]);
22654
+ const classified = yield* runFor(GitCommand.pull(remote, options?.ref, options?.rebase ?? false, options?.ffOnly ?? false), cwd, "merge");
21183
22655
  switch (classified._tag) {
21184
- case "success": {
21185
- const short = classified.output.trim();
21186
- const prefix = `${remote}/`;
21187
- return effect.Option.some(short.startsWith(prefix) ? short.slice(prefix.length) : short);
21188
- }
21189
- case "absent": return effect.Option.none();
22656
+ case "success": return;
22657
+ case "dirtyWorktree": return yield* effect.Effect.fail(new DirtyWorktreeError({ cwd }));
22658
+ case "mergeConflict": return yield* effect.Effect.fail(new MergeConflictError({ cwd }));
21190
22659
  case "notARepository": return yield* effect.Effect.fail(new NotARepositoryError({ cwd }));
21191
22660
  case "unknownRef": return yield* effect.Effect.fail(new UnknownRefError({
21192
- ref: `refs/remotes/${remote}/HEAD`,
22661
+ ref: options?.ref ?? "(upstream)",
21193
22662
  cwd
21194
22663
  }));
21195
22664
  case "failure": return yield* effect.Effect.fail(classified.error);
21196
- default: return yield* effect.Effect.die(`Git.defaultBranch: unexpected classification "${classified._tag}"`);
22665
+ default: return yield* effect.Effect.die(`Git.pull: unexpected classification "${classified._tag}"`);
21197
22666
  }
21198
22667
  }),
21199
- currentBranch: effect.Effect.fn("Git.currentBranch")(function* (cwd) {
21200
- yield* effect.Effect.annotateCurrentSpan({ cwd });
21201
- const command = effect_unstable_process.ChildProcess.setCwd(GitCommand.currentBranch(), cwd);
21202
- const classified = yield* runFor(command, cwd, "generic");
21203
- switch (classified._tag) {
21204
- case "success": {
21205
- const name = classified.output.trim();
21206
- return name === "HEAD" ? effect.Option.none() : effect.Option.some(name);
21207
- }
21208
- case "notARepository": return yield* effect.Effect.fail(new NotARepositoryError({ cwd }));
21209
- case "unknownRef": return yield* effect.Effect.fail(new UnknownRefError({
21210
- ref: "HEAD",
21211
- cwd
21212
- }));
21213
- case "failure": return yield* effect.Effect.fail(classified.error);
21214
- default: return yield* effect.Effect.die(`Git.currentBranch: unexpected classification "${classified._tag}"`);
21215
- }
22668
+ configList: effect.Effect.fn("Git.configList")(function* (cwd, options) {
22669
+ yield* effect.Effect.annotateCurrentSpan({
22670
+ cwd,
22671
+ file: options?.file ?? "(repository config)"
22672
+ });
22673
+ yield* rejectOptionLikeRefs(cwd, options?.file !== void 0 ? [options.file] : []);
22674
+ return yield* runParsed("Git.configList", GitCommand.configList(options?.file), cwd, "config", "generic", parseConfigList);
21216
22675
  }),
21217
- repoRoot: effect.Effect.fn("Git.repoRoot")(function* (cwd) {
21218
- yield* effect.Effect.annotateCurrentSpan({ cwd });
21219
- const command = effect_unstable_process.ChildProcess.setCwd(GitCommand.repoRoot(), cwd);
21220
- const classified = yield* runFor(command, cwd, "generic");
21221
- switch (classified._tag) {
21222
- case "success": return classified.output.trim();
21223
- case "notARepository": return yield* effect.Effect.fail(new NotARepositoryError({ cwd }));
21224
- case "unknownRef": return yield* effect.Effect.fail(new UnknownRefError({
21225
- ref: "working tree",
21226
- cwd
21227
- }));
21228
- case "failure": return yield* effect.Effect.fail(classified.error);
21229
- default: return yield* effect.Effect.die(`Git.repoRoot: unexpected classification "${classified._tag}"`);
21230
- }
22676
+ configGetAll: effect.Effect.fn("Git.configGetAll")(function* (cwd, key, options) {
22677
+ yield* effect.Effect.annotateCurrentSpan({
22678
+ cwd,
22679
+ key,
22680
+ file: options?.file ?? "(repository config)"
22681
+ });
22682
+ yield* rejectOptionLikeRefs(cwd, [key, ...options?.file !== void 0 ? [options.file] : []]);
22683
+ return yield* runParsed("Git.configGetAll", GitCommand.configGetAll(key, options?.file), cwd, key, "quiet", parseNulSeparated, () => []);
21231
22684
  }),
21232
- configGet: effect.Effect.fn("Git.configGet")(function* (cwd, key) {
22685
+ configUnset: effect.Effect.fn("Git.configUnset")(function* (cwd, key, options) {
21233
22686
  yield* effect.Effect.annotateCurrentSpan({
21234
22687
  cwd,
21235
- key
22688
+ key,
22689
+ file: options?.file ?? "(repository config)"
21236
22690
  });
21237
- yield* rejectOptionLikeRefs(cwd, [key]);
21238
- const command = effect_unstable_process.ChildProcess.setCwd(GitCommand.configGet(key), cwd);
21239
- const classified = yield* runFor(command, cwd, "quiet");
21240
- switch (classified._tag) {
21241
- case "success": return effect.Option.some(classified.output.trim());
21242
- case "absent": return effect.Option.none();
21243
- case "notARepository": return yield* effect.Effect.fail(new NotARepositoryError({ cwd }));
21244
- case "unknownRef": return yield* effect.Effect.fail(new UnknownRefError({
21245
- ref: key,
21246
- cwd
21247
- }));
21248
- case "failure": return yield* effect.Effect.fail(classified.error);
21249
- default: return yield* effect.Effect.die(`Git.configGet: unexpected classification "${classified._tag}"`);
21250
- }
22691
+ yield* rejectOptionLikeRefs(cwd, [key, ...options?.file !== void 0 ? [options.file] : []]);
22692
+ return yield* runVoid("Git.configUnset", GitCommand.configUnset(key, options?.file, options?.all ?? false), cwd, key);
21251
22693
  }),
21252
- remoteUrl: effect.Effect.fn("Git.remoteUrl")(function* (cwd, options) {
21253
- const remote = options?.remote ?? "origin";
22694
+ rm: effect.Effect.fn("Git.rm")(function* (cwd, paths, options) {
21254
22695
  yield* effect.Effect.annotateCurrentSpan({
21255
22696
  cwd,
21256
- remote
22697
+ count: paths.length,
22698
+ cached: options?.cached ?? false
21257
22699
  });
21258
- yield* rejectOptionLikeRefs(cwd, [remote]);
21259
- const command = effect_unstable_process.ChildProcess.setCwd(GitCommand.remoteUrl(remote), cwd);
21260
- const classified = yield* runFor(command, cwd, "noSuchRemote");
21261
- switch (classified._tag) {
21262
- case "success": return effect.Option.some(classified.output.trim());
21263
- case "absent": return effect.Option.none();
21264
- case "notARepository": return yield* effect.Effect.fail(new NotARepositoryError({ cwd }));
21265
- case "unknownRef": return yield* effect.Effect.fail(new UnknownRefError({
21266
- ref: remote,
21267
- cwd
21268
- }));
21269
- case "failure": return yield* effect.Effect.fail(classified.error);
21270
- default: return yield* effect.Effect.die(`Git.remoteUrl: unexpected classification "${classified._tag}"`);
21271
- }
22700
+ return yield* runVoid("Git.rm", GitCommand.rm(paths, options?.cached ?? false, options?.recursive ?? false, options?.force ?? false), cwd, "working tree");
21272
22701
  }),
21273
- commitInfo: effect.Effect.fn("Git.commitInfo")(function* (cwd, ref) {
21274
- const target = ref ?? "HEAD";
22702
+ mv: effect.Effect.fn("Git.mv")(function* (cwd, source, destination, options) {
21275
22703
  yield* effect.Effect.annotateCurrentSpan({
21276
22704
  cwd,
21277
- ref: target
22705
+ source,
22706
+ destination
21278
22707
  });
21279
- yield* rejectOptionLikeRefs(cwd, [target]);
21280
- const command = effect_unstable_process.ChildProcess.setCwd(GitCommand.commitInfo(target), cwd);
21281
- const classified = yield* runFor(command, cwd, "generic");
21282
- switch (classified._tag) {
21283
- case "success": return parseCommitInfo(classified.output);
21284
- case "notARepository": return yield* effect.Effect.fail(new NotARepositoryError({ cwd }));
21285
- case "unknownRef": return yield* effect.Effect.fail(new UnknownRefError({
21286
- ref: target,
21287
- cwd
21288
- }));
21289
- case "failure": return yield* effect.Effect.fail(classified.error);
21290
- default: return yield* effect.Effect.die(`Git.commitInfo: unexpected classification "${classified._tag}"`);
21291
- }
22708
+ return yield* runVoid("Git.mv", GitCommand.mv(source, destination, options?.force ?? false), cwd, "working tree");
22709
+ }),
22710
+ checkIgnore: effect.Effect.fn("Git.checkIgnore")(function* (cwd, paths) {
22711
+ yield* effect.Effect.annotateCurrentSpan({
22712
+ cwd,
22713
+ count: paths.length
22714
+ });
22715
+ return yield* runParsed("Git.checkIgnore", GitCommand.checkIgnore(paths), cwd, "check-ignore", "quiet", parseNulSeparated, () => []);
21292
22716
  }),
21293
- status: effect.Effect.fn("Git.status")(function* (cwd) {
22717
+ worktreeAdd: effect.Effect.fn("Git.worktreeAdd")(function* (cwd, path, options) {
22718
+ yield* effect.Effect.annotateCurrentSpan({
22719
+ cwd,
22720
+ path,
22721
+ ref: options?.ref ?? "(default)"
22722
+ });
22723
+ yield* rejectOptionLikeRefs(cwd, [path, ...options?.ref !== void 0 ? [options.ref] : []]);
22724
+ return yield* runVoid("Git.worktreeAdd", GitCommand.worktreeAdd(path, options?.ref, options?.detach ?? false, options?.force ?? false), cwd, options?.ref ?? path);
22725
+ }),
22726
+ worktreeList: effect.Effect.fn("Git.worktreeList")(function* (cwd) {
21294
22727
  yield* effect.Effect.annotateCurrentSpan({ cwd });
21295
- const command = effect_unstable_process.ChildProcess.setCwd(GitCommand.status(), cwd);
21296
- const classified = yield* runFor(command, cwd, "generic");
21297
- switch (classified._tag) {
21298
- case "success": return parseStatus(classified.output);
21299
- case "notARepository": return yield* effect.Effect.fail(new NotARepositoryError({ cwd }));
21300
- case "unknownRef": return yield* effect.Effect.fail(new UnknownRefError({
21301
- ref: "working tree",
21302
- cwd
21303
- }));
21304
- case "failure": return yield* effect.Effect.fail(classified.error);
21305
- default: return yield* effect.Effect.die(`Git.status: unexpected classification "${classified._tag}"`);
21306
- }
22728
+ return yield* runParsed("Git.worktreeList", GitCommand.worktreeList(), cwd, "worktrees", "generic", parseWorktreeList);
22729
+ }),
22730
+ worktreeRemove: effect.Effect.fn("Git.worktreeRemove")(function* (cwd, path, options) {
22731
+ yield* effect.Effect.annotateCurrentSpan({
22732
+ cwd,
22733
+ path
22734
+ });
22735
+ yield* rejectOptionLikeRefs(cwd, [path]);
22736
+ return yield* runVoid("Git.worktreeRemove", GitCommand.worktreeRemove(path, options?.force ?? false), cwd, path);
22737
+ }),
22738
+ lsFiles: effect.Effect.fn("Git.lsFiles")(function* (cwd, options) {
22739
+ yield* effect.Effect.annotateCurrentSpan({
22740
+ cwd,
22741
+ patterns: (options?.pathspec ?? []).length
22742
+ });
22743
+ return yield* runParsed("Git.lsFiles", GitCommand.lsFiles(options?.pathspec ?? []), cwd, "index", "generic", parseLsFiles);
21307
22744
  })
21308
22745
  };
21309
22746
  };
@@ -21315,17 +22752,23 @@ const make = (spawner) => {
21315
22752
  const notStubbed = (method) => () => effect.Effect.die(/* @__PURE__ */ new Error(`Git.makeTest: ${method}() was called but not stubbed — no honest default exists for a test double; pass a \`${method}\` override.`));
21316
22753
  /**
21317
22754
  * Typed git introspection over core's `ChildProcessSpawner`: read a
21318
- * repository's state at any ref without checking it out, plus the mutating
21319
- * tier (`checkout`, `fetch`, `fetchAny`, `submoduleUpdate`, `submoduleAdd`,
21320
- * `sparseCheckoutSet`, `configSet`, `add`) that changes it.
22755
+ * repository's state at any ref without checking it out (including the
22756
+ * network read `lsRemote` and the index read `lsFiles`), plus the mutating
22757
+ * tier checkout/fetch, the working-tree restore trio and stash, branches
22758
+ * and tags, remotes, worktrees, commit/push/pull, submodules,
22759
+ * sparse-checkout, config writes and staging — that changes it. Every
22760
+ * mutating method's TSDoc opens with the literal word `Mutating:`.
21321
22761
  *
21322
22762
  * @remarks
21323
22763
  * Every method takes `cwd` explicitly and classifies git's stderr/exit-code
21324
22764
  * taxonomy exactly once, in this module's private `classify` step — a
21325
22765
  * spawn-level `PlatformError` and `Cause.TimeoutError` never escape a `Git`
21326
22766
  * method; every failure surfaces as {@link GitCommandError},
21327
- * {@link NotARepositoryError}, or {@link UnknownRefError}, or degrades to
21328
- * the documented non-error (`Option.none`, `false`).
22767
+ * {@link NotARepositoryError}, {@link UnknownRefError}, or one of the three
22768
+ * consumer-branchable classifications ({@link NonFastForwardError} from
22769
+ * `push`; {@link MergeConflictError} and {@link DirtyWorktreeError} from the
22770
+ * merge-shaped `pull` / `stashPop` / `stashApply`), or degrades to the
22771
+ * documented non-error (`Option.none`, `false`, the empty array).
21329
22772
  *
21330
22773
  * Every method whose TSDoc opens "Mutating:" changes the working tree,
21331
22774
  * `HEAD`, the index, the repository config, the object database and
@@ -21334,6 +22777,12 @@ const notStubbed = (method) => () => effect.Effect.die(/* @__PURE__ */ new Error
21334
22777
  * that — a caller running two mutating calls (or a mutating call alongside a
21335
22778
  * read) against one `cwd` at once owns the race.
21336
22779
  *
22780
+ * **Redaction policy (documented, not just convention).** Error values
22781
+ * persist only the constructor's REDACTED argv (see `GitCommandError.args`),
22782
+ * and span annotations carry stable identifiers only — `cwd`, refs, keys,
22783
+ * paths, remote names — never config values and never URLs, which can embed
22784
+ * userinfo. A new method must follow both halves before it ships.
22785
+ *
21337
22786
  * @public
21338
22787
  */
21339
22788
  var Git = class Git extends effect.Context.Service()("@effected/git/Git") {
@@ -21348,7 +22797,7 @@ var Git = class Git extends effect.Context.Service()("@effected/git/Git") {
21348
22797
  *
21349
22798
  * @remarks
21350
22799
  * Unlike `WorkspaceDiscovery.makeTest`, **no method here has an honest
21351
- * default** — the shape is twenty-six unrelated git operations, and a
22800
+ * default** — the shape is unrelated git operations, and a
21352
22801
  * fabricated answer for any of them (an empty tree, a made-up sha, a silent
21353
22802
  * no-op `checkout`) would leak into consumer logic as fact. So every
21354
22803
  * unstubbed method fails loudly as a defect
@@ -21387,8 +22836,23 @@ var Git = class Git extends effect.Context.Service()("@effected/git/Git") {
21387
22836
  checkout: notStubbed("checkout"),
21388
22837
  fetch: notStubbed("fetch"),
21389
22838
  fetchAny: notStubbed("fetchAny"),
22839
+ fetchUnshallow: notStubbed("fetchUnshallow"),
22840
+ isShallow: notStubbed("isShallow"),
22841
+ reset: notStubbed("reset"),
22842
+ clean: notStubbed("clean"),
22843
+ restore: notStubbed("restore"),
22844
+ branchCreate: notStubbed("branchCreate"),
22845
+ branchDelete: notStubbed("branchDelete"),
21390
22846
  submoduleUpdate: notStubbed("submoduleUpdate"),
21391
22847
  submoduleAdd: notStubbed("submoduleAdd"),
22848
+ submoduleStatus: notStubbed("submoduleStatus"),
22849
+ submoduleInit: notStubbed("submoduleInit"),
22850
+ submoduleDeinit: notStubbed("submoduleDeinit"),
22851
+ submoduleSync: notStubbed("submoduleSync"),
22852
+ submoduleSetUrl: notStubbed("submoduleSetUrl"),
22853
+ submoduleSetBranch: notStubbed("submoduleSetBranch"),
22854
+ submoduleAbsorbgitdirs: notStubbed("submoduleAbsorbgitdirs"),
22855
+ submoduleForeach: notStubbed("submoduleForeach"),
21392
22856
  sparseCheckoutSet: notStubbed("sparseCheckoutSet"),
21393
22857
  configSet: notStubbed("configSet"),
21394
22858
  add: notStubbed("add"),
@@ -21403,6 +22867,34 @@ var Git = class Git extends effect.Context.Service()("@effected/git/Git") {
21403
22867
  remoteUrl: notStubbed("remoteUrl"),
21404
22868
  commitInfo: notStubbed("commitInfo"),
21405
22869
  status: notStubbed("status"),
22870
+ lsRemote: notStubbed("lsRemote"),
22871
+ remoteAdd: notStubbed("remoteAdd"),
22872
+ remoteRemove: notStubbed("remoteRemove"),
22873
+ remoteSetUrl: notStubbed("remoteSetUrl"),
22874
+ stashPush: notStubbed("stashPush"),
22875
+ stashPop: notStubbed("stashPop"),
22876
+ stashApply: notStubbed("stashApply"),
22877
+ stashDrop: notStubbed("stashDrop"),
22878
+ stashList: notStubbed("stashList"),
22879
+ branchList: notStubbed("branchList"),
22880
+ tagCreate: notStubbed("tagCreate"),
22881
+ tagDelete: notStubbed("tagDelete"),
22882
+ tagList: notStubbed("tagList"),
22883
+ forEachRef: notStubbed("forEachRef"),
22884
+ revList: notStubbed("revList"),
22885
+ commit: notStubbed("commit"),
22886
+ push: notStubbed("push"),
22887
+ pull: notStubbed("pull"),
22888
+ configList: notStubbed("configList"),
22889
+ configGetAll: notStubbed("configGetAll"),
22890
+ configUnset: notStubbed("configUnset"),
22891
+ rm: notStubbed("rm"),
22892
+ mv: notStubbed("mv"),
22893
+ checkIgnore: notStubbed("checkIgnore"),
22894
+ worktreeAdd: notStubbed("worktreeAdd"),
22895
+ worktreeList: notStubbed("worktreeList"),
22896
+ worktreeRemove: notStubbed("worktreeRemove"),
22897
+ lsFiles: notStubbed("lsFiles"),
21406
22898
  ...overrides
21407
22899
  });
21408
22900
  /**
@@ -21431,7 +22923,7 @@ var Git = class Git extends effect.Context.Service()("@effected/git/Git") {
21431
22923
  static layerTest = (overrides = {}) => effect.Layer.succeed(Git, Git.makeTest(overrides));
21432
22924
  };
21433
22925
  //#endregion
21434
- //#region ../../node_modules/.pnpm/@effected+workspaces@0.10.0_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/ChangeDetector.js
22926
+ //#region ../../node_modules/.pnpm/@effected+workspaces@0.10.2_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__@effected+semv_feff9e309e6abeafa28f7ea259b8a9bf/node_modules/@effected/workspaces/ChangeDetector.js
21435
22927
  /**
21436
22928
  * Which git refs to compare, and whether to fold in the working tree.
21437
22929
  *
@@ -21687,7 +23179,7 @@ function resolveFromCatalog(catalogs, wantedDependency) {
21687
23179
  };
21688
23180
  }
21689
23181
  //#endregion
21690
- //#region ../../node_modules/.pnpm/@effected+workspaces@0.10.0_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/internal/catalogs.js
23182
+ //#region ../../node_modules/.pnpm/@effected+workspaces@0.10.2_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__@effected+semv_feff9e309e6abeafa28f7ea259b8a9bf/node_modules/@effected/workspaces/internal/catalogs.js
21691
23183
  /** Project a pnpm-workspace manifest's `catalog` / `catalogs` fields into a `Catalogs` map. */
21692
23184
  const inlineCatalogs = (manifest) => {
21693
23185
  if (manifest.catalog === void 0 && manifest.catalogs === void 0) return {};
@@ -21751,7 +23243,7 @@ const rangeOf = (catalogs, dependency, specifier) => {
21751
23243
  });
21752
23244
  };
21753
23245
  //#endregion
21754
- //#region ../../node_modules/.pnpm/@effected+workspaces@0.10.0_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/ConfigDependencyHooks.js
23246
+ //#region ../../node_modules/.pnpm/@effected+workspaces@0.10.2_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__@effected+semv_feff9e309e6abeafa28f7ea259b8a9bf/node_modules/@effected/workspaces/ConfigDependencyHooks.js
21755
23247
  /** Whether `value` is a non-null, non-array object. */
21756
23248
  const isObject$2 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
21757
23249
  /**
@@ -21953,8 +23445,12 @@ process.stdout.write("\\n" + JSON.stringify(payload) + "\\n", () => process.exit
21953
23445
  */
21954
23446
  const REPLAY_TIMEOUT = effect.Duration.seconds(30);
21955
23447
  /**
21956
- * The subprocess protocol payload — the child's final stdout line, framed and
21957
- * parsed by `Run.jsonLine`. The envelope is strict (a payload without a usable
23448
+ * The subprocess protocol payload — a single JSON line near the end of the
23449
+ * child's stdout, framed and parsed by `Run.jsonLine`, which scans lines from
23450
+ * the end for the first that decodes (so a hook logging after the payload —
23451
+ * e.g. from `process.on("exit", ...)` — cannot displace it). The `ok`
23452
+ * discriminant is what keeps an accidental log line from satisfying the
23453
+ * envelope. The envelope is strict (a payload without a usable
21958
23454
  * `ok` discriminant is a mechanism failure, typed); the `config` slice inside a
21959
23455
  * success stays `Unknown` because a hook's returned *data* is tolerantly
21960
23456
  * threaded (`configOf`), never fatal.
@@ -22158,7 +23654,7 @@ var ConfigDependencyHooks = class ConfigDependencyHooks extends effect.Context.S
22158
23654
  }));
22159
23655
  };
22160
23656
  //#endregion
22161
- //#region ../../node_modules/.pnpm/@effected+workspaces@0.10.0_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/PackageManagerName.js
23657
+ //#region ../../node_modules/.pnpm/@effected+workspaces@0.10.2_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__@effected+semv_feff9e309e6abeafa28f7ea259b8a9bf/node_modules/@effected/workspaces/PackageManagerName.js
22162
23658
  /**
22163
23659
  * The four package managers this package understands.
22164
23660
  *
@@ -22486,7 +23982,7 @@ var PackageManagerDetector = class PackageManagerDetector extends effect.Context
22486
23982
  static layerTest = (overrides = {}) => effect.Layer.succeed(PackageManagerDetector, PackageManagerDetector.makeTest(overrides));
22487
23983
  };
22488
23984
  //#endregion
22489
- //#region ../../node_modules/.pnpm/@effected+workspaces@0.10.0_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/LockfileReader.js
23985
+ //#region ../../node_modules/.pnpm/@effected+workspaces@0.10.2_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__@effected+semv_feff9e309e6abeafa28f7ea259b8a9bf/node_modules/@effected/workspaces/LockfileReader.js
22490
23986
  /**
22491
23987
  * Raised when the workspace's lockfile cannot be read off disk.
22492
23988
  *
@@ -22666,7 +24162,7 @@ var LockfileReader = class LockfileReader extends effect.Context.Service()("@eff
22666
24162
  static layerTest = (overrides = {}) => effect.Layer.succeed(LockfileReader, LockfileReader.makeTest(overrides));
22667
24163
  };
22668
24164
  //#endregion
22669
- //#region ../../node_modules/.pnpm/@effected+workspaces@0.10.0_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/Publishability.js
24165
+ //#region ../../node_modules/.pnpm/@effected+workspaces@0.10.2_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__@effected+semv_feff9e309e6abeafa28f7ea259b8a9bf/node_modules/@effected/workspaces/Publishability.js
22670
24166
  /** The public npm registry, used when `publishConfig.registry` says nothing. */
22671
24167
  const DEFAULT_REGISTRY = "https://registry.npmjs.org/";
22672
24168
  /**
@@ -22825,7 +24321,7 @@ var PublishabilityDetector = class extends effect.Context.Service()("@effected/w
22825
24321
  static layerNone = effect.Layer.succeed(this, this.none);
22826
24322
  };
22827
24323
  //#endregion
22828
- //#region ../../node_modules/.pnpm/@effected+workspaces@0.10.0_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/internal/importerVersions.js
24324
+ //#region ../../node_modules/.pnpm/@effected+workspaces@0.10.2_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__@effected+semv_feff9e309e6abeafa28f7ea259b8a9bf/node_modules/@effected/workspaces/internal/importerVersions.js
22829
24325
  /**
22830
24326
  * Strip pnpm's peer-disambiguation suffix from a recorded importer version.
22831
24327
  *
@@ -22911,7 +24407,7 @@ const unanimousVersionOf = (index, dependency) => {
22911
24407
  return agreed;
22912
24408
  };
22913
24409
  //#endregion
22914
- //#region ../../node_modules/.pnpm/@effected+workspaces@0.10.0_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/WorkspaceCatalogs.js
24410
+ //#region ../../node_modules/.pnpm/@effected+workspaces@0.10.2_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__@effected+semv_feff9e309e6abeafa28f7ea259b8a9bf/node_modules/@effected/workspaces/WorkspaceCatalogs.js
22915
24411
  /**
22916
24412
  * An immutable, fully-normalized catalog collection — the one catalog
22917
24413
  * resolution semantic in the package.
@@ -23426,9 +24922,9 @@ var WorkspaceCatalogs = class WorkspaceCatalogs extends effect.Context.Service()
23426
24922
  * consumers to `_tag`-sniff `unknown`); only the remaining mechanism failure,
23427
24923
  * an unfindable workspace root, is wrapped as `DependencyResolutionError`.
23428
24924
  */
23429
- static catalogResolver = effect.Layer.effect(CatalogResolver$1, effect.Effect.gen(function* () {
24925
+ static catalogResolver = effect.Layer.effect(CatalogResolver, effect.Effect.gen(function* () {
23430
24926
  const catalogs = yield* WorkspaceCatalogs;
23431
- return { rangeOf: (packageName, catalog) => catalogs.set().pipe(effect.Effect.map((set) => set.rangeOf(packageName, catalog)), effect.Effect.catchTag("WorkspaceRootNotFoundError", (cause) => effect.Effect.fail(new DependencyResolutionError$1({
24927
+ return { rangeOf: (packageName, catalog) => catalogs.set().pipe(effect.Effect.map((set) => set.rangeOf(packageName, catalog)), effect.Effect.catchTag("WorkspaceRootNotFoundError", (cause) => effect.Effect.fail(new DependencyResolutionError({
23432
24928
  specifier: effect.Option.match(catalog, {
23433
24929
  onNone: () => "catalog:",
23434
24930
  onSome: (name) => `catalog:${name}`
@@ -23438,7 +24934,7 @@ var WorkspaceCatalogs = class WorkspaceCatalogs extends effect.Context.Service()
23438
24934
  }));
23439
24935
  };
23440
24936
  //#endregion
23441
- //#region ../../node_modules/.pnpm/@effected+workspaces@0.10.0_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/WorkspaceStateSnapshot.js
24937
+ //#region ../../node_modules/.pnpm/@effected+workspaces@0.10.2_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__@effected+semv_feff9e309e6abeafa28f7ea259b8a9bf/node_modules/@effected/workspaces/WorkspaceStateSnapshot.js
23442
24938
  const EMPTY = Object.freeze(Object.create(null));
23443
24939
  const DependencyMap = effect.Schema.Record(effect.Schema.String, effect.Schema.String).pipe(effect.Schema.withDecodingDefaultKey(effect.Effect.succeed(EMPTY)), effect.Schema.withConstructorDefault(effect.Effect.succeed(EMPTY)));
23444
24940
  /**
@@ -23617,7 +25113,7 @@ var WorkspaceStateSnapshot = class extends effect.Schema.Class("WorkspaceStateSn
23617
25113
  * resolving to `Option.none()` so the caller falls back to the raw string.
23618
25114
  */
23619
25115
  #resolveWith(dependency, specifier, onUnresolvedCatalog) {
23620
- const exit = effect.Schema.decodeUnknownExit(DependencySpecifier$1.FromString)(specifier);
25116
+ const exit = effect.Schema.decodeUnknownExit(DependencySpecifier.FromString)(specifier);
23621
25117
  if (!effect.Exit.isSuccess(exit)) return effect.Option.none();
23622
25118
  const classified = exit.value;
23623
25119
  switch (classified._tag) {
@@ -23642,7 +25138,7 @@ var WorkspaceStateSnapshot = class extends effect.Schema.Class("WorkspaceStateSn
23642
25138
  * `rangeOf` never fails.
23643
25139
  */
23644
25140
  get catalogResolver() {
23645
- if (this.#catalogResolver === void 0) this.#catalogResolver = effect.Layer.succeed(CatalogResolver$1, { rangeOf: (packageName, catalog) => effect.Effect.succeed(this.catalogs.rangeOf(packageName, catalog)) });
25141
+ if (this.#catalogResolver === void 0) this.#catalogResolver = effect.Layer.succeed(CatalogResolver, { rangeOf: (packageName, catalog) => effect.Effect.succeed(this.catalogs.rangeOf(packageName, catalog)) });
23646
25142
  return this.#catalogResolver;
23647
25143
  }
23648
25144
  /**
@@ -23651,7 +25147,7 @@ var WorkspaceStateSnapshot = class extends effect.Schema.Class("WorkspaceStateSn
23651
25147
  * `workspace:` specifiers as of this ref. Built once per instance and cached.
23652
25148
  */
23653
25149
  get workspaceResolver() {
23654
- if (this.#workspaceResolver === void 0) this.#workspaceResolver = effect.Layer.succeed(WorkspaceResolver$1, { versionOf: (packageName) => effect.Effect.succeed(effect.Option.fromUndefinedOr(this.#versions().get(packageName))) });
25150
+ if (this.#workspaceResolver === void 0) this.#workspaceResolver = effect.Layer.succeed(WorkspaceResolver, { versionOf: (packageName) => effect.Effect.succeed(effect.Option.fromUndefinedOr(this.#versions().get(packageName))) });
23655
25151
  return this.#workspaceResolver;
23656
25152
  }
23657
25153
  /** Both snapshot-scoped resolver layers merged. Built once per instance and cached. */
@@ -23661,7 +25157,7 @@ var WorkspaceStateSnapshot = class extends effect.Schema.Class("WorkspaceStateSn
23661
25157
  }
23662
25158
  };
23663
25159
  //#endregion
23664
- //#region ../../node_modules/.pnpm/@effected+workspaces@0.10.0_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/WorkspaceSnapshots.js
25160
+ //#region ../../node_modules/.pnpm/@effected+workspaces@0.10.2_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__@effected+semv_feff9e309e6abeafa28f7ea259b8a9bf/node_modules/@effected/workspaces/WorkspaceSnapshots.js
23665
25161
  /** Whether `value` is a non-null, non-array object. */
23666
25162
  const isObject = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
23667
25163
  /** Whether every value in a record is a string — a usable dependency map. */
@@ -23938,7 +25434,7 @@ var WorkspaceSnapshots = class WorkspaceSnapshots extends effect.Context.Service
23938
25434
  static layerTest = (overrides = {}) => effect.Layer.succeed(WorkspaceSnapshots, WorkspaceSnapshots.makeTest(overrides));
23939
25435
  };
23940
25436
  //#endregion
23941
- //#region ../../node_modules/.pnpm/@effected+workspaces@0.10.0_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/Workspaces.js
25437
+ //#region ../../node_modules/.pnpm/@effected+workspaces@0.10.2_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__@effected+semv_feff9e309e6abeafa28f7ea259b8a9bf/node_modules/@effected/workspaces/Workspaces.js
23942
25438
  const compose = (options, catalogsFactory) => {
23943
25439
  const roots = WorkspaceRoot.layer;
23944
25440
  const detector = PackageManagerDetector.layer;
@@ -24072,7 +25568,8 @@ var Workspaces = class {
24072
25568
  * never detects changes or reads at a ref should not have to be able to
24073
25569
  * spawn a subprocess. The consumer provides `ChildProcessSpawner` once at
24074
25570
  * the edge (`@effect/platform-node`'s `NodeServices.layer`); a test
24075
- * provides `Layer.succeed(Git, …)` and needs no repository on disk.
25571
+ * provides `Git.layerTest({ })` git's own shipped double, whose
25572
+ * unstubbed members die named — and needs no repository on disk.
24076
25573
  */
24077
25574
  static layerWithGit = layerWithGit;
24078
25575
  /**
@@ -24121,9 +25618,14 @@ var Workspaces = class {
24121
25618
  * import { Workspaces } from "@effected/workspaces";
24122
25619
  * import { Layer } from "effect";
24123
25620
  *
25621
+ * // Bound to consts per the warning above: each factory call mints a
25622
+ * // fresh layer reference, and layers memoize by reference.
25623
+ * const LocalExecLayer = Workspaces.localExecLayer();
25624
+ * const WorkspacesLayer = Workspaces.layer();
25625
+ *
24124
25626
  * const AppLayer = ToolDiscovery.layer.pipe(
24125
- * Layer.provide(Workspaces.localExecLayer()),
24126
- * Layer.provide(Workspaces.layer()),
25627
+ * Layer.provide(LocalExecLayer),
25628
+ * Layer.provide(WorkspacesLayer),
24127
25629
  * Layer.provide(NodeServices.layer),
24128
25630
  * );
24129
25631
  * ```