@node9/proxy 2.43.0 → 2.43.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -5483,7 +5483,10 @@ function classify(inv) {
5483
5483
  out.push({ ...f, shown: inv.shown, reason: `${f.reason}: ${inv.shown}` });
5484
5484
  };
5485
5485
  if (hooksBypass(inv)) found(HOOKS_BYPASS);
5486
- if (stagesEverything(inv)) found(STAGE_ALL);
5486
+ const staged = stagesEverything(inv);
5487
+ if (staged) {
5488
+ found(staged.ifWorkTreeTop === void 0 ? STAGE_ALL : { ...STAGE_ALL, ...staged });
5489
+ }
5487
5490
  if (inv.sub === null) {
5488
5491
  found(UNREADABLE);
5489
5492
  return out;
@@ -5544,12 +5547,35 @@ function appliedValue(env, name) {
5544
5547
  const word = f?.Stmts?.[0]?.Cmd?.Args?.[1];
5545
5548
  return word ? resolveWordLiteral(word) : null;
5546
5549
  }
5550
+ function lexicalPath(p) {
5551
+ if (/^[\\/~$]/.test(p) || /^[A-Za-z]:/.test(p)) return null;
5552
+ const parts = [];
5553
+ let climbed = false;
5554
+ for (const part of p.split(/[\\/]+/)) {
5555
+ if (part === "" || part === ".") continue;
5556
+ if (part === "..") {
5557
+ if (parts.length === 0) climbed = true;
5558
+ else parts.pop();
5559
+ } else parts.push(part);
5560
+ }
5561
+ return { parts, climbed };
5562
+ }
5563
+ function hooksPathBypasses(value) {
5564
+ if (value === null || value === void 0) return true;
5565
+ const v = value.trim();
5566
+ if (v === "" || v === "true") return true;
5567
+ const lp = lexicalPath(v);
5568
+ if (lp === null || lp.climbed || lp.parts.length === 0) return true;
5569
+ return lp.parts[0] === ".git" && lp.parts[1] !== "hooks";
5570
+ }
5547
5571
  function hooksBypass(inv) {
5548
- if (inv.config.has("core.hookspath")) return true;
5572
+ if (inv.config.has("core.hookspath") && hooksPathBypasses(inv.config.get("core.hookspath")))
5573
+ return true;
5549
5574
  for (const [name, value] of inv.env) {
5550
5575
  if (name === "GIT_CONFIG_PARAMETERS" && value !== null && /core\.hookspath/i.test(value))
5551
5576
  return true;
5552
- if (/^GIT_CONFIG_KEY_\d+$/.test(name) && value !== null && value.toLowerCase() === "core.hookspath")
5577
+ const key = /^GIT_CONFIG_KEY_(\d+)$/.exec(name);
5578
+ if (key && value !== null && value.toLowerCase() === "core.hookspath" && hooksPathBypasses(inv.env.get(`GIT_CONFIG_VALUE_${key[1]}`)))
5553
5579
  return true;
5554
5580
  }
5555
5581
  for (const name of HOOK_KILL_SWITCHES) {
@@ -5591,7 +5617,10 @@ function configWritesHooksPath(args) {
5591
5617
  }
5592
5618
  const key = args[i];
5593
5619
  if (key === null || key === void 0 || key.toLowerCase() !== "core.hookspath") return false;
5594
- return write2 || i + 1 < args.length;
5620
+ const unset = args.slice(0, i).some((w) => w === "--unset" || w === "--unset-all") || args[0] === "unset";
5621
+ if (unset) return true;
5622
+ if (i + 1 < args.length) return hooksPathBypasses(args[i + 1]);
5623
+ return write2;
5595
5624
  }
5596
5625
  function isHookPath(word) {
5597
5626
  return /(^|[\\/])(\.git[\\/]hooks|\.husky)([\\/]|$)/.test(word);
@@ -5626,31 +5655,49 @@ function chmodDisarmsHook(args, shown) {
5626
5655
  function wholeTree(operand) {
5627
5656
  if (/^:\(top\)\.?$/.test(operand) || operand === ":/" || operand === "*") return true;
5628
5657
  if (operand.startsWith(":")) return false;
5658
+ const lp = lexicalPath(operand);
5659
+ return lp !== null && lp.parts.length === 0;
5660
+ }
5661
+ function chdirPrefix(inv) {
5662
+ const dirs = inv.chdir ?? [];
5663
+ if (dirs.length === 0) return null;
5629
5664
  const parts = [];
5630
- for (const part of operand.split("/")) {
5631
- if (!part || part === ".") continue;
5632
- if (part === "..") parts.pop();
5633
- else parts.push(part);
5665
+ for (const d of dirs) {
5666
+ if (d === null || d === "") return null;
5667
+ const lp = lexicalPath(d);
5668
+ if (lp === null || lp.climbed) return null;
5669
+ parts.push(...lp.parts);
5634
5670
  }
5635
- return parts.length === 0 && !operand.startsWith("/");
5671
+ return parts.length === 0 ? null : parts.join("/");
5636
5672
  }
5637
5673
  function stagesEverything(inv) {
5638
5674
  const sub = inv.sub?.toLowerCase();
5675
+ const prefix = chdirPrefix(inv);
5676
+ const judge = (operands2) => {
5677
+ let conditional = false;
5678
+ for (const operand of operands2) {
5679
+ if (!wholeTree(operand)) continue;
5680
+ if (prefix === null || operand.startsWith(":") || operand.startsWith("/")) return {};
5681
+ if (wholeTree(`${prefix}/${operand === "*" ? "." : operand}`)) return {};
5682
+ conditional = true;
5683
+ }
5684
+ return conditional && prefix !== null ? { ifWorkTreeTop: prefix } : null;
5685
+ };
5639
5686
  if (sub === "add") {
5640
5687
  const o = parseOptions(inv.args, "", ADD_LONG_VALUE);
5641
5688
  if (o.flags.has("-n") || o.flags.has("--dry-run") || o.flags.has("-i") || o.flags.has("--interactive") || o.flags.has("-p") || o.flags.has("--patch") || o.flags.has("-e") || o.flags.has("--edit"))
5642
- return false;
5689
+ return null;
5643
5690
  const all = o.flags.has("-A") || o.flags.has("--all") || o.flags.has("--no-ignore-removal") || o.flags.has("-u") || o.flags.has("--update");
5644
- if (all && o.operands.length === 0) return true;
5645
- return o.operands.some(wholeTree);
5691
+ if (all && o.operands.length === 0) return {};
5692
+ return judge(o.operands);
5646
5693
  }
5647
5694
  if (sub === "commit") {
5648
5695
  const o = parseOptions(inv.args, "mFCcut", COMMIT_LONG_VALUE);
5649
- if (o.flags.has("--dry-run")) return false;
5650
- if (o.flags.has("-a") || o.flags.has("--all")) return true;
5651
- return o.operands.some(wholeTree);
5696
+ if (o.flags.has("--dry-run")) return null;
5697
+ if (o.flags.has("-a") || o.flags.has("--all")) return {};
5698
+ return judge(o.operands);
5652
5699
  }
5653
- return false;
5700
+ return null;
5654
5701
  }
5655
5702
  function hookTextRunsNothing(text) {
5656
5703
  return text.split(/\r?\n/).every((line) => INERT_LINE_RE.test(line.trim()));
@@ -7703,7 +7750,7 @@ async function evaluatePolicy(config, toolName, args, context = {}, hostHooks =
7703
7750
  }
7704
7751
  async function evaluatePolicyCore(config, toolName, args, context = {}, hooks = {}) {
7705
7752
  const { agent, cwd, activeEnvironment } = context;
7706
- const { checkProvenance: checkProvenance2, isTrustedHost: isTrustedHost2, isConfiguredRegistry } = hooks;
7753
+ const { checkProvenance: checkProvenance2, isTrustedHost: isTrustedHost2, isConfiguredRegistry, isGitWorkTreeTop: isGitWorkTreeTop2 } = hooks;
7707
7754
  const settingsView = catalogSettings(config);
7708
7755
  const layers = inspectionLayers(config.policy);
7709
7756
  const cv = (id) => checkValue(settingsView, id);
@@ -7857,6 +7904,8 @@ async function evaluatePolicyCore(config, toolName, args, context = {}, hooks =
7857
7904
  const action = cv(id);
7858
7905
  const finding = action === "off" ? void 0 : git.findings.find((f) => f.checkId === id);
7859
7906
  if (!finding) continue;
7907
+ if (finding.ifWorkTreeTop !== void 0 && isGitWorkTreeTop2 && cwd && !isGitWorkTreeTop2(finding.ifWorkTreeTop, cwd))
7908
+ continue;
7860
7909
  const v = applyCheckValue(action, {
7861
7910
  decision: "review",
7862
7911
  blockedByLabel: `Node9 (AST): ${finding.ruleName}`,
@@ -17196,6 +17245,7 @@ zoo`.split("\n");
17196
17245
  /** The words after `git`: global options, then the subcommand. */
17197
17246
  visitGit(rest, env, depth, viaXargs, fromAlias, shown) {
17198
17247
  const config = /* @__PURE__ */ new Map();
17248
+ const chdir = [];
17199
17249
  let i = 0;
17200
17250
  while (i < rest.length) {
17201
17251
  const w = rest[i];
@@ -17210,6 +17260,7 @@ zoo`.split("\n");
17210
17260
  i++;
17211
17261
  value = i < rest.length ? rest[i] : null;
17212
17262
  }
17263
+ if (name === "-C") chdir.push(viaXargs || (value ?? "").includes("{}") ? null : value);
17213
17264
  if (name === "-c" && value !== null) {
17214
17265
  const ceq = value.indexOf("=");
17215
17266
  const key = (ceq > 0 ? value.slice(0, ceq) : value).toLowerCase();
@@ -17226,7 +17277,7 @@ zoo`.split("\n");
17226
17277
  }
17227
17278
  const subWord = i < rest.length ? rest[i] : void 0;
17228
17279
  const args = rest.slice(i + 1);
17229
- const inv = { sub: null, args, config, env, shown };
17280
+ const inv = { sub: null, args, config, env, shown, chdir };
17230
17281
  if (subWord === void 0) {
17231
17282
  if (!viaXargs) return;
17232
17283
  this.emit(inv);
@@ -17240,16 +17291,23 @@ zoo`.split("\n");
17240
17291
  const fromConfig = config.get(`alias.${subWord.toLowerCase()}`);
17241
17292
  const alias = fromConfig !== void 0 ? fromConfig : this.aliases.get(subWord);
17242
17293
  if (alias !== void 0 && !fromAlias) {
17243
- this.expandAlias(subWord, alias, args, env, depth, 0, shown);
17294
+ this.expandAlias(subWord, alias, args, env, depth, 0, shown, chdir);
17244
17295
  return;
17245
17296
  }
17246
17297
  inv.sub = subWord;
17247
17298
  this.emit(inv);
17248
17299
  this.recordAliasDefinition(inv, env, depth);
17249
17300
  }
17250
- expandAlias(name, value, args, env, depth, level, shown) {
17301
+ expandAlias(name, value, args, env, depth, level, shown, chdir) {
17251
17302
  if (value === null) {
17252
- this.emit({ sub: null, args, config: /* @__PURE__ */ new Map(), env, shown: `${shown} (alias ${name})` });
17303
+ this.emit({
17304
+ sub: null,
17305
+ args,
17306
+ config: /* @__PURE__ */ new Map(),
17307
+ env,
17308
+ shown: `${shown} (alias ${name})`,
17309
+ chdir
17310
+ });
17253
17311
  return;
17254
17312
  }
17255
17313
  if (value.startsWith("!")) {
@@ -17263,7 +17321,16 @@ zoo`.split("\n");
17263
17321
  const nested = this.aliases.get(sub);
17264
17322
  const expandedShown = `${shown} (alias ${name} = ${value})`;
17265
17323
  if (nested !== void 0 && level < MAX_ALIAS_DEPTH) {
17266
- this.expandAlias(sub, nested, [...words.slice(1), ...args], env, depth, level + 1, shown);
17324
+ this.expandAlias(
17325
+ sub,
17326
+ nested,
17327
+ [...words.slice(1), ...args],
17328
+ env,
17329
+ depth,
17330
+ level + 1,
17331
+ shown,
17332
+ chdir
17333
+ );
17267
17334
  return;
17268
17335
  }
17269
17336
  this.emit({
@@ -17271,7 +17338,8 @@ zoo`.split("\n");
17271
17338
  args: [...words.slice(1), ...args],
17272
17339
  config: /* @__PURE__ */ new Map(),
17273
17340
  env,
17274
- shown: expandedShown
17341
+ shown: expandedShown,
17342
+ chdir
17275
17343
  });
17276
17344
  }
17277
17345
  /**
@@ -17305,7 +17373,7 @@ zoo`.split("\n");
17305
17373
  if (i + 1 >= args.length) return;
17306
17374
  const value = args[i + 1];
17307
17375
  this.aliases.set(m[1], value);
17308
- this.expandAlias(m[1], value, [], env, depth, 0, `${inv.shown}`);
17376
+ this.expandAlias(m[1], value, [], env, depth, 0, `${inv.shown}`, []);
17309
17377
  }
17310
17378
  };
17311
17379
  POSITIONAL2 = "\0positional";
@@ -18851,7 +18919,7 @@ zoo`.split("\n");
18851
18919
  { view: "separators-stripped", decoder: "separators", stripped: true }
18852
18920
  ];
18853
18921
  LONG_OUTPUT_THRESHOLD_BYTES = 100 * 1024;
18854
- CANONICAL_EXTRACTOR_VERSION = "canonical-v34";
18922
+ CANONICAL_EXTRACTOR_VERSION = "canonical-v35";
18855
18923
  DEDUPE_PREVIEW_LEN = 120;
18856
18924
  ENGINE_VERSION = "1.4.0";
18857
18925
  }
@@ -22929,10 +22997,19 @@ async function evaluatePolicy2(toolName, args, agent, cwd, opts) {
22929
22997
  // reaches a long-lived in-process authorizer (the gateway) within seconds.
22930
22998
  isTrustedHost: config.policy.trustedHostsManaged ? (host2) => matchesTrustedHost(host2, config.policy.trustedHosts) : isTrustedHost,
22931
22999
  readAgentSettings,
22932
- isConfiguredRegistry: (host2, at) => configuredRegistryHosts(at).has(host2)
23000
+ isConfiguredRegistry: (host2, at) => configuredRegistryHosts(at).has(host2),
23001
+ isGitWorkTreeTop
22933
23002
  }
22934
23003
  );
22935
23004
  }
23005
+ function isGitWorkTreeTop(dir2, cwd) {
23006
+ if (!import_path13.default.isAbsolute(cwd)) return true;
23007
+ try {
23008
+ return import_fs13.default.existsSync(import_path13.default.join(import_path13.default.resolve(cwd, dir2), ".git"));
23009
+ } catch {
23010
+ return true;
23011
+ }
23012
+ }
22936
23013
  function readAgentSettings(absPath) {
22937
23014
  const r = readCappedText(
22938
23015
  absPath,
package/dist/cli.mjs CHANGED
@@ -5504,7 +5504,10 @@ function classify(inv) {
5504
5504
  out.push({ ...f, shown: inv.shown, reason: `${f.reason}: ${inv.shown}` });
5505
5505
  };
5506
5506
  if (hooksBypass(inv)) found(HOOKS_BYPASS);
5507
- if (stagesEverything(inv)) found(STAGE_ALL);
5507
+ const staged = stagesEverything(inv);
5508
+ if (staged) {
5509
+ found(staged.ifWorkTreeTop === void 0 ? STAGE_ALL : { ...STAGE_ALL, ...staged });
5510
+ }
5508
5511
  if (inv.sub === null) {
5509
5512
  found(UNREADABLE);
5510
5513
  return out;
@@ -5565,12 +5568,35 @@ function appliedValue(env, name) {
5565
5568
  const word = f?.Stmts?.[0]?.Cmd?.Args?.[1];
5566
5569
  return word ? resolveWordLiteral(word) : null;
5567
5570
  }
5571
+ function lexicalPath(p) {
5572
+ if (/^[\\/~$]/.test(p) || /^[A-Za-z]:/.test(p)) return null;
5573
+ const parts = [];
5574
+ let climbed = false;
5575
+ for (const part of p.split(/[\\/]+/)) {
5576
+ if (part === "" || part === ".") continue;
5577
+ if (part === "..") {
5578
+ if (parts.length === 0) climbed = true;
5579
+ else parts.pop();
5580
+ } else parts.push(part);
5581
+ }
5582
+ return { parts, climbed };
5583
+ }
5584
+ function hooksPathBypasses(value) {
5585
+ if (value === null || value === void 0) return true;
5586
+ const v = value.trim();
5587
+ if (v === "" || v === "true") return true;
5588
+ const lp = lexicalPath(v);
5589
+ if (lp === null || lp.climbed || lp.parts.length === 0) return true;
5590
+ return lp.parts[0] === ".git" && lp.parts[1] !== "hooks";
5591
+ }
5568
5592
  function hooksBypass(inv) {
5569
- if (inv.config.has("core.hookspath")) return true;
5593
+ if (inv.config.has("core.hookspath") && hooksPathBypasses(inv.config.get("core.hookspath")))
5594
+ return true;
5570
5595
  for (const [name, value] of inv.env) {
5571
5596
  if (name === "GIT_CONFIG_PARAMETERS" && value !== null && /core\.hookspath/i.test(value))
5572
5597
  return true;
5573
- if (/^GIT_CONFIG_KEY_\d+$/.test(name) && value !== null && value.toLowerCase() === "core.hookspath")
5598
+ const key = /^GIT_CONFIG_KEY_(\d+)$/.exec(name);
5599
+ if (key && value !== null && value.toLowerCase() === "core.hookspath" && hooksPathBypasses(inv.env.get(`GIT_CONFIG_VALUE_${key[1]}`)))
5574
5600
  return true;
5575
5601
  }
5576
5602
  for (const name of HOOK_KILL_SWITCHES) {
@@ -5612,7 +5638,10 @@ function configWritesHooksPath(args) {
5612
5638
  }
5613
5639
  const key = args[i];
5614
5640
  if (key === null || key === void 0 || key.toLowerCase() !== "core.hookspath") return false;
5615
- return write2 || i + 1 < args.length;
5641
+ const unset = args.slice(0, i).some((w) => w === "--unset" || w === "--unset-all") || args[0] === "unset";
5642
+ if (unset) return true;
5643
+ if (i + 1 < args.length) return hooksPathBypasses(args[i + 1]);
5644
+ return write2;
5616
5645
  }
5617
5646
  function isHookPath(word) {
5618
5647
  return /(^|[\\/])(\.git[\\/]hooks|\.husky)([\\/]|$)/.test(word);
@@ -5647,31 +5676,49 @@ function chmodDisarmsHook(args, shown) {
5647
5676
  function wholeTree(operand) {
5648
5677
  if (/^:\(top\)\.?$/.test(operand) || operand === ":/" || operand === "*") return true;
5649
5678
  if (operand.startsWith(":")) return false;
5679
+ const lp = lexicalPath(operand);
5680
+ return lp !== null && lp.parts.length === 0;
5681
+ }
5682
+ function chdirPrefix(inv) {
5683
+ const dirs = inv.chdir ?? [];
5684
+ if (dirs.length === 0) return null;
5650
5685
  const parts = [];
5651
- for (const part of operand.split("/")) {
5652
- if (!part || part === ".") continue;
5653
- if (part === "..") parts.pop();
5654
- else parts.push(part);
5686
+ for (const d of dirs) {
5687
+ if (d === null || d === "") return null;
5688
+ const lp = lexicalPath(d);
5689
+ if (lp === null || lp.climbed) return null;
5690
+ parts.push(...lp.parts);
5655
5691
  }
5656
- return parts.length === 0 && !operand.startsWith("/");
5692
+ return parts.length === 0 ? null : parts.join("/");
5657
5693
  }
5658
5694
  function stagesEverything(inv) {
5659
5695
  const sub = inv.sub?.toLowerCase();
5696
+ const prefix = chdirPrefix(inv);
5697
+ const judge = (operands2) => {
5698
+ let conditional = false;
5699
+ for (const operand of operands2) {
5700
+ if (!wholeTree(operand)) continue;
5701
+ if (prefix === null || operand.startsWith(":") || operand.startsWith("/")) return {};
5702
+ if (wholeTree(`${prefix}/${operand === "*" ? "." : operand}`)) return {};
5703
+ conditional = true;
5704
+ }
5705
+ return conditional && prefix !== null ? { ifWorkTreeTop: prefix } : null;
5706
+ };
5660
5707
  if (sub === "add") {
5661
5708
  const o = parseOptions(inv.args, "", ADD_LONG_VALUE);
5662
5709
  if (o.flags.has("-n") || o.flags.has("--dry-run") || o.flags.has("-i") || o.flags.has("--interactive") || o.flags.has("-p") || o.flags.has("--patch") || o.flags.has("-e") || o.flags.has("--edit"))
5663
- return false;
5710
+ return null;
5664
5711
  const all = o.flags.has("-A") || o.flags.has("--all") || o.flags.has("--no-ignore-removal") || o.flags.has("-u") || o.flags.has("--update");
5665
- if (all && o.operands.length === 0) return true;
5666
- return o.operands.some(wholeTree);
5712
+ if (all && o.operands.length === 0) return {};
5713
+ return judge(o.operands);
5667
5714
  }
5668
5715
  if (sub === "commit") {
5669
5716
  const o = parseOptions(inv.args, "mFCcut", COMMIT_LONG_VALUE);
5670
- if (o.flags.has("--dry-run")) return false;
5671
- if (o.flags.has("-a") || o.flags.has("--all")) return true;
5672
- return o.operands.some(wholeTree);
5717
+ if (o.flags.has("--dry-run")) return null;
5718
+ if (o.flags.has("-a") || o.flags.has("--all")) return {};
5719
+ return judge(o.operands);
5673
5720
  }
5674
- return false;
5721
+ return null;
5675
5722
  }
5676
5723
  function hookTextRunsNothing(text) {
5677
5724
  return text.split(/\r?\n/).every((line) => INERT_LINE_RE.test(line.trim()));
@@ -7724,7 +7771,7 @@ async function evaluatePolicy(config, toolName, args, context = {}, hostHooks =
7724
7771
  }
7725
7772
  async function evaluatePolicyCore(config, toolName, args, context = {}, hooks = {}) {
7726
7773
  const { agent, cwd, activeEnvironment } = context;
7727
- const { checkProvenance: checkProvenance2, isTrustedHost: isTrustedHost2, isConfiguredRegistry } = hooks;
7774
+ const { checkProvenance: checkProvenance2, isTrustedHost: isTrustedHost2, isConfiguredRegistry, isGitWorkTreeTop: isGitWorkTreeTop2 } = hooks;
7728
7775
  const settingsView = catalogSettings(config);
7729
7776
  const layers = inspectionLayers(config.policy);
7730
7777
  const cv = (id) => checkValue(settingsView, id);
@@ -7878,6 +7925,8 @@ async function evaluatePolicyCore(config, toolName, args, context = {}, hooks =
7878
7925
  const action = cv(id);
7879
7926
  const finding = action === "off" ? void 0 : git.findings.find((f) => f.checkId === id);
7880
7927
  if (!finding) continue;
7928
+ if (finding.ifWorkTreeTop !== void 0 && isGitWorkTreeTop2 && cwd && !isGitWorkTreeTop2(finding.ifWorkTreeTop, cwd))
7929
+ continue;
7881
7930
  const v = applyCheckValue(action, {
7882
7931
  decision: "review",
7883
7932
  blockedByLabel: `Node9 (AST): ${finding.ruleName}`,
@@ -17200,6 +17249,7 @@ zoo`.split("\n");
17200
17249
  /** The words after `git`: global options, then the subcommand. */
17201
17250
  visitGit(rest, env, depth, viaXargs, fromAlias, shown) {
17202
17251
  const config = /* @__PURE__ */ new Map();
17252
+ const chdir = [];
17203
17253
  let i = 0;
17204
17254
  while (i < rest.length) {
17205
17255
  const w = rest[i];
@@ -17214,6 +17264,7 @@ zoo`.split("\n");
17214
17264
  i++;
17215
17265
  value = i < rest.length ? rest[i] : null;
17216
17266
  }
17267
+ if (name === "-C") chdir.push(viaXargs || (value ?? "").includes("{}") ? null : value);
17217
17268
  if (name === "-c" && value !== null) {
17218
17269
  const ceq = value.indexOf("=");
17219
17270
  const key = (ceq > 0 ? value.slice(0, ceq) : value).toLowerCase();
@@ -17230,7 +17281,7 @@ zoo`.split("\n");
17230
17281
  }
17231
17282
  const subWord = i < rest.length ? rest[i] : void 0;
17232
17283
  const args = rest.slice(i + 1);
17233
- const inv = { sub: null, args, config, env, shown };
17284
+ const inv = { sub: null, args, config, env, shown, chdir };
17234
17285
  if (subWord === void 0) {
17235
17286
  if (!viaXargs) return;
17236
17287
  this.emit(inv);
@@ -17244,16 +17295,23 @@ zoo`.split("\n");
17244
17295
  const fromConfig = config.get(`alias.${subWord.toLowerCase()}`);
17245
17296
  const alias = fromConfig !== void 0 ? fromConfig : this.aliases.get(subWord);
17246
17297
  if (alias !== void 0 && !fromAlias) {
17247
- this.expandAlias(subWord, alias, args, env, depth, 0, shown);
17298
+ this.expandAlias(subWord, alias, args, env, depth, 0, shown, chdir);
17248
17299
  return;
17249
17300
  }
17250
17301
  inv.sub = subWord;
17251
17302
  this.emit(inv);
17252
17303
  this.recordAliasDefinition(inv, env, depth);
17253
17304
  }
17254
- expandAlias(name, value, args, env, depth, level, shown) {
17305
+ expandAlias(name, value, args, env, depth, level, shown, chdir) {
17255
17306
  if (value === null) {
17256
- this.emit({ sub: null, args, config: /* @__PURE__ */ new Map(), env, shown: `${shown} (alias ${name})` });
17307
+ this.emit({
17308
+ sub: null,
17309
+ args,
17310
+ config: /* @__PURE__ */ new Map(),
17311
+ env,
17312
+ shown: `${shown} (alias ${name})`,
17313
+ chdir
17314
+ });
17257
17315
  return;
17258
17316
  }
17259
17317
  if (value.startsWith("!")) {
@@ -17267,7 +17325,16 @@ zoo`.split("\n");
17267
17325
  const nested = this.aliases.get(sub);
17268
17326
  const expandedShown = `${shown} (alias ${name} = ${value})`;
17269
17327
  if (nested !== void 0 && level < MAX_ALIAS_DEPTH) {
17270
- this.expandAlias(sub, nested, [...words.slice(1), ...args], env, depth, level + 1, shown);
17328
+ this.expandAlias(
17329
+ sub,
17330
+ nested,
17331
+ [...words.slice(1), ...args],
17332
+ env,
17333
+ depth,
17334
+ level + 1,
17335
+ shown,
17336
+ chdir
17337
+ );
17271
17338
  return;
17272
17339
  }
17273
17340
  this.emit({
@@ -17275,7 +17342,8 @@ zoo`.split("\n");
17275
17342
  args: [...words.slice(1), ...args],
17276
17343
  config: /* @__PURE__ */ new Map(),
17277
17344
  env,
17278
- shown: expandedShown
17345
+ shown: expandedShown,
17346
+ chdir
17279
17347
  });
17280
17348
  }
17281
17349
  /**
@@ -17309,7 +17377,7 @@ zoo`.split("\n");
17309
17377
  if (i + 1 >= args.length) return;
17310
17378
  const value = args[i + 1];
17311
17379
  this.aliases.set(m[1], value);
17312
- this.expandAlias(m[1], value, [], env, depth, 0, `${inv.shown}`);
17380
+ this.expandAlias(m[1], value, [], env, depth, 0, `${inv.shown}`, []);
17313
17381
  }
17314
17382
  };
17315
17383
  POSITIONAL2 = "\0positional";
@@ -18855,7 +18923,7 @@ zoo`.split("\n");
18855
18923
  { view: "separators-stripped", decoder: "separators", stripped: true }
18856
18924
  ];
18857
18925
  LONG_OUTPUT_THRESHOLD_BYTES = 100 * 1024;
18858
- CANONICAL_EXTRACTOR_VERSION = "canonical-v34";
18926
+ CANONICAL_EXTRACTOR_VERSION = "canonical-v35";
18859
18927
  DEDUPE_PREVIEW_LEN = 120;
18860
18928
  ENGINE_VERSION = "1.4.0";
18861
18929
  }
@@ -22932,10 +23000,19 @@ async function evaluatePolicy2(toolName, args, agent, cwd, opts) {
22932
23000
  // reaches a long-lived in-process authorizer (the gateway) within seconds.
22933
23001
  isTrustedHost: config.policy.trustedHostsManaged ? (host2) => matchesTrustedHost(host2, config.policy.trustedHosts) : isTrustedHost,
22934
23002
  readAgentSettings,
22935
- isConfiguredRegistry: (host2, at) => configuredRegistryHosts(at).has(host2)
23003
+ isConfiguredRegistry: (host2, at) => configuredRegistryHosts(at).has(host2),
23004
+ isGitWorkTreeTop
22936
23005
  }
22937
23006
  );
22938
23007
  }
23008
+ function isGitWorkTreeTop(dir2, cwd) {
23009
+ if (!path13.isAbsolute(cwd)) return true;
23010
+ try {
23011
+ return fs13.existsSync(path13.join(path13.resolve(cwd, dir2), ".git"));
23012
+ } catch {
23013
+ return true;
23014
+ }
23015
+ }
22939
23016
  function readAgentSettings(absPath) {
22940
23017
  const r = readCappedText(
22941
23018
  absPath,