@savvy-web/silk 3.4.1 → 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.
@@ -2338,7 +2338,7 @@ var GlobSet = class GlobSet extends effect.Schema.Class("GlobSet")(effect.Schema
2338
2338
  }
2339
2339
  };
2340
2340
  //#endregion
2341
- //#region ../../node_modules/.pnpm/@effected+lockfiles@0.3.2_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__@effected+npm@0._ff048038a9678f5144f817ad24d8f96e/node_modules/@effected/lockfiles/BunExtension.js
2341
+ //#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/BunExtension.js
2342
2342
  /**
2343
2343
  * Extension data specific to bun lockfiles, attached to `Lockfile.extension`
2344
2344
  * when the format is `"bun"`.
@@ -2359,7 +2359,7 @@ var BunExtension = class extends effect.Schema.Class("BunExtension")({
2359
2359
  trustedDependencies: effect.Schema.optionalKey(effect.Schema.Array(effect.Schema.String))
2360
2360
  }) {};
2361
2361
  //#endregion
2362
- //#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
2362
+ //#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/CatalogResolver.js
2363
2363
  /**
2364
2364
  * Contract for resolving pnpm `catalog:` dependency specifiers to concrete
2365
2365
  * version ranges.
@@ -2405,7 +2405,7 @@ var CatalogResolver = class CatalogResolver extends effect.Context.Service()("@e
2405
2405
  static noop = effect.Layer.succeed(CatalogResolver, { rangeOf: () => effect.Effect.succeed(effect.Option.none()) });
2406
2406
  };
2407
2407
  //#endregion
2408
- //#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/WorkspaceResolver.js
2408
+ //#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/WorkspaceResolver.js
2409
2409
  /**
2410
2410
  * Raised when a `catalog:` or `workspace:` specifier cannot be resolved
2411
2411
  * because the resolution mechanism itself failed — not for an ordinary
@@ -2466,7 +2466,7 @@ var WorkspaceResolver = class WorkspaceResolver extends effect.Context.Service()
2466
2466
  static noop = effect.Layer.succeed(WorkspaceResolver, { versionOf: () => effect.Effect.succeed(effect.Option.none()) });
2467
2467
  };
2468
2468
  //#endregion
2469
- //#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/CatalogAssemblyError.js
2469
+ //#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/CatalogAssemblyError.js
2470
2470
  /**
2471
2471
  * Raised when a workspace's catalogs cannot be assembled — a `pnpm-workspace.yaml`
2472
2472
  * that is unreadable or not valid YAML, a root `package.json` `workspaces` field
@@ -2510,7 +2510,7 @@ var CatalogAssemblyError = class extends effect.Schema.TaggedErrorClass()("Catal
2510
2510
  }
2511
2511
  };
2512
2512
  //#endregion
2513
- //#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
2513
+ //#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
2514
2514
  /**
2515
2515
  * The short dependency kind: which dependency map an entry came from, named the
2516
2516
  * way consumers branch on it.
@@ -4125,7 +4125,7 @@ const isComparatorSetSubset = (sub, sup) => {
4125
4125
  return true;
4126
4126
  };
4127
4127
  //#endregion
4128
- //#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
4128
+ //#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/DependencySpecifier.js
4129
4129
  /**
4130
4130
  * Indicates that a string could not be parsed as a valid dependency specifier.
4131
4131
  *
@@ -4332,7 +4332,7 @@ const DependencySpecifier = Object.assign(brandedSpecifier, {
4332
4332
  FromString: fromString
4333
4333
  });
4334
4334
  //#endregion
4335
- //#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
4335
+ //#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
4336
4336
  const SRI_RE = /^(sha1|sha256|sha384|sha512)-[A-Za-z0-9+/]+={0,2}$/;
4337
4337
  const COREPACK_RE = /^(sha1|sha224|sha256|sha384|sha512)\.[0-9a-f]+$/;
4338
4338
  const YARN_RE = /^[0-9]+(c[0-9]+)?\/[0-9a-f]+$/;
@@ -4631,7 +4631,678 @@ var LocalExec = class LocalExec extends effect.Context.Service()("@effected/comm
4631
4631
  static layerTest = (overrides = {}) => effect.Layer.succeed(LocalExec, LocalExec.makeTest(overrides));
4632
4632
  };
4633
4633
  //#endregion
4634
- //#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/ReleaseAgeGate.js
4634
+ //#region ../../node_modules/.pnpm/@effected+commands@0.3.1_effect@4.0.0-beta.101/node_modules/@effected/commands/Redaction.js
4635
+ /**
4636
+ * Argument tokens whose *following* positional (or `=`-joined value) is a
4637
+ * secret. Lowercase; matching is case-insensitive.
4638
+ *
4639
+ * @remarks
4640
+ * This is the heuristic backstop, not the primary mechanism — it can only know
4641
+ * about flags someone thought to list. The primary mechanism is
4642
+ * {@link Redaction.applyArgs}, which redacts by **value**: the caller says what
4643
+ * its secrets are and every occurrence goes, whatever flag carried it.
4644
+ *
4645
+ * @public
4646
+ */
4647
+ const SECRET_FLAGS = /* @__PURE__ */ new Set([
4648
+ "--access-token",
4649
+ "--api-key",
4650
+ "--auth",
4651
+ "--auth-token",
4652
+ "--otp",
4653
+ "--password",
4654
+ "--registry-token",
4655
+ "--token"
4656
+ ]);
4657
+ /**
4658
+ * npm config keys whose value is a credential (`//registry/:_authToken`,
4659
+ * `//registry/:_password`).
4660
+ */
4661
+ const AUTH_KEY = /:(?:_authtoken|_password)$/i;
4662
+ /**
4663
+ * The distinct, non-empty secret values, longest first.
4664
+ *
4665
+ * @remarks
4666
+ * Longest-first is load-bearing: redacting `"ab"` before `"abcd"` rewrites
4667
+ * `"abcd"` to `"***cd"`, leaking `"cd"` — a fragment of the longer secret.
4668
+ * Empty values are dropped because `"abc".split("").join("***")` would insert
4669
+ * the placeholder between every character.
4670
+ */
4671
+ const prepare = (secrets) => [...new Set(secrets.map(effect.Redacted.value))].filter((value) => value.length > 0).sort((a, b) => b.length - a.length);
4672
+ /** Replaces each prepared value with {@link REDACTED}, literally (never as a pattern). */
4673
+ const replaceAll = (text, values) => {
4674
+ let out = text;
4675
+ for (const value of values) out = out.split(value).join("***");
4676
+ return out;
4677
+ };
4678
+ const apply = (text, secrets) => secrets.length === 0 ? text : replaceAll(text, prepare(secrets));
4679
+ const applyArgs = (args, secrets) => {
4680
+ if (secrets.length === 0) return args;
4681
+ const values = prepare(secrets);
4682
+ return args.map((arg) => replaceAll(arg, values));
4683
+ };
4684
+ /** Whether `name` introduces a credential value. */
4685
+ const isSecretName = (name, extra) => {
4686
+ const lower = name.toLowerCase();
4687
+ return SECRET_FLAGS.has(lower) || extra.has(lower) || AUTH_KEY.test(name);
4688
+ };
4689
+ const scrubArgs = (args, options) => {
4690
+ const extra = new Set((options?.flags ?? []).map((flag) => flag.toLowerCase()));
4691
+ const out = [];
4692
+ for (let index = 0; index < args.length; index++) {
4693
+ const arg = args[index] ?? "";
4694
+ const equals = arg.indexOf("=");
4695
+ if (equals > 0 && isSecretName(arg.slice(0, equals), extra)) {
4696
+ out.push(`${arg.slice(0, equals)}=***`);
4697
+ continue;
4698
+ }
4699
+ out.push(arg);
4700
+ if (isSecretName(arg, extra) && index + 1 < args.length) {
4701
+ out.push("***");
4702
+ index++;
4703
+ }
4704
+ }
4705
+ return out;
4706
+ };
4707
+ /**
4708
+ * Secret scrubbing for command arguments and captured output.
4709
+ *
4710
+ * @remarks
4711
+ * Two mechanisms, deliberately layered. {@link Redaction.apply} and
4712
+ * {@link Redaction.applyArgs} redact **by value** — the caller declares its
4713
+ * secrets as `Redacted` and every occurrence is removed wherever it appears.
4714
+ * {@link Redaction.scrubArgs} is a **flag heuristic** that runs in addition, for
4715
+ * the secrets a caller forgot to declare.
4716
+ *
4717
+ * @public
4718
+ */
4719
+ var Redaction = class {
4720
+ constructor() {}
4721
+ /**
4722
+ * Replaces every occurrence of every secret's value in `text` with
4723
+ * {@link REDACTED}.
4724
+ *
4725
+ * @remarks
4726
+ * Exact, literal matching — no pattern compilation, no encoding-aware search. A
4727
+ * secret that reaches the text base64-encoded, URL-encoded, or split across a
4728
+ * line break is **not** found; declare the encoded form as a secret too if that
4729
+ * is a real risk.
4730
+ *
4731
+ * A secret composed only of the placeholder's own characters (`*`, `**`, `***`)
4732
+ * cannot be fully removed, because the replacement reintroduces it. That is a
4733
+ * documented limitation, not a defect.
4734
+ */
4735
+ static apply = apply;
4736
+ /**
4737
+ * {@link Redaction.apply} over each entry of an argv array. An entry is
4738
+ * redacted whether it *is* a secret or merely *contains* one
4739
+ * (`--url=https://u:s3cr3t@host`).
4740
+ */
4741
+ static applyArgs = applyArgs;
4742
+ /**
4743
+ * Heuristic backstop: redact any argv value that is introduced by a known
4744
+ * secret-bearing flag or npm auth key, in either the separated
4745
+ * (`--token abc`) or inline (`--token=abc`) form.
4746
+ *
4747
+ * @remarks
4748
+ * This catches secrets the caller forgot to declare; it cannot catch a flag
4749
+ * nobody listed. Prefer {@link Redaction.applyArgs} with the actual
4750
+ * `Redacted` values — this runs *in addition*, never instead.
4751
+ */
4752
+ static scrubArgs = scrubArgs;
4753
+ /** Flags treated as secret-bearing by {@link Redaction.scrubArgs}. See {@link SECRET_FLAGS}. */
4754
+ static SECRET_FLAGS = SECRET_FLAGS;
4755
+ };
4756
+ //#endregion
4757
+ //#region ../../node_modules/.pnpm/@effected+commands@0.3.1_effect@4.0.0-beta.101/node_modules/@effected/commands/internal/capture.js
4758
+ /**
4759
+ * Raised when a captured stream exceeds its byte budget.
4760
+ *
4761
+ * @remarks
4762
+ * Internal and never exported from the package: `Run` maps it to the public
4763
+ * `CommandOutputError`. `Data.TaggedError` is appropriate precisely because it
4764
+ * never escapes — it is an in-process signal, not a contract.
4765
+ */
4766
+ var OutputTooLarge = class extends effect.Data.TaggedError("OutputTooLarge") {};
4767
+ /**
4768
+ * Collects a byte stream into a string, failing once more than `limit` bytes
4769
+ * have arrived.
4770
+ *
4771
+ * @remarks
4772
+ * The budget is enforced **during** accumulation, not after: checking the
4773
+ * length of an already-collected string would mean the memory was already
4774
+ * spent, which is the exact failure the budget exists to prevent. Counting is
4775
+ * on raw bytes, before decoding, because bytes are what the process actually
4776
+ * produced.
4777
+ */
4778
+ const collectBounded = (stream, limit) => effect.Effect.gen(function* () {
4779
+ const seen = yield* effect.Ref.make(0);
4780
+ const bounded = effect.Stream.mapEffect(stream, (chunk) => effect.Effect.flatMap(effect.Ref.updateAndGet(seen, (total) => total + chunk.length), (total) => total > limit ? effect.Effect.fail(new OutputTooLarge({ limit })) : effect.Effect.succeed(chunk)));
4781
+ return yield* effect.Stream.mkString(effect.Stream.decodeText(bounded));
4782
+ });
4783
+ //#endregion
4784
+ //#region ../../node_modules/.pnpm/@effected+commands@0.3.1_effect@4.0.0-beta.101/node_modules/@effected/commands/Run.js
4785
+ /**
4786
+ * Default ceiling on captured bytes per stream (16 MiB).
4787
+ *
4788
+ * @remarks
4789
+ * Collecting a child's output without a bound is a memory-exhaustion vector.
4790
+ * Output genuinely larger than this belongs on {@link Run.stream}, which never
4791
+ * accumulates.
4792
+ *
4793
+ * @public
4794
+ */
4795
+ const DEFAULT_MAX_OUTPUT_BYTES = 16777216;
4796
+ /** Characters shown from the tail of captured output in an error message. */
4797
+ const MAX_MESSAGE_CHARS = 2e3;
4798
+ /**
4799
+ * What one completed run produced.
4800
+ *
4801
+ * @public
4802
+ */
4803
+ var CommandOutput = class extends effect.Schema.Class("CommandOutput")({
4804
+ /** Captured standard output, redacted. */
4805
+ stdout: effect.Schema.String,
4806
+ /** Captured standard error, redacted. */
4807
+ stderr: effect.Schema.String,
4808
+ /** The process exit code. A non-zero value is NOT an error at this level. */
4809
+ exitCode: effect.Schema.Number
4810
+ }) {
4811
+ /** Whether the process exited zero. */
4812
+ get succeeded() {
4813
+ return this.exitCode === 0;
4814
+ }
4815
+ };
4816
+ /** The executable and argv an error should report for `command`. */
4817
+ const describeCommand = (command) => {
4818
+ if (effect_unstable_process.ChildProcess.isStandardCommand(command)) return {
4819
+ command: command.command,
4820
+ args: command.args
4821
+ };
4822
+ const left = describeCommand(command.left);
4823
+ const right = describeCommand(command.right);
4824
+ return {
4825
+ command: `${left.command} | ${right.command}`,
4826
+ args: []
4827
+ };
4828
+ };
4829
+ /** argv as an error should store it: declared secrets removed, then the flag heuristic. */
4830
+ const safeArgs = (args, secrets) => Redaction.scrubArgs(Redaction.applyArgs(args, secrets ?? []));
4831
+ /** Captured text as an error should store it. */
4832
+ const safeText = (text, secrets) => Redaction.apply(text, secrets ?? []);
4833
+ /** Tail-bounded rendering: tools write warnings first and the real error last. */
4834
+ const tail = (text) => {
4835
+ const trimmed = text.trim();
4836
+ if (trimmed.length <= MAX_MESSAGE_CHARS) return trimmed;
4837
+ return `...[${trimmed.length - MAX_MESSAGE_CHARS} chars truncated from head]...\n${trimmed.slice(-2e3)}`;
4838
+ };
4839
+ /**
4840
+ * A command that could not be run, or that ran and failed.
4841
+ *
4842
+ * @remarks
4843
+ * `kind` is the routing surface, never the message: `"nonZero"` (the process
4844
+ * ran and exited non-zero), `"spawn"` (it never started — the executable is
4845
+ * missing, or the platform refused), `"timeout"` (a caller-supplied ceiling
4846
+ * elapsed). Composed retry and fallback logic branches on `kind`; nothing in
4847
+ * this package asks a caller to match on prose.
4848
+ *
4849
+ * `args` is **always** stored redacted.
4850
+ *
4851
+ * @public
4852
+ */
4853
+ var CommandFailedError = class CommandFailedError extends effect.Schema.TaggedErrorClass()("CommandFailedError", {
4854
+ /** Why it failed. */
4855
+ kind: effect.Schema.Literals([
4856
+ "nonZero",
4857
+ "spawn",
4858
+ "timeout"
4859
+ ]),
4860
+ /** The executable (or `"a | b"` for a pipeline). */
4861
+ command: effect.Schema.String,
4862
+ /** argv, redacted. */
4863
+ args: effect.Schema.Array(effect.Schema.String),
4864
+ /** The exit code, when the process ran. */
4865
+ exitCode: effect.Schema.optionalKey(effect.Schema.Number),
4866
+ /** Captured standard error, redacted, when the process ran. */
4867
+ stderr: effect.Schema.optionalKey(effect.Schema.String),
4868
+ /** Captured standard output, redacted, when the process ran. */
4869
+ stdout: effect.Schema.optionalKey(effect.Schema.String),
4870
+ /** The absorbed platform failure, for `"spawn"`. */
4871
+ cause: effect.Schema.optionalKey(effect.Schema.Defect())
4872
+ }) {
4873
+ /** The process ran and exited non-zero. */
4874
+ static nonZero = (command, output, secrets) => {
4875
+ const described = describeCommand(command);
4876
+ return new CommandFailedError({
4877
+ kind: "nonZero",
4878
+ command: described.command,
4879
+ args: safeArgs(described.args, secrets),
4880
+ exitCode: output.exitCode,
4881
+ stderr: output.stderr,
4882
+ stdout: output.stdout
4883
+ });
4884
+ };
4885
+ /** The process never started. */
4886
+ static spawn = (command, cause, secrets) => {
4887
+ const described = describeCommand(command);
4888
+ return new CommandFailedError({
4889
+ kind: "spawn",
4890
+ command: described.command,
4891
+ args: safeArgs(described.args, secrets),
4892
+ cause
4893
+ });
4894
+ };
4895
+ /** A caller-supplied ceiling elapsed; the child was killed with its scope. */
4896
+ static timedOut = (command, secrets) => {
4897
+ const described = describeCommand(command);
4898
+ return new CommandFailedError({
4899
+ kind: "timeout",
4900
+ command: described.command,
4901
+ args: safeArgs(described.args, secrets)
4902
+ });
4903
+ };
4904
+ /**
4905
+ * Whether this is a spawn failure caused by the executable not existing —
4906
+ * the structural "tool is not installed" signal.
4907
+ */
4908
+ get notFound() {
4909
+ return this.kind === "spawn" && this.cause instanceof effect.PlatformError.PlatformError && this.cause.reason._tag === "NotFound";
4910
+ }
4911
+ /** Names the command and surfaces the tail of whichever stream carries the cause. */
4912
+ get message() {
4913
+ const parts = [`Command "${this.args.length > 0 ? `${this.command} ${this.args.join(" ")}` : this.command}" failed`];
4914
+ if (this.kind === "timeout") parts.push("(timed out)");
4915
+ if (this.exitCode !== void 0) parts.push(`(exit ${this.exitCode})`);
4916
+ const stream = this.stderr?.trim() ? this.stderr : this.stdout?.trim() ? this.stdout : void 0;
4917
+ if (stream !== void 0) parts.push(`:\n${tail(stream)}`);
4918
+ return parts.join(" ");
4919
+ }
4920
+ };
4921
+ /**
4922
+ * A command ran, but its output could not be used.
4923
+ *
4924
+ * @remarks
4925
+ * Separate from {@link CommandFailedError} because the process itself
4926
+ * succeeded: `"notJson"` (stdout is not JSON), `"schema"` (it is JSON but does
4927
+ * not decode), `"tooLarge"` (capture exceeded its byte budget). Keeping the two
4928
+ * distinguishable is the point — a schema drift and a crashed tool call for
4929
+ * different responses.
4930
+ *
4931
+ * The context fields (`exitCode`, `stderr`, `stdout`) are populated by
4932
+ * {@link Run.jsonLine}, whose payload framing parses regardless of exit code —
4933
+ * when no payload arrives, the exit code and captured streams are the only
4934
+ * evidence of what actually went wrong. Both streams are **always** stored
4935
+ * redacted.
4936
+ *
4937
+ * @public
4938
+ */
4939
+ var CommandOutputError = class extends effect.Schema.TaggedErrorClass()("CommandOutputError", {
4940
+ /** Which way the output was unusable. */
4941
+ kind: effect.Schema.Literals([
4942
+ "notJson",
4943
+ "schema",
4944
+ "tooLarge"
4945
+ ]),
4946
+ /** The executable that produced it. */
4947
+ command: effect.Schema.String,
4948
+ /** The underlying parse or decode failure. */
4949
+ cause: effect.Schema.optionalKey(effect.Schema.Defect()),
4950
+ /** The exit code, when the combinator parses independently of it. */
4951
+ exitCode: effect.Schema.optionalKey(effect.Schema.Number),
4952
+ /** Captured standard error, redacted, when the process ran. */
4953
+ stderr: effect.Schema.optionalKey(effect.Schema.String),
4954
+ /** Captured standard output, redacted, when the process ran. */
4955
+ stdout: effect.Schema.optionalKey(effect.Schema.String)
4956
+ }) {
4957
+ get message() {
4958
+ const parts = [];
4959
+ if (this.kind === "notJson") parts.push(`Command "${this.command}" did not produce JSON`);
4960
+ else if (this.kind === "schema") parts.push(`Command "${this.command}" produced JSON that did not match the expected schema`);
4961
+ else parts.push(`Command "${this.command}" produced more output than the configured limit`);
4962
+ if (this.exitCode !== void 0) parts.push(`(exit ${this.exitCode})`);
4963
+ if (this.stderr !== void 0 && this.stderr.trim().length > 0) parts.push(`:\n${tail(this.stderr)}`);
4964
+ return parts.join(" ");
4965
+ }
4966
+ };
4967
+ /** Spawns, collects both streams concurrently, and awaits exit. */
4968
+ const collectRaw = (command, options, tee) => effect.Effect.scoped(effect.Effect.gen(function* () {
4969
+ const handle = yield* (yield* effect_unstable_process.ChildProcessSpawner.ChildProcessSpawner).spawn(command);
4970
+ const limit = options?.maxOutputBytes ?? 16777216;
4971
+ const out = tee === void 0 ? handle.stdout : effect.Stream.tapSink(handle.stdout, tee.stdout());
4972
+ const err = tee === void 0 ? handle.stderr : effect.Stream.tapSink(handle.stderr, tee.stderr());
4973
+ const [stdout, stderr, exitCode] = yield* effect.Effect.all([
4974
+ collectBounded(out, limit),
4975
+ collectBounded(err, limit),
4976
+ handle.exitCode
4977
+ ], { concurrency: "unbounded" });
4978
+ const secrets = options?.redact;
4979
+ return CommandOutput.make({
4980
+ stdout: safeText(stdout, secrets),
4981
+ stderr: safeText(stderr, secrets),
4982
+ exitCode: Number(exitCode)
4983
+ });
4984
+ }));
4985
+ /** Maps the raw failure modes onto this package's taxonomy, and applies any ceiling. */
4986
+ const collectClassified = (command, options, tee) => {
4987
+ const described = describeCommand(command);
4988
+ const classified = collectRaw(command, options, tee).pipe(effect.Effect.catch((error) => effect.Effect.fail(error instanceof OutputTooLarge ? new CommandOutputError({
4989
+ kind: "tooLarge",
4990
+ command: described.command,
4991
+ cause: error
4992
+ }) : CommandFailedError.spawn(command, error, options?.redact))));
4993
+ return options?.timeout === void 0 ? classified : effect.Effect.timeoutOrElse(classified, {
4994
+ duration: options.timeout,
4995
+ orElse: () => effect.Effect.fail(CommandFailedError.timedOut(command, options.redact))
4996
+ });
4997
+ };
4998
+ /** Fails a run whose process exited non-zero. */
4999
+ const requireZero = (command, output, options) => output.succeeded ? effect.Effect.succeed(output) : effect.Effect.fail(CommandFailedError.nonZero(command, output, options?.redact));
5000
+ /** Span attributes: what ran and how many arguments — never the arguments. */
5001
+ const annotate = (command) => {
5002
+ const described = describeCommand(command);
5003
+ return effect.Effect.annotateCurrentSpan({
5004
+ command: described.command,
5005
+ argc: described.args.length
5006
+ });
5007
+ };
5008
+ const collect = effect.Effect.fn("Run.collect")(function* (command, options) {
5009
+ yield* annotate(command);
5010
+ return yield* collectClassified(command, options, void 0);
5011
+ });
5012
+ const collectTee = effect.Effect.fn("Run.collectTee")(function* (command, options) {
5013
+ yield* annotate(command);
5014
+ const stdio = yield* effect.Stdio.Stdio;
5015
+ return yield* collectClassified(command, options, stdio);
5016
+ });
5017
+ const text$4 = effect.Effect.fn("Run.text")(function* (command, options) {
5018
+ yield* annotate(command);
5019
+ const output = yield* collectClassified(command, options, void 0);
5020
+ return (yield* requireZero(command, output, options)).stdout.trim();
5021
+ });
5022
+ const lines = effect.Effect.fn("Run.lines")(function* (command, options) {
5023
+ yield* annotate(command);
5024
+ const output = yield* collectClassified(command, options, void 0);
5025
+ return (yield* requireZero(command, output, options)).stdout.split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0);
5026
+ });
5027
+ const json = effect.Effect.fn("Run.json")(function* (command, schema, options) {
5028
+ yield* annotate(command);
5029
+ const described = describeCommand(command);
5030
+ const output = yield* collectClassified(command, options, void 0);
5031
+ const checked = yield* requireZero(command, output, options);
5032
+ const parsed = yield* effect.Effect.try({
5033
+ try: () => JSON.parse(checked.stdout),
5034
+ catch: (cause) => new CommandOutputError({
5035
+ kind: "notJson",
5036
+ command: described.command,
5037
+ cause
5038
+ })
5039
+ });
5040
+ return yield* effect.Schema.decodeUnknownEffect(schema)(parsed).pipe(effect.Effect.catch((cause) => effect.Effect.fail(new CommandOutputError({
5041
+ kind: "schema",
5042
+ command: described.command,
5043
+ cause
5044
+ }))));
5045
+ });
5046
+ const jsonLine = effect.Effect.fn("Run.jsonLine")(function* (command, schema, options) {
5047
+ yield* annotate(command);
5048
+ const described = describeCommand(command);
5049
+ const output = yield* collectClassified(command, options, void 0);
5050
+ const context = {
5051
+ exitCode: output.exitCode,
5052
+ stderr: output.stderr,
5053
+ stdout: output.stdout
5054
+ };
5055
+ const candidates = output.stdout.split(/\r?\n/).filter((candidate) => candidate.trim().length > 0);
5056
+ if (candidates.length === 0) return yield* effect.Effect.fail(new CommandOutputError({
5057
+ kind: "notJson",
5058
+ command: described.command,
5059
+ cause: /* @__PURE__ */ new Error("stdout carried no non-empty line"),
5060
+ ...context
5061
+ }));
5062
+ let notJsonCause;
5063
+ let schemaCause;
5064
+ for (let index = candidates.length - 1; index >= 0; index--) {
5065
+ const candidate = candidates[index];
5066
+ if (candidate === void 0) continue;
5067
+ let parsed;
5068
+ try {
5069
+ parsed = JSON.parse(candidate);
5070
+ } catch (cause) {
5071
+ notJsonCause ??= cause;
5072
+ continue;
5073
+ }
5074
+ const decoded = yield* effect.Effect.result(effect.Schema.decodeUnknownEffect(schema)(parsed));
5075
+ if (effect.Result.isSuccess(decoded)) return decoded.success;
5076
+ schemaCause ??= decoded.failure;
5077
+ }
5078
+ return yield* effect.Effect.fail(schemaCause !== void 0 ? new CommandOutputError({
5079
+ kind: "schema",
5080
+ command: described.command,
5081
+ cause: schemaCause,
5082
+ ...context
5083
+ }) : new CommandOutputError({
5084
+ kind: "notJson",
5085
+ command: described.command,
5086
+ cause: notJsonCause,
5087
+ ...context
5088
+ }));
5089
+ });
5090
+ const exitCode = effect.Effect.fn("Run.exitCode")(function* (command, options) {
5091
+ yield* annotate(command);
5092
+ return (yield* collectClassified(command, options, void 0)).exitCode;
5093
+ });
5094
+ const succeeds = effect.Effect.fn("Run.succeeds")(function* (command, options) {
5095
+ yield* annotate(command);
5096
+ return yield* collectClassified(command, options, void 0).pipe(effect.Effect.map((output) => output.succeeded), effect.Effect.catch(() => effect.Effect.succeed(false)));
5097
+ });
5098
+ const detach = effect.Effect.fn("Run.detach")(function* (command) {
5099
+ yield* annotate(command);
5100
+ return yield* effect.Effect.scoped(effect.Effect.gen(function* () {
5101
+ const handle = yield* (yield* effect_unstable_process.ChildProcessSpawner.ChildProcessSpawner).spawn(command);
5102
+ yield* handle.unref;
5103
+ return handle.pid;
5104
+ })).pipe(effect.Effect.catch((error) => effect.Effect.fail(CommandFailedError.spawn(command, error))));
5105
+ });
5106
+ const stream = (command, options) => effect.Stream.unwrap(effect.Effect.map(effect_unstable_process.ChildProcessSpawner.ChildProcessSpawner, (spawner) => spawner.streamLines(command, { includeStderr: options?.includeStderr ?? false }))).pipe(effect.Stream.mapError((error) => CommandFailedError.spawn(command, error)));
5107
+ const extendEnv = effect.Function.dual(2, (self, env) => {
5108
+ if (effect_unstable_process.ChildProcess.isStandardCommand(self)) {
5109
+ const merged = self.options.env === void 0 ? env : {
5110
+ ...self.options.env,
5111
+ ...env
5112
+ };
5113
+ return effect_unstable_process.ChildProcess.make(self.command, self.args, {
5114
+ ...self.options,
5115
+ env: merged,
5116
+ extendEnv: true
5117
+ });
5118
+ }
5119
+ return effect_unstable_process.ChildProcess.pipeTo(extendEnv(self.left, env), extendEnv(self.right, env), self.options);
5120
+ });
5121
+ /**
5122
+ * Structured running of core `ChildProcess.Command` values.
5123
+ *
5124
+ * @remarks
5125
+ * These are free functions over core's contract, **not** a service: core's
5126
+ * `ChildProcessSpawner` already is the subprocess service, and wrapping it in a
5127
+ * second one is the re-declaration this package exists not to repeat. Tests
5128
+ * stub the spawner (`ChildProcessSpawner.make(mockSpawn)`), not these.
5129
+ *
5130
+ * A non-zero exit is a *result* for {@link Run.collect}, {@link Run.exitCode},
5131
+ * {@link Run.succeeds} and {@link Run.jsonLine}, and a typed *failure* for
5132
+ * {@link Run.text}, {@link Run.lines} and {@link Run.json} — the split is
5133
+ * deliberate, matching core (where a non-zero exit is a success) at the
5134
+ * reporting level while giving the interpreting helpers the ergonomics callers
5135
+ * actually want.
5136
+ *
5137
+ * The interpreting helpers also **trim**: {@link Run.text} strips leading and
5138
+ * trailing whitespace from the whole result — not just a trailing newline —
5139
+ * and {@link Run.lines} trims each line. Fixed-column output whose first
5140
+ * column can be whitespace (`git status --porcelain`) silently loses that
5141
+ * column through either, producing plausible wrong values rather than an
5142
+ * error. Parse that kind of output from the untrimmed `stdout` of
5143
+ * {@link Run.collect}'s {@link CommandOutput} instead.
5144
+ *
5145
+ * @public
5146
+ */
5147
+ var Run = class {
5148
+ constructor() {}
5149
+ /**
5150
+ * Spawns `command`, collects stdout and stderr concurrently, and resolves
5151
+ * with the {@link CommandOutput} once the process exits.
5152
+ *
5153
+ * @remarks
5154
+ * A non-zero exit is a *result* here, not a failure — see {@link Run}'s
5155
+ * remarks for the split against {@link Run.text}, {@link Run.lines} and
5156
+ * {@link Run.json}.
5157
+ */
5158
+ static collect = collect;
5159
+ /**
5160
+ * Like {@link Run.collect}, but also tees each stream to the `Stdio` in `R`
5161
+ * as it arrives, for a caller that wants live output alongside the captured
5162
+ * {@link CommandOutput}.
5163
+ */
5164
+ static collectTee = collectTee;
5165
+ /**
5166
+ * Runs `command` and resolves with trimmed stdout on a zero exit.
5167
+ *
5168
+ * @remarks
5169
+ * A non-zero exit is a typed failure here — {@link CommandFailedError} —
5170
+ * unlike {@link Run.collect}, {@link Run.exitCode} and {@link Run.succeeds},
5171
+ * which treat it as a result.
5172
+ *
5173
+ * The trim strips **leading and trailing whitespace**, not just the trailing
5174
+ * newline. For parse-sensitive output where leading whitespace is data
5175
+ * (`git status --porcelain`, whose first entry's status column it would
5176
+ * silently eat), use {@link Run.collect} and read its {@link CommandOutput}'s
5177
+ * untrimmed `stdout` instead.
5178
+ */
5179
+ static text = text$4;
5180
+ /**
5181
+ * Runs `command` and resolves with stdout split into trimmed, non-empty
5182
+ * lines on a zero exit.
5183
+ *
5184
+ * @remarks
5185
+ * A non-zero exit is a typed failure here — {@link CommandFailedError} —
5186
+ * matching {@link Run.text} and {@link Run.json}.
5187
+ */
5188
+ static lines = lines;
5189
+ /**
5190
+ * Runs `command`, parses stdout as JSON and decodes it against `schema` on
5191
+ * a zero exit.
5192
+ *
5193
+ * @remarks
5194
+ * Fails with {@link CommandOutputError} when stdout is not JSON or does not
5195
+ * decode; a non-zero exit fails with {@link CommandFailedError}, matching
5196
+ * {@link Run.text} and {@link Run.lines}.
5197
+ *
5198
+ * This parses the **whole** of stdout and requires a zero exit. For a
5199
+ * protocol payload located by scanning stdout lines from the end — tolerant
5200
+ * of noise around it and of a non-zero exit — use {@link Run.jsonLine}
5201
+ * instead.
5202
+ */
5203
+ static json = json;
5204
+ /**
5205
+ * Runs `command` and, **scanning stdout lines from the end**, resolves with
5206
+ * the first line that both parses as JSON and decodes against `schema` —
5207
+ * the framing variant of {@link Run.json}, for a child that reports through
5208
+ * a single JSON protocol payload near the end of its output.
5209
+ *
5210
+ * @remarks
5211
+ * The framing tolerates noise on **both sides** of the payload: noise before
5212
+ * it (a subprocess-loaded hook's own `console.log`, a tool's warnings) and
5213
+ * noise after it (a hook logging from `process.on("exit", ...)` fires after
5214
+ * the payload has flushed — the trigger for widening the old "last non-empty
5215
+ * line must decode" contract, spencerbeggs/effected#292). Lines are split on
5216
+ * `\r?\n`, whitespace-only lines are dropped, and the scan runs from the last
5217
+ * line backwards until one decodes. The tolerance is positional, not
5218
+ * volumetric: the whole of stdout is still captured under
5219
+ * {@link RunOptions.maxOutputBytes} (default
5220
+ * {@link DEFAULT_MAX_OUTPUT_BYTES}, 16 MiB), so a child whose noise exceeds
5221
+ * the ceiling fails typed as `"tooLarge"` before any line is examined —
5222
+ * raise the ceiling for a child known to be loud in volume.
5223
+ *
5224
+ * The scan's consequence: when **multiple** lines decode under `schema`, the
5225
+ * **last** one wins. A child must therefore never emit two schema-valid
5226
+ * lines, and a consumer schema should be shaped so an accidental log line
5227
+ * cannot satisfy it — a discriminated envelope with a required literal field
5228
+ * (`ok: true | false`, the shape `@effected/workspaces`' `ReplayPayload`
5229
+ * uses) rather than a permissive record a stray `console.log(someObject)`
5230
+ * might match.
5231
+ *
5232
+ * Unlike {@link Run.json}, this parses **regardless of the exit code** — a
5233
+ * deliberate posture, not an oversight. A protocol payload discriminates
5234
+ * success in-band (its own `ok` field, its own error shape), so the payload
5235
+ * outranks the exit code: a child that crashes *after* flushing its payload
5236
+ * still reported, and a caller that wants exit-code semantics has
5237
+ * {@link Run.json}. When no line decodes anywhere, the typed
5238
+ * {@link CommandOutputError} carries the exit code and both captured streams
5239
+ * (redacted) as context, so the failure is diagnosable without re-running.
5240
+ * Its `kind` preserves the near-miss diagnostic: `"schema"` when at least
5241
+ * one line parsed as JSON but none decoded — with the **last parseable
5242
+ * line's** decode failure as `cause`, that line being the most probable
5243
+ * intended payload — and `"notJson"` only when no non-empty line was JSON at
5244
+ * all (carrying the last non-empty line's parse error). A spawn failure or
5245
+ * an opted-in timeout still fails with {@link CommandFailedError}.
5246
+ */
5247
+ static jsonLine = jsonLine;
5248
+ /**
5249
+ * Runs `command` and resolves with its exit code alone.
5250
+ *
5251
+ * @remarks
5252
+ * A non-zero exit is a *result* here, not a failure — see {@link Run}'s
5253
+ * remarks for the split against {@link Run.text}, {@link Run.lines} and
5254
+ * {@link Run.json}.
5255
+ */
5256
+ static exitCode = exitCode;
5257
+ /**
5258
+ * Runs `command` and resolves with whether it exited zero, collapsing a
5259
+ * spawn or other classified failure to `false` rather than propagating it.
5260
+ */
5261
+ static succeeds = succeeds;
5262
+ /** Decoded stdout lines as they arrive, for output too large or too long-lived to collect. */
5263
+ static stream = stream;
5264
+ /**
5265
+ * Spawns `command` and resolves with its pid without waiting for exit.
5266
+ *
5267
+ * @remarks
5268
+ * Unrefs the child **before** this scope closes, so it survives the
5269
+ * caller's scope closing — the Node backend's release skips the kill for an
5270
+ * unref'd child, and reversing that order kills it with the scope instead.
5271
+ * Fails with {@link CommandFailedError} if the process never starts.
5272
+ */
5273
+ static detach = detach;
5274
+ /**
5275
+ * Adds environment variables to a command WITHOUT losing the parent
5276
+ * environment: merges `env` over any existing command environment (new values
5277
+ * win, matching core's `ChildProcess.setEnv`) and sets `extendEnv: true`.
5278
+ *
5279
+ * @remarks
5280
+ * This combinator exists because of a core trap: `ChildProcess.setEnv` merges
5281
+ * into `options.env` but never sets `extendEnv`, and the Node spawner resolves
5282
+ * the child environment as `extendEnv ? { ...process.env, ...env } : env` — so
5283
+ * a command built with bare `setEnv({ SOME_VAR: x })` spawns a child whose
5284
+ * ENTIRE environment is that one variable: no `PATH`, no `HOME`. The failure is
5285
+ * silent at the type level and surfaces as "spawned tool cannot find its own
5286
+ * binary" at runtime.
5287
+ *
5288
+ * Deliberately forces `extendEnv: true` even where construction set it `false`
5289
+ * — inheriting the parent environment is this combinator's entire purpose. A
5290
+ * caller who wants a hermetic environment uses core's `setEnv` or construction
5291
+ * options (`ChildProcess.make(cmd, args, { env, extendEnv: false })`) directly.
5292
+ *
5293
+ * For a pipeline, applies to every command in the pipeline (mirroring core's
5294
+ * `setEnv`), preserving the pipe's own options. Composes core's public
5295
+ * vocabulary (`ChildProcess.make`, `ChildProcess.pipeTo`) — it re-declares
5296
+ * nothing.
5297
+ */
5298
+ static extendEnv = extendEnv;
5299
+ /** Default ceiling on captured bytes per stream. See {@link DEFAULT_MAX_OUTPUT_BYTES}. */
5300
+ static DEFAULT_MAX_OUTPUT_BYTES = DEFAULT_MAX_OUTPUT_BYTES;
5301
+ /** The placeholder written in place of a redacted secret. See {@link REDACTED}. */
5302
+ static REDACTED = "***";
5303
+ };
5304
+ //#endregion
5305
+ //#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/ReleaseAgeGate.js
4635
5306
  const MS_PER_MINUTE = 6e4;
4636
5307
  /**
4637
5308
  * A source's partial contribution to a {@link ReleaseAgeGate}: the effective
@@ -4801,7 +5472,7 @@ var ReleaseAgeGate = class ReleaseAgeGate extends effect.Schema.Class("ReleaseAg
4801
5472
  }
4802
5473
  };
4803
5474
  //#endregion
4804
- //#region ../../node_modules/.pnpm/@effected+lockfiles@0.3.2_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__@effected+npm@0._ff048038a9678f5144f817ad24d8f96e/node_modules/@effected/lockfiles/ImporterDependency.js
5475
+ //#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/ImporterDependency.js
4805
5476
  /**
4806
5477
  * One declared dependency of one workspace importer, as the lockfile records it.
4807
5478
  *
@@ -4839,7 +5510,7 @@ var ImporterDependency = class extends effect.Schema.Class("ImporterDependency")
4839
5510
  depType: DependencyField
4840
5511
  }) {};
4841
5512
  //#endregion
4842
- //#region ../../node_modules/.pnpm/@effected+lockfiles@0.3.2_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__@effected+npm@0._ff048038a9678f5144f817ad24d8f96e/node_modules/@effected/lockfiles/LockfileImporter.js
5513
+ //#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
4843
5514
  /**
4844
5515
  * One workspace importer's declared dependencies, as the lockfile records them.
4845
5516
  *
@@ -4863,7 +5534,7 @@ var LockfileImporter = class extends effect.Schema.Class("LockfileImporter")({
4863
5534
  dependencies: effect.Schema.Array(ImporterDependency)
4864
5535
  }) {};
4865
5536
  //#endregion
4866
- //#region ../../node_modules/.pnpm/@effected+lockfiles@0.3.2_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__@effected+npm@0._ff048038a9678f5144f817ad24d8f96e/node_modules/@effected/lockfiles/ResolvedPackage.js
5537
+ //#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/ResolvedPackage.js
4867
5538
  const EMPTY_DEPENDENCIES = {};
4868
5539
  /**
4869
5540
  * A package resolved from a lockfile.
@@ -4898,7 +5569,7 @@ var ResolvedPackage = class extends effect.Schema.Class("ResolvedPackage")({
4898
5569
  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)))
4899
5570
  }) {};
4900
5571
  //#endregion
4901
- //#region ../../node_modules/.pnpm/@effected+lockfiles@0.3.2_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__@effected+npm@0._ff048038a9678f5144f817ad24d8f96e/node_modules/@effected/lockfiles/WorkspaceDependency.js
5572
+ //#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/WorkspaceDependency.js
4902
5573
  /**
4903
5574
  * A directed dependency edge between two workspace packages as recorded in
4904
5575
  * the lockfile.
@@ -4920,7 +5591,7 @@ var WorkspaceDependency = class extends effect.Schema.Class("WorkspaceDependency
4920
5591
  constraint: effect.Schema.String
4921
5592
  }) {};
4922
5593
  //#endregion
4923
- //#region ../../node_modules/.pnpm/@effected+lockfiles@0.3.2_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__@effected+npm@0._ff048038a9678f5144f817ad24d8f96e/node_modules/@effected/lockfiles/PnpmExtension.js
5594
+ //#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/PnpmExtension.js
4924
5595
  /**
4925
5596
  * Extension data specific to pnpm lockfiles, attached to `Lockfile.extension`
4926
5597
  * when the format is `"pnpm"`.
@@ -4945,7 +5616,7 @@ var PnpmExtension = class extends effect.Schema.Class("PnpmExtension")({
4945
5616
  }))
4946
5617
  }) {};
4947
5618
  //#endregion
4948
- //#region ../../node_modules/.pnpm/@effected+lockfiles@0.3.2_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__@effected+npm@0._ff048038a9678f5144f817ad24d8f96e/node_modules/@effected/lockfiles/LockfileFormat.js
5619
+ //#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/LockfileFormat.js
4949
5620
  /**
4950
5621
  * The lockfile formats this package parses: bun's `bun.lock` (JSONC), npm's
4951
5622
  * `package-lock.json` (v2/v3 JSON), pnpm's `pnpm-lock.yaml` and yarn Berry's
@@ -4983,7 +5654,7 @@ const FILENAMES = {
4983
5654
  */
4984
5655
  const filenameFor = (format) => FILENAMES[format][0];
4985
5656
  //#endregion
4986
- //#region ../../node_modules/.pnpm/@effected+lockfiles@0.3.2_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__@effected+npm@0._ff048038a9678f5144f817ad24d8f96e/node_modules/@effected/lockfiles/internal/shared.js
5657
+ //#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/internal/shared.js
4987
5658
  /**
4988
5659
  * The four dependency sections of a manifest, in a stable order — the shared
4989
5660
  * dependency-sections table (v3's `DEP_SECTIONS`). Each entry is both the
@@ -6912,7 +7583,7 @@ var JsoncModifier = class {
6912
7583
  });
6913
7584
  };
6914
7585
  //#endregion
6915
- //#region ../../node_modules/.pnpm/@effected+lockfiles@0.3.2_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__@effected+npm@0._ff048038a9678f5144f817ad24d8f96e/node_modules/@effected/lockfiles/internal/bun.js
7586
+ //#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/internal/bun.js
6916
7587
  const DepRecord$2 = effect.Schema.optionalKey(effect.Schema.Record(effect.Schema.String, effect.Schema.String));
6917
7588
  const BunWorkspaceEntry = effect.Schema.Struct({
6918
7589
  name: effect.Schema.optionalKey(effect.Schema.String),
@@ -7005,7 +7676,7 @@ const toFields$3 = (raw) => effect.Effect.gen(function* () {
7005
7676
  };
7006
7677
  });
7007
7678
  //#endregion
7008
- //#region ../../node_modules/.pnpm/@effected+lockfiles@0.3.2_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__@effected+npm@0._ff048038a9678f5144f817ad24d8f96e/node_modules/@effected/lockfiles/internal/npm.js
7679
+ //#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/internal/npm.js
7009
7680
  const DepRecord$1 = effect.Schema.optionalKey(effect.Schema.Record(effect.Schema.String, effect.Schema.String));
7010
7681
  const NpmPackageEntry = effect.Schema.Struct({
7011
7682
  name: effect.Schema.optionalKey(effect.Schema.String),
@@ -13927,7 +14598,7 @@ function deepEqualValues(a, b) {
13927
14598
  return false;
13928
14599
  }
13929
14600
  //#endregion
13930
- //#region ../../node_modules/.pnpm/@effected+lockfiles@0.3.2_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__@effected+npm@0._ff048038a9678f5144f817ad24d8f96e/node_modules/@effected/lockfiles/internal/documents.js
14601
+ //#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/internal/documents.js
13931
14602
  /**
13932
14603
  * An empty YAML document composes to `null` (`Yaml.parseAll("")` is `[null]`,
13933
14604
  * and the trailing document of an env-only `pnpm-lock.yaml` is `null` too).
@@ -13997,7 +14668,7 @@ const selectSoleDocument = (content) => effect.Effect.gen(function* () {
13997
14668
  };
13998
14669
  });
13999
14670
  //#endregion
14000
- //#region ../../node_modules/.pnpm/@effected+lockfiles@0.3.2_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__@effected+npm@0._ff048038a9678f5144f817ad24d8f96e/node_modules/@effected/lockfiles/internal/pnpm.js
14671
+ //#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/internal/pnpm.js
14001
14672
  const PnpmImporterDeps = effect.Schema.optionalKey(effect.Schema.Record(effect.Schema.String, effect.Schema.Struct({
14002
14673
  specifier: effect.Schema.String,
14003
14674
  version: effect.Schema.String
@@ -14122,7 +14793,7 @@ const toFields$1 = (raw) => effect.Effect.gen(function* () {
14122
14793
  };
14123
14794
  });
14124
14795
  //#endregion
14125
- //#region ../../node_modules/.pnpm/@effected+lockfiles@0.3.2_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__@effected+npm@0._ff048038a9678f5144f817ad24d8f96e/node_modules/@effected/lockfiles/internal/yarn.js
14796
+ //#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/internal/yarn.js
14126
14797
  const YarnLockfileRaw = effect.Schema.Record(effect.Schema.String, effect.Schema.Unknown);
14127
14798
  const DepRecord = effect.Schema.optionalKey(effect.Schema.Record(effect.Schema.String, effect.Schema.String));
14128
14799
  const YarnEntry = effect.Schema.Struct({
@@ -14245,7 +14916,7 @@ const cleanYarnDeps = (deps) => {
14245
14916
  return Object.fromEntries(Object.entries(deps).map(([name, value]) => [name, value.startsWith("npm:") ? value.slice(4) : value]));
14246
14917
  };
14247
14918
  //#endregion
14248
- //#region ../../node_modules/.pnpm/@effected+lockfiles@0.3.2_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__@effected+npm@0._ff048038a9678f5144f817ad24d8f96e/node_modules/@effected/lockfiles/Lockfile.js
14919
+ //#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/Lockfile.js
14249
14920
  const EMPTY_IMPORTERS = [];
14250
14921
  /**
14251
14922
  * Failure of `Lockfile.parse`: the given content is not a valid lockfile of
@@ -14489,7 +15160,7 @@ var Lockfile = class Lockfile extends effect.Schema.Class("Lockfile")({
14489
15160
  }
14490
15161
  };
14491
15162
  //#endregion
14492
- //#region ../../node_modules/.pnpm/@effected+lockfiles@0.3.2_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__@effected+npm@0._ff048038a9678f5144f817ad24d8f96e/node_modules/@effected/lockfiles/LockfileIntegrity.js
15163
+ //#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/LockfileIntegrity.js
14493
15164
  /**
14494
15165
  * The minimal manifest shape {@link LockfileIntegrity.compare} checks a
14495
15166
  * lockfile against: a package name plus the four optional dependency maps.
@@ -17288,7 +17959,7 @@ var Package = class Package extends effect.Schema.Class("Package")({
17288
17959
  }
17289
17960
  };
17290
17961
  //#endregion
17291
- //#region ../../node_modules/.pnpm/@effected+workspaces@0.9.5_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/WorkspacePackage.js
17962
+ //#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
17292
17963
  const EMPTY$1 = Object.freeze(Object.create(null));
17293
17964
  const EMPTY_MANIFEST = Object.freeze(Object.create(null));
17294
17965
  /**
@@ -17886,7 +18557,7 @@ var Walker$1 = class {
17886
18557
  static findRoot = findRoot$1;
17887
18558
  };
17888
18559
  //#endregion
17889
- //#region ../../node_modules/.pnpm/@effected+workspaces@0.9.5_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/WorkspaceRoot.js
18560
+ //#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
17890
18561
  /**
17891
18562
  * The marker filenames {@link WorkspaceRoot} probes for, in priority order.
17892
18563
  *
@@ -18073,7 +18744,7 @@ var WorkspaceRoot = class WorkspaceRoot extends effect.Context.Service()("@effec
18073
18744
  static layerTest = (root) => effect.Layer.effect(WorkspaceRoot, WorkspaceRoot.makeTest(root)).pipe(effect.Layer.provide(effect.Path.layer));
18074
18745
  };
18075
18746
  //#endregion
18076
- //#region ../../node_modules/.pnpm/@effected+workspaces@0.9.5_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/internal/limits.js
18747
+ //#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
18077
18748
  /**
18078
18749
  * Hard ceiling on directories the enumerator will visit for one pattern set.
18079
18750
  * Guards the pathological case a depth cap alone does not: a wide, shallow
@@ -18091,7 +18762,7 @@ const MAX_ENUMERATION_ENTRIES = 1e5;
18091
18762
  */
18092
18763
  const PRUNED_DIRECTORIES = /* @__PURE__ */ new Set([".git", "node_modules"]);
18093
18764
  //#endregion
18094
- //#region ../../node_modules/.pnpm/@effected+workspaces@0.9.5_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/internal/traverse.js
18765
+ //#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
18095
18766
  /** Directory names never descended into. */
18096
18767
  const isPruned = (entry) => PRUNED_DIRECTORIES.has(entry);
18097
18768
  /** Join root-relative POSIX segments; `""` is the root itself. */
@@ -18181,7 +18852,7 @@ var Traversal = class {
18181
18852
  }
18182
18853
  };
18183
18854
  //#endregion
18184
- //#region ../../node_modules/.pnpm/@effected+workspaces@0.9.5_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/internal/enumerate.js
18855
+ //#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
18185
18856
  /** Strip a trailing slash from `GlobPattern.enumerationPrefix` to get a relative directory. */
18186
18857
  const baseOf = (pattern) => pattern.enumerationPrefix.replace(/\/$/, "");
18187
18858
  /**
@@ -18251,7 +18922,7 @@ const enumerate = (root, globs, options) => effect.Effect.gen(function* () {
18251
18922
  return results;
18252
18923
  });
18253
18924
  //#endregion
18254
- //#region ../../node_modules/.pnpm/@effected+workspaces@0.9.5_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/internal/patterns.js
18925
+ //#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
18255
18926
  const stringsOf = (value) => Array.isArray(value) ? value.filter((entry) => typeof entry === "string") : void 0;
18256
18927
  /** The `packages:` list of a `pnpm-workspace.yaml` document. Total on a parsed document. */
18257
18928
  const pnpmPatternsOf = (document) => {
@@ -18308,7 +18979,7 @@ const readPatterns = (root) => effect.Effect.gen(function* () {
18308
18979
  return manifestPatternsOf(manifest);
18309
18980
  });
18310
18981
  //#endregion
18311
- //#region ../../node_modules/.pnpm/@effected+workspaces@0.9.5_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/WorkspaceDiscovery.js
18982
+ //#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
18312
18983
  /**
18313
18984
  * Raised when a workspace member's `package.json` cannot be read, parsed, or
18314
18985
  * used — it is missing, malformed, or lacks a `name` or `version`.
@@ -18561,6 +19232,15 @@ var WorkspaceDiscovery = class WorkspaceDiscovery extends effect.Context.Service
18561
19232
  for (const entry of index) if (filePath.startsWith(entry.prefix)) return effect.Option.some(entry.package);
18562
19233
  return effect.Option.none();
18563
19234
  };
19235
+ const packageIndexes = /* @__PURE__ */ new WeakMap();
19236
+ const packagesByName = (all) => {
19237
+ const cached = packageIndexes.get(all);
19238
+ if (cached !== void 0) return cached;
19239
+ const index = /* @__PURE__ */ new Map();
19240
+ for (const pkg of all) if (!index.has(pkg.name)) index.set(pkg.name, pkg);
19241
+ packageIndexes.set(all, index);
19242
+ return index;
19243
+ };
18564
19244
  return {
18565
19245
  info: effect.Effect.fn("WorkspaceDiscovery.info")(function* () {
18566
19246
  return (yield* memo).info;
@@ -18574,7 +19254,7 @@ var WorkspaceDiscovery = class WorkspaceDiscovery extends effect.Context.Service
18574
19254
  }),
18575
19255
  getPackage: effect.Effect.fn("WorkspaceDiscovery.getPackage")(function* (name) {
18576
19256
  const all = yield* packages;
18577
- const found = all.find((pkg) => pkg.name === name);
19257
+ const found = packagesByName(all).get(name);
18578
19258
  if (found !== void 0) return found;
18579
19259
  return yield* effect.Effect.fail(new PackageNotFoundError({
18580
19260
  name,
@@ -18738,7 +19418,16 @@ var WorkspaceDiscovery = class WorkspaceDiscovery extends effect.Context.Service
18738
19418
  */
18739
19419
  static workspaceResolver = effect.Layer.effect(WorkspaceResolver, effect.Effect.gen(function* () {
18740
19420
  const discovery = yield* WorkspaceDiscovery;
18741
- return { versionOf: (packageName) => discovery.listPackages().pipe(effect.Effect.map((all) => effect.Option.fromUndefinedOr(all.find((pkg) => pkg.name === packageName)?.version)), effect.Effect.mapError((cause) => new DependencyResolutionError({
19421
+ const versionIndexes = /* @__PURE__ */ new WeakMap();
19422
+ const versionsByName = (all) => {
19423
+ const cached = versionIndexes.get(all);
19424
+ if (cached !== void 0) return cached;
19425
+ const index = /* @__PURE__ */ new Map();
19426
+ for (const pkg of all) if (!index.has(pkg.name)) index.set(pkg.name, pkg.version);
19427
+ versionIndexes.set(all, index);
19428
+ return index;
19429
+ };
19430
+ return { versionOf: (packageName) => discovery.listPackages().pipe(effect.Effect.map((all) => effect.Option.fromUndefinedOr(versionsByName(all).get(packageName))), effect.Effect.mapError((cause) => new DependencyResolutionError({
18742
19431
  specifier: `workspace:${packageName}`,
18743
19432
  cause
18744
19433
  }))) };
@@ -18746,7 +19435,7 @@ var WorkspaceDiscovery = class WorkspaceDiscovery extends effect.Context.Service
18746
19435
  };
18747
19436
  const isStringRecord$2 = (value) => value !== null && typeof value === "object" && !Array.isArray(value) && Object.values(value).every((entry) => typeof entry === "string");
18748
19437
  //#endregion
18749
- //#region ../../node_modules/.pnpm/@effected+workspaces@0.9.5_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/DependencyGraph.js
19438
+ //#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
18750
19439
  /**
18751
19440
  * Raised when the workspace dependency graph cannot be topologically ordered
18752
19441
  * because it contains a cycle.
@@ -18979,10 +19668,32 @@ const kahn = (edges) => {
18979
19668
  };
18980
19669
  };
18981
19670
  //#endregion
18982
- //#region ../../node_modules/.pnpm/@effected+git@0.5.2_effect@4.0.0-beta.101/node_modules/@effected/git/GitCommand.js
19671
+ //#region ../../node_modules/.pnpm/@effected+git@0.6.0_effect@4.0.0-beta.101/node_modules/@effected/git/GitCommand.js
19672
+ /** The mask every whole-value sensitive positional is replaced with. */
19673
+ const REDACTED = "<redacted>";
19674
+ const secretValue = (value) => ({
19675
+ redact: "value",
19676
+ value
19677
+ });
19678
+ const secretUrl = (value) => ({
19679
+ redact: "url",
19680
+ value
19681
+ });
19682
+ /**
19683
+ * Masks the userinfo component of a URL (`scheme://user:token@host/...` →
19684
+ * `scheme://<redacted>@host/...`). A value carrying no embedded userinfo — a
19685
+ * remote name, a credential-free URL, an scp-style `host:path` — passes
19686
+ * through untouched, so the common case stays fully debuggable.
19687
+ *
19688
+ * The userinfo match is greedy (`[^/]*@` — everything through the LAST `@`
19689
+ * before the first path slash): URL authorities split at the last `@`, so a
19690
+ * password containing a literal `@` (`user:p\@ss\@host/...`) must be
19691
+ * consumed whole or its tail would survive into `redactedArgs`.
19692
+ */
19693
+ const redactUrlUserinfo = (value) => value.replace(/^([a-z][a-z0-9+.-]*:\/\/)[^/]*@/i, `$1${REDACTED}@`);
18983
19694
  /**
18984
- * Builds a `git` `ChildProcess.StandardCommand` with the argv this package
18985
- * classifies against.
19695
+ * Builds a `git` {@link GitInvocation} with the argv this package classifies
19696
+ * against.
18986
19697
  *
18987
19698
  * @remarks
18988
19699
  * `LC_ALL=C` is pinned on every invocation because git's stderr
@@ -18998,10 +19709,18 @@ const kahn = (edges) => {
18998
19709
  * the working directory per invocation via `ChildProcess.setCwd`, which
18999
19710
  * returns a new command and leaves this one unchanged.
19000
19711
  */
19001
- const git = (args) => effect_unstable_process.ChildProcess.make("git", args, {
19002
- env: { LC_ALL: "C" },
19003
- extendEnv: true
19004
- });
19712
+ const git = (args, stdin) => {
19713
+ const raw = args.map((arg) => typeof arg === "string" ? arg : arg.value);
19714
+ const redactedArgs = args.map((arg) => typeof arg === "string" ? arg : arg.redact === "value" ? REDACTED : redactUrlUserinfo(arg.value));
19715
+ return {
19716
+ command: effect_unstable_process.ChildProcess.make("git", raw, {
19717
+ env: { LC_ALL: "C" },
19718
+ extendEnv: true,
19719
+ ...stdin !== void 0 ? { stdin: effect.Stream.make(new TextEncoder().encode(stdin)) } : {}
19720
+ }),
19721
+ redactedArgs
19722
+ };
19723
+ };
19005
19724
  const show = (ref, path) => git(["show", `${ref}:${path}`]);
19006
19725
  const lsTree = (ref, pathspec = []) => git([
19007
19726
  "ls-tree",
@@ -19060,7 +19779,7 @@ const checkout = (ref, detach = false) => git([
19060
19779
  const fetch$1 = (remote, ref, depth, tag = false) => git([
19061
19780
  "fetch",
19062
19781
  ...depth !== void 0 ? ["--depth", String(depth)] : [],
19063
- remote,
19782
+ secretUrl(remote),
19064
19783
  ...tag ? ["tag"] : [],
19065
19784
  ref
19066
19785
  ]);
@@ -19076,7 +19795,7 @@ const submoduleAdd = (url, path, depth) => git([
19076
19795
  "add",
19077
19796
  ...depth !== void 0 ? ["--depth", String(depth)] : [],
19078
19797
  "--",
19079
- url,
19798
+ secretUrl(url),
19080
19799
  path
19081
19800
  ]);
19082
19801
  const sparseCheckoutSet = (patterns, cone) => git([
@@ -19089,13 +19808,55 @@ const configSet = (key, value, file) => git([
19089
19808
  "config",
19090
19809
  ...file !== void 0 ? ["-f", file] : [],
19091
19810
  key,
19092
- value
19811
+ secretValue(value)
19093
19812
  ]);
19094
19813
  const add = (paths) => git([
19095
19814
  "add",
19096
19815
  "--",
19097
19816
  ...paths
19098
19817
  ]);
19818
+ const reset = (mode = "mixed", ref) => git([
19819
+ "reset",
19820
+ `--${mode}`,
19821
+ ...ref !== void 0 ? [ref] : []
19822
+ ]);
19823
+ const clean = (directories = false, ignored = false, paths = []) => git([
19824
+ "clean",
19825
+ "--force",
19826
+ ...directories ? ["-d"] : [],
19827
+ ...ignored ? ["-x"] : [],
19828
+ ...paths.length > 0 ? ["--", ...paths] : []
19829
+ ]);
19830
+ const restore = (paths, source, staged = false, worktree = false) => git([
19831
+ "restore",
19832
+ ...source !== void 0 ? ["--source", source] : [],
19833
+ ...staged ? ["--staged"] : [],
19834
+ ...worktree ? ["--worktree"] : [],
19835
+ "--",
19836
+ ...paths
19837
+ ]);
19838
+ const branchCreate = (name, startPoint, checkout = false, force = false) => checkout ? git([
19839
+ "checkout",
19840
+ force ? "-B" : "-b",
19841
+ name,
19842
+ ...startPoint !== void 0 ? [startPoint] : []
19843
+ ]) : git([
19844
+ "branch",
19845
+ ...force ? ["-f"] : [],
19846
+ name,
19847
+ ...startPoint !== void 0 ? [startPoint] : []
19848
+ ]);
19849
+ const branchDelete = (name, force = false) => git([
19850
+ "branch",
19851
+ force ? "-D" : "-d",
19852
+ name
19853
+ ]);
19854
+ const isShallow = () => git(["rev-parse", "--is-shallow-repository"]);
19855
+ const fetchUnshallow = (remote = "origin") => git([
19856
+ "fetch",
19857
+ "--unshallow",
19858
+ secretUrl(remote)
19859
+ ]);
19099
19860
  const nameStatus = (base, head, relative = false) => git([
19100
19861
  "diff",
19101
19862
  "--name-status",
@@ -19136,40 +19897,276 @@ const status = () => git([
19136
19897
  "--porcelain",
19137
19898
  "-z"
19138
19899
  ]);
19139
- /**
19140
- * Pure constructors for the `git` `ChildProcess.Command` values this package
19141
- * spawns.
19142
- *
19143
- * @remarks
19144
- * Every constructor returns a cwd-less, argv-only `Command` — no spawning,
19145
- * no working directory baked in. `Git` applies the working directory per
19146
- * call with `ChildProcess.setCwd` and owns the actual spawn, timeout, and
19147
- * error classification.
19148
- *
19149
- * @public
19150
- */
19151
- var GitCommand = class {
19152
- constructor() {}
19153
- /**
19154
- * `git show <ref>:<path>` the contents of `path` as it existed at `ref`,
19155
- * without checking anything out.
19156
- */
19157
- static show = show;
19158
- /**
19159
- * `git ls-tree -r -z <ref> [-- <pathspec>...]` every path in the tree at
19160
- * `ref`, recursively, NUL-terminated, optionally scoped to `pathspec`.
19161
- *
19162
- * @remarks
19163
- * `-z` is load-bearing: git paths may themselves contain newlines, so the
19164
- * caller must split on `"\0"`, never on `"\n"`. When `pathspec` is provided,
19165
- * a literal `--` separator is inserted before the pathspec entries to prevent
19166
- * git from interpreting pathspec values as options.
19167
- */
19168
- static lsTree = lsTree;
19169
- /**
19170
- * `git cat-file -e <ref>` — checks whether `ref` resolves to an existing
19171
- * object, without printing it. A non-zero exit means the ref does not exist.
19172
- */
19900
+ const submoduleStatus = (paths = [], recursive = false) => git([
19901
+ "submodule",
19902
+ "status",
19903
+ ...recursive ? ["--recursive"] : [],
19904
+ ...paths.length > 0 ? ["--", ...paths] : []
19905
+ ]);
19906
+ const submoduleInit = (paths = []) => git([
19907
+ "submodule",
19908
+ "init",
19909
+ ...paths.length > 0 ? ["--", ...paths] : []
19910
+ ]);
19911
+ const submoduleDeinit = (paths, all = false, force = false) => git([
19912
+ "submodule",
19913
+ "deinit",
19914
+ ...force ? ["--force"] : [],
19915
+ ...all ? ["--all"] : ["--", ...paths]
19916
+ ]);
19917
+ const submoduleSync = (paths = [], recursive = false) => git([
19918
+ "submodule",
19919
+ "sync",
19920
+ ...recursive ? ["--recursive"] : [],
19921
+ ...paths.length > 0 ? ["--", ...paths] : []
19922
+ ]);
19923
+ const submoduleSetUrl = (path, url) => git([
19924
+ "submodule",
19925
+ "set-url",
19926
+ "--",
19927
+ path,
19928
+ secretUrl(url)
19929
+ ]);
19930
+ const submoduleSetBranch = (path, branch) => git([
19931
+ "submodule",
19932
+ "set-branch",
19933
+ ...branch === void 0 ? ["--default"] : ["--branch", branch],
19934
+ "--",
19935
+ path
19936
+ ]);
19937
+ const submoduleAbsorbgitdirs = (paths = []) => git([
19938
+ "submodule",
19939
+ "absorbgitdirs",
19940
+ ...paths.length > 0 ? ["--", ...paths] : []
19941
+ ]);
19942
+ const submoduleForeach = (command, recursive = false) => git([
19943
+ "submodule",
19944
+ "foreach",
19945
+ ...recursive ? ["--recursive"] : [],
19946
+ command
19947
+ ]);
19948
+ const lsRemote = (remote, heads = false, tags = false, patterns = []) => git([
19949
+ "ls-remote",
19950
+ ...heads ? ["--heads"] : [],
19951
+ ...tags ? ["--tags"] : [],
19952
+ secretUrl(remote),
19953
+ ...patterns
19954
+ ]);
19955
+ const remoteAdd = (name, url) => git([
19956
+ "remote",
19957
+ "add",
19958
+ name,
19959
+ secretUrl(url)
19960
+ ]);
19961
+ const remoteRemove = (name) => git([
19962
+ "remote",
19963
+ "remove",
19964
+ name
19965
+ ]);
19966
+ const remoteSetUrl = (name, url) => git([
19967
+ "remote",
19968
+ "set-url",
19969
+ name,
19970
+ secretUrl(url)
19971
+ ]);
19972
+ const stashRef = (index) => `stash@{${index}}`;
19973
+ const stashPush = (message, includeUntracked = false, paths = []) => git([
19974
+ "stash",
19975
+ "push",
19976
+ ...includeUntracked ? ["--include-untracked"] : [],
19977
+ ...message !== void 0 ? ["-m", message] : [],
19978
+ ...paths.length > 0 ? ["--", ...paths] : []
19979
+ ]);
19980
+ const stashPop = (index) => git([
19981
+ "stash",
19982
+ "pop",
19983
+ ...index !== void 0 ? [stashRef(index)] : []
19984
+ ]);
19985
+ const stashApply = (index) => git([
19986
+ "stash",
19987
+ "apply",
19988
+ ...index !== void 0 ? [stashRef(index)] : []
19989
+ ]);
19990
+ const stashDrop = (index) => git([
19991
+ "stash",
19992
+ "drop",
19993
+ ...index !== void 0 ? [stashRef(index)] : []
19994
+ ]);
19995
+ const stashList = () => git([
19996
+ "stash",
19997
+ "list",
19998
+ "-z",
19999
+ "--format=%gd%x1f%H%x1f%gs"
20000
+ ]);
20001
+ const branchList = (remotes = false, all = false) => git([
20002
+ "branch",
20003
+ "--list",
20004
+ ...all ? ["--all"] : remotes ? ["--remotes"] : [],
20005
+ "--format=%(HEAD)%00%(refname:short)%00%(objectname)"
20006
+ ]);
20007
+ const tagCreate = (name, ref, message, force = false) => git([
20008
+ "tag",
20009
+ ...force ? ["--force"] : [],
20010
+ ...message !== void 0 ? ["-m", message] : [],
20011
+ name,
20012
+ ...ref !== void 0 ? [ref] : []
20013
+ ]);
20014
+ const tagDelete = (name) => git([
20015
+ "tag",
20016
+ "--delete",
20017
+ name
20018
+ ]);
20019
+ const tagList = (pattern) => git([
20020
+ "tag",
20021
+ "--list",
20022
+ ...pattern !== void 0 ? [pattern] : []
20023
+ ]);
20024
+ const forEachRef = (patterns = []) => git([
20025
+ "for-each-ref",
20026
+ "--format=%(refname)%00%(objectname)%00%(objecttype)",
20027
+ ...patterns
20028
+ ]);
20029
+ const revList = (ref, limit, firstParent = false) => git([
20030
+ "rev-list",
20031
+ ...limit !== void 0 ? [`--max-count=${limit}`] : [],
20032
+ ...firstParent ? ["--first-parent"] : [],
20033
+ ref
20034
+ ]);
20035
+ const commit = (message, all = false, allowEmpty = false, amend = false, author) => git([
20036
+ "commit",
20037
+ ...all ? ["--all"] : [],
20038
+ ...allowEmpty ? ["--allow-empty"] : [],
20039
+ ...amend ? ["--amend"] : [],
20040
+ ...author !== void 0 ? [`--author=${author}`] : [],
20041
+ "-m",
20042
+ message
20043
+ ]);
20044
+ const push$1 = (remote, refspec, force = false, forceWithLease = false, tags = false, setUpstream = false) => git([
20045
+ "push",
20046
+ ...force ? ["--force"] : [],
20047
+ ...forceWithLease ? ["--force-with-lease"] : [],
20048
+ ...tags ? ["--tags"] : [],
20049
+ ...setUpstream ? ["--set-upstream"] : [],
20050
+ secretUrl(remote),
20051
+ ...refspec !== void 0 ? [refspec] : []
20052
+ ]);
20053
+ const pull = (remote, ref, rebase = false, ffOnly = false) => git([
20054
+ "pull",
20055
+ ...rebase ? ["--rebase"] : [],
20056
+ ...ffOnly ? ["--ff-only"] : [],
20057
+ secretUrl(remote),
20058
+ ...ref !== void 0 ? [ref] : []
20059
+ ]);
20060
+ const configList = (file) => git([
20061
+ "config",
20062
+ ...file !== void 0 ? ["-f", file] : [],
20063
+ "--list",
20064
+ "-z"
20065
+ ]);
20066
+ const configGetAll = (key, file) => git([
20067
+ "config",
20068
+ ...file !== void 0 ? ["-f", file] : [],
20069
+ "--get-all",
20070
+ "-z",
20071
+ key
20072
+ ]);
20073
+ const configUnset = (key, file, all = false) => git([
20074
+ "config",
20075
+ ...file !== void 0 ? ["-f", file] : [],
20076
+ all ? "--unset-all" : "--unset",
20077
+ key
20078
+ ]);
20079
+ const rm = (paths, cached = false, recursive = false, force = false) => git([
20080
+ "rm",
20081
+ ...cached ? ["--cached"] : [],
20082
+ ...recursive ? ["-r"] : [],
20083
+ ...force ? ["--force"] : [],
20084
+ "--",
20085
+ ...paths
20086
+ ]);
20087
+ const mv = (source, destination, force = false) => git([
20088
+ "mv",
20089
+ ...force ? ["--force"] : [],
20090
+ "--",
20091
+ source,
20092
+ destination
20093
+ ]);
20094
+ const checkIgnore = (paths) => git([
20095
+ "check-ignore",
20096
+ "-z",
20097
+ "--stdin"
20098
+ ], paths.map((path) => `${path}\0`).join(""));
20099
+ const worktreeAdd = (path, ref, detach = false, force = false) => git([
20100
+ "worktree",
20101
+ "add",
20102
+ ...force ? ["--force"] : [],
20103
+ ...detach ? ["--detach"] : [],
20104
+ path,
20105
+ ...ref !== void 0 ? [ref] : []
20106
+ ]);
20107
+ const worktreeList = () => git([
20108
+ "worktree",
20109
+ "list",
20110
+ "--porcelain",
20111
+ "-z"
20112
+ ]);
20113
+ const worktreeRemove = (path, force = false) => git([
20114
+ "worktree",
20115
+ "remove",
20116
+ ...force ? ["--force"] : [],
20117
+ path
20118
+ ]);
20119
+ const lsFiles = (pathspec = []) => git([
20120
+ "ls-files",
20121
+ "--stage",
20122
+ "-z",
20123
+ ...pathspec.length > 0 ? ["--", ...pathspec] : []
20124
+ ]);
20125
+ /**
20126
+ * Pure constructors for the `git` {@link GitInvocation} values this package
20127
+ * spawns.
20128
+ *
20129
+ * @remarks
20130
+ * Every constructor returns a cwd-less, argv-only {@link GitInvocation} — no
20131
+ * spawning, no working directory baked in. `Git` applies the working
20132
+ * directory per call with `ChildProcess.setCwd` on `invocation.command` and
20133
+ * owns the actual spawn, timeout, and error classification.
20134
+ *
20135
+ * **Redaction policy.** A constructor whose argv carries a sensitive
20136
+ * positional — a config value (`configSet`), or a URL that may embed
20137
+ * userinfo (the remote of `fetch`, `fetchUnshallow`, `lsRemote`, `push` and
20138
+ * `pull`, and the url of `submoduleAdd`, `submoduleSetUrl`, `remoteAdd` and
20139
+ * `remoteSetUrl`) —
20140
+ * masks it in {@link GitInvocation.redactedArgs}: a config value becomes
20141
+ * `<redacted>` wholesale, a URL keeps everything but its `userinfo@`
20142
+ * component. The `Git` service persists only the redacted argv in error
20143
+ * values, and its span annotations carry stable identifiers only (`cwd`,
20144
+ * keys, paths, remote/ref names) — never config values, never URLs.
20145
+ *
20146
+ * @public
20147
+ */
20148
+ var GitCommand = class {
20149
+ constructor() {}
20150
+ /**
20151
+ * `git show <ref>:<path>` — the contents of `path` as it existed at `ref`,
20152
+ * without checking anything out.
20153
+ */
20154
+ static show = show;
20155
+ /**
20156
+ * `git ls-tree -r -z <ref> [-- <pathspec>...]` — every path in the tree at
20157
+ * `ref`, recursively, NUL-terminated, optionally scoped to `pathspec`.
20158
+ *
20159
+ * @remarks
20160
+ * `-z` is load-bearing: git paths may themselves contain newlines, so the
20161
+ * caller must split on `"\0"`, never on `"\n"`. When `pathspec` is provided,
20162
+ * a literal `--` separator is inserted before the pathspec entries to prevent
20163
+ * git from interpreting pathspec values as options.
20164
+ */
20165
+ static lsTree = lsTree;
20166
+ /**
20167
+ * `git cat-file -e <ref>` — checks whether `ref` resolves to an existing
20168
+ * object, without printing it. A non-zero exit means the ref does not exist.
20169
+ */
19173
20170
  static refExists = refExists;
19174
20171
  /**
19175
20172
  * `git merge-base <a> <b>` — the best common ancestor commit of `a` and `b`.
@@ -19242,9 +20239,106 @@ var GitCommand = class {
19242
20239
  /**
19243
20240
  * Mutating: `git fetch [--depth <n>] <remote> [tag] <ref>` — fetches the given
19244
20241
  * ref from a remote, optionally with a depth limit and the `tag` keyword.
20242
+ *
20243
+ * @remarks
20244
+ * `remote` may be a URL as well as a remote name; an embedded
20245
+ * `userinfo@` credential is masked in {@link GitInvocation.redactedArgs}.
19245
20246
  */
19246
20247
  static fetch = fetch$1;
19247
20248
  /**
20249
+ * Mutating: `git fetch --unshallow <remote>` — converts a shallow clone
20250
+ * into a complete one by fetching the missing history.
20251
+ *
20252
+ * @remarks
20253
+ * `--unshallow` is a distinct MODE, not a depth value: git rejects it
20254
+ * outright in a repository that is not shallow, with
20255
+ * `--unshallow on a complete repository does not make sense`, so it
20256
+ * cannot be expressed as `fetch`'s `depth` option. The caller decides
20257
+ * whether to run it — probe with `Git.isShallow` first.
20258
+ *
20259
+ * `remote` may be a URL as well as a remote name; an embedded `userinfo@`
20260
+ * credential is masked in {@link GitInvocation.redactedArgs}.
20261
+ */
20262
+ static fetchUnshallow = fetchUnshallow;
20263
+ /**
20264
+ * `git rev-parse --is-shallow-repository` — prints `true` when the
20265
+ * repository is a shallow clone, `false` otherwise.
20266
+ *
20267
+ * @remarks
20268
+ * A dedicated probe constructor, deliberately separate from
20269
+ * {@link GitCommand.revParse}: `revParse` takes a REF and resolves it,
20270
+ * while this takes nothing and answers a repository-shape question.
20271
+ * Folding the flag into `revParse` would make that constructor
20272
+ * sometimes-takes-a-ref, sometimes-takes-a-flag.
20273
+ */
20274
+ static isShallow = isShallow;
20275
+ /**
20276
+ * Mutating: `git reset --soft|--mixed|--hard [<ref>]` — moves `HEAD` (and,
20277
+ * per mode, the index and working tree) to `ref`.
20278
+ *
20279
+ * @remarks
20280
+ * The mode flag is always explicit — `--mixed` is emitted for the default
20281
+ * rather than omitted — so the argv states what runs. `ref` may be any
20282
+ * commit-ish, including a gitlink sha.
20283
+ */
20284
+ static reset = reset;
20285
+ /**
20286
+ * Mutating: `git clean --force [-d] [-x] [-- <paths>...]` — deletes
20287
+ * untracked files from the working tree.
20288
+ *
20289
+ * @remarks
20290
+ * `--force` is unconditional: this constructor exists so a consumer can
20291
+ * restore a tree to a known state (e.g. before retrying a non-idempotent
20292
+ * operation), and without `--force` git refuses to clean at all under the
20293
+ * default `clean.requireForce` config — a clean that silently did nothing
20294
+ * would hand the retry the same dirty tree. `-d` removes untracked
20295
+ * directories too; `-x` removes ignored files as well. The literal `--`
20296
+ * separator makes the optional pathspec injection-safe by construction.
20297
+ */
20298
+ static clean = clean;
20299
+ /**
20300
+ * Mutating: `git restore [--source <ref>] [--staged] [--worktree] -- <paths...>`
20301
+ * — restores the given paths from the index (or from `source`), the
20302
+ * `checkout -- <paths>`-shaped operation.
20303
+ *
20304
+ * @remarks
20305
+ * This is a separate constructor precisely because {@link GitCommand.checkout}'s
20306
+ * service guard refuses `--` and option-like refs by design — `restore` is
20307
+ * git's own verb for pathspec restoration, and its paths always sit behind
20308
+ * a literal `--`, so they are injection-safe by construction. With neither
20309
+ * `staged` nor `worktree` set, git defaults to restoring the working tree.
20310
+ */
20311
+ static restore = restore;
20312
+ /**
20313
+ * Mutating: `git branch [-f] <name> [<start-point>]`, or
20314
+ * `git checkout (-b | -B) <name> [<start-point>]` when `checkout` is true —
20315
+ * creates a branch, optionally from an explicit start point, optionally
20316
+ * switching to it, optionally force-resetting an existing branch.
20317
+ *
20318
+ * @remarks
20319
+ * Branch creation is a branch-member concern, NOT a widening of
20320
+ * {@link GitCommand.checkout}: `checkout`'s contract stays "move to an
20321
+ * existing ref" and its option-like-ref refusal stays intact. The `-b` /
20322
+ * `-B` here is this constructor's own literal, never caller data.
20323
+ *
20324
+ * `force` with `checkout` exists because the delete-then-create longhand
20325
+ * (`branch -D` swallowed, then `checkout -b`) papers over a real edge:
20326
+ * `git branch -D` refuses to delete the currently checked-out branch,
20327
+ * while `checkout -B` resets it fine — one invocation handles both
20328
+ * states.
20329
+ */
20330
+ static branchCreate = branchCreate;
20331
+ /**
20332
+ * Mutating: `git branch -d <name>` (or `-D` when `force` is true) —
20333
+ * deletes a local branch.
20334
+ *
20335
+ * @remarks
20336
+ * The default `-d` refuses to delete a branch not fully merged — a typed
20337
+ * failure, which is usually the honest answer. `force: true` emits `-D`
20338
+ * and deletes regardless.
20339
+ */
20340
+ static branchDelete = branchDelete;
20341
+ /**
19248
20342
  * Mutating: `git submodule update [--init] [--depth <n>] [-- <paths>...]` — updates
19249
20343
  * registered submodules, optionally initializing them, with an optional depth limit,
19250
20344
  * and scoped to specific paths. The literal `--` separator makes the pathspec
@@ -19255,6 +20349,10 @@ var GitCommand = class {
19255
20349
  * Mutating: `git submodule add [--depth <n>] -- <url> <path>` — registers and
19256
20350
  * initializes a new submodule. The literal `--` separator makes the url and path
19257
20351
  * injection-safe by construction.
20352
+ *
20353
+ * @remarks
20354
+ * An embedded `userinfo@` credential in `url` is masked in
20355
+ * {@link GitInvocation.redactedArgs}.
19258
20356
  */
19259
20357
  static submoduleAdd = submoduleAdd;
19260
20358
  /**
@@ -19267,6 +20365,13 @@ var GitCommand = class {
19267
20365
  /**
19268
20366
  * Mutating: `git config [-f <file>] <key> <value>` — writes a configuration value,
19269
20367
  * optionally into an explicit configuration file (e.g., `.gitmodules`).
20368
+ *
20369
+ * @remarks
20370
+ * `value` may be a secret (a token, a credential-bearing URL), so it is
20371
+ * masked wholesale — as `<redacted>` — in
20372
+ * {@link GitInvocation.redactedArgs}. The key and file stay visible: they
20373
+ * are stable identifiers, and they are what a caller debugging a failed
20374
+ * write actually needs.
19270
20375
  */
19271
20376
  static configSet = configSet;
19272
20377
  /**
@@ -19349,9 +20454,304 @@ var GitCommand = class {
19349
20454
  * Each entry is a pair of status codes followed by a space and the path.
19350
20455
  */
19351
20456
  static status = status;
20457
+ /**
20458
+ * `git submodule status [--recursive] [-- <paths>...]` — one line per
20459
+ * registered submodule: a state prefix, the checked-out (or gitlink) sha,
20460
+ * the path, and — when the submodule is initialized — a `git describe`
20461
+ * suffix in parentheses.
20462
+ *
20463
+ * @remarks
20464
+ * `git submodule status` has no `-z` mode, so its output is line-based —
20465
+ * the one path-emitting constructor in this package that cannot follow
20466
+ * the `-z` rule. A submodule path containing a newline would corrupt the
20467
+ * parse; accepted as a git-imposed limitation.
20468
+ */
20469
+ static submoduleStatus = submoduleStatus;
20470
+ /**
20471
+ * Mutating: `git submodule init [-- <paths>...]` — registers the
20472
+ * submodules from `.gitmodules` into `.git/config` (all of them, or only
20473
+ * `paths`), without cloning or checking anything out.
20474
+ */
20475
+ static submoduleInit = submoduleInit;
20476
+ /**
20477
+ * Mutating: `git submodule deinit [--force] (--all | -- <paths>...)` —
20478
+ * unregisters submodules: clears their working trees and removes their
20479
+ * `.git/config` registration. The literal `--` separator makes the
20480
+ * pathspec injection-safe by construction.
20481
+ */
20482
+ static submoduleDeinit = submoduleDeinit;
20483
+ /**
20484
+ * Mutating: `git submodule sync [--recursive] [-- <paths>...]` —
20485
+ * re-copies each submodule's URL from `.gitmodules` into `.git/config`
20486
+ * (and into the submodule's own `remote.origin.url`), so a `.gitmodules`
20487
+ * URL change actually reaches git's live configuration.
20488
+ */
20489
+ static submoduleSync = submoduleSync;
20490
+ /**
20491
+ * Mutating: `git submodule set-url -- <path> <url>` — rewrites the
20492
+ * submodule's URL in `.gitmodules` and synchronizes it into
20493
+ * `.git/config`. The literal `--` separator makes the path and url
20494
+ * injection-safe by construction.
20495
+ *
20496
+ * @remarks
20497
+ * An embedded `userinfo@` credential in `url` is masked in
20498
+ * {@link GitInvocation.redactedArgs}.
20499
+ */
20500
+ static submoduleSetUrl = submoduleSetUrl;
20501
+ /**
20502
+ * Mutating: `git submodule set-branch (--branch <branch> | --default) -- <path>`
20503
+ * — records (or clears, when `branch` is omitted) the branch a submodule
20504
+ * tracks in `.gitmodules`. The literal `--` separator makes the path
20505
+ * injection-safe by construction.
20506
+ */
20507
+ static submoduleSetBranch = submoduleSetBranch;
20508
+ /**
20509
+ * Mutating: `git submodule absorbgitdirs [-- <paths>...]` — moves each
20510
+ * submodule's embedded `.git` directory into the superproject's
20511
+ * `.git/modules/` and leaves a gitfile pointer behind.
20512
+ */
20513
+ static submoduleAbsorbgitdirs = submoduleAbsorbgitdirs;
20514
+ /**
20515
+ * Mutating: `git submodule foreach [--recursive] <command>` — runs a shell
20516
+ * command in every checked-out submodule. `command` is a single shell
20517
+ * string, evaluated by git in each submodule's directory; it can mutate
20518
+ * anything, which is why the constructor is marked mutating regardless of
20519
+ * what the command does.
20520
+ *
20521
+ * @remarks
20522
+ * This is the ONE constructor whose argument cannot be made injection-safe
20523
+ * by construction: git evaluates `command` with `sh -c`, so every character
20524
+ * of it is shell code — a `--` separator or quoting cannot help. Callers
20525
+ * must treat `command` as a trusted literal and never interpolate untrusted
20526
+ * data into it.
20527
+ */
20528
+ static submoduleForeach = submoduleForeach;
20529
+ /**
20530
+ * `git ls-remote [--heads] [--tags] <remote> [<patterns>...]` — the refs a
20531
+ * remote advertises (sha + refname), optionally filtered to branch heads,
20532
+ * tags, and/or shell-glob patterns.
20533
+ *
20534
+ * @remarks
20535
+ * A read that talks to the NETWORK, not to the local repository — the one
20536
+ * non-mutating constructor in this package that does. An embedded
20537
+ * `userinfo@` credential in `remote` is masked in
20538
+ * {@link GitInvocation.redactedArgs}. An annotated tag advertises two
20539
+ * entries: `refs/tags/<name>` (the tag object) and `refs/tags/<name>^{}`
20540
+ * (the peeled commit).
20541
+ */
20542
+ static lsRemote = lsRemote;
20543
+ /**
20544
+ * Mutating: `git remote add <name> <url>` — registers a new remote.
20545
+ *
20546
+ * @remarks
20547
+ * An embedded `userinfo@` credential in `url` is masked in
20548
+ * {@link GitInvocation.redactedArgs}.
20549
+ */
20550
+ static remoteAdd = remoteAdd;
20551
+ /**
20552
+ * Mutating: `git remote remove <name>` — deletes a remote and its
20553
+ * remote-tracking refs and configuration.
20554
+ */
20555
+ static remoteRemove = remoteRemove;
20556
+ /**
20557
+ * Mutating: `git remote set-url <name> <url>` — rewrites a remote's fetch
20558
+ * URL.
20559
+ *
20560
+ * @remarks
20561
+ * An embedded `userinfo@` credential in `url` is masked in
20562
+ * {@link GitInvocation.redactedArgs}.
20563
+ */
20564
+ static remoteSetUrl = remoteSetUrl;
20565
+ /**
20566
+ * Mutating: `git stash push [--include-untracked] [-m <message>] [-- <paths>...]`
20567
+ * — saves the working tree (and index) state onto the stash stack. The
20568
+ * literal `--` separator makes the optional pathspec injection-safe by
20569
+ * construction; the message rides behind `-m`, which git consumes as a
20570
+ * value even when it begins with `-`.
20571
+ */
20572
+ static stashPush = stashPush;
20573
+ /**
20574
+ * Mutating: `git stash pop [stash@{n}]` — applies a stash entry and drops
20575
+ * it on success. The stash ref is rendered from an INTEGER index by this
20576
+ * package, never caller text.
20577
+ */
20578
+ static stashPop = stashPop;
20579
+ /**
20580
+ * Mutating: `git stash apply [stash@{n}]` — applies a stash entry and
20581
+ * keeps it on the stack. The stash ref is rendered from an INTEGER index
20582
+ * by this package, never caller text.
20583
+ */
20584
+ static stashApply = stashApply;
20585
+ /**
20586
+ * Mutating: `git stash drop [stash@{n}]` — deletes a stash entry without
20587
+ * applying it. The stash ref is rendered from an INTEGER index by this
20588
+ * package, never caller text.
20589
+ */
20590
+ static stashDrop = stashDrop;
20591
+ /**
20592
+ * `git stash list -z --format=%gd%x1f%H%x1f%gs` — every stash entry as a
20593
+ * NUL-terminated record of unit-separated fields: the reflog selector
20594
+ * (`stash@{0}`), the stash commit sha, and the reflog subject.
20595
+ *
20596
+ * @remarks
20597
+ * The `%x1f` (ASCII unit separator) field separator plus `-z` record
20598
+ * terminator keeps the parse split-safe: a stash message cannot contain
20599
+ * either byte (reflog subjects are single-line).
20600
+ */
20601
+ static stashList = stashList;
20602
+ /**
20603
+ * `git branch --list [--remotes | --all] --format=%(HEAD)%00%(refname:short)%00%(objectname)`
20604
+ * — every branch as a NUL-separated triple: the current-branch marker, the
20605
+ * short name, and the tip sha.
20606
+ *
20607
+ * @remarks
20608
+ * Records are newline-separated, which is split-safe here: git refnames
20609
+ * cannot contain a newline (or a space), so the only NUL bytes are the
20610
+ * format's own field separators. `all` wins over `remotes` when both are
20611
+ * set.
20612
+ */
20613
+ static branchList = branchList;
20614
+ /**
20615
+ * Mutating: `git tag [--force] [-m <message>] <name> [<ref>]` — creates a
20616
+ * lightweight tag, or an annotated one when `message` is given (`-m`
20617
+ * implies `-a`).
20618
+ */
20619
+ static tagCreate = tagCreate;
20620
+ /** Mutating: `git tag --delete <name>` — deletes a local tag. */
20621
+ static tagDelete = tagDelete;
20622
+ /**
20623
+ * `git tag --list [<pattern>]` — tag names, optionally filtered by a
20624
+ * shell-glob pattern, one per line (refnames cannot contain newlines).
20625
+ */
20626
+ static tagList = tagList;
20627
+ /**
20628
+ * `git for-each-ref --format=%(refname)%00%(objectname)%00%(objecttype) [<patterns>...]`
20629
+ * — every matching ref as a NUL-separated triple: full refname, sha, and
20630
+ * object type.
20631
+ *
20632
+ * @remarks
20633
+ * The format is this package's own fixed triple — the parse contract and
20634
+ * the argv are decided together, so the format string is a constructor
20635
+ * literal, never caller data. An annotated tag's `objecttype` is `tag`
20636
+ * (the tag object), not `commit`.
20637
+ */
20638
+ static forEachRef = forEachRef;
20639
+ /**
20640
+ * `git rev-list [--max-count=<n>] [--first-parent] <ref-or-range>` — commit
20641
+ * shas reachable from the ref (or range, e.g. `main..feat`), newest first.
20642
+ */
20643
+ static revList = revList;
20644
+ /**
20645
+ * Mutating: `git commit [--all] [--allow-empty] [--amend] [--author=<author>] -m <message>`
20646
+ * — records a commit. The message always rides argv behind `-m` (git
20647
+ * consumes it as a value even when it begins with `-`); committer identity
20648
+ * comes from the caller's environment — this constructor sets no
20649
+ * `GIT_AUTHOR_*`/`GIT_COMMITTER_*` variables, and the optional `author`
20650
+ * override is the fused `--author=` form.
20651
+ */
20652
+ static commit = commit;
20653
+ /**
20654
+ * Mutating: `git push [--force | --force-with-lease] [--tags] [--set-upstream] <remote> [<refspec>]`
20655
+ * — updates remote refs.
20656
+ *
20657
+ * @remarks
20658
+ * `remote` may be a URL as well as a remote name; an embedded `userinfo@`
20659
+ * credential is masked in {@link GitInvocation.redactedArgs}.
20660
+ */
20661
+ static push = push$1;
20662
+ /**
20663
+ * Mutating: `git pull [--rebase] [--ff-only] <remote> [<ref>]` — fetches
20664
+ * and integrates.
20665
+ *
20666
+ * @remarks
20667
+ * `remote` may be a URL as well as a remote name; an embedded `userinfo@`
20668
+ * credential is masked in {@link GitInvocation.redactedArgs}.
20669
+ */
20670
+ static pull = pull;
20671
+ /**
20672
+ * `git config [-f <file>] --list -z` — every configuration entry in scope
20673
+ * (or in the given file only), NUL-terminated, the key separated from the
20674
+ * value by a newline within each record.
20675
+ *
20676
+ * @remarks
20677
+ * `-z` is load-bearing: a config VALUE may contain newlines; only the NUL
20678
+ * record terminator plus first-newline field split parses it losslessly.
20679
+ * A valueless key (git's boolean-true shorthand) emits no newline at all.
20680
+ */
20681
+ static configList = configList;
20682
+ /**
20683
+ * `git config [-f <file>] --get-all -z <key>` — every value of a
20684
+ * (possibly multi-valued) key, NUL-terminated. An unset key exits 1 with
20685
+ * silent stderr.
20686
+ */
20687
+ static configGetAll = configGetAll;
20688
+ /**
20689
+ * Mutating: `git config [-f <file>] (--unset | --unset-all) <key>` —
20690
+ * removes a key (or, with `all`, every value of a multi-valued key).
20691
+ *
20692
+ * @remarks
20693
+ * git exits 5, silently, when the key was not set — a loud failure by
20694
+ * this package's classification, deliberately: an unset that silently did
20695
+ * nothing is indistinguishable from one that worked.
20696
+ */
20697
+ static configUnset = configUnset;
20698
+ /**
20699
+ * Mutating: `git rm [--cached] [-r] [--force] -- <paths...>` — removes
20700
+ * paths from the index (and, without `cached`, the working tree). The
20701
+ * literal `--` separator makes the pathspec injection-safe by
20702
+ * construction.
20703
+ */
20704
+ static rm = rm;
20705
+ /**
20706
+ * Mutating: `git mv [--force] -- <source> <destination>` — moves or
20707
+ * renames a tracked path. The literal `--` separator makes both positionals
20708
+ * injection-safe by construction.
20709
+ */
20710
+ static mv = mv;
20711
+ /**
20712
+ * `git check-ignore -z --stdin` — which of the given paths git would
20713
+ * ignore, paths fed NUL-separated via stdin and answers returned
20714
+ * NUL-separated.
20715
+ *
20716
+ * @remarks
20717
+ * The `--stdin -z` form is the only fully robust one: `-z` without
20718
+ * `--stdin` is rejected by git outright, and the non-`-z` output C-quotes
20719
+ * special-character paths. Feeding paths via stdin also makes them
20720
+ * injection-safe by construction — nothing caller-controlled enters the
20721
+ * argv. When NO path is ignored, git exits 1 with silent stderr.
20722
+ */
20723
+ static checkIgnore = checkIgnore;
20724
+ /**
20725
+ * Mutating: `git worktree add [--force] [--detach] <path> [<ref>]` —
20726
+ * creates a linked working tree at `path`, checked out at `ref` (or the
20727
+ * branch named after `path`'s basename).
20728
+ */
20729
+ static worktreeAdd = worktreeAdd;
20730
+ /**
20731
+ * `git worktree list --porcelain -z` — every working tree as a block of
20732
+ * NUL-terminated attributes (`worktree <path>`, `HEAD <sha>`,
20733
+ * `branch <ref>` / `detached`, `bare`, `locked [<reason>]`,
20734
+ * `prunable [<reason>]`), blocks separated by an empty attribute.
20735
+ */
20736
+ static worktreeList = worktreeList;
20737
+ /** Mutating: `git worktree remove [--force] <path>` — removes a linked working tree. */
20738
+ static worktreeRemove = worktreeRemove;
20739
+ /**
20740
+ * `git ls-files --stage -z [-- <pathspec>...]` — every INDEX entry (mode,
20741
+ * oid, stage number, path), NUL-terminated, optionally scoped to
20742
+ * `pathspec`.
20743
+ *
20744
+ * @remarks
20745
+ * The index-side sibling of {@link GitCommand.lsTree}: `lsTree` reads a
20746
+ * COMMITTED tree at a ref, while this reads the staging area — the only
20747
+ * place a staged-but-uncommitted gitlink (`160000 <oid> 0 <path>`) is
20748
+ * visible. `-z` is load-bearing twice over: paths may contain newlines,
20749
+ * and the non-`-z` output C-quotes special-character paths.
20750
+ */
20751
+ static lsFiles = lsFiles;
19352
20752
  };
19353
20753
  //#endregion
19354
- //#region ../../node_modules/.pnpm/@effected+git@0.5.2_effect@4.0.0-beta.101/node_modules/@effected/git/internal/run.js
20754
+ //#region ../../node_modules/.pnpm/@effected+git@0.6.0_effect@4.0.0-beta.101/node_modules/@effected/git/internal/run.js
19355
20755
  /**
19356
20756
  * Spawns `command` and collects its stdout, stderr, and exit code as a single
19357
20757
  * triple.
@@ -19378,7 +20778,7 @@ const runCollected = (command) => effect.Effect.scoped(effect.Effect.gen(functio
19378
20778
  };
19379
20779
  }));
19380
20780
  //#endregion
19381
- //#region ../../node_modules/.pnpm/@effected+git@0.5.2_effect@4.0.0-beta.101/node_modules/@effected/git/Git.js
20781
+ //#region ../../node_modules/.pnpm/@effected+git@0.6.0_effect@4.0.0-beta.101/node_modules/@effected/git/Git.js
19382
20782
  /** git's own ceiling: a run that has not answered in 30s is not going to. */
19383
20783
  const GIT_TIMEOUT = effect.Duration.seconds(30);
19384
20784
  /**
@@ -19406,7 +20806,16 @@ var GitCommandError = class extends effect.Schema.TaggedErrorClass()("GitCommand
19406
20806
  * logic routes on this instead of matching `detail` prose.
19407
20807
  */
19408
20808
  kind: effect.Schema.Literals(["refused", "failed"]),
19409
- /** The argument vector, without the leading `git`. */
20809
+ /**
20810
+ * The REDACTED argument vector, without the leading `git`.
20811
+ *
20812
+ * Sensitive positionals — config values, a URL's embedded userinfo — are
20813
+ * already masked by the constructor's redaction mask before this error is
20814
+ * constructed (`configSet`'s value reads `<redacted>`; a
20815
+ * `https://user:token@host/...` remote keeps everything but its
20816
+ * `userinfo@`). The raw argv is never persisted in an error value, and
20817
+ * `message` renders this redacted vector.
20818
+ */
19410
20819
  args: effect.Schema.Array(effect.Schema.String),
19411
20820
  /** The working directory the command ran in. */
19412
20821
  cwd: effect.Schema.String,
@@ -19452,9 +20861,74 @@ var UnknownRefError = class extends effect.Schema.TaggedErrorClass()("UnknownRef
19452
20861
  }
19453
20862
  };
19454
20863
  /**
19455
- * One entry of a `git ls-tree` listing.
20864
+ * A `git push` was rejected because the remote ref has moved: the classic
20865
+ * non-fast-forward rejection (`fetch first` / `non-fast-forward`), or a
20866
+ * `--force-with-lease` lease failure (`stale info`).
19456
20867
  *
19457
- * @public
20868
+ * @remarks
20869
+ * The typed signal a fetch-then-retry (or rebase-then-retry) fallback
20870
+ * branches on — every other push failure stays a {@link GitCommandError}.
20871
+ * Only `Git.push` can fail with this error.
20872
+ *
20873
+ * @public
20874
+ */
20875
+ var NonFastForwardError = class extends effect.Schema.TaggedErrorClass()("NonFastForwardError", {
20876
+ /** The working directory the push ran in. */
20877
+ cwd: effect.Schema.String,
20878
+ /** The refspec that was rejected, when the caller passed one. */
20879
+ refspec: effect.Schema.optionalKey(effect.Schema.String)
20880
+ }) {
20881
+ /** Renders the rejected push into a one-line message. */
20882
+ get message() {
20883
+ 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}`;
20884
+ }
20885
+ };
20886
+ /**
20887
+ * A merge-shaped operation (`pull`, `stash pop`, `stash apply`) stopped with
20888
+ * conflict markers in the working tree.
20889
+ *
20890
+ * @remarks
20891
+ * The typed signal a resolve-or-abort recovery branches on. The conflicted
20892
+ * state is REAL: git has already written conflict markers, and (for `pull`)
20893
+ * `MERGE_HEAD` is set — the caller owns resolving or aborting. Detection
20894
+ * matches git's conflict report, which lands on STDOUT for a merge and on
20895
+ * stderr for a rebase-mode pull; both streams are inspected.
20896
+ *
20897
+ * @public
20898
+ */
20899
+ var MergeConflictError = class extends effect.Schema.TaggedErrorClass()("MergeConflictError", {
20900
+ /** The working directory the merge ran in. */
20901
+ cwd: effect.Schema.String }) {
20902
+ /** Renders the conflicted merge into a one-line message. */
20903
+ get message() {
20904
+ return `merge conflict in ${this.cwd}: fix conflicts (or abort) before continuing`;
20905
+ }
20906
+ };
20907
+ /**
20908
+ * A merge-shaped operation refused to start because local modifications would
20909
+ * be overwritten — git's refusal reads
20910
+ * `Your local changes ... would be overwritten by merge`.
20911
+ *
20912
+ * @remarks
20913
+ * The typed "commit or stash first" signal. Unlike {@link MergeConflictError}
20914
+ * the working tree is UNTOUCHED — git aborted before changing anything.
20915
+ * Only the merge-shaped methods (`pull`, `stashPop`, `stashApply`) can fail
20916
+ * with this error.
20917
+ *
20918
+ * @public
20919
+ */
20920
+ var DirtyWorktreeError = class extends effect.Schema.TaggedErrorClass()("DirtyWorktreeError", {
20921
+ /** The working directory whose local changes blocked the operation. */
20922
+ cwd: effect.Schema.String }) {
20923
+ /** Renders the blocked operation into a one-line message. */
20924
+ get message() {
20925
+ return `local changes would be overwritten in ${this.cwd}: commit or stash them first`;
20926
+ }
20927
+ };
20928
+ /**
20929
+ * One entry of a `git ls-tree` listing.
20930
+ *
20931
+ * @public
19458
20932
  */
19459
20933
  var LsTreeEntry = class extends effect.Schema.Class("LsTreeEntry")({
19460
20934
  /** The entry's file mode, e.g. `100644`. */
@@ -19512,11 +20986,26 @@ const UNKNOWN_REF_PATTERNS = [
19512
20986
  "couldn't find remote ref"
19513
20987
  ];
19514
20988
  const ABSENT_AT_REF_PATTERNS = ["does not exist in", "exists on disk, but not in"];
20989
+ const PUSH_REJECTED_PATTERNS = [
20990
+ "non-fast-forward",
20991
+ "fetch first",
20992
+ "stale info"
20993
+ ];
20994
+ const MERGE_CONFLICT_PATTERNS = [
20995
+ "CONFLICT (",
20996
+ "Automatic merge failed",
20997
+ "could not apply"
20998
+ ];
20999
+ const DIRTY_WORKTREE_PATTERN = "would be overwritten by";
19515
21000
  const matchesAny = (stderr, patterns) => patterns.some((pattern) => stderr.includes(pattern));
19516
21001
  /**
19517
21002
  * Classifies one completed run (or spawn-level `PlatformError`) against
19518
21003
  * git's stderr taxonomy. Written once — every `Git` method funnels through
19519
21004
  * this before deciding its own return value.
21005
+ *
21006
+ * `args` is the invocation's REDACTED argv: it is the only argv this
21007
+ * function may persist into a `GitCommandError`, per the #86 redaction
21008
+ * policy.
19520
21009
  */
19521
21010
  const classify = (cwd, args, outcome, kind) => {
19522
21011
  if (outcome instanceof effect.PlatformError.PlatformError) {
@@ -19539,6 +21028,11 @@ const classify = (cwd, args, outcome, kind) => {
19539
21028
  };
19540
21029
  if (stderr.includes(NOT_A_REPOSITORY)) return { _tag: "notARepository" };
19541
21030
  if (matchesAny(stderr, UNKNOWN_REF_PATTERNS)) return { _tag: "unknownRef" };
21031
+ if (kind === "push" && stderr.includes("[rejected]") && matchesAny(stderr, PUSH_REJECTED_PATTERNS)) return { _tag: "nonFastForward" };
21032
+ if (kind === "merge") {
21033
+ if (stderr.includes(DIRTY_WORKTREE_PATTERN)) return { _tag: "dirtyWorktree" };
21034
+ if (matchesAny(stdout, MERGE_CONFLICT_PATTERNS) || matchesAny(stderr, MERGE_CONFLICT_PATTERNS)) return { _tag: "mergeConflict" };
21035
+ }
19542
21036
  if (kind === "quiet" && exitCode === 1 && stderr === "") return { _tag: "absent" };
19543
21037
  if (kind === "noSuchRemote" && stderr.includes("No such remote")) return { _tag: "absent" };
19544
21038
  if (kind === "show" && matchesAny(stderr, ABSENT_AT_REF_PATTERNS)) return { _tag: "absent" };
@@ -19555,13 +21049,19 @@ const classify = (cwd, args, outcome, kind) => {
19555
21049
  };
19556
21050
  };
19557
21051
  /**
19558
- * Runs `command`, classifies the outcome, and never fails: a spawn-level
19559
- * `PlatformError` and a per-run timeout are both absorbed into the
19560
- * `"failure"` classification rather than escaping the effect's error
19561
- * channel.
21052
+ * Runs an invocation's command in `cwd`, classifies the outcome, and never
21053
+ * fails: a spawn-level `PlatformError` and a per-run timeout are both
21054
+ * absorbed into the `"failure"` classification rather than escaping the
21055
+ * effect's error channel.
21056
+ *
21057
+ * The argv handed to `classify` — and therefore persisted into any
21058
+ * `GitCommandError` — is the invocation's REDACTED argv, never the raw one:
21059
+ * the redaction mask the pure constructor carries is applied here, at the
21060
+ * single classification choke point (the #86 redaction policy).
19562
21061
  */
19563
- const runClassified = (command, cwd, kind) => {
19564
- const args = effect_unstable_process.ChildProcess.isStandardCommand(command) ? command.args : [];
21062
+ const runClassified = (invocation, cwd, kind) => {
21063
+ const args = invocation.redactedArgs;
21064
+ const command = effect_unstable_process.ChildProcess.setCwd(invocation.command, cwd);
19565
21065
  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({
19566
21066
  duration: GIT_TIMEOUT,
19567
21067
  orElse: () => effect.Effect.succeed({
@@ -19691,7 +21191,43 @@ var StatusEntry = class extends effect.Schema.Class("StatusEntry")({
19691
21191
  path: effect.Schema.String,
19692
21192
  /** The original path; present only on rename/copy entries. */
19693
21193
  origPath: effect.Schema.optionalKey(effect.Schema.String)
19694
- }) {};
21194
+ }) {
21195
+ /**
21196
+ * Renders this entry back to one porcelain-shaped line: `XY <path>`.
21197
+ *
21198
+ * @remarks
21199
+ * **The rename convention is decided here, once, for every consumer.** By
21200
+ * default a rename/copy entry renders its NEW path only — `path` IS the
21201
+ * entry's current path, the one a line-oriented downstream can actually
21202
+ * open — which is a deliberate divergence from git's own non-`-z`
21203
+ * rendering (`orig -> new`). The arrow form is ambiguous to naive
21204
+ * line/whitespace splitters (paths may contain spaces, or a literal
21205
+ * `" -> "`), so it is opt-in via `renames: "arrow"` for consumers that
21206
+ * want git parity.
21207
+ *
21208
+ * A second recorded divergence: git's non-`-z` porcelain C-quotes paths
21209
+ * containing special characters; this renderer emits paths raw. It exists
21210
+ * for whitespace-insensitive text consumers — a machine parser should
21211
+ * consume the decoded {@link StatusEntry} values (or `-z` output)
21212
+ * directly, never re-parse this rendering.
21213
+ */
21214
+ toLine(options) {
21215
+ const rendered = options?.renames === "arrow" && this.origPath !== void 0 ? `${this.origPath} -> ${this.path}` : this.path;
21216
+ return `${this.x}${this.y} ${rendered}`;
21217
+ }
21218
+ /**
21219
+ * Renders entries back to porcelain-shaped text: one {@link StatusEntry.toLine}
21220
+ * line per entry, newline-joined, no trailing newline.
21221
+ *
21222
+ * @remarks
21223
+ * The route back from `Git.status`'s parsed entries to line-oriented text,
21224
+ * so a consumer whose downstream contract is porcelain-shaped text does
21225
+ * not hand-roll its own renderer (and re-decide the rename convention —
21226
+ * see {@link StatusEntry.toLine} for that decision). An empty array
21227
+ * renders as the empty string.
21228
+ */
21229
+ static format = (entries, options) => entries.map((entry) => entry.toLine(options)).join("\n");
21230
+ };
19695
21231
  /**
19696
21232
  * Parses `git log -1 --format=%H%x00%G?%x00%B` output: exactly two NUL
19697
21233
  * separators, everything after the second is the raw message, untrimmed.
@@ -19745,6 +21281,360 @@ const parseStatus = (output) => {
19745
21281
  return entries;
19746
21282
  };
19747
21283
  /**
21284
+ * One line of a `git submodule status` listing.
21285
+ *
21286
+ * @remarks
21287
+ * The `state` decodes git's one-character prefix: `" "` → `"current"` (the
21288
+ * checked-out commit matches the index gitlink), `"-"` → `"uninitialized"`,
21289
+ * `"+"` → `"outOfSync"` (the checked-out commit differs from the gitlink),
21290
+ * `"U"` → `"conflict"` (merge conflicts). `describe` carries the
21291
+ * parenthesized `git describe` suffix git appends for initialized
21292
+ * submodules.
21293
+ *
21294
+ * @public
21295
+ */
21296
+ var SubmoduleStatusEntry = class extends effect.Schema.Class("SubmoduleStatusEntry")({
21297
+ /** The decoded state prefix. */
21298
+ state: effect.Schema.Literals([
21299
+ "current",
21300
+ "uninitialized",
21301
+ "outOfSync",
21302
+ "conflict"
21303
+ ]),
21304
+ /** The submodule's checked-out (or, uninitialized, gitlink) commit sha. */
21305
+ sha: effect.Schema.String,
21306
+ /** The submodule's path relative to the superproject root. */
21307
+ path: effect.Schema.String,
21308
+ /** The `git describe` suffix, present only for initialized submodules. */
21309
+ describe: effect.Schema.optionalKey(effect.Schema.String)
21310
+ }) {};
21311
+ /**
21312
+ * Parses `git submodule status` output. Line-based — the one parser in this
21313
+ * package without a `-z` mode to lean on, because git does not offer one for
21314
+ * `submodule status`; a submodule path containing a newline (or a literal
21315
+ * ` (` suffix mimicking the describe parenthesis) would corrupt the parse.
21316
+ * Accepted as a git-imposed limitation.
21317
+ */
21318
+ const parseSubmoduleStatus = (output) => {
21319
+ const entries = [];
21320
+ for (const line of output.split("\n")) {
21321
+ const trimmedEnd = line.endsWith("\r") ? line.slice(0, -1) : line;
21322
+ if (trimmedEnd === "") continue;
21323
+ const prefix = trimmedEnd.charAt(0);
21324
+ const state = prefix === "-" ? "uninitialized" : prefix === "+" ? "outOfSync" : prefix === "U" ? "conflict" : "current";
21325
+ const rest = prefix === " " || prefix === "-" || prefix === "+" || prefix === "U" ? trimmedEnd.slice(1) : trimmedEnd;
21326
+ const shaEnd = rest.indexOf(" ");
21327
+ const sha = shaEnd === -1 ? rest : rest.slice(0, shaEnd);
21328
+ const remainder = shaEnd === -1 ? "" : rest.slice(shaEnd + 1);
21329
+ const describeStart = remainder.endsWith(")") ? remainder.lastIndexOf(" (") : -1;
21330
+ if (describeStart === -1) entries.push(SubmoduleStatusEntry.make({
21331
+ state,
21332
+ sha,
21333
+ path: remainder
21334
+ }));
21335
+ else entries.push(SubmoduleStatusEntry.make({
21336
+ state,
21337
+ sha,
21338
+ path: remainder.slice(0, describeStart),
21339
+ describe: remainder.slice(describeStart + 2, -1)
21340
+ }));
21341
+ }
21342
+ return entries;
21343
+ };
21344
+ /**
21345
+ * One ref a remote advertises, from `git ls-remote`.
21346
+ *
21347
+ * @remarks
21348
+ * `ref` is the FULL refname as advertised (`refs/heads/main`,
21349
+ * `refs/tags/v1`), including the `^{}` suffix on an annotated tag's peeled
21350
+ * entry — an annotated tag appears twice, once as the tag object and once
21351
+ * peeled to its commit.
21352
+ *
21353
+ * @public
21354
+ */
21355
+ var LsRemoteEntry = class LsRemoteEntry extends effect.Schema.Class("LsRemoteEntry")({
21356
+ /** The sha the advertised ref points at. */
21357
+ sha: effect.Schema.String,
21358
+ /** The full advertised refname, `^{}` peel suffix included. */
21359
+ ref: effect.Schema.String
21360
+ }) {
21361
+ /**
21362
+ * The human-facing short name of an advertised refname: the
21363
+ * `refs/heads/` / `refs/tags/` / `refs/remotes/` prefix and any `^{}`
21364
+ * peel suffix stripped (`refs/tags/v1^{}` → `v1`).
21365
+ */
21366
+ static shortName = (ref) => {
21367
+ const base = ref.endsWith("^{}") ? ref.slice(0, -3) : ref;
21368
+ for (const prefix of [
21369
+ "refs/heads/",
21370
+ "refs/tags/",
21371
+ "refs/remotes/"
21372
+ ]) if (base.startsWith(prefix)) return base.slice(prefix.length);
21373
+ return base;
21374
+ };
21375
+ /**
21376
+ * The entries whose short name is a NEAR MISS for `ref`: not an exact
21377
+ * match, but ending in `ref` right behind a separator (`@`, `/`, `-`,
21378
+ * `_`) — the monorepo-prefixed-tag case, where a caller asks for
21379
+ * `4.0.0-beta.101` and the remote advertises `effect@4.0.0-beta.101`.
21380
+ *
21381
+ * @remarks
21382
+ * A pure, decode-side helper for validate-before-mutate flows: run
21383
+ * `lsRemote`, look for the wanted ref, and when it is absent hand the
21384
+ * listing to this to compute a suggestion. Deliberately a helper on the
21385
+ * ENTRY value rather than behavior baked into the service — the service
21386
+ * returns the full listing and the caller owns the matching policy. An
21387
+ * annotated tag's peeled `^{}` entry shares its base short name, so a
21388
+ * near miss on such a tag can surface both of its entries.
21389
+ */
21390
+ static nearMatches = (entries, ref) => {
21391
+ const separators = [
21392
+ "@",
21393
+ "/",
21394
+ "-",
21395
+ "_"
21396
+ ];
21397
+ return entries.filter((entry) => {
21398
+ const short = LsRemoteEntry.shortName(entry.ref);
21399
+ if (short === ref || !short.endsWith(ref)) return false;
21400
+ return separators.includes(short.charAt(short.length - ref.length - 1));
21401
+ });
21402
+ };
21403
+ };
21404
+ /**
21405
+ * Parses `git ls-remote` output: one `<sha>\t<refname>` line per advertised
21406
+ * ref. Line-based deliberately — refnames cannot contain a newline (or a
21407
+ * tab), so the split is safe without a `-z` mode (which `ls-remote` does not
21408
+ * offer).
21409
+ */
21410
+ const parseLsRemote = (output) => output.split("\n").filter((line) => line.length > 0).map((line) => {
21411
+ const tabIndex = line.indexOf(" ");
21412
+ return LsRemoteEntry.make({
21413
+ sha: line.slice(0, tabIndex),
21414
+ ref: line.slice(tabIndex + 1)
21415
+ });
21416
+ });
21417
+ /**
21418
+ * One stash entry, from `git stash list`.
21419
+ *
21420
+ * @public
21421
+ */
21422
+ var StashEntry = class extends effect.Schema.Class("StashEntry")({
21423
+ /** The reflog selector (`stash@{0}`) — the index other stash methods take. */
21424
+ ref: effect.Schema.String,
21425
+ /** The stash commit's sha. */
21426
+ sha: effect.Schema.String,
21427
+ /** The reflog subject: `WIP on <branch>: ...` or `On <branch>: <message>`. */
21428
+ message: effect.Schema.String
21429
+ }) {};
21430
+ /**
21431
+ * Parses `git stash list -z --format=%gd%x1f%H%x1f%gs` output: NUL-terminated
21432
+ * records of unit-separated (`\x1f`) fields. Reflog subjects are single-line
21433
+ * and cannot contain either separator byte.
21434
+ */
21435
+ const parseStashList = (output) => parseNulSeparated(output).map((record) => {
21436
+ const [ref = "", sha = "", ...rest] = record.split("");
21437
+ return StashEntry.make({
21438
+ ref,
21439
+ sha,
21440
+ message: rest.join("")
21441
+ });
21442
+ });
21443
+ /**
21444
+ * One local (or remote-tracking) branch, from `git branch --list`.
21445
+ *
21446
+ * @public
21447
+ */
21448
+ var BranchEntry = class extends effect.Schema.Class("BranchEntry")({
21449
+ /** The short branch name (`main`, or `origin/main` for a remote branch). */
21450
+ name: effect.Schema.String,
21451
+ /** The branch tip's sha. */
21452
+ sha: effect.Schema.String,
21453
+ /** Whether this branch is checked out in the current working tree. */
21454
+ current: effect.Schema.Boolean
21455
+ }) {};
21456
+ /**
21457
+ * Parses `git branch --list --format=%(HEAD)%00%(refname:short)%00%(objectname)`
21458
+ * output: newline-separated records (refnames cannot contain newlines) of
21459
+ * NUL-separated fields. The `%(HEAD)` marker is `*` for the checked-out
21460
+ * branch; anything else (` `, or `+` for a branch checked out in a linked
21461
+ * worktree) is not-current.
21462
+ */
21463
+ const parseBranchList = (output) => output.split("\n").filter((line) => line.length > 0).map((line) => {
21464
+ const [marker = "", name = "", sha = ""] = line.split("\0");
21465
+ return BranchEntry.make({
21466
+ name,
21467
+ sha,
21468
+ current: marker === "*"
21469
+ });
21470
+ });
21471
+ /**
21472
+ * One ref, from `git for-each-ref`.
21473
+ *
21474
+ * @public
21475
+ */
21476
+ var RefEntry = class extends effect.Schema.Class("RefEntry")({
21477
+ /** The full refname (`refs/tags/v1`). */
21478
+ ref: effect.Schema.String,
21479
+ /** The sha of the object the ref points at. */
21480
+ sha: effect.Schema.String,
21481
+ /**
21482
+ * The pointed-at object's type. An annotated tag is `tag` (the tag
21483
+ * object itself, not its target commit).
21484
+ */
21485
+ objectType: effect.Schema.Literals([
21486
+ "commit",
21487
+ "tag",
21488
+ "tree",
21489
+ "blob"
21490
+ ])
21491
+ }) {};
21492
+ /**
21493
+ * Parses `git for-each-ref --format=%(refname)%00%(objectname)%00%(objecttype)`
21494
+ * output: newline-separated records (refnames cannot contain newlines) of
21495
+ * NUL-separated fields.
21496
+ */
21497
+ const parseForEachRef = (output) => output.split("\n").filter((line) => line.length > 0).map((line) => {
21498
+ const [ref = "", sha = "", objectType = "commit"] = line.split("\0");
21499
+ return RefEntry.make({
21500
+ ref,
21501
+ sha,
21502
+ objectType
21503
+ });
21504
+ });
21505
+ /**
21506
+ * One configuration entry, from `git config --list`.
21507
+ *
21508
+ * @public
21509
+ */
21510
+ var ConfigListEntry = class extends effect.Schema.Class("ConfigListEntry")({
21511
+ /** The canonical dotted key (`section.subsection.key`). */
21512
+ key: effect.Schema.String,
21513
+ /**
21514
+ * The raw value. A valueless key (git's boolean-true shorthand,
21515
+ * `[section]` + bare `key`) surfaces as the empty string — distinguish it
21516
+ * with `configGetAll` if the difference matters.
21517
+ */
21518
+ value: effect.Schema.String
21519
+ }) {};
21520
+ /**
21521
+ * Parses `git config --list -z` output: NUL-terminated records, key separated
21522
+ * from value by the FIRST newline (a config value may itself contain
21523
+ * newlines — the reason `-z` is load-bearing). A record with no newline is a
21524
+ * valueless boolean-shorthand key.
21525
+ */
21526
+ const parseConfigList = (output) => parseNulSeparated(output).map((record) => {
21527
+ const newlineIndex = record.indexOf("\n");
21528
+ return newlineIndex === -1 ? ConfigListEntry.make({
21529
+ key: record,
21530
+ value: ""
21531
+ }) : ConfigListEntry.make({
21532
+ key: record.slice(0, newlineIndex),
21533
+ value: record.slice(newlineIndex + 1)
21534
+ });
21535
+ });
21536
+ /**
21537
+ * One working tree, from `git worktree list --porcelain`.
21538
+ *
21539
+ * @public
21540
+ */
21541
+ var WorktreeEntry = class extends effect.Schema.Class("WorktreeEntry")({
21542
+ /** The working tree's absolute path. */
21543
+ path: effect.Schema.String,
21544
+ /** The checked-out commit sha; absent for a bare repository entry. */
21545
+ head: effect.Schema.optionalKey(effect.Schema.String),
21546
+ /** The checked-out branch's full refname; absent when detached or bare. */
21547
+ branch: effect.Schema.optionalKey(effect.Schema.String),
21548
+ /** Whether the working tree is in detached-HEAD state. */
21549
+ detached: effect.Schema.Boolean,
21550
+ /** Whether the entry is the bare repository itself. */
21551
+ bare: effect.Schema.Boolean,
21552
+ /** Present when the worktree is locked; holds the lock reason (possibly empty). */
21553
+ locked: effect.Schema.optionalKey(effect.Schema.String),
21554
+ /** Present when the worktree is prunable; holds the reason (possibly empty). */
21555
+ prunable: effect.Schema.optionalKey(effect.Schema.String)
21556
+ }) {};
21557
+ /**
21558
+ * Parses `git worktree list --porcelain -z` output: NUL-terminated attribute
21559
+ * lines, one blank attribute terminating each entry. Attribute vocabulary:
21560
+ * `worktree <path>`, `HEAD <sha>`, `branch <ref>`, and the flag/annotation
21561
+ * attributes `detached`, `bare`, `locked [<reason>]`, `prunable [<reason>]`.
21562
+ */
21563
+ const parseWorktreeList = (output) => {
21564
+ const entries = [];
21565
+ let path;
21566
+ let head;
21567
+ let branch;
21568
+ let detached = false;
21569
+ let bare = false;
21570
+ let locked;
21571
+ let prunable;
21572
+ const flush = () => {
21573
+ if (path !== void 0) entries.push(WorktreeEntry.make({
21574
+ path,
21575
+ detached,
21576
+ bare,
21577
+ ...head !== void 0 ? { head } : {},
21578
+ ...branch !== void 0 ? { branch } : {},
21579
+ ...locked !== void 0 ? { locked } : {},
21580
+ ...prunable !== void 0 ? { prunable } : {}
21581
+ }));
21582
+ path = void 0;
21583
+ head = void 0;
21584
+ branch = void 0;
21585
+ detached = false;
21586
+ bare = false;
21587
+ locked = void 0;
21588
+ prunable = void 0;
21589
+ };
21590
+ for (const attribute of output.split("\0")) if (attribute === "") flush();
21591
+ else if (attribute.startsWith("worktree ")) path = attribute.slice(9);
21592
+ else if (attribute.startsWith("HEAD ")) head = attribute.slice(5);
21593
+ else if (attribute.startsWith("branch ")) branch = attribute.slice(7);
21594
+ else if (attribute === "detached") detached = true;
21595
+ else if (attribute === "bare") bare = true;
21596
+ else if (attribute === "locked" || attribute.startsWith("locked ")) locked = attribute === "locked" ? "" : attribute.slice(7);
21597
+ else if (attribute === "prunable" || attribute.startsWith("prunable ")) prunable = attribute === "prunable" ? "" : attribute.slice(9);
21598
+ flush();
21599
+ return entries;
21600
+ };
21601
+ /**
21602
+ * One index (staging area) entry, from `git ls-files --stage`.
21603
+ *
21604
+ * @remarks
21605
+ * The index-side sibling of {@link LsTreeEntry}: this is the ONLY place a
21606
+ * staged-but-uncommitted gitlink (`mode` `160000`) is visible — `lsTree`
21607
+ * reads the committed tree and misses exactly that window.
21608
+ *
21609
+ * @public
21610
+ */
21611
+ var LsFilesEntry = class extends effect.Schema.Class("LsFilesEntry")({
21612
+ /** The entry's file mode, e.g. `100644` — `160000` for a gitlink. */
21613
+ mode: effect.Schema.String,
21614
+ /** The staged object id. */
21615
+ oid: effect.Schema.String,
21616
+ /** The merge stage: `0` normally; `1`/`2`/`3` during an unresolved merge. */
21617
+ stage: effect.Schema.Number,
21618
+ /** The entry's path, relative to `cwd`. May contain spaces or newlines. */
21619
+ path: effect.Schema.String
21620
+ }) {};
21621
+ /**
21622
+ * Parses `git ls-files --stage -z` output: each NUL-terminated entry is
21623
+ * `<mode> <oid> <stage>\t<path>`. `path` is everything after the first tab,
21624
+ * so a path containing spaces or newlines is preserved intact — the same
21625
+ * split rule as `parseLsTree`.
21626
+ */
21627
+ const parseLsFiles = (output) => parseNulSeparated(output).map((entry) => {
21628
+ const tabIndex = entry.indexOf(" ");
21629
+ const header = entry.slice(0, tabIndex).split(" ");
21630
+ return LsFilesEntry.make({
21631
+ mode: header[0] ?? "",
21632
+ oid: header[1] ?? "",
21633
+ stage: Number(header[2] ?? "0"),
21634
+ path: entry.slice(tabIndex + 1)
21635
+ });
21636
+ });
21637
+ /**
19748
21638
  * Refuse a caller-supplied ref or range that git would parse as an option.
19749
21639
  *
19750
21640
  * Refs are caller-controlled and land in git's argv as positional entries; a
@@ -19754,20 +21644,49 @@ const parseStatus = (output) => {
19754
21644
  * refused outright, before any spawn, as a typed {@link GitCommandError}.
19755
21645
  * `show`'s `path` needs no guard: it is fused after the ref into one
19756
21646
  * `ref:path` token, which cannot begin with `-` unless the ref does.
21647
+ *
21648
+ * `sensitive` values get the same check but a REDACTED report: a refused
21649
+ * sensitive positional (a `configSet` value) must not leak into
21650
+ * `GitCommandError.args`/`detail` any more than a spawned one may — the #86
21651
+ * redaction policy applies to guard rejections too.
19757
21652
  */
19758
- const rejectOptionLikeRefs = (cwd, refs) => {
21653
+ const rejectOptionLikeRefs = (cwd, refs, sensitive = []) => {
19759
21654
  const offending = refs.find((ref) => ref.startsWith("-"));
19760
- return offending === void 0 ? effect.Effect.void : effect.Effect.fail(new GitCommandError({
21655
+ if (offending !== void 0) return effect.Effect.fail(new GitCommandError({
19761
21656
  kind: "refused",
19762
21657
  args: [offending],
19763
21658
  cwd,
19764
21659
  stderr: "",
19765
21660
  detail: `refused a ref argument git would parse as an option: ${JSON.stringify(offending)}`
19766
21661
  }));
21662
+ return sensitive.find((value) => value.startsWith("-")) === void 0 ? effect.Effect.void : effect.Effect.fail(new GitCommandError({
21663
+ kind: "refused",
21664
+ args: ["<redacted>"],
21665
+ cwd,
21666
+ stderr: "",
21667
+ detail: "refused a sensitive argument git would parse as an option (value redacted)"
21668
+ }));
19767
21669
  };
21670
+ /**
21671
+ * Refuse a caller-supplied numeric index/limit that is not a non-negative
21672
+ * integer.
21673
+ *
21674
+ * Every relational comparison against `NaN` is `false`, so a bare
21675
+ * `value < 0` guard admits `NaN` (and a fractional value truncates nothing —
21676
+ * it rides straight into the argv as `stash@{1.5}` / `--max-count=NaN`).
21677
+ * Integrality and range are therefore checked together, pre-spawn, as a
21678
+ * typed refusal.
21679
+ */
21680
+ const rejectNonNaturalNumber = (cwd, label, value) => value === void 0 || Number.isInteger(value) && value >= 0 ? effect.Effect.void : effect.Effect.fail(new GitCommandError({
21681
+ kind: "refused",
21682
+ args: [String(value)],
21683
+ cwd,
21684
+ stderr: "",
21685
+ detail: `refused ${label}: expected a non-negative integer, received ${value}`
21686
+ }));
19768
21687
  /** Builds the `Git.Service` shape over an already-resolved `ChildProcessSpawner`. */
19769
21688
  const make = (spawner) => {
19770
- const runFor = (command, cwd, kind) => runClassified(command, cwd, kind).pipe(effect.Effect.provideService(effect_unstable_process.ChildProcessSpawner.ChildProcessSpawner, spawner));
21689
+ const runFor = (invocation, cwd, kind) => runClassified(invocation, cwd, kind).pipe(effect.Effect.provideService(effect_unstable_process.ChildProcessSpawner.ChildProcessSpawner, spawner));
19771
21690
  const show = effect.Effect.fn("Git.show")(function* (cwd, ref, path) {
19772
21691
  yield* effect.Effect.annotateCurrentSpan({
19773
21692
  cwd,
@@ -19775,8 +21694,7 @@ const make = (spawner) => {
19775
21694
  path
19776
21695
  });
19777
21696
  yield* rejectOptionLikeRefs(cwd, [ref]);
19778
- const command = effect_unstable_process.ChildProcess.setCwd(GitCommand.show(ref, path), cwd);
19779
- const classified = yield* runFor(command, cwd, "show");
21697
+ const classified = yield* runFor(GitCommand.show(ref, path), cwd, "show");
19780
21698
  switch (classified._tag) {
19781
21699
  case "success": return effect.Option.some(classified.output);
19782
21700
  case "absent": return effect.Option.none();
@@ -19795,8 +21713,7 @@ const make = (spawner) => {
19795
21713
  ref
19796
21714
  });
19797
21715
  yield* rejectOptionLikeRefs(cwd, [ref]);
19798
- const command = effect_unstable_process.ChildProcess.setCwd(GitCommand.lsTree(ref, options?.pathspec ?? []), cwd);
19799
- const classified = yield* runFor(command, cwd, "generic");
21716
+ const classified = yield* runFor(GitCommand.lsTree(ref, options?.pathspec ?? []), cwd, "generic");
19800
21717
  switch (classified._tag) {
19801
21718
  case "success": return parseLsTree(classified.output);
19802
21719
  case "notARepository": return yield* effect.Effect.fail(new NotARepositoryError({ cwd }));
@@ -19814,8 +21731,7 @@ const make = (spawner) => {
19814
21731
  ref
19815
21732
  });
19816
21733
  yield* rejectOptionLikeRefs(cwd, [ref]);
19817
- const command = effect_unstable_process.ChildProcess.setCwd(GitCommand.refExists(ref), cwd);
19818
- const classified = yield* runFor(command, cwd, "refExists");
21734
+ const classified = yield* runFor(GitCommand.refExists(ref), cwd, "refExists");
19819
21735
  switch (classified._tag) {
19820
21736
  case "success": return true;
19821
21737
  case "refMissing": return false;
@@ -19832,8 +21748,7 @@ const make = (spawner) => {
19832
21748
  b
19833
21749
  });
19834
21750
  yield* rejectOptionLikeRefs(cwd, [a, b]);
19835
- const command = effect_unstable_process.ChildProcess.setCwd(GitCommand.mergeBase(a, b), cwd);
19836
- const classified = yield* runFor(command, cwd, "generic");
21751
+ const classified = yield* runFor(GitCommand.mergeBase(a, b), cwd, "generic");
19837
21752
  switch (classified._tag) {
19838
21753
  case "success": return classified.output.trim();
19839
21754
  case "notARepository": return yield* effect.Effect.fail(new NotARepositoryError({ cwd }));
@@ -19854,8 +21769,7 @@ const make = (spawner) => {
19854
21769
  relative
19855
21770
  });
19856
21771
  yield* rejectOptionLikeRefs(cwd, [options.base, options.head]);
19857
- const command = effect_unstable_process.ChildProcess.setCwd(GitCommand.changedFiles(options.base, options.head, relative), cwd);
19858
- const classified = yield* runFor(command, cwd, "generic");
21772
+ const classified = yield* runFor(GitCommand.changedFiles(options.base, options.head, relative), cwd, "generic");
19859
21773
  switch (classified._tag) {
19860
21774
  case "success": return parseNulSeparated(classified.output);
19861
21775
  case "notARepository": return yield* effect.Effect.fail(new NotARepositoryError({ cwd }));
@@ -19867,8 +21781,8 @@ const make = (spawner) => {
19867
21781
  default: return yield* effect.Effect.die(`Git.changedFiles: unexpected classification "${classified._tag}"`);
19868
21782
  }
19869
21783
  });
19870
- const collectPaths = (method, command, cwd) => effect.Effect.gen(function* () {
19871
- const classified = yield* runFor(command, cwd, "generic");
21784
+ const collectPaths = (method, invocation, cwd) => effect.Effect.gen(function* () {
21785
+ const classified = yield* runFor(invocation, cwd, "generic");
19872
21786
  switch (classified._tag) {
19873
21787
  case "success": return parseNulSeparated(classified.output);
19874
21788
  case "notARepository": return yield* effect.Effect.fail(new NotARepositoryError({ cwd }));
@@ -19886,7 +21800,7 @@ const make = (spawner) => {
19886
21800
  cwd,
19887
21801
  relative
19888
21802
  });
19889
- return yield* collectPaths("Git.unstagedChanges", effect_unstable_process.ChildProcess.setCwd(GitCommand.unstagedChanges(relative), cwd), cwd);
21803
+ return yield* collectPaths("Git.unstagedChanges", GitCommand.unstagedChanges(relative), cwd);
19890
21804
  });
19891
21805
  const stagedChanges = effect.Effect.fn("Git.stagedChanges")(function* (cwd, options) {
19892
21806
  const relative = options?.relative ?? false;
@@ -19894,7 +21808,7 @@ const make = (spawner) => {
19894
21808
  cwd,
19895
21809
  relative
19896
21810
  });
19897
- return yield* collectPaths("Git.stagedChanges", effect_unstable_process.ChildProcess.setCwd(GitCommand.stagedChanges(relative), cwd), cwd);
21811
+ return yield* collectPaths("Git.stagedChanges", GitCommand.stagedChanges(relative), cwd);
19898
21812
  });
19899
21813
  const untrackedFiles = effect.Effect.fn("Git.untrackedFiles")(function* (cwd, options) {
19900
21814
  const relative = options?.relative ?? false;
@@ -19902,7 +21816,7 @@ const make = (spawner) => {
19902
21816
  cwd,
19903
21817
  relative
19904
21818
  });
19905
- return yield* collectPaths("Git.untrackedFiles", effect_unstable_process.ChildProcess.setCwd(GitCommand.untrackedFiles(relative), cwd), cwd);
21819
+ return yield* collectPaths("Git.untrackedFiles", GitCommand.untrackedFiles(relative), cwd);
19906
21820
  });
19907
21821
  const workingChanges = effect.Effect.fn("Git.workingChanges")(function* (cwd, options) {
19908
21822
  yield* effect.Effect.annotateCurrentSpan({
@@ -19927,80 +21841,669 @@ const make = (spawner) => {
19927
21841
  relative
19928
21842
  });
19929
21843
  yield* rejectOptionLikeRefs(cwd, options.head === void 0 ? [options.base] : [options.base, options.head]);
19930
- const command = effect_unstable_process.ChildProcess.setCwd(GitCommand.nameStatus(options.base, options.head, relative), cwd);
19931
- const classified = yield* runFor(command, cwd, "generic");
21844
+ const classified = yield* runFor(GitCommand.nameStatus(options.base, options.head, relative), cwd, "generic");
21845
+ switch (classified._tag) {
21846
+ case "success": return parseNameStatus(classified.output);
21847
+ case "notARepository": return yield* effect.Effect.fail(new NotARepositoryError({ cwd }));
21848
+ case "unknownRef": return yield* effect.Effect.fail(new UnknownRefError({
21849
+ ref: options.head === void 0 ? options.base : `${options.base}...${options.head}`,
21850
+ cwd
21851
+ }));
21852
+ case "failure": return yield* effect.Effect.fail(classified.error);
21853
+ default: return yield* effect.Effect.die(`Git.nameStatus: unexpected classification "${classified._tag}"`);
21854
+ }
21855
+ });
21856
+ const revParse = effect.Effect.fn("Git.revParse")(function* (cwd, ref) {
21857
+ yield* effect.Effect.annotateCurrentSpan({
21858
+ cwd,
21859
+ ref
21860
+ });
21861
+ yield* rejectOptionLikeRefs(cwd, [ref]);
21862
+ const classified = yield* runFor(GitCommand.revParse(ref), cwd, "generic");
21863
+ switch (classified._tag) {
21864
+ case "success": return classified.output.trim();
21865
+ case "notARepository": return yield* effect.Effect.fail(new NotARepositoryError({ cwd }));
21866
+ case "unknownRef": return yield* effect.Effect.fail(new UnknownRefError({
21867
+ ref,
21868
+ cwd
21869
+ }));
21870
+ case "failure": return yield* effect.Effect.fail(classified.error);
21871
+ default: return yield* effect.Effect.die(`Git.revParse: unexpected classification "${classified._tag}"`);
21872
+ }
21873
+ });
21874
+ const checkout = effect.Effect.fn("Git.checkout")(function* (cwd, ref, options) {
21875
+ const detach = options?.detach ?? false;
21876
+ yield* effect.Effect.annotateCurrentSpan({
21877
+ cwd,
21878
+ ref,
21879
+ detach
21880
+ });
21881
+ yield* rejectOptionLikeRefs(cwd, [ref]);
21882
+ const classified = yield* runFor(GitCommand.checkout(ref, detach), cwd, "generic");
21883
+ switch (classified._tag) {
21884
+ case "success": return;
21885
+ case "notARepository": return yield* effect.Effect.fail(new NotARepositoryError({ cwd }));
21886
+ case "unknownRef": return yield* effect.Effect.fail(new UnknownRefError({
21887
+ ref,
21888
+ cwd
21889
+ }));
21890
+ case "failure": return yield* effect.Effect.fail(classified.error);
21891
+ default: return yield* effect.Effect.die(`Git.checkout: unexpected classification "${classified._tag}"`);
21892
+ }
21893
+ });
21894
+ const reset = effect.Effect.fn("Git.reset")(function* (cwd, options) {
21895
+ const mode = options?.mode ?? "mixed";
21896
+ yield* effect.Effect.annotateCurrentSpan({
21897
+ cwd,
21898
+ mode,
21899
+ ref: options?.ref ?? "HEAD"
21900
+ });
21901
+ if (options?.ref !== void 0) yield* rejectOptionLikeRefs(cwd, [options.ref]);
21902
+ const classified = yield* runFor(GitCommand.reset(mode, options?.ref), cwd, "generic");
21903
+ switch (classified._tag) {
21904
+ case "success": return;
21905
+ case "notARepository": return yield* effect.Effect.fail(new NotARepositoryError({ cwd }));
21906
+ case "unknownRef": return yield* effect.Effect.fail(new UnknownRefError({
21907
+ ref: options?.ref ?? "HEAD",
21908
+ cwd
21909
+ }));
21910
+ case "failure": return yield* effect.Effect.fail(classified.error);
21911
+ default: return yield* effect.Effect.die(`Git.reset: unexpected classification "${classified._tag}"`);
21912
+ }
21913
+ });
21914
+ const clean = effect.Effect.fn("Git.clean")(function* (cwd, options) {
21915
+ const directories = options?.directories ?? false;
21916
+ const ignored = options?.ignored ?? false;
21917
+ yield* effect.Effect.annotateCurrentSpan({
21918
+ cwd,
21919
+ directories,
21920
+ ignored
21921
+ });
21922
+ const classified = yield* runFor(GitCommand.clean(directories, ignored, options?.paths ?? []), cwd, "generic");
21923
+ switch (classified._tag) {
21924
+ case "success": return;
21925
+ case "notARepository": return yield* effect.Effect.fail(new NotARepositoryError({ cwd }));
21926
+ case "unknownRef": return yield* effect.Effect.fail(new UnknownRefError({
21927
+ ref: "working tree",
21928
+ cwd
21929
+ }));
21930
+ case "failure": return yield* effect.Effect.fail(classified.error);
21931
+ default: return yield* effect.Effect.die(`Git.clean: unexpected classification "${classified._tag}"`);
21932
+ }
21933
+ });
21934
+ const restore = effect.Effect.fn("Git.restore")(function* (cwd, paths, options) {
21935
+ yield* effect.Effect.annotateCurrentSpan({
21936
+ cwd,
21937
+ count: paths.length,
21938
+ source: options?.source ?? "(index)"
21939
+ });
21940
+ if (options?.source !== void 0) yield* rejectOptionLikeRefs(cwd, [options.source]);
21941
+ const classified = yield* runFor(GitCommand.restore(paths, options?.source, options?.staged ?? false, options?.worktree ?? false), cwd, "generic");
21942
+ switch (classified._tag) {
21943
+ case "success": return;
21944
+ case "notARepository": return yield* effect.Effect.fail(new NotARepositoryError({ cwd }));
21945
+ case "unknownRef": return yield* effect.Effect.fail(new UnknownRefError({
21946
+ ref: options?.source ?? "working tree",
21947
+ cwd
21948
+ }));
21949
+ case "failure": return yield* effect.Effect.fail(classified.error);
21950
+ default: return yield* effect.Effect.die(`Git.restore: unexpected classification "${classified._tag}"`);
21951
+ }
21952
+ });
21953
+ const branchCreate = effect.Effect.fn("Git.branchCreate")(function* (cwd, name, options) {
21954
+ const checkoutBranch = options?.checkout ?? false;
21955
+ const force = options?.force ?? false;
21956
+ yield* effect.Effect.annotateCurrentSpan({
21957
+ cwd,
21958
+ name,
21959
+ startPoint: options?.startPoint ?? "HEAD",
21960
+ checkout: checkoutBranch,
21961
+ force
21962
+ });
21963
+ yield* rejectOptionLikeRefs(cwd, [name, ...options?.startPoint !== void 0 ? [options.startPoint] : []]);
21964
+ const classified = yield* runFor(GitCommand.branchCreate(name, options?.startPoint, checkoutBranch, force), cwd, "generic");
21965
+ switch (classified._tag) {
21966
+ case "success": return;
21967
+ case "notARepository": return yield* effect.Effect.fail(new NotARepositoryError({ cwd }));
21968
+ case "unknownRef": return yield* effect.Effect.fail(new UnknownRefError({
21969
+ ref: options?.startPoint ?? name,
21970
+ cwd
21971
+ }));
21972
+ case "failure": return yield* effect.Effect.fail(classified.error);
21973
+ default: return yield* effect.Effect.die(`Git.branchCreate: unexpected classification "${classified._tag}"`);
21974
+ }
21975
+ });
21976
+ const branchDelete = effect.Effect.fn("Git.branchDelete")(function* (cwd, name, options) {
21977
+ yield* effect.Effect.annotateCurrentSpan({
21978
+ cwd,
21979
+ name,
21980
+ force: options?.force ?? false
21981
+ });
21982
+ yield* rejectOptionLikeRefs(cwd, [name]);
21983
+ const classified = yield* runFor(GitCommand.branchDelete(name, options?.force ?? false), cwd, "generic");
21984
+ switch (classified._tag) {
21985
+ case "success": return;
21986
+ case "notARepository": return yield* effect.Effect.fail(new NotARepositoryError({ cwd }));
21987
+ case "unknownRef": return yield* effect.Effect.fail(new UnknownRefError({
21988
+ ref: name,
21989
+ cwd
21990
+ }));
21991
+ case "failure": return yield* effect.Effect.fail(classified.error);
21992
+ default: return yield* effect.Effect.die(`Git.branchDelete: unexpected classification "${classified._tag}"`);
21993
+ }
21994
+ });
21995
+ const isShallow = effect.Effect.fn("Git.isShallow")(function* (cwd) {
21996
+ yield* effect.Effect.annotateCurrentSpan({ cwd });
21997
+ const classified = yield* runFor(GitCommand.isShallow(), cwd, "generic");
21998
+ switch (classified._tag) {
21999
+ case "success": return classified.output.trim() === "true";
22000
+ case "notARepository": return yield* effect.Effect.fail(new NotARepositoryError({ cwd }));
22001
+ case "unknownRef": return yield* effect.Effect.fail(new UnknownRefError({
22002
+ ref: "HEAD",
22003
+ cwd
22004
+ }));
22005
+ case "failure": return yield* effect.Effect.fail(classified.error);
22006
+ default: return yield* effect.Effect.die(`Git.isShallow: unexpected classification "${classified._tag}"`);
22007
+ }
22008
+ });
22009
+ const fetchUnshallow = effect.Effect.fn("Git.fetchUnshallow")(function* (cwd, options) {
22010
+ const remote = options?.remote ?? "origin";
22011
+ yield* effect.Effect.annotateCurrentSpan({ cwd });
22012
+ yield* rejectOptionLikeRefs(cwd, [remote]);
22013
+ const classified = yield* runFor(GitCommand.fetchUnshallow(remote), cwd, "generic");
22014
+ switch (classified._tag) {
22015
+ case "success": return;
22016
+ case "notARepository": return yield* effect.Effect.fail(new NotARepositoryError({ cwd }));
22017
+ case "unknownRef": return yield* effect.Effect.fail(new UnknownRefError({
22018
+ ref: "--unshallow",
22019
+ cwd
22020
+ }));
22021
+ case "failure": return yield* effect.Effect.fail(classified.error);
22022
+ default: return yield* effect.Effect.die(`Git.fetchUnshallow: unexpected classification "${classified._tag}"`);
22023
+ }
22024
+ });
22025
+ const fetch = effect.Effect.fn("Git.fetch")(function* (cwd, options) {
22026
+ const remote = options.remote ?? "origin";
22027
+ const tag = options.tag ?? false;
22028
+ yield* effect.Effect.annotateCurrentSpan({
22029
+ cwd,
22030
+ ref: options.ref,
22031
+ tag
22032
+ });
22033
+ yield* rejectOptionLikeRefs(cwd, [remote, options.ref]);
22034
+ yield* rejectNonNaturalNumber(cwd, "a fetch depth", options.depth);
22035
+ const classified = yield* runFor(GitCommand.fetch(remote, options.ref, options.depth, tag), cwd, "generic");
22036
+ switch (classified._tag) {
22037
+ case "success": return;
22038
+ case "notARepository": return yield* effect.Effect.fail(new NotARepositoryError({ cwd }));
22039
+ case "unknownRef": return yield* effect.Effect.fail(new UnknownRefError({
22040
+ ref: options.ref,
22041
+ cwd
22042
+ }));
22043
+ case "failure": return yield* effect.Effect.fail(classified.error);
22044
+ default: return yield* effect.Effect.die(`Git.fetch: unexpected classification "${classified._tag}"`);
22045
+ }
22046
+ });
22047
+ const fetchAny = effect.Effect.fn("Git.fetchAny")(function* (cwd, options) {
22048
+ yield* effect.Effect.annotateCurrentSpan({
22049
+ cwd,
22050
+ ref: options.ref
22051
+ });
22052
+ return yield* fetch(cwd, {
22053
+ ...options,
22054
+ tag: true
22055
+ }).pipe(effect.Effect.catchTag(["UnknownRefError", "GitCommandError"], (error) => error._tag === "GitCommandError" && error.kind === "refused" ? effect.Effect.fail(error) : fetch(cwd, options)));
22056
+ });
22057
+ const submoduleUpdate = effect.Effect.fn("Git.submoduleUpdate")(function* (cwd, options) {
22058
+ const init = options?.init ?? false;
22059
+ yield* effect.Effect.annotateCurrentSpan({
22060
+ cwd,
22061
+ init
22062
+ });
22063
+ yield* rejectNonNaturalNumber(cwd, "a submodule update depth", options?.depth);
22064
+ const classified = yield* runFor(GitCommand.submoduleUpdate(init, options?.depth, options?.paths ?? []), cwd, "generic");
22065
+ switch (classified._tag) {
22066
+ case "success": return;
22067
+ case "notARepository": return yield* effect.Effect.fail(new NotARepositoryError({ cwd }));
22068
+ case "unknownRef": return yield* effect.Effect.fail(new UnknownRefError({
22069
+ ref: "submodule update",
22070
+ cwd
22071
+ }));
22072
+ case "failure": return yield* effect.Effect.fail(classified.error);
22073
+ default: return yield* effect.Effect.die(`Git.submoduleUpdate: unexpected classification "${classified._tag}"`);
22074
+ }
22075
+ });
22076
+ const submoduleAdd = effect.Effect.fn("Git.submoduleAdd")(function* (cwd, options) {
22077
+ yield* effect.Effect.annotateCurrentSpan({
22078
+ cwd,
22079
+ path: options.path
22080
+ });
22081
+ yield* rejectNonNaturalNumber(cwd, "a submodule add depth", options.depth);
22082
+ const classified = yield* runFor(GitCommand.submoduleAdd(options.url, options.path, options.depth), cwd, "generic");
22083
+ switch (classified._tag) {
22084
+ case "success": return;
22085
+ case "notARepository": return yield* effect.Effect.fail(new NotARepositoryError({ cwd }));
22086
+ case "unknownRef": return yield* effect.Effect.fail(new UnknownRefError({
22087
+ ref: options.path,
22088
+ cwd
22089
+ }));
22090
+ case "failure": return yield* effect.Effect.fail(classified.error);
22091
+ default: return yield* effect.Effect.die(`Git.submoduleAdd: unexpected classification "${classified._tag}"`);
22092
+ }
22093
+ });
22094
+ const sparseCheckoutSet = effect.Effect.fn("Git.sparseCheckoutSet")(function* (cwd, patterns, options) {
22095
+ yield* effect.Effect.annotateCurrentSpan({
22096
+ cwd,
22097
+ cone: options.cone
22098
+ });
22099
+ yield* rejectOptionLikeRefs(cwd, patterns);
22100
+ const classified = yield* runFor(GitCommand.sparseCheckoutSet(patterns, options.cone), cwd, "generic");
22101
+ switch (classified._tag) {
22102
+ case "success": return;
22103
+ case "notARepository": return yield* effect.Effect.fail(new NotARepositoryError({ cwd }));
22104
+ case "unknownRef": return yield* effect.Effect.fail(new UnknownRefError({
22105
+ ref: "sparse-checkout",
22106
+ cwd
22107
+ }));
22108
+ case "failure": return yield* effect.Effect.fail(classified.error);
22109
+ default: return yield* effect.Effect.die(`Git.sparseCheckoutSet: unexpected classification "${classified._tag}"`);
22110
+ }
22111
+ });
22112
+ const configSet = effect.Effect.fn("Git.configSet")(function* (cwd, key, value, options) {
22113
+ yield* effect.Effect.annotateCurrentSpan({
22114
+ cwd,
22115
+ key,
22116
+ file: options?.file ?? "(repository config)"
22117
+ });
22118
+ yield* rejectOptionLikeRefs(cwd, [key, ...options?.file !== void 0 ? [options.file] : []], [value]);
22119
+ const classified = yield* runFor(GitCommand.configSet(key, value, options?.file), cwd, "generic");
22120
+ switch (classified._tag) {
22121
+ case "success": return;
22122
+ case "notARepository": return yield* effect.Effect.fail(new NotARepositoryError({ cwd }));
22123
+ case "unknownRef": return yield* effect.Effect.fail(new UnknownRefError({
22124
+ ref: key,
22125
+ cwd
22126
+ }));
22127
+ case "failure": return yield* effect.Effect.fail(classified.error);
22128
+ default: return yield* effect.Effect.die(`Git.configSet: unexpected classification "${classified._tag}"`);
22129
+ }
22130
+ });
22131
+ const add = effect.Effect.fn("Git.add")(function* (cwd, paths) {
22132
+ yield* effect.Effect.annotateCurrentSpan({
22133
+ cwd,
22134
+ count: paths.length
22135
+ });
22136
+ const classified = yield* runFor(GitCommand.add(paths), cwd, "generic");
22137
+ switch (classified._tag) {
22138
+ case "success": return;
22139
+ case "notARepository": return yield* effect.Effect.fail(new NotARepositoryError({ cwd }));
22140
+ case "unknownRef": return yield* effect.Effect.fail(new UnknownRefError({
22141
+ ref: "working tree",
22142
+ cwd
22143
+ }));
22144
+ case "failure": return yield* effect.Effect.fail(classified.error);
22145
+ default: return yield* effect.Effect.die(`Git.add: unexpected classification "${classified._tag}"`);
22146
+ }
22147
+ });
22148
+ const defaultBranch = effect.Effect.fn("Git.defaultBranch")(function* (cwd, options) {
22149
+ const remote = options?.remote ?? "origin";
22150
+ yield* effect.Effect.annotateCurrentSpan({
22151
+ cwd,
22152
+ remote
22153
+ });
22154
+ yield* rejectOptionLikeRefs(cwd, [remote]);
22155
+ const classified = yield* runFor(GitCommand.defaultBranch(remote), cwd, "quiet");
22156
+ switch (classified._tag) {
22157
+ case "success": {
22158
+ const short = classified.output.trim();
22159
+ const prefix = `${remote}/`;
22160
+ return effect.Option.some(short.startsWith(prefix) ? short.slice(prefix.length) : short);
22161
+ }
22162
+ case "absent": return effect.Option.none();
22163
+ case "notARepository": return yield* effect.Effect.fail(new NotARepositoryError({ cwd }));
22164
+ case "unknownRef": return yield* effect.Effect.fail(new UnknownRefError({
22165
+ ref: `refs/remotes/${remote}/HEAD`,
22166
+ cwd
22167
+ }));
22168
+ case "failure": return yield* effect.Effect.fail(classified.error);
22169
+ default: return yield* effect.Effect.die(`Git.defaultBranch: unexpected classification "${classified._tag}"`);
22170
+ }
22171
+ });
22172
+ const currentBranch = effect.Effect.fn("Git.currentBranch")(function* (cwd) {
22173
+ yield* effect.Effect.annotateCurrentSpan({ cwd });
22174
+ const classified = yield* runFor(GitCommand.currentBranch(), cwd, "generic");
22175
+ switch (classified._tag) {
22176
+ case "success": {
22177
+ const name = classified.output.trim();
22178
+ return name === "HEAD" ? effect.Option.none() : effect.Option.some(name);
22179
+ }
22180
+ case "notARepository": return yield* effect.Effect.fail(new NotARepositoryError({ cwd }));
22181
+ case "unknownRef": return yield* effect.Effect.fail(new UnknownRefError({
22182
+ ref: "HEAD",
22183
+ cwd
22184
+ }));
22185
+ case "failure": return yield* effect.Effect.fail(classified.error);
22186
+ default: return yield* effect.Effect.die(`Git.currentBranch: unexpected classification "${classified._tag}"`);
22187
+ }
22188
+ });
22189
+ const repoRoot = effect.Effect.fn("Git.repoRoot")(function* (cwd) {
22190
+ yield* effect.Effect.annotateCurrentSpan({ cwd });
22191
+ const classified = yield* runFor(GitCommand.repoRoot(), cwd, "generic");
22192
+ switch (classified._tag) {
22193
+ case "success": return classified.output.trim();
22194
+ case "notARepository": return yield* effect.Effect.fail(new NotARepositoryError({ cwd }));
22195
+ case "unknownRef": return yield* effect.Effect.fail(new UnknownRefError({
22196
+ ref: "working tree",
22197
+ cwd
22198
+ }));
22199
+ case "failure": return yield* effect.Effect.fail(classified.error);
22200
+ default: return yield* effect.Effect.die(`Git.repoRoot: unexpected classification "${classified._tag}"`);
22201
+ }
22202
+ });
22203
+ const configGet = effect.Effect.fn("Git.configGet")(function* (cwd, key) {
22204
+ yield* effect.Effect.annotateCurrentSpan({
22205
+ cwd,
22206
+ key
22207
+ });
22208
+ yield* rejectOptionLikeRefs(cwd, [key]);
22209
+ const classified = yield* runFor(GitCommand.configGet(key), cwd, "quiet");
22210
+ switch (classified._tag) {
22211
+ case "success": return effect.Option.some(classified.output.trim());
22212
+ case "absent": return effect.Option.none();
22213
+ case "notARepository": return yield* effect.Effect.fail(new NotARepositoryError({ cwd }));
22214
+ case "unknownRef": return yield* effect.Effect.fail(new UnknownRefError({
22215
+ ref: key,
22216
+ cwd
22217
+ }));
22218
+ case "failure": return yield* effect.Effect.fail(classified.error);
22219
+ default: return yield* effect.Effect.die(`Git.configGet: unexpected classification "${classified._tag}"`);
22220
+ }
22221
+ });
22222
+ const remoteUrl = effect.Effect.fn("Git.remoteUrl")(function* (cwd, options) {
22223
+ const remote = options?.remote ?? "origin";
22224
+ yield* effect.Effect.annotateCurrentSpan({
22225
+ cwd,
22226
+ remote
22227
+ });
22228
+ yield* rejectOptionLikeRefs(cwd, [remote]);
22229
+ const classified = yield* runFor(GitCommand.remoteUrl(remote), cwd, "noSuchRemote");
22230
+ switch (classified._tag) {
22231
+ case "success": return effect.Option.some(classified.output.trim());
22232
+ case "absent": return effect.Option.none();
22233
+ case "notARepository": return yield* effect.Effect.fail(new NotARepositoryError({ cwd }));
22234
+ case "unknownRef": return yield* effect.Effect.fail(new UnknownRefError({
22235
+ ref: remote,
22236
+ cwd
22237
+ }));
22238
+ case "failure": return yield* effect.Effect.fail(classified.error);
22239
+ default: return yield* effect.Effect.die(`Git.remoteUrl: unexpected classification "${classified._tag}"`);
22240
+ }
22241
+ });
22242
+ const commitInfo = effect.Effect.fn("Git.commitInfo")(function* (cwd, ref) {
22243
+ const target = ref ?? "HEAD";
22244
+ yield* effect.Effect.annotateCurrentSpan({
22245
+ cwd,
22246
+ ref: target
22247
+ });
22248
+ yield* rejectOptionLikeRefs(cwd, [target]);
22249
+ const classified = yield* runFor(GitCommand.commitInfo(target), cwd, "generic");
22250
+ switch (classified._tag) {
22251
+ case "success": return parseCommitInfo(classified.output);
22252
+ case "notARepository": return yield* effect.Effect.fail(new NotARepositoryError({ cwd }));
22253
+ case "unknownRef": return yield* effect.Effect.fail(new UnknownRefError({
22254
+ ref: target,
22255
+ cwd
22256
+ }));
22257
+ case "failure": return yield* effect.Effect.fail(classified.error);
22258
+ default: return yield* effect.Effect.die(`Git.commitInfo: unexpected classification "${classified._tag}"`);
22259
+ }
22260
+ });
22261
+ const status = effect.Effect.fn("Git.status")(function* (cwd) {
22262
+ yield* effect.Effect.annotateCurrentSpan({ cwd });
22263
+ const classified = yield* runFor(GitCommand.status(), cwd, "generic");
22264
+ switch (classified._tag) {
22265
+ case "success": return parseStatus(classified.output);
22266
+ case "notARepository": return yield* effect.Effect.fail(new NotARepositoryError({ cwd }));
22267
+ case "unknownRef": return yield* effect.Effect.fail(new UnknownRefError({
22268
+ ref: "working tree",
22269
+ cwd
22270
+ }));
22271
+ case "failure": return yield* effect.Effect.fail(classified.error);
22272
+ default: return yield* effect.Effect.die(`Git.status: unexpected classification "${classified._tag}"`);
22273
+ }
22274
+ });
22275
+ const submoduleStatus = effect.Effect.fn("Git.submoduleStatus")(function* (cwd, options) {
22276
+ yield* effect.Effect.annotateCurrentSpan({
22277
+ cwd,
22278
+ recursive: options?.recursive ?? false
22279
+ });
22280
+ const classified = yield* runFor(GitCommand.submoduleStatus(options?.paths ?? [], options?.recursive ?? false), cwd, "generic");
22281
+ switch (classified._tag) {
22282
+ case "success": return parseSubmoduleStatus(classified.output);
22283
+ case "notARepository": return yield* effect.Effect.fail(new NotARepositoryError({ cwd }));
22284
+ case "unknownRef": return yield* effect.Effect.fail(new UnknownRefError({
22285
+ ref: "submodule status",
22286
+ cwd
22287
+ }));
22288
+ case "failure": return yield* effect.Effect.fail(classified.error);
22289
+ default: return yield* effect.Effect.die(`Git.submoduleStatus: unexpected classification "${classified._tag}"`);
22290
+ }
22291
+ });
22292
+ const submoduleInit = effect.Effect.fn("Git.submoduleInit")(function* (cwd, options) {
22293
+ yield* effect.Effect.annotateCurrentSpan({ cwd });
22294
+ const classified = yield* runFor(GitCommand.submoduleInit(options?.paths ?? []), cwd, "generic");
22295
+ switch (classified._tag) {
22296
+ case "success": return;
22297
+ case "notARepository": return yield* effect.Effect.fail(new NotARepositoryError({ cwd }));
22298
+ case "unknownRef": return yield* effect.Effect.fail(new UnknownRefError({
22299
+ ref: "submodule init",
22300
+ cwd
22301
+ }));
22302
+ case "failure": return yield* effect.Effect.fail(classified.error);
22303
+ default: return yield* effect.Effect.die(`Git.submoduleInit: unexpected classification "${classified._tag}"`);
22304
+ }
22305
+ });
22306
+ const submoduleDeinit = effect.Effect.fn("Git.submoduleDeinit")(function* (cwd, options) {
22307
+ const paths = options.paths ?? [];
22308
+ const all = options.all ?? false;
22309
+ yield* effect.Effect.annotateCurrentSpan({
22310
+ cwd,
22311
+ all,
22312
+ count: paths.length
22313
+ });
22314
+ if (!all && paths.length === 0) return yield* effect.Effect.fail(new GitCommandError({
22315
+ kind: "refused",
22316
+ args: ["submodule", "deinit"],
22317
+ cwd,
22318
+ stderr: "",
22319
+ detail: "refused: submoduleDeinit needs either paths or all: true"
22320
+ }));
22321
+ const classified = yield* runFor(GitCommand.submoduleDeinit(paths, all, options.force ?? false), cwd, "generic");
22322
+ switch (classified._tag) {
22323
+ case "success": return;
22324
+ case "notARepository": return yield* effect.Effect.fail(new NotARepositoryError({ cwd }));
22325
+ case "unknownRef": return yield* effect.Effect.fail(new UnknownRefError({
22326
+ ref: "submodule deinit",
22327
+ cwd
22328
+ }));
22329
+ case "failure": return yield* effect.Effect.fail(classified.error);
22330
+ default: return yield* effect.Effect.die(`Git.submoduleDeinit: unexpected classification "${classified._tag}"`);
22331
+ }
22332
+ });
22333
+ const submoduleSync = effect.Effect.fn("Git.submoduleSync")(function* (cwd, options) {
22334
+ yield* effect.Effect.annotateCurrentSpan({
22335
+ cwd,
22336
+ recursive: options?.recursive ?? false
22337
+ });
22338
+ const classified = yield* runFor(GitCommand.submoduleSync(options?.paths ?? [], options?.recursive ?? false), cwd, "generic");
22339
+ switch (classified._tag) {
22340
+ case "success": return;
22341
+ case "notARepository": return yield* effect.Effect.fail(new NotARepositoryError({ cwd }));
22342
+ case "unknownRef": return yield* effect.Effect.fail(new UnknownRefError({
22343
+ ref: "submodule sync",
22344
+ cwd
22345
+ }));
22346
+ case "failure": return yield* effect.Effect.fail(classified.error);
22347
+ default: return yield* effect.Effect.die(`Git.submoduleSync: unexpected classification "${classified._tag}"`);
22348
+ }
22349
+ });
22350
+ const submoduleSetUrl = effect.Effect.fn("Git.submoduleSetUrl")(function* (cwd, path, url) {
22351
+ yield* effect.Effect.annotateCurrentSpan({
22352
+ cwd,
22353
+ path
22354
+ });
22355
+ const classified = yield* runFor(GitCommand.submoduleSetUrl(path, url), cwd, "generic");
22356
+ switch (classified._tag) {
22357
+ case "success": return;
22358
+ case "notARepository": return yield* effect.Effect.fail(new NotARepositoryError({ cwd }));
22359
+ case "unknownRef": return yield* effect.Effect.fail(new UnknownRefError({
22360
+ ref: path,
22361
+ cwd
22362
+ }));
22363
+ case "failure": return yield* effect.Effect.fail(classified.error);
22364
+ default: return yield* effect.Effect.die(`Git.submoduleSetUrl: unexpected classification "${classified._tag}"`);
22365
+ }
22366
+ });
22367
+ const submoduleSetBranch = effect.Effect.fn("Git.submoduleSetBranch")(function* (cwd, path, options) {
22368
+ const branch = options?.branch;
22369
+ yield* effect.Effect.annotateCurrentSpan({
22370
+ cwd,
22371
+ path,
22372
+ branch: branch ?? "(default)"
22373
+ });
22374
+ if (branch !== void 0) yield* rejectOptionLikeRefs(cwd, [branch]);
22375
+ const classified = yield* runFor(GitCommand.submoduleSetBranch(path, branch), cwd, "generic");
22376
+ switch (classified._tag) {
22377
+ case "success": return;
22378
+ case "notARepository": return yield* effect.Effect.fail(new NotARepositoryError({ cwd }));
22379
+ case "unknownRef": return yield* effect.Effect.fail(new UnknownRefError({
22380
+ ref: branch ?? path,
22381
+ cwd
22382
+ }));
22383
+ case "failure": return yield* effect.Effect.fail(classified.error);
22384
+ default: return yield* effect.Effect.die(`Git.submoduleSetBranch: unexpected classification "${classified._tag}"`);
22385
+ }
22386
+ });
22387
+ const submoduleAbsorbgitdirs = effect.Effect.fn("Git.submoduleAbsorbgitdirs")(function* (cwd, options) {
22388
+ yield* effect.Effect.annotateCurrentSpan({ cwd });
22389
+ const classified = yield* runFor(GitCommand.submoduleAbsorbgitdirs(options?.paths ?? []), cwd, "generic");
19932
22390
  switch (classified._tag) {
19933
- case "success": return parseNameStatus(classified.output);
22391
+ case "success": return;
19934
22392
  case "notARepository": return yield* effect.Effect.fail(new NotARepositoryError({ cwd }));
19935
22393
  case "unknownRef": return yield* effect.Effect.fail(new UnknownRefError({
19936
- ref: options.head === void 0 ? options.base : `${options.base}...${options.head}`,
22394
+ ref: "submodule absorbgitdirs",
19937
22395
  cwd
19938
22396
  }));
19939
22397
  case "failure": return yield* effect.Effect.fail(classified.error);
19940
- default: return yield* effect.Effect.die(`Git.nameStatus: unexpected classification "${classified._tag}"`);
22398
+ default: return yield* effect.Effect.die(`Git.submoduleAbsorbgitdirs: unexpected classification "${classified._tag}"`);
19941
22399
  }
19942
22400
  });
19943
- const revParse = effect.Effect.fn("Git.revParse")(function* (cwd, ref) {
22401
+ const submoduleForeach = effect.Effect.fn("Git.submoduleForeach")(function* (cwd, command, options) {
19944
22402
  yield* effect.Effect.annotateCurrentSpan({
19945
22403
  cwd,
19946
- ref
22404
+ recursive: options?.recursive ?? false
19947
22405
  });
19948
- yield* rejectOptionLikeRefs(cwd, [ref]);
19949
- const command = effect_unstable_process.ChildProcess.setCwd(GitCommand.revParse(ref), cwd);
19950
- const classified = yield* runFor(command, cwd, "generic");
22406
+ yield* rejectOptionLikeRefs(cwd, [command]);
22407
+ const classified = yield* runFor(GitCommand.submoduleForeach(command, options?.recursive ?? false), cwd, "generic");
19951
22408
  switch (classified._tag) {
19952
- case "success": return classified.output.trim();
22409
+ case "success": return classified.output;
19953
22410
  case "notARepository": return yield* effect.Effect.fail(new NotARepositoryError({ cwd }));
19954
22411
  case "unknownRef": return yield* effect.Effect.fail(new UnknownRefError({
19955
- ref,
22412
+ ref: "submodule foreach",
19956
22413
  cwd
19957
22414
  }));
19958
22415
  case "failure": return yield* effect.Effect.fail(classified.error);
19959
- default: return yield* effect.Effect.die(`Git.revParse: unexpected classification "${classified._tag}"`);
22416
+ default: return yield* effect.Effect.die(`Git.submoduleForeach: unexpected classification "${classified._tag}"`);
19960
22417
  }
19961
22418
  });
19962
- const checkout = effect.Effect.fn("Git.checkout")(function* (cwd, ref, options) {
19963
- const detach = options?.detach ?? false;
19964
- yield* effect.Effect.annotateCurrentSpan({
19965
- cwd,
19966
- ref,
19967
- detach
19968
- });
19969
- yield* rejectOptionLikeRefs(cwd, [ref]);
19970
- const command = effect_unstable_process.ChildProcess.setCwd(GitCommand.checkout(ref, detach), cwd);
19971
- const classified = yield* runFor(command, cwd, "generic");
22419
+ const runVoid = (method, invocation, cwd, refLabel) => effect.Effect.gen(function* () {
22420
+ const classified = yield* runFor(invocation, cwd, "generic");
19972
22421
  switch (classified._tag) {
19973
22422
  case "success": return;
19974
22423
  case "notARepository": return yield* effect.Effect.fail(new NotARepositoryError({ cwd }));
19975
22424
  case "unknownRef": return yield* effect.Effect.fail(new UnknownRefError({
19976
- ref,
22425
+ ref: refLabel,
19977
22426
  cwd
19978
22427
  }));
19979
22428
  case "failure": return yield* effect.Effect.fail(classified.error);
19980
- default: return yield* effect.Effect.die(`Git.checkout: unexpected classification "${classified._tag}"`);
22429
+ default: return yield* effect.Effect.die(`${method}: unexpected classification "${classified._tag}"`);
19981
22430
  }
19982
22431
  });
19983
- const fetch = effect.Effect.fn("Git.fetch")(function* (cwd, options) {
19984
- const remote = options.remote ?? "origin";
19985
- const tag = options.tag ?? false;
22432
+ const runParsed = (method, invocation, cwd, refLabel, kind, parse, absent) => effect.Effect.gen(function* () {
22433
+ const classified = yield* runFor(invocation, cwd, kind);
22434
+ switch (classified._tag) {
22435
+ case "success": return parse(classified.output);
22436
+ case "absent":
22437
+ if (absent !== void 0) return absent();
22438
+ return yield* effect.Effect.die(`${method}: unexpected classification "absent"`);
22439
+ case "notARepository": return yield* effect.Effect.fail(new NotARepositoryError({ cwd }));
22440
+ case "unknownRef": return yield* effect.Effect.fail(new UnknownRefError({
22441
+ ref: refLabel,
22442
+ cwd
22443
+ }));
22444
+ case "failure": return yield* effect.Effect.fail(classified.error);
22445
+ default: return yield* effect.Effect.die(`${method}: unexpected classification "${classified._tag}"`);
22446
+ }
22447
+ });
22448
+ const lsRemote = effect.Effect.fn("Git.lsRemote")(function* (cwd, remote, options) {
19986
22449
  yield* effect.Effect.annotateCurrentSpan({
19987
22450
  cwd,
19988
- remote,
19989
- ref: options.ref,
19990
- tag
22451
+ heads: options?.heads ?? false,
22452
+ tags: options?.tags ?? false,
22453
+ patterns: (options?.patterns ?? []).length
19991
22454
  });
19992
- yield* rejectOptionLikeRefs(cwd, [remote, options.ref]);
19993
- const command = effect_unstable_process.ChildProcess.setCwd(GitCommand.fetch(remote, options.ref, options.depth, tag), cwd);
19994
- const classified = yield* runFor(command, cwd, "generic");
22455
+ yield* rejectOptionLikeRefs(cwd, [remote, ...options?.patterns ?? []]);
22456
+ return yield* runParsed("Git.lsRemote", GitCommand.lsRemote(remote, options?.heads ?? false, options?.tags ?? false, options?.patterns ?? []), cwd, "ls-remote", "generic", parseLsRemote);
22457
+ });
22458
+ const remoteAdd = effect.Effect.fn("Git.remoteAdd")(function* (cwd, name, url) {
22459
+ yield* effect.Effect.annotateCurrentSpan({
22460
+ cwd,
22461
+ name
22462
+ });
22463
+ yield* rejectOptionLikeRefs(cwd, [name, url]);
22464
+ return yield* runVoid("Git.remoteAdd", GitCommand.remoteAdd(name, url), cwd, name);
22465
+ });
22466
+ const remoteRemove = effect.Effect.fn("Git.remoteRemove")(function* (cwd, name) {
22467
+ yield* effect.Effect.annotateCurrentSpan({
22468
+ cwd,
22469
+ name
22470
+ });
22471
+ yield* rejectOptionLikeRefs(cwd, [name]);
22472
+ return yield* runVoid("Git.remoteRemove", GitCommand.remoteRemove(name), cwd, name);
22473
+ });
22474
+ const remoteSetUrl = effect.Effect.fn("Git.remoteSetUrl")(function* (cwd, name, url) {
22475
+ yield* effect.Effect.annotateCurrentSpan({
22476
+ cwd,
22477
+ name
22478
+ });
22479
+ yield* rejectOptionLikeRefs(cwd, [name, url]);
22480
+ return yield* runVoid("Git.remoteSetUrl", GitCommand.remoteSetUrl(name, url), cwd, name);
22481
+ });
22482
+ const stashPush = effect.Effect.fn("Git.stashPush")(function* (cwd, options) {
22483
+ yield* effect.Effect.annotateCurrentSpan({
22484
+ cwd,
22485
+ includeUntracked: options?.includeUntracked ?? false
22486
+ });
22487
+ return yield* runVoid("Git.stashPush", GitCommand.stashPush(options?.message, options?.includeUntracked ?? false, options?.paths ?? []), cwd, "stash");
22488
+ });
22489
+ const stashRestore = (method, invocation) => effect.Effect.fn(method)(function* (cwd, options) {
22490
+ yield* effect.Effect.annotateCurrentSpan({
22491
+ cwd,
22492
+ index: options?.index ?? 0
22493
+ });
22494
+ yield* rejectNonNaturalNumber(cwd, "a stash index", options?.index);
22495
+ const classified = yield* runFor(invocation(options?.index), cwd, "merge");
19995
22496
  switch (classified._tag) {
19996
22497
  case "success": return;
22498
+ case "dirtyWorktree": return yield* effect.Effect.fail(new DirtyWorktreeError({ cwd }));
22499
+ case "mergeConflict": return yield* effect.Effect.fail(new MergeConflictError({ cwd }));
19997
22500
  case "notARepository": return yield* effect.Effect.fail(new NotARepositoryError({ cwd }));
19998
22501
  case "unknownRef": return yield* effect.Effect.fail(new UnknownRefError({
19999
- ref: options.ref,
22502
+ ref: "stash",
20000
22503
  cwd
20001
22504
  }));
20002
22505
  case "failure": return yield* effect.Effect.fail(classified.error);
20003
- default: return yield* effect.Effect.die(`Git.fetch: unexpected classification "${classified._tag}"`);
22506
+ default: return yield* effect.Effect.die(`${method}: unexpected classification "${classified._tag}"`);
20004
22507
  }
20005
22508
  });
20006
22509
  return {
@@ -20013,254 +22516,235 @@ const make = (spawner) => {
20013
22516
  revParse,
20014
22517
  checkout,
20015
22518
  fetch,
20016
- fetchAny: effect.Effect.fn("Git.fetchAny")(function* (cwd, options) {
20017
- const remote = options.remote ?? "origin";
22519
+ fetchAny,
22520
+ fetchUnshallow,
22521
+ isShallow,
22522
+ reset,
22523
+ clean,
22524
+ restore,
22525
+ branchCreate,
22526
+ branchDelete,
22527
+ submoduleUpdate,
22528
+ submoduleAdd,
22529
+ submoduleStatus,
22530
+ submoduleInit,
22531
+ submoduleDeinit,
22532
+ submoduleSync,
22533
+ submoduleSetUrl,
22534
+ submoduleSetBranch,
22535
+ submoduleAbsorbgitdirs,
22536
+ submoduleForeach,
22537
+ sparseCheckoutSet,
22538
+ configSet,
22539
+ add,
22540
+ nameStatus,
22541
+ unstagedChanges,
22542
+ stagedChanges,
22543
+ untrackedFiles,
22544
+ defaultBranch,
22545
+ currentBranch,
22546
+ repoRoot,
22547
+ configGet,
22548
+ remoteUrl,
22549
+ commitInfo,
22550
+ status,
22551
+ lsRemote,
22552
+ remoteAdd,
22553
+ remoteRemove,
22554
+ remoteSetUrl,
22555
+ stashPush,
22556
+ stashPop: stashRestore("Git.stashPop", GitCommand.stashPop),
22557
+ stashApply: stashRestore("Git.stashApply", GitCommand.stashApply),
22558
+ stashDrop: effect.Effect.fn("Git.stashDrop")(function* (cwd, options) {
20018
22559
  yield* effect.Effect.annotateCurrentSpan({
20019
22560
  cwd,
20020
- remote,
20021
- ref: options.ref
22561
+ index: options?.index ?? 0
20022
22562
  });
20023
- return yield* fetch(cwd, {
20024
- ...options,
20025
- tag: true
20026
- }).pipe(effect.Effect.catchTag(["UnknownRefError", "GitCommandError"], (error) => error._tag === "GitCommandError" && error.kind === "refused" ? effect.Effect.fail(error) : fetch(cwd, options)));
22563
+ yield* rejectNonNaturalNumber(cwd, "a stash index", options?.index);
22564
+ return yield* runVoid("Git.stashDrop", GitCommand.stashDrop(options?.index), cwd, "stash");
22565
+ }),
22566
+ stashList: effect.Effect.fn("Git.stashList")(function* (cwd) {
22567
+ yield* effect.Effect.annotateCurrentSpan({ cwd });
22568
+ return yield* runParsed("Git.stashList", GitCommand.stashList(), cwd, "stash", "generic", parseStashList);
20027
22569
  }),
20028
- submoduleUpdate: effect.Effect.fn("Git.submoduleUpdate")(function* (cwd, options) {
20029
- const init = options?.init ?? false;
22570
+ branchList: effect.Effect.fn("Git.branchList")(function* (cwd, options) {
20030
22571
  yield* effect.Effect.annotateCurrentSpan({
20031
22572
  cwd,
20032
- init
22573
+ remotes: options?.remotes ?? false,
22574
+ all: options?.all ?? false
20033
22575
  });
20034
- const command = effect_unstable_process.ChildProcess.setCwd(GitCommand.submoduleUpdate(init, options?.depth, options?.paths ?? []), cwd);
20035
- const classified = yield* runFor(command, cwd, "generic");
20036
- switch (classified._tag) {
20037
- case "success": return;
20038
- case "notARepository": return yield* effect.Effect.fail(new NotARepositoryError({ cwd }));
20039
- case "unknownRef": return yield* effect.Effect.fail(new UnknownRefError({
20040
- ref: "submodule update",
20041
- cwd
20042
- }));
20043
- case "failure": return yield* effect.Effect.fail(classified.error);
20044
- default: return yield* effect.Effect.die(`Git.submoduleUpdate: unexpected classification "${classified._tag}"`);
20045
- }
22576
+ return yield* runParsed("Git.branchList", GitCommand.branchList(options?.remotes ?? false, options?.all ?? false), cwd, "branches", "generic", parseBranchList);
20046
22577
  }),
20047
- submoduleAdd: effect.Effect.fn("Git.submoduleAdd")(function* (cwd, options) {
22578
+ tagCreate: effect.Effect.fn("Git.tagCreate")(function* (cwd, name, options) {
20048
22579
  yield* effect.Effect.annotateCurrentSpan({
20049
22580
  cwd,
20050
- url: options.url,
20051
- path: options.path
22581
+ name,
22582
+ ref: options?.ref ?? "HEAD",
22583
+ force: options?.force ?? false
20052
22584
  });
20053
- const command = effect_unstable_process.ChildProcess.setCwd(GitCommand.submoduleAdd(options.url, options.path, options.depth), cwd);
20054
- const classified = yield* runFor(command, cwd, "generic");
20055
- switch (classified._tag) {
20056
- case "success": return;
20057
- case "notARepository": return yield* effect.Effect.fail(new NotARepositoryError({ cwd }));
20058
- case "unknownRef": return yield* effect.Effect.fail(new UnknownRefError({
20059
- ref: options.url,
20060
- cwd
20061
- }));
20062
- case "failure": return yield* effect.Effect.fail(classified.error);
20063
- default: return yield* effect.Effect.die(`Git.submoduleAdd: unexpected classification "${classified._tag}"`);
20064
- }
22585
+ yield* rejectOptionLikeRefs(cwd, [name, ...options?.ref !== void 0 ? [options.ref] : []]);
22586
+ return yield* runVoid("Git.tagCreate", GitCommand.tagCreate(name, options?.ref, options?.message, options?.force ?? false), cwd, options?.ref ?? name);
20065
22587
  }),
20066
- sparseCheckoutSet: effect.Effect.fn("Git.sparseCheckoutSet")(function* (cwd, patterns, options) {
22588
+ tagDelete: effect.Effect.fn("Git.tagDelete")(function* (cwd, name) {
20067
22589
  yield* effect.Effect.annotateCurrentSpan({
20068
22590
  cwd,
20069
- cone: options.cone
22591
+ name
20070
22592
  });
20071
- yield* rejectOptionLikeRefs(cwd, patterns);
20072
- const command = effect_unstable_process.ChildProcess.setCwd(GitCommand.sparseCheckoutSet(patterns, options.cone), cwd);
20073
- const classified = yield* runFor(command, cwd, "generic");
20074
- switch (classified._tag) {
20075
- case "success": return;
20076
- case "notARepository": return yield* effect.Effect.fail(new NotARepositoryError({ cwd }));
20077
- case "unknownRef": return yield* effect.Effect.fail(new UnknownRefError({
20078
- ref: "sparse-checkout",
20079
- cwd
20080
- }));
20081
- case "failure": return yield* effect.Effect.fail(classified.error);
20082
- default: return yield* effect.Effect.die(`Git.sparseCheckoutSet: unexpected classification "${classified._tag}"`);
20083
- }
22593
+ yield* rejectOptionLikeRefs(cwd, [name]);
22594
+ return yield* runVoid("Git.tagDelete", GitCommand.tagDelete(name), cwd, name);
22595
+ }),
22596
+ tagList: effect.Effect.fn("Git.tagList")(function* (cwd, options) {
22597
+ yield* effect.Effect.annotateCurrentSpan({ cwd });
22598
+ yield* rejectOptionLikeRefs(cwd, options?.pattern !== void 0 ? [options.pattern] : []);
22599
+ return yield* runParsed("Git.tagList", GitCommand.tagList(options?.pattern), cwd, "tags", "generic", (output) => output.split("\n").filter((line) => line.length > 0));
20084
22600
  }),
20085
- configSet: effect.Effect.fn("Git.configSet")(function* (cwd, key, value, options) {
22601
+ forEachRef: effect.Effect.fn("Git.forEachRef")(function* (cwd, options) {
20086
22602
  yield* effect.Effect.annotateCurrentSpan({
20087
22603
  cwd,
20088
- key,
20089
- file: options?.file ?? "(repository config)"
22604
+ patterns: (options?.patterns ?? []).length
20090
22605
  });
20091
- yield* rejectOptionLikeRefs(cwd, [
20092
- key,
20093
- value,
20094
- ...options?.file !== void 0 ? [options.file] : []
20095
- ]);
20096
- const command = effect_unstable_process.ChildProcess.setCwd(GitCommand.configSet(key, value, options?.file), cwd);
20097
- const classified = yield* runFor(command, cwd, "generic");
20098
- switch (classified._tag) {
20099
- case "success": return;
20100
- case "notARepository": return yield* effect.Effect.fail(new NotARepositoryError({ cwd }));
20101
- case "unknownRef": return yield* effect.Effect.fail(new UnknownRefError({
20102
- ref: key,
20103
- cwd
20104
- }));
20105
- case "failure": return yield* effect.Effect.fail(classified.error);
20106
- default: return yield* effect.Effect.die(`Git.configSet: unexpected classification "${classified._tag}"`);
20107
- }
22606
+ yield* rejectOptionLikeRefs(cwd, options?.patterns ?? []);
22607
+ return yield* runParsed("Git.forEachRef", GitCommand.forEachRef(options?.patterns ?? []), cwd, "for-each-ref", "generic", parseForEachRef);
20108
22608
  }),
20109
- add: effect.Effect.fn("Git.add")(function* (cwd, paths) {
22609
+ revList: effect.Effect.fn("Git.revList")(function* (cwd, ref, options) {
20110
22610
  yield* effect.Effect.annotateCurrentSpan({
20111
22611
  cwd,
20112
- count: paths.length
22612
+ ref,
22613
+ firstParent: options?.firstParent ?? false
22614
+ });
22615
+ yield* rejectOptionLikeRefs(cwd, [ref]);
22616
+ yield* rejectNonNaturalNumber(cwd, "a rev-list limit", options?.limit);
22617
+ 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));
22618
+ }),
22619
+ commit: effect.Effect.fn("Git.commit")(function* (cwd, message, options) {
22620
+ yield* effect.Effect.annotateCurrentSpan({
22621
+ cwd,
22622
+ amend: options?.amend ?? false
22623
+ });
22624
+ return yield* runVoid("Git.commit", GitCommand.commit(message, options?.all ?? false, options?.allowEmpty ?? false, options?.amend ?? false, options?.author), cwd, "HEAD");
22625
+ }),
22626
+ push: effect.Effect.fn("Git.push")(function* (cwd, options) {
22627
+ const remote = options?.remote ?? "origin";
22628
+ yield* effect.Effect.annotateCurrentSpan({
22629
+ cwd,
22630
+ refspec: options?.refspec ?? "(current branch)",
22631
+ forceWithLease: options?.forceWithLease ?? false
20113
22632
  });
20114
- const command = effect_unstable_process.ChildProcess.setCwd(GitCommand.add(paths), cwd);
20115
- const classified = yield* runFor(command, cwd, "generic");
22633
+ yield* rejectOptionLikeRefs(cwd, [remote, ...options?.refspec !== void 0 ? [options.refspec] : []]);
22634
+ const classified = yield* runFor(GitCommand.push(remote, options?.refspec, options?.force ?? false, options?.forceWithLease ?? false, options?.tags ?? false, options?.setUpstream ?? false), cwd, "push");
20116
22635
  switch (classified._tag) {
20117
22636
  case "success": return;
22637
+ case "nonFastForward": return yield* effect.Effect.fail(new NonFastForwardError({
22638
+ cwd,
22639
+ ...options?.refspec !== void 0 ? { refspec: options.refspec } : {}
22640
+ }));
20118
22641
  case "notARepository": return yield* effect.Effect.fail(new NotARepositoryError({ cwd }));
20119
22642
  case "unknownRef": return yield* effect.Effect.fail(new UnknownRefError({
20120
- ref: "working tree",
22643
+ ref: options?.refspec ?? "HEAD",
20121
22644
  cwd
20122
22645
  }));
20123
22646
  case "failure": return yield* effect.Effect.fail(classified.error);
20124
- default: return yield* effect.Effect.die(`Git.add: unexpected classification "${classified._tag}"`);
22647
+ default: return yield* effect.Effect.die(`Git.push: unexpected classification "${classified._tag}"`);
20125
22648
  }
20126
22649
  }),
20127
- nameStatus,
20128
- unstagedChanges,
20129
- stagedChanges,
20130
- untrackedFiles,
20131
- defaultBranch: effect.Effect.fn("Git.defaultBranch")(function* (cwd, options) {
22650
+ pull: effect.Effect.fn("Git.pull")(function* (cwd, options) {
20132
22651
  const remote = options?.remote ?? "origin";
20133
22652
  yield* effect.Effect.annotateCurrentSpan({
20134
22653
  cwd,
20135
- remote
22654
+ ref: options?.ref ?? "(upstream)",
22655
+ rebase: options?.rebase ?? false
20136
22656
  });
20137
- yield* rejectOptionLikeRefs(cwd, [remote]);
20138
- const command = effect_unstable_process.ChildProcess.setCwd(GitCommand.defaultBranch(remote), cwd);
20139
- const classified = yield* runFor(command, cwd, "quiet");
22657
+ yield* rejectOptionLikeRefs(cwd, [remote, ...options?.ref !== void 0 ? [options.ref] : []]);
22658
+ const classified = yield* runFor(GitCommand.pull(remote, options?.ref, options?.rebase ?? false, options?.ffOnly ?? false), cwd, "merge");
20140
22659
  switch (classified._tag) {
20141
- case "success": {
20142
- const short = classified.output.trim();
20143
- const prefix = `${remote}/`;
20144
- return effect.Option.some(short.startsWith(prefix) ? short.slice(prefix.length) : short);
20145
- }
20146
- case "absent": return effect.Option.none();
22660
+ case "success": return;
22661
+ case "dirtyWorktree": return yield* effect.Effect.fail(new DirtyWorktreeError({ cwd }));
22662
+ case "mergeConflict": return yield* effect.Effect.fail(new MergeConflictError({ cwd }));
20147
22663
  case "notARepository": return yield* effect.Effect.fail(new NotARepositoryError({ cwd }));
20148
22664
  case "unknownRef": return yield* effect.Effect.fail(new UnknownRefError({
20149
- ref: `refs/remotes/${remote}/HEAD`,
22665
+ ref: options?.ref ?? "(upstream)",
20150
22666
  cwd
20151
22667
  }));
20152
22668
  case "failure": return yield* effect.Effect.fail(classified.error);
20153
- default: return yield* effect.Effect.die(`Git.defaultBranch: unexpected classification "${classified._tag}"`);
22669
+ default: return yield* effect.Effect.die(`Git.pull: unexpected classification "${classified._tag}"`);
20154
22670
  }
20155
22671
  }),
20156
- currentBranch: effect.Effect.fn("Git.currentBranch")(function* (cwd) {
20157
- yield* effect.Effect.annotateCurrentSpan({ cwd });
20158
- const command = effect_unstable_process.ChildProcess.setCwd(GitCommand.currentBranch(), cwd);
20159
- const classified = yield* runFor(command, cwd, "generic");
20160
- switch (classified._tag) {
20161
- case "success": {
20162
- const name = classified.output.trim();
20163
- return name === "HEAD" ? effect.Option.none() : effect.Option.some(name);
20164
- }
20165
- case "notARepository": return yield* effect.Effect.fail(new NotARepositoryError({ cwd }));
20166
- case "unknownRef": return yield* effect.Effect.fail(new UnknownRefError({
20167
- ref: "HEAD",
20168
- cwd
20169
- }));
20170
- case "failure": return yield* effect.Effect.fail(classified.error);
20171
- default: return yield* effect.Effect.die(`Git.currentBranch: unexpected classification "${classified._tag}"`);
20172
- }
22672
+ configList: effect.Effect.fn("Git.configList")(function* (cwd, options) {
22673
+ yield* effect.Effect.annotateCurrentSpan({
22674
+ cwd,
22675
+ file: options?.file ?? "(repository config)"
22676
+ });
22677
+ yield* rejectOptionLikeRefs(cwd, options?.file !== void 0 ? [options.file] : []);
22678
+ return yield* runParsed("Git.configList", GitCommand.configList(options?.file), cwd, "config", "generic", parseConfigList);
20173
22679
  }),
20174
- repoRoot: effect.Effect.fn("Git.repoRoot")(function* (cwd) {
20175
- yield* effect.Effect.annotateCurrentSpan({ cwd });
20176
- const command = effect_unstable_process.ChildProcess.setCwd(GitCommand.repoRoot(), cwd);
20177
- const classified = yield* runFor(command, cwd, "generic");
20178
- switch (classified._tag) {
20179
- case "success": return classified.output.trim();
20180
- case "notARepository": return yield* effect.Effect.fail(new NotARepositoryError({ cwd }));
20181
- case "unknownRef": return yield* effect.Effect.fail(new UnknownRefError({
20182
- ref: "working tree",
20183
- cwd
20184
- }));
20185
- case "failure": return yield* effect.Effect.fail(classified.error);
20186
- default: return yield* effect.Effect.die(`Git.repoRoot: unexpected classification "${classified._tag}"`);
20187
- }
22680
+ configGetAll: effect.Effect.fn("Git.configGetAll")(function* (cwd, key, options) {
22681
+ yield* effect.Effect.annotateCurrentSpan({
22682
+ cwd,
22683
+ key,
22684
+ file: options?.file ?? "(repository config)"
22685
+ });
22686
+ yield* rejectOptionLikeRefs(cwd, [key, ...options?.file !== void 0 ? [options.file] : []]);
22687
+ return yield* runParsed("Git.configGetAll", GitCommand.configGetAll(key, options?.file), cwd, key, "quiet", parseNulSeparated, () => []);
20188
22688
  }),
20189
- configGet: effect.Effect.fn("Git.configGet")(function* (cwd, key) {
22689
+ configUnset: effect.Effect.fn("Git.configUnset")(function* (cwd, key, options) {
20190
22690
  yield* effect.Effect.annotateCurrentSpan({
20191
22691
  cwd,
20192
- key
22692
+ key,
22693
+ file: options?.file ?? "(repository config)"
20193
22694
  });
20194
- yield* rejectOptionLikeRefs(cwd, [key]);
20195
- const command = effect_unstable_process.ChildProcess.setCwd(GitCommand.configGet(key), cwd);
20196
- const classified = yield* runFor(command, cwd, "quiet");
20197
- switch (classified._tag) {
20198
- case "success": return effect.Option.some(classified.output.trim());
20199
- case "absent": return effect.Option.none();
20200
- case "notARepository": return yield* effect.Effect.fail(new NotARepositoryError({ cwd }));
20201
- case "unknownRef": return yield* effect.Effect.fail(new UnknownRefError({
20202
- ref: key,
20203
- cwd
20204
- }));
20205
- case "failure": return yield* effect.Effect.fail(classified.error);
20206
- default: return yield* effect.Effect.die(`Git.configGet: unexpected classification "${classified._tag}"`);
20207
- }
22695
+ yield* rejectOptionLikeRefs(cwd, [key, ...options?.file !== void 0 ? [options.file] : []]);
22696
+ return yield* runVoid("Git.configUnset", GitCommand.configUnset(key, options?.file, options?.all ?? false), cwd, key);
20208
22697
  }),
20209
- remoteUrl: effect.Effect.fn("Git.remoteUrl")(function* (cwd, options) {
20210
- const remote = options?.remote ?? "origin";
22698
+ rm: effect.Effect.fn("Git.rm")(function* (cwd, paths, options) {
20211
22699
  yield* effect.Effect.annotateCurrentSpan({
20212
22700
  cwd,
20213
- remote
22701
+ count: paths.length,
22702
+ cached: options?.cached ?? false
20214
22703
  });
20215
- yield* rejectOptionLikeRefs(cwd, [remote]);
20216
- const command = effect_unstable_process.ChildProcess.setCwd(GitCommand.remoteUrl(remote), cwd);
20217
- const classified = yield* runFor(command, cwd, "noSuchRemote");
20218
- switch (classified._tag) {
20219
- case "success": return effect.Option.some(classified.output.trim());
20220
- case "absent": return effect.Option.none();
20221
- case "notARepository": return yield* effect.Effect.fail(new NotARepositoryError({ cwd }));
20222
- case "unknownRef": return yield* effect.Effect.fail(new UnknownRefError({
20223
- ref: remote,
20224
- cwd
20225
- }));
20226
- case "failure": return yield* effect.Effect.fail(classified.error);
20227
- default: return yield* effect.Effect.die(`Git.remoteUrl: unexpected classification "${classified._tag}"`);
20228
- }
22704
+ return yield* runVoid("Git.rm", GitCommand.rm(paths, options?.cached ?? false, options?.recursive ?? false, options?.force ?? false), cwd, "working tree");
20229
22705
  }),
20230
- commitInfo: effect.Effect.fn("Git.commitInfo")(function* (cwd, ref) {
20231
- const target = ref ?? "HEAD";
22706
+ mv: effect.Effect.fn("Git.mv")(function* (cwd, source, destination, options) {
20232
22707
  yield* effect.Effect.annotateCurrentSpan({
20233
22708
  cwd,
20234
- ref: target
22709
+ source,
22710
+ destination
20235
22711
  });
20236
- yield* rejectOptionLikeRefs(cwd, [target]);
20237
- const command = effect_unstable_process.ChildProcess.setCwd(GitCommand.commitInfo(target), cwd);
20238
- const classified = yield* runFor(command, cwd, "generic");
20239
- switch (classified._tag) {
20240
- case "success": return parseCommitInfo(classified.output);
20241
- case "notARepository": return yield* effect.Effect.fail(new NotARepositoryError({ cwd }));
20242
- case "unknownRef": return yield* effect.Effect.fail(new UnknownRefError({
20243
- ref: target,
20244
- cwd
20245
- }));
20246
- case "failure": return yield* effect.Effect.fail(classified.error);
20247
- default: return yield* effect.Effect.die(`Git.commitInfo: unexpected classification "${classified._tag}"`);
20248
- }
22712
+ return yield* runVoid("Git.mv", GitCommand.mv(source, destination, options?.force ?? false), cwd, "working tree");
22713
+ }),
22714
+ checkIgnore: effect.Effect.fn("Git.checkIgnore")(function* (cwd, paths) {
22715
+ yield* effect.Effect.annotateCurrentSpan({
22716
+ cwd,
22717
+ count: paths.length
22718
+ });
22719
+ return yield* runParsed("Git.checkIgnore", GitCommand.checkIgnore(paths), cwd, "check-ignore", "quiet", parseNulSeparated, () => []);
22720
+ }),
22721
+ worktreeAdd: effect.Effect.fn("Git.worktreeAdd")(function* (cwd, path, options) {
22722
+ yield* effect.Effect.annotateCurrentSpan({
22723
+ cwd,
22724
+ path,
22725
+ ref: options?.ref ?? "(default)"
22726
+ });
22727
+ yield* rejectOptionLikeRefs(cwd, [path, ...options?.ref !== void 0 ? [options.ref] : []]);
22728
+ return yield* runVoid("Git.worktreeAdd", GitCommand.worktreeAdd(path, options?.ref, options?.detach ?? false, options?.force ?? false), cwd, options?.ref ?? path);
20249
22729
  }),
20250
- status: effect.Effect.fn("Git.status")(function* (cwd) {
22730
+ worktreeList: effect.Effect.fn("Git.worktreeList")(function* (cwd) {
20251
22731
  yield* effect.Effect.annotateCurrentSpan({ cwd });
20252
- const command = effect_unstable_process.ChildProcess.setCwd(GitCommand.status(), cwd);
20253
- const classified = yield* runFor(command, cwd, "generic");
20254
- switch (classified._tag) {
20255
- case "success": return parseStatus(classified.output);
20256
- case "notARepository": return yield* effect.Effect.fail(new NotARepositoryError({ cwd }));
20257
- case "unknownRef": return yield* effect.Effect.fail(new UnknownRefError({
20258
- ref: "working tree",
20259
- cwd
20260
- }));
20261
- case "failure": return yield* effect.Effect.fail(classified.error);
20262
- default: return yield* effect.Effect.die(`Git.status: unexpected classification "${classified._tag}"`);
20263
- }
22732
+ return yield* runParsed("Git.worktreeList", GitCommand.worktreeList(), cwd, "worktrees", "generic", parseWorktreeList);
22733
+ }),
22734
+ worktreeRemove: effect.Effect.fn("Git.worktreeRemove")(function* (cwd, path, options) {
22735
+ yield* effect.Effect.annotateCurrentSpan({
22736
+ cwd,
22737
+ path
22738
+ });
22739
+ yield* rejectOptionLikeRefs(cwd, [path]);
22740
+ return yield* runVoid("Git.worktreeRemove", GitCommand.worktreeRemove(path, options?.force ?? false), cwd, path);
22741
+ }),
22742
+ lsFiles: effect.Effect.fn("Git.lsFiles")(function* (cwd, options) {
22743
+ yield* effect.Effect.annotateCurrentSpan({
22744
+ cwd,
22745
+ patterns: (options?.pathspec ?? []).length
22746
+ });
22747
+ return yield* runParsed("Git.lsFiles", GitCommand.lsFiles(options?.pathspec ?? []), cwd, "index", "generic", parseLsFiles);
20264
22748
  })
20265
22749
  };
20266
22750
  };
@@ -20272,17 +22756,23 @@ const make = (spawner) => {
20272
22756
  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.`));
20273
22757
  /**
20274
22758
  * Typed git introspection over core's `ChildProcessSpawner`: read a
20275
- * repository's state at any ref without checking it out, plus the mutating
20276
- * tier (`checkout`, `fetch`, `fetchAny`, `submoduleUpdate`, `submoduleAdd`,
20277
- * `sparseCheckoutSet`, `configSet`, `add`) that changes it.
22759
+ * repository's state at any ref without checking it out (including the
22760
+ * network read `lsRemote` and the index read `lsFiles`), plus the mutating
22761
+ * tier checkout/fetch, the working-tree restore trio and stash, branches
22762
+ * and tags, remotes, worktrees, commit/push/pull, submodules,
22763
+ * sparse-checkout, config writes and staging — that changes it. Every
22764
+ * mutating method's TSDoc opens with the literal word `Mutating:`.
20278
22765
  *
20279
22766
  * @remarks
20280
22767
  * Every method takes `cwd` explicitly and classifies git's stderr/exit-code
20281
22768
  * taxonomy exactly once, in this module's private `classify` step — a
20282
22769
  * spawn-level `PlatformError` and `Cause.TimeoutError` never escape a `Git`
20283
22770
  * method; every failure surfaces as {@link GitCommandError},
20284
- * {@link NotARepositoryError}, or {@link UnknownRefError}, or degrades to
20285
- * the documented non-error (`Option.none`, `false`).
22771
+ * {@link NotARepositoryError}, {@link UnknownRefError}, or one of the three
22772
+ * consumer-branchable classifications ({@link NonFastForwardError} from
22773
+ * `push`; {@link MergeConflictError} and {@link DirtyWorktreeError} from the
22774
+ * merge-shaped `pull` / `stashPop` / `stashApply`), or degrades to the
22775
+ * documented non-error (`Option.none`, `false`, the empty array).
20286
22776
  *
20287
22777
  * Every method whose TSDoc opens "Mutating:" changes the working tree,
20288
22778
  * `HEAD`, the index, the repository config, the object database and
@@ -20291,6 +22781,12 @@ const notStubbed = (method) => () => effect.Effect.die(/* @__PURE__ */ new Error
20291
22781
  * that — a caller running two mutating calls (or a mutating call alongside a
20292
22782
  * read) against one `cwd` at once owns the race.
20293
22783
  *
22784
+ * **Redaction policy (documented, not just convention).** Error values
22785
+ * persist only the constructor's REDACTED argv (see `GitCommandError.args`),
22786
+ * and span annotations carry stable identifiers only — `cwd`, refs, keys,
22787
+ * paths, remote names — never config values and never URLs, which can embed
22788
+ * userinfo. A new method must follow both halves before it ships.
22789
+ *
20294
22790
  * @public
20295
22791
  */
20296
22792
  var Git = class Git extends effect.Context.Service()("@effected/git/Git") {
@@ -20305,7 +22801,7 @@ var Git = class Git extends effect.Context.Service()("@effected/git/Git") {
20305
22801
  *
20306
22802
  * @remarks
20307
22803
  * Unlike `WorkspaceDiscovery.makeTest`, **no method here has an honest
20308
- * default** — the shape is twenty-six unrelated git operations, and a
22804
+ * default** — the shape is unrelated git operations, and a
20309
22805
  * fabricated answer for any of them (an empty tree, a made-up sha, a silent
20310
22806
  * no-op `checkout`) would leak into consumer logic as fact. So every
20311
22807
  * unstubbed method fails loudly as a defect
@@ -20344,8 +22840,23 @@ var Git = class Git extends effect.Context.Service()("@effected/git/Git") {
20344
22840
  checkout: notStubbed("checkout"),
20345
22841
  fetch: notStubbed("fetch"),
20346
22842
  fetchAny: notStubbed("fetchAny"),
22843
+ fetchUnshallow: notStubbed("fetchUnshallow"),
22844
+ isShallow: notStubbed("isShallow"),
22845
+ reset: notStubbed("reset"),
22846
+ clean: notStubbed("clean"),
22847
+ restore: notStubbed("restore"),
22848
+ branchCreate: notStubbed("branchCreate"),
22849
+ branchDelete: notStubbed("branchDelete"),
20347
22850
  submoduleUpdate: notStubbed("submoduleUpdate"),
20348
22851
  submoduleAdd: notStubbed("submoduleAdd"),
22852
+ submoduleStatus: notStubbed("submoduleStatus"),
22853
+ submoduleInit: notStubbed("submoduleInit"),
22854
+ submoduleDeinit: notStubbed("submoduleDeinit"),
22855
+ submoduleSync: notStubbed("submoduleSync"),
22856
+ submoduleSetUrl: notStubbed("submoduleSetUrl"),
22857
+ submoduleSetBranch: notStubbed("submoduleSetBranch"),
22858
+ submoduleAbsorbgitdirs: notStubbed("submoduleAbsorbgitdirs"),
22859
+ submoduleForeach: notStubbed("submoduleForeach"),
20349
22860
  sparseCheckoutSet: notStubbed("sparseCheckoutSet"),
20350
22861
  configSet: notStubbed("configSet"),
20351
22862
  add: notStubbed("add"),
@@ -20360,6 +22871,34 @@ var Git = class Git extends effect.Context.Service()("@effected/git/Git") {
20360
22871
  remoteUrl: notStubbed("remoteUrl"),
20361
22872
  commitInfo: notStubbed("commitInfo"),
20362
22873
  status: notStubbed("status"),
22874
+ lsRemote: notStubbed("lsRemote"),
22875
+ remoteAdd: notStubbed("remoteAdd"),
22876
+ remoteRemove: notStubbed("remoteRemove"),
22877
+ remoteSetUrl: notStubbed("remoteSetUrl"),
22878
+ stashPush: notStubbed("stashPush"),
22879
+ stashPop: notStubbed("stashPop"),
22880
+ stashApply: notStubbed("stashApply"),
22881
+ stashDrop: notStubbed("stashDrop"),
22882
+ stashList: notStubbed("stashList"),
22883
+ branchList: notStubbed("branchList"),
22884
+ tagCreate: notStubbed("tagCreate"),
22885
+ tagDelete: notStubbed("tagDelete"),
22886
+ tagList: notStubbed("tagList"),
22887
+ forEachRef: notStubbed("forEachRef"),
22888
+ revList: notStubbed("revList"),
22889
+ commit: notStubbed("commit"),
22890
+ push: notStubbed("push"),
22891
+ pull: notStubbed("pull"),
22892
+ configList: notStubbed("configList"),
22893
+ configGetAll: notStubbed("configGetAll"),
22894
+ configUnset: notStubbed("configUnset"),
22895
+ rm: notStubbed("rm"),
22896
+ mv: notStubbed("mv"),
22897
+ checkIgnore: notStubbed("checkIgnore"),
22898
+ worktreeAdd: notStubbed("worktreeAdd"),
22899
+ worktreeList: notStubbed("worktreeList"),
22900
+ worktreeRemove: notStubbed("worktreeRemove"),
22901
+ lsFiles: notStubbed("lsFiles"),
20363
22902
  ...overrides
20364
22903
  });
20365
22904
  /**
@@ -20388,7 +22927,7 @@ var Git = class Git extends effect.Context.Service()("@effected/git/Git") {
20388
22927
  static layerTest = (overrides = {}) => effect.Layer.succeed(Git, Git.makeTest(overrides));
20389
22928
  };
20390
22929
  //#endregion
20391
- //#region ../../node_modules/.pnpm/@effected+workspaces@0.9.5_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/ChangeDetector.js
22930
+ //#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
20392
22931
  /**
20393
22932
  * Which git refs to compare, and whether to fold in the working tree.
20394
22933
  *
@@ -20644,7 +23183,7 @@ function resolveFromCatalog(catalogs, wantedDependency) {
20644
23183
  };
20645
23184
  }
20646
23185
  //#endregion
20647
- //#region ../../node_modules/.pnpm/@effected+workspaces@0.9.5_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/internal/catalogs.js
23186
+ //#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
20648
23187
  /** Project a pnpm-workspace manifest's `catalog` / `catalogs` fields into a `Catalogs` map. */
20649
23188
  const inlineCatalogs = (manifest) => {
20650
23189
  if (manifest.catalog === void 0 && manifest.catalogs === void 0) return {};
@@ -20708,7 +23247,7 @@ const rangeOf = (catalogs, dependency, specifier) => {
20708
23247
  });
20709
23248
  };
20710
23249
  //#endregion
20711
- //#region ../../node_modules/.pnpm/@effected+workspaces@0.9.5_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/ConfigDependencyHooks.js
23250
+ //#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
20712
23251
  /** Whether `value` is a non-null, non-array object. */
20713
23252
  const isObject$2 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
20714
23253
  /**
@@ -20801,6 +23340,141 @@ const updateConfigOf = (mod) => {
20801
23340
  }
20802
23341
  };
20803
23342
  /**
23343
+ * The subprocess replay program {@link ConfigDependencyHooks.layerSubprocess}
23344
+ * hands to `node --input-type=module -e`.
23345
+ *
23346
+ * @remarks
23347
+ * A **static** string constant, deliberately: a bundler compiles a *computed*
23348
+ * dynamic `import()` into a context module that cannot resolve a runtime path
23349
+ * (`Cannot find module 'file:///…'`), so the computed import has to run in a
23350
+ * child process whose program text carries **no interpolated runtime value** —
23351
+ * the workspace root, the seed and the dependency names all arrive via argv
23352
+ * (`process.argv.slice(1)` under `-e`), never spliced into the script.
23353
+ *
23354
+ * The script mirrors this module's in-process semantics exactly so the two
23355
+ * layers are drop-in interchangeable: `pnpmfile.mjs` before `pnpmfile.cjs`
23356
+ * (pnpm 11's loader order), the `ERR_MODULE_NOT_FOUND`-for-the-candidate-itself
23357
+ * skip discrimination (`err.url` equality), the same hook-locator shapes, the
23358
+ * same tolerant threading of returned data (`configOf` / `finiteNumberOr` /
23359
+ * `stringArrayOr` clones below), and the same synchronous hook call. Only the
23360
+ * *mechanism* failures are reported: the script prints one final line of JSON —
23361
+ * `{ ok: true, config }` on success, `{ ok: false, name, message, stack? }`
23362
+ * naming the offending dependency on a load/replay failure — and exits through
23363
+ * the write callback so the payload is flushed even if a hook left the event
23364
+ * loop occupied. The final-line framing tolerates a hook's own `console.log`
23365
+ * noise on stdout.
23366
+ */
23367
+ const REPLAY_SCRIPT = `
23368
+ const [root, seedJson, ...names] = process.argv.slice(1);
23369
+ const { pathToFileURL } = await import("node:url");
23370
+ const { join } = await import("node:path");
23371
+ const isObject = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
23372
+ const finiteNumberOr = (value, fallback) => (typeof value === "number" && Number.isFinite(value) ? value : fallback);
23373
+ const stringArrayOr = (value, fallback) =>
23374
+ Array.isArray(value) && value.every((entry) => typeof entry === "string") ? value : fallback;
23375
+ const configOf = (value, fallback) =>
23376
+ isObject(value)
23377
+ ? {
23378
+ catalog: isObject(value.catalog) ? value.catalog : fallback.catalog,
23379
+ catalogs: isObject(value.catalogs) ? value.catalogs : fallback.catalogs,
23380
+ minimumReleaseAge: finiteNumberOr(value.minimumReleaseAge, fallback.minimumReleaseAge),
23381
+ minimumReleaseAgeExclude: stringArrayOr(value.minimumReleaseAgeExclude, fallback.minimumReleaseAgeExclude),
23382
+ }
23383
+ : fallback;
23384
+ const failure = (name, cause) => ({
23385
+ ok: false,
23386
+ name,
23387
+ message: cause instanceof Error ? cause.message : String(cause),
23388
+ ...(cause instanceof Error && typeof cause.stack === "string" ? { stack: cause.stack } : {}),
23389
+ });
23390
+ const replay = async () => {
23391
+ let catalog = {};
23392
+ const catalogs = {};
23393
+ for (const [name, entries] of Object.entries(JSON.parse(seedJson))) {
23394
+ if (name === "default") catalog = { ...entries };
23395
+ else catalogs[name] = { ...entries };
23396
+ }
23397
+ let config = { catalog, catalogs, minimumReleaseAge: undefined, minimumReleaseAgeExclude: undefined };
23398
+ for (const name of names) {
23399
+ let loaded;
23400
+ let found = false;
23401
+ for (const filename of ["pnpmfile.mjs", "pnpmfile.cjs"]) {
23402
+ const candidate = pathToFileURL(join(root, "node_modules", ".pnpm-config", name, filename)).href;
23403
+ try {
23404
+ loaded = await import(candidate);
23405
+ found = true;
23406
+ break;
23407
+ } catch (cause) {
23408
+ const url =
23409
+ isObject(cause) && cause.code === "ERR_MODULE_NOT_FOUND" && typeof cause.url === "string"
23410
+ ? cause.url
23411
+ : undefined;
23412
+ if (url === candidate) continue;
23413
+ return failure(name, cause);
23414
+ }
23415
+ }
23416
+ if (!found) continue;
23417
+ let hook;
23418
+ for (const candidate of [loaded, isObject(loaded) ? loaded.default : undefined]) {
23419
+ if (!isObject(candidate)) continue;
23420
+ if (isObject(candidate.hooks) && typeof candidate.hooks.updateConfig === "function") {
23421
+ hook = candidate.hooks.updateConfig;
23422
+ break;
23423
+ }
23424
+ if (typeof candidate.updateConfig === "function") {
23425
+ hook = candidate.updateConfig;
23426
+ break;
23427
+ }
23428
+ }
23429
+ if (hook === undefined) continue;
23430
+ try {
23431
+ config = configOf(hook(config), config);
23432
+ } catch (cause) {
23433
+ return failure(name, cause);
23434
+ }
23435
+ }
23436
+ return { ok: true, config };
23437
+ };
23438
+ const payload = await replay();
23439
+ process.stdout.write("\\n" + JSON.stringify(payload) + "\\n", () => process.exit(0));
23440
+ `;
23441
+ /**
23442
+ * The ceiling on one subprocess replay. A config dependency's `updateConfig`
23443
+ * reads and rewrites a config object — no install work, no network — so thirty
23444
+ * seconds is generous. Without a ceiling a pnpmfile that loops or awaits a
23445
+ * promise that never settles hangs `inject`, and through it the one memoized
23446
+ * {@link WorkspaceCatalogs} assemble pass every catalog read blocks on. Expiry
23447
+ * kills the child (`Run` scopes it) and surfaces as a `CommandFailedError`
23448
+ * through the same typed transport-failure path as any other mechanism failure.
23449
+ */
23450
+ const REPLAY_TIMEOUT = effect.Duration.seconds(30);
23451
+ /**
23452
+ * The subprocess protocol payload — a single JSON line near the end of the
23453
+ * child's stdout, framed and parsed by `Run.jsonLine`, which scans lines from
23454
+ * the end for the first that decodes (so a hook logging after the payload —
23455
+ * e.g. from `process.on("exit", ...)` — cannot displace it). The `ok`
23456
+ * discriminant is what keeps an accidental log line from satisfying the
23457
+ * envelope. The envelope is strict (a payload without a usable
23458
+ * `ok` discriminant is a mechanism failure, typed); the `config` slice inside a
23459
+ * success stays `Unknown` because a hook's returned *data* is tolerantly
23460
+ * threaded (`configOf`), never fatal.
23461
+ */
23462
+ const ReplayPayload = effect.Schema.Union([effect.Schema.Struct({
23463
+ ok: effect.Schema.Literal(true),
23464
+ config: effect.Schema.Unknown
23465
+ }), effect.Schema.Struct({
23466
+ ok: effect.Schema.Literal(false),
23467
+ name: effect.Schema.optionalKey(effect.Schema.String),
23468
+ message: effect.Schema.optionalKey(effect.Schema.String),
23469
+ stack: effect.Schema.optionalKey(effect.Schema.String)
23470
+ })]);
23471
+ /** Rebuild the subprocess's serialized failure as an `Error`, preserving the child-side stack when it carried one. */
23472
+ const replayFailureCause = (payload) => {
23473
+ const error = new Error(payload.message ?? "config dependency hook replay failed");
23474
+ if (payload.stack !== void 0) error.stack = payload.stack;
23475
+ return error;
23476
+ };
23477
+ /**
20804
23478
  * Replays a workspace's `configDependencies` `updateConfig` hooks over the inline
20805
23479
  * catalogs — the opt-in seam that lets hook-injected catalogs participate in
20806
23480
  * assembly.
@@ -20893,9 +23567,98 @@ var ConfigDependencyHooks = class ConfigDependencyHooks extends effect.Context.S
20893
23567
  releaseAge: releaseAgeOf(config)
20894
23568
  };
20895
23569
  }) });
23570
+ /**
23571
+ * The subprocess layer: replays each config dependency's pnpmfile in a `node`
23572
+ * child process instead of an in-process dynamic `import()`, with identical
23573
+ * typed semantics to {@link ConfigDependencyHooks.layerLive} — the two are
23574
+ * drop-in interchangeable.
23575
+ *
23576
+ * @remarks
23577
+ * `layerLive` computes the `import()` path at runtime, and a bundler (rspack,
23578
+ * for one) compiles a *computed* dynamic import into a context module that
23579
+ * throws `Cannot find module 'file:///…'` at runtime — so in any bundled
23580
+ * consumer, a GitHub Action above all, the in-process replay is unreachable.
23581
+ * This layer keeps every computed load out of the bundle graph: the replay
23582
+ * program is a **static** string constant passed via argv
23583
+ * (`node --input-type=module -e <script> <root> <seed> <...names>`), and the
23584
+ * child process performs the computed imports where no bundler rewrote them.
23585
+ * A subprocess also keeps config-dependency code out of the consumer's own
23586
+ * process.
23587
+ *
23588
+ * The contract's semantics are unchanged, not the downstream fail-open shape:
23589
+ * an empty `configDependencies` returns the seed without spawning anything; a
23590
+ * `..` path segment in a dependency name fails typed **before** any spawn; a
23591
+ * missing pnpmfile (neither `.mjs` nor `.cjs`) is the one legitimate skip,
23592
+ * discriminated inside the child by `err.url` equality exactly as
23593
+ * `layerLive` discriminates in process; any other load failure — a syntax
23594
+ * error, a throwing top level, an `ERR_MODULE_NOT_FOUND` for a module the
23595
+ * pnpmfile itself imports — and a hook that throws when called are serialized
23596
+ * back per-name and surface typed as a `hooks`-source `CatalogAssemblyError`
23597
+ * naming that dependency. A hook's returned *data* stays tolerantly threaded
23598
+ * (last well-formed write wins), never fatal. Spawn and transport failures —
23599
+ * `node` absent, a non-zero exit without a result payload, unparseable
23600
+ * output — fail typed too, never a defect and never a silent skip.
23601
+ *
23602
+ * Two bounds this layer imposes that `layerLive` cannot: the replay is
23603
+ * given thirty seconds (a pnpmfile that loops or awaits forever fails typed
23604
+ * instead of hanging the memoized assemble pass — a subprocess is killable,
23605
+ * while `layerLive`'s in-process synchronous hook call is not interruptible
23606
+ * by any means, so the asymmetry is inherent, not a parity violation), and
23607
+ * the child's stdout is captured under `Run.jsonLine`'s 16 MiB default
23608
+ * ceiling (a hook that logs more than that fails typed as `tooLarge`, where
23609
+ * `layerLive` — which captures nothing — would succeed).
23610
+ *
23611
+ * Catalog folding and normalization stay in the **parent** (the same
23612
+ * `@pnpm/catalogs`-derived path `layerLive` uses); the child returns only the
23613
+ * raw threaded config slice, since the script cannot import kit code.
23614
+ *
23615
+ * Requires core's `ChildProcessSpawner`, resolved when the layer is built —
23616
+ * the consumer provides it once at the edge (`@effect/platform-node`'s
23617
+ * `NodeServices.layer`), the same discharge `@effected/git` uses. Wired by
23618
+ * `WorkspaceCatalogs.layerWithConfigDependenciesSubprocess` /
23619
+ * `Workspaces.layerWithConfigDependenciesSubprocess`.
23620
+ */
23621
+ static layerSubprocess = effect.Layer.effect(ConfigDependencyHooks, effect.Effect.gen(function* () {
23622
+ const spawner = yield* effect_unstable_process.ChildProcessSpawner.ChildProcessSpawner;
23623
+ return { inject: (root, configDependencies, seed) => effect.Effect.gen(function* () {
23624
+ const names = Object.keys(configDependencies);
23625
+ if (names.length === 0) return {
23626
+ catalogs: seed,
23627
+ releaseAge: {}
23628
+ };
23629
+ for (const name of names) if (hasTraversalSegment(name)) return yield* effect.Effect.fail(new CatalogAssemblyError({
23630
+ source: "hooks",
23631
+ path: name,
23632
+ cause: /* @__PURE__ */ new Error(`config dependency name has a '..' path segment: ${name}`)
23633
+ }));
23634
+ const command = effect_unstable_process.ChildProcess.make("node", [
23635
+ "--input-type=module",
23636
+ "-e",
23637
+ REPLAY_SCRIPT,
23638
+ root,
23639
+ JSON.stringify(seed),
23640
+ ...names
23641
+ ]);
23642
+ const payload = yield* Run.jsonLine(command, ReplayPayload, { timeout: REPLAY_TIMEOUT }).pipe(effect.Effect.provideService(effect_unstable_process.ChildProcessSpawner.ChildProcessSpawner, spawner), effect.Effect.catch((cause) => effect.Effect.fail(new CatalogAssemblyError({
23643
+ source: "hooks",
23644
+ path: root,
23645
+ cause
23646
+ }))));
23647
+ if (payload.ok === false) return yield* effect.Effect.fail(new CatalogAssemblyError({
23648
+ source: "hooks",
23649
+ path: payload.name ?? root,
23650
+ cause: replayFailureCause(payload)
23651
+ }));
23652
+ const config = configOf(payload.config, seedToConfig(seed));
23653
+ return {
23654
+ catalogs: configToEntries(config),
23655
+ releaseAge: releaseAgeOf(config)
23656
+ };
23657
+ }) };
23658
+ }));
20896
23659
  };
20897
23660
  //#endregion
20898
- //#region ../../node_modules/.pnpm/@effected+workspaces@0.9.5_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/PackageManagerName.js
23661
+ //#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
20899
23662
  /**
20900
23663
  * The four package managers this package understands.
20901
23664
  *
@@ -21223,7 +23986,7 @@ var PackageManagerDetector = class PackageManagerDetector extends effect.Context
21223
23986
  static layerTest = (overrides = {}) => effect.Layer.succeed(PackageManagerDetector, PackageManagerDetector.makeTest(overrides));
21224
23987
  };
21225
23988
  //#endregion
21226
- //#region ../../node_modules/.pnpm/@effected+workspaces@0.9.5_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/LockfileReader.js
23989
+ //#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
21227
23990
  /**
21228
23991
  * Raised when the workspace's lockfile cannot be read off disk.
21229
23992
  *
@@ -21403,7 +24166,7 @@ var LockfileReader = class LockfileReader extends effect.Context.Service()("@eff
21403
24166
  static layerTest = (overrides = {}) => effect.Layer.succeed(LockfileReader, LockfileReader.makeTest(overrides));
21404
24167
  };
21405
24168
  //#endregion
21406
- //#region ../../node_modules/.pnpm/@effected+workspaces@0.9.5_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/Publishability.js
24169
+ //#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
21407
24170
  /** The public npm registry, used when `publishConfig.registry` says nothing. */
21408
24171
  const DEFAULT_REGISTRY = "https://registry.npmjs.org/";
21409
24172
  /**
@@ -21562,7 +24325,7 @@ var PublishabilityDetector = class extends effect.Context.Service()("@effected/w
21562
24325
  static layerNone = effect.Layer.succeed(this, this.none);
21563
24326
  };
21564
24327
  //#endregion
21565
- //#region ../../node_modules/.pnpm/@effected+workspaces@0.9.5_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/internal/importerVersions.js
24328
+ //#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
21566
24329
  /**
21567
24330
  * Strip pnpm's peer-disambiguation suffix from a recorded importer version.
21568
24331
  *
@@ -21648,7 +24411,7 @@ const unanimousVersionOf = (index, dependency) => {
21648
24411
  return agreed;
21649
24412
  };
21650
24413
  //#endregion
21651
- //#region ../../node_modules/.pnpm/@effected+workspaces@0.9.5_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/WorkspaceCatalogs.js
24414
+ //#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
21652
24415
  /**
21653
24416
  * An immutable, fully-normalized catalog collection — the one catalog
21654
24417
  * resolution semantic in the package.
@@ -22069,6 +24832,24 @@ var WorkspaceCatalogs = class WorkspaceCatalogs extends effect.Context.Service()
22069
24832
  */
22070
24833
  static layerWithConfigDependencies = (options) => effect.Layer.effect(WorkspaceCatalogs, WorkspaceCatalogs.make(options)).pipe(effect.Layer.provide(ConfigDependencyHooks.layerLive));
22071
24834
  /**
24835
+ * The opt-in layer that replays config-dependency `pnpmfile` hooks in a
24836
+ * `node` **child process**: it wires
24837
+ * {@link ConfigDependencyHooks.layerSubprocess} in place of the in-process
24838
+ * `layerLive`.
24839
+ *
24840
+ * @remarks
24841
+ * Same typed semantics as {@link WorkspaceCatalogs.layerWithConfigDependencies}
24842
+ * — the two hook layers are drop-in interchangeable — but the replay's
24843
+ * computed dynamic `import()` runs in the subprocess, so it survives bundling
24844
+ * (a bundler compiles a computed in-process `import()` into a context module
24845
+ * that cannot resolve at runtime — every bundled GitHub Action hits this).
24846
+ * The cost is one extra requirement: core's `ChildProcessSpawner`, provided
24847
+ * once at the edge (`@effect/platform-node`'s `NodeServices.layer`) — the
24848
+ * same sanctioned R-widening as `Workspaces.layerWithGit`. Parameterized, so
24849
+ * bind it to a `const` and reuse it.
24850
+ */
24851
+ static layerWithConfigDependenciesSubprocess = (options) => effect.Layer.effect(WorkspaceCatalogs, WorkspaceCatalogs.make(options)).pipe(effect.Layer.provide(ConfigDependencyHooks.layerSubprocess));
24852
+ /**
22072
24853
  * A test double satisfying the full {@link WorkspaceCatalogsShape} with no
22073
24854
  * filesystem, lockfile read, or hook replay.
22074
24855
  *
@@ -22157,7 +24938,7 @@ var WorkspaceCatalogs = class WorkspaceCatalogs extends effect.Context.Service()
22157
24938
  }));
22158
24939
  };
22159
24940
  //#endregion
22160
- //#region ../../node_modules/.pnpm/@effected+workspaces@0.9.5_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/WorkspaceStateSnapshot.js
24941
+ //#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
22161
24942
  const EMPTY = Object.freeze(Object.create(null));
22162
24943
  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)));
22163
24944
  /**
@@ -22380,7 +25161,7 @@ var WorkspaceStateSnapshot = class extends effect.Schema.Class("WorkspaceStateSn
22380
25161
  }
22381
25162
  };
22382
25163
  //#endregion
22383
- //#region ../../node_modules/.pnpm/@effected+workspaces@0.9.5_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/WorkspaceSnapshots.js
25164
+ //#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
22384
25165
  /** Whether `value` is a non-null, non-array object. */
22385
25166
  const isObject = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
22386
25167
  /** Whether every value in a record is a string — a usable dependency map. */
@@ -22657,7 +25438,7 @@ var WorkspaceSnapshots = class WorkspaceSnapshots extends effect.Context.Service
22657
25438
  static layerTest = (overrides = {}) => effect.Layer.succeed(WorkspaceSnapshots, WorkspaceSnapshots.makeTest(overrides));
22658
25439
  };
22659
25440
  //#endregion
22660
- //#region ../../node_modules/.pnpm/@effected+workspaces@0.9.5_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/Workspaces.js
25441
+ //#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
22661
25442
  const compose = (options, catalogsFactory) => {
22662
25443
  const roots = WorkspaceRoot.layer;
22663
25444
  const detector = PackageManagerDetector.layer;
@@ -22674,6 +25455,7 @@ const layerWithGit = (options) => {
22674
25455
  };
22675
25456
  const resolvers = effect.Layer.mergeAll(WorkspaceCatalogs.catalogResolver, WorkspaceDiscovery.workspaceResolver);
22676
25457
  const layerWithConfigDependencies = (options) => compose(options, WorkspaceCatalogs.layerWithConfigDependencies);
25458
+ const layerWithConfigDependenciesSubprocess = (options) => compose(options, WorkspaceCatalogs.layerWithConfigDependenciesSubprocess);
22677
25459
  const resolverLayer = (options) => resolvers.pipe(effect.Layer.provide(layerWithConfigDependencies(options)));
22678
25460
  const resolveManifest = effect.Effect.fn("Workspaces.resolveManifest")(function* (manifest, options) {
22679
25461
  return yield* manifest.resolve().pipe(effect.Effect.provide(resolverLayer(options)));
@@ -22755,6 +25537,32 @@ var Workspaces = class {
22755
25537
  */
22756
25538
  static layerWithConfigDependencies = layerWithConfigDependencies;
22757
25539
  /**
25540
+ * The git-free composite with config-dependency hook replay in a `node`
25541
+ * **child process** —
25542
+ * {@link WorkspaceCatalogs.layerWithConfigDependenciesSubprocess} in place of
25543
+ * the in-process replay.
25544
+ *
25545
+ * @remarks
25546
+ * Same typed semantics as {@link Workspaces.layerWithConfigDependencies}; the
25547
+ * difference is mechanism, and it matters in exactly one environment class: a
25548
+ * **bundled** consumer. The in-process replay's computed dynamic `import()`
25549
+ * is compiled by bundlers (rspack among them) into a context module that
25550
+ * throws `Cannot find module 'file:///…'` at runtime, which makes
25551
+ * `WorkspaceCatalogs.releaseAgeGate()` unreachable from any bundled GitHub
25552
+ * Action. Here the computed import runs inside a `node` child process whose
25553
+ * program text is a static string handed over argv, so nothing computed
25554
+ * enters the bundle graph.
25555
+ *
25556
+ * The extra requirement is core's `ChildProcessSpawner`, provided once at
25557
+ * the edge (`@effect/platform-node`'s `NodeServices.layer`) — the same
25558
+ * sanctioned R-widening as {@link Workspaces.layerWithGit}, and the reason
25559
+ * this is a separate composite rather than a flag: a consumer that keeps the
25560
+ * in-process replay should not have to be able to spawn a subprocess.
25561
+ *
25562
+ * **Bind the result to a `const`.**
25563
+ */
25564
+ static layerWithConfigDependenciesSubprocess = layerWithConfigDependenciesSubprocess;
25565
+ /**
22758
25566
  * The git-free composite plus {@link ChangeDetector} and
22759
25567
  * {@link WorkspaceSnapshots}, over `@effected/git`'s `Git` service.
22760
25568
  *
@@ -22764,7 +25572,8 @@ var Workspaces = class {
22764
25572
  * never detects changes or reads at a ref should not have to be able to
22765
25573
  * spawn a subprocess. The consumer provides `ChildProcessSpawner` once at
22766
25574
  * the edge (`@effect/platform-node`'s `NodeServices.layer`); a test
22767
- * provides `Layer.succeed(Git, …)` and needs no repository on disk.
25575
+ * provides `Git.layerTest({ })` git's own shipped double, whose
25576
+ * unstubbed members die named — and needs no repository on disk.
22768
25577
  */
22769
25578
  static layerWithGit = layerWithGit;
22770
25579
  /**
@@ -22813,9 +25622,14 @@ var Workspaces = class {
22813
25622
  * import { Workspaces } from "@effected/workspaces";
22814
25623
  * import { Layer } from "effect";
22815
25624
  *
25625
+ * // Bound to consts per the warning above: each factory call mints a
25626
+ * // fresh layer reference, and layers memoize by reference.
25627
+ * const LocalExecLayer = Workspaces.localExecLayer();
25628
+ * const WorkspacesLayer = Workspaces.layer();
25629
+ *
22816
25630
  * const AppLayer = ToolDiscovery.layer.pipe(
22817
- * Layer.provide(Workspaces.localExecLayer()),
22818
- * Layer.provide(Workspaces.layer()),
25631
+ * Layer.provide(LocalExecLayer),
25632
+ * Layer.provide(WorkspacesLayer),
22819
25633
  * Layer.provide(NodeServices.layer),
22820
25634
  * );
22821
25635
  * ```