mu-agent 0.2.10 → 0.2.12

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/judge/mu/index.js CHANGED
@@ -2687,9 +2687,9 @@ var require_dispatcher_base = __commonJS({
2687
2687
  }
2688
2688
  close(callback) {
2689
2689
  if (callback === void 0) {
2690
- return new Promise((resolve15, reject) => {
2690
+ return new Promise((resolve16, reject) => {
2691
2691
  this.close((err, data) => {
2692
- return err ? reject(err) : resolve15(data);
2692
+ return err ? reject(err) : resolve16(data);
2693
2693
  });
2694
2694
  });
2695
2695
  }
@@ -2727,9 +2727,9 @@ var require_dispatcher_base = __commonJS({
2727
2727
  err = null;
2728
2728
  }
2729
2729
  if (callback === void 0) {
2730
- return new Promise((resolve15, reject) => {
2730
+ return new Promise((resolve16, reject) => {
2731
2731
  this.destroy(err, (err2, data) => {
2732
- return err2 ? reject(err2) : resolve15(data);
2732
+ return err2 ? reject(err2) : resolve16(data);
2733
2733
  });
2734
2734
  });
2735
2735
  }
@@ -7686,12 +7686,12 @@ upgrade: ${upgrade}\r
7686
7686
  cb();
7687
7687
  }
7688
7688
  }
7689
- const waitForDrain = () => new Promise((resolve15, reject) => {
7689
+ const waitForDrain = () => new Promise((resolve16, reject) => {
7690
7690
  assert(callback === null);
7691
7691
  if (socket[kError]) {
7692
7692
  reject(socket[kError]);
7693
7693
  } else {
7694
- callback = resolve15;
7694
+ callback = resolve16;
7695
7695
  }
7696
7696
  });
7697
7697
  socket.on("close", onDrain).on("drain", onDrain);
@@ -9074,12 +9074,12 @@ var require_client_h2 = __commonJS({
9074
9074
  cb();
9075
9075
  }
9076
9076
  }
9077
- const waitForDrain = () => new Promise((resolve15, reject) => {
9077
+ const waitForDrain = () => new Promise((resolve16, reject) => {
9078
9078
  assert(callback === null);
9079
9079
  if (socket[kError]) {
9080
9080
  reject(socket[kError]);
9081
9081
  } else {
9082
- callback = resolve15;
9082
+ callback = resolve16;
9083
9083
  }
9084
9084
  });
9085
9085
  h2stream.on("close", onDrain).on("drain", onDrain);
@@ -9448,16 +9448,16 @@ var require_client = __commonJS({
9448
9448
  return this[kNeedDrain] < 2;
9449
9449
  }
9450
9450
  [kClose]() {
9451
- return new Promise((resolve15) => {
9451
+ return new Promise((resolve16) => {
9452
9452
  if (this[kSize]) {
9453
- this[kClosedResolve] = resolve15;
9453
+ this[kClosedResolve] = resolve16;
9454
9454
  } else {
9455
- resolve15(null);
9455
+ resolve16(null);
9456
9456
  }
9457
9457
  });
9458
9458
  }
9459
9459
  [kDestroy](err) {
9460
- return new Promise((resolve15) => {
9460
+ return new Promise((resolve16) => {
9461
9461
  const requests = this[kQueue].splice(this[kPendingIdx]);
9462
9462
  for (let i = 0; i < requests.length; i++) {
9463
9463
  const request = requests[i];
@@ -9470,7 +9470,7 @@ var require_client = __commonJS({
9470
9470
  this[kClosedResolve]();
9471
9471
  this[kClosedResolve] = null;
9472
9472
  }
9473
- resolve15(null);
9473
+ resolve16(null);
9474
9474
  };
9475
9475
  if (this[kHTTPContext]) {
9476
9476
  this[kHTTPContext].destroy(err, callback);
@@ -9883,8 +9883,8 @@ var require_pool_base = __commonJS({
9883
9883
  }
9884
9884
  return Promise.all(closeAll);
9885
9885
  } else {
9886
- return new Promise((resolve15) => {
9887
- this[kClosedResolve] = resolve15;
9886
+ return new Promise((resolve16) => {
9887
+ this[kClosedResolve] = resolve16;
9888
9888
  });
9889
9889
  }
9890
9890
  }
@@ -12547,7 +12547,7 @@ var require_readable = __commonJS({
12547
12547
  if (this._readableState.closeEmitted) {
12548
12548
  return Promise.resolve(null);
12549
12549
  }
12550
- return new Promise((resolve15, reject) => {
12550
+ return new Promise((resolve16, reject) => {
12551
12551
  if (this[kContentLength] && this[kContentLength] > limit || this[kBytesRead] > limit) {
12552
12552
  this.destroy(new AbortError());
12553
12553
  }
@@ -12561,11 +12561,11 @@ var require_readable = __commonJS({
12561
12561
  if (signal.aborted) {
12562
12562
  reject(signal.reason ?? new AbortError());
12563
12563
  } else {
12564
- resolve15(null);
12564
+ resolve16(null);
12565
12565
  }
12566
12566
  });
12567
12567
  } else {
12568
- this.on("close", resolve15);
12568
+ this.on("close", resolve16);
12569
12569
  }
12570
12570
  this.on("error", noop).on("data", () => {
12571
12571
  if (this[kBytesRead] > limit) {
@@ -12593,7 +12593,7 @@ var require_readable = __commonJS({
12593
12593
  }
12594
12594
  function consume(stream, type) {
12595
12595
  assert(!stream[kConsume]);
12596
- return new Promise((resolve15, reject) => {
12596
+ return new Promise((resolve16, reject) => {
12597
12597
  if (isUnusable(stream)) {
12598
12598
  const rState = stream._readableState;
12599
12599
  if (rState.destroyed && rState.closeEmitted === false) {
@@ -12608,7 +12608,7 @@ var require_readable = __commonJS({
12608
12608
  stream[kConsume] = {
12609
12609
  type,
12610
12610
  stream,
12611
- resolve: resolve15,
12611
+ resolve: resolve16,
12612
12612
  reject,
12613
12613
  length: 0,
12614
12614
  body: []
@@ -12686,18 +12686,18 @@ var require_readable = __commonJS({
12686
12686
  return buffer;
12687
12687
  }
12688
12688
  function consumeEnd(consume2, encoding) {
12689
- const { type, body, resolve: resolve15, stream, length } = consume2;
12689
+ const { type, body, resolve: resolve16, stream, length } = consume2;
12690
12690
  try {
12691
12691
  if (type === "text") {
12692
- resolve15(chunksDecode(body, length, encoding));
12692
+ resolve16(chunksDecode(body, length, encoding));
12693
12693
  } else if (type === "json") {
12694
- resolve15(JSON.parse(chunksDecode(body, length, encoding)));
12694
+ resolve16(JSON.parse(chunksDecode(body, length, encoding)));
12695
12695
  } else if (type === "arrayBuffer") {
12696
- resolve15(chunksConcat(body, length).buffer);
12696
+ resolve16(chunksConcat(body, length).buffer);
12697
12697
  } else if (type === "blob") {
12698
- resolve15(new Blob(body, { type: stream[kContentType] }));
12698
+ resolve16(new Blob(body, { type: stream[kContentType] }));
12699
12699
  } else if (type === "bytes") {
12700
- resolve15(chunksConcat(body, length));
12700
+ resolve16(chunksConcat(body, length));
12701
12701
  }
12702
12702
  consumeFinish(consume2);
12703
12703
  } catch (err) {
@@ -12916,9 +12916,9 @@ var require_api_request = __commonJS({
12916
12916
  };
12917
12917
  function request(opts, callback) {
12918
12918
  if (callback === void 0) {
12919
- return new Promise((resolve15, reject) => {
12919
+ return new Promise((resolve16, reject) => {
12920
12920
  request.call(this, opts, (err, data) => {
12921
- return err ? reject(err) : resolve15(data);
12921
+ return err ? reject(err) : resolve16(data);
12922
12922
  });
12923
12923
  });
12924
12924
  }
@@ -13179,9 +13179,9 @@ var require_api_stream = __commonJS({
13179
13179
  };
13180
13180
  function stream(opts, factory, callback) {
13181
13181
  if (callback === void 0) {
13182
- return new Promise((resolve15, reject) => {
13182
+ return new Promise((resolve16, reject) => {
13183
13183
  stream.call(this, opts, factory, (err, data) => {
13184
- return err ? reject(err) : resolve15(data);
13184
+ return err ? reject(err) : resolve16(data);
13185
13185
  });
13186
13186
  });
13187
13187
  }
@@ -13481,9 +13481,9 @@ var require_api_upgrade = __commonJS({
13481
13481
  };
13482
13482
  function upgrade(opts, callback) {
13483
13483
  if (callback === void 0) {
13484
- return new Promise((resolve15, reject) => {
13484
+ return new Promise((resolve16, reject) => {
13485
13485
  upgrade.call(this, opts, (err, data) => {
13486
- return err ? reject(err) : resolve15(data);
13486
+ return err ? reject(err) : resolve16(data);
13487
13487
  });
13488
13488
  });
13489
13489
  }
@@ -13577,9 +13577,9 @@ var require_api_connect = __commonJS({
13577
13577
  };
13578
13578
  function connect2(opts, callback) {
13579
13579
  if (callback === void 0) {
13580
- return new Promise((resolve15, reject) => {
13580
+ return new Promise((resolve16, reject) => {
13581
13581
  connect2.call(this, opts, (err, data) => {
13582
- return err ? reject(err) : resolve15(data);
13582
+ return err ? reject(err) : resolve16(data);
13583
13583
  });
13584
13584
  });
13585
13585
  }
@@ -15046,7 +15046,7 @@ var require_snapshot_recorder = __commonJS({
15046
15046
  "node_modules/undici/lib/mock/snapshot-recorder.js"(exports, module) {
15047
15047
  "use strict";
15048
15048
  var { writeFile: writeFile7, readFile: readFile8, mkdir: mkdir2 } = __require("node:fs/promises");
15049
- var { dirname: dirname13, resolve: resolve15 } = __require("node:path");
15049
+ var { dirname: dirname13, resolve: resolve16 } = __require("node:path");
15050
15050
  var { setTimeout: setTimeout2, clearTimeout: clearTimeout2 } = __require("node:timers");
15051
15051
  var { InvalidArgumentError, UndiciError } = require_errors();
15052
15052
  var { hashId, isUrlExcludedFactory, normalizeHeaders, createHeaderFilters } = require_snapshot_utils();
@@ -15262,7 +15262,7 @@ var require_snapshot_recorder = __commonJS({
15262
15262
  throw new InvalidArgumentError("Snapshot path is required");
15263
15263
  }
15264
15264
  try {
15265
- const data = await readFile8(resolve15(path), "utf8");
15265
+ const data = await readFile8(resolve16(path), "utf8");
15266
15266
  const parsed = JSON.parse(data);
15267
15267
  if (Array.isArray(parsed)) {
15268
15268
  this.#snapshots.clear();
@@ -15291,7 +15291,7 @@ var require_snapshot_recorder = __commonJS({
15291
15291
  if (!path) {
15292
15292
  throw new InvalidArgumentError("Snapshot path is required");
15293
15293
  }
15294
- const resolvedPath = resolve15(path);
15294
+ const resolvedPath = resolve16(path);
15295
15295
  await mkdir2(dirname13(resolvedPath), { recursive: true });
15296
15296
  const data = Array.from(this.#snapshots.entries()).map(([hash, snapshot2]) => ({
15297
15297
  hash,
@@ -22955,7 +22955,7 @@ var require_fetch = __commonJS({
22955
22955
  const hasTrailingQuestionMark = url.search.length === 0 && url.href[url.href.length - url.hash.length - 1] === "?";
22956
22956
  return dispatchWithProtocolPreference(body);
22957
22957
  function dispatchWithProtocolPreference(body2, allowH2) {
22958
- return new Promise((resolve15, reject) => agent.dispatch(
22958
+ return new Promise((resolve16, reject) => agent.dispatch(
22959
22959
  {
22960
22960
  path: hasTrailingQuestionMark ? `${path}?` : path,
22961
22961
  origin: url.origin,
@@ -23038,7 +23038,7 @@ var require_fetch = __commonJS({
23038
23038
  }
23039
23039
  }
23040
23040
  const onError = (err) => this.onResponseError(controller, err);
23041
- resolve15({
23041
+ resolve16({
23042
23042
  status,
23043
23043
  statusText,
23044
23044
  headersList,
@@ -23071,7 +23071,7 @@ var require_fetch = __commonJS({
23071
23071
  fetchParams.controller.off("terminated", this.abort);
23072
23072
  }
23073
23073
  if (request.mode === "websocket" && allowH2 !== false && error?.code === "UND_ERR_INFO" && error?.message === "HTTP/2: Extended CONNECT protocol not supported by server") {
23074
- resolve15(dispatchWithProtocolPreference(body2, false));
23074
+ resolve16(dispatchWithProtocolPreference(body2, false));
23075
23075
  return;
23076
23076
  }
23077
23077
  this.body?.destroy(error);
@@ -23088,7 +23088,7 @@ var require_fetch = __commonJS({
23088
23088
  const rawHeaders = controller?.rawHeaders ?? [];
23089
23089
  const headersList = new HeadersList();
23090
23090
  appendHeadersListFromResponseHeaders(headersList, headers, rawHeaders);
23091
- resolve15({
23091
+ resolve16({
23092
23092
  status,
23093
23093
  statusText: STATUS_CODES[status],
23094
23094
  headersList,
@@ -31157,8 +31157,8 @@ var KyrnRuntime = class {
31157
31157
  let timer;
31158
31158
  return Promise.race([
31159
31159
  work,
31160
- new Promise((resolve15) => {
31161
- timer = setTimeout(() => resolve15(void 0), left);
31160
+ new Promise((resolve16) => {
31161
+ timer = setTimeout(() => resolve16(void 0), left);
31162
31162
  })
31163
31163
  ]).finally(() => {
31164
31164
  if (timer) clearTimeout(timer);
@@ -31276,8 +31276,8 @@ function within(work, waitMs) {
31276
31276
  let timer;
31277
31277
  return Promise.race([
31278
31278
  work,
31279
- new Promise((resolve15) => {
31280
- timer = setTimeout(() => resolve15(void 0), waitMs);
31279
+ new Promise((resolve16) => {
31280
+ timer = setTimeout(() => resolve16(void 0), waitMs);
31281
31281
  })
31282
31282
  ]).finally(() => {
31283
31283
  if (timer) clearTimeout(timer);
@@ -31924,14 +31924,14 @@ var JobManager = class {
31924
31924
  scanFrom = offset;
31925
31925
  return void 0;
31926
31926
  };
31927
- return new Promise((resolve15) => {
31927
+ return new Promise((resolve16) => {
31928
31928
  let timer;
31929
31929
  const settle = (result) => {
31930
31930
  if (timer) clearTimeout(timer);
31931
31931
  job.listeners.delete(check);
31932
31932
  request.signal?.removeEventListener("abort", onAbort);
31933
31933
  job.waiting--;
31934
- resolve15(result);
31934
+ resolve16(result);
31935
31935
  };
31936
31936
  const check = () => {
31937
31937
  const line3 = scan2();
@@ -31969,13 +31969,13 @@ var JobManager = class {
31969
31969
  }
31970
31970
  /** Polls a condition that a job's end may change; resolves to whether it came true in time. */
31971
31971
  until(job, condition, timeoutMs) {
31972
- return new Promise((resolve15) => {
31973
- if (condition()) return resolve15(true);
31972
+ return new Promise((resolve16) => {
31973
+ if (condition()) return resolve16(true);
31974
31974
  const startedAt = Date.now();
31975
31975
  const done = (result) => {
31976
31976
  clearInterval(poll);
31977
31977
  job.listeners.delete(check);
31978
- resolve15(result);
31978
+ resolve16(result);
31979
31979
  };
31980
31980
  const check = () => {
31981
31981
  if (condition()) done(true);
@@ -33000,6 +33000,10 @@ var BoardProjects = class {
33000
33000
  }
33001
33001
  };
33002
33002
 
33003
+ // packages/kyrn-judge/src/checkpoint/mutating.ts
33004
+ import { realpathSync } from "node:fs";
33005
+ import { isAbsolute as isAbsolute2, resolve as resolve3 } from "node:path";
33006
+
33003
33007
  // packages/kyrn-judge/src/extension/shell-tools.ts
33004
33008
  var SHELL_TOOLS = /* @__PURE__ */ new Set(["bash", "powershell"]);
33005
33009
  function isShellTool(toolName) {
@@ -33023,7 +33027,7 @@ var READ_ONLY_TOOLS = /* @__PURE__ */ new Set([
33023
33027
  ]);
33024
33028
  var SHELL_TRICKS = /[<>;&`\n\r]|\$\(|\$\{/;
33025
33029
  var POWERSHELL_TRICKS = /[(){}]/;
33026
- var READ_ONLY_PROGRAM = /^(?:ls|pwd|cat|head|tail|wc|which|file|stat|du|df|date|whoami|uname|echo|printf|rg|grep|sort|uniq|cut|nl|tree|git\s+(?:status|log|diff|show|blame|rev-parse|ls-files|describe)|Get-ChildItem|gci|dir|Get-Content|gc|type|Get-Location|Select-String|sls|Get-Item|gi|Get-Date|Write-Output|Write-Host)(?:\s|$)/i;
33030
+ var READ_ONLY_PROGRAM = /^(?:ls|pwd|cat|head|tail|wc|which|file|stat|du|df|date|whoami|uname|echo|printf|rg|grep|sort|uniq|cut|nl|tree|git|Get-ChildItem|gci|dir|Get-Content|gc|type|Get-Location|Select-String|sls|Get-Item|gi|Get-Date|Write-Output|Write-Host)(?:\s|$)/i;
33027
33031
  var WRITES_OR_RUNS = /* @__PURE__ */ new Map([
33028
33032
  // ripgrep runs `--pre` on every file it searches, and `--hostname-bin` for its links.
33029
33033
  ["rg", /(?:^|\s)--(?:pre|hostname-bin)(?:[\s=]|$)/],
@@ -33048,21 +33052,145 @@ function longOption(words2, option, shortest = 1) {
33048
33052
  return name.length >= shortest && option.startsWith(name);
33049
33053
  });
33050
33054
  }
33051
- function readOnlyProgram(piece) {
33055
+ var GIT_READS = /* @__PURE__ */ new Set([
33056
+ "status",
33057
+ "log",
33058
+ "diff",
33059
+ "show",
33060
+ "blame",
33061
+ "rev-parse",
33062
+ "ls-files",
33063
+ "describe",
33064
+ "shortlog",
33065
+ "rev-list",
33066
+ "ls-tree",
33067
+ "cat-file",
33068
+ "merge-base",
33069
+ "name-rev",
33070
+ "for-each-ref",
33071
+ "show-ref",
33072
+ "diff-tree",
33073
+ "diff-index",
33074
+ "diff-files",
33075
+ "grep",
33076
+ "version"
33077
+ ]);
33078
+ var GIT_LISTS = /* @__PURE__ */ new Map([
33079
+ [
33080
+ "branch",
33081
+ {
33082
+ long: /* @__PURE__ */ new Set([
33083
+ "show-current",
33084
+ "list",
33085
+ "all",
33086
+ "remotes",
33087
+ "verbose",
33088
+ "contains",
33089
+ "no-contains",
33090
+ "merged",
33091
+ "no-merged",
33092
+ "points-at",
33093
+ "sort",
33094
+ "format",
33095
+ "color",
33096
+ "no-color",
33097
+ "column",
33098
+ "no-column",
33099
+ "abbrev",
33100
+ "no-abbrev",
33101
+ "ignore-case",
33102
+ "omit-empty"
33103
+ ]),
33104
+ short: /^-[ailrv]+$/,
33105
+ listing: /^(?:--(?:list|contains|no-contains|merged|no-merged|points-at)(?:=|$)|-[ailrv]*l)/
33106
+ }
33107
+ ],
33108
+ [
33109
+ "tag",
33110
+ {
33111
+ long: /* @__PURE__ */ new Set([
33112
+ "list",
33113
+ "contains",
33114
+ "no-contains",
33115
+ "merged",
33116
+ "no-merged",
33117
+ "points-at",
33118
+ "sort",
33119
+ "format",
33120
+ "color",
33121
+ "no-color",
33122
+ "column",
33123
+ "no-column",
33124
+ "ignore-case",
33125
+ "omit-empty"
33126
+ ]),
33127
+ // `-v` is not here: it verifies a tag with the program the config names.
33128
+ short: /^-(?:[il]+|n\d*)$/,
33129
+ listing: /^(?:--(?:list|contains|no-contains|merged|no-merged|points-at)(?:=|$)|-i*l|-n)/
33130
+ }
33131
+ ]
33132
+ ]);
33133
+ var CONFIG_SHOWS = /^(?:--(?:global|system|local|worktree|file|blob|show-origin|show-scope|name-only|null|includes|no-includes|type|bool|int|bool-or-int|path|expiry-date|default)(?:=|$)|-z$)/;
33134
+ var CONFIG_GETS = /^(?:--(?:get|get-all|get-regexp|get-urlmatch|list)|-l)$/;
33135
+ function readOnlyGit(args) {
33136
+ let at = 0;
33137
+ while (/^(?:-P|--no-pager|--no-optional-locks)$/.test(args[at] ?? "")) at++;
33138
+ const [command, ...rest] = args.slice(at);
33139
+ if (command === "--version") return rest.length === 0;
33140
+ if (command === "grep") {
33141
+ return !rest.some((arg) => /^-[a-zA-Z]*O/.test(arg)) && !longOption(rest, "open-files-in-pager");
33142
+ }
33143
+ if (command !== void 0 && GIT_READS.has(command)) return true;
33144
+ const list4 = command === void 0 ? void 0 : GIT_LISTS.get(command);
33145
+ if (list4) {
33146
+ let named = false;
33147
+ for (const arg of rest) {
33148
+ if (arg.startsWith("--")) {
33149
+ if (!list4.long.has(arg.slice(2).split("=")[0])) return false;
33150
+ } else if (arg.startsWith("-")) {
33151
+ if (!list4.short.test(arg)) return false;
33152
+ } else named = true;
33153
+ }
33154
+ return !named || rest.some((arg) => list4.listing.test(arg));
33155
+ }
33156
+ if (command === "stash") return rest[0] === "list" || rest[0] === "show";
33157
+ if (command === "worktree") return rest[0] === "list";
33158
+ if (command === "remote") return rest[0] === "get-url" || rest.every((arg) => arg === "-v" || arg === "--verbose");
33159
+ if (command === "config") {
33160
+ if (rest[0] === "get" || rest[0] === "list") return true;
33161
+ const names = rest.filter((arg) => !arg.startsWith("-")).length;
33162
+ return rest.every((arg) => !arg.startsWith("-") || CONFIG_GETS.test(arg) || CONFIG_SHOWS.test(arg)) && (rest.some((arg) => CONFIG_GETS.test(arg)) || names === 1);
33163
+ }
33164
+ return false;
33165
+ }
33166
+ function readOnlyProgram(piece, elsewhere = false) {
33052
33167
  if (!READ_ONLY_PROGRAM.test(piece)) return false;
33053
33168
  const words2 = piece.split(/\s+/);
33054
33169
  if (longOption(words2, "output")) return false;
33055
33170
  const program = words2[0].toLowerCase();
33171
+ if (program === "git") return !elsewhere && readOnlyGit(words2.slice(1));
33056
33172
  if (program === "uniq") return !uniqWrites(words2);
33057
33173
  if (program === "sort" && longOption(words2, "compress-program", 2)) return false;
33058
33174
  if (program === "file" && longOption(words2, "compile", 2)) return false;
33059
33175
  return !WRITES_OR_RUNS.get(program)?.test(piece);
33060
33176
  }
33061
- function isReadOnlyCommand(command, powershell = false) {
33177
+ function samePlace(dir, cwd) {
33178
+ if (resolve3(dir) === resolve3(cwd)) return true;
33179
+ try {
33180
+ return realpathSync.native(dir) === realpathSync.native(cwd);
33181
+ } catch {
33182
+ return false;
33183
+ }
33184
+ }
33185
+ function startsElsewhere(cwd, start) {
33186
+ return cwd !== void 0 && start !== void 0 && !samePlace(start, cwd);
33187
+ }
33188
+ function isReadOnlyCommand(command, powershell = false, cwd, start = cwd) {
33062
33189
  const text9 = command.trim();
33063
33190
  if (!text9 || SHELL_TRICKS.test(text9) || /--output\b/.test(text9)) return false;
33064
33191
  if (powershell && POWERSHELL_TRICKS.test(text9)) return false;
33065
- return text9.split("|").every((part) => readOnlyProgram(part.trim()));
33192
+ const elsewhere = startsElsewhere(cwd, start);
33193
+ return text9.split("|").every((part) => readOnlyProgram(part.trim(), elsewhere));
33066
33194
  }
33067
33195
  var FIND_ACTS = /^-(?:delete|exec|ok|fprint|fls)/;
33068
33196
  function harmlessRedirect(text9, at, both) {
@@ -33077,7 +33205,16 @@ function harmlessRedirect(text9, at, both) {
33077
33205
  if (!text9.startsWith("/dev/null", index) || !/^(?:[\s;&|]|$)/.test(text9.slice(end, end + 1))) return void 0;
33078
33206
  return end - 1;
33079
33207
  }
33080
- function simpleCommands(text9) {
33208
+ function fileRedirect(text9, at, writes) {
33209
+ let index = at + 1;
33210
+ if (text9[index] === ">") index++;
33211
+ while (text9[index] === " " || text9[index] === " ") index++;
33212
+ const name = /^[\w./@%+,:=-]+/.exec(text9.slice(index))?.[0];
33213
+ if (!name || !/^(?:[\s;&|]|$)/.test(text9.slice(index + name.length, index + name.length + 1))) return void 0;
33214
+ writes.push(name);
33215
+ return index + name.length - 1;
33216
+ }
33217
+ function simpleCommands(text9, writes) {
33081
33218
  if (text9.includes("\r")) return void 0;
33082
33219
  const commands = [];
33083
33220
  let words2 = [];
@@ -33110,7 +33247,7 @@ function simpleCommands(text9) {
33110
33247
  endCommand();
33111
33248
  } else if (next === ">") {
33112
33249
  endWord();
33113
- const end = harmlessRedirect(text9, index + 1, true);
33250
+ const end = harmlessRedirect(text9, index + 1, true) ?? (writes ? fileRedirect(text9, index + 1, writes) : void 0);
33114
33251
  if (end === void 0) return void 0;
33115
33252
  index = end;
33116
33253
  } else return void 0;
@@ -33119,7 +33256,7 @@ function simpleCommands(text9) {
33119
33256
  word = "";
33120
33257
  started = false;
33121
33258
  } else endWord();
33122
- const end = harmlessRedirect(text9, index, false);
33259
+ const end = harmlessRedirect(text9, index, false) ?? (writes ? fileRedirect(text9, index, writes) : void 0);
33123
33260
  if (end === void 0) return void 0;
33124
33261
  index = end;
33125
33262
  } else if (char === "'") {
@@ -33158,32 +33295,66 @@ function simpleCommands(text9) {
33158
33295
  endCommand();
33159
33296
  return commands;
33160
33297
  }
33161
- function isReadOnlyChain(command, powershell = false) {
33162
- if (powershell) return isReadOnlyCommand(command, true);
33298
+ function isReadOnlyChain(command, powershell = false, cwd, start = cwd) {
33299
+ if (powershell) return isReadOnlyCommand(command, true, cwd, start);
33163
33300
  const commands = simpleCommands(command.trim());
33164
33301
  if (!commands?.some((words2) => words2.length > 0)) return false;
33165
- let moved = false;
33302
+ let elsewhere = startsElsewhere(cwd, start);
33166
33303
  return commands.every((words2) => {
33167
- const [program] = words2;
33168
- if (program === void 0 || program === "true" || program === "false" || program === ":") return true;
33169
- if (program === "cd") {
33170
- moved = true;
33171
- return true;
33172
- }
33173
- if (program === "find") return !words2.some((word) => FIND_ACTS.test(word));
33174
- if (moved && program.toLowerCase() === "git") return false;
33175
- return readOnlyProgram(words2.join(" "));
33304
+ if (words2[0] !== "cd") return readOnlyPart(words2, elsewhere);
33305
+ elsewhere = !cdHome(words2, cwd);
33306
+ return true;
33176
33307
  });
33177
33308
  }
33178
- function isMutatingCall(toolName, input) {
33309
+ function cdHome(words2, cwd) {
33310
+ const [, to, ...more] = words2;
33311
+ return cwd !== void 0 && to !== void 0 && more.length === 0 && isAbsolute2(to) && !/[$*?[~]/.test(to) && !to.split(/[\\/]/).includes("..") && samePlace(to, cwd);
33312
+ }
33313
+ function readOnlyPart(words2, elsewhere) {
33314
+ const [program] = words2;
33315
+ if (program === void 0 || program === "true" || program === "false" || program === ":") return true;
33316
+ if (program === "find") return !words2.some((word) => FIND_ACTS.test(word));
33317
+ return readOnlyProgram(words2.join(" "), elsewhere);
33318
+ }
33319
+ function isMutatingCall(toolName, input, cwd) {
33179
33320
  if (READ_ONLY_TOOLS.has(toolName)) return false;
33180
- if (isShellTool(toolName)) return !isReadOnlyChain(String(input.command ?? ""), toolName === "powershell");
33321
+ if (isShellTool(toolName)) return !isReadOnlyChain(String(input.command ?? ""), toolName === "powershell", cwd);
33181
33322
  return true;
33182
33323
  }
33324
+ function shellStart(toolName, input, cwd) {
33325
+ return toolName === "bg_start" && typeof input.cwd === "string" && input.cwd ? resolve3(cwd, input.cwd) : cwd;
33326
+ }
33183
33327
  var CHECK_COMMAND = /\b(?:vitest|jest|pytest|mocha|ava|tsc|eslint|biome|ruff|mypy|rspec|phpunit|ctest|tox|nox|gradle|mvn)\b|\b(?:npm|pnpm|yarn|bun)\s+(?:run\s+)?(?:test|build|check|lint|typecheck)\b|\b(?:cargo|go|dotnet|swift|make|deno)\s+(?:test|build|check|vet|clippy)\b|\bnode\b[^\n]*--test\b|\btest\.sh\b/;
33184
33328
  function isCheckCommand(command) {
33185
33329
  return CHECK_COMMAND.test(command);
33186
33330
  }
33331
+ var CHECK_RUN = /^(?:(?:(?:npx|bunx)\s+|(?:pnpm|yarn)\s+(?:exec\s+)?|python3?\s+-m\s+)?(?:vitest|jest|pytest|mocha|ava|tsc|eslint|biome|ruff|mypy|rspec|phpunit|ctest|tox|nox)|(?:npm|pnpm|yarn|bun)\s+(?:run\s+)?(?:test|build|check|lint|typecheck)|(?:cargo|go|dotnet|swift|make|deno)\s+(?:test|build|check|vet|clippy)|node\s+--test|(?:(?:ba)?sh\s+(?:\.\/)?|\.\/)(?:[\w-][\w.-]*\/)*test\.sh|(?:[\w-][\w.-]*\/)+test\.sh)(?:\s|$)/;
33332
+ var CHECK_SETTING = /^(?:PYTHONPATH|CI|NODE_ENV|FORCE_COLOR|NO_COLOR|RUST_BACKTRACE)=[^$]*$/;
33333
+ function tempFile(name) {
33334
+ return /^\/(?:private\/)?tmp\//.test(name) && !name.split("/").includes("..");
33335
+ }
33336
+ function isCheckChain(command, powershell = false, cwd, start = cwd) {
33337
+ if (powershell) return false;
33338
+ const writes = [];
33339
+ const commands = simpleCommands(command.trim(), writes);
33340
+ if (!commands || !writes.every(tempFile)) return false;
33341
+ let elsewhere = startsElsewhere(cwd, start);
33342
+ let checks = 0;
33343
+ const parts = commands.every((words2) => {
33344
+ if (words2[0] === "cd") {
33345
+ elsewhere = !cdHome(words2, cwd);
33346
+ return true;
33347
+ }
33348
+ let at = words2[0] === "env" ? 1 : 0;
33349
+ while (at < words2.length && CHECK_SETTING.test(words2[at])) at++;
33350
+ if (CHECK_RUN.test(words2.slice(at).join(" "))) {
33351
+ checks++;
33352
+ return !elsewhere;
33353
+ }
33354
+ return at === 0 && readOnlyPart(words2, elsewhere);
33355
+ });
33356
+ return parts && checks > 0;
33357
+ }
33187
33358
 
33188
33359
  // packages/kyrn-judge/src/decisions/board-read.ts
33189
33360
  var MAX_EVENTS = 16;
@@ -34169,11 +34340,10 @@ function describeCall2(toolName, input) {
34169
34340
  const body = text9(record4.content) || text9(record4.newText) || text9(record4.new_string) || text9(record4.rewrite);
34170
34341
  return clip(`${path}${body ? ` <- ${body}` : ""}` || JSON.stringify(record4), 500);
34171
34342
  }
34172
- function readOnlyShell(toolName, input) {
34343
+ function readOnlyShell(toolName, input, cwd) {
34173
34344
  if (!isShellTool(toolName) && toolName !== "bg_start") return false;
34174
- const command = input?.command;
34175
34345
  const powershell = toolName === "powershell" || toolName === "bg_start" && process.platform === "win32";
34176
- return typeof command === "string" && isReadOnlyChain(command, powershell);
34346
+ return typeof input.command === "string" && isReadOnlyChain(input.command, powershell, cwd, shellStart(toolName, input, cwd));
34177
34347
  }
34178
34348
  function registerConstraints(runtime) {
34179
34349
  const options = runtime.options("constraints", {
@@ -34189,7 +34359,7 @@ function registerConstraints(runtime) {
34189
34359
  failOpen(async (event, ctx) => {
34190
34360
  runtime.touch(ctx);
34191
34361
  if (!MUTATING.has(event.toolName)) return void 0;
34192
- if (options.skipReadOnly && readOnlyShell(event.toolName, event.input)) return void 0;
34362
+ if (options.skipReadOnly && readOnlyShell(event.toolName, event.input, ctx.cwd)) return void 0;
34193
34363
  const constraints = (runtime.frame?.constraints ?? []).slice(-options.maxConstraints).map((entry) => entry.text);
34194
34364
  const mode = runtime.mode(toolConstraint.id);
34195
34365
  if (constraints.length === 0 || mode === "off") return void 0;
@@ -34201,7 +34371,7 @@ function registerConstraints(runtime) {
34201
34371
  }
34202
34372
  const decision = await Promise.race([
34203
34373
  runtime.engine.decide(toolConstraint, input, { signal: ctx.signal }),
34204
- new Promise((resolve15) => setTimeout(() => resolve15(void 0), options.waitMs))
34374
+ new Promise((resolve16) => setTimeout(() => resolve16(void 0), options.waitMs))
34205
34375
  ]);
34206
34376
  if (!decision || decision.mode !== "active" || decision.source !== "judge") return void 0;
34207
34377
  const broken = decision.outcome.broken.map((index) => constraints[index]).filter(Boolean);
@@ -35688,9 +35858,9 @@ function isLoopbackUrl(url) {
35688
35858
  if (host2 === "localhost" || host2.endsWith(".localhost")) return true;
35689
35859
  return isIP(host2) !== 0 && classifyAddress(host2) === "loopback";
35690
35860
  }
35691
- function checkedLookup(policy, resolve15 = dnsLookup) {
35861
+ function checkedLookup(policy, resolve16 = dnsLookup) {
35692
35862
  return (hostname, options, callback) => {
35693
- resolve15(hostname, { ...options, all: true }, (error, answer) => {
35863
+ resolve16(hostname, { ...options, all: true }, (error, answer) => {
35694
35864
  if (error) return callback(error);
35695
35865
  const addresses = Array.isArray(answer) ? answer : [];
35696
35866
  if (addresses.length === 0) return callback(new FetchRefusal("dns", `${hostname} has no address`));
@@ -35734,8 +35904,8 @@ var Bounds = class {
35734
35904
  start;
35735
35905
  resolve;
35736
35906
  places = /* @__PURE__ */ new Map();
35737
- constructor(start, resolve15 = systemResolve) {
35738
- this.resolve = resolve15;
35907
+ constructor(start, resolve16 = systemResolve) {
35908
+ this.resolve = resolve16;
35739
35909
  let parsed;
35740
35910
  try {
35741
35911
  parsed = new URL(start);
@@ -35928,7 +36098,7 @@ var SNAPSHOT_SCRIPT = String.raw`(() => {
35928
36098
  // packages/kyrn-judge/src/browser/session.ts
35929
36099
  var StalePage = class extends Error {
35930
36100
  };
35931
- var sleep = (ms) => new Promise((resolve15) => setTimeout(resolve15, ms));
36101
+ var sleep = (ms) => new Promise((resolve16) => setTimeout(resolve16, ms));
35932
36102
  var same = (a, b) => JSON.stringify(a) === JSON.stringify(b);
35933
36103
  var BrowserSession = class _BrowserSession {
35934
36104
  /** The address this tab was opened on: where the run was asked to go, before any page sent it elsewhere. */
@@ -36313,7 +36483,7 @@ var CdpConnection = class _CdpConnection {
36313
36483
  socket.addEventListener("error", () => this.failAll("The browser connection failed"));
36314
36484
  }
36315
36485
  static connect(url, timeoutMs = 5e3) {
36316
- return new Promise((resolve15, reject) => {
36486
+ return new Promise((resolve16, reject) => {
36317
36487
  const socket = new WebSocket(url);
36318
36488
  const timer = setTimeout(() => {
36319
36489
  socket.close();
@@ -36321,7 +36491,7 @@ var CdpConnection = class _CdpConnection {
36321
36491
  }, timeoutMs);
36322
36492
  socket.addEventListener("open", () => {
36323
36493
  clearTimeout(timer);
36324
- resolve15(new _CdpConnection(socket));
36494
+ resolve16(new _CdpConnection(socket));
36325
36495
  });
36326
36496
  socket.addEventListener("error", () => {
36327
36497
  clearTimeout(timer);
@@ -36356,7 +36526,7 @@ var CdpConnection = class _CdpConnection {
36356
36526
  send(method, params = {}, sessionId, timeoutMs = 3e4) {
36357
36527
  if (this.closed) return Promise.reject(new CdpError("The browser connection is closed"));
36358
36528
  const id = this.nextId++;
36359
- return new Promise((resolve15, reject) => {
36529
+ return new Promise((resolve16, reject) => {
36360
36530
  const timer = setTimeout(() => {
36361
36531
  this.pending.delete(id);
36362
36532
  reject(new CdpError(`The browser did not answer ${method} within ${Math.round(timeoutMs / 1e3)}s`));
@@ -36364,7 +36534,7 @@ var CdpConnection = class _CdpConnection {
36364
36534
  this.pending.set(id, {
36365
36535
  resolve: (value) => {
36366
36536
  clearTimeout(timer);
36367
- resolve15(value);
36537
+ resolve16(value);
36368
36538
  },
36369
36539
  reject: (error) => {
36370
36540
  clearTimeout(timer);
@@ -36638,11 +36808,11 @@ async function isAlive(endpoint) {
36638
36808
  }
36639
36809
  function exitOf(child, ms) {
36640
36810
  if (child.exitCode !== null || child.signalCode !== null) return Promise.resolve();
36641
- return new Promise((resolve15) => {
36642
- const timer = setTimeout(resolve15, ms);
36811
+ return new Promise((resolve16) => {
36812
+ const timer = setTimeout(resolve16, ms);
36643
36813
  child.once("exit", () => {
36644
36814
  clearTimeout(timer);
36645
- resolve15();
36815
+ resolve16();
36646
36816
  });
36647
36817
  });
36648
36818
  }
@@ -36684,7 +36854,7 @@ async function launchChrome(options = {}) {
36684
36854
  code: "browser_exited_on_start",
36685
36855
  params: { exitCode: child.exitCode }
36686
36856
  });
36687
- await new Promise((resolve15) => setTimeout(resolve15, 100));
36857
+ await new Promise((resolve16) => setTimeout(resolve16, 100));
36688
36858
  }
36689
36859
  child.kill();
36690
36860
  await exitOf(child, 5e3);
@@ -36787,7 +36957,7 @@ var EmbeddedBrowser = class _EmbeddedBrowser {
36787
36957
  const state = await this.control();
36788
36958
  if (state.stop) return false;
36789
36959
  if (!state.paused) return true;
36790
- await new Promise((resolve15) => setTimeout(resolve15, pollMs));
36960
+ await new Promise((resolve16) => setTimeout(resolve16, pollMs));
36791
36961
  }
36792
36962
  }
36793
36963
  };
@@ -37527,7 +37697,7 @@ ${result.stdout}`))
37527
37697
  };
37528
37698
  }
37529
37699
  function spawnOnce(binary, timeoutMs, args, env, input, limit) {
37530
- return new Promise((resolve15, reject) => {
37700
+ return new Promise((resolve16, reject) => {
37531
37701
  let child;
37532
37702
  try {
37533
37703
  child = spawn4(binary, [...args], { env: { ...env }, windowsHide: true, stdio: ["pipe", "pipe", "pipe"] });
@@ -37563,10 +37733,10 @@ function spawnOnce(binary, timeoutMs, args, env, input, limit) {
37563
37733
  child.on("close", (code) => {
37564
37734
  clearTimeout(timer);
37565
37735
  if (truncated) {
37566
- resolve15({ code: 0, stdout: Buffer.concat(out).toString("utf8"), stderr: "", truncated: true });
37736
+ resolve16({ code: 0, stdout: Buffer.concat(out).toString("utf8"), stderr: "", truncated: true });
37567
37737
  return;
37568
37738
  }
37569
- resolve15({
37739
+ resolve16({
37570
37740
  code: timedOut ? TIMED_OUT : code ?? 1,
37571
37741
  stdout: Buffer.concat(out).toString("utf8"),
37572
37742
  stderr: timedOut ? `timed out after ${timeoutMs} ms` : Buffer.concat(err).toString("utf8")
@@ -37611,14 +37781,14 @@ import {
37611
37781
  mkdirSync as mkdirSync8,
37612
37782
  readdirSync as readdirSync2,
37613
37783
  readFileSync as readFileSync9,
37614
- realpathSync,
37784
+ realpathSync as realpathSync2,
37615
37785
  rmdirSync,
37616
37786
  rmSync as rmSync5,
37617
37787
  statSync as statSync6,
37618
37788
  unlinkSync as unlinkSync2,
37619
37789
  writeFileSync as writeFileSync6
37620
37790
  } from "node:fs";
37621
- import { basename as basename3, dirname as dirname4, isAbsolute as isAbsolute2, join as join17, relative, resolve as resolve3, sep } from "node:path";
37791
+ import { basename as basename3, dirname as dirname4, isAbsolute as isAbsolute3, join as join17, relative, resolve as resolve4, sep } from "node:path";
37622
37792
  var BUILT_IN_IGNORES = [
37623
37793
  "node_modules/",
37624
37794
  "bower_components/",
@@ -37696,7 +37866,7 @@ var SnapshotTooLarge = class extends Error {
37696
37866
  function projectKey(root) {
37697
37867
  let real2 = root;
37698
37868
  try {
37699
- real2 = realpathSync.native(root);
37869
+ real2 = realpathSync2.native(root);
37700
37870
  } catch {
37701
37871
  }
37702
37872
  return createHash3("sha256").update(real2).digest("hex").slice(0, 16);
@@ -37715,9 +37885,9 @@ function isSafePath(path) {
37715
37885
  }
37716
37886
  var onDisk = (store, path) => join17(store.root, ...path.split("/"));
37717
37887
  function realPath(path) {
37718
- const absolute3 = resolve3(path);
37888
+ const absolute3 = resolve4(path);
37719
37889
  try {
37720
- return realpathSync.native(absolute3);
37890
+ return realpathSync2.native(absolute3);
37721
37891
  } catch {
37722
37892
  const parent = dirname4(absolute3);
37723
37893
  return parent === absolute3 ? absolute3 : join17(realPath(parent), basename3(absolute3));
@@ -37725,7 +37895,7 @@ function realPath(path) {
37725
37895
  }
37726
37896
  function inside(outer, inner) {
37727
37897
  const rel = relative(realPath(outer), realPath(inner));
37728
- return rel === ".." || rel.startsWith(`..${sep}`) || isAbsolute2(rel) ? void 0 : rel;
37898
+ return rel === ".." || rel.startsWith(`..${sep}`) || isAbsolute3(rel) ? void 0 : rel;
37729
37899
  }
37730
37900
  function isWithin(outer, inner) {
37731
37901
  return inside(outer, inner) !== void 0;
@@ -38314,7 +38484,7 @@ function registerCheckpoint(runtime, roots, deps = {}) {
38314
38484
  };
38315
38485
  }
38316
38486
  pending = void 0;
38317
- const mutating = isMutatingCall(event.toolName, event.input);
38487
+ const mutating = isMutatingCall(event.toolName, event.input, ctx.cwd);
38318
38488
  calls.set(event.toolCallId, { name: event.toolName, input: event.input, mutating });
38319
38489
  if (mutating) turn.changed = true;
38320
38490
  if (!mutating || off || turn.checkpoint || turn.snapshotFailed) return void 0;
@@ -38407,8 +38577,8 @@ function registerCheckpoint(runtime, roots, deps = {}) {
38407
38577
  let body = `Abandoned because: ${reason}`;
38408
38578
  const writer = runtime.writer();
38409
38579
  if (writer && turn.steps.length > 0) {
38410
- const timeout = new Promise((resolve15) => {
38411
- setTimeout(() => resolve15(void 0), 8e3).unref?.();
38580
+ const timeout = new Promise((resolve16) => {
38581
+ setTimeout(() => resolve16(void 0), 8e3).unref?.();
38412
38582
  });
38413
38583
  const reply = await Promise.race([
38414
38584
  writer({
@@ -38752,8 +38922,8 @@ The agent will then start over from your request, with a note about what didn't
38752
38922
  const wasBusy = busy > 0;
38753
38923
  await Promise.race([
38754
38924
  chain,
38755
- new Promise((resolve15) => {
38756
- setTimeout(resolve15, 3e3).unref?.();
38925
+ new Promise((resolve16) => {
38926
+ setTimeout(resolve16, 3e3).unref?.();
38757
38927
  })
38758
38928
  ]);
38759
38929
  if (store) releaseLocks(store, wasBusy && busy > 0 ? 0 : 12e4);
@@ -41038,8 +41208,8 @@ function registerFrame(runtime) {
41038
41208
  let timer;
41039
41209
  const late = await Promise.race([
41040
41210
  ask.pending.then(() => false),
41041
- new Promise((resolve15) => {
41042
- timer = setTimeout(() => resolve15(true), Math.max(0, options.waitMs - (Date.now() - ask.startedAt)));
41211
+ new Promise((resolve16) => {
41212
+ timer = setTimeout(() => resolve16(true), Math.max(0, options.waitMs - (Date.now() - ask.startedAt)));
41043
41213
  })
41044
41214
  ]);
41045
41215
  if (timer) clearTimeout(timer);
@@ -41891,7 +42061,7 @@ async function pkce() {
41891
42061
  return { verifier, challenge: base64url(new Uint8Array(digest2)) };
41892
42062
  }
41893
42063
  function listen(config, state) {
41894
- return new Promise((resolve15, reject) => {
42064
+ return new Promise((resolve16, reject) => {
41895
42065
  let settle = () => {
41896
42066
  };
41897
42067
  const wait = new Promise((done) => {
@@ -41938,7 +42108,7 @@ function listen(config, state) {
41938
42108
  server.listen(
41939
42109
  config.callbackPort,
41940
42110
  config.callbackHost,
41941
- () => resolve15({ server, wait, cancel: () => settle(void 0) })
42111
+ () => resolve16({ server, wait, cancel: () => settle(void 0) })
41942
42112
  );
41943
42113
  });
41944
42114
  }
@@ -42031,7 +42201,7 @@ async function geminiProject(config, token, interaction) {
42031
42201
  if (!started.ok) throw new Error(`onboardUser failed (${started.status}): ${(await started.text()).slice(0, 300)}`);
42032
42202
  let operation = await started.json();
42033
42203
  for (let attempt = 0; !operation.done && operation.name && attempt < 60; attempt++) {
42034
- await new Promise((resolve15) => setTimeout(resolve15, attempt === 0 ? 1e3 : 5e3));
42204
+ await new Promise((resolve16) => setTimeout(resolve16, attempt === 0 ? 1e3 : 5e3));
42035
42205
  const polled = await fetch(`${endpoint}/v1internal/${operation.name}`, { headers, signal: interaction.signal });
42036
42206
  if (!polled.ok) throw new Error(`Setting up the project failed (${polled.status})`);
42037
42207
  operation = await polled.json();
@@ -42911,7 +43081,7 @@ function gitArgs(args, platform = process.platform) {
42911
43081
  ];
42912
43082
  }
42913
43083
  var INHERITED = ["GIT_DIR", "GIT_WORK_TREE", "GIT_INDEX_FILE", "GIT_COMMON_DIR", "GIT_PREFIX"];
42914
- var spawnGit2 = (args, options) => new Promise((resolve15) => {
43084
+ var spawnGit2 = (args, options) => new Promise((resolve16) => {
42915
43085
  const env = { ...process.env };
42916
43086
  for (const name of INHERITED) delete env[name];
42917
43087
  Object.assign(env, { LC_ALL: "C", LANGUAGE: "C", GIT_TERMINAL_PROMPT: "0" }, options.env);
@@ -42928,7 +43098,7 @@ var spawnGit2 = (args, options) => new Promise((resolve15) => {
42928
43098
  signal: options.signal
42929
43099
  });
42930
43100
  } catch (error) {
42931
- resolve15({ code: -1, stdout: Buffer.alloc(0), stderr: String(error), missing: true });
43101
+ resolve16({ code: -1, stdout: Buffer.alloc(0), stderr: String(error), missing: true });
42932
43102
  return;
42933
43103
  }
42934
43104
  child.stdout?.on("data", (chunk) => out.push(chunk));
@@ -42936,9 +43106,9 @@ var spawnGit2 = (args, options) => new Promise((resolve15) => {
42936
43106
  stderr = (stderr + chunk.toString("utf8")).slice(-8e3);
42937
43107
  });
42938
43108
  child.on("error", (error) => {
42939
- resolve15({ code: -1, stdout: Buffer.concat(out), stderr: error.message, missing: error.code === "ENOENT" });
43109
+ resolve16({ code: -1, stdout: Buffer.concat(out), stderr: error.message, missing: error.code === "ENOENT" });
42940
43110
  });
42941
- child.on("close", (code) => resolve15({ code: code ?? -1, stdout: Buffer.concat(out), stderr }));
43111
+ child.on("close", (code) => resolve16({ code: code ?? -1, stdout: Buffer.concat(out), stderr }));
42942
43112
  child.stdin?.on("error", () => void 0);
42943
43113
  child.stdin?.end(options.input);
42944
43114
  });
@@ -43982,7 +44152,7 @@ var spawnRunner = async (task, assignment, signal, env, observer) => {
43982
44152
  await writeFile2(promptPath, assignment.agent.systemPrompt, { encoding: "utf8", mode: 384 });
43983
44153
  }
43984
44154
  try {
43985
- return await new Promise((resolve15, reject) => {
44155
+ return await new Promise((resolve16, reject) => {
43986
44156
  const invocation = piInvocation(childArgs(task, assignment, promptPath));
43987
44157
  const child = spawn6(invocation.command, invocation.args, {
43988
44158
  // An isolated sub-agent works in its own checkout; everyone else where the parent is.
@@ -44019,7 +44189,7 @@ var spawnRunner = async (task, assignment, signal, env, observer) => {
44019
44189
  finished = true;
44020
44190
  signal?.removeEventListener("abort", onAbort);
44021
44191
  if (error) reject(error);
44022
- else resolve15(lastText.trim());
44192
+ else resolve16(lastText.trim());
44023
44193
  };
44024
44194
  const onAbort = () => {
44025
44195
  terminate();
@@ -44766,7 +44936,7 @@ ${lines3.join("\n")}`);
44766
44936
  return void 0;
44767
44937
  }
44768
44938
  if (lastCalled || !options.lastCall) return void 0;
44769
- await Promise.race([queue, new Promise((resolve15) => setTimeout(resolve15, LAST_CALL_WAIT_MS))]);
44939
+ await Promise.race([queue, new Promise((resolve16) => setTimeout(resolve16, LAST_CALL_WAIT_MS))]);
44770
44940
  if (inbox.length === 0) return void 0;
44771
44941
  const lines2 = takeInbox();
44772
44942
  if (lines2.length === 0) return void 0;
@@ -44778,7 +44948,7 @@ ${lines3.join("\n")}`);
44778
44948
  runtime.pi.on(
44779
44949
  "agent_end",
44780
44950
  failOpen(async () => {
44781
- await Promise.race([queue, new Promise((resolve15) => setTimeout(resolve15, 6e3))]);
44951
+ await Promise.race([queue, new Promise((resolve16) => setTimeout(resolve16, 6e3))]);
44782
44952
  return void 0;
44783
44953
  })
44784
44954
  );
@@ -45077,12 +45247,12 @@ function registerHiveCommand(runtime) {
45077
45247
  return void 0;
45078
45248
  })
45079
45249
  );
45080
- const untilTurnEnds = () => new Promise((resolve15) => {
45250
+ const untilTurnEnds = () => new Promise((resolve16) => {
45081
45251
  let timer;
45082
45252
  const over = () => {
45083
45253
  clearTimeout(timer);
45084
45254
  waiting = void 0;
45085
- resolve15();
45255
+ resolve16();
45086
45256
  };
45087
45257
  waiting = { started: false, over };
45088
45258
  timer = setTimeout(() => {
@@ -45174,7 +45344,7 @@ var import_pi_coding_agent9 = __toESM(require_pi_coding_agent(), 1);
45174
45344
  var import_pi_tui4 = __toESM(require_pi_tui(), 1);
45175
45345
 
45176
45346
  // packages/kyrn-judge/src/import/index.ts
45177
- import { mkdirSync as mkdirSync13, readdirSync as readdirSync6, readFileSync as readFileSync16, realpathSync as realpathSync2, renameSync as renameSync7, statSync as statSync11, writeFileSync as writeFileSync11 } from "node:fs";
45347
+ import { mkdirSync as mkdirSync13, readdirSync as readdirSync6, readFileSync as readFileSync16, realpathSync as realpathSync3, renameSync as renameSync7, statSync as statSync11, writeFileSync as writeFileSync11 } from "node:fs";
45178
45348
  import { homedir as homedir7 } from "node:os";
45179
45349
  import { join as join32 } from "node:path";
45180
45350
 
@@ -45300,7 +45470,7 @@ function list2(value) {
45300
45470
  import { createHash as createHash5, randomBytes as randomBytes2, randomUUID as randomUUID7 } from "node:crypto";
45301
45471
  import { closeSync as closeSync4, openSync as openSync4, readdirSync as readdirSync5, renameSync as renameSync6, rmSync as rmSync7, statSync as statSync7, writeSync } from "node:fs";
45302
45472
  import { homedir as homedir5 } from "node:os";
45303
- import { isAbsolute as isAbsolute3, join as join30, resolve as resolve4 } from "node:path";
45473
+ import { isAbsolute as isAbsolute4, join as join30, resolve as resolve5 } from "node:path";
45304
45474
  var TOOL_NAMES = {
45305
45475
  "claude-code": "Claude Code",
45306
45476
  codex: "Codex",
@@ -45353,7 +45523,7 @@ function expand(path) {
45353
45523
  }
45354
45524
  function absolute(path, base = process.cwd()) {
45355
45525
  const expanded = expand(path);
45356
- return isAbsolute3(expanded) ? resolve4(expanded) : resolve4(base, expanded);
45526
+ return isAbsolute4(expanded) ? resolve5(expanded) : resolve5(base, expanded);
45357
45527
  }
45358
45528
  function defaultSessionDir(cwd, agentDir) {
45359
45529
  const safe = `--${absolute(cwd).replace(/^[/\\]/, "").replace(/[/\\:]/g, "-")}--`;
@@ -47180,7 +47350,7 @@ function sameFolder(a, b) {
47180
47350
  const canonical2 = (dir) => {
47181
47351
  const path = absolute(dir);
47182
47352
  try {
47183
- return realpathSync2.native(path);
47353
+ return realpathSync3.native(path);
47184
47354
  } catch {
47185
47355
  return path;
47186
47356
  }
@@ -47599,15 +47769,15 @@ ${theme.fg("dim", detail)}`, 0, 0));
47599
47769
  }
47600
47770
 
47601
47771
  // packages/kyrn-judge/src/extension/features/inherit.ts
47602
- import { isAbsolute as isAbsolute4, join as join38, resolve as resolve7 } from "node:path";
47772
+ import { isAbsolute as isAbsolute5, join as join38, resolve as resolve8 } from "node:path";
47603
47773
 
47604
47774
  // packages/kyrn-judge/src/inherit/files.ts
47605
- import { existsSync as existsSync13, readdirSync as readdirSync7, readFileSync as readFileSync17, realpathSync as realpathSync3, statSync as statSync12 } from "node:fs";
47606
- import { dirname as dirname7, join as join33, resolve as resolve5 } from "node:path";
47775
+ import { existsSync as existsSync13, readdirSync as readdirSync7, readFileSync as readFileSync17, realpathSync as realpathSync4, statSync as statSync12 } from "node:fs";
47776
+ import { dirname as dirname7, join as join33, resolve as resolve6 } from "node:path";
47607
47777
  var MAX_FILE_BYTES = 2 * 1024 * 1024;
47608
47778
  function projectChain(projectDir, home) {
47609
- const start = resolve5(projectDir);
47610
- const homeDir = resolve5(home);
47779
+ const start = resolve6(projectDir);
47780
+ const homeDir = resolve6(home);
47611
47781
  const chain = [];
47612
47782
  let current = start;
47613
47783
  for (let depth = 0; depth < 32; depth++) {
@@ -47666,9 +47836,9 @@ function listFiles(dir, extensions, depth = 4) {
47666
47836
  }
47667
47837
  function canonical(path) {
47668
47838
  try {
47669
- return realpathSync3(path);
47839
+ return realpathSync4(path);
47670
47840
  } catch {
47671
- return resolve5(path);
47841
+ return resolve6(path);
47672
47842
  }
47673
47843
  }
47674
47844
 
@@ -47931,7 +48101,7 @@ import { mkdirSync as mkdirSync14, readFileSync as readFileSync18, writeFileSync
47931
48101
  import { dirname as dirname8, join as join37 } from "node:path";
47932
48102
 
47933
48103
  // packages/kyrn-judge/src/inherit/mcp-config.ts
47934
- import { join as join35, resolve as resolve6 } from "node:path";
48104
+ import { join as join35, resolve as resolve7 } from "node:path";
47935
48105
 
47936
48106
  // packages/kyrn-judge/src/inherit/json-members.ts
47937
48107
  var QUOTE = 34;
@@ -48374,7 +48544,7 @@ function discoverMcpServers(options, problems) {
48374
48544
  let disabledInClaude = /* @__PURE__ */ new Set();
48375
48545
  if (inherit && switches.claude) {
48376
48546
  const path = join35(roots.home, ".claude.json");
48377
- const dirs = [resolve6(roots.projectDir), ...chain.slice(1)];
48547
+ const dirs = [resolve7(roots.projectDir), ...chain.slice(1)];
48378
48548
  const wanted = new Set(dirs.map((dir) => pathKey(dir, platform)));
48379
48549
  const config = parseJson(path, problems, {
48380
48550
  mcpServers: true,
@@ -48414,14 +48584,14 @@ function discoverMcpServers(options, problems) {
48414
48584
  }
48415
48585
  }
48416
48586
  if (inherit) {
48417
- const userFiles = /* @__PURE__ */ new Set([resolve6(join35(roots.home, ".cursor", "mcp.json"))]);
48587
+ const userFiles = /* @__PURE__ */ new Set([resolve7(join35(roots.home, ".cursor", "mcp.json"))]);
48418
48588
  for (const dir of chain) {
48419
48589
  const files = [
48420
48590
  { path: join35(dir, ".mcp.json"), tool: "claude", on: switches.claude },
48421
48591
  { path: join35(dir, ".cursor", "mcp.json"), tool: "cursor", on: switches.cursor }
48422
48592
  ];
48423
48593
  for (const file of files) {
48424
- if (!file.on || userFiles.has(resolve6(file.path))) continue;
48594
+ if (!file.on || userFiles.has(resolve7(file.path))) continue;
48425
48595
  if (!roots.projectTrusted) {
48426
48596
  if (readText(file.path, []) !== void 0) {
48427
48597
  skipped.push({ name: "*", source: file.path, reason: "the project is not trusted" });
@@ -48753,7 +48923,7 @@ ${lines2.join("\n")}`
48753
48923
  if (!scan2 || event.isError || !TOUCHING_TOOLS.includes(event.toolName)) return void 0;
48754
48924
  const path = event.input.path;
48755
48925
  if (typeof path !== "string" || !path) return void 0;
48756
- const file = isAbsolute4(path) ? path : resolve7(ctx.cwd, path);
48926
+ const file = isAbsolute5(path) ? path : resolve8(ctx.cwd, path);
48757
48927
  const matching = rulesForFile(scan2.rules, file).filter((rule) => !delivered.has(rule.path));
48758
48928
  if (matching.length === 0) return void 0;
48759
48929
  const notes = matching.map((rule) => {
@@ -49472,7 +49642,7 @@ function decompressed(response) {
49472
49642
  return response.pipe(through);
49473
49643
  }
49474
49644
  function once(url, limits, policy, signal) {
49475
- return new Promise((resolve15, reject) => {
49645
+ return new Promise((resolve16, reject) => {
49476
49646
  const send = url.protocol === "https:" ? httpsRequest : httpRequest;
49477
49647
  const request = send(
49478
49648
  url,
@@ -49488,7 +49658,7 @@ function once(url, limits, policy, signal) {
49488
49658
  ...limits.headers
49489
49659
  }
49490
49660
  },
49491
- resolve15
49661
+ resolve16
49492
49662
  );
49493
49663
  request.on("error", reject);
49494
49664
  request.end();
@@ -50198,7 +50368,7 @@ ${lines2.join("\n\n")}`
50198
50368
  id: "tool:web",
50199
50369
  kind: "tool",
50200
50370
  title: "Web reading and search",
50201
- description: "Read a web page as text and search the web from mainland China without a key, or through Tavily with TAVILY_API_KEY set.",
50371
+ description: "Read a web page as text, and search the web with no key or through Tavily with TAVILY_API_KEY set. The default search source also works from mainland China.",
50202
50372
  tools: ["web_fetch", "web_search"],
50203
50373
  exposure: "always"
50204
50374
  });
@@ -50450,8 +50620,8 @@ function registerInterjection(runtime) {
50450
50620
  const earlier = previous;
50451
50621
  let release = () => {
50452
50622
  };
50453
- previous = new Promise((resolve15) => {
50454
- release = () => setTimeout(resolve15, 0);
50623
+ previous = new Promise((resolve16) => {
50624
+ release = () => setTimeout(resolve16, 0);
50455
50625
  });
50456
50626
  try {
50457
50627
  const other = await otherWay(event, sent).catch(() => void 0);
@@ -50682,7 +50852,7 @@ function registerLayaNotice(runtime, skipped, roots, muHome2) {
50682
50852
  var import_pi_coding_agent12 = __toESM(require_pi_coding_agent(), 1);
50683
50853
  import { readFileSync as readFileSync20, statSync as statSync15 } from "node:fs";
50684
50854
  import { homedir as homedir8 } from "node:os";
50685
- import { join as join40, relative as relative4, resolve as resolve8 } from "node:path";
50855
+ import { join as join40, relative as relative4, resolve as resolve9 } from "node:path";
50686
50856
 
50687
50857
  // packages/kyrn-judge/src/decisions/diagnostics-delivery.ts
50688
50858
  var diagnosticsDelivery = defineDecision({
@@ -51134,12 +51304,12 @@ var LspClient = class {
51134
51304
  this.state = "stopping";
51135
51305
  this.clearTimers();
51136
51306
  if (child && child.exitCode === null && child.signalCode === null) {
51137
- const gone = new Promise((resolve15) => child.once("exit", () => resolve15()));
51307
+ const gone = new Promise((resolve16) => child.once("exit", () => resolve16()));
51138
51308
  if (wasRunning) {
51139
51309
  await this.request("shutdown", void 0, 2e3).catch(() => void 0);
51140
51310
  this.notify("exit", void 0);
51141
51311
  }
51142
- await Promise.race([gone, new Promise((resolve15) => setTimeout(resolve15, wasRunning ? 1e3 : 0))]);
51312
+ await Promise.race([gone, new Promise((resolve16) => setTimeout(resolve16, wasRunning ? 1e3 : 0))]);
51143
51313
  killTree(child, this.platform);
51144
51314
  }
51145
51315
  this.state = "stopped";
@@ -51244,16 +51414,16 @@ var LspClient = class {
51244
51414
  return true;
51245
51415
  };
51246
51416
  if (settled()) return Promise.resolve(true);
51247
- return new Promise((resolve15) => {
51417
+ return new Promise((resolve16) => {
51248
51418
  const check = () => {
51249
51419
  if (!settled()) return;
51250
51420
  clearTimeout(timer);
51251
51421
  this.waiters.delete(check);
51252
- resolve15(true);
51422
+ resolve16(true);
51253
51423
  };
51254
51424
  const timer = setTimeout(() => {
51255
51425
  this.waiters.delete(check);
51256
- resolve15(false);
51426
+ resolve16(false);
51257
51427
  }, budgetMs);
51258
51428
  this.waiters.add(check);
51259
51429
  });
@@ -51445,7 +51615,7 @@ var LspClient = class {
51445
51615
  }
51446
51616
  request(method, params, timeoutMs) {
51447
51617
  const id = this.nextId++;
51448
- return new Promise((resolve15, reject) => {
51618
+ return new Promise((resolve16, reject) => {
51449
51619
  const timer = setTimeout(
51450
51620
  () => {
51451
51621
  this.pending.delete(id);
@@ -51454,7 +51624,7 @@ var LspClient = class {
51454
51624
  },
51455
51625
  timeoutMs ?? this.options.requestTimeoutMs ?? 1e4
51456
51626
  );
51457
- this.pending.set(id, { resolve: resolve15, reject, timer });
51627
+ this.pending.set(id, { resolve: resolve16, reject, timer });
51458
51628
  this.send({ id, method, params });
51459
51629
  });
51460
51630
  }
@@ -52149,7 +52319,7 @@ function registerLsp(runtime) {
52149
52319
  const raw = event.input.path;
52150
52320
  if (typeof raw !== "string" || !raw.trim()) return void 0;
52151
52321
  const named = raw.startsWith("@") ? raw.slice(1) : raw;
52152
- const file = resolve8(
52322
+ const file = resolve9(
52153
52323
  ctx.cwd,
52154
52324
  named === "~" || named.startsWith("~/") ? join40(homedir8(), named.slice(1)) : named
52155
52325
  );
@@ -52395,7 +52565,7 @@ function capabilityId(serverName) {
52395
52565
  // packages/kyrn-judge/src/mcp/store.ts
52396
52566
  import { createHash as createHash7 } from "node:crypto";
52397
52567
  import { mkdirSync as mkdirSync16, readFileSync as readFileSync21, renameSync as renameSync9, writeFileSync as writeFileSync14 } from "node:fs";
52398
- import { join as join41, resolve as resolve9 } from "node:path";
52568
+ import { join as join41, resolve as resolve10 } from "node:path";
52399
52569
  var DESCRIPTION_LENGTH2 = 200;
52400
52570
  function sorted(map) {
52401
52571
  return Object.entries(map).sort(([left], [right]) => left.localeCompare(right));
@@ -52426,7 +52596,7 @@ function readJson(path, empty) {
52426
52596
  function writeJson(path, value) {
52427
52597
  if (!path) return;
52428
52598
  try {
52429
- mkdirSync16(resolve9(path, ".."), { recursive: true });
52599
+ mkdirSync16(resolve10(path, ".."), { recursive: true });
52430
52600
  const temporary = `${path}.${process.pid}.tmp`;
52431
52601
  writeFileSync14(temporary, `${JSON.stringify(value, null, " ")}
52432
52602
  `);
@@ -52464,11 +52634,11 @@ var McpStore = class {
52464
52634
  writeJson(this.cachePath, this.cache);
52465
52635
  }
52466
52636
  isApproved(projectDir, server) {
52467
- return this.approvals.projects?.[resolve9(projectDir)]?.[server.name] === definitionHash(server);
52637
+ return this.approvals.projects?.[resolve10(projectDir)]?.[server.name] === definitionHash(server);
52468
52638
  }
52469
52639
  approve(projectDir, server) {
52470
52640
  this.approvals = readJson(this.approvalPath, this.approvals);
52471
- const project = resolve9(projectDir);
52641
+ const project = resolve10(projectDir);
52472
52642
  this.approvals.projects = {
52473
52643
  ...this.approvals.projects,
52474
52644
  [project]: { ...this.approvals.projects?.[project], [server.name]: definitionHash(server) }
@@ -52620,9 +52790,9 @@ function registerMcp(runtime, roots) {
52620
52790
  if (!ctx) throw new Error("no session is running");
52621
52791
  unregister(entry);
52622
52792
  let timer;
52623
- const settled = new Promise((resolve15) => {
52624
- timer = setTimeout(() => resolve15(void 0), options.startTimeoutMs);
52625
- entry.waiter = resolve15;
52793
+ const settled = new Promise((resolve16) => {
52794
+ timer = setTimeout(() => resolve16(void 0), options.startTimeoutMs);
52795
+ entry.waiter = resolve16;
52626
52796
  });
52627
52797
  let event;
52628
52798
  try {
@@ -54460,12 +54630,12 @@ import { posix as posix3, win32 as win323 } from "node:path";
54460
54630
  var STDERR_LIMIT = 64 * 1024;
54461
54631
  var KILL_GRACE_MS2 = 2e3;
54462
54632
  var PIPE_GRACE_MS = 500;
54463
- var run = (command, args, options = {}) => new Promise((resolve15) => {
54633
+ var run = (command, args, options = {}) => new Promise((resolve16) => {
54464
54634
  const platform = options.platform ?? process.platform;
54465
54635
  const env = { ...process.env, ...options.env };
54466
54636
  const invocation = invocationFor(command, args, { platform, env });
54467
54637
  if (!invocation) {
54468
- resolve15({ code: 127, stdout: "", stderr: "", missing: true, stopped: false });
54638
+ resolve16({ code: 127, stdout: "", stderr: "", missing: true, stopped: false });
54469
54639
  return;
54470
54640
  }
54471
54641
  const encoding = options.encoding ?? "utf8";
@@ -54511,7 +54681,7 @@ var run = (command, args, options = {}) => new Promise((resolve15) => {
54511
54681
  if (late) clearTimeout(late);
54512
54682
  options.signal?.removeEventListener("abort", stop);
54513
54683
  if (options.onLine && carry && !stopped) options.onLine(carry);
54514
- resolve15({ code, stdout: Buffer.concat(chunks).toString(encoding), stderr, missing, stopped });
54684
+ resolve16({ code, stdout: Buffer.concat(chunks).toString(encoding), stderr, missing, stopped });
54515
54685
  };
54516
54686
  if (options.onLine) {
54517
54687
  child.stdout?.setEncoding(encoding);
@@ -54612,7 +54782,7 @@ function installHint(binary, platform) {
54612
54782
  var import_pi_coding_agent14 = __toESM(require_pi_coding_agent(), 1);
54613
54783
  var import_typebox11 = __toESM(require_typebox(), 1);
54614
54784
  import { readFile as readFile3, writeFile as writeFile3 } from "node:fs/promises";
54615
- import { resolve as resolve10 } from "node:path";
54785
+ import { resolve as resolve11 } from "node:path";
54616
54786
 
54617
54787
  // packages/kyrn-judge/src/packs/ast-grep.ts
54618
54788
  function sgArgs(query) {
@@ -54910,7 +55080,7 @@ function astGrepPack(shared, options) {
54910
55080
  read: (path) => readFile3(path),
54911
55081
  write: (path, data) => writeFile3(path, data),
54912
55082
  locked: import_pi_coding_agent14.withFileMutationQueue,
54913
- resolve: (file) => resolve10(ctx.cwd, file)
55083
+ resolve: (file) => resolve11(ctx.cwd, file)
54914
55084
  },
54915
55085
  { apply: params.apply === true, maxDiffChars: options.maxDiffChars }
54916
55086
  );
@@ -55602,9 +55772,9 @@ function report2(outcome) {
55602
55772
 
55603
55773
  // packages/kyrn-judge/src/extension/features/packs/conflicts.ts
55604
55774
  var import_typebox12 = __toESM(require_typebox(), 1);
55605
- import { realpathSync as realpathSync4 } from "node:fs";
55775
+ import { realpathSync as realpathSync5 } from "node:fs";
55606
55776
  import { readFile as readFile5, writeFile as writeFile6 } from "node:fs/promises";
55607
- import { basename as basename13, dirname as dirname11, isAbsolute as isAbsolute5, join as join46, relative as relative5 } from "node:path";
55777
+ import { basename as basename13, dirname as dirname11, isAbsolute as isAbsolute6, join as join46, relative as relative5 } from "node:path";
55608
55778
 
55609
55779
  // packages/kyrn-judge/src/packs/conflicts.ts
55610
55780
  import { mkdtemp as mkdtemp2, rm as rm5, writeFile as writeFile5 } from "node:fs/promises";
@@ -55739,7 +55909,7 @@ function looksBinary(content) {
55739
55909
  // packages/kyrn-judge/src/extension/features/packs/conflicts.ts
55740
55910
  function real(path) {
55741
55911
  try {
55742
- return realpathSync4.native(path);
55912
+ return realpathSync5.native(path);
55743
55913
  } catch {
55744
55914
  const parent = dirname11(path);
55745
55915
  return parent === path ? path : join46(real(parent), basename13(path));
@@ -55759,7 +55929,7 @@ function conflictsPack(shared, options) {
55759
55929
  return { repo, files };
55760
55930
  };
55761
55931
  const inRepo = (root, cwd, path) => {
55762
- const inside2 = relative5(real(root), real(isAbsolute5(path) ? path : join46(cwd, path))).replaceAll("\\", "/");
55932
+ const inside2 = relative5(real(root), real(isAbsolute6(path) ? path : join46(cwd, path))).replaceAll("\\", "/");
55763
55933
  if (inside2.startsWith("../") || inside2 === "..") throw new Error(`${path} is outside the repository`);
55764
55934
  return inside2;
55765
55935
  };
@@ -55944,7 +56114,7 @@ function conflictsPack(shared, options) {
55944
56114
 
55945
56115
  // packages/kyrn-judge/src/extension/features/packs/debugger.ts
55946
56116
  var import_typebox13 = __toESM(require_typebox(), 1);
55947
- import { isAbsolute as isAbsolute6, relative as relative6, resolve as resolve11 } from "node:path";
56117
+ import { isAbsolute as isAbsolute7, relative as relative6, resolve as resolve12 } from "node:path";
55948
56118
 
55949
56119
  // packages/kyrn-judge/src/dap/adapters.ts
55950
56120
  import { extname, posix as posix4, win32 as win324 } from "node:path";
@@ -56052,15 +56222,15 @@ import { spawn as spawn9, spawnSync as spawnSync2 } from "node:child_process";
56052
56222
  import { connect, createServer as createServer2 } from "node:net";
56053
56223
  var DapError = class extends Error {
56054
56224
  };
56055
- var sleep2 = (ms) => new Promise((resolve15) => setTimeout(resolve15, ms));
56225
+ var sleep2 = (ms) => new Promise((resolve16) => setTimeout(resolve16, ms));
56056
56226
  async function freePort() {
56057
- return new Promise((resolve15, reject) => {
56227
+ return new Promise((resolve16, reject) => {
56058
56228
  const server = createServer2();
56059
56229
  server.once("error", reject);
56060
56230
  server.listen(0, "127.0.0.1", () => {
56061
56231
  const address = server.address();
56062
56232
  const port = typeof address === "object" && address ? address.port : 0;
56063
- server.close(() => resolve15(port));
56233
+ server.close(() => resolve16(port));
56064
56234
  });
56065
56235
  });
56066
56236
  }
@@ -56118,8 +56288,8 @@ var DapClient = class {
56118
56288
  while (true) {
56119
56289
  if (this.ended) throw new DapError(this.why());
56120
56290
  try {
56121
- const socket = await new Promise((resolve15, reject) => {
56122
- const attempt = connect(port, "127.0.0.1", () => resolve15(attempt));
56291
+ const socket = await new Promise((resolve16, reject) => {
56292
+ const attempt = connect(port, "127.0.0.1", () => resolve16(attempt));
56123
56293
  attempt.once("error", reject);
56124
56294
  });
56125
56295
  socket.on("close", () => this.fail("the debug adapter closed the connection"));
@@ -56195,7 +56365,7 @@ var DapClient = class {
56195
56365
  request(command, args = {}, timeoutMs) {
56196
56366
  if (this.ended) return Promise.reject(new DapError(`${command}: ${this.why()}`));
56197
56367
  const seq = this.seq++;
56198
- return new Promise((resolve15, reject) => {
56368
+ return new Promise((resolve16, reject) => {
56199
56369
  const timer = setTimeout(
56200
56370
  () => {
56201
56371
  this.pending.delete(seq);
@@ -56203,7 +56373,7 @@ var DapClient = class {
56203
56373
  },
56204
56374
  timeoutMs ?? this.options.requestTimeoutMs ?? 3e4
56205
56375
  );
56206
- this.pending.set(seq, { command, resolve: resolve15, reject, timer });
56376
+ this.pending.set(seq, { command, resolve: resolve16, reject, timer });
56207
56377
  this.write({ seq, type: "request", command, arguments: args });
56208
56378
  });
56209
56379
  }
@@ -56219,12 +56389,12 @@ var DapClient = class {
56219
56389
  if (names.includes(this.received[at].event)) return this.received[at];
56220
56390
  }
56221
56391
  if (this.ended || signal?.aborted || Date.now() >= deadline) return void 0;
56222
- await new Promise((resolve15) => {
56392
+ await new Promise((resolve16) => {
56223
56393
  const wake = () => {
56224
56394
  this.waiters.delete(wake);
56225
56395
  signal?.removeEventListener("abort", wake);
56226
56396
  clearTimeout(timer);
56227
- resolve15();
56397
+ resolve16();
56228
56398
  };
56229
56399
  const timer = setTimeout(wake, Math.max(1, deadline - Date.now()));
56230
56400
  this.waiters.add(wake);
@@ -56508,7 +56678,7 @@ var UNTRUSTED5 = "Values and output below come from the program being debugged:
56508
56678
  function shown(path, cwd) {
56509
56679
  if (!path) return "?";
56510
56680
  const inside2 = relative6(cwd, path);
56511
- return inside2 && !inside2.startsWith("..") && !isAbsolute6(inside2) ? inside2 : path;
56681
+ return inside2 && !inside2.startsWith("..") && !isAbsolute7(inside2) ? inside2 : path;
56512
56682
  }
56513
56683
  function variableLine(variable) {
56514
56684
  const type = variable.type ? ` (${variable.type})` : "";
@@ -56683,8 +56853,8 @@ function debuggerPack(shared, options) {
56683
56853
  }),
56684
56854
  execute: async (_toolCallId, params, signal, _onUpdate, ctx) => {
56685
56855
  runtime.touch(ctx);
56686
- const cwd = params.cwd ? resolve11(ctx.cwd, params.cwd) : ctx.cwd;
56687
- const program = params.program ? resolve11(cwd, params.program) : void 0;
56856
+ const cwd = params.cwd ? resolve12(ctx.cwd, params.cwd) : ctx.cwd;
56857
+ const program = params.program ? resolve12(cwd, params.program) : void 0;
56688
56858
  const extra = launchExtra(params.launch);
56689
56859
  const module = typeof extra.module === "string" ? extra.module : void 0;
56690
56860
  if (!program && !module) throw new Error("Name the program to run (or, for Python, launch.module).");
@@ -56723,7 +56893,7 @@ function debuggerPack(shared, options) {
56723
56893
  spec.id,
56724
56894
  launch,
56725
56895
  params.breakpoints.map((point) => ({
56726
- file: resolve11(cwd, point.file),
56896
+ file: resolve12(cwd, point.file),
56727
56897
  line: Math.max(1, Math.floor(point.line)),
56728
56898
  condition: point.condition?.trim() || void 0
56729
56899
  })),
@@ -57147,13 +57317,14 @@ function registerPacks(runtime) {
57147
57317
  // packages/kyrn-judge/src/extension/features/permissions.ts
57148
57318
  var import_pi_coding_agent15 = __toESM(require_pi_coding_agent(), 1);
57149
57319
  import { homedir as homedir11 } from "node:os";
57150
- import { join as join48, resolve as resolve13, sep as sep3 } from "node:path";
57320
+ import { join as join48, resolve as resolve14, sep as sep3 } from "node:path";
57151
57321
 
57152
57322
  // packages/kyrn-judge/src/decisions/tool-approval.ts
57153
57323
  var APPROVE_AT = 0.8;
57324
+ var CHECK_APPROVE_AT = 0.7;
57154
57325
  var toolApproval = defineDecision({
57155
57326
  id: "tool.approval",
57156
- version: 1,
57327
+ version: 2,
57157
57328
  cacheImpact: "none",
57158
57329
  latency: "inline",
57159
57330
  capabilities: "relate",
@@ -57173,11 +57344,12 @@ var toolApproval = defineDecision({
57173
57344
  buildState(input) {
57174
57345
  return { tool_call: input.call, where: input.where, task: input.task, user_message: input.userMessage };
57175
57346
  },
57176
- policy(answers) {
57347
+ policy(answers, input) {
57177
57348
  const { choice, probabilities } = answers.verdict;
57178
57349
  if (isEscapeOption(choice)) return "unsure";
57179
57350
  const p = probabilities?.[choice];
57180
- if (choice === "needed") return p === void 0 || p >= APPROVE_AT ? "approve" : "unsure";
57351
+ const line2 = input.check ? CHECK_APPROVE_AT : APPROVE_AT;
57352
+ if (choice === "needed") return p === void 0 || p >= line2 ? "approve" : "unsure";
57181
57353
  return choice === "beyond" || choice === "unrelated" ? choice : "unsure";
57182
57354
  },
57183
57355
  // Nobody could look at it: the user decides.
@@ -57187,9 +57359,9 @@ var toolApproval = defineDecision({
57187
57359
  });
57188
57360
 
57189
57361
  // packages/kyrn-judge/src/permissions/modes.ts
57190
- import { lstatSync as lstatSync2, mkdirSync as mkdirSync18, readFileSync as readFileSync23, readlinkSync, realpathSync as realpathSync5, renameSync as renameSync10, writeFileSync as writeFileSync15 } from "node:fs";
57362
+ import { lstatSync as lstatSync2, mkdirSync as mkdirSync18, readFileSync as readFileSync23, readlinkSync, realpathSync as realpathSync6, renameSync as renameSync10, writeFileSync as writeFileSync15 } from "node:fs";
57191
57363
  import { homedir as homedir10 } from "node:os";
57192
- import { basename as basename14, dirname as dirname12, isAbsolute as isAbsolute7, join as join47, relative as relative7, resolve as resolve12, sep as sep2 } from "node:path";
57364
+ import { basename as basename14, dirname as dirname12, isAbsolute as isAbsolute8, join as join47, relative as relative7, resolve as resolve13, sep as sep2 } from "node:path";
57193
57365
  import { fileURLToPath as fileURLToPath5 } from "node:url";
57194
57366
  var PERMISSION_MODES = ["full", "judge", "ask"];
57195
57367
  var MODE_TEXT = {
@@ -57272,12 +57444,12 @@ function pathOf2(input) {
57272
57444
  }
57273
57445
  function realPath2(path, depth = 0) {
57274
57446
  try {
57275
- return realpathSync5.native(path);
57447
+ return realpathSync6.native(path);
57276
57448
  } catch {
57277
57449
  if (depth < 40) {
57278
57450
  try {
57279
57451
  if (lstatSync2(path).isSymbolicLink())
57280
- return realPath2(resolve12(dirname12(path), readlinkSync(path)), depth + 1);
57452
+ return realPath2(resolve13(dirname12(path), readlinkSync(path)), depth + 1);
57281
57453
  } catch {
57282
57454
  }
57283
57455
  }
@@ -57305,12 +57477,12 @@ function toolPath(cwd, raw, home = homedir10()) {
57305
57477
  return void 0;
57306
57478
  }
57307
57479
  }
57308
- return realPath2(isAbsolute7(path) ? resolve12(path) : resolve12(cwd, path));
57480
+ return realPath2(isAbsolute8(path) ? resolve13(path) : resolve13(cwd, path));
57309
57481
  }
57310
57482
  function inProject(cwd, target) {
57311
57483
  if (target === void 0) return void 0;
57312
- const rel = relative7(realPath2(resolve12(cwd)), target);
57313
- return rel === ".." || rel.startsWith(`..${sep2}`) || isAbsolute7(rel) ? void 0 : rel;
57484
+ const rel = relative7(realPath2(resolve13(cwd)), target);
57485
+ return rel === ".." || rel.startsWith(`..${sep2}`) || isAbsolute8(rel) ? void 0 : rel;
57314
57486
  }
57315
57487
  function projectFile(cwd, target) {
57316
57488
  const rel = inProject(cwd, target);
@@ -57345,7 +57517,9 @@ function permissionNeed(toolName, input, cwd, protectedPaths2 = [], chains = tru
57345
57517
  if (isShellTool(toolName) || toolName === "bg_start") {
57346
57518
  const command = text8(input.command);
57347
57519
  const powershell = toolName === "powershell" || toolName === "bg_start" && process.platform === "win32";
57348
- if (chains ? isReadOnlyChain(command, powershell) : isReadOnlyCommand(command, powershell)) return void 0;
57520
+ const start = shellStart(toolName, input, cwd);
57521
+ if (chains ? isReadOnlyChain(command, powershell, cwd, start) : isReadOnlyCommand(command, powershell, cwd, start))
57522
+ return void 0;
57349
57523
  const guarded = touches(command);
57350
57524
  const prefix = commandPrefix(command);
57351
57525
  return {
@@ -57361,7 +57535,7 @@ function permissionNeed(toolName, input, cwd, protectedPaths2 = [], chains = tru
57361
57535
  const paths = [...path ? [path] : [], ...listed2];
57362
57536
  const targets = paths.map((each) => ({ said: each, target: toolPath(cwd, each) }));
57363
57537
  const summary = clip5(`${toolName} ${path || listed2.join(" ") || text8(input.id) || text8(input.pattern)}`, 300);
57364
- const guarded = targets.flatMap(({ said, target }) => [resolve12(cwd, said), ...target ? [target] : []]).map(touches).find(Boolean);
57538
+ const guarded = targets.flatMap(({ said, target }) => [resolve13(cwd, said), ...target ? [target] : []]).map(touches).find(Boolean);
57365
57539
  if (guarded) return { kind: "edit", summary, protected: guarded };
57366
57540
  const away = targets.find(({ target }) => !projectFile(cwd, target));
57367
57541
  return away ? {
@@ -57482,7 +57656,7 @@ function protectedPaths(roots) {
57482
57656
  return real2 && real2 !== roots.agentDir ? [...spelled, real2] : spelled;
57483
57657
  }
57484
57658
  function projectSettings(cwd) {
57485
- const spelled = join48(resolve13(cwd), import_pi_coding_agent15.CONFIG_DIR_NAME);
57659
+ const spelled = join48(resolve14(cwd), import_pi_coding_agent15.CONFIG_DIR_NAME);
57486
57660
  const real2 = toolPath(cwd, import_pi_coding_agent15.CONFIG_DIR_NAME) ?? spelled;
57487
57661
  return [.../* @__PURE__ */ new Set([spelled, real2])].map((path) => `${path}${sep3}`);
57488
57662
  }
@@ -57575,6 +57749,9 @@ function registerPermissions(runtime, roots) {
57575
57749
  return { approved: asked2 && (decision2.judged ?? decision2.outcome) === "allow", reason: "flagged" };
57576
57750
  }
57577
57751
  const frame = runtime.frame;
57752
+ const input = event.input;
57753
+ const powershell = event.toolName === "powershell" || event.toolName === "bg_start" && process.platform === "win32";
57754
+ const check = need.kind === "shell" && isCheckChain(String(input.command ?? ""), powershell, ctx.cwd, shellStart(event.toolName, input, ctx.cwd));
57578
57755
  const decision = await runtime.engine.decide(
57579
57756
  toolApproval,
57580
57757
  {
@@ -57584,7 +57761,8 @@ function registerPermissions(runtime, roots) {
57584
57761
  ),
57585
57762
  userMessage,
57586
57763
  call,
57587
- where: need.kind === "outside" ? "outside the project folder" : need.kind === "shell" || need.kind === "run" ? "a program run in the project folder" : need.kind === "delegate" ? "subagents working on the project" : "an action outside this computer or program, such as a web page or a connected service"
57764
+ where: need.kind === "outside" ? "outside the project folder" : need.kind === "shell" || need.kind === "run" ? "a program run in the project folder" : need.kind === "delegate" ? "subagents working on the project" : "an action outside this computer or program, such as a web page or a connected service",
57765
+ check
57588
57766
  },
57589
57767
  { signal: ctx.signal }
57590
57768
  );
@@ -58276,8 +58454,8 @@ function registerPreflight(runtime) {
58276
58454
  }
58277
58455
  let skip = () => {
58278
58456
  };
58279
- const skipped = new Promise((resolve15) => {
58280
- skip = () => resolve15("skipped");
58457
+ const skipped = new Promise((resolve16) => {
58458
+ skip = () => resolve16("skipped");
58281
58459
  });
58282
58460
  const unsubscribe = panel ? ctx.ui.onTerminalInput((keys) => {
58283
58461
  if (!(0, import_pi_tui6.matchesKey)(keys, "escape")) return void 0;
@@ -58285,8 +58463,8 @@ function registerPreflight(runtime) {
58285
58463
  return { consume: true };
58286
58464
  }) : void 0;
58287
58465
  let timer;
58288
- const timeout = new Promise((resolve15) => {
58289
- timer = setTimeout(() => resolve15("timeout"), options.waitMs);
58466
+ const timeout = new Promise((resolve16) => {
58467
+ timer = setTimeout(() => resolve16("timeout"), options.waitMs);
58290
58468
  });
58291
58469
  try {
58292
58470
  current.waitEndedBy = await Promise.race([pending.then(() => "verdict"), timeout, skipped]);
@@ -58752,11 +58930,11 @@ var SandboxApiError = class extends Error {
58752
58930
  this.status = status;
58753
58931
  }
58754
58932
  };
58755
- var sleep3 = (ms, signal) => new Promise((resolve15, reject) => {
58933
+ var sleep3 = (ms, signal) => new Promise((resolve16, reject) => {
58756
58934
  if (signal?.aborted) return reject(new Error("aborted"));
58757
58935
  const timer = setTimeout(() => {
58758
58936
  signal?.removeEventListener("abort", onAbort);
58759
- resolve15();
58937
+ resolve16();
58760
58938
  }, ms);
58761
58939
  const onAbort = () => {
58762
58940
  clearTimeout(timer);
@@ -59000,7 +59178,7 @@ function errorDetail(text9) {
59000
59178
 
59001
59179
  // packages/kyrn-judge/src/sandbox/operations.ts
59002
59180
  import { readFile as readFile7 } from "node:fs/promises";
59003
- import { extname as extname2, isAbsolute as isAbsolute8, posix as posix6, relative as relative9, sep as sep5 } from "node:path";
59181
+ import { extname as extname2, isAbsolute as isAbsolute9, posix as posix6, relative as relative9, sep as sep5 } from "node:path";
59004
59182
 
59005
59183
  // packages/kyrn-judge/src/sandbox/session.ts
59006
59184
  import { posix as posix5 } from "node:path";
@@ -59091,7 +59269,7 @@ function createTar(entries) {
59091
59269
  // packages/kyrn-judge/src/sandbox/project.ts
59092
59270
  var gzipAsync = promisify(gzip);
59093
59271
  function runGit2(args, cwd, input) {
59094
- return new Promise((resolve15) => {
59272
+ return new Promise((resolve16) => {
59095
59273
  const child = spawn10("git", args, {
59096
59274
  cwd,
59097
59275
  stdio: [input ? "pipe" : "ignore", "pipe", "pipe"],
@@ -59102,10 +59280,10 @@ function runGit2(args, cwd, input) {
59102
59280
  const err = [];
59103
59281
  child.stdout?.on("data", (chunk) => out.push(chunk));
59104
59282
  child.stderr?.on("data", (chunk) => err.push(chunk));
59105
- child.on("error", (error) => resolve15({ code: 127, stdout: Buffer.alloc(0), stderr: error.message }));
59283
+ child.on("error", (error) => resolve16({ code: 127, stdout: Buffer.alloc(0), stderr: error.message }));
59106
59284
  child.on(
59107
59285
  "close",
59108
- (code) => resolve15({ code: code ?? 1, stdout: Buffer.concat(out), stderr: Buffer.concat(err).toString("utf8") })
59286
+ (code) => resolve16({ code: code ?? 1, stdout: Buffer.concat(out), stderr: Buffer.concat(err).toString("utf8") })
59109
59287
  );
59110
59288
  if (input) {
59111
59289
  child.stdin?.on("error", () => void 0);
@@ -59275,13 +59453,13 @@ function tail(buffer, chars = 600) {
59275
59453
  function untilAborted(work, signal) {
59276
59454
  if (!signal) return work;
59277
59455
  if (signal.aborted) return Promise.reject(new Error("aborted"));
59278
- return new Promise((resolve15, reject) => {
59456
+ return new Promise((resolve16, reject) => {
59279
59457
  const onAbort = () => reject(new Error("aborted"));
59280
59458
  signal.addEventListener("abort", onAbort, { once: true });
59281
59459
  work.then(
59282
59460
  (value) => {
59283
59461
  signal.removeEventListener("abort", onAbort);
59284
- resolve15(value);
59462
+ resolve16(value);
59285
59463
  },
59286
59464
  (error) => {
59287
59465
  signal.removeEventListener("abort", onAbort);
@@ -59533,14 +59711,14 @@ var SandboxSession = class {
59533
59711
  function toSandboxPath(localPath, root, workdir) {
59534
59712
  const inside2 = relative9(root, localPath);
59535
59713
  if (inside2 === "") return workdir;
59536
- if (inside2 !== ".." && !inside2.startsWith(`..${sep5}`) && !isAbsolute8(inside2)) {
59714
+ if (inside2 !== ".." && !inside2.startsWith(`..${sep5}`) && !isAbsolute9(inside2)) {
59537
59715
  return posix6.join(workdir, inside2.split(sep5).join("/"));
59538
59716
  }
59539
59717
  return localPath.split(sep5).join("/");
59540
59718
  }
59541
59719
  function insideProject(localPath, root) {
59542
59720
  const inside2 = relative9(root, localPath);
59543
- return inside2 === "" || inside2 !== ".." && !inside2.startsWith(`..${sep5}`) && !isAbsolute8(inside2);
59721
+ return inside2 === "" || inside2 !== ".." && !inside2.startsWith(`..${sep5}`) && !isAbsolute9(inside2);
59544
59722
  }
59545
59723
  var IMAGE_TYPES2 = {
59546
59724
  ".png": "image/png",
@@ -60590,7 +60768,7 @@ import { join as join52 } from "node:path";
60590
60768
 
60591
60769
  // packages/kyrn-judge/src/auth/exit.ts
60592
60770
  import { mkdirSync as mkdirSync20, rmdirSync as rmdirSync2 } from "node:fs";
60593
- import { resolve as resolve14 } from "node:path";
60771
+ import { resolve as resolve15 } from "node:path";
60594
60772
  import { setTimeout as sleep4 } from "node:timers/promises";
60595
60773
  async function holdLocksUntilExit(files, {
60596
60774
  limitMs = 3e3,
@@ -60617,7 +60795,7 @@ async function holdLocksUntilExit(files, {
60617
60795
  return release;
60618
60796
  }
60619
60797
  function lockFolders(files) {
60620
- return [...new Set(files.map((file) => `${resolve14(file)}.lock`))];
60798
+ return [...new Set(files.map((file) => `${resolve15(file)}.lock`))];
60621
60799
  }
60622
60800
  function takeAll(locks) {
60623
60801
  const taken = [];