github-router 0.3.204 → 0.3.206

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.
@@ -27330,11 +27330,152 @@ function buildWorkerTools(opts) {
27330
27330
  ];
27331
27331
  }
27332
27332
 
27333
+ //#endregion
27334
+ //#region src/lib/worker-agent/relay-cap.ts
27335
+ /** Default relay-safe byte budget for a worker result. */
27336
+ const DEFAULT_MAX_RESULT_BYTES = 16 * 1024;
27337
+ /** Lower clamp — below this a preview is barely useful. */
27338
+ const MIN_MAX_RESULT_BYTES = 8 * 1024;
27339
+ /**
27340
+ * Upper clamp. 20480 B ≈ 20k tokens even at the ~1 byte/token dense
27341
+ * worst case, comfortably under Claude Code's 25k-token result cap. The
27342
+ * env override is clamped to this, so it can never reintroduce the
27343
+ * overflow the cap exists to prevent.
27344
+ */
27345
+ const MAX_MAX_RESULT_BYTES = 20 * 1024;
27346
+ /**
27347
+ * Age at which a spilled `.patch`/`.txt` is swept. Matches the worktree
27348
+ * dir age sweep in `worktree.ts`.
27349
+ */
27350
+ const AGE_SWEEP_MS$1 = 10080 * 60 * 1e3;
27351
+ /** Min interval between throttled hot-path sweeps (see `sweepAgedWorkerDiffs`). */
27352
+ const SWEEP_THROTTLE_MS = 60 * 1e3;
27353
+ let lastThrottledSweepAt = 0;
27354
+ /**
27355
+ * Strict name pattern for router-written overflow files:
27356
+ * `<pid>-<8hex>.(patch|txt)`. Shared by the sweep so it NEVER removes a
27357
+ * file it didn't write (a user could drop something else under the dir).
27358
+ */
27359
+ const WORKER_DIFF_NAME_RE = /^\d+-[0-9a-f]{8}\.(?:patch|txt)$/;
27360
+ /** Resolve the relay-safe byte cap from env, clamped to the safe range. */
27361
+ function resolveMaxResultBytes() {
27362
+ const raw = process$1.env.GH_ROUTER_WORKER_MAX_RESULT_BYTES;
27363
+ if (raw === void 0) return DEFAULT_MAX_RESULT_BYTES;
27364
+ const n = Number(raw);
27365
+ if (!Number.isFinite(n) || !Number.isInteger(n) || n <= 0) return DEFAULT_MAX_RESULT_BYTES;
27366
+ return Math.min(MAX_MAX_RESULT_BYTES, Math.max(MIN_MAX_RESULT_BYTES, n));
27367
+ }
27368
+ /**
27369
+ * Return the longest prefix of `text` whose UTF-8 encoding is at most
27370
+ * `maxBytes` long, cut on a codepoint boundary (never mid-multibyte).
27371
+ */
27372
+ function utf8HeadPreview(text, maxBytes) {
27373
+ if (maxBytes <= 0) return "";
27374
+ const buf = Buffer.from(text, "utf8");
27375
+ if (buf.length <= maxBytes) return text;
27376
+ let end = maxBytes;
27377
+ while (end > 0 && (buf[end] & 192) === 128) end--;
27378
+ return buf.subarray(0, end).toString("utf8");
27379
+ }
27380
+ /**
27381
+ * Best-effort age sweep of router-written overflow files under
27382
+ * `WORKER_DIFFS_DIR`. Only removes entries whose NAME matches
27383
+ * `WORKER_DIFF_NAME_RE` and whose mtime is older than 7 days — a fresh
27384
+ * file a concurrent worker just wrote (new mtime) is never touched, and
27385
+ * a locked file just skips. Errors are swallowed so a sweep never blocks
27386
+ * the write it precedes.
27387
+ *
27388
+ * `opts.throttle` (used by the write hot path) skips the readdir/stat scan
27389
+ * when a throttled sweep ran within the last minute, so concurrent overflow
27390
+ * writes don't each re-scan the directory. Direct callers (and tests) sweep
27391
+ * unconditionally.
27392
+ */
27393
+ async function sweepAgedWorkerDiffs(opts = {}) {
27394
+ if (opts.throttle) {
27395
+ const now$1 = Date.now();
27396
+ if (now$1 - lastThrottledSweepAt < SWEEP_THROTTLE_MS) return;
27397
+ lastThrottledSweepAt = now$1;
27398
+ }
27399
+ let entries;
27400
+ try {
27401
+ entries = await fs.readdir(PATHS.WORKER_DIFFS_DIR);
27402
+ } catch {
27403
+ return;
27404
+ }
27405
+ const now = Date.now();
27406
+ for (const name of entries) {
27407
+ if (!WORKER_DIFF_NAME_RE.test(name)) continue;
27408
+ const full = nodePath.join(PATHS.WORKER_DIFFS_DIR, name);
27409
+ try {
27410
+ if (now - (await fs.stat(full)).mtimeMs < AGE_SWEEP_MS$1) continue;
27411
+ await fs.rm(full, { force: true }).catch(() => {});
27412
+ } catch {}
27413
+ }
27414
+ }
27415
+ /**
27416
+ * Write `text` in full to a durable `.txt` under `WORKER_DIFFS_DIR` and
27417
+ * return its absolute path. Unique `<pid>-<8hex>.txt` name, `0o600`,
27418
+ * exclusive-create (`wx`) so it never clobbers a pre-existing file /
27419
+ * symlink. Retries on the (astronomically rare) name collision with a
27420
+ * fresh suffix. Sweeps aged files first (throttled, best-effort).
27421
+ */
27422
+ async function saveOverflowResult(text) {
27423
+ await sweepAgedWorkerDiffs({ throttle: true });
27424
+ await fs.mkdir(PATHS.WORKER_DIFFS_DIR, { recursive: true });
27425
+ let lastErr;
27426
+ for (let attempt = 0; attempt < 5; attempt++) {
27427
+ const name = `${process$1.pid}-${randomBytes(4).toString("hex")}.txt`;
27428
+ const outPath = nodePath.join(PATHS.WORKER_DIFFS_DIR, name);
27429
+ try {
27430
+ await fs.writeFile(outPath, text, {
27431
+ mode: 384,
27432
+ flag: "wx"
27433
+ });
27434
+ return outPath;
27435
+ } catch (err) {
27436
+ if (err.code !== "EEXIST") throw err;
27437
+ lastErr = err;
27438
+ }
27439
+ }
27440
+ throw lastErr instanceof Error ? lastErr : /* @__PURE__ */ new Error("saveOverflowResult: exhausted unique-name retries");
27441
+ }
27442
+ /**
27443
+ * Cap a worker result to a relay-safe size. `reservedBytes` is the UTF-8
27444
+ * byte length of any must-survive envelope the caller will add OUTSIDE this
27445
+ * result (a `clampNote`/`worktreeNote` prefix, or the browse
27446
+ * `[browse session: id]` suffix), so the caller's final `envelope + result`
27447
+ * (or `result + envelope`) is guaranteed `<=` the configured cap.
27448
+ *
27449
+ * If the text fits under the effective cap it is returned unchanged.
27450
+ * Otherwise the FULL text is spilled to a durable file and a bounded
27451
+ * UTF-8-safe head preview + the file path is returned. On write failure the
27452
+ * preview is still returned with an explicit failure note — NEVER the
27453
+ * oversized original (that would re-trigger the overflow this guard prevents).
27454
+ */
27455
+ async function relaySafeText(text, reservedBytes = 0) {
27456
+ const cap = Math.max(0, resolveMaxResultBytes() - Math.max(0, reservedBytes));
27457
+ if (Buffer.byteLength(text, "utf8") <= cap) return text;
27458
+ let savedPath = null;
27459
+ let saveError = null;
27460
+ try {
27461
+ savedPath = await saveOverflowResult(text);
27462
+ } catch (err) {
27463
+ saveError = err instanceof Error ? err.message : String(err);
27464
+ }
27465
+ const trailer = savedPath !== null ? `\n\n[result truncated to fit the relay; full result saved to: ${savedPath}]` : `\n\n[result truncated to fit the relay; saving the full result failed: ${saveError ?? "unknown"}]`;
27466
+ const out = utf8HeadPreview(text, Math.max(0, cap - Buffer.byteLength(trailer, "utf8"))) + trailer;
27467
+ return Buffer.byteLength(out, "utf8") <= cap ? out : utf8HeadPreview(out, cap);
27468
+ }
27469
+
27333
27470
  //#endregion
27334
27471
  //#region src/lib/worker-agent/worktree.ts
27335
- /** Hard cap on the `finalize()` diff text. Above this we return a
27336
- * summary instead of a half-hunk. */
27337
- const DIFF_CAP_BYTES = 256 * 1024;
27472
+ /**
27473
+ * A diff at or below this size is inlined in full. Above it, `finalize()`
27474
+ * saves the complete patch to a file and returns a `git diff --stat`
27475
+ * summary + a bounded UTF-8-safe preview + the file path, so the full
27476
+ * change never rides (and overflows) Claude Code's 25k-token result relay.
27477
+ */
27478
+ const PREVIEW_CAP = 8 * 1024;
27338
27479
  /** Max entries allowed under `<repoRoot>/.git/worker-worktrees/`. */
27339
27480
  const QUOTA_PER_REPO = 20;
27340
27481
  /** Per-call age sweep: remove worktree dirs older than this. */
@@ -27421,7 +27562,7 @@ async function findRepoRoot(workspaceAbs) {
27421
27562
  } catch (err) {
27422
27563
  const e = err;
27423
27564
  const detail = e.stderr ? e.stderr.trim() : e.message;
27424
- throw new Error(`worker-agent worktree: git unavailable or workspace is not a repository: ${detail}`);
27565
+ throw new Error(`worker-agent worktree: git unavailable or workspace is not a repository: ${detail}. worker_implement/worker_test always run in an isolated git worktree and require a git repo; for in-place edits (or a non-git workspace), use the native \`implementer\` subagent instead.`);
27425
27566
  }
27426
27567
  const lines = result.stdout.split(/\r?\n/).filter((s) => s.length > 0);
27427
27568
  if (lines.length < 2) throw new Error(`worker-agent worktree: unexpected git rev-parse output: ${JSON.stringify(result.stdout)}`);
@@ -27598,7 +27739,7 @@ async function createWorktree(workspaceAbs, opts) {
27598
27739
  "diff",
27599
27740
  "HEAD"
27600
27741
  ], { maxBuffer: 256 * 1024 * 1024 });
27601
- if (diff.stdout.length <= DIFF_CAP_BYTES) return diff.stdout;
27742
+ if (Buffer.byteLength(diff.stdout, "utf8") <= PREVIEW_CAP) return diff.stdout;
27602
27743
  let stat$1 = "";
27603
27744
  try {
27604
27745
  stat$1 = (await execFileP("git", [
@@ -27609,8 +27750,8 @@ async function createWorktree(workspaceAbs, opts) {
27609
27750
  "HEAD"
27610
27751
  ])).stdout;
27611
27752
  } catch {}
27612
- const lineCount = stat$1.split(/\r?\n/).filter((l) => l.length > 0).length;
27613
- const summary = `[diff truncated at 256KB; ${Math.max(0, lineCount - 1)} files changed]\n${stat$1}`;
27753
+ const preview = utf8HeadPreview(diff.stdout, PREVIEW_CAP);
27754
+ const previewBlock = `\n\n--- diff preview (first ${PREVIEW_CAP >> 10} KiB of ${Buffer.byteLength(diff.stdout, "utf8")} bytes) ---\n` + preview;
27614
27755
  let savedPath = null;
27615
27756
  let saveError = null;
27616
27757
  try {
@@ -27618,8 +27759,8 @@ async function createWorktree(workspaceAbs, opts) {
27618
27759
  } catch (err) {
27619
27760
  saveError = err.message;
27620
27761
  }
27621
- if (savedPath !== null) return `${summary}\nFull patch (git apply-able; includes binary blobs) saved to: ${savedPath}`;
27622
- return `${summary}\n[full patch save failed: ${saveError ?? "unknown"}; only the summary above is available]`;
27762
+ if (savedPath !== null) return `[large diff — full patch saved to a file]\n${stat$1}${previewBlock}\n\nFull patch (git apply-able; includes binary blobs) saved to: ${savedPath}`;
27763
+ return `[large diff — full patch save FAILED: ${saveError ?? "unknown"}; only the summary + preview below survive]\n${stat$1}${previewBlock}`;
27623
27764
  };
27624
27765
  return {
27625
27766
  dir,
@@ -27633,11 +27774,11 @@ async function createWorktree(workspaceAbs, opts) {
27633
27774
  * durable, router-owned file under `PATHS.WORKER_DIFFS_DIR` and return its
27634
27775
  * absolute path.
27635
27776
  *
27636
- * Called by `finalize()` ONLY when the inline diff overflows
27637
- * `DIFF_CAP_BYTES`: the worktree is removed immediately after finalize, so a
27638
- * truncated inline diff would otherwise lose the actual patch forever. The
27639
- * durable dir lives under the app dir — never inside the worktree (deleted)
27640
- * nor the user's repo (don't pollute it).
27777
+ * Called by `finalize()` whenever the inline diff exceeds `PREVIEW_CAP`:
27778
+ * the worktree is removed immediately after finalize, so the full patch
27779
+ * must be persisted or the actual change is lost forever. The durable dir
27780
+ * lives under the app dir — never inside the worktree (deleted) nor the
27781
+ * user's repo (don't pollute it).
27641
27782
  *
27642
27783
  * `--binary` keeps binary blobs recoverable (git base85-encodes them into
27643
27784
  * the patch) and `--full-index` writes exact 40-char object indexes, so the
@@ -27656,14 +27797,24 @@ async function saveOverflowPatch(dir) {
27656
27797
  "--full-index",
27657
27798
  "HEAD"
27658
27799
  ], { maxBuffer: 256 * 1024 * 1024 });
27800
+ await sweepAgedWorkerDiffs({ throttle: true });
27659
27801
  await fs.mkdir(PATHS.WORKER_DIFFS_DIR, { recursive: true });
27660
- const name = `${process$1.pid}-${randomBytes(4).toString("hex")}.patch`;
27661
- const patchPath = nodePath.join(PATHS.WORKER_DIFFS_DIR, name);
27662
- await fs.writeFile(patchPath, patch.stdout, {
27663
- mode: 384,
27664
- flag: "wx"
27665
- });
27666
- return patchPath;
27802
+ let lastErr;
27803
+ for (let attempt = 0; attempt < 5; attempt++) {
27804
+ const name = `${process$1.pid}-${randomBytes(4).toString("hex")}.patch`;
27805
+ const patchPath = nodePath.join(PATHS.WORKER_DIFFS_DIR, name);
27806
+ try {
27807
+ await fs.writeFile(patchPath, patch.stdout, {
27808
+ mode: 384,
27809
+ flag: "wx"
27810
+ });
27811
+ return patchPath;
27812
+ } catch (err) {
27813
+ if (err.code !== "EEXIST") throw err;
27814
+ lastErr = err;
27815
+ }
27816
+ }
27817
+ throw lastErr instanceof Error ? lastErr : /* @__PURE__ */ new Error("saveOverflowPatch: exhausted unique-name retries");
27667
27818
  }
27668
27819
 
27669
27820
  //#endregion
@@ -30697,7 +30848,7 @@ function buildPeerAwarenessSnippet(opts) {
30697
30848
  criticList.push("`opus_critic` (Opus 4.6)");
30698
30849
  const codexCliClause = opts.codexCli ? " `mcp__codex-cli__codex` dispatches to `codex-implementer` (gpt-5.3-codex with workspace-write) for end-to-end coding tasks." : "";
30699
30850
  const para2Parts = [`\`mcp__${searchKey}__code\` is the one-stop code search (no extra model call). Its DEFAULT mode (or \`mode:"semantic"\`) ranks by MEANING via ColBERT over a per-workspace index, the first thing to reach for on intent/concept questions ("where is retry/backoff handled", "how does auth work"); when that index isn't ready it transparently falls back to lexical (the response \`source\` says which engine ran). Forced modes cover the rest: \`lexical\` (BM25F-ranked + tree-sitter, best for exact symbols), \`exact\`, \`regex\`, \`complete\` (exhaustive set), \`ast_pattern\`+\`ast_lang\` for multi-line AST shapes, \`scan\` for a whole-workspace symbol outline, \`multiline\` for cross-line regex. Multiple queries can run in a single turn. The index covers code-shaped files; for unstructured files (logs, \`.csv\`, \`.env*\`, config-only wiring), \`grep\`/\`glob\` still apply.`];
30700
- if (opts.workerToolsAvailable) para2Parts.push(`\`worker-*\` are background Agent subagents (subagent_type) that run the matching worker in its own context and deliver the result as a completion notification, so a long run never blocks the turn: \`worker-explore\` (read-only research), \`worker-review\` (reads the code to verify a change or claim), \`worker-plan\` (ordered implementation plan), \`worker-implement\` (edit/write/bash; \`worktree: true\` isolates in a git worktree and returns the diff), \`worker-test\` (independent test author). The raw \`mcp__${workersKey}__*\` tools they call are guarded (a direct main-thread call is redirected to the matching agent); Workers themselves have \`code_search\`.`);
30851
+ if (opts.workerToolsAvailable) para2Parts.push(`\`worker-*\` are background Agent subagents (subagent_type) that run the matching worker in its own context and deliver the result as a completion notification, so a long run never blocks the turn: \`worker-explore\` (read-only research), \`worker-review\` (reads the code to verify a change or claim), \`worker-plan\` (ordered implementation plan), \`worker-implement\` (edit/write/bash; ALWAYS runs in an isolated git worktree and returns the diff via a saved patch file; for in-place edits use the \`implementer\` subagent), \`worker-test\` (independent test author; also always worktree-isolated). The raw \`mcp__${workersKey}__*\` tools they call are guarded (a direct main-thread call is redirected to the matching agent); Workers themselves have \`code_search\`.`);
30701
30852
  para2Parts.push(`Three native subagents are always available (Task): \`implementer\` (bounded implementation), \`debugger\` (reproduce + isolate a failure's root cause), and \`qa-engineer\` (review + author/run tests), each in its own context so the lead's context stays free; on gpt-5.6-sol when in the catalog, else the lead's model.`);
30702
30853
  if (opts.workerToolsAvailable) para2Parts.push(`For a bounded, well-scoped implementation, prefer the \`implementer\` subagent over \`worker-implement\`; reach for \`worker-implement\` only when you specifically need git-worktree isolation, parallel variants, or a throwaway experiment.`);
30703
30854
  if (opts.workerToolsAvailable) para2Parts.push(`\`mcp__${orchestrateKey}__decompose\` composes an open-ended ask into a typed, VERIFIED workflow IR (a strong driver decorrelated by a cross-lab critic, so the decompose step isn't a single point of failure), and \`mcp__${orchestrateKey}__run_workflow\` executes that IR through a frozen kernel delivering max(orchestrated, baseline) over a sealed executable gate, so it never ships worse than a plain single-model run. \`mcp__${orchestrateKey}__verify_workflow\` checks an IR's floor invariants before you run it, and \`mcp__${orchestrateKey}__attest_step\` audits that a finished run's producers were each checked by a different lab. They suit non-trivial, role-separated asks; a trivial ask does not need them.`);
@@ -31010,7 +31161,7 @@ const NON_PERSONA_MCP_TOOLS = Object.freeze([
31010
31161
  toolNameHttp: "implement",
31011
31162
  group: "workers",
31012
31163
  capability: "worker",
31013
- description: "Runs as the background `worker-implement` agent. Dispatch via the Agent tool (subagent_type: worker-implement) so the turn is never blocked; the result arrives as a completion notification. Delegates a scoped coding task to an autonomous worker (Pi runtime; default model `gpt-5.6-sol` at xhigh reasoning, override via `model` with any Copilot-catalog model that advertises `tool_calls`). It has the explore read-only tools plus edit, write, bash, and codex_review, and it returns its final text with any changed files or worktree diff. Use for bounded implementation work that may take a while or benefits from isolated worker context. Not for pure research, planning, review, or independent test authoring; use explore, plan, review, or test for those scopes. With `worktree: false` (default) edits happen in place, so concurrent implement calls and lead edits to the same files can race. With `worktree: true` it runs in an isolated git worktree and returns the diff; this errors if the workspace is not a git repository.",
31164
+ description: "Runs as the background `worker-implement` agent. Dispatch via the Agent tool (subagent_type: worker-implement) so the turn is never blocked; the result arrives as a completion notification. Delegates a scoped coding task to an autonomous worker (Pi runtime; default model `gpt-5.6-sol` at xhigh reasoning, override via `model` with any Copilot-catalog model that advertises `tool_calls`). It has the explore read-only tools plus edit, write, bash, and codex_review, and it returns its final text with any changed files or worktree diff. Use for bounded implementation work that may take a while or benefits from isolated worker context. Not for pure research, planning, review, or independent test authoring; use explore, plan, review, or test for those scopes. ALWAYS runs in an isolated git worktree and returns the diff via a saved patch file (a `--stat` summary + a bounded preview + the patch path; a small diff is inlined in full) it never edits your working tree, and it HARD-ERRORS if the workspace is not a git repository. For in-place edits, use the native `implementer` subagent.",
31014
31165
  inputSchema: {
31015
31166
  type: "object",
31016
31167
  required: ["prompt"],
@@ -31022,7 +31173,7 @@ const NON_PERSONA_MCP_TOOLS = Object.freeze([
31022
31173
  },
31023
31174
  worktree: {
31024
31175
  type: "boolean",
31025
- description: "When true, run inside a fresh git worktree and return Pi's final text followed by the unified diff (so the lead can review before merging). When false/omitted, edits the workspace in place, so concurrent worker calls and lead edits can race. Errors if true and the workspace is not a git repository."
31176
+ description: "Ignored worker_implement ALWAYS runs in an isolated git worktree and returns the diff (retained for compatibility; worktree:false is overridden with a note). For in-place edits, use the `implementer` subagent."
31026
31177
  },
31027
31178
  model: {
31028
31179
  type: "string",
@@ -31042,7 +31193,7 @@ const NON_PERSONA_MCP_TOOLS = Object.freeze([
31042
31193
  },
31043
31194
  workspace: {
31044
31195
  type: "string",
31045
- description: "Optional absolute path to the workspace the worker operates in. Defaults to the proxy's launch cwd. Use this when the parent agent has multiple workspaces open and the worker must operate in a specific one. Must be absolute (relative paths rejected). For worktree:true, must be inside a git repo."
31196
+ description: "Optional absolute path to the workspace the worker operates in. Defaults to the proxy's launch cwd. Use this when the parent agent has multiple workspaces open and the worker must operate in a specific one. Must be absolute (relative paths rejected). Must be inside a git repo (implement always runs in a worktree)."
31046
31197
  },
31047
31198
  maxWallClockMs: {
31048
31199
  type: "integer",
@@ -31158,7 +31309,7 @@ const NON_PERSONA_MCP_TOOLS = Object.freeze([
31158
31309
  toolNameHttp: "test",
31159
31310
  group: "workers",
31160
31311
  capability: "worker",
31161
- description: "Runs as the background `worker-test` agent. Dispatch via the Agent tool (subagent_type: worker-test) so the turn is never blocked; the result arrives as a completion notification. Independent adversarial test authoring by an autonomous worker (Pi runtime; default model `gpt-5.6-sol` at xhigh reasoning, override via `model` with any Copilot-catalog model that advertises `tool_calls`). It has the same read/write toolset as implement and writes tests that try to break the implementation through edge cases, error paths, and acceptance criteria, then runs them and reports pass/fail. Use when a separate test author should challenge an implementation without modifying the production code to make tests pass. Not for implementing fixes, broad research, or code review; use implement, explore, or review for those scopes. With `worktree: true` it runs in an isolated git worktree and returns the test diff; this errors if the workspace is not a git repository.",
31312
+ description: "Runs as the background `worker-test` agent. Dispatch via the Agent tool (subagent_type: worker-test) so the turn is never blocked; the result arrives as a completion notification. Independent adversarial test authoring by an autonomous worker (Pi runtime; default model `gpt-5.6-sol` at xhigh reasoning, override via `model` with any Copilot-catalog model that advertises `tool_calls`). It has the same read/write toolset as implement and writes tests that try to break the implementation through edge cases, error paths, and acceptance criteria, then runs them and reports pass/fail. Use when a separate test author should challenge an implementation without modifying the production code to make tests pass. Not for implementing fixes, broad research, or code review; use implement, explore, or review for those scopes. ALWAYS runs in an isolated git worktree and returns the test diff via a saved patch file (a `--stat` summary + a bounded preview + the patch path; a small diff is inlined in full) — it never edits your working tree, and it HARD-ERRORS if the workspace is not a git repository. For in-place test authoring, use the native `implementer` subagent.",
31162
31313
  inputSchema: {
31163
31314
  type: "object",
31164
31315
  required: ["prompt"],
@@ -31170,7 +31321,7 @@ const NON_PERSONA_MCP_TOOLS = Object.freeze([
31170
31321
  },
31171
31322
  worktree: {
31172
31323
  type: "boolean",
31173
- description: "When true, run inside a fresh git worktree and return Pi's final text followed by the unified diff (so the lead can review the authored tests before merging). When false/omitted, writes tests in place, so concurrent worker calls and lead edits can race. Errors if true and the workspace is not a git repository."
31324
+ description: "Ignored worker_test ALWAYS runs in an isolated git worktree and returns the diff (retained for compatibility; worktree:false is overridden with a note). For in-place test authoring, use the `implementer` subagent."
31174
31325
  },
31175
31326
  model: {
31176
31327
  type: "string",
@@ -31190,7 +31341,7 @@ const NON_PERSONA_MCP_TOOLS = Object.freeze([
31190
31341
  },
31191
31342
  workspace: {
31192
31343
  type: "string",
31193
- description: "Optional absolute path to the workspace the worker operates in. Defaults to the proxy's launch cwd. Use this when the parent agent has multiple workspaces open and the worker must operate in a specific one. Must be absolute (relative paths rejected). For worktree:true, must be inside a git repo."
31344
+ description: "Optional absolute path to the workspace the worker operates in. Defaults to the proxy's launch cwd. Use this when the parent agent has multiple workspaces open and the worker must operate in a specific one. Must be absolute (relative paths rejected). Must be inside a git repo (test always runs in a worktree)."
31194
31345
  },
31195
31346
  maxWallClockMs: {
31196
31347
  type: "integer",
@@ -31579,15 +31730,19 @@ async function runWorkerToolCall(call) {
31579
31730
  thinking = thinkingRaw;
31580
31731
  }
31581
31732
  let worktree;
31582
- if ((mode === "implement" || mode === "test") && args.worktree !== void 0) {
31583
- if (typeof args.worktree !== "boolean") return {
31733
+ let worktreeNote = "";
31734
+ if (mode === "implement" || mode === "test") {
31735
+ if (args.worktree !== void 0 && typeof args.worktree !== "boolean") return {
31584
31736
  content: [{
31585
31737
  type: "text",
31586
31738
  text: `worker_${mode}: arguments.worktree must be a boolean when provided`
31587
31739
  }],
31588
31740
  isError: true
31589
31741
  };
31590
- worktree = args.worktree;
31742
+ worktree = true;
31743
+ if (args.worktree === false) worktreeNote = `[note: worker_${mode} always runs in an isolated git worktree; the requested worktree:false was overridden. For in-place edits, use the \`implementer\` subagent.]
31744
+
31745
+ `;
31591
31746
  }
31592
31747
  let workspace;
31593
31748
  if (args.workspace !== void 0) {
@@ -31641,10 +31796,11 @@ async function runWorkerToolCall(call) {
31641
31796
  maxWallClockMs,
31642
31797
  signal
31643
31798
  });
31799
+ const notePrefix = `${clampNote}${worktreeNote}`;
31644
31800
  return {
31645
31801
  content: [{
31646
31802
  type: "text",
31647
- text: `${clampNote}${result.text}`
31803
+ text: `${notePrefix}${await relaySafeText(result.text, Buffer.byteLength(notePrefix, "utf8"))}`
31648
31804
  }],
31649
31805
  isError: result.isError
31650
31806
  };
@@ -31733,10 +31889,11 @@ async function runBrowseToolCall(args, signal) {
31733
31889
  } finally {
31734
31890
  releaseBrowseSession(sessionId);
31735
31891
  }
31892
+ const sessionSuffix = `\n\n[browse session: ${sessionId}]`;
31736
31893
  return {
31737
31894
  content: [{
31738
31895
  type: "text",
31739
- text: `${result.text}\n\n[browse session: ${sessionId}]`
31896
+ text: `${await relaySafeText(result.text, Buffer.byteLength(sessionSuffix, "utf8"))}${sessionSuffix}`
31740
31897
  }],
31741
31898
  isError: result.isError
31742
31899
  };
@@ -31874,4 +32031,4 @@ function enumerateInjectedMcpToolNames(groupKeys, opts = {}) {
31874
32031
 
31875
32032
  //#endregion
31876
32033
  export { buildAdvisorStream as $, setupCopilotToken as $t, trustRepo as A, readResponseBodyCapped as At, runWorkerAgent as B, buildWorkspaceHeaderJson as Bt, fileLastPromptStore as C, getTokenCount as Ct, repoRoot as D, createResponses as Dt, repoFingerprint as E, pickEndpoint as Et, EXPLORE_DEFAULT_MODEL as F, extractTarGzMember as Ft, toolbeltEnabled as G, DEFAULT_CODEX_MODEL_FALLBACKS as Gt, buildEnv as H, toolbeltPathOverride as Ht, IMPLEMENT_DEFAULT_MODEL as I, extractZipMember as It, TOOLBELT_TOOLS$1 as J, UPSTREAM_INACTIVITY_TIMEOUT_MS as Jt, toolbeltSkipSet as K, DEFAULT_PORT as Kt, PLAN_DEFAULT_MODEL as L, shouldUseInsecureTls as Lt, resolveSealedGate as M, provisionBrowserAssets as Mt, BROWSE_DEFAULT_MODEL as N, hasSupportedBrowserInstalled as Nt, stopGateEnabledForRepo as O, createChatCompletions as Ot, DEFAULT_MODEL as P, provisionAndIndexColbert as Pt, ADVISOR_TOOL_INSTRUCTIONS as Q, withInstallLock as Qt, REVIEW_DEFAULT_MODEL as R, ArtifactClient as Rt, fileFindingsStore as S, createMessages as St, isSubagentContext as T, resolveMcpToolTimeoutMs as Tt, availableToolCommands as U, DEFAULT_CLAUDE_MODEL_FALLBACKS as Ut, withNoOutputRetry as V, collapsePathKeys as Vt, buildToolbeltAwareness as W, DEFAULT_CODEX_MODEL as Wt, searchWeb as X, pickClaudeDefault as Xt, assetFor as Y, generateRandomPort as Yt, ADVISOR_INTERNAL_TOOL_NAME as Z, getPackageVersion as Zt, stopGateDisabled as _, copilotBaseUrl as _n, nativeSubagentModel as _t, buildPeerAwarenessSnippet as a, cacheVSCodeVersion as an, logStreamError as at, stopReviewEnabled as b, state as bn, shimDefaultsToXhigh as bt, personasFor as c, resolveCodexModel as cn, handleMcpDelete as ct, buildStopHookCommand as d, getModels as dn, artifactToolsEnabled as dt, setupGitHubAgentToken as en, injectAdvisorTool as et, captureLaunchBaseline as f, getGitHubUser as fn, browseAgentEnabled as ft, launchBaselineKey as g, GITHUB_API_BASE_URL as gn, geminiAvailable as gt, injectStopHookIntoSettingsFile as h, forwardError as hn, fleetToolsEnabled as ht, buildAgentPrompt as i, cacheModels as in, isControllerClosedError as it, liveExec as j, parseJsonOrDiagnose as jt, stopReviewStateDir as k, MAX_RESPONSE_BODY_BYTES as kt, buildArtifactOpenHookCommand as l, resolveModel as ln, handleMcpPost as lt, fileBlockBudget as m, HTTPError as mn, browserToolsEnabled as mt, MCP_GROUPS as n, tryRefreshAndRetry as nn, buildAnthropicErrorEvent as nt, buildPeerAwarenessSummary as o, filterBetaHeader as on, readIteratorWithTimeout as ot, decideStopHook as p, fetchWithTransientRetry as pn, browserCompoundToolsEnabled as pt, vscodeRipgrepPath as q, UPSTREAM_FETCH_TIMEOUT_MS as qt, assertMcpToolSurfaceConsistent as r, cacheCopilotVersion as rn, buildOpenAIErrorEvent as rt, enumerateInjectedMcpToolNames as s, isNullish as sn, relayAnthropicStream as st, GROUP_META as t, setupGitHubToken as tn, isAdvisorRequested as tt, buildSessionBindHookCommand as u, sleep as un, agentToolsEnabled as ut, stopGateId as v, copilotHeaders as vn, standInToolEnabled as vt, fileReviewDebounce as w, assembleResponsesPayload as wt, fileBaselineStore as x, countTokens as xt, stopGatePlanMode as y, githubHeaders as yn, workerToolsEnabled as yt, appendPlanReminder as z, buildWorkspaceHeaderHelperCommand as zt };
31877
- //# sourceMappingURL=peer-mcp-personas-BekOx3Rp.js.map
32034
+ //# sourceMappingURL=peer-mcp-personas-C3ii7ZqP.js.map