usebeeline 0.1.20 → 0.1.21

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.
Files changed (2) hide show
  1. package/dist/usebeeline.mjs +980 -428
  2. package/package.json +1 -1
@@ -212,8 +212,8 @@ async function runSquireBrokerLink(options) {
212
212
  const pending = /* @__PURE__ */ new Map();
213
213
  const queued = [];
214
214
  let resolveDone;
215
- const done = new Promise((resolve45) => {
216
- resolveDone = resolve45;
215
+ const done = new Promise((resolve49) => {
216
+ resolveDone = resolve49;
217
217
  });
218
218
  const failResponse = (id) => `${JSON.stringify({
219
219
  jsonrpc: "2.0",
@@ -480,8 +480,8 @@ function socketHolders(inodes, profileDir, procRoot = "/proc") {
480
480
  }
481
481
  function alive(pid, procRoot) {
482
482
  try {
483
- const stat10 = readFileSync(join(procRoot, String(pid), "stat"), "utf8");
484
- return stat10.slice(stat10.lastIndexOf(")") + 2, stat10.lastIndexOf(")") + 3) !== "Z";
483
+ const stat11 = readFileSync(join(procRoot, String(pid), "stat"), "utf8");
484
+ return stat11.slice(stat11.lastIndexOf(")") + 2, stat11.lastIndexOf(")") + 3) !== "Z";
485
485
  } catch {
486
486
  return false;
487
487
  }
@@ -5680,11 +5680,11 @@ async function stageRelease(layout, manifestUrl, published, opts = {}) {
5680
5680
  const extract2 = await run("tar", ["-xzf", tempArchive, "-C", releaseDir], 5 * 6e4);
5681
5681
  if (extract2.status !== 0)
5682
5682
  throw new Error(`extracting bundle failed: ${extract2.stderr}`);
5683
- for (const relative4 of requiredBundlePaths()) {
5683
+ for (const relative5 of requiredBundlePaths()) {
5684
5684
  try {
5685
- await access(join8(releaseDir, relative4), fsConstants2.F_OK);
5685
+ await access(join8(releaseDir, relative5), fsConstants2.F_OK);
5686
5686
  } catch {
5687
- throw new Error(`staged bundle is missing ${relative4}`);
5687
+ throw new Error(`staged bundle is missing ${relative5}`);
5688
5688
  }
5689
5689
  }
5690
5690
  const engineMinimum = await readBundleEngineMinimum(releaseDir);
@@ -10099,10 +10099,10 @@ var require_resolve_block_map = __commonJS({
10099
10099
  let offset = bm.offset;
10100
10100
  let commentEnd = null;
10101
10101
  for (const collItem of bm.items) {
10102
- const { start, key, sep: sep3, value } = collItem;
10102
+ const { start, key, sep: sep4, value } = collItem;
10103
10103
  const keyProps = resolveProps.resolveProps(start, {
10104
10104
  indicator: "explicit-key-ind",
10105
- next: key ?? sep3?.[0],
10105
+ next: key ?? sep4?.[0],
10106
10106
  offset,
10107
10107
  onError,
10108
10108
  parentIndent: bm.indent,
@@ -10116,7 +10116,7 @@ var require_resolve_block_map = __commonJS({
10116
10116
  else if ("indent" in key && key.indent !== bm.indent)
10117
10117
  onError(offset, "BAD_INDENT", startColMsg);
10118
10118
  }
10119
- if (!keyProps.anchor && !keyProps.tag && !sep3) {
10119
+ if (!keyProps.anchor && !keyProps.tag && !sep4) {
10120
10120
  commentEnd = keyProps.end;
10121
10121
  if (keyProps.comment) {
10122
10122
  if (map.comment)
@@ -10140,7 +10140,7 @@ var require_resolve_block_map = __commonJS({
10140
10140
  ctx.atKey = false;
10141
10141
  if (utilMapIncludes.mapIncludes(ctx, map.items, keyNode))
10142
10142
  onError(keyStart, "DUPLICATE_KEY", "Map keys must be unique");
10143
- const valueProps = resolveProps.resolveProps(sep3 ?? [], {
10143
+ const valueProps = resolveProps.resolveProps(sep4 ?? [], {
10144
10144
  indicator: "map-value-ind",
10145
10145
  next: value,
10146
10146
  offset: keyNode.range[2],
@@ -10156,7 +10156,7 @@ var require_resolve_block_map = __commonJS({
10156
10156
  if (ctx.options.strict && keyProps.start < valueProps.found.offset - 1024)
10157
10157
  onError(keyNode.range, "KEY_OVER_1024_CHARS", "The : indicator must be at most 1024 chars after the start of an implicit block mapping key");
10158
10158
  }
10159
- const valueNode = value ? composeNode(ctx, value, valueProps, onError) : composeEmptyNode(ctx, offset, sep3, null, valueProps, onError);
10159
+ const valueNode = value ? composeNode(ctx, value, valueProps, onError) : composeEmptyNode(ctx, offset, sep4, null, valueProps, onError);
10160
10160
  if (ctx.schema.compat)
10161
10161
  utilFlowIndentCheck.flowIndentCheck(bm.indent, value, onError);
10162
10162
  offset = valueNode.range[2];
@@ -10247,7 +10247,7 @@ var require_resolve_end = __commonJS({
10247
10247
  let comment = "";
10248
10248
  if (end) {
10249
10249
  let hasSpace = false;
10250
- let sep3 = "";
10250
+ let sep4 = "";
10251
10251
  for (const token of end) {
10252
10252
  const { source, type } = token;
10253
10253
  switch (type) {
@@ -10261,13 +10261,13 @@ var require_resolve_end = __commonJS({
10261
10261
  if (!comment)
10262
10262
  comment = cb;
10263
10263
  else
10264
- comment += sep3 + cb;
10265
- sep3 = "";
10264
+ comment += sep4 + cb;
10265
+ sep4 = "";
10266
10266
  break;
10267
10267
  }
10268
10268
  case "newline":
10269
10269
  if (comment)
10270
- sep3 += source;
10270
+ sep4 += source;
10271
10271
  hasSpace = true;
10272
10272
  break;
10273
10273
  default:
@@ -10310,18 +10310,18 @@ var require_resolve_flow_collection = __commonJS({
10310
10310
  let offset = fc.offset + fc.start.source.length;
10311
10311
  for (let i3 = 0; i3 < fc.items.length; ++i3) {
10312
10312
  const collItem = fc.items[i3];
10313
- const { start, key, sep: sep3, value } = collItem;
10313
+ const { start, key, sep: sep4, value } = collItem;
10314
10314
  const props = resolveProps.resolveProps(start, {
10315
10315
  flow: fcName,
10316
10316
  indicator: "explicit-key-ind",
10317
- next: key ?? sep3?.[0],
10317
+ next: key ?? sep4?.[0],
10318
10318
  offset,
10319
10319
  onError,
10320
10320
  parentIndent: fc.indent,
10321
10321
  startOnNewline: false
10322
10322
  });
10323
10323
  if (!props.found) {
10324
- if (!props.anchor && !props.tag && !sep3 && !value) {
10324
+ if (!props.anchor && !props.tag && !sep4 && !value) {
10325
10325
  if (i3 === 0 && props.comma)
10326
10326
  onError(props.comma, "UNEXPECTED_TOKEN", `Unexpected , in ${fcName}`);
10327
10327
  else if (i3 < fc.items.length - 1)
@@ -10375,8 +10375,8 @@ var require_resolve_flow_collection = __commonJS({
10375
10375
  }
10376
10376
  }
10377
10377
  }
10378
- if (!isMap && !sep3 && !props.found) {
10379
- const valueNode = value ? composeNode(ctx, value, props, onError) : composeEmptyNode(ctx, props.end, sep3, null, props, onError);
10378
+ if (!isMap && !sep4 && !props.found) {
10379
+ const valueNode = value ? composeNode(ctx, value, props, onError) : composeEmptyNode(ctx, props.end, sep4, null, props, onError);
10380
10380
  coll.items.push(valueNode);
10381
10381
  offset = valueNode.range[2];
10382
10382
  if (isBlock(value))
@@ -10388,7 +10388,7 @@ var require_resolve_flow_collection = __commonJS({
10388
10388
  if (isBlock(key))
10389
10389
  onError(keyNode.range, "BLOCK_IN_FLOW", blockMsg);
10390
10390
  ctx.atKey = false;
10391
- const valueProps = resolveProps.resolveProps(sep3 ?? [], {
10391
+ const valueProps = resolveProps.resolveProps(sep4 ?? [], {
10392
10392
  flow: fcName,
10393
10393
  indicator: "map-value-ind",
10394
10394
  next: value,
@@ -10399,8 +10399,8 @@ var require_resolve_flow_collection = __commonJS({
10399
10399
  });
10400
10400
  if (valueProps.found) {
10401
10401
  if (!isMap && !props.found && ctx.options.strict) {
10402
- if (sep3)
10403
- for (const st of sep3) {
10402
+ if (sep4)
10403
+ for (const st of sep4) {
10404
10404
  if (st === valueProps.found)
10405
10405
  break;
10406
10406
  if (st.type === "newline") {
@@ -10417,7 +10417,7 @@ var require_resolve_flow_collection = __commonJS({
10417
10417
  else
10418
10418
  onError(valueProps.start, "MISSING_CHAR", `Missing , or : between ${fcName} items`);
10419
10419
  }
10420
- const valueNode = value ? composeNode(ctx, value, valueProps, onError) : valueProps.found ? composeEmptyNode(ctx, valueProps.end, sep3, null, valueProps, onError) : null;
10420
+ const valueNode = value ? composeNode(ctx, value, valueProps, onError) : valueProps.found ? composeEmptyNode(ctx, valueProps.end, sep4, null, valueProps, onError) : null;
10421
10421
  if (valueNode) {
10422
10422
  if (isBlock(value))
10423
10423
  onError(valueNode.range, "BLOCK_IN_FLOW", blockMsg);
@@ -10597,7 +10597,7 @@ var require_resolve_block_scalar = __commonJS({
10597
10597
  chompStart = i3 + 1;
10598
10598
  }
10599
10599
  let value = "";
10600
- let sep3 = "";
10600
+ let sep4 = "";
10601
10601
  let prevMoreIndented = false;
10602
10602
  for (let i3 = 0; i3 < contentStart; ++i3)
10603
10603
  value += lines[i3][0].slice(trimIndent) + "\n";
@@ -10614,24 +10614,24 @@ var require_resolve_block_scalar = __commonJS({
10614
10614
  indent = "";
10615
10615
  }
10616
10616
  if (type === Scalar.Scalar.BLOCK_LITERAL) {
10617
- value += sep3 + indent.slice(trimIndent) + content;
10618
- sep3 = "\n";
10617
+ value += sep4 + indent.slice(trimIndent) + content;
10618
+ sep4 = "\n";
10619
10619
  } else if (indent.length > trimIndent || content[0] === " ") {
10620
- if (sep3 === " ")
10621
- sep3 = "\n";
10622
- else if (!prevMoreIndented && sep3 === "\n")
10623
- sep3 = "\n\n";
10624
- value += sep3 + indent.slice(trimIndent) + content;
10625
- sep3 = "\n";
10620
+ if (sep4 === " ")
10621
+ sep4 = "\n";
10622
+ else if (!prevMoreIndented && sep4 === "\n")
10623
+ sep4 = "\n\n";
10624
+ value += sep4 + indent.slice(trimIndent) + content;
10625
+ sep4 = "\n";
10626
10626
  prevMoreIndented = true;
10627
10627
  } else if (content === "") {
10628
- if (sep3 === "\n")
10628
+ if (sep4 === "\n")
10629
10629
  value += "\n";
10630
10630
  else
10631
- sep3 = "\n";
10631
+ sep4 = "\n";
10632
10632
  } else {
10633
- value += sep3 + content;
10634
- sep3 = " ";
10633
+ value += sep4 + content;
10634
+ sep4 = " ";
10635
10635
  prevMoreIndented = false;
10636
10636
  }
10637
10637
  }
@@ -10813,25 +10813,25 @@ var require_resolve_flow_scalar = __commonJS({
10813
10813
  if (!match)
10814
10814
  return source;
10815
10815
  let res = match[1];
10816
- let sep3 = " ";
10816
+ let sep4 = " ";
10817
10817
  let pos = first.lastIndex;
10818
10818
  line.lastIndex = pos;
10819
10819
  while (match = line.exec(source)) {
10820
10820
  if (match[1] === "") {
10821
- if (sep3 === "\n")
10822
- res += sep3;
10821
+ if (sep4 === "\n")
10822
+ res += sep4;
10823
10823
  else
10824
- sep3 = "\n";
10824
+ sep4 = "\n";
10825
10825
  } else {
10826
- res += sep3 + match[1];
10827
- sep3 = " ";
10826
+ res += sep4 + match[1];
10827
+ sep4 = " ";
10828
10828
  }
10829
10829
  pos = line.lastIndex;
10830
10830
  }
10831
10831
  const last = /[ \t]*(.*)/sy;
10832
10832
  last.lastIndex = pos;
10833
10833
  match = last.exec(source);
10834
- return res + sep3 + (match?.[1] ?? "");
10834
+ return res + sep4 + (match?.[1] ?? "");
10835
10835
  }
10836
10836
  function doubleQuotedValue(source, onError) {
10837
10837
  let res = "";
@@ -11641,14 +11641,14 @@ var require_cst_stringify = __commonJS({
11641
11641
  }
11642
11642
  }
11643
11643
  }
11644
- function stringifyItem({ start, key, sep: sep3, value }) {
11644
+ function stringifyItem({ start, key, sep: sep4, value }) {
11645
11645
  let res = "";
11646
11646
  for (const st of start)
11647
11647
  res += st.source;
11648
11648
  if (key)
11649
11649
  res += stringifyToken(key);
11650
- if (sep3)
11651
- for (const st of sep3)
11650
+ if (sep4)
11651
+ for (const st of sep4)
11652
11652
  res += st.source;
11653
11653
  if (value)
11654
11654
  res += stringifyToken(value);
@@ -12815,18 +12815,18 @@ var require_parser = __commonJS({
12815
12815
  if (this.type === "map-value-ind") {
12816
12816
  const prev = getPrevProps(this.peek(2));
12817
12817
  const start = getFirstKeyStartProps(prev);
12818
- let sep3;
12818
+ let sep4;
12819
12819
  if (scalar.end) {
12820
- sep3 = scalar.end;
12821
- sep3.push(this.sourceToken);
12820
+ sep4 = scalar.end;
12821
+ sep4.push(this.sourceToken);
12822
12822
  delete scalar.end;
12823
12823
  } else
12824
- sep3 = [this.sourceToken];
12824
+ sep4 = [this.sourceToken];
12825
12825
  const map = {
12826
12826
  type: "block-map",
12827
12827
  offset: scalar.offset,
12828
12828
  indent: scalar.indent,
12829
- items: [{ start, key: scalar, sep: sep3 }]
12829
+ items: [{ start, key: scalar, sep: sep4 }]
12830
12830
  };
12831
12831
  this.onKeyLine = true;
12832
12832
  this.stack[this.stack.length - 1] = map;
@@ -12979,15 +12979,15 @@ var require_parser = __commonJS({
12979
12979
  } else if (isFlowToken(it.key) && !includesToken(it.sep, "newline")) {
12980
12980
  const start2 = getFirstKeyStartProps(it.start);
12981
12981
  const key = it.key;
12982
- const sep3 = it.sep;
12983
- sep3.push(this.sourceToken);
12982
+ const sep4 = it.sep;
12983
+ sep4.push(this.sourceToken);
12984
12984
  delete it.key;
12985
12985
  delete it.sep;
12986
12986
  this.stack.push({
12987
12987
  type: "block-map",
12988
12988
  offset: this.offset,
12989
12989
  indent: this.indent,
12990
- items: [{ start: start2, key, sep: sep3 }]
12990
+ items: [{ start: start2, key, sep: sep4 }]
12991
12991
  });
12992
12992
  } else if (start.length > 0) {
12993
12993
  it.sep = it.sep.concat(start, this.sourceToken);
@@ -13181,13 +13181,13 @@ var require_parser = __commonJS({
13181
13181
  const prev = getPrevProps(parent);
13182
13182
  const start = getFirstKeyStartProps(prev);
13183
13183
  fixFlowSeqItems(fc);
13184
- const sep3 = fc.end.splice(1, fc.end.length);
13185
- sep3.push(this.sourceToken);
13184
+ const sep4 = fc.end.splice(1, fc.end.length);
13185
+ sep4.push(this.sourceToken);
13186
13186
  const map = {
13187
13187
  type: "block-map",
13188
13188
  offset: fc.offset,
13189
13189
  indent: fc.indent,
13190
- items: [{ start, key: fc, sep: sep3 }]
13190
+ items: [{ start, key: fc, sep: sep4 }]
13191
13191
  };
13192
13192
  this.onKeyLine = true;
13193
13193
  this.stack[this.stack.length - 1] = map;
@@ -14036,7 +14036,7 @@ function configureNetworkFamilyDefaults(network = net) {
14036
14036
  configureNetworkFamilyDefaults();
14037
14037
 
14038
14038
  // apps/body/dist/cli.js
14039
- import { dirname as dirname31, resolve as resolve44 } from "node:path";
14039
+ import { dirname as dirname32, resolve as resolve48 } from "node:path";
14040
14040
  import { stdin as stdin4, stdout as stdout5 } from "node:process";
14041
14041
 
14042
14042
  // node_modules/@clack/core/dist/index.mjs
@@ -15476,7 +15476,7 @@ function parseCursorModelsOutput(output) {
15476
15476
  };
15477
15477
  }
15478
15478
  async function enumerateCursorModels(env = process.env) {
15479
- return new Promise((resolve45) => {
15479
+ return new Promise((resolve49) => {
15480
15480
  const child = spawn2("cursor-agent", ["models"], {
15481
15481
  env,
15482
15482
  stdio: ["ignore", "pipe", "ignore"]
@@ -15490,11 +15490,11 @@ async function enumerateCursorModels(env = process.env) {
15490
15490
  });
15491
15491
  child.on("error", () => {
15492
15492
  clearTimeout(timer);
15493
- resolve45(void 0);
15493
+ resolve49(void 0);
15494
15494
  });
15495
15495
  child.on("close", (code) => {
15496
15496
  clearTimeout(timer);
15497
- resolve45(code === 0 ? parseCursorModelsOutput(output) : void 0);
15497
+ resolve49(code === 0 ? parseCursorModelsOutput(output) : void 0);
15498
15498
  });
15499
15499
  });
15500
15500
  }
@@ -15921,13 +15921,13 @@ var CursorAcpServer = class {
15921
15921
  consumeLine(line);
15922
15922
  });
15923
15923
  try {
15924
- const { code, signal } = await new Promise((resolve45) => {
15924
+ const { code, signal } = await new Promise((resolve49) => {
15925
15925
  let settled = false;
15926
15926
  const finish = (exitCode, exitSignal) => {
15927
15927
  if (settled)
15928
15928
  return;
15929
15929
  settled = true;
15930
- resolve45({ code: exitCode, signal: exitSignal });
15930
+ resolve49({ code: exitCode, signal: exitSignal });
15931
15931
  };
15932
15932
  child.once("error", (error) => {
15933
15933
  spawnError = error instanceof Error ? error.message : String(error);
@@ -16072,10 +16072,10 @@ function releaseSquireConnectSession(log2, owner = "") {
16072
16072
  function squireChromeProfileDir() {
16073
16073
  return process.env.TRUSTY_SQUIRE_PROFILE_DIR ?? squireHostPaths(homedir2()).profileDir;
16074
16074
  }
16075
- var defaultShellRunner = (command, args) => new Promise((resolve45) => {
16075
+ var defaultShellRunner = (command, args) => new Promise((resolve49) => {
16076
16076
  execFile(command, [...args], { timeout: 12e4, maxBuffer: 4 * 1024 * 1024, encoding: "utf8" }, (error, stdout6, stderr) => {
16077
16077
  const code = error?.code;
16078
- resolve45({
16078
+ resolve49({
16079
16079
  code: typeof code === "number" ? code : error ? 1 : 0,
16080
16080
  stdout: String(stdout6 ?? ""),
16081
16081
  stderr: String(stderr ?? "")
@@ -16100,7 +16100,7 @@ function killConnectTree(child) {
16100
16100
  }
16101
16101
  child.kill();
16102
16102
  }
16103
- var defaultStreamedRunner = (command, args, env, owner = "") => new Promise((resolve45) => {
16103
+ var defaultStreamedRunner = (command, args, env, owner = "") => new Promise((resolve49) => {
16104
16104
  const child = spawn5(command, args, {
16105
16105
  stdio: ["ignore", "pipe", "pipe"],
16106
16106
  env: env ?? squireConnectProcessEnv(),
@@ -16114,7 +16114,7 @@ var defaultStreamedRunner = (command, args, env, owner = "") => new Promise((res
16114
16114
  const safetyTimer = setTimeout(() => {
16115
16115
  if (!resolved) {
16116
16116
  resolved = true;
16117
- resolve45({ stdout: stdout6, stderr, pid: child.pid ?? void 0, report, abort: () => {
16117
+ resolve49({ stdout: stdout6, stderr, pid: child.pid ?? void 0, report, abort: () => {
16118
16118
  } });
16119
16119
  }
16120
16120
  killConnectTree(child);
@@ -16149,7 +16149,7 @@ var defaultStreamedRunner = (command, args, env, owner = "") => new Promise((res
16149
16149
  const finish = (result) => {
16150
16150
  if (!resolved) {
16151
16151
  resolved = true;
16152
- resolve45(result);
16152
+ resolve49(result);
16153
16153
  }
16154
16154
  };
16155
16155
  const settle = (result) => {
@@ -16641,13 +16641,13 @@ var StdioSquireMcpClient = class {
16641
16641
  const child = this.child;
16642
16642
  if (!child)
16643
16643
  return Promise.reject(new Error("Squire MCP session is not running"));
16644
- return new Promise((resolve45, reject) => {
16644
+ return new Promise((resolve49, reject) => {
16645
16645
  const timeoutMs = method === "initialize" ? INITIALIZE_TIMEOUT_MS : CALL_TIMEOUT_MS;
16646
16646
  const timer = setTimeout(() => {
16647
16647
  this.pending.delete(id);
16648
16648
  reject(new Error(`${toolName2 ?? method} timed out after ${timeoutMs}ms`));
16649
16649
  }, timeoutMs);
16650
- this.pending.set(id, { resolve: resolve45, reject, timer });
16650
+ this.pending.set(id, { resolve: resolve49, reject, timer });
16651
16651
  child.stdin.write(`${JSON.stringify({ jsonrpc: "2.0", id, method, params })}
16652
16652
  `);
16653
16653
  });
@@ -16809,9 +16809,9 @@ var SquireTaskRelay = class {
16809
16809
  response.writeHead(400, { "content-type": "application/json" }).end(JSON.stringify({ error: error instanceof Error ? error.message : "Squire relay failed" }));
16810
16810
  }
16811
16811
  });
16812
- await new Promise((resolve45, reject) => {
16812
+ await new Promise((resolve49, reject) => {
16813
16813
  server.once("error", reject);
16814
- server.listen(0, "127.0.0.1", resolve45);
16814
+ server.listen(0, "127.0.0.1", resolve49);
16815
16815
  });
16816
16816
  this.server = server;
16817
16817
  const address = server.address();
@@ -17850,11 +17850,11 @@ var RegistryMcpHostBroker = class {
17850
17850
  })();
17851
17851
  });
17852
17852
  });
17853
- await new Promise((resolve45, reject) => {
17853
+ await new Promise((resolve49, reject) => {
17854
17854
  this.server.once("error", reject);
17855
17855
  this.server.listen(this.socketPath, () => {
17856
17856
  this.server.off("error", reject);
17857
- resolve45();
17857
+ resolve49();
17858
17858
  });
17859
17859
  });
17860
17860
  chmodSync(this.socketPath, 384);
@@ -17863,12 +17863,12 @@ var RegistryMcpHostBroker = class {
17863
17863
  const server = this.server;
17864
17864
  this.server = void 0;
17865
17865
  if (server)
17866
- await new Promise((resolve45) => server.close(() => resolve45()));
17866
+ await new Promise((resolve49) => server.close(() => resolve49()));
17867
17867
  rmSync(this.socketPath, { force: true });
17868
17868
  }
17869
17869
  };
17870
17870
  async function brokerRequest(socketPath, request) {
17871
- return new Promise((resolve45, reject) => {
17871
+ return new Promise((resolve49, reject) => {
17872
17872
  const socket = createConnection3(socketPath);
17873
17873
  let output = "";
17874
17874
  socket.setEncoding("utf8");
@@ -17885,7 +17885,7 @@ async function brokerRequest(socketPath, request) {
17885
17885
  throw new Error(parsed.error);
17886
17886
  if (!Array.isArray(parsed.messages) || !parsed.messages.every((entry) => typeof entry === "string"))
17887
17887
  throw new Error("Registry MCP broker returned an invalid response");
17888
- resolve45(parsed.messages);
17888
+ resolve49(parsed.messages);
17889
17889
  } catch (error) {
17890
17890
  reject(error);
17891
17891
  }
@@ -18099,7 +18099,8 @@ var TURN_SILENCE_KINDS = [
18099
18099
  "helper-out-of-date",
18100
18100
  "update-interrupted",
18101
18101
  "offline",
18102
- "context-overflow"
18102
+ "context-overflow",
18103
+ "resource-limit"
18103
18104
  ];
18104
18105
  var TURN_RECEIPT_REASON_KINDS = [
18105
18106
  "hiccup",
@@ -18111,6 +18112,7 @@ var TURN_RECEIPT_REASON_KINDS = [
18111
18112
  "update-interrupted",
18112
18113
  "offline",
18113
18114
  "context-overflow",
18115
+ "resource-limit",
18114
18116
  "model-selection-unavailable"
18115
18117
  ];
18116
18118
  function isTurnReceiptReasonKind(value) {
@@ -18158,6 +18160,9 @@ function classifyTurnSilence(reason, reasonKind) {
18158
18160
  if (isContextOverflowFault(text2)) {
18159
18161
  return { kind: "context-overflow" };
18160
18162
  }
18163
+ if (/\bresource_limit: ACP session exceeded its \d+ MiB memory limit\b/i.test(text2)) {
18164
+ return { kind: "resource-limit" };
18165
+ }
18161
18166
  if (/\b402\b/.test(text2) || /usage limit/i.test(text2) || /more credits/i.test(text2) || /quota/i.test(text2) || /allowance is spent/i.test(text2)) {
18162
18167
  return {
18163
18168
  kind: "allowance-spent",
@@ -19354,7 +19359,7 @@ var AgentSignIn = class {
19354
19359
  };
19355
19360
  for (const name of ISOLATION_VARIABLES)
19356
19361
  delete env[name];
19357
- return new Promise((resolve45, reject) => {
19362
+ return new Promise((resolve49, reject) => {
19358
19363
  let output = "";
19359
19364
  let answered = false;
19360
19365
  let child;
@@ -19395,7 +19400,7 @@ var AgentSignIn = class {
19395
19400
  return;
19396
19401
  answered = true;
19397
19402
  clearTimeout(linkTimer);
19398
- resolve45(link2);
19403
+ resolve49(link2);
19399
19404
  };
19400
19405
  child.stdout?.on("data", read2);
19401
19406
  child.stderr?.on("data", read2);
@@ -29228,13 +29233,13 @@ var RoomSupervisor = class {
29228
29233
  */
29229
29234
  retryDelay(failures, signal, since = this.#wakes) {
29230
29235
  const delay = this.delaysMs[failures - 1];
29231
- return new Promise((resolve45) => {
29236
+ return new Promise((resolve49) => {
29232
29237
  let timer;
29233
29238
  const done = () => {
29234
29239
  clearTimeout(timer);
29235
29240
  this.#parked.delete(done);
29236
29241
  signal?.removeEventListener("abort", done);
29237
- resolve45();
29242
+ resolve49();
29238
29243
  };
29239
29244
  this.#parked.add(done);
29240
29245
  signal?.addEventListener("abort", done, { once: true });
@@ -29426,12 +29431,12 @@ async function retryBeforeReady(work, options) {
29426
29431
  if (wait2 <= 0)
29427
29432
  break;
29428
29433
  await options.extendStartTimeout(wait2 + 15e3);
29429
- await new Promise((resolve45) => {
29434
+ await new Promise((resolve49) => {
29430
29435
  const timer = setTimeout(done, wait2);
29431
29436
  function done() {
29432
29437
  clearTimeout(timer);
29433
29438
  options.signal?.removeEventListener("abort", done);
29434
- resolve45();
29439
+ resolve49();
29435
29440
  }
29436
29441
  wake = done;
29437
29442
  options.signal?.addEventListener("abort", done, { once: true });
@@ -29599,6 +29604,94 @@ import { resolve as resolve20 } from "node:path";
29599
29604
  import { spawn as spawn11 } from "node:child_process";
29600
29605
  import { EventEmitter } from "node:events";
29601
29606
 
29607
+ // apps/body/dist/acp-resource-scope.js
29608
+ import { execFile as execFile6 } from "node:child_process";
29609
+ import { randomUUID as randomUUID6 } from "node:crypto";
29610
+ import { readFileSync as readFileSync4 } from "node:fs";
29611
+ import { totalmem } from "node:os";
29612
+ import { promisify as promisify5 } from "node:util";
29613
+ var execFileAsync5 = promisify5(execFile6);
29614
+ function acpSessionMemoryMaxBytes(hostMemoryBytes = totalmem()) {
29615
+ return Math.max(8 * 1024 ** 3, Math.floor(hostMemoryBytes / 4));
29616
+ }
29617
+ var ACP_SESSION_MEMORY_MAX_BYTES = acpSessionMemoryMaxBytes();
29618
+ var AcpResourceScope = class {
29619
+ memoryMaxBytes;
29620
+ unit = `beeline-acp-${randomUUID6()}.scope`;
29621
+ #stop;
29622
+ constructor(memoryMaxBytes = ACP_SESSION_MEMORY_MAX_BYTES) {
29623
+ this.memoryMaxBytes = memoryMaxBytes;
29624
+ }
29625
+ launch(command, args, agentEnv) {
29626
+ const env = { ...agentEnv };
29627
+ const stripBus = !Object.hasOwn(agentEnv, "DBUS_SESSION_BUS_ADDRESS");
29628
+ if (stripBus && process.env.DBUS_SESSION_BUS_ADDRESS)
29629
+ env.DBUS_SESSION_BUS_ADDRESS = process.env.DBUS_SESSION_BUS_ADDRESS;
29630
+ if (!env.XDG_RUNTIME_DIR && process.env.XDG_RUNTIME_DIR)
29631
+ env.XDG_RUNTIME_DIR = process.env.XDG_RUNTIME_DIR;
29632
+ const stripRuntime = !Object.hasOwn(agentEnv, "XDG_RUNTIME_DIR");
29633
+ const owner = managedServiceUnit();
29634
+ return {
29635
+ command: "systemd-run",
29636
+ args: [
29637
+ "--user",
29638
+ "--scope",
29639
+ "--quiet",
29640
+ "--same-dir",
29641
+ `--unit=${this.unit}`,
29642
+ `--property=MemoryMax=${this.memoryMaxBytes}`,
29643
+ "--property=MemorySwapMax=0",
29644
+ "--property=OOMPolicy=kill",
29645
+ "--property=KillMode=control-group",
29646
+ "--property=TimeoutStopSec=1s",
29647
+ ...owner ? [`--property=BindsTo=${owner}`, `--property=After=${owner}`] : [],
29648
+ "/usr/bin/env",
29649
+ ...stripBus ? ["-u", "DBUS_SESSION_BUS_ADDRESS"] : [],
29650
+ ...stripRuntime ? ["-u", "XDG_RUNTIME_DIR"] : [],
29651
+ command,
29652
+ ...args
29653
+ ],
29654
+ env
29655
+ };
29656
+ }
29657
+ /** An OOM result survives process exit until reset-failed unloads the unit. */
29658
+ async exceededMemoryLimit() {
29659
+ try {
29660
+ const { stdout: stdout6 } = await execFileAsync5("systemctl", ["--user", "show", this.unit, "--property=Result", "--value"], { timeout: 5e3 });
29661
+ return stdout6.trim() === "oom-kill";
29662
+ } catch {
29663
+ return false;
29664
+ }
29665
+ }
29666
+ async stop() {
29667
+ return this.#stop ??= (async () => {
29668
+ try {
29669
+ await execFileAsync5("systemctl", ["--user", "stop", this.unit], { timeout: 5e3 });
29670
+ } catch (error) {
29671
+ const { stdout: stdout6 } = await execFileAsync5("systemctl", ["--user", "show", this.unit, "--property=LoadState", "--value"], { timeout: 5e3 });
29672
+ if (stdout6.trim() !== "not-found")
29673
+ throw error;
29674
+ } finally {
29675
+ await execFileAsync5("systemctl", ["--user", "reset-failed", this.unit], { timeout: 5e3 }).catch(() => void 0);
29676
+ }
29677
+ })().catch((error) => {
29678
+ this.#stop = void 0;
29679
+ throw error;
29680
+ });
29681
+ }
29682
+ };
29683
+ function managedServiceUnit() {
29684
+ if (process.env.BEELINE_MANAGED_BY_SYSTEMD !== "1")
29685
+ return void 0;
29686
+ try {
29687
+ const cgroup = readFileSync4("/proc/self/cgroup", "utf8");
29688
+ const path = cgroup.split("\n").find((line) => line.startsWith("0::"))?.slice(3);
29689
+ return path?.split("/").find((part) => /^beeline-(?:helper|agent@.+)\.service$/.test(part));
29690
+ } catch {
29691
+ return void 0;
29692
+ }
29693
+ }
29694
+
29602
29695
  // apps/body/dist/harness-capabilities.js
29603
29696
  var PROFILES = [
29604
29697
  {
@@ -29912,6 +30005,13 @@ var AcpRuntimeExitedError = class extends Error {
29912
30005
  this.name = "AcpRuntimeExitedError";
29913
30006
  }
29914
30007
  };
30008
+ var AcpResourceLimitError = class extends Error {
30009
+ cause = "resource_limit";
30010
+ constructor(memoryMaxBytes) {
30011
+ super(`resource_limit: ACP session exceeded its ${Math.floor(memoryMaxBytes / 1024 / 1024)} MiB memory limit`);
30012
+ this.name = "AcpResourceLimitError";
30013
+ }
30014
+ };
29915
30015
  function killChildProcessGroup(child, signal) {
29916
30016
  if (!child.pid)
29917
30017
  return;
@@ -30196,6 +30296,10 @@ var AcpClient = class extends EventEmitter {
30196
30296
  permissionAllowlist;
30197
30297
  commandsHandler;
30198
30298
  oomKills;
30299
+ useResourceScope;
30300
+ resourceScopeMemoryMaxBytes;
30301
+ resourceScope;
30302
+ resourceScopeUnavailable = false;
30199
30303
  /** A deliberate stop owns its SIGKILL; that exit is never labelled OOM. */
30200
30304
  stopping = false;
30201
30305
  constructor(opts) {
@@ -30216,21 +30320,25 @@ var AcpClient = class extends EventEmitter {
30216
30320
  this.permissionAllowlist = opts.permissionAllowlist;
30217
30321
  this.commandsHandler = opts.onCommands;
30218
30322
  this.oomKills = opts.oomKills ?? new OomKillTracker(cgroupOomKillProbe());
30323
+ this.useResourceScope = opts.resourceScope === "systemd" || opts.resourceScope === void 0 && process.platform === "linux" && process.env.BEELINE_MANAGED_BY_SYSTEMD === "1";
30324
+ this.resourceScopeMemoryMaxBytes = opts.resourceScopeMemoryMaxBytes;
30219
30325
  }
30220
30326
  async start(timeoutMs = 6e4) {
30221
30327
  if (this.alive)
30222
30328
  return;
30223
30329
  await this.oomKills.prime().catch(() => void 0);
30224
30330
  this.stopping = false;
30225
- this.child = await withAdapterInstallLock(() => spawn11(this.agentCommand, this.agentArgs, {
30331
+ const childEnv = this.inheritProcessEnv ? { ...process.env, ...this.agentEnv } : this.agentEnv;
30332
+ this.resourceScope = this.useResourceScope && !this.resourceScopeUnavailable ? new AcpResourceScope(this.resourceScopeMemoryMaxBytes) : void 0;
30333
+ const launch = this.resourceScope?.launch(this.agentCommand, this.agentArgs, childEnv);
30334
+ this.child = await withAdapterInstallLock(() => spawn11(launch?.command ?? this.agentCommand, launch?.args ?? this.agentArgs, {
30226
30335
  // agentEnv is the child's whole environment: buildAgentEnv's allowlist is
30227
30336
  // a real boundary, not a decorative one layered over a full inherit.
30228
- env: this.inheritProcessEnv ? { ...process.env, ...this.agentEnv } : this.agentEnv,
30337
+ env: launch?.env ?? childEnv,
30229
30338
  ...this.agentCwd ? { cwd: this.agentCwd } : {},
30230
- // The harness and every tool it spawns share a disposable process
30231
- // group. A hard turn deadline can therefore retire the whole tree,
30232
- // never just the ACP parent while a shell/compiler keeps running.
30233
- detached: process.platform !== "win32",
30339
+ // Managed Linux sessions use a cgroup scope. The process-group fallback
30340
+ // covers helpers without a user systemd manager.
30341
+ detached: !launch && process.platform !== "win32",
30234
30342
  stdio: ["pipe", "pipe", "pipe"]
30235
30343
  }));
30236
30344
  this.alive = true;
@@ -30265,10 +30373,35 @@ var AcpClient = class extends EventEmitter {
30265
30373
  if (this.listenerCount("error") > 0)
30266
30374
  this.emit("error", err);
30267
30375
  });
30268
- const initResult = await this.request("initialize", {
30269
- protocolVersion: 1,
30270
- clientCapabilities: {}
30271
- }, timeoutMs);
30376
+ let initResult;
30377
+ try {
30378
+ initResult = await this.request("initialize", {
30379
+ protocolVersion: 1,
30380
+ clientCapabilities: {}
30381
+ }, timeoutMs);
30382
+ } catch (error) {
30383
+ if (launch && /EPIPE/.test(String(error)) && this.child?.exitCode === null) {
30384
+ await new Promise((resolve49) => {
30385
+ const timer = setTimeout(resolve49, 250);
30386
+ this.child?.once("close", () => {
30387
+ clearTimeout(timer);
30388
+ resolve49();
30389
+ });
30390
+ });
30391
+ }
30392
+ const scopeUnavailable = launch && !this.resourceScopeUnavailable && /(?:Failed to connect to bus|Failed to create bus connection|spawn systemd-run ENOENT)/i.test(`${this.stderrTail}
30393
+ ${String(error)}`);
30394
+ await this.stop().catch(() => void 0);
30395
+ if (scopeUnavailable) {
30396
+ this.resourceScopeUnavailable = true;
30397
+ this.resourceScope = void 0;
30398
+ this.child = null;
30399
+ this.alive = false;
30400
+ console.warn("[acp] systemd user scope unavailable; starting ACP session in a process group");
30401
+ return this.start(timeoutMs);
30402
+ }
30403
+ throw error;
30404
+ }
30272
30405
  const initMeta = initResult._meta;
30273
30406
  const steering = initMeta?.steering;
30274
30407
  this.supportsStandardSteering = steering?.supported === true;
@@ -30281,22 +30414,25 @@ var AcpClient = class extends EventEmitter {
30281
30414
  }
30282
30415
  /**
30283
30416
  * One child exit: reject every in-flight request so the turn fails and is
30284
- * reported instead of hanging, then publish the exit. A SIGKILL is checked
30285
- * against the daemon cgroup's OOM counter so the rejection can name the real
30286
- * cause instead of a bare signal.
30417
+ * reported instead of hanging, then publish the exit. A scoped exit reads
30418
+ * that scope's result; an unscoped SIGKILL uses the daemon cgroup's OOM
30419
+ * counter so the rejection can name the cause instead of a bare signal.
30287
30420
  */
30288
30421
  async handleChildExit(code, signal) {
30422
+ const child = this.child;
30289
30423
  this.alive = false;
30290
30424
  for (const p of this.pending.values())
30291
30425
  this.clearTimer(p);
30426
+ const scope = this.resourceScope;
30427
+ const memoryLimited = scope && !this.stopping ? await scope.exceededMemoryLimit() : false;
30292
30428
  let oomKilled = false;
30293
- if (signal === "SIGKILL" && !this.stopping) {
30429
+ if (!memoryLimited && signal === "SIGKILL" && !this.stopping) {
30294
30430
  let diagnosticTimer;
30295
30431
  try {
30296
30432
  oomKilled = await Promise.race([
30297
30433
  this.oomKills.consume().catch(() => false),
30298
- new Promise((resolve45) => {
30299
- diagnosticTimer = setTimeout(() => resolve45(false), 100);
30434
+ new Promise((resolve49) => {
30435
+ diagnosticTimer = setTimeout(() => resolve49(false), 100);
30300
30436
  })
30301
30437
  ]);
30302
30438
  } finally {
@@ -30308,13 +30444,21 @@ var AcpClient = class extends EventEmitter {
30308
30444
  const stderrSuffix = meaningful ? `: ${meaningful}` : "";
30309
30445
  for (const [, p] of this.pending) {
30310
30446
  this.clearTimer(p);
30311
- p.reject(new AcpRuntimeExitedError(`${exitText}${stderrSuffix}`));
30447
+ p.reject(memoryLimited ? new AcpResourceLimitError(scope.memoryMaxBytes) : new AcpRuntimeExitedError(`${exitText}${stderrSuffix}`));
30312
30448
  }
30313
30449
  this.pending.clear();
30314
30450
  this.activeRunIds.clear();
30315
30451
  this.activePromptSessions.clear();
30316
30452
  this.toolCallMetadata.clear();
30317
30453
  this.sessionCommands.clear();
30454
+ if (scope) {
30455
+ await scope.stop().then(() => {
30456
+ if (this.resourceScope === scope)
30457
+ this.resourceScope = void 0;
30458
+ if (this.child === child)
30459
+ this.child = null;
30460
+ }).catch((error) => console.error("[acp] resource scope cleanup failed:", error));
30461
+ }
30318
30462
  this.emit("exit", { code, signal });
30319
30463
  }
30320
30464
  failRuntime(detail) {
@@ -30324,27 +30468,36 @@ var AcpClient = class extends EventEmitter {
30324
30468
  p.reject(new AcpRuntimeExitedError(detail));
30325
30469
  }
30326
30470
  this.pending.clear();
30471
+ if (this.resourceScope)
30472
+ void this.resourceScope.stop().catch((error) => console.error("[acp] resource scope cleanup failed:", error));
30327
30473
  }
30328
30474
  async stop() {
30329
30475
  const child = this.child;
30330
- if (!child)
30476
+ const scope = this.resourceScope;
30477
+ if (!child && !scope)
30331
30478
  return;
30332
30479
  this.stopping = true;
30333
30480
  try {
30334
- if (this.child?.stdin.writable) {
30481
+ if (child?.stdin.writable) {
30335
30482
  this.notify("shutdown", {});
30336
30483
  }
30337
30484
  } catch {
30338
30485
  }
30339
- await new Promise((r2) => setTimeout(r2, 300));
30340
- try {
30341
- killChildProcessGroup(child, "SIGTERM");
30342
- } catch {
30343
- }
30344
- await new Promise((r2) => setTimeout(r2, 500));
30345
- try {
30346
- killChildProcessGroup(child, "SIGKILL");
30347
- } catch {
30486
+ if (scope) {
30487
+ await scope.stop();
30488
+ if (this.resourceScope === scope)
30489
+ this.resourceScope = void 0;
30490
+ } else if (child) {
30491
+ await new Promise((r2) => setTimeout(r2, 300));
30492
+ try {
30493
+ killChildProcessGroup(child, "SIGTERM");
30494
+ } catch {
30495
+ }
30496
+ await new Promise((r2) => setTimeout(r2, 500));
30497
+ try {
30498
+ killChildProcessGroup(child, "SIGKILL");
30499
+ } catch {
30500
+ }
30348
30501
  }
30349
30502
  this.child = null;
30350
30503
  this.alive = false;
@@ -30720,7 +30873,7 @@ var AcpClient = class extends EventEmitter {
30720
30873
  const current = this.activeRunIds.get(sessionId);
30721
30874
  if (current)
30722
30875
  return Promise.resolve(current);
30723
- return new Promise((resolve45, reject) => {
30876
+ return new Promise((resolve49, reject) => {
30724
30877
  const onUpdate = (update) => {
30725
30878
  if (update.sessionId !== sessionId)
30726
30879
  return;
@@ -30728,7 +30881,7 @@ var AcpClient = class extends EventEmitter {
30728
30881
  if (!runId)
30729
30882
  return;
30730
30883
  cleanup();
30731
- resolve45(runId);
30884
+ resolve49(runId);
30732
30885
  };
30733
30886
  const timer = setTimeout(() => {
30734
30887
  cleanup();
@@ -30807,14 +30960,14 @@ var AcpClient = class extends EventEmitter {
30807
30960
  }
30808
30961
  const id = this.nextId++;
30809
30962
  const payload = { jsonrpc: "2.0", id, method, params };
30810
- return new Promise((resolve45, reject) => {
30963
+ return new Promise((resolve49, reject) => {
30811
30964
  const timer = backstop ? void 0 : setTimeout(() => {
30812
30965
  this.pending.delete(id);
30813
30966
  reject(new AcpRequestTimeoutError(method, timeoutMs, this.stderrTail, false, detail));
30814
30967
  }, timeoutMs);
30815
30968
  const sessionId = params?.sessionId;
30816
30969
  this.pending.set(id, {
30817
- resolve: resolve45,
30970
+ resolve: resolve49,
30818
30971
  reject,
30819
30972
  timer,
30820
30973
  method,
@@ -30845,7 +30998,7 @@ var AcpClient = class extends EventEmitter {
30845
30998
 
30846
30999
  // apps/body/dist/agent-home.js
30847
31000
  var import_yaml2 = __toESM(require_dist(), 1);
30848
- import { existsSync as existsSync7, readFileSync as readFileSync5, watch } from "node:fs";
31001
+ import { existsSync as existsSync7, readFileSync as readFileSync6, watch } from "node:fs";
30849
31002
 
30850
31003
  // node_modules/smol-toml/dist/date.js
30851
31004
  var DATE_TIME_RE = /^(\d{4}-\d{2}-\d{2})?[T ]?(?:(\d{2}):\d{2}(?::\d{2}(?:\.\d+)?)?)?(Z|[-+]\d{2}:\d{2})?$/i;
@@ -31013,7 +31166,7 @@ function skipVoid(ctx, banNewLines, banComments) {
31013
31166
  skipComment(ctx);
31014
31167
  }
31015
31168
  }
31016
- function skipUntil(ctx, sep3, end) {
31169
+ function skipUntil(ctx, sep4, end) {
31017
31170
  let ptr = ctx.p;
31018
31171
  if (!end) {
31019
31172
  ptr = indexOfNewline(ctx.s, ptr);
@@ -31024,7 +31177,7 @@ function skipUntil(ctx, sep3, end) {
31024
31177
  let c2 = ctx.s.charCodeAt(ctx.p);
31025
31178
  if (c2 === 35) {
31026
31179
  skipComment(ctx);
31027
- } else if (c2 === end || c2 === sep3) {
31180
+ } else if (c2 === end || c2 === sep4) {
31028
31181
  return;
31029
31182
  }
31030
31183
  }
@@ -31642,7 +31795,7 @@ function stringify(obj, { maxDepth = 1e3, numbersAsFloat = false } = {}) {
31642
31795
  }
31643
31796
 
31644
31797
  // apps/body/dist/agent-home.js
31645
- import { createHash as createHash7, randomUUID as randomUUID6 } from "node:crypto";
31798
+ import { createHash as createHash7, randomUUID as randomUUID7 } from "node:crypto";
31646
31799
  import { chmod as chmod5, copyFile, lstat as lstat3, mkdir as mkdir11, readFile as readFile16, readlink, readdir as readdir4, realpath, rename as rename7, rm as rm6, symlink as symlink2, unlink as unlink5, writeFile as writeFile9 } from "node:fs/promises";
31647
31800
  import { homedir as homedir11 } from "node:os";
31648
31801
  import { basename as basename3, dirname as dirname12, join as join12, relative, resolve as resolve16, sep } from "node:path";
@@ -31768,7 +31921,7 @@ function androidAgentEnv(input) {
31768
31921
  }
31769
31922
 
31770
31923
  // apps/body/dist/beeline-skill.js
31771
- import { readFileSync as readFileSync4 } from "node:fs";
31924
+ import { readFileSync as readFileSync5 } from "node:fs";
31772
31925
  import { resolve as resolve13 } from "node:path";
31773
31926
 
31774
31927
  // packages/api-contract/dist/phone-types.js
@@ -32275,7 +32428,7 @@ var BEELINE_ROOM_MECHANICS = [
32275
32428
  "If you need reach outside the sandbox, call beeline-agent request_grant. If you already know discrete options, call beeline-agent ask_choice (one human, optional) or open_poll (every human in this Room, required deadline). A poll is refused below two electors and above fifty, and in a DM. A plurality is a fact, never permission to deploy, delete, merge, or spend. Open-ended asks stay tagged prose. Never put Always / Once / No on a preference.",
32276
32429
  "To state something that happened so the Room and other agents can act on it, call beeline-agent emit_event with your own agent:<slug> kind, one sentence, and optionally the agent members to wake. Chains of events are bounded and a refused emit posts nothing."
32277
32430
  ].join(" ");
32278
- function runningBeelineReleaseId(env = process.env, read2 = (path) => readFileSync4(path, "utf8")) {
32431
+ function runningBeelineReleaseId(env = process.env, read2 = (path) => readFileSync5(path, "utf8")) {
32279
32432
  try {
32280
32433
  const lib = env.BEELINE_LIB_DIR;
32281
32434
  if (!lib)
@@ -32312,7 +32465,7 @@ The tools this build knows, what each is for, and which the owner of this machin
32312
32465
 
32313
32466
  **Use available tools before asking the person.** Before asking a person for a code, a status or a file, call workbench_status and check whether a tool or connected app you already have can get it, then use it. This includes an emailed verification code in an already-connected inbox. Ask only when none can, and say why. The key-ownership and grant rules still apply.
32314
32467
 
32315
- **Offer the tool at the moment you need it.** When the work in front of you needs a tool the person does not have, do not send them to a settings page and do not stop at naming it. Call workbench_status first - a tool they already have is used, not offered. In a Room or DM, call offer_connector with the connectorType and one short reason: a card appears there, spoken by you, addressed to the person you are answering, with one action. Connector offers are unavailable in corners; use a Room or DM for those. Your turn pauses on the card - say in prose what you are waiting for and end the turn; you are woken when it is added, and then you carry on.
32468
+ **Offer the tool at the moment you need it.** When the work in front of you needs a tool the person does not have, do not send them to a settings page and do not stop at naming it. Call workbench_status first - a tool they already have is used, not offered. In a Room or DM, call offer_connector with the connectorType and one short reason: a card appears there, spoken by you, addressed to the person you are answering, with one action. Connector offers are unavailable in corners; use a Room or DM for those. When the person wants Squire on a different Google account (or its signed-in account is the wrong one), call offer_connector with connectorType trusty-squire and intent "switch" - a plain connect keeps the account it already has. Your turn pauses on the card - say in prose what you are waiting for and end the turn; you are woken when it is added, and then you carry on.
32316
32469
 
32317
32470
  **Research before you offer, and say so.** Never offer a tool you cannot describe. If someone asks you to install or add something you do not already know - by name, by purpose, or by what it will hold - say plainly that you are looking it up first, find out what it is and what it does with credentials, and state what you learned in your reply BEFORE the card appears. A person reading "Add X?" must already have read, in your own words, what X is. Refusing to act blind is part of being trusted with keys.
32318
32471
 
@@ -33579,7 +33732,7 @@ async function writeBackDetachedClaudeLogin(target, source) {
33579
33732
  const written = await withSharedClaudeLoginLock(shared, async () => {
33580
33733
  if (!await isNewer())
33581
33734
  return false;
33582
- const temp = `${shared}.beeline-${randomUUID6()}`;
33735
+ const temp = `${shared}.beeline-${randomUUID7()}`;
33583
33736
  try {
33584
33737
  await writeFile9(temp, detached, { flag: "wx", mode: 384 });
33585
33738
  await chmod5(temp, 384);
@@ -33596,7 +33749,7 @@ async function writeBackDetachedClaudeLogin(target, source) {
33596
33749
  return "not-newer";
33597
33750
  if (await readFile16(target, "utf8") !== detached)
33598
33751
  return "busy";
33599
- const link2 = `${target}.beeline-link-${randomUUID6()}`;
33752
+ const link2 = `${target}.beeline-link-${randomUUID7()}`;
33600
33753
  await symlink2(source, link2);
33601
33754
  await rename7(link2, target);
33602
33755
  return "linked";
@@ -33626,7 +33779,7 @@ async function repairRoomAgentCredentialLinks(input) {
33626
33779
  if (outcome !== "not-newer")
33627
33780
  continue;
33628
33781
  }
33629
- const quarantine = `${target}.beeline-quarantine-${Date.now()}-${randomUUID6()}`;
33782
+ const quarantine = `${target}.beeline-quarantine-${Date.now()}-${randomUUID7()}`;
33630
33783
  await rename7(target, quarantine);
33631
33784
  }
33632
33785
  await symlink2(source, target);
@@ -33745,7 +33898,7 @@ async function provisionAgentSkillsAndMcp(root, operatorHome, skillReleaseId, fa
33745
33898
  try {
33746
33899
  const source = resolve16(operatorHome, config.toml);
33747
33900
  const target = resolve16(root, config.dir, "config.toml");
33748
- const mcpSection = existsSync7(source) ? localHarnessMcpToml(readFileSync5(source, "utf8")) : void 0;
33901
+ const mcpSection = existsSync7(source) ? localHarnessMcpToml(readFileSync6(source, "utf8")) : void 0;
33749
33902
  const section = config.dir === "codex" ? [CODEX_ROOM_AGENT_LOCKDOWN_TOML, CODEX_ROOM_WEB_SEARCH_TOML, mcpSection].filter(Boolean).join("\n") : mcpSection;
33750
33903
  if (!section) {
33751
33904
  await unlink5(target).catch(() => void 0);
@@ -33765,7 +33918,7 @@ async function provisionAgentSkillsAndMcp(root, operatorHome, skillReleaseId, fa
33765
33918
  const source = resolve16(operatorHome, ".config", "goose", name);
33766
33919
  const target = resolve16(gooseConfigDir, name);
33767
33920
  if (existsSync7(source)) {
33768
- const body = readFileSync5(source, "utf8");
33921
+ const body = readFileSync6(source, "utf8");
33769
33922
  await writeIsolatedHarnessFile(target, name === "config.yaml" ? localGooseConfig(body) : body);
33770
33923
  } else {
33771
33924
  await unlink5(target).catch(() => void 0);
@@ -33843,7 +33996,7 @@ async function applyGrantedHostRoutes(root, operatorHome, granted, agentKind, fa
33843
33996
  if (Object.keys(routes).length === 0)
33844
33997
  continue;
33845
33998
  const target = resolve16(root, config.dir, "config.toml");
33846
- const existing = existsSync7(target) ? readFileSync5(target, "utf8") : void 0;
33999
+ const existing = existsSync7(target) ? readFileSync6(target, "utf8") : void 0;
33847
34000
  const merged = mergeTomlHostRoutes(existing, routes);
33848
34001
  if (merged)
33849
34002
  await writeIsolatedHarnessFile(target, merged);
@@ -33854,7 +34007,7 @@ async function applyGrantedHostRoutes(root, operatorHome, granted, agentKind, fa
33854
34007
  const gooseConfigDir = resolve16(root, "goose", "config");
33855
34008
  await mkdir11(gooseConfigDir, { recursive: true, mode: 448 });
33856
34009
  const target = resolve16(gooseConfigDir, "config.yaml");
33857
- const existing = existsSync7(target) ? readFileSync5(target, "utf8") : void 0;
34010
+ const existing = existsSync7(target) ? readFileSync6(target, "utf8") : void 0;
33858
34011
  const merged = mergeGooseHostRoutes(existing, routes);
33859
34012
  if (merged)
33860
34013
  await writeIsolatedHarnessFile(target, merged);
@@ -33929,7 +34082,7 @@ async function provisionPiCustomModelConfig(root, operatorHome, failClosed, open
33929
34082
  if (resolvedSource !== source) {
33930
34083
  throw new AgentHomeSecurityError(`Pi custom model config resolves through a link: ${source}`);
33931
34084
  }
33932
- const sourceValue = JSON.parse(readFileSync5(resolvedSource, "utf8"));
34085
+ const sourceValue = JSON.parse(readFileSync6(resolvedSource, "utf8"));
33933
34086
  await writeIsolatedHarnessFile(target, `${JSON.stringify(withOpenRouterModelRouting(sourceValue, pin), null, 2)}
33934
34087
  `);
33935
34088
  } catch (error) {
@@ -33941,7 +34094,7 @@ async function provisionPiCustomModelConfig(root, operatorHome, failClosed, open
33941
34094
  }
33942
34095
  function readClaudeUserScopeMcpServers(path) {
33943
34096
  try {
33944
- const parsed = JSON.parse(readFileSync5(path, "utf8"));
34097
+ const parsed = JSON.parse(readFileSync6(path, "utf8"));
33945
34098
  const servers = recordValue2(parsed.mcpServers);
33946
34099
  if (servers)
33947
34100
  return localMcpServers(servers);
@@ -34142,7 +34295,7 @@ function readExistingText(path) {
34142
34295
  if (!existsSync7(path))
34143
34296
  return void 0;
34144
34297
  try {
34145
- return readFileSync5(path, "utf8");
34298
+ return readFileSync6(path, "utf8");
34146
34299
  } catch {
34147
34300
  return void 0;
34148
34301
  }
@@ -34164,7 +34317,7 @@ async function provisionManagedSkillsDir(target, managedSkills, sharedSkills, op
34164
34317
  const plan = await planManagedSkills(managedSkills, sharedSkills, optionalShares);
34165
34318
  if (await materializedSkillManifest(target) === plan.manifest)
34166
34319
  return;
34167
- const staged = resolve16(parent, `.skills.${process.pid}.${randomUUID6()}.tmp`);
34320
+ const staged = resolve16(parent, `.skills.${process.pid}.${randomUUID7()}.tmp`);
34168
34321
  await mkdir11(staged, { mode: 448 });
34169
34322
  try {
34170
34323
  for (const entry of plan.entries) {
@@ -34416,7 +34569,7 @@ async function writeIsolatedHarnessFile(path, content) {
34416
34569
  if (!parentStats.isDirectory() || parentStats.isSymbolicLink()) {
34417
34570
  throw new Error(`isolated harness parent is not a real directory: ${parent}`);
34418
34571
  }
34419
- const temporary = resolve16(parent, `.${basename3(path)}.${process.pid}.${randomUUID6()}.tmp`);
34572
+ const temporary = resolve16(parent, `.${basename3(path)}.${process.pid}.${randomUUID7()}.tmp`);
34420
34573
  try {
34421
34574
  await writeFile9(temporary, content, { mode: 384, flag: "wx" });
34422
34575
  await chmod5(temporary, 384);
@@ -34473,8 +34626,8 @@ function harnessStateDirsFromEnv(env) {
34473
34626
  }
34474
34627
 
34475
34628
  // apps/body/dist/bwrap-sandbox.js
34476
- import { execFile as execFile6, spawnSync } from "node:child_process";
34477
- import { lstatSync, readdirSync as readdirSync3, readFileSync as readFileSync6, rmSync as rmSync2, writeFileSync as writeFileSync3 } from "node:fs";
34629
+ import { execFile as execFile7, spawnSync } from "node:child_process";
34630
+ import { lstatSync, readdirSync as readdirSync3, readFileSync as readFileSync7, rmSync as rmSync2, writeFileSync as writeFileSync3 } from "node:fs";
34478
34631
  import { homedir as homedir12 } from "node:os";
34479
34632
  import { basename as basename4, dirname as dirname13, isAbsolute as isAbsolute2, relative as relative2, resolve as resolve17 } from "node:path";
34480
34633
  var DEFAULT_SANDBOX_POLICY = "bwrap";
@@ -34533,7 +34686,7 @@ var KNOWN_CREDENTIAL_MASK_PATHS = [
34533
34686
  ".secrets.env",
34534
34687
  ".beeline/registry-mcp"
34535
34688
  ];
34536
- function credentialMaskPaths(extraPaths, home = homedir12(), stat10 = (path) => {
34689
+ function credentialMaskPaths(extraPaths, home = homedir12(), stat11 = (path) => {
34537
34690
  try {
34538
34691
  const info = lstatSync(path);
34539
34692
  return { isDirectory: info.isDirectory() };
@@ -34552,7 +34705,7 @@ function credentialMaskPaths(extraPaths, home = homedir12(), stat10 = (path) =>
34552
34705
  if (seen.has(path))
34553
34706
  continue;
34554
34707
  seen.add(path);
34555
- const info = stat10(path);
34708
+ const info = stat11(path);
34556
34709
  if (!info) {
34557
34710
  if (required.has(path))
34558
34711
  masks.push({ path, kind: "dir", create: true });
@@ -34787,7 +34940,7 @@ function readInstallFailure(stateDir) {
34787
34940
  if (!stateDir)
34788
34941
  return void 0;
34789
34942
  try {
34790
- const at = Number.parseInt(readFileSync6(installFailureMarker(stateDir), "utf8").trim(), 10);
34943
+ const at = Number.parseInt(readFileSync7(installFailureMarker(stateDir), "utf8").trim(), 10);
34791
34944
  return Number.isFinite(at) ? at : void 0;
34792
34945
  } catch {
34793
34946
  return void 0;
@@ -34810,8 +34963,8 @@ function clearInstallFailure(stateDir) {
34810
34963
  } catch {
34811
34964
  }
34812
34965
  }
34813
- var runSandboxInstallCommand = (command, args) => new Promise((resolve45) => {
34814
- execFile6(command, [...args], {
34966
+ var runSandboxInstallCommand = (command, args) => new Promise((resolve49) => {
34967
+ execFile7(command, [...args], {
34815
34968
  timeout: INSTALL_TIMEOUT_MS,
34816
34969
  maxBuffer: INSTALL_OUTPUT_LIMIT * 2,
34817
34970
  // A dpkg prompt on a host with a held conffile would otherwise sit on
@@ -34820,7 +34973,7 @@ var runSandboxInstallCommand = (command, args) => new Promise((resolve45) => {
34820
34973
  }, (error, stdout6, stderr) => {
34821
34974
  const code = error && "code" in error && typeof error.code === "number" ? error.code : error ? null : 0;
34822
34975
  const output = [stdout6, stderr].join("").trim();
34823
- resolve45({ code, output: output || (error ? error.message : "") });
34976
+ resolve49({ code, output: output || (error ? error.message : "") });
34824
34977
  });
34825
34978
  });
34826
34979
  function lastLine2(output, fallback) {
@@ -35105,7 +35258,7 @@ function isAllowedAgentModelConfigCategory(category, id) {
35105
35258
  }
35106
35259
 
35107
35260
  // apps/body/dist/model-config.js
35108
- import { lstatSync as lstatSync2, readFileSync as readFileSync7 } from "node:fs";
35261
+ import { lstatSync as lstatSync2, readFileSync as readFileSync8 } from "node:fs";
35109
35262
  import { basename as basename5, resolve as resolve19 } from "node:path";
35110
35263
 
35111
35264
  // apps/body/dist/transient-provider-error.js
@@ -35331,7 +35484,7 @@ function credentialedPiCustomProviders(env) {
35331
35484
  if (!stats.isFile() || stats.isSymbolicLink() || stats.nlink !== 1 || stats.size > 1048576) {
35332
35485
  return held;
35333
35486
  }
35334
- const parsed = JSON.parse(readFileSync7(path, "utf8"));
35487
+ const parsed = JSON.parse(readFileSync8(path, "utf8"));
35335
35488
  const providers = parsed.providers;
35336
35489
  const remember = (name, config) => {
35337
35490
  if (typeof name !== "string" || !name.trim() || !config || typeof config !== "object")
@@ -35564,7 +35717,7 @@ function describeCurrentReleaseOutcome(outcome) {
35564
35717
  async function retryWhileAdapterReinstalls(run2, options = {}) {
35565
35718
  const attempts = options.attempts ?? 12;
35566
35719
  const delayMs = options.delayMs ?? 5e3;
35567
- const sleep4 = options.sleep ?? ((ms) => new Promise((resolve45) => setTimeout(resolve45, ms)));
35720
+ const sleep4 = options.sleep ?? ((ms) => new Promise((resolve49) => setTimeout(resolve49, ms)));
35568
35721
  for (let attempt = 1; ; attempt += 1) {
35569
35722
  try {
35570
35723
  return await run2();
@@ -36792,7 +36945,7 @@ async function runStartCommand(args, interactiveUi, dependencyOverrides = {}) {
36792
36945
 
36793
36946
  // apps/body/dist/connect-command.js
36794
36947
  import { spawn as spawn13 } from "node:child_process";
36795
- import { createHash as createHash9, randomUUID as randomUUID7 } from "node:crypto";
36948
+ import { createHash as createHash9, randomUUID as randomUUID8 } from "node:crypto";
36796
36949
  import { chmod as chmod7, mkdir as mkdir16, readFile as readFile20, unlink as unlink7, writeFile as writeFile13 } from "node:fs/promises";
36797
36950
  import { homedir as homedir15, hostname } from "node:os";
36798
36951
  import { dirname as dirname19, resolve as resolve26 } from "node:path";
@@ -36912,7 +37065,7 @@ async function validateAgentModelSelection(agent, agentEnv, selection) {
36912
37065
  }
36913
37066
 
36914
37067
  // apps/body/dist/config.js
36915
- import { accessSync as accessSync3, constants as constants2, existsSync as existsSync8, readFileSync as readFileSync8 } from "node:fs";
37068
+ import { accessSync as accessSync3, constants as constants2, existsSync as existsSync8, readFileSync as readFileSync9 } from "node:fs";
36916
37069
  import { basename as basename7, dirname as dirname17, resolve as resolve24 } from "node:path";
36917
37070
  function firstExisting2(paths) {
36918
37071
  for (const p of paths) {
@@ -37009,7 +37162,7 @@ function parseEnvFile(path) {
37009
37162
  const out = {};
37010
37163
  if (!existsSync8(path))
37011
37164
  return out;
37012
- const text2 = readFileSync8(path, "utf8");
37165
+ const text2 = readFileSync9(path, "utf8");
37013
37166
  for (const raw of text2.split("\n")) {
37014
37167
  const line = raw.trim();
37015
37168
  if (!line || line.startsWith("#"))
@@ -37856,7 +38009,7 @@ async function readMachineId(env = process.env) {
37856
38009
  if (!/^[0-9a-f-]{32,}$/.test(machineId))
37857
38010
  throw new Error("invalid persisted machine id");
37858
38011
  } catch {
37859
- machineId = randomUUID7();
38012
+ machineId = randomUUID8();
37860
38013
  try {
37861
38014
  await mkdir16(configDir, { recursive: true, mode: 448 });
37862
38015
  await writeFile13(machineIdPath, `${machineId}
@@ -38186,7 +38339,7 @@ async function probeReleaseInSubprocess(input) {
38186
38339
  return { kind: "unavailable", reason: `release ${input.releaseId} has no runnable CLI entrypoint` };
38187
38340
  }
38188
38341
  const timeoutMs = input.timeoutMs ?? CURRENT_RELEASE_PROBE_TIMEOUT_MS;
38189
- return new Promise((resolve45) => {
38342
+ return new Promise((resolve49) => {
38190
38343
  const child = spawn14(input.execPath ?? process.execPath, [entrypoint, UPDATE_PROBE_COMMAND, "--config", input.runtimeConfigPath], { env: input.env ?? process.env, stdio: ["ignore", "pipe", "pipe"] });
38191
38344
  let stdout6 = "";
38192
38345
  let stderr = "";
@@ -38196,7 +38349,7 @@ async function probeReleaseInSubprocess(input) {
38196
38349
  return;
38197
38350
  settled = true;
38198
38351
  clearTimeout(timer);
38199
- resolve45(outcome);
38352
+ resolve49(outcome);
38200
38353
  };
38201
38354
  const timer = setTimeout(() => {
38202
38355
  child.kill("SIGKILL");
@@ -38276,12 +38429,12 @@ async function runUpdateProbeCommand(args, options = {}) {
38276
38429
  }
38277
38430
 
38278
38431
  // apps/body/dist/machine-helper.js
38279
- import { mkdir as mkdir29, rename as rename13, stat as stat9, writeFile as writeFile22 } from "node:fs/promises";
38280
- import { dirname as dirname30 } from "node:path";
38432
+ import { mkdir as mkdir29, rename as rename13, stat as stat10, writeFile as writeFile22 } from "node:fs/promises";
38433
+ import { dirname as dirname31, resolve as resolve47 } from "node:path";
38281
38434
 
38282
38435
  // apps/body/dist/agent-runtime.js
38283
38436
  import { homedir as homedir19 } from "node:os";
38284
- import { dirname as dirname29, join as join21, resolve as resolve43 } from "node:path";
38437
+ import { dirname as dirname30, join as join23, resolve as resolve45 } from "node:path";
38285
38438
 
38286
38439
  // apps/body/dist/model-availability.js
38287
38440
  var SECRET_VALUE = /(?:token|key|secret|password)=?[^\s,;]*/gi;
@@ -38404,8 +38557,8 @@ async function syncAgentModelCatalog(input) {
38404
38557
  }
38405
38558
 
38406
38559
  // apps/body/dist/connector-tailscale.js
38407
- import { execFile as execFile7 } from "node:child_process";
38408
- import { randomUUID as randomUUID8 } from "node:crypto";
38560
+ import { execFile as execFile8 } from "node:child_process";
38561
+ import { randomUUID as randomUUID9 } from "node:crypto";
38409
38562
  import { rm as rm10 } from "node:fs/promises";
38410
38563
  import { tmpdir as tmpdir3, userInfo } from "node:os";
38411
38564
  import { join as join14 } from "node:path";
@@ -38415,10 +38568,10 @@ var LOGIN_URL = /https:\/\/login\.tailscale\.com\/[A-Za-z0-9_/-]+/u;
38415
38568
  function clipped(value) {
38416
38569
  return value.length <= OUTPUT_LIMIT ? value : value.slice(value.length - OUTPUT_LIMIT);
38417
38570
  }
38418
- var runTailscaleCommand = (command, args) => new Promise((resolve45) => {
38419
- execFile7(command, [...args], { timeout: COMMAND_TIMEOUT_MS, maxBuffer: OUTPUT_LIMIT * 2 }, (error, stdout6, stderr) => {
38571
+ var runTailscaleCommand = (command, args) => new Promise((resolve49) => {
38572
+ execFile8(command, [...args], { timeout: COMMAND_TIMEOUT_MS, maxBuffer: OUTPUT_LIMIT * 2 }, (error, stdout6, stderr) => {
38420
38573
  const code = error && "code" in error && typeof error.code === "number" ? error.code : error ? null : 0;
38421
- resolve45({ code, stdout: clipped(stdout6), stderr: clipped(stderr) });
38574
+ resolve49({ code, stdout: clipped(stdout6), stderr: clipped(stderr) });
38422
38575
  });
38423
38576
  });
38424
38577
  function loginUrlFrom(status, output) {
@@ -38495,7 +38648,7 @@ async function ensureInstalled(run2, onProgress, platform) {
38495
38648
  }
38496
38649
  };
38497
38650
  }
38498
- const script = join14(tmpdir3(), `beeline-tailscale-install-${process.pid}-${randomUUID8()}.sh`);
38651
+ const script = join14(tmpdir3(), `beeline-tailscale-install-${process.pid}-${randomUUID9()}.sh`);
38499
38652
  const steps2 = [
38500
38653
  step2("Tailscale installed", "running", {
38501
38654
  command: "curl -fsSL https://tailscale.com/install.sh"
@@ -38978,16 +39131,16 @@ function describe2(error) {
38978
39131
  }
38979
39132
 
38980
39133
  // apps/body/dist/room-runtime.js
38981
- import { execFile as execFile13 } from "node:child_process";
39134
+ import { execFile as execFile16 } from "node:child_process";
38982
39135
  import { createHash as createHash14 } from "node:crypto";
38983
39136
  import { existsSync as existsSync10, mkdirSync as mkdirSync3 } from "node:fs";
38984
- import { mkdir as mkdir27, readdir as readdir9, realpath as realpath2, rm as rm15 } from "node:fs/promises";
38985
- import { dirname as dirname27, relative as relative3, resolve as resolve38, sep as sep2 } from "node:path";
38986
- import { promisify as promisify8 } from "node:util";
39137
+ import { lstat as lstat7, mkdir as mkdir27, readdir as readdir11, realpath as realpath3, rm as rm17 } from "node:fs/promises";
39138
+ import { dirname as dirname28, relative as relative4, resolve as resolve40, sep as sep3 } from "node:path";
39139
+ import { promisify as promisify11 } from "node:util";
38987
39140
 
38988
39141
  // apps/body/dist/grant-runner.js
38989
- import { execFile as execFile8 } from "node:child_process";
38990
- import { createHash as createHash11, randomBytes as randomBytes9, randomUUID as randomUUID9 } from "node:crypto";
39142
+ import { execFile as execFile9 } from "node:child_process";
39143
+ import { createHash as createHash11, randomBytes as randomBytes9, randomUUID as randomUUID10 } from "node:crypto";
38991
39144
  import { chmod as chmod8, mkdir as mkdir17, readFile as readFile22, readdir as readdir6, rename as rename9, rm as rm11, rmdir, stat as stat7, writeFile as writeFile15 } from "node:fs/promises";
38992
39145
  import { createServer as createServer3 } from "node:http";
38993
39146
  import { dirname as dirname21, resolve as resolve28 } from "node:path";
@@ -39168,7 +39321,7 @@ var GrantCommandRunner = class {
39168
39321
  const sandboxMarker = runsOnHost ? void 0 : `[beeline-sandbox-started:${randomBytes9(16).toString("hex")}]`;
39169
39322
  const spawn15 = runsOnHost ? { command: argv[0], args: argv.slice(1) } : roomSandboxCommand(policy, room.cwd, argv, sandboxMarker);
39170
39323
  const outcome = await new Promise((resolveRun) => {
39171
- const child = execFile8(spawn15.command, spawn15.args, {
39324
+ const child = execFile9(spawn15.command, spawn15.args, {
39172
39325
  cwd: room.cwd,
39173
39326
  env,
39174
39327
  timeout: this.options.timeoutMs ?? GRANT_COMMAND_TIMEOUT_MS,
@@ -39538,13 +39691,13 @@ var TurnUsageAccumulator = class {
39538
39691
  };
39539
39692
 
39540
39693
  // apps/body/dist/server-command-intake.js
39541
- import { randomUUID as randomUUID10 } from "node:crypto";
39694
+ import { randomUUID as randomUUID11 } from "node:crypto";
39542
39695
  import { mkdir as mkdir18, writeFile as writeFile16 } from "node:fs/promises";
39543
39696
  import { writeFileSync as writeFileSync4 } from "node:fs";
39544
39697
  import { tmpdir as tmpdir4 } from "node:os";
39545
39698
  import { dirname as dirname22, join as join16 } from "node:path";
39546
39699
  var CommandExecutionContext = class {
39547
- generationId = randomUUID10();
39700
+ generationId = randomUUID11();
39548
39701
  path;
39549
39702
  current;
39550
39703
  constructor(root) {
@@ -39702,11 +39855,11 @@ async function runServerCommandIntake(options) {
39702
39855
  if (attempt === 3)
39703
39856
  throw error;
39704
39857
  const waitMs = Math.max(250 * 2 ** attempt, error instanceof DaemonApiError ? error.retryAfterMs ?? 0 : 0);
39705
- await new Promise((resolve45) => {
39858
+ await new Promise((resolve49) => {
39706
39859
  const done = () => {
39707
39860
  clearTimeout(timer);
39708
39861
  signal?.removeEventListener("abort", done);
39709
- resolve45();
39862
+ resolve49();
39710
39863
  };
39711
39864
  const timer = setTimeout(done, waitMs);
39712
39865
  signal?.addEventListener("abort", done, { once: true });
@@ -39797,11 +39950,11 @@ async function runServerCommandIntake(options) {
39797
39950
  }
39798
39951
  }
39799
39952
  options.onPoll?.();
39800
- const reconcile = await new Promise((resolve45) => {
39953
+ const reconcile = await new Promise((resolve49) => {
39801
39954
  const done = (needed) => {
39802
39955
  signal?.removeEventListener("abort", aborted);
39803
39956
  wake = void 0;
39804
- resolve45(needed);
39957
+ resolve49(needed);
39805
39958
  };
39806
39959
  const aborted = () => done(false);
39807
39960
  wake = done;
@@ -39841,13 +39994,13 @@ async function runServerCommandIntake(options) {
39841
39994
  }
39842
39995
 
39843
39996
  // apps/body/dist/monolith-corner-turn.js
39844
- import { execFile as execFile12 } from "node:child_process";
39997
+ import { execFile as execFile14 } from "node:child_process";
39845
39998
  import { createHash as createHash13 } from "node:crypto";
39846
39999
  import { existsSync as existsSync9 } from "node:fs";
39847
40000
  import { mkdir as mkdir26, readFile as readFile30, writeFile as writeFile20 } from "node:fs/promises";
39848
40001
  import { homedir as homedir18, hostname as hostname3 } from "node:os";
39849
- import { dirname as dirname26, join as join20, resolve as resolve37 } from "node:path";
39850
- import { promisify as promisify7 } from "node:util";
40002
+ import { dirname as dirname26, join as join21, resolve as resolve38 } from "node:path";
40003
+ import { promisify as promisify9 } from "node:util";
39851
40004
 
39852
40005
  // apps/body/dist/agent-command-catalog.js
39853
40006
  function agentCommandCatalogPublisher(input) {
@@ -40497,13 +40650,13 @@ async function hasCornerPrepareScript(worktreePath) {
40497
40650
  }
40498
40651
 
40499
40652
  // apps/body/dist/pi-mcp-bridge.js
40500
- import { execFile as execFile9 } from "node:child_process";
40653
+ import { execFile as execFile10 } from "node:child_process";
40501
40654
  import { mkdtemp as mkdtemp2, mkdir as mkdir20, readFile as readFile26, rm as rm12, unlink as unlink8 } from "node:fs/promises";
40502
40655
  import { tmpdir as tmpdir5 } from "node:os";
40503
40656
  import { resolve as resolve30 } from "node:path";
40504
- import { promisify as promisify5 } from "node:util";
40657
+ import { promisify as promisify6 } from "node:util";
40505
40658
  var PI_MCP_BRIDGE_FILENAME = "beeline-mcp-bridge.js";
40506
- var execFileAsync5 = promisify5(execFile9);
40659
+ var execFileAsync6 = promisify6(execFile10);
40507
40660
  var nativeMcpProbes = /* @__PURE__ */ new Map();
40508
40661
  async function piHasNativeMcp(command, env) {
40509
40662
  const path = env?.PATH ?? process.env.PATH ?? "";
@@ -40513,7 +40666,7 @@ async function piHasNativeMcp(command, env) {
40513
40666
  probe = (async () => {
40514
40667
  const home = await mkdtemp2(resolve30(tmpdir5(), "beeline-pi-mcp-probe-"));
40515
40668
  try {
40516
- const { stdout: stdout6 } = await execFileAsync5(command, ["mcp", "list", "--json"], {
40669
+ const { stdout: stdout6 } = await execFileAsync6(command, ["mcp", "list", "--json"], {
40517
40670
  cwd: home,
40518
40671
  timeout: 1200,
40519
40672
  env: { PATH: path, HOME: home, PI_CODING_AGENT_DIR: home, PI_OFFLINE: "1" }
@@ -40810,7 +40963,7 @@ export default async function (pi) {
40810
40963
  `;
40811
40964
 
40812
40965
  // apps/body/dist/corner-branch-sync.js
40813
- import { execFile as execFile10 } from "node:child_process";
40966
+ import { execFile as execFile11 } from "node:child_process";
40814
40967
  import { access as access2, readFile as readFile27 } from "node:fs/promises";
40815
40968
  import { resolve as resolve31 } from "node:path";
40816
40969
  var CORNER_GIT_SYNC_TIMEOUT_MS = 12e4;
@@ -40818,7 +40971,7 @@ var CORNER_GIT_SYNC_KILL_GRACE_MS = 1e3;
40818
40971
  var CornerGitSyncInterruptedError = class extends Error {
40819
40972
  };
40820
40973
  async function syncCornerBranch(input) {
40821
- const git = async (args, cleanup = false) => {
40974
+ const git2 = async (args, cleanup = false) => {
40822
40975
  const controller = new AbortController();
40823
40976
  const signal = input.signal && !cleanup ? AbortSignal.any([input.signal, controller.signal]) : controller.signal;
40824
40977
  const timer = setTimeout(() => controller.abort(), CORNER_GIT_SYNC_TIMEOUT_MS);
@@ -40826,11 +40979,11 @@ async function syncCornerBranch(input) {
40826
40979
  try {
40827
40980
  if (signal.aborted)
40828
40981
  throw interrupted();
40829
- return await new Promise((resolve45, reject) => {
40982
+ return await new Promise((resolve49, reject) => {
40830
40983
  let killTimer;
40831
40984
  let stdout6 = "";
40832
40985
  let failure = null;
40833
- const child = input.git ? void 0 : execFile10("git", ["-C", input.worktreePath, ...args], {
40986
+ const child = input.git ? void 0 : execFile11("git", ["-C", input.worktreePath, ...args], {
40834
40987
  ...input.env ? { env: input.env } : {},
40835
40988
  signal,
40836
40989
  maxBuffer: 4 * 1024 * 1024
@@ -40860,10 +41013,10 @@ async function syncCornerBranch(input) {
40860
41013
  else if (failure)
40861
41014
  reject(failure);
40862
41015
  else
40863
- resolve45(stdout6);
41016
+ resolve49(stdout6);
40864
41017
  });
40865
41018
  else
40866
- input.git(args).then(resolve45, reject).finally(cleanup2);
41019
+ input.git(args).then(resolve49, reject).finally(cleanup2);
40867
41020
  });
40868
41021
  } finally {
40869
41022
  clearTimeout(timer);
@@ -40873,10 +41026,10 @@ async function syncCornerBranch(input) {
40873
41026
  const gitDir = resolve31(input.worktreePath, marker.startsWith("gitdir: ") ? marker.slice(8).trim() : ".git");
40874
41027
  for (const directory of ["rebase-merge", "rebase-apply"]) {
40875
41028
  if (await access2(resolve31(gitDir, directory)).then(() => true, () => false))
40876
- await git(["rebase", "--abort"], true);
41029
+ await git2(["rebase", "--abort"], true);
40877
41030
  }
40878
41031
  const remoteRef = `refs/remotes/origin/${input.featureBranch}`;
40879
- const fetched = await git([
41032
+ const fetched = await git2([
40880
41033
  "fetch",
40881
41034
  "origin",
40882
41035
  `+refs/heads/${input.featureBranch}:${remoteRef}`
@@ -40888,31 +41041,31 @@ async function syncCornerBranch(input) {
40888
41041
  });
40889
41042
  if (!fetched)
40890
41043
  return "unchanged";
40891
- const remote = (await git(["rev-parse", remoteRef])).trim();
41044
+ const remote = (await git2(["rev-parse", remoteRef])).trim();
40892
41045
  if (!remote)
40893
41046
  throw new Error(`fetched corner branch has no remote ref: ${remoteRef}`);
40894
- const local = (await git(["rev-parse", "HEAD"])).trim();
41047
+ const local = (await git2(["rev-parse", "HEAD"])).trim();
40895
41048
  if (local === remote)
40896
41049
  return "unchanged";
40897
- if (await contains(git, local, remote))
41050
+ if (await contains(git2, local, remote))
40898
41051
  return "unchanged";
40899
- const behind = await contains(git, remote, local);
41052
+ const behind = await contains(git2, remote, local);
40900
41053
  try {
40901
- await git(behind ? ["merge", "--ff-only", remote] : ["rebase", remote]);
41054
+ await git2(behind ? ["merge", "--ff-only", remote] : ["rebase", remote]);
40902
41055
  return behind ? "fast-forwarded" : "rebased";
40903
41056
  } catch (error) {
40904
- await git(["rebase", "--abort"], true).catch((error2) => {
41057
+ await git2(["rebase", "--abort"], true).catch((error2) => {
40905
41058
  if (error2 instanceof CornerGitSyncInterruptedError)
40906
41059
  throw error2;
40907
41060
  });
40908
41061
  if (error instanceof CornerGitSyncInterruptedError)
40909
41062
  throw error;
40910
- await git(["reset", "--hard", remote]);
41063
+ await git2(["reset", "--hard", remote]);
40911
41064
  return "realigned";
40912
41065
  }
40913
41066
  }
40914
- async function contains(git, head, ancestor) {
40915
- return git(["merge-base", "--is-ancestor", ancestor, head]).then(() => true, (error) => {
41067
+ async function contains(git2, head, ancestor) {
41068
+ return git2(["merge-base", "--is-ancestor", ancestor, head]).then(() => true, (error) => {
40916
41069
  if (error instanceof CornerGitSyncInterruptedError)
40917
41070
  throw error;
40918
41071
  return false;
@@ -41066,6 +41219,7 @@ var AGENT_SURFACE_TOOL_NAMES = [
41066
41219
  "pr_checks_status",
41067
41220
  "post_artifact",
41068
41221
  "write_scratch_file",
41222
+ "scratch_status",
41069
41223
  "fetch_image",
41070
41224
  "connect_app"
41071
41225
  ];
@@ -41138,11 +41292,11 @@ function beelineAgentMcpServer(config, api, context) {
41138
41292
  { name: "BEELINE_DAEMON_ROOM_ID", value: context.roomId },
41139
41293
  { name: "BEELINE_DAEMON_WORKSPACE_ID", value: context.workspaceId },
41140
41294
  ...context.cornerId ? [{ name: "BEELINE_DAEMON_CORNER_ID", value: context.cornerId }] : [],
41141
- ...context.agentMayCloseCorner ? [{ name: "BEELINE_CORNER_AGENT_CLOSE", value: "1" }] : [],
41142
41295
  ...context.reviewer ? [{ name: "BEELINE_CORNER_REVIEWER", value: "1" }] : [],
41143
41296
  ...context.cornerId && context.repositoryBacked ? [{ name: "BEELINE_CORNER_REPOSITORY", value: "1" }] : [],
41144
41297
  ...context.attachRoot ? [{ name: "BEELINE_ATTACH_ROOT", value: context.attachRoot }] : [],
41145
41298
  ...context.attachScratchRoot ? [{ name: "BEELINE_ATTACH_SCRATCH_ROOT", value: context.attachScratchRoot }] : [],
41299
+ ...context.cornerScratchRoot ? [{ name: "BEELINE_CORNER_SCRATCH_ROOT", value: context.cornerScratchRoot }] : [],
41146
41300
  ...context.grantRunner ? [
41147
41301
  { name: "BEELINE_GRANT_RUNNER_URL", value: context.grantRunner.url },
41148
41302
  { name: "BEELINE_GRANT_RUNNER_TOKEN", value: context.grantRunner.token }
@@ -41172,6 +41326,90 @@ function readOnlyMcpServer(config, cwd, agentMemoryDir) {
41172
41326
  };
41173
41327
  }
41174
41328
 
41329
+ // apps/body/dist/scratch-lifecycle.js
41330
+ import { execFile as execFile12 } from "node:child_process";
41331
+ import { lstat as lstat4, readdir as readdir7, rmdir as rmdir2, rm as rm13, stat as stat8, unlink as unlink9 } from "node:fs/promises";
41332
+ import { join as join18, resolve as resolve33 } from "node:path";
41333
+ import { promisify as promisify7 } from "node:util";
41334
+ var execFileAsync7 = promisify7(execFile12);
41335
+ var CORNER_SCRATCH_BUDGET_BYTES = 5 * 1024 ** 3;
41336
+ var CORNER_SCRATCH_TTL_MS = 14 * 24 * 60 * 6e4;
41337
+ var SHARED_MODEL_CACHE_BUDGET_BYTES = 32 * 1024 ** 3;
41338
+ var MODEL_CACHE_IDLE_MS = 24 * 60 * 6e4;
41339
+ async function allocatedDirectoryBytes(path) {
41340
+ if (!await lstat4(path).catch(() => void 0))
41341
+ return 0;
41342
+ const output = await execFileAsync7("du", ["-s", "-B1", "--", path], {
41343
+ maxBuffer: 1024 * 1024
41344
+ }).then((result) => result.stdout);
41345
+ const bytes = Number(output.split(/\s+/)[0]);
41346
+ if (!Number.isSafeInteger(bytes) || bytes < 0)
41347
+ throw new Error("scratch usage could not be measured");
41348
+ return bytes;
41349
+ }
41350
+ function scratchBudgetMessage(usage2, budget = CORNER_SCRATCH_BUDGET_BYTES) {
41351
+ const mib = (bytes) => Math.ceil(bytes / 1024 ** 2);
41352
+ return `Scratch ${mib(usage2)} / ${mib(budget)} MiB; files idle for 14 days expire. Use scratch_status and your shell to inspect, update or delete files. ${usage2 > budget ? "OVER BUDGET: remove files before writing more." : ""}`.trim();
41353
+ }
41354
+ function scratchGrowthExceedsBudget(usage2, atTurnStart, budget = CORNER_SCRATCH_BUDGET_BYTES) {
41355
+ return usage2 > budget && usage2 > atTurnStart;
41356
+ }
41357
+ async function sweepStaleCornerScratch(root, now2 = Date.now(), ttlMs = CORNER_SCRATCH_TTL_MS) {
41358
+ const cutoff = now2 - ttlMs;
41359
+ let files = 0;
41360
+ let bytes = 0;
41361
+ const visit = async (dir, top) => {
41362
+ for (const entry of await readdir7(dir, { withFileTypes: true }).catch(() => [])) {
41363
+ if (top && (entry.name === "agent-home" || entry.name === ".git"))
41364
+ continue;
41365
+ const path = join18(dir, entry.name);
41366
+ const info = await lstat4(path).catch(() => void 0);
41367
+ if (!info || info.isSymbolicLink())
41368
+ continue;
41369
+ if (info.isDirectory()) {
41370
+ await visit(path, false);
41371
+ if (!top)
41372
+ await rmdir2(path).catch(() => void 0);
41373
+ } else if (info.isFile() && info.mtimeMs < cutoff) {
41374
+ await unlink9(path);
41375
+ files++;
41376
+ bytes += info.size;
41377
+ }
41378
+ }
41379
+ };
41380
+ if ((await lstat4(root).catch(() => void 0))?.isDirectory())
41381
+ await visit(resolve33(root), true);
41382
+ return { files, bytes };
41383
+ }
41384
+ async function pruneSharedModelCache(root, now2 = Date.now(), budget = SHARED_MODEL_CACHE_BUDGET_BYTES) {
41385
+ let usage2 = await allocatedDirectoryBytes(root);
41386
+ if (usage2 <= budget)
41387
+ return [];
41388
+ const candidates = [];
41389
+ for (const parent of [join18(root, "hub"), root]) {
41390
+ for (const entry of await readdir7(parent, { withFileTypes: true }).catch(() => [])) {
41391
+ const eligible = parent === root ? entry.name === "xet" : /^(?:models|datasets|spaces)--/.test(entry.name);
41392
+ if (!eligible || !entry.isDirectory())
41393
+ continue;
41394
+ const path = join18(parent, entry.name);
41395
+ const info = await stat8(path);
41396
+ if (info.mtimeMs > now2 - MODEL_CACHE_IDLE_MS)
41397
+ continue;
41398
+ candidates.push({ path, usedAt: info.mtimeMs });
41399
+ }
41400
+ }
41401
+ candidates.sort((a2, b) => a2.usedAt - b.usedAt || a2.path.localeCompare(b.path));
41402
+ const removed = [];
41403
+ for (const item of candidates) {
41404
+ if (usage2 <= budget)
41405
+ break;
41406
+ await rm13(item.path, { recursive: true, force: true });
41407
+ usage2 = await allocatedDirectoryBytes(root);
41408
+ removed.push(item.path);
41409
+ }
41410
+ return removed;
41411
+ }
41412
+
41175
41413
  // apps/body/dist/institutional-context.js
41176
41414
  import { performance as performance2 } from "node:perf_hooks";
41177
41415
  var INSTITUTIONAL_CONTEXT_TIMEOUT_MS = 500;
@@ -41220,16 +41458,16 @@ async function awaitInstitutionalContext(fetch2, log2 = console.warn, budgetMs =
41220
41458
  }
41221
41459
 
41222
41460
  // apps/body/dist/codegraph.js
41223
- import { execFile as execFile11 } from "node:child_process";
41461
+ import { execFile as execFile13 } from "node:child_process";
41224
41462
  import { access as access3, appendFile, mkdir as mkdir21, readFile as readFile28 } from "node:fs/promises";
41225
- import { dirname as dirname23, isAbsolute as isAbsolute3, resolve as resolve33 } from "node:path";
41226
- import { promisify as promisify6 } from "node:util";
41227
- var execFileAsync6 = promisify6(execFile11);
41463
+ import { dirname as dirname23, isAbsolute as isAbsolute3, resolve as resolve34 } from "node:path";
41464
+ import { promisify as promisify8 } from "node:util";
41465
+ var execFileAsync8 = promisify8(execFile13);
41228
41466
  var CODEGRAPH_MCP_SERVER_NAME = "codegraph";
41229
41467
  var CODEGRAPH_INDEX_PATH = ".codegraph/codegraph.db";
41230
41468
  var CODEGRAPH_PREPARE_TIMEOUT_MS = 12e4;
41231
41469
  function codegraphIndexDirectory(cwd) {
41232
- return resolve33(cwd, dirname23(CODEGRAPH_INDEX_PATH));
41470
+ return resolve34(cwd, dirname23(CODEGRAPH_INDEX_PATH));
41233
41471
  }
41234
41472
  function codegraphMcpServer(config, cwd, options) {
41235
41473
  if (!config.codegraphCommand)
@@ -41237,7 +41475,7 @@ function codegraphMcpServer(config, cwd, options) {
41237
41475
  return {
41238
41476
  name: CODEGRAPH_MCP_SERVER_NAME,
41239
41477
  command: config.codegraphCommand,
41240
- args: ["serve", "--mcp", "--path", resolve33(cwd), ...options.readonly ? ["--no-watch"] : []],
41478
+ args: ["serve", "--mcp", "--path", resolve34(cwd), ...options.readonly ? ["--no-watch"] : []],
41241
41479
  env: [
41242
41480
  { name: "CODEGRAPH_TELEMETRY", value: "0" },
41243
41481
  // One MCP child per harness session is easier to contain than a daemon
@@ -41251,25 +41489,25 @@ function codegraphFingerprintServers(config, servers, mounted = Boolean(config.c
41251
41489
  }
41252
41490
  async function isGitWorktree(cwd) {
41253
41491
  try {
41254
- const { stdout: stdout6 } = await execFileAsync6("git", ["rev-parse", "--show-toplevel"], {
41492
+ const { stdout: stdout6 } = await execFileAsync8("git", ["rev-parse", "--show-toplevel"], {
41255
41493
  cwd,
41256
41494
  timeout: 1e4
41257
41495
  });
41258
- return resolve33(stdout6.trim()) === resolve33(cwd);
41496
+ return resolve34(stdout6.trim()) === resolve34(cwd);
41259
41497
  } catch {
41260
41498
  return false;
41261
41499
  }
41262
41500
  }
41263
41501
  async function excludeIndexFromGitStatus(cwd) {
41264
41502
  try {
41265
- const { stdout: stdout6 } = await execFileAsync6("git", ["rev-parse", "--git-path", "info/exclude"], {
41503
+ const { stdout: stdout6 } = await execFileAsync8("git", ["rev-parse", "--git-path", "info/exclude"], {
41266
41504
  cwd,
41267
41505
  timeout: 1e4
41268
41506
  });
41269
41507
  const gitPath = stdout6.trim();
41270
41508
  if (!gitPath)
41271
41509
  return;
41272
- const path = isAbsolute3(gitPath) ? gitPath : resolve33(cwd, gitPath);
41510
+ const path = isAbsolute3(gitPath) ? gitPath : resolve34(cwd, gitPath);
41273
41511
  await mkdir21(dirname23(path), { recursive: true });
41274
41512
  const existing = await readFile28(path, "utf8").catch(() => "");
41275
41513
  if (existing.split("\n").includes(".codegraph/"))
@@ -41284,11 +41522,11 @@ async function prepareCodegraphIndex(config, cwd) {
41284
41522
  if (!command || !await isGitWorktree(cwd))
41285
41523
  return false;
41286
41524
  await excludeIndexFromGitStatus(cwd);
41287
- const indexPath = resolve33(cwd, CODEGRAPH_INDEX_PATH);
41525
+ const indexPath = resolve34(cwd, CODEGRAPH_INDEX_PATH);
41288
41526
  const indexed = await access3(indexPath).then(() => true, () => false);
41289
41527
  const args = indexed ? ["sync", "--quiet", cwd] : ["init", "--yes", cwd];
41290
41528
  try {
41291
- await execFileAsync6(command, args, {
41529
+ await execFileAsync8(command, args, {
41292
41530
  cwd,
41293
41531
  env: { ...process.env, CODEGRAPH_TELEMETRY: "0", CODEGRAPH_NO_DAEMON: "1" },
41294
41532
  timeout: CODEGRAPH_PREPARE_TIMEOUT_MS,
@@ -41304,7 +41542,7 @@ async function prepareCodegraphIndex(config, cwd) {
41304
41542
  // apps/body/dist/monolith-room-turn.js
41305
41543
  import { mkdir as mkdir23, writeFile as writeFile18 } from "node:fs/promises";
41306
41544
  import { homedir as homedir17, hostname as hostname2 } from "node:os";
41307
- import { dirname as dirname24, join as join18 } from "node:path";
41545
+ import { dirname as dirname24, join as join19 } from "node:path";
41308
41546
 
41309
41547
  // packages/api-contract/dist/scheduled-prompts.js
41310
41548
  var SCHEDULE_SCHEDULER_NAME = "Beeline Scheduler";
@@ -41408,6 +41646,7 @@ function cornerHasRepositoryWork(brief) {
41408
41646
  var CORNER_RUNTIME_AUTHOR_CONTRACT = `The current brief's spec \u2014 stories, criteria, non-goals, risks \u2014 defines scope and done. The human approval quote wins any conflict. The short objective is navigation-only, never scope.
41409
41647
  Meet every story; respect every non-goal and risk.
41410
41648
  Before any code or build action, the brief must hold this ask's outline; opening and prompting inside it is not that outline. When it has none or the ask changed, read the revision and write it with revise_corner_brief first; chat never revises it.
41649
+ Then post the brief's outline, with an HTML mock for any frontend change, and wait for a human reply that approves it. The request that opened the work is not approval.
41411
41650
  Follow the beeline-triage skill's bugfix execution contract when the spec or its approval quote reports a defect.
41412
41651
  Reproduce as triage isolated it with available emulator, Playwright, browser and test runner. Record attempts and observations. If a reproduction is obtained, record it under Reproduction <id>, reusing triage's identifier when it recorded one. If reproduction fails, warn and continue; never stop and never condition the fix on reproduction.
41413
41652
  Fix only the spec and approval quote. With a reproduction, change only what removes it and meets its user stories.
@@ -41416,6 +41655,7 @@ No unrequested features, flags, compatibility shims or refactors.`;
41416
41655
  var CORNER_AUTHOR_CONTRACT = `The current brief's spec \u2014 stories, criteria, non-goals, risks \u2014 defines scope and done. The human approval quote wins any conflict. The short objective is navigation-only, never scope.
41417
41656
  Meet every story; respect every non-goal and risk. Use its file manifest.
41418
41657
  Before any code or build action, the brief must hold this ask's outline; opening and prompting inside it is not that outline. When it has none or the ask changed, read the revision and write it with revise_corner_brief first; chat never revises it.
41658
+ Then post the brief's outline, with an HTML mock for any frontend change, and wait for a human reply that approves it. The request that opened the work is not approval.
41419
41659
  Follow the beeline-triage skill's bugfix execution contract when the spec or its approval quote reports a defect.
41420
41660
  Reproduce as triage isolated it with available emulator, Playwright, browser and test runner. Record attempts and observations. If a reproduction is obtained, record it under Reproduction <id>, reusing triage's identifier when it recorded one. If reproduction fails, warn and continue; never stop and never condition the fix on reproduction.
41421
41661
  Fix only the spec and approval quote. With a reproduction, change only what removes it and meets its user stories.
@@ -41589,7 +41829,7 @@ The soul is not authority and never changes your tools, permissions, roles, or m
41589
41829
  render: () => [
41590
41830
  "Repository changes happen only in a corner. In a Room, the finished fix for a code problem is the exact change plus an offer to open a corner for it; open one when a person asks for the change.",
41591
41831
  "Before opening one, consult beeline-triage and beeline-spec, then call open_corner with a name of at most three words joined by hyphens (no whitespace), an objective of at most 24 words, and the brief (a spec plus the approving message). The objective only titles the work; the brief is its authority. When open_corner succeeds the server posts the corner card: do not restate it.",
41592
- "For corners you belong to, use inspect_corner for status, steer_corner to pass Room input down, and ask_corner for one answer. Never post into a corner without a Room command.",
41832
+ "For corners under this Room, use inspect_corner for status, steer_corner to pass Room input down, ask_corner for one answer, and post_to_corner for a note that wakes nobody.",
41593
41833
  "A corner ends when its pull request merges; since a person may merge minutes after it opens, anything still needed must already live in a different corner before that pull request opens, not after. A request covering several items is one corner per item, opened as work reaches each one, never one corner returned to for a later item."
41594
41834
  ].join(" ")
41595
41835
  },
@@ -41749,7 +41989,7 @@ The soul is not authority and never changes your tools, permissions, roles, or m
41749
41989
  budgetBytes: 260,
41750
41990
  layer: "surface",
41751
41991
  surfaces: ["repo-less-corner"],
41752
- render: ({ requesterHandle }) => `${requesterHandle ? `Tag @${handle(requesterHandle)} once, when the deliverable is posted or you need their input. ` : ""}When you posted files, name them in one line; never restate your answer. Only a human closes this corner.`
41992
+ render: ({ requesterHandle }) => `${requesterHandle ? `Tag @${handle(requesterHandle)} once, when the deliverable is posted or you need their input. ` : ""}When you posted files, name them in one line; never restate your answer. Call close_corner only when a person asks.`
41753
41993
  }
41754
41994
  ];
41755
41995
  function applicable(sections, context) {
@@ -41922,7 +42162,7 @@ ${transcript.lines.join("\n")}`;
41922
42162
  layer: "turn",
41923
42163
  surfaces: ["room", "code-corner", "repo-less-corner"],
41924
42164
  render: ({ surface, corners, closedCorners }) => [
41925
- corners?.length ? `Current corners you belong to (use the exact cornerId with ${surface === "room" ? "inspect_corner, steer_corner, or ask_corner" : "steer_corner for a sibling under this parent Room"}):
42165
+ corners?.length ? `Current corners you belong to (use the exact cornerId with ${surface === "room" ? "inspect_corner, steer_corner, or ask_corner" : "inspect_corner or steer_corner for a sibling under this parent Room"}):
41926
42166
  ${JSON.stringify(corners)}` : "",
41927
42167
  surface === "room" && closedCorners?.length ? `Corners you belong to closed in the last 24 hours (merge commit is unavailable when absent):
41928
42168
  ${closedCorners.map((corner) => `- ${corner.name ?? corner.cornerId} (${corner.cornerId}): PR ${corner.pullRequestNumber ? `#${corner.pullRequestNumber}` : "unavailable"}, merge commit ${corner.mergeCommitSha ?? "unavailable"}`).join("\n")}` : ""
@@ -41989,8 +42229,8 @@ function assembleTurnPrompt(context) {
41989
42229
  }
41990
42230
 
41991
42231
  // apps/body/dist/turn-trace.js
41992
- import { appendFile as appendFile2, mkdir as mkdir22, readdir as readdir7, rm as rm13 } from "node:fs/promises";
41993
- import { resolve as resolve34 } from "node:path";
42232
+ import { appendFile as appendFile2, mkdir as mkdir22, readdir as readdir8, rm as rm14 } from "node:fs/promises";
42233
+ import { resolve as resolve35 } from "node:path";
41994
42234
  import { performance as performance3 } from "node:perf_hooks";
41995
42235
  var TURN_PHASES = [
41996
42236
  /** Enqueued on `SessionScheduler` until this turn holds a slot. A capacity wait lives here. */
@@ -42276,7 +42516,7 @@ function formatTurnTraceLine(record5) {
42276
42516
  return [head, ...record5.attempts.map((attempt) => formatTurnAttempt(attempt))].join("\n ");
42277
42517
  }
42278
42518
  function turnTraceDirectory(runtimeDir) {
42279
- return resolve34(runtimeDir, "turn-traces");
42519
+ return resolve35(runtimeDir, "turn-traces");
42280
42520
  }
42281
42521
  var TURN_TRACE_RETENTION_DAYS = 7;
42282
42522
  function traceFileName(date) {
@@ -42293,7 +42533,7 @@ var TurnTraceFile = class {
42293
42533
  this.options = options;
42294
42534
  }
42295
42535
  path(now2 = (this.options.clock ?? (() => /* @__PURE__ */ new Date()))()) {
42296
- return resolve34(this.directory, traceFileName(now2));
42536
+ return resolve35(this.directory, traceFileName(now2));
42297
42537
  }
42298
42538
  write(record5) {
42299
42539
  this.tail = this.tail.catch(() => void 0).then(async () => {
@@ -42316,8 +42556,8 @@ var TurnTraceFile = class {
42316
42556
  return;
42317
42557
  this.prunedDay = day;
42318
42558
  const cutoff = traceFileName(new Date(now2.getTime() - TURN_TRACE_RETENTION_DAYS * 864e5));
42319
- const names = await readdir7(this.directory).catch(() => []);
42320
- await Promise.all(names.filter((name) => /^turns-\d{4}-\d{2}-\d{2}\.jsonl$/.test(name) && name < cutoff).map((name) => rm13(resolve34(this.directory, name), { force: true })));
42559
+ const names = await readdir8(this.directory).catch(() => []);
42560
+ await Promise.all(names.filter((name) => /^turns-\d{4}-\d{2}-\d{2}\.jsonl$/.test(name) && name < cutoff).map((name) => rm14(resolve35(this.directory, name), { force: true })));
42321
42561
  }
42322
42562
  };
42323
42563
 
@@ -42669,7 +42909,7 @@ var MonolithRoomTurnLoop = class {
42669
42909
  const cached = this.deliveredAttachments.get(item.id);
42670
42910
  if (cached?.length === item.attachments.length)
42671
42911
  return cached;
42672
- const delivered = await deliverAttachments(item.attachments, join18(this.attachmentDir, item.id.replace(/[^\w-]/g, "_")), this.options.fetchImpl, cached);
42912
+ const delivered = await deliverAttachments(item.attachments, join19(this.attachmentDir, item.id.replace(/[^\w-]/g, "_")), this.options.fetchImpl, cached);
42673
42913
  this.deliveredAttachments.set(item.id, withoutImageData(delivered.filter((entry) => entry.path)));
42674
42914
  return delivered;
42675
42915
  }
@@ -42739,7 +42979,7 @@ var MonolithRoomTurnLoop = class {
42739
42979
  this.sessionFingerprint = void 0;
42740
42980
  this.sessionCodegraphReady = false;
42741
42981
  this.pinnedProviderOverride = void 0;
42742
- if (client?.isAlive)
42982
+ if (client)
42743
42983
  await client.stop();
42744
42984
  }
42745
42985
  /**
@@ -42919,7 +43159,7 @@ var MonolithRoomTurnLoop = class {
42919
43159
  args: this.options.config.agentArgs ?? []
42920
43160
  }, selection);
42921
43161
  const { stateDirs, tmpDir } = harnessStateDirsFromEnv(agentEnv);
42922
- this.attachmentDir = tmpDir ? join18(tmpDir, "beeline-attachments") : void 0;
43162
+ this.attachmentDir = tmpDir ? join19(tmpDir, "beeline-attachments") : void 0;
42923
43163
  this.sessionScratchDir = tmpDir;
42924
43164
  this.sessionStateDirs = stateDirs;
42925
43165
  const homeStateDirs = harnessHomeStateDirs(harnessLabel, agentEnv.HOME ?? operatorHome);
@@ -43160,7 +43400,7 @@ var MonolithRoomTurnLoop = class {
43160
43400
  this.sessionId = void 0;
43161
43401
  this.sessionFingerprint = void 0;
43162
43402
  this.sessionCodegraphReady = false;
43163
- if (client?.isAlive)
43403
+ if (client)
43164
43404
  await client.stop();
43165
43405
  this.pinnedProviderOverride = next;
43166
43406
  await (trace ? trace.measure("activation", () => this.activate(trace)) : this.activate());
@@ -43239,8 +43479,8 @@ var MonolithRoomTurnLoop = class {
43239
43479
  let timer;
43240
43480
  const stats = statsPromise && remaining > 0 ? await Promise.race([
43241
43481
  statsPromise,
43242
- new Promise((resolve45) => {
43243
- timer = setTimeout(() => resolve45(void 0), remaining);
43482
+ new Promise((resolve49) => {
43483
+ timer = setTimeout(() => resolve49(void 0), remaining);
43244
43484
  })
43245
43485
  ]).finally(() => {
43246
43486
  if (timer)
@@ -43624,6 +43864,7 @@ var MonolithRoomTurnLoop = class {
43624
43864
  this.squireRelay.close();
43625
43865
  this.options.grantRunner?.unregister(roomId);
43626
43866
  await this.options.scheduler.suspend(roomId);
43867
+ this.options.scheduler.forget(roomId);
43627
43868
  }
43628
43869
  }
43629
43870
  };
@@ -43654,9 +43895,9 @@ function roomMessagePrompt(author, body, attachments, delivered, harnessAcceptsI
43654
43895
 
43655
43896
  // apps/body/dist/corner-github-auth.js
43656
43897
  import { chmod as chmod9, mkdir as mkdir24, writeFile as writeFile19 } from "node:fs/promises";
43657
- import { delimiter as delimiter3, resolve as resolve35 } from "node:path";
43898
+ import { delimiter as delimiter3, resolve as resolve36 } from "node:path";
43658
43899
  async function installCornerGitHubWrappers(input) {
43659
- const bin = resolve35(input.root, "beeline-github-bin");
43900
+ const bin = resolve36(input.root, "beeline-github-bin");
43660
43901
  await mkdir24(bin, { recursive: true, mode: 448 });
43661
43902
  const common = {
43662
43903
  node: process.execPath,
@@ -43668,13 +43909,13 @@ async function installCornerGitHubWrappers(input) {
43668
43909
  gitCommand: input.gitBinary,
43669
43910
  originUrl: input.originUrl ?? ""
43670
43911
  };
43671
- await writeLauncher(resolve35(bin, "git"), {
43912
+ await writeLauncher(resolve36(bin, "git"), {
43672
43913
  ...common,
43673
43914
  command: input.gitBinary,
43674
43915
  launcher: "git",
43675
43916
  restFallback: false
43676
43917
  });
43677
- await writeLauncher(resolve35(bin, "gh"), {
43918
+ await writeLauncher(resolve36(bin, "gh"), {
43678
43919
  ...common,
43679
43920
  command: input.ghBinary ?? "",
43680
43921
  launcher: "gh",
@@ -44109,37 +44350,37 @@ if (!refusal) {
44109
44350
  }
44110
44351
 
44111
44352
  // apps/body/dist/warm-node-modules.js
44112
- import { createHash as createHash12, randomUUID as randomUUID11 } from "node:crypto";
44353
+ import { createHash as createHash12, randomUUID as randomUUID12 } from "node:crypto";
44113
44354
  import { constants as fsConstants3 } from "node:fs";
44114
- import { chmod as chmod10, copyFile as copyFile2, link, lstat as lstat4, mkdir as mkdir25, readdir as readdir8, readFile as readFile29, readlink as readlink2, rename as rename10, rm as rm14, stat as stat8, symlink as symlink3, utimes } from "node:fs/promises";
44115
- import { dirname as dirname25, join as join19, resolve as resolve36 } from "node:path";
44355
+ import { chmod as chmod10, copyFile as copyFile2, link, lstat as lstat5, mkdir as mkdir25, readdir as readdir9, readFile as readFile29, readlink as readlink2, rename as rename10, rm as rm15, stat as stat9, symlink as symlink3, utimes } from "node:fs/promises";
44356
+ import { dirname as dirname25, join as join20, resolve as resolve37 } from "node:path";
44116
44357
  var STORE_FORMAT = "v1";
44117
44358
  var STAGING_PREFIX = ".beeline-warm-";
44118
44359
  var STAGING_SWEEP_MS = 24 * 60 * 60 * 1e3;
44119
44360
  var WARM_STORE_MAX_ENTRIES = 3;
44120
44361
  function sharedNpmCacheDir(supervisorRoot) {
44121
- return resolve36(supervisorRoot, "beeline", "npm-cache");
44362
+ return resolve37(supervisorRoot, "beeline", "npm-cache");
44122
44363
  }
44123
44364
  function sharedPnpmStoreDir(supervisorRoot) {
44124
- return resolve36(supervisorRoot, "beeline", "pnpm-store");
44365
+ return resolve37(supervisorRoot, "beeline", "pnpm-store");
44125
44366
  }
44126
44367
  function sharedCargoTargetDir(supervisorRoot) {
44127
- return resolve36(supervisorRoot, "beeline", "cargo-target");
44368
+ return resolve37(supervisorRoot, "beeline", "cargo-target");
44128
44369
  }
44129
44370
  function sharedTurboCacheDir(supervisorRoot) {
44130
- return resolve36(supervisorRoot, "beeline", "turbo-cache");
44371
+ return resolve37(supervisorRoot, "beeline", "turbo-cache");
44131
44372
  }
44132
44373
  function warmNodeModulesStoreDir(supervisorRoot) {
44133
- return resolve36(supervisorRoot, "beeline", "node-modules");
44374
+ return resolve37(supervisorRoot, "beeline", "node-modules");
44134
44375
  }
44135
44376
  function mobileNodeModulesStoreDir(supervisorRoot) {
44136
- return resolve36(supervisorRoot, "beeline", "node-modules-mobile");
44377
+ return resolve37(supervisorRoot, "beeline", "node-modules-mobile");
44137
44378
  }
44138
44379
  function isPlanRefusal(value) {
44139
44380
  return "failure" in value;
44140
44381
  }
44141
44382
  async function readWarmPlan(worktreePath) {
44142
- const lockfile = await readFile29(resolve36(worktreePath, "package-lock.json")).catch(() => void 0);
44383
+ const lockfile = await readFile29(resolve37(worktreePath, "package-lock.json")).catch(() => void 0);
44143
44384
  if (!lockfile)
44144
44385
  return { failure: "no-lockfile" };
44145
44386
  const packages = parseLockfilePackages(lockfile);
@@ -44178,11 +44419,11 @@ async function seedWarmNodeModules(input) {
44178
44419
  return { reason: plan.failure, ...plan.detail ? { detail: plan.detail } : {} };
44179
44420
  }
44180
44421
  for (const tree of plan.trees) {
44181
- if (await pathExists(resolve36(input.worktreePath, tree))) {
44422
+ if (await pathExists(resolve37(input.worktreePath, tree))) {
44182
44423
  return { reason: "present", key: plan.key };
44183
44424
  }
44184
44425
  }
44185
- const entry = resolve36(input.storeRoot, plan.key);
44426
+ const entry = resolve37(input.storeRoot, plan.key);
44186
44427
  if (!await isDirectory(entry))
44187
44428
  return { reason: "cold", key: plan.key };
44188
44429
  const [storeDevice, checkoutDevice] = await Promise.all([
@@ -44192,29 +44433,29 @@ async function seedWarmNodeModules(input) {
44192
44433
  if (storeDevice === void 0 || storeDevice !== checkoutDevice) {
44193
44434
  return { reason: "cross-device", key: plan.key };
44194
44435
  }
44195
- const staging = resolve36(input.storeRoot, `${STAGING_PREFIX}${process.pid}.${randomUUID11()}`);
44436
+ const staging = resolve37(input.storeRoot, `${STAGING_PREFIX}${process.pid}.${randomUUID12()}`);
44196
44437
  const placed = [];
44197
44438
  const now2 = (input.now ?? Date.now)();
44198
44439
  try {
44199
44440
  await sweepStaleStaging(input.storeRoot, now2);
44200
44441
  await utimes(entry, now2 / 1e3, now2 / 1e3).catch(() => void 0);
44201
44442
  for (const tree of plan.trees) {
44202
- await cloneTree(resolve36(entry, tree), resolve36(staging, tree), seedFile);
44443
+ await cloneTree(resolve37(entry, tree), resolve37(staging, tree), seedFile);
44203
44444
  }
44204
44445
  for (const tree of plan.trees) {
44205
- const target = resolve36(input.worktreePath, tree);
44446
+ const target = resolve37(input.worktreePath, tree);
44206
44447
  await mkdir25(dirname25(target), { recursive: true });
44207
- await rename10(resolve36(staging, tree), target);
44448
+ await rename10(resolve37(staging, tree), target);
44208
44449
  placed.push(target);
44209
44450
  }
44210
44451
  return { reason: "seeded", key: plan.key };
44211
44452
  } catch (error) {
44212
44453
  for (const target of placed) {
44213
- await rm14(target, { recursive: true, force: true }).catch(() => void 0);
44454
+ await rm15(target, { recursive: true, force: true }).catch(() => void 0);
44214
44455
  }
44215
44456
  return { reason: "failed", key: plan.key, detail: describe3(error) };
44216
44457
  } finally {
44217
- await rm14(staging, { recursive: true, force: true }).catch(() => void 0);
44458
+ await rm15(staging, { recursive: true, force: true }).catch(() => void 0);
44218
44459
  }
44219
44460
  }
44220
44461
  async function harvestWarmNodeModules(input) {
@@ -44222,11 +44463,11 @@ async function harvestWarmNodeModules(input) {
44222
44463
  if (isPlanRefusal(plan)) {
44223
44464
  return { reason: plan.failure, ...plan.detail ? { detail: plan.detail } : {} };
44224
44465
  }
44225
- const entry = resolve36(input.storeRoot, plan.key);
44466
+ const entry = resolve37(input.storeRoot, plan.key);
44226
44467
  if (await pathExists(entry))
44227
44468
  return { reason: "already-warm", key: plan.key };
44228
44469
  for (const tree of plan.trees) {
44229
- if (!await isDirectory(resolve36(input.worktreePath, tree))) {
44470
+ if (!await isDirectory(resolve37(input.worktreePath, tree))) {
44230
44471
  return { reason: "no-node-modules", key: plan.key, detail: tree };
44231
44472
  }
44232
44473
  }
@@ -44238,12 +44479,12 @@ async function harvestWarmNodeModules(input) {
44238
44479
  detail: `${missing.length} absent, e.g. ${missing.slice(0, 3).join(", ")}`
44239
44480
  };
44240
44481
  }
44241
- const staging = resolve36(input.storeRoot, `${STAGING_PREFIX}${process.pid}.${randomUUID11()}`);
44482
+ const staging = resolve37(input.storeRoot, `${STAGING_PREFIX}${process.pid}.${randomUUID12()}`);
44242
44483
  try {
44243
44484
  await mkdir25(input.storeRoot, { recursive: true, mode: 493 });
44244
44485
  await sweepStaleStaging(input.storeRoot, (input.now ?? Date.now)());
44245
44486
  for (const tree of plan.trees) {
44246
- await cloneTree(resolve36(input.worktreePath, tree), resolve36(staging, tree), harvestFile);
44487
+ await cloneTree(resolve37(input.worktreePath, tree), resolve37(staging, tree), harvestFile);
44247
44488
  }
44248
44489
  await input.onCopied?.();
44249
44490
  if (!await stagedTreeIsPublishable(input.worktreePath, staging, plan.key)) {
@@ -44257,25 +44498,25 @@ async function harvestWarmNodeModules(input) {
44257
44498
  return { reason: "already-warm", key: plan.key };
44258
44499
  return { reason: "failed", key: plan.key, detail: describe3(error) };
44259
44500
  } finally {
44260
- await rm14(staging, { recursive: true, force: true }).catch(() => void 0);
44501
+ await rm15(staging, { recursive: true, force: true }).catch(() => void 0);
44261
44502
  }
44262
44503
  }
44263
44504
  async function stagedTreeIsPublishable(worktreePath, staging, key) {
44264
44505
  const settled = await readWarmPlan(worktreePath);
44265
44506
  if (isPlanRefusal(settled) || settled.key !== key)
44266
44507
  return false;
44267
- const hidden = join19("node_modules", ".package-lock.json");
44508
+ const hidden = join20("node_modules", ".package-lock.json");
44268
44509
  const [copied, current] = await Promise.all([
44269
- readFile29(resolve36(staging, hidden)).catch(() => void 0),
44270
- readFile29(resolve36(worktreePath, hidden)).catch(() => void 0)
44510
+ readFile29(resolve37(staging, hidden)).catch(() => void 0),
44511
+ readFile29(resolve37(worktreePath, hidden)).catch(() => void 0)
44271
44512
  ]);
44272
44513
  if (!copied || !current || !copied.equals(current))
44273
44514
  return false;
44274
44515
  return (await missingInstalledPackages(worktreePath, staging)).length === 0;
44275
44516
  }
44276
44517
  async function missingInstalledPackages(worktreePath, treeRoot = worktreePath) {
44277
- const wanted = parseLockfilePackages(await readFile29(resolve36(worktreePath, "package-lock.json")).catch(() => void 0));
44278
- const installed = parseLockfilePackages(await readFile29(resolve36(treeRoot, "node_modules", ".package-lock.json")).catch(() => void 0));
44518
+ const wanted = parseLockfilePackages(await readFile29(resolve37(worktreePath, "package-lock.json")).catch(() => void 0));
44519
+ const installed = parseLockfilePackages(await readFile29(resolve37(treeRoot, "node_modules", ".package-lock.json")).catch(() => void 0));
44279
44520
  if (!wanted)
44280
44521
  return ["package-lock.json is unreadable"];
44281
44522
  if (!installed)
@@ -44295,14 +44536,14 @@ async function missingInstalledPackages(worktreePath, treeRoot = worktreePath) {
44295
44536
  required.push(path);
44296
44537
  }
44297
44538
  await mapWithLimit(required, INTEGRITY_READ_CONCURRENCY, async (path) => {
44298
- if (!(path in installed) || !await isInstalledPackage(resolve36(treeRoot, path))) {
44539
+ if (!(path in installed) || !await isInstalledPackage(resolve37(treeRoot, path))) {
44299
44540
  missing.push(path);
44300
44541
  }
44301
44542
  });
44302
44543
  return missing.sort();
44303
44544
  }
44304
44545
  async function isInstalledPackage(path) {
44305
- return stat8(join19(path, "package.json")).then((info) => info.isFile(), () => false);
44546
+ return stat9(join20(path, "package.json")).then((info) => info.isFile(), () => false);
44306
44547
  }
44307
44548
  var INTEGRITY_READ_CONCURRENCY = 64;
44308
44549
  async function mapWithLimit(values, limit, visit) {
@@ -44335,9 +44576,9 @@ function isContainedTreePath(value) {
44335
44576
  }
44336
44577
  async function cloneTree(source, target, file, topLevel = true) {
44337
44578
  await mkdir25(target, { recursive: true, mode: 493 });
44338
- for (const entry of await readdir8(source, { withFileTypes: true })) {
44339
- const from = join19(source, entry.name);
44340
- const to = join19(target, entry.name);
44579
+ for (const entry of await readdir9(source, { withFileTypes: true })) {
44580
+ const from = join20(source, entry.name);
44581
+ const to = join20(target, entry.name);
44341
44582
  if (entry.isSymbolicLink()) {
44342
44583
  await symlink3(await readlink2(from), to);
44343
44584
  continue;
@@ -44352,7 +44593,7 @@ async function cloneTree(source, target, file, topLevel = true) {
44352
44593
  }
44353
44594
  var harvestFile = async (source, target) => {
44354
44595
  await copyFile2(source, target, fsConstants3.COPYFILE_FICLONE);
44355
- const info = await stat8(source);
44596
+ const info = await stat9(source);
44356
44597
  await chmod10(target, info.mode & 4095 & ~146);
44357
44598
  };
44358
44599
  var seedFile = async (source, target, topLevel) => {
@@ -44364,46 +44605,46 @@ var seedFile = async (source, target, topLevel) => {
44364
44605
  await chmod10(target, 420);
44365
44606
  };
44366
44607
  async function pruneWarmStore(storeRoot, keep) {
44367
- const names = (await readdir8(storeRoot).catch(() => [])).filter((name) => !name.startsWith(STAGING_PREFIX));
44608
+ const names = (await readdir9(storeRoot).catch(() => [])).filter((name) => !name.startsWith(STAGING_PREFIX));
44368
44609
  const entries = [];
44369
44610
  for (const name of names) {
44370
- const info = await lstat4(join19(storeRoot, name)).catch(() => void 0);
44611
+ const info = await lstat5(join20(storeRoot, name)).catch(() => void 0);
44371
44612
  if (info?.isDirectory())
44372
44613
  entries.push({ name, usedAt: info.mtimeMs });
44373
44614
  }
44374
44615
  const dropped = entries.sort((a2, b) => b.usedAt - a2.usedAt || a2.name.localeCompare(b.name)).slice(keep);
44375
44616
  for (const entry of dropped) {
44376
- await rm14(join19(storeRoot, entry.name), { recursive: true, force: true }).catch(() => void 0);
44617
+ await rm15(join20(storeRoot, entry.name), { recursive: true, force: true }).catch(() => void 0);
44377
44618
  }
44378
44619
  return dropped.map((entry) => entry.name);
44379
44620
  }
44380
44621
  async function sweepStaleStaging(storeRoot, now2) {
44381
- const entries = await readdir8(storeRoot).catch(() => []);
44622
+ const entries = await readdir9(storeRoot).catch(() => []);
44382
44623
  for (const name of entries) {
44383
44624
  if (!name.startsWith(STAGING_PREFIX))
44384
44625
  continue;
44385
- const path = join19(storeRoot, name);
44386
- const info = await lstat4(path).catch(() => void 0);
44626
+ const path = join20(storeRoot, name);
44627
+ const info = await lstat5(path).catch(() => void 0);
44387
44628
  if (!info || now2 - info.mtimeMs < STAGING_SWEEP_MS)
44388
44629
  continue;
44389
- await rm14(path, { recursive: true, force: true }).catch(() => void 0);
44630
+ await rm15(path, { recursive: true, force: true }).catch(() => void 0);
44390
44631
  }
44391
44632
  }
44392
44633
  async function pathExists(path) {
44393
- return lstat4(path).then(() => true, () => false);
44634
+ return lstat5(path).then(() => true, () => false);
44394
44635
  }
44395
44636
  async function deviceOf(path) {
44396
- return stat8(path).then((info) => info.dev, () => void 0);
44637
+ return stat9(path).then((info) => info.dev, () => void 0);
44397
44638
  }
44398
44639
  async function isDirectory(path) {
44399
- return stat8(path).then((info) => info.isDirectory(), () => false);
44640
+ return stat9(path).then((info) => info.isDirectory(), () => false);
44400
44641
  }
44401
44642
  function describe3(error) {
44402
44643
  return error instanceof Error ? error.message : String(error);
44403
44644
  }
44404
44645
 
44405
44646
  // apps/body/dist/monolith-corner-turn.js
44406
- var execFileAsync7 = promisify7(execFile12);
44647
+ var execFileAsync9 = promisify9(execFile14);
44407
44648
  var TOOL_ARGUMENT_MAX_BYTES = 1200;
44408
44649
  var TOOL_OUTPUT_MAX_BYTES = 3200;
44409
44650
  var TOOL_PATH_LIMIT = 12;
@@ -44417,8 +44658,8 @@ function isCornerReviewTurn(reviewer, trigger) {
44417
44658
  async function cornerUndeliveredRepositoryState(worktreePath, featureBranch, targetBranch) {
44418
44659
  try {
44419
44660
  const [{ stdout: status }, ahead] = await Promise.all([
44420
- execFileAsync7("git", ["-C", worktreePath, "status", "--porcelain=v1"]),
44421
- featureBranch ? firstResolvedRemoteRef(worktreePath, [featureBranch, targetBranch]).then((remoteRef) => remoteRef ? execFileAsync7("git", [
44661
+ execFileAsync9("git", ["-C", worktreePath, "status", "--porcelain=v1"]),
44662
+ featureBranch ? firstResolvedRemoteRef(worktreePath, [featureBranch, targetBranch]).then((remoteRef) => remoteRef ? execFileAsync9("git", [
44422
44663
  "-C",
44423
44664
  worktreePath,
44424
44665
  "rev-list",
@@ -44438,7 +44679,7 @@ async function firstResolvedRemoteRef(worktreePath, branches) {
44438
44679
  if (!branch)
44439
44680
  continue;
44440
44681
  const ref = `refs/remotes/origin/${branch}`;
44441
- const resolved = await execFileAsync7("git", ["-C", worktreePath, "rev-parse", "--verify", ref]).then(() => true).catch(() => false);
44682
+ const resolved = await execFileAsync9("git", ["-C", worktreePath, "rev-parse", "--verify", ref]).then(() => true).catch(() => false);
44442
44683
  if (resolved)
44443
44684
  return ref;
44444
44685
  }
@@ -44590,7 +44831,7 @@ async function cornerToolActivity(call, worktreePath, requestedBy) {
44590
44831
  let title = oneLine(redactToolDetail(call.title ?? "")) || `${operation} tool`;
44591
44832
  if (isSuccessfulCommit(call)) {
44592
44833
  try {
44593
- const shown = await execFileAsync7("git", ["-C", worktreePath, "show", "--format=%s", "--name-only", "--no-renames", "HEAD"], { maxBuffer: 1024 * 1024 });
44834
+ const shown = await execFileAsync9("git", ["-C", worktreePath, "show", "--format=%s", "--name-only", "--no-renames", "HEAD"], { maxBuffer: 1024 * 1024 });
44594
44835
  const lines = shown.stdout.split(/\r?\n/);
44595
44836
  const subject = oneLine(lines.shift() ?? "commit");
44596
44837
  const files = new Set(lines.map(oneLine).filter(Boolean));
@@ -44851,7 +45092,7 @@ var MonolithCornerTurnLoop = class {
44851
45092
  this.sessionCodegraphReady = false;
44852
45093
  this.pinnedProviderOverride = void 0;
44853
45094
  this.sessionModel = null;
44854
- if (client?.isAlive)
45095
+ if (client)
44855
45096
  await client.stop();
44856
45097
  }
44857
45098
  /** See `MonolithRoomTurnLoop.sessionIsCurrent`: retention never keeps a
@@ -45012,9 +45253,9 @@ var MonolithCornerTurnLoop = class {
45012
45253
  const repository = this.options.repository;
45013
45254
  let githubEnv = repository ? { GH_TOKEN: repository.githubToken, GITHUB_TOKEN: repository.githubToken } : {};
45014
45255
  if (repository && this.options.config.runtimeConfigPath && this.options.config.agentHomeRoot) {
45015
- const gitBinary = (await execFileAsync7("which", ["git"])).stdout.trim();
45016
- const ghBinary = await execFileAsync7("which", ["gh"]).then((result) => result.stdout.trim()).catch(() => void 0);
45017
- const originUrl = await execFileAsync7(gitBinary, [
45256
+ const gitBinary = (await execFileAsync9("which", ["git"])).stdout.trim();
45257
+ const ghBinary = await execFileAsync9("which", ["gh"]).then((result) => result.stdout.trim()).catch(() => void 0);
45258
+ const originUrl = await execFileAsync9(gitBinary, [
45018
45259
  "-C",
45019
45260
  this.options.worktreePath,
45020
45261
  "remote",
@@ -45040,7 +45281,8 @@ var MonolithCornerTurnLoop = class {
45040
45281
  const pnpmStoreDir = sharedPnpmStoreDir(this.options.runtime.supervisorRoot);
45041
45282
  const cargoTargetDir = sharedCargoTargetDir(this.options.runtime.supervisorRoot);
45042
45283
  const turboCacheDir = sharedTurboCacheDir(this.options.runtime.supervisorRoot);
45043
- await Promise.all([npmCacheDir, pnpmStoreDir, cargoTargetDir, turboCacheDir].map((path) => mkdir26(path, { recursive: true, mode: 448 })));
45284
+ const modelCacheDir = resolve38(this.options.runtime.supervisorRoot, "beeline", "model-cache");
45285
+ await Promise.all([npmCacheDir, pnpmStoreDir, cargoTargetDir, turboCacheDir, modelCacheDir].map((path) => mkdir26(path, { recursive: true, mode: 448 })));
45044
45286
  const agentEnv = {
45045
45287
  ...this.options.config.agentEnv,
45046
45288
  ...homeOverlay,
@@ -45050,7 +45292,9 @@ var MonolithCornerTurnLoop = class {
45050
45292
  // hardlinks packages out of this content-addressable store.
45051
45293
  PNPM_CONFIG_STORE_DIR: pnpmStoreDir,
45052
45294
  CARGO_TARGET_DIR: cargoTargetDir,
45053
- TURBO_CACHE_DIR: turboCacheDir
45295
+ TURBO_CACHE_DIR: turboCacheDir,
45296
+ HF_HOME: modelCacheDir,
45297
+ HUGGINGFACE_HUB_CACHE: join21(modelCacheDir, "hub")
45054
45298
  };
45055
45299
  this.agentEnv = agentEnv;
45056
45300
  this.modelContextTokens = await modelContextWindowTokens(selection.model, agentEnv.PI_CODING_AGENT_DIR);
@@ -45060,7 +45304,7 @@ var MonolithCornerTurnLoop = class {
45060
45304
  args: this.options.config.agentArgs ?? []
45061
45305
  }, selection);
45062
45306
  const { stateDirs, tmpDir } = harnessStateDirsFromEnv(agentEnv);
45063
- this.attachmentDir = tmpDir ? join20(tmpDir, "beeline-attachments") : void 0;
45307
+ this.attachmentDir = tmpDir ? join21(tmpDir, "beeline-attachments") : void 0;
45064
45308
  this.sessionScratchDir = tmpDir;
45065
45309
  const homeStateDirs = harnessHomeStateDirs(harnessLabel, agentEnv.HOME ?? operatorHome);
45066
45310
  await Promise.all(homeStateDirs.map((dir) => mkdir26(dir, { recursive: true })));
@@ -45087,6 +45331,7 @@ var MonolithCornerTurnLoop = class {
45087
45331
  pnpmStoreDir,
45088
45332
  cargoTargetDir,
45089
45333
  turboCacheDir,
45334
+ modelCacheDir,
45090
45335
  ...registryMcpHostBindPaths(configuration.registryMcpRoutes, this.options.config.registryMcpBrokerSocket),
45091
45336
  ...grantedSquireHostBindPaths({
45092
45337
  operatorHome,
@@ -45165,7 +45410,9 @@ var MonolithCornerTurnLoop = class {
45165
45410
  // per-corner cache.
45166
45411
  { name: "npm_config_cache", value: npmCacheDir },
45167
45412
  { name: "PNPM_CONFIG_STORE_DIR", value: pnpmStoreDir },
45168
- { name: "CARGO_TARGET_DIR", value: cargoTargetDir }
45413
+ { name: "CARGO_TARGET_DIR", value: cargoTargetDir },
45414
+ { name: "HF_HOME", value: modelCacheDir },
45415
+ { name: "HUGGINGFACE_HUB_CACHE", value: join21(modelCacheDir, "hub") }
45169
45416
  ]
45170
45417
  }
45171
45418
  ] : [],
@@ -45173,13 +45420,13 @@ var MonolithCornerTurnLoop = class {
45173
45420
  roomId: this.options.parentRoomId,
45174
45421
  workspaceId: this.options.workspaceId,
45175
45422
  cornerId: this.options.cornerId,
45176
- agentMayCloseCorner: Boolean(repository),
45177
45423
  reviewer,
45178
45424
  repositoryBacked: Boolean(repository),
45179
45425
  attachRoot: this.options.worktreePath,
45180
45426
  // The whole per-session overlay, not an enumerated subset: see
45181
45427
  // `monolith-room-turn.ts`'s matching comment.
45182
45428
  attachScratchRoot,
45429
+ ...!repository ? { cornerScratchRoot: this.options.worktreePath } : {},
45183
45430
  turnContextPath: this.commandContext.path,
45184
45431
  squireRelay: squireScope.relay,
45185
45432
  ...this.options.grantRunnerEndpoint ? { grantRunner: this.options.grantRunnerEndpoint } : {}
@@ -45273,7 +45520,7 @@ var MonolithCornerTurnLoop = class {
45273
45520
  this.options.api.execute("getCornerRestoreState", {
45274
45521
  cornerId: this.options.cornerId
45275
45522
  }),
45276
- execFileAsync7("git", ["-C", this.options.worktreePath, "rev-parse", "HEAD"]).then(({ stdout: stdout6 }) => stdout6.trim())
45523
+ execFileAsync9("git", ["-C", this.options.worktreePath, "rev-parse", "HEAD"]).then(({ stdout: stdout6 }) => stdout6.trim())
45277
45524
  ]);
45278
45525
  const pr = restore.lifecycle?.pr;
45279
45526
  if (restore.lifecycle?.checks !== "passing" || !pr?.number || !pr.headSha || pr.headSha !== localHead)
@@ -45287,7 +45534,7 @@ var MonolithCornerTurnLoop = class {
45287
45534
  briefRevision: restore.brief?.revision
45288
45535
  }),
45289
45536
  ...this.options.config.agentHomeRoot && this.options.config.agentKind && !AGENT_SKILL_DIRS.includes(this.options.config.agentKind) ? [
45290
- `This harness has no verified native skill discovery. Read the release-managed review procedure at ${resolve37(this.options.config.agentHomeRoot, "codex", "skills", "beeline-review", "SKILL.md")} before the verdict.`
45537
+ `This harness has no verified native skill discovery. Read the release-managed review procedure at ${resolve38(this.options.config.agentHomeRoot, "codex", "skills", "beeline-review", "SKILL.md")} before the verdict.`
45291
45538
  ] : []
45292
45539
  ].join("\n");
45293
45540
  } catch {
@@ -45353,7 +45600,7 @@ var MonolithCornerTurnLoop = class {
45353
45600
  this.sessionId = void 0;
45354
45601
  this.sessionFingerprint = void 0;
45355
45602
  this.sessionCodegraphReady = false;
45356
- if (client?.isAlive)
45603
+ if (client)
45357
45604
  await client.stop();
45358
45605
  this.pinnedProviderOverride = next;
45359
45606
  await (trace ? trace.measure("activation", () => this.activate(trace)) : this.activate());
@@ -45402,8 +45649,8 @@ var MonolithCornerTurnLoop = class {
45402
45649
  let timer;
45403
45650
  const stats = statsPromise && remaining > 0 ? await Promise.race([
45404
45651
  statsPromise,
45405
- new Promise((resolve45) => {
45406
- timer = setTimeout(() => resolve45(void 0), remaining);
45652
+ new Promise((resolve49) => {
45653
+ timer = setTimeout(() => resolve49(void 0), remaining);
45407
45654
  })
45408
45655
  ]).finally(() => {
45409
45656
  if (timer)
@@ -45454,7 +45701,7 @@ var MonolithCornerTurnLoop = class {
45454
45701
  let repositoryWork = cornerHasRepositoryWork(restored.brief);
45455
45702
  let repositoryHeld = restored.held === true;
45456
45703
  let assignedBrief = restored.brief;
45457
- const taskDelivered = this.attachmentDir && attachments.length ? await deliverAttachments(attachments, join20(this.attachmentDir, requestId.replace(/[^\w-]/g, "_")), this.options.fetchImpl) : [];
45704
+ const taskDelivered = this.attachmentDir && attachments.length ? await deliverAttachments(attachments, join21(this.attachmentDir, requestId.replace(/[^\w-]/g, "_")), this.options.fetchImpl) : [];
45458
45705
  let delivered = taskDelivered;
45459
45706
  let briefFileLines = [];
45460
45707
  let missingRequiredBriefFile = false;
@@ -45465,7 +45712,7 @@ var MonolithCornerTurnLoop = class {
45465
45712
  mimeType: file.mime,
45466
45713
  size: file.size
45467
45714
  }));
45468
- const briefDelivered = this.attachmentDir && briefAttachments.length ? await deliverAttachments(briefAttachments, join20(this.attachmentDir, requestId.replace(/[^\w-]/g, "_"), "brief", String(assignedBrief.revision)), this.options.fetchImpl) : [];
45715
+ const briefDelivered = this.attachmentDir && briefAttachments.length ? await deliverAttachments(briefAttachments, join21(this.attachmentDir, requestId.replace(/[^\w-]/g, "_"), "brief", String(assignedBrief.revision)), this.options.fetchImpl) : [];
45469
45716
  briefFileLines = await Promise.all((assignedBrief?.attachments ?? []).map(async (file, index) => {
45470
45717
  const entry = briefDelivered.find((item) => item.attachment === briefAttachments[index]);
45471
45718
  const verified = entry?.path && createHash13("sha256").update(await readFile30(entry.path)).digest("hex") === file.sha256;
@@ -45551,11 +45798,19 @@ var MonolithCornerTurnLoop = class {
45551
45798
  }
45552
45799
  });
45553
45800
  trace.notePromptSections(assembled.report);
45554
- trace.notePromptWindow(assembled.text, this.modelContextTokens);
45555
45801
  this.commandContext.notePromptSections([
45556
45802
  ...this.sessionPromptSectionIds,
45557
45803
  ...assembled.report.map((section) => section.id)
45558
45804
  ]);
45805
+ if (!repositoryWork) {
45806
+ const usage2 = await allocatedDirectoryBytes(this.options.worktreePath);
45807
+ const text2 = `${assembled.text}
45808
+
45809
+ ${scratchBudgetMessage(usage2)}`;
45810
+ trace.notePromptWindow(text2, this.modelContextTokens);
45811
+ return text2;
45812
+ }
45813
+ trace.notePromptWindow(assembled.text, this.modelContextTokens);
45559
45814
  return assembled.text;
45560
45815
  };
45561
45816
  const stream = new AgentTurnStream({
@@ -45664,24 +45919,34 @@ var MonolithCornerTurnLoop = class {
45664
45919
  narrationRunBoundary = 0;
45665
45920
  currentNarrationRun = "";
45666
45921
  trace.promptSent();
45667
- return this.turnUsage.measure({ agentEnv: this.agentEnv, sessionId: this.sessionId }, () => this.client.sessionPrompt(this.sessionId, promptWithImages(prompt, attachmentImageBlocks(delivered, this.acceptsImages())), ROOM_PROMPT_BACKSTOP_MS, (delta, full, currentRun, runs) => {
45668
- trace.firstModelOutput();
45669
- if (runs) {
45670
- completedNarrationRuns = runs.slice(narrationRunBoundary);
45671
- currentNarrationRun = "";
45672
- } else if (currentRun === void 0)
45673
- currentNarrationRun += delta;
45674
- else {
45675
- if (currentNarrationRun && currentNarrationRun !== currentRun && !currentRun.startsWith(currentNarrationRun))
45676
- completedNarrationRuns.push(currentNarrationRun);
45677
- currentNarrationRun = currentRun;
45922
+ const scratchRoot = this.repositoryWork ? void 0 : this.options.worktreePath;
45923
+ const scratchAtStart = scratchRoot ? await allocatedDirectoryBytes(scratchRoot) : 0;
45924
+ try {
45925
+ return await this.turnUsage.measure({ agentEnv: this.agentEnv, sessionId: this.sessionId }, () => this.client.sessionPrompt(this.sessionId, promptWithImages(prompt, attachmentImageBlocks(delivered, this.acceptsImages())), ROOM_PROMPT_BACKSTOP_MS, (delta, full, currentRun, runs) => {
45926
+ trace.firstModelOutput();
45927
+ if (runs) {
45928
+ completedNarrationRuns = runs.slice(narrationRunBoundary);
45929
+ currentNarrationRun = "";
45930
+ } else if (currentRun === void 0)
45931
+ currentNarrationRun += delta;
45932
+ else {
45933
+ if (currentNarrationRun && currentNarrationRun !== currentRun && !currentRun.startsWith(currentNarrationRun))
45934
+ completedNarrationRuns.push(currentNarrationRun);
45935
+ currentNarrationRun = currentRun;
45936
+ }
45937
+ stream.onChunk(delta, full, currentRun);
45938
+ }, void 0, (calls) => {
45939
+ trace.toolCalls(calls);
45940
+ publishToolCalls(calls, true);
45941
+ publishToolCalls(calls, false, lastNarratedToolCall);
45942
+ }));
45943
+ } finally {
45944
+ if (scratchRoot) {
45945
+ const usage2 = await allocatedDirectoryBytes(scratchRoot);
45946
+ if (scratchGrowthExceedsBudget(usage2, scratchAtStart))
45947
+ throw new Error(`Scratch budget exceeded. ${scratchBudgetMessage(usage2)}`);
45678
45948
  }
45679
- stream.onChunk(delta, full, currentRun);
45680
- }, void 0, (calls) => {
45681
- trace.toolCalls(calls);
45682
- publishToolCalls(calls, true);
45683
- publishToolCalls(calls, false, lastNarratedToolCall);
45684
- }));
45949
+ }
45685
45950
  };
45686
45951
  let loginRetryUsed = false;
45687
45952
  const runPrompt = async (prompt, continuation) => {
@@ -45886,13 +46151,13 @@ ${continuation}` : assembled;
45886
46151
  if (this.harvest || !this.options.repository)
45887
46152
  return;
45888
46153
  const { cornerId, worktreePath, runtime } = this.options;
45889
- const mobilePath = resolve37(worktreePath, "apps/mobile");
46154
+ const mobilePath = resolve38(worktreePath, "apps/mobile");
45890
46155
  const jobs = [
45891
46156
  harvestWarmNodeModules({
45892
46157
  worktreePath,
45893
46158
  storeRoot: warmNodeModulesStoreDir(runtime.supervisorRoot)
45894
46159
  }),
45895
- ...existsSync9(resolve37(mobilePath, "package-lock.json")) ? [
46160
+ ...existsSync9(resolve38(mobilePath, "package-lock.json")) ? [
45896
46161
  harvestWarmNodeModules({
45897
46162
  worktreePath: mobilePath,
45898
46163
  storeRoot: mobileNodeModulesStoreDir(runtime.supervisorRoot)
@@ -45940,7 +46205,7 @@ ${continuation}` : assembled;
45940
46205
  const delay = outage ? Math.min(2e3 * 2 ** attempt, 3e4) : 250 * (attempt + 1);
45941
46206
  if ((outage ? Date.now() + delay > outageDeadline : attempt === 2) || this.forcedStop || this.currentTurn && this.stoppedTurns.has(this.currentTurn.requestId))
45942
46207
  throw error;
45943
- await new Promise((resolve45) => setTimeout(resolve45, delay));
46208
+ await new Promise((resolve49) => setTimeout(resolve49, delay));
45944
46209
  }
45945
46210
  }
45946
46211
  if (!token)
@@ -46032,11 +46297,95 @@ ${continuation}` : assembled;
46032
46297
  this.squireRelay.close();
46033
46298
  this.options.grantRunner?.unregister(cornerId);
46034
46299
  await this.options.scheduler.suspend(cornerId);
46300
+ this.options.scheduler.forget(cornerId);
46035
46301
  await this.harvest;
46036
46302
  }
46037
46303
  }
46038
46304
  };
46039
46305
 
46306
+ // apps/body/dist/corner-disk-recovery.js
46307
+ import { execFile as execFile15 } from "node:child_process";
46308
+ import { lstat as lstat6, readdir as readdir10, realpath as realpath2, rm as rm16 } from "node:fs/promises";
46309
+ import { basename as basename9, dirname as dirname27, join as join22, relative as relative3, resolve as resolve39, sep as sep2 } from "node:path";
46310
+ import { promisify as promisify10 } from "node:util";
46311
+ var execFileAsync10 = promisify10(execFile15);
46312
+ var GENERATED_DIRS = /* @__PURE__ */ new Set([
46313
+ "node_modules",
46314
+ "target",
46315
+ "build",
46316
+ "dist",
46317
+ ".next",
46318
+ ".turbo",
46319
+ ".expo"
46320
+ ]);
46321
+ var MAX_DIRECTORY_DEPTH = 4;
46322
+ var MAX_VISITED_DIRECTORIES = 5e3;
46323
+ function cornerRecoveryPointerPath(worktree) {
46324
+ const checkout = resolve39(worktree.path);
46325
+ if (basename9(checkout) !== worktree.cornerId || basename9(dirname27(checkout)) !== "corners" || basename9(dirname27(dirname27(checkout))) !== "beeline" || !/^[a-zA-Z0-9-]{1,80}$/.test(worktree.cornerId)) {
46326
+ throw new Error("refusing recovery pointer outside a Beeline corner checkout");
46327
+ }
46328
+ return resolve39(dirname27(dirname27(checkout)), "recovery", "corners", `${worktree.cornerId}.json`);
46329
+ }
46330
+ async function git(checkout, args) {
46331
+ const result = await execFileAsync10("git", ["-C", checkout, ...args], {
46332
+ maxBuffer: 4 * 1024 * 1024
46333
+ });
46334
+ return result.stdout;
46335
+ }
46336
+ async function ignoredAndUntracked(checkout, path) {
46337
+ const rel = relative3(checkout, path);
46338
+ if (!rel || rel === ".." || rel.startsWith(`..${sep2}`))
46339
+ return false;
46340
+ const ignored = await git(checkout, ["check-ignore", "-q", "--", `${rel}/`]).then(() => true, () => false);
46341
+ if (!ignored)
46342
+ return false;
46343
+ return !(await git(checkout, ["ls-files", "--", rel])).trim();
46344
+ }
46345
+ async function preserveUnpublishedCornerWorktree(worktree, reason) {
46346
+ const checkout = resolve39(worktree.path);
46347
+ const pointer = cornerRecoveryPointerPath(worktree);
46348
+ const info = await lstat6(checkout);
46349
+ if (!info.isDirectory() || await realpath2(checkout) !== checkout) {
46350
+ throw new Error("refusing to prune a non-canonical corner checkout");
46351
+ }
46352
+ const head = (await git(checkout, ["rev-parse", "--verify", "HEAD"])).trim();
46353
+ const record5 = {
46354
+ cornerId: worktree.cornerId,
46355
+ checkout,
46356
+ branch: worktree.branch,
46357
+ head,
46358
+ reason,
46359
+ recordedAt: (/* @__PURE__ */ new Date()).toISOString()
46360
+ };
46361
+ await writePrivateFileAtomically(pointer, `${JSON.stringify(record5, null, 2)}
46362
+ `);
46363
+ const pruned = [];
46364
+ const pending = [{ path: checkout, depth: 0 }];
46365
+ let visited = 0;
46366
+ while (pending.length) {
46367
+ const current = pending.shift();
46368
+ if (++visited > MAX_VISITED_DIRECTORIES)
46369
+ break;
46370
+ if (current.depth >= MAX_DIRECTORY_DEPTH)
46371
+ continue;
46372
+ for (const entry of await readdir10(current.path, { withFileTypes: true })) {
46373
+ if (!entry.isDirectory() || entry.name === ".git")
46374
+ continue;
46375
+ const path = join22(current.path, entry.name);
46376
+ if (GENERATED_DIRS.has(entry.name)) {
46377
+ if (await ignoredAndUntracked(checkout, path)) {
46378
+ await rm16(path, { recursive: true, force: true });
46379
+ pruned.push(relative3(checkout, path));
46380
+ }
46381
+ continue;
46382
+ }
46383
+ pending.push({ path, depth: current.depth + 1 });
46384
+ }
46385
+ }
46386
+ return { pointer, pruned };
46387
+ }
46388
+
46040
46389
  // apps/body/dist/surface-health.js
46041
46390
  var SurfaceHealth = class {
46042
46391
  surfaces = /* @__PURE__ */ new Map();
@@ -46125,7 +46474,7 @@ function resolveSessionIdleMs(env = process.env) {
46125
46474
  return Number.isSafeInteger(value) && value > 0 ? value : DEFAULT_SESSION_IDLE_MS;
46126
46475
  }
46127
46476
  var DEFAULT_WORKSPACE_LIVE_SESSIONS_FLOOR = 4;
46128
- var SessionScheduler = class {
46477
+ var SessionScheduler = class _SessionScheduler {
46129
46478
  /** Fixed ceiling when explicitly configured; undefined selects the dynamic one. */
46130
46479
  fixedMaxLiveSessions;
46131
46480
  perRoomLiveSessions;
@@ -46140,6 +46489,7 @@ var SessionScheduler = class {
46140
46489
  queues = /* @__PURE__ */ new Map();
46141
46490
  drainingKeys = /* @__PURE__ */ new Set();
46142
46491
  physicalHistory = /* @__PURE__ */ new Map();
46492
+ static MAX_GENERATIONS_PER_KEY = 4;
46143
46493
  /**
46144
46494
  * Sessions already removed from `live` whose process is still being torn
46145
46495
  * down. They keep occupying capacity until `suspend()` resolves, so an
@@ -46263,6 +46613,10 @@ var SessionScheduler = class {
46263
46613
  generations(key) {
46264
46614
  return this.physicalHistory.get(key) ?? [];
46265
46615
  }
46616
+ /** A Room/corner loop ended; its diagnostic IDs no longer have a reader. */
46617
+ forget(key) {
46618
+ this.physicalHistory.delete(key);
46619
+ }
46266
46620
  /**
46267
46621
  * Read-only capacity diagnostic, exported beside the turn trace
46268
46622
  * (`turn-trace.ts`) so a stalled turn can be attributed to a capacity wait
@@ -46336,6 +46690,7 @@ var SessionScheduler = class {
46336
46690
  this.sweepTimer = void 0;
46337
46691
  const sessions = [...this.live.values()];
46338
46692
  this.live.clear();
46693
+ this.physicalHistory.clear();
46339
46694
  await Promise.all(sessions.map((session) => this.retire(session)));
46340
46695
  this.wakeCapacityWaiters();
46341
46696
  }
@@ -46449,6 +46804,8 @@ var SessionScheduler = class {
46449
46804
  await this.notifyState(lifecycle, "live");
46450
46805
  const generations = this.physicalHistory.get(key) ?? [];
46451
46806
  generations.push(physicalSessionId);
46807
+ if (generations.length > _SessionScheduler.MAX_GENERATIONS_PER_KEY)
46808
+ generations.shift();
46452
46809
  this.physicalHistory.set(key, generations);
46453
46810
  return true;
46454
46811
  } catch (error) {
@@ -46548,7 +46905,7 @@ function cornerStartConfigKey(repository, objective) {
46548
46905
  function cornerRepositoryCacheDir(supervisorRoot, remote) {
46549
46906
  const normalizedRemote = roomCheckoutRemote(remote);
46550
46907
  const repositoryHash = createHash14("sha256").update(normalizedRemote).digest("hex").slice(0, 24);
46551
- return resolve38(supervisorRoot, "beeline", "repositories", `${repositoryHash}.git`);
46908
+ return resolve40(supervisorRoot, "beeline", "repositories", `${repositoryHash}.git`);
46552
46909
  }
46553
46910
  function isStandingCornerStartFault(error) {
46554
46911
  const text2 = error instanceof Error ? error.message : String(error);
@@ -46557,24 +46914,24 @@ function isStandingCornerStartFault(error) {
46557
46914
  async function materializeCornerWorktree(input) {
46558
46915
  const remote = roomCheckoutRemote(input.remote);
46559
46916
  const gitCommonDir = cornerRepositoryCacheDir(input.supervisorRoot, remote);
46560
- const path = resolve38(input.supervisorRoot, "beeline", "corners", input.cornerId);
46561
- await mkdir27(dirname27(gitCommonDir), { recursive: true, mode: 448 });
46562
- await mkdir27(dirname27(path), { recursive: true, mode: 448 });
46917
+ const path = resolve40(input.supervisorRoot, "beeline", "corners", input.cornerId);
46918
+ await mkdir27(dirname28(gitCommonDir), { recursive: true, mode: 448 });
46919
+ await mkdir27(dirname28(path), { recursive: true, mode: 448 });
46563
46920
  const authEnv = githubGitEnv(input.token);
46564
- if (!existsSync10(resolve38(gitCommonDir, "HEAD"))) {
46565
- await execFileAsync8("git", ["clone", "--bare", remote, gitCommonDir], {
46921
+ if (!existsSync10(resolve40(gitCommonDir, "HEAD"))) {
46922
+ await execFileAsync11("git", ["clone", "--bare", remote, gitCommonDir], {
46566
46923
  env: authEnv,
46567
46924
  maxBuffer: 4 * 1024 * 1024
46568
46925
  });
46569
46926
  }
46570
- await execFileAsync8("git", [
46927
+ await execFileAsync11("git", [
46571
46928
  `--git-dir=${gitCommonDir}`,
46572
46929
  "fetch",
46573
46930
  "--prune",
46574
46931
  "origin",
46575
46932
  `+refs/heads/${input.targetBranch}:refs/remotes/origin/${input.targetBranch}`
46576
46933
  ], { env: authEnv, maxBuffer: 4 * 1024 * 1024 });
46577
- const restored = await execFileAsync8("git", [
46934
+ const restored = await execFileAsync11("git", [
46578
46935
  `--git-dir=${gitCommonDir}`,
46579
46936
  "fetch",
46580
46937
  "origin",
@@ -46584,9 +46941,9 @@ async function materializeCornerWorktree(input) {
46584
46941
  return false;
46585
46942
  throw error;
46586
46943
  });
46587
- if (!existsSync10(resolve38(path, ".git"))) {
46588
- await rm15(path, { recursive: true, force: true });
46589
- await execFileAsync8("git", [
46944
+ if (!existsSync10(resolve40(path, ".git"))) {
46945
+ await rm17(path, { recursive: true, force: true });
46946
+ await execFileAsync11("git", [
46590
46947
  `--git-dir=${gitCommonDir}`,
46591
46948
  "worktree",
46592
46949
  "add",
@@ -46602,8 +46959,8 @@ async function materializeCornerWorktree(input) {
46602
46959
  if (seed.reason !== "no-lockfile") {
46603
46960
  console.log(`[thin-core] corner ${input.cornerId} warm node_modules: ${seed.reason}${seed.detail ? ` (${seed.detail})` : ""}`);
46604
46961
  }
46605
- const mobilePath = resolve38(path, "apps/mobile");
46606
- if (existsSync10(resolve38(mobilePath, "package-lock.json"))) {
46962
+ const mobilePath = resolve40(path, "apps/mobile");
46963
+ if (existsSync10(resolve40(mobilePath, "package-lock.json"))) {
46607
46964
  const mobileSeed = await seedWarmNodeModules({
46608
46965
  worktreePath: mobilePath,
46609
46966
  storeRoot: mobileNodeModulesStoreDir(input.supervisorRoot)
@@ -46613,14 +46970,14 @@ async function materializeCornerWorktree(input) {
46613
46970
  }
46614
46971
  }
46615
46972
  }
46616
- await execFileAsync8("git", [
46973
+ await execFileAsync11("git", [
46617
46974
  `--git-dir=${gitCommonDir}`,
46618
46975
  "config",
46619
46976
  "extensions.worktreeConfig",
46620
46977
  "true"
46621
46978
  ]);
46622
- await execFileAsync8("git", ["-C", path, "config", "--worktree", "core.bare", "false"]);
46623
- await execFileAsync8("git", [
46979
+ await execFileAsync11("git", ["-C", path, "config", "--worktree", "core.bare", "false"]);
46980
+ await execFileAsync11("git", [
46624
46981
  "-C",
46625
46982
  path,
46626
46983
  "config",
@@ -46628,7 +46985,7 @@ async function materializeCornerWorktree(input) {
46628
46985
  "credential.https://github.com.helper",
46629
46986
  "!f() { echo username=x-access-token; echo password=$GH_TOKEN; }; f"
46630
46987
  ]);
46631
- await execFileAsync8("git", [
46988
+ await execFileAsync11("git", [
46632
46989
  "-C",
46633
46990
  path,
46634
46991
  "config",
@@ -46636,7 +46993,7 @@ async function materializeCornerWorktree(input) {
46636
46993
  "user.name",
46637
46994
  input.committer.name
46638
46995
  ]);
46639
- await execFileAsync8("git", [
46996
+ await execFileAsync11("git", [
46640
46997
  "-C",
46641
46998
  path,
46642
46999
  "config",
@@ -46644,8 +47001,8 @@ async function materializeCornerWorktree(input) {
46644
47001
  "user.email",
46645
47002
  `${input.committer.publicKey.slice(0, 16)}@users.noreply.github.com`
46646
47003
  ]);
46647
- const top = (await execFileAsync8("git", ["-C", path, "rev-parse", "--show-toplevel"])).stdout.trim();
46648
- if (await realpath2(top) !== await realpath2(path)) {
47004
+ const top = (await execFileAsync11("git", ["-C", path, "rev-parse", "--show-toplevel"])).stdout.trim();
47005
+ if (await realpath3(top) !== await realpath3(path)) {
46649
47006
  throw new Error(`corner worktree escaped its isolated root: ${top}`);
46650
47007
  }
46651
47008
  return { path, gitCommonDir };
@@ -46660,31 +47017,31 @@ async function mapWithConcurrency(values, limit, visit) {
46660
47017
  }));
46661
47018
  }
46662
47019
  async function discoverCornerWorktree(supervisorRoot, cornerId) {
46663
- const cornersRoot = resolve38(supervisorRoot, "beeline", "corners");
46664
- const path = resolve38(cornersRoot, cornerId);
46665
- if (dirname27(path) !== cornersRoot || !existsSync10(resolve38(path, ".git")))
47020
+ const cornersRoot = resolve40(supervisorRoot, "beeline", "corners");
47021
+ const path = resolve40(cornersRoot, cornerId);
47022
+ if (dirname28(path) !== cornersRoot || !existsSync10(resolve40(path, ".git")))
46666
47023
  return void 0;
46667
47024
  const [canonicalRoot, canonicalPath] = await Promise.all([
46668
- realpath2(cornersRoot),
46669
- realpath2(path).catch(() => void 0)
47025
+ realpath3(cornersRoot),
47026
+ realpath3(path).catch(() => void 0)
46670
47027
  ]);
46671
- if (!canonicalPath || relative3(canonicalRoot, canonicalPath) !== cornerId) {
47028
+ if (!canonicalPath || relative4(canonicalRoot, canonicalPath) !== cornerId) {
46672
47029
  throw new Error(`refusing corner ${cornerId} whose checkout path is not canonical`);
46673
47030
  }
46674
- const common = await execFileAsync8("git", ["-C", path, "rev-parse", "--git-common-dir"]).catch(() => void 0);
47031
+ const common = await execFileAsync11("git", ["-C", path, "rev-parse", "--git-common-dir"]).catch(() => void 0);
46675
47032
  if (!common)
46676
47033
  return void 0;
46677
- const gitCommonDir = resolve38(path, common.stdout.trim());
46678
- const repositoriesRoot = resolve38(supervisorRoot, "beeline", "repositories");
46679
- const commonRelative = relative3(repositoriesRoot, gitCommonDir);
46680
- if (!commonRelative || commonRelative === ".." || commonRelative.startsWith(`..${sep2}`) || commonRelative.startsWith(sep2)) {
47034
+ const gitCommonDir = resolve40(path, common.stdout.trim());
47035
+ const repositoriesRoot = resolve40(supervisorRoot, "beeline", "repositories");
47036
+ const commonRelative = relative4(repositoriesRoot, gitCommonDir);
47037
+ if (!commonRelative || commonRelative === ".." || commonRelative.startsWith(`..${sep3}`) || commonRelative.startsWith(sep3)) {
46681
47038
  throw new Error(`refusing corner ${cornerId} with git directory outside repository cache`);
46682
47039
  }
46683
47040
  return { path, gitCommonDir };
46684
47041
  }
46685
47042
  async function localCornerWorktreeIds(supervisorRoot) {
46686
- const root = resolve38(supervisorRoot, "beeline", "corners");
46687
- const entries = await readdir9(root, { withFileTypes: true }).catch((error) => {
47043
+ const root = resolve40(supervisorRoot, "beeline", "corners");
47044
+ const entries = await readdir11(root, { withFileTypes: true }).catch((error) => {
46688
47045
  if (error.code === "ENOENT")
46689
47046
  return [];
46690
47047
  throw error;
@@ -46698,12 +47055,12 @@ async function removeCornerWorktreeAndBranches(worktree, options = {}) {
46698
47055
  const worktreeExists = existsSync10(worktree.path);
46699
47056
  const localExists = await gitRefExists(worktree.gitCommonDir, localRef);
46700
47057
  if (worktreeExists) {
46701
- const checkedOut = await execFileAsync8("git", ["-C", worktree.path, "symbolic-ref", "--quiet", "HEAD"], { maxBuffer: 4 * 1024 * 1024 }).then((result) => result.stdout.trim(), () => void 0);
47058
+ const checkedOut = await execFileAsync11("git", ["-C", worktree.path, "symbolic-ref", "--quiet", "HEAD"], { maxBuffer: 4 * 1024 * 1024 }).then((result) => result.stdout.trim(), () => void 0);
46702
47059
  if (!worktree.recovered && checkedOut !== localRef) {
46703
47060
  throw new Error(`corner worktree branch mismatch: expected ${localRef}`);
46704
47061
  }
46705
47062
  await assertCornerWorktreePublished(worktree);
46706
- await execFileAsync8("git", [
47063
+ await execFileAsync11("git", [
46707
47064
  `--git-dir=${worktree.gitCommonDir}`,
46708
47065
  "worktree",
46709
47066
  "remove",
@@ -46728,7 +47085,7 @@ async function removeCornerWorktreeAndBranches(worktree, options = {}) {
46728
47085
  await deleteExactRemoteBranch(worktree.gitCommonDir, remoteRef, worktree.token);
46729
47086
  }
46730
47087
  if (await gitRefExists(worktree.gitCommonDir, localRef)) {
46731
- await execFileAsync8("git", [
47088
+ await execFileAsync11("git", [
46732
47089
  `--git-dir=${worktree.gitCommonDir}`,
46733
47090
  "branch",
46734
47091
  "--delete",
@@ -46739,18 +47096,18 @@ async function removeCornerWorktreeAndBranches(worktree, options = {}) {
46739
47096
  }
46740
47097
  }
46741
47098
  async function assertCornerWorktreePublished(worktree) {
46742
- const status = async () => (await execFileAsync8("git", ["-C", worktree.path, "status", "--porcelain=v1", "--untracked-files=all"], { maxBuffer: 4 * 1024 * 1024 })).stdout.trim();
46743
- const originalHead = (await execFileAsync8("git", ["-C", worktree.path, "rev-parse", "--verify", "HEAD"])).stdout.trim();
47099
+ const status = async () => (await execFileAsync11("git", ["-C", worktree.path, "status", "--porcelain=v1", "--untracked-files=all"], { maxBuffer: 4 * 1024 * 1024 })).stdout.trim();
47100
+ const originalHead = (await execFileAsync11("git", ["-C", worktree.path, "rev-parse", "--verify", "HEAD"])).stdout.trim();
46744
47101
  if (await status())
46745
47102
  throw new Error(`corner ${worktree.cornerId} has unpushed working-tree work`);
46746
47103
  await assertPublishedOnOrigin(worktree.gitCommonDir, originalHead, worktree.cornerId, worktree.token);
46747
- const settledHead = (await execFileAsync8("git", ["-C", worktree.path, "rev-parse", "--verify", "HEAD"])).stdout.trim();
47104
+ const settledHead = (await execFileAsync11("git", ["-C", worktree.path, "rev-parse", "--verify", "HEAD"])).stdout.trim();
46748
47105
  if (settledHead !== originalHead || await status()) {
46749
47106
  throw new Error(`corner ${worktree.cornerId} changed during cleanup`);
46750
47107
  }
46751
47108
  }
46752
47109
  async function assertLocalBranchPublished(worktree) {
46753
- const head = (await execFileAsync8("git", [
47110
+ const head = (await execFileAsync11("git", [
46754
47111
  `--git-dir=${worktree.gitCommonDir}`,
46755
47112
  "rev-parse",
46756
47113
  "--verify",
@@ -46761,7 +47118,7 @@ async function assertLocalBranchPublished(worktree) {
46761
47118
  async function assertPublishedOnOrigin(gitCommonDir, head, cornerId, token) {
46762
47119
  let published = await originContains(gitCommonDir, head);
46763
47120
  if (!published) {
46764
- await execFileAsync8("git", [
47121
+ await execFileAsync11("git", [
46765
47122
  `--git-dir=${gitCommonDir}`,
46766
47123
  "fetch",
46767
47124
  "--prune",
@@ -46777,7 +47134,7 @@ function hasUnpublishedWork(error) {
46777
47134
  return error instanceof Error && / has unpushed (?:commits|working-tree work)$/.test(error.message);
46778
47135
  }
46779
47136
  async function originContains(gitCommonDir, head) {
46780
- const result = await execFileAsync8("git", [
47137
+ const result = await execFileAsync11("git", [
46781
47138
  `--git-dir=${gitCommonDir}`,
46782
47139
  "for-each-ref",
46783
47140
  "--format=%(refname)",
@@ -46787,13 +47144,13 @@ async function originContains(gitCommonDir, head) {
46787
47144
  ]);
46788
47145
  return Boolean(result.stdout.trim());
46789
47146
  }
46790
- var execFileAsync8 = promisify8(execFile13);
47147
+ var execFileAsync11 = promisify11(execFile16);
46791
47148
  async function removeCornerScratchWorkspace(input) {
46792
- const expected = resolve38(input.roomRoot, "scratch");
46793
- if (resolve38(input.scratchPath) !== expected) {
47149
+ const expected = resolve40(input.roomRoot, "scratch");
47150
+ if (resolve40(input.scratchPath) !== expected) {
46794
47151
  throw new Error(`refusing to remove scratch outside corner ${input.cornerId}`);
46795
47152
  }
46796
- await rm15(expected, { recursive: true, force: true });
47153
+ await rm17(expected, { recursive: true, force: true });
46797
47154
  }
46798
47155
  var RoomRuntimeCoordinator = class {
46799
47156
  configPath;
@@ -46820,6 +47177,7 @@ var RoomRuntimeCoordinator = class {
46820
47177
  * then left alone; the checkout and its commits are kept, never deleted.
46821
47178
  */
46822
47179
  archiveCleanupAbandoned = /* @__PURE__ */ new Set();
47180
+ lastCornerScratchSweepAt = 0;
46823
47181
  startingCorners = /* @__PURE__ */ new Set();
46824
47182
  /**
46825
47183
  * Rooms whose start is in flight. `running` is not set until the checkout
@@ -47060,7 +47418,8 @@ var RoomRuntimeCoordinator = class {
47060
47418
  return;
47061
47419
  try {
47062
47420
  const result = await this.options.daemonApi.execute("listRoomCorners", {
47063
- roomId: room.roomId
47421
+ roomId: room.roomId,
47422
+ activeOnly: true
47064
47423
  });
47065
47424
  for (const corner of result.corners) {
47066
47425
  this.monolithCornerParents.set(corner.cornerId, room.roomId);
@@ -47100,6 +47459,9 @@ var RoomRuntimeCoordinator = class {
47100
47459
  if (this.stopped)
47101
47460
  return "member";
47102
47461
  await this.sweepArchivedCornerWorktrees(archivedCorners, desired);
47462
+ if (this.stopped)
47463
+ return "member";
47464
+ await this.sweepCornerLocalState(archivedCorners, desired);
47103
47465
  if (this.stopped)
47104
47466
  return "member";
47105
47467
  for (const cornerId of this.idleCornerSubscriptions.keys()) {
@@ -47117,6 +47479,10 @@ var RoomRuntimeCoordinator = class {
47117
47479
  await this.stopRunning(channelId, running);
47118
47480
  this.roomRemovalConfirmations.delete(channelId);
47119
47481
  }
47482
+ for (const cornerId of this.monolithCornerParents.keys()) {
47483
+ if (!desired.has(cornerId) && !this.running.has(cornerId) && !this.startingCorners.has(cornerId))
47484
+ this.monolithCornerParents.delete(cornerId);
47485
+ }
47120
47486
  this.surfaceHealth.retain(/* @__PURE__ */ new Set([...desired, ...this.running.keys()]));
47121
47487
  await mapWithConcurrency(desiredTopRooms, ROOM_JOIN_CONCURRENCY, async (roomId) => {
47122
47488
  if (this.stopped)
@@ -47191,6 +47557,8 @@ var RoomRuntimeCoordinator = class {
47191
47557
  if (event.archived === true) {
47192
47558
  this.unwatchCorner(roomId);
47193
47559
  this.surfaceHealth.remove(roomId);
47560
+ if (!this.running.has(roomId))
47561
+ this.monolithCornerParents.delete(roomId);
47194
47562
  return;
47195
47563
  }
47196
47564
  this.roomRemovalConfirmations.delete(roomId);
@@ -47228,18 +47596,20 @@ var RoomRuntimeCoordinator = class {
47228
47596
  } catch (error) {
47229
47597
  console.error(`[thin-core] corner ${channelId} cleanup failed; will retry:`, error);
47230
47598
  }
47599
+ if (running.worktree || running.scratch)
47600
+ await this.cleanupArchivedCornerLocalState(channelId);
47231
47601
  }
47232
47602
  roomRecord(roomId) {
47233
47603
  return this.runtime.rooms.find((room) => room.channelId === roomId);
47234
47604
  }
47235
47605
  roomRoot(roomId) {
47236
- return this.roomRecord(roomId)?.root ?? resolve38(dirname27(this.configPath), "rooms", roomId);
47606
+ return this.roomRecord(roomId)?.root ?? resolve40(dirname28(this.configPath), "rooms", roomId);
47237
47607
  }
47238
47608
  roomAgentHomeRoot(workspaceRoot, required = false) {
47239
47609
  const flag = process.env.BUZZY_BODY_ROOM_HOME;
47240
47610
  if (!required && flag === "0")
47241
47611
  return void 0;
47242
- const home = resolve38(workspaceRoot, "agent-home");
47612
+ const home = resolve40(workspaceRoot, "agent-home");
47243
47613
  if (!required && flag !== "1" && !existsSync10(home) && existsSync10(workspaceRoot))
47244
47614
  return void 0;
47245
47615
  try {
@@ -47255,10 +47625,10 @@ var RoomRuntimeCoordinator = class {
47255
47625
  return {
47256
47626
  ...this.baseConfig,
47257
47627
  workspaceRoot,
47258
- agentPrivateRoot: resolve38(workspaceRoot, "agent-private"),
47259
- agentMemoryRoot: resolve38(dirname27(this.configPath), "memory"),
47260
- openRouterRoutingCacheDir: openRouterRoutingCacheDir(dirname27(this.configPath)),
47261
- turnTraceDir: turnTraceDirectory(dirname27(this.configPath)),
47628
+ agentPrivateRoot: resolve40(workspaceRoot, "agent-private"),
47629
+ agentMemoryRoot: resolve40(dirname28(this.configPath), "memory"),
47630
+ openRouterRoutingCacheDir: openRouterRoutingCacheDir(dirname28(this.configPath)),
47631
+ turnTraceDir: turnTraceDirectory(dirname28(this.configPath)),
47262
47632
  ...agentHomeRoot ? { agentHomeRoot } : {}
47263
47633
  };
47264
47634
  }
@@ -47339,17 +47709,17 @@ var RoomRuntimeCoordinator = class {
47339
47709
  const remote = roomCheckoutRemote(repository.remote);
47340
47710
  const targetBranch = repository.targetBranch || "main";
47341
47711
  const checkoutId = createHash14("sha256").update(`${roomId}\0${remote}\0${targetBranch}`).digest("hex").slice(0, 24);
47342
- const path = resolve38(this.runtime.supervisorRoot, "beeline", "room-checkouts", checkoutId);
47343
- await mkdir27(dirname27(path), { recursive: true, mode: 448 });
47712
+ const path = resolve40(this.runtime.supervisorRoot, "beeline", "room-checkouts", checkoutId);
47713
+ await mkdir27(dirname28(path), { recursive: true, mode: 448 });
47344
47714
  const token = remote.startsWith("https://github.com/") ? await this.parentRepositoryToken(roomId) : void 0;
47345
47715
  const env = token ? githubGitEnv(token.token) : process.env;
47346
- if (!existsSync10(resolve38(path, ".git"))) {
47347
- await execFileAsync8("git", ["clone", "--no-checkout", remote, path], {
47716
+ if (!existsSync10(resolve40(path, ".git"))) {
47717
+ await execFileAsync11("git", ["clone", "--no-checkout", remote, path], {
47348
47718
  env,
47349
47719
  maxBuffer: 4 * 1024 * 1024
47350
47720
  });
47351
47721
  }
47352
- const fetched = await execFileAsync8("git", [
47722
+ const fetched = await execFileAsync11("git", [
47353
47723
  "-C",
47354
47724
  path,
47355
47725
  "fetch",
@@ -47365,7 +47735,7 @@ var RoomRuntimeCoordinator = class {
47365
47735
  void this.options.daemonApi.execute("noteEmptyRoomRepository", { roomId }).catch((error) => console.warn(`[thin-core] Room ${roomId} empty-repository notice failed:`, error));
47366
47736
  return this.roomRoot(roomId);
47367
47737
  }
47368
- await execFileAsync8("git", ["-C", path, "checkout", "--detach", "--force", `origin/${targetBranch}`], {
47738
+ await execFileAsync11("git", ["-C", path, "checkout", "--detach", "--force", `origin/${targetBranch}`], {
47369
47739
  env,
47370
47740
  maxBuffer: 4 * 1024 * 1024
47371
47741
  });
@@ -47380,7 +47750,7 @@ var RoomRuntimeCoordinator = class {
47380
47750
  const cwd = await this.materializeRoomCheckout(roomId, repository);
47381
47751
  if (cwd === this.roomRoot(roomId))
47382
47752
  return { cwd };
47383
- const { stdout: stdout6 } = await execFileAsync8("git", ["-C", cwd, "rev-parse", "--verify", "HEAD"]);
47753
+ const { stdout: stdout6 } = await execFileAsync11("git", ["-C", cwd, "rev-parse", "--verify", "HEAD"]);
47384
47754
  return { cwd, branch, commit: stdout6.trim() };
47385
47755
  } catch (error) {
47386
47756
  console.warn(`[thin-core] Room ${roomId} checkout refresh unavailable:`, error);
@@ -47430,9 +47800,11 @@ var RoomRuntimeCoordinator = class {
47430
47800
  featureBranch,
47431
47801
  token: granted.token
47432
47802
  }) : void 0;
47433
- const workspacePath = worktree?.path ?? resolve38(this.roomRoot(corner.cornerId), "scratch");
47803
+ const workspacePath = worktree?.path ?? resolve40(this.roomRoot(corner.cornerId), "scratch");
47434
47804
  if (!worktree)
47435
47805
  await mkdir27(workspacePath, { recursive: true, mode: 448 });
47806
+ await writePrivateFileAtomically(resolve40(this.roomRoot(corner.cornerId), ".beeline-corner.json"), `${JSON.stringify({ cornerId: corner.cornerId, parentRoomId: corner.parentRoomId })}
47807
+ `);
47436
47808
  if (worktree && shouldPostInitialCornerWorkingState(restore)) {
47437
47809
  await this.options.daemonApi.execute("postCornerRemoteState", {
47438
47810
  cornerId: corner.cornerId,
@@ -47486,10 +47858,11 @@ var RoomRuntimeCoordinator = class {
47486
47858
  this.surfaceHealth.degraded(corner.cornerId, "corner command loop exited");
47487
47859
  console.error(`[thin-core] corner ${corner.cornerId} failed:`, error);
47488
47860
  }
47489
- }).finally(() => {
47861
+ }).finally(async () => {
47490
47862
  if (this.running.get(corner.cornerId)?.body === loop) {
47491
47863
  this.running.delete(corner.cornerId);
47492
47864
  }
47865
+ await this.cleanupArchivedCornerLocalState(corner.cornerId).catch((error) => console.error(`[thin-core] corner ${corner.cornerId} local cleanup deferred:`, error));
47493
47866
  });
47494
47867
  if (this.stopped) {
47495
47868
  controller.abort();
@@ -47606,7 +47979,7 @@ var RoomRuntimeCoordinator = class {
47606
47979
  await this.restartRunningRoomForRepositoryChange(roomId);
47607
47980
  if (this.stopped)
47608
47981
  return;
47609
- const result = await this.options.daemonApi.execute("listRoomCorners", { roomId });
47982
+ const result = await this.options.daemonApi.execute("listRoomCorners", { roomId, activeOnly: true });
47610
47983
  for (const corner of result.corners) {
47611
47984
  this.monolithCornerParents.set(corner.cornerId, roomId);
47612
47985
  if (corner.archived)
@@ -47763,6 +48136,12 @@ var RoomRuntimeCoordinator = class {
47763
48136
  } catch (error) {
47764
48137
  if (hasUnpublishedWork(error)) {
47765
48138
  this.archiveCleanupAbandoned.add(cornerId);
48139
+ try {
48140
+ const saved = await preserveUnpublishedCornerWorktree(worktree, "archived with unpublished local work");
48141
+ console.warn(`[thin-core] corner ${cornerId} recoverable at ${saved.pointer}; pruned ${saved.pruned.join(", ") || "no generated directories"}`);
48142
+ } catch (preserveError) {
48143
+ console.error(`[thin-core] corner ${cornerId} recovery preservation failed:`, preserveError);
48144
+ }
47766
48145
  console.error(`[thin-core] corner ${cornerId} branch cleanup abandoned; unpublished work kept:`, error);
47767
48146
  continue;
47768
48147
  }
@@ -47783,11 +48162,14 @@ var RoomRuntimeCoordinator = class {
47783
48162
  continue;
47784
48163
  if (!this.archiveCleanupDue(cornerId))
47785
48164
  continue;
48165
+ if (this.archiveCleanupAbandoned.has(cornerId))
48166
+ continue;
47786
48167
  if (this.archiveCleanupAccessDenied.has(cornerId) && !corners.has(cornerId))
47787
48168
  continue;
47788
48169
  this.archiveCleanupAccessDenied.delete(cornerId);
47789
48170
  let corner = corners.get(cornerId);
47790
48171
  let discovered;
48172
+ let candidate;
47791
48173
  try {
47792
48174
  discovered = await discoverCornerWorktree(this.runtime.supervisorRoot, cornerId);
47793
48175
  if (!discovered) {
@@ -47813,22 +48195,33 @@ var RoomRuntimeCoordinator = class {
47813
48195
  throw new Error(`archived corner ${corner.cornerId} has no authoritative repository`);
47814
48196
  }
47815
48197
  const expectedCommonDir = cornerRepositoryCacheDir(this.runtime.supervisorRoot, repository.remote);
47816
- if (resolve38(discovered.gitCommonDir) !== expectedCommonDir) {
48198
+ if (resolve40(discovered.gitCommonDir) !== expectedCommonDir) {
47817
48199
  throw new Error(`archived corner ${corner.cornerId} repository cache does not match`);
47818
48200
  }
47819
48201
  if (!restore.featureBranch) {
47820
48202
  throw new Error(`archived corner ${corner.cornerId} has no authoritative feature branch`);
47821
48203
  }
47822
- await this.reapCornerWorktree({
48204
+ candidate = {
47823
48205
  ...discovered,
47824
48206
  cornerId: corner.cornerId,
47825
48207
  branch: restore.featureBranch,
47826
48208
  parentRoomId: corner.parentRoomId,
47827
48209
  token: "",
47828
48210
  recovered: true
47829
- });
48211
+ };
48212
+ await this.reapCornerWorktree(candidate);
47830
48213
  console.log(`[thin-core] swept archived corner worktree ${cornerId}`);
47831
48214
  } catch (error) {
48215
+ if (candidate && hasUnpublishedWork(error)) {
48216
+ this.archiveCleanupAbandoned.add(cornerId);
48217
+ try {
48218
+ const saved = await preserveUnpublishedCornerWorktree(candidate, "archived with unpublished local work");
48219
+ console.warn(`[thin-core] archived corner ${cornerId} recoverable at ${saved.pointer}; pruned ${saved.pruned.join(", ") || "no generated directories"}`);
48220
+ } catch (preserveError) {
48221
+ console.error(`[thin-core] archived corner ${cornerId} recovery preservation failed:`, preserveError);
48222
+ }
48223
+ continue;
48224
+ }
47832
48225
  if (error instanceof DaemonApiError && error.status === 403)
47833
48226
  this.archiveCleanupAccessDenied.add(cornerId);
47834
48227
  else
@@ -47885,6 +48278,64 @@ var RoomRuntimeCoordinator = class {
47885
48278
  scratchPath: scratch.path
47886
48279
  });
47887
48280
  }
48281
+ /** Reap a corner's private state only after the server confirms archive and
48282
+ * its ACP session has suspended. A missing/failed read is never authority. */
48283
+ async cleanupArchivedCornerLocalState(cornerId, knownArchive) {
48284
+ if (this.running.has(cornerId) || this.startingCorners.has(cornerId))
48285
+ return false;
48286
+ const root = resolve40(dirname28(this.configPath), "rooms", cornerId);
48287
+ if (this.roomRoot(cornerId) !== root || !/^[a-zA-Z0-9-]{1,80}$/.test(cornerId))
48288
+ return false;
48289
+ const info = await lstat7(root).catch(() => void 0);
48290
+ if (!info?.isDirectory() || await realpath3(root) !== root)
48291
+ return false;
48292
+ let archived = knownArchive?.has(cornerId) ?? false;
48293
+ if (!archived) {
48294
+ try {
48295
+ const restore = await this.options.daemonApi.execute("getCornerRestoreState", { cornerId });
48296
+ archived = restore.archived === true;
48297
+ } catch {
48298
+ return false;
48299
+ }
48300
+ }
48301
+ if (!archived)
48302
+ return false;
48303
+ await this.scheduler.suspend(cornerId);
48304
+ await rm17(resolve40(root, "scratch"), { recursive: true, force: true });
48305
+ await rm17(resolve40(root, "agent-home"), { recursive: true, force: true });
48306
+ await rm17(resolve40(root, ".beeline-corner.json"), { force: true });
48307
+ return true;
48308
+ }
48309
+ /** Recover chat-only scratch and per-member homes after missed close events
48310
+ * or a helper restart. A marker identifies new code corners after their
48311
+ * checkout has already gone; a scratch directory identifies legacy chat
48312
+ * corners. Active scratch gets a 14-day file TTL, never a wholesale reap. */
48313
+ async sweepCornerLocalState(archived, desired) {
48314
+ const root = resolve40(dirname28(this.configPath), "rooms");
48315
+ const due = this.now() - this.lastCornerScratchSweepAt >= 6 * 60 * 6e4;
48316
+ if (due)
48317
+ this.lastCornerScratchSweepAt = this.now();
48318
+ for (const entry of await readdir11(root, { withFileTypes: true }).catch(() => [])) {
48319
+ if (!entry.isDirectory() || !/^[a-zA-Z0-9-]{1,80}$/.test(entry.name))
48320
+ continue;
48321
+ const roomRoot = resolve40(root, entry.name);
48322
+ const scratch = resolve40(roomRoot, "scratch");
48323
+ const marker = resolve40(roomRoot, ".beeline-corner.json");
48324
+ const hasScratch = (await lstat7(scratch).catch(() => void 0))?.isDirectory() ?? false;
48325
+ const hasMarker = (await lstat7(marker).catch(() => void 0))?.isFile() ?? false;
48326
+ if (!hasScratch && !hasMarker)
48327
+ continue;
48328
+ if (desired.has(entry.name)) {
48329
+ if (due && hasScratch && !this.startingCorners.has(entry.name) && !this.running.get(entry.name)?.body.isBusy()) {
48330
+ await sweepStaleCornerScratch(scratch, this.now(), CORNER_SCRATCH_TTL_MS).catch((error) => console.error(`[thin-core] corner ${entry.name} scratch TTL sweep failed:`, error));
48331
+ }
48332
+ continue;
48333
+ }
48334
+ if (this.running.has(entry.name) || this.startingCorners.has(entry.name))
48335
+ continue;
48336
+ await this.cleanupArchivedCornerLocalState(entry.name, archived).catch((error) => console.error(`[thin-core] corner ${entry.name} local cleanup deferred:`, error));
48337
+ }
48338
+ }
47888
48339
  notePoll(roomId) {
47889
48340
  this.surfaceHealth.intakeReady(roomId);
47890
48341
  const room = this.running.get(roomId);
@@ -47969,7 +48420,7 @@ function githubGitEnv(token) {
47969
48420
  }
47970
48421
  async function gitRefExists(gitCommonDir, ref) {
47971
48422
  try {
47972
- await execFileAsync8("git", [
48423
+ await execFileAsync11("git", [
47973
48424
  `--git-dir=${gitCommonDir}`,
47974
48425
  "show-ref",
47975
48426
  "--verify",
@@ -47985,7 +48436,7 @@ async function gitRefExists(gitCommonDir, ref) {
47985
48436
  }
47986
48437
  async function repositoryHeadRef(gitCommonDir) {
47987
48438
  try {
47988
- const head = await execFileAsync8("git", [
48439
+ const head = await execFileAsync11("git", [
47989
48440
  `--git-dir=${gitCommonDir}`,
47990
48441
  "symbolic-ref",
47991
48442
  "--quiet",
@@ -48005,7 +48456,7 @@ ${gitStderr(error)}`);
48005
48456
  }
48006
48457
  async function deleteExactRemoteBranch(gitCommonDir, remoteRef, token, options = {}) {
48007
48458
  const authEnv = githubGitEnv(token);
48008
- const listRemote = () => execFileAsync8("git", [`--git-dir=${gitCommonDir}`, "ls-remote", "--heads", "origin", remoteRef], {
48459
+ const listRemote = () => execFileAsync11("git", [`--git-dir=${gitCommonDir}`, "ls-remote", "--heads", "origin", remoteRef], {
48009
48460
  env: authEnv,
48010
48461
  maxBuffer: 4 * 1024 * 1024
48011
48462
  });
@@ -48021,7 +48472,7 @@ async function deleteExactRemoteBranch(gitCommonDir, remoteRef, token, options =
48021
48472
  try {
48022
48473
  const remote = await listRemote();
48023
48474
  if (remote.stdout.trim()) {
48024
- await execFileAsync8("git", [`--git-dir=${gitCommonDir}`, "push", "origin", `:${remoteRef}`], {
48475
+ await execFileAsync11("git", [`--git-dir=${gitCommonDir}`, "push", "origin", `:${remoteRef}`], {
48025
48476
  env: authEnv,
48026
48477
  maxBuffer: 4 * 1024 * 1024
48027
48478
  });
@@ -48163,15 +48614,15 @@ var ThinDaemonCore = class {
48163
48614
  };
48164
48615
 
48165
48616
  // apps/body/dist/force-update-journal.js
48166
- import { mkdirSync as mkdirSync4, readFileSync as readFileSync9, renameSync, writeFileSync as writeFileSync5 } from "node:fs";
48167
- import { resolve as resolve39 } from "node:path";
48617
+ import { mkdirSync as mkdirSync4, readFileSync as readFileSync10, renameSync, writeFileSync as writeFileSync5 } from "node:fs";
48618
+ import { resolve as resolve41 } from "node:path";
48168
48619
  var NAME = "force-update-interruptions.json";
48169
48620
  function pathFor(runtimeDir) {
48170
- return resolve39(runtimeDir, NAME);
48621
+ return resolve41(runtimeDir, NAME);
48171
48622
  }
48172
48623
  function read(runtimeDir) {
48173
48624
  try {
48174
- const rows = JSON.parse(readFileSync9(pathFor(runtimeDir), "utf8"));
48625
+ const rows = JSON.parse(readFileSync10(pathFor(runtimeDir), "utf8"));
48175
48626
  if (!Array.isArray(rows))
48176
48627
  throw new Error("invalid force-update interruption journal");
48177
48628
  return rows.map((row) => {
@@ -48245,17 +48696,17 @@ function staleGeneration(error) {
48245
48696
  init_launchd();
48246
48697
  init_systemd();
48247
48698
  import { mkdir as mkdir28, rename as rename11 } from "node:fs/promises";
48248
- import { dirname as dirname28, resolve as resolve40 } from "node:path";
48699
+ import { dirname as dirname29, resolve as resolve42 } from "node:path";
48249
48700
  async function retireRemovedAgent(runtime, options = {}) {
48250
- const deletedRoot = resolve40(runtime.supervisorRoot, "beeline", "deleted-runtimes");
48251
- const target = resolve40(deletedRoot, `${runtime.agent.publicKey}-${Date.now()}`);
48701
+ const deletedRoot = resolve42(runtime.supervisorRoot, "beeline", "deleted-runtimes");
48702
+ const target = resolve42(deletedRoot, `${runtime.agent.publicKey}-${Date.now()}`);
48252
48703
  return relocateAgentRuntime(runtime, target, {
48253
48704
  ...options.run ? { run: options.run } : {}
48254
48705
  });
48255
48706
  }
48256
48707
  async function relocateAgentRuntime(runtime, target, options = {}) {
48257
48708
  const source = runtimeDirectory(runtime.supervisorRoot, runtime.agent.publicKey);
48258
- const destination = resolve40(target);
48709
+ const destination = resolve42(target);
48259
48710
  if (destination === source || destination.startsWith(`${source}/`)) {
48260
48711
  throw new Error("agent runtime destination must be outside the live runtime");
48261
48712
  }
@@ -48268,7 +48719,7 @@ async function relocateAgentRuntime(runtime, target, options = {}) {
48268
48719
  ...options.run ? { run: options.run } : {}
48269
48720
  });
48270
48721
  }
48271
- await mkdir28(dirname28(destination), { recursive: true, mode: 448 });
48722
+ await mkdir28(dirname29(destination), { recursive: true, mode: 448 });
48272
48723
  await rename11(source, destination);
48273
48724
  return destination;
48274
48725
  }
@@ -48278,8 +48729,8 @@ init_self_update();
48278
48729
  init_systemd();
48279
48730
 
48280
48731
  // apps/body/dist/release-status.js
48281
- import { readFile as readFile31, readdir as readdir10, rename as rename12, writeFile as writeFile21 } from "node:fs/promises";
48282
- import { resolve as resolve41 } from "node:path";
48732
+ import { readFile as readFile31, readdir as readdir12, rename as rename12, writeFile as writeFile21 } from "node:fs/promises";
48733
+ import { resolve as resolve43 } from "node:path";
48283
48734
  var DAEMON_RELEASE_STATUS_FILE = "release-status.json";
48284
48735
  var RELEASE_VERSION = /^v\d+\.\d+\.\d+$/;
48285
48736
  var SOURCE_SHA = /^[0-9a-f]{7,64}$/;
@@ -48296,7 +48747,7 @@ async function writeDaemonReleaseStatus(runtimeDir, agentPubkey, identity, optio
48296
48747
  pid: options.pid ?? process.pid,
48297
48748
  readyAt: (options.now?.() ?? /* @__PURE__ */ new Date()).toISOString()
48298
48749
  };
48299
- const target = resolve41(runtimeDir, DAEMON_RELEASE_STATUS_FILE);
48750
+ const target = resolve43(runtimeDir, DAEMON_RELEASE_STATUS_FILE);
48300
48751
  const temporary = `${target}.${status.pid}.tmp`;
48301
48752
  await writeFile21(temporary, `${JSON.stringify(status, null, 2)}
48302
48753
  `, { mode: 384 });
@@ -48305,8 +48756,8 @@ async function writeDaemonReleaseStatus(runtimeDir, agentPubkey, identity, optio
48305
48756
  }
48306
48757
 
48307
48758
  // apps/body/dist/scratch-sweep.js
48308
- import { lstat as lstat5, readdir as readdir11, rmdir as rmdir2, unlink as unlink9 } from "node:fs/promises";
48309
- import { resolve as resolve42 } from "node:path";
48759
+ import { lstat as lstat8, readdir as readdir13, rmdir as rmdir3, unlink as unlink10 } from "node:fs/promises";
48760
+ import { resolve as resolve44 } from "node:path";
48310
48761
  var DEFAULT_SCRATCH_TTL_HOURS = 72;
48311
48762
  var NEVER_SWEEP_SUBDIR_NAMES = new Set(HOME_SUBDIRS.filter((name) => name !== "tmp"));
48312
48763
  function scratchTtlMs(env = process.env) {
@@ -48315,10 +48766,10 @@ function scratchTtlMs(env = process.env) {
48315
48766
  return (Number.isFinite(hours) && hours > 0 ? hours : DEFAULT_SCRATCH_TTL_HOURS) * 60 * 60 * 1e3;
48316
48767
  }
48317
48768
  async function discoverAttachScratchRoots(runtimeDir) {
48318
- const roomsDir = resolve42(runtimeDir, "rooms");
48769
+ const roomsDir = resolve44(runtimeDir, "rooms");
48319
48770
  let entries;
48320
48771
  try {
48321
- entries = await readdir11(roomsDir, { withFileTypes: true });
48772
+ entries = await readdir13(roomsDir, { withFileTypes: true });
48322
48773
  } catch {
48323
48774
  return [];
48324
48775
  }
@@ -48326,8 +48777,8 @@ async function discoverAttachScratchRoots(runtimeDir) {
48326
48777
  for (const entry of entries) {
48327
48778
  if (!entry.isDirectory())
48328
48779
  continue;
48329
- const home = resolve42(roomsDir, entry.name, "agent-home");
48330
- const stats = await lstat5(home).catch(() => void 0);
48780
+ const home = resolve44(roomsDir, entry.name, "agent-home");
48781
+ const stats = await lstat8(home).catch(() => void 0);
48331
48782
  if (stats?.isDirectory())
48332
48783
  roots.push(home);
48333
48784
  }
@@ -48336,7 +48787,7 @@ async function discoverAttachScratchRoots(runtimeDir) {
48336
48787
  async function removeStaleFiles(dir, cutoffMs, protectNamesHere) {
48337
48788
  let entries;
48338
48789
  try {
48339
- entries = await readdir11(dir, { withFileTypes: true });
48790
+ entries = await readdir13(dir, { withFileTypes: true });
48340
48791
  } catch {
48341
48792
  return { removedFiles: 0, removedBytes: 0 };
48342
48793
  }
@@ -48345,22 +48796,22 @@ async function removeStaleFiles(dir, cutoffMs, protectNamesHere) {
48345
48796
  for (const entry of entries) {
48346
48797
  if (protectNamesHere && NEVER_SWEEP_SUBDIR_NAMES.has(entry.name))
48347
48798
  continue;
48348
- const path = resolve42(dir, entry.name);
48349
- const stats = await lstat5(path).catch(() => void 0);
48799
+ const path = resolve44(dir, entry.name);
48800
+ const stats = await lstat8(path).catch(() => void 0);
48350
48801
  if (!stats || stats.isSymbolicLink())
48351
48802
  continue;
48352
48803
  if (stats.isDirectory()) {
48353
48804
  const nested = await removeStaleFiles(path, cutoffMs, false);
48354
48805
  removedFiles += nested.removedFiles;
48355
48806
  removedBytes += nested.removedBytes;
48356
- const remaining = await readdir11(path).catch(() => void 0);
48807
+ const remaining = await readdir13(path).catch(() => void 0);
48357
48808
  if (remaining && remaining.length === 0)
48358
- await rmdir2(path).catch(() => void 0);
48809
+ await rmdir3(path).catch(() => void 0);
48359
48810
  continue;
48360
48811
  }
48361
48812
  if (!stats.isFile() || stats.mtimeMs >= cutoffMs)
48362
48813
  continue;
48363
- await unlink9(path).catch(() => void 0);
48814
+ await unlink10(path).catch(() => void 0);
48364
48815
  removedFiles += 1;
48365
48816
  removedBytes += stats.size;
48366
48817
  }
@@ -48371,7 +48822,7 @@ async function sweepAttachScratchRoots(roots, ttlMs, now2 = Date.now()) {
48371
48822
  let removedFiles = 0;
48372
48823
  let removedBytes = 0;
48373
48824
  for (const root of roots) {
48374
- const stats = await lstat5(root).catch(() => void 0);
48825
+ const stats = await lstat8(root).catch(() => void 0);
48375
48826
  if (!stats?.isDirectory())
48376
48827
  continue;
48377
48828
  const result = await removeStaleFiles(root, cutoffMs, true);
@@ -48394,7 +48845,7 @@ function runScratchSweepLogged(runtimeDir) {
48394
48845
  void runScratchSweep(runtimeDir).catch((error) => console.error("[body] scratch sweep failed:", error));
48395
48846
  }
48396
48847
  async function runAgentRuntime(configPath, host, signal) {
48397
- const runtimeDir = dirname29(configPath);
48848
+ const runtimeDir = dirname30(configPath);
48398
48849
  await convergeRuntimeRecordFileModes(configPath);
48399
48850
  const accessMigration = await migrateRuntimeRecordAccessPolicy(configPath);
48400
48851
  let runtime = accessMigration.runtime;
@@ -48430,7 +48881,7 @@ async function runAgentRuntime(configPath, host, signal) {
48430
48881
  BUZZ_DEV_MCP_BIN: runtime.mcpBinary
48431
48882
  };
48432
48883
  const config = loadBodyConfig({
48433
- workspaceRoot: resolve43(runtimeDir, "workspace"),
48884
+ workspaceRoot: resolve45(runtimeDir, "workspace"),
48434
48885
  llmEnvFile: runtime.llmEnvFile,
48435
48886
  env,
48436
48887
  agent
@@ -48740,7 +49191,7 @@ async function runAgentRuntime(configPath, host, signal) {
48740
49191
  return exitReason ?? lifecycle.stopReason ?? "stopped";
48741
49192
  }
48742
49193
  function registryBrokerSocketPath(home, agentId) {
48743
- return join21(home ?? homedir19(), ".beeline", "registry-mcp-broker", `${process.pid}-${agentId.slice(0, 8)}.sock`);
49194
+ return join23(home ?? homedir19(), ".beeline", "registry-mcp-broker", `${process.pid}-${agentId.slice(0, 8)}.sock`);
48744
49195
  }
48745
49196
  function interruptHostedAgent(agent) {
48746
49197
  agent.lifecycle.quiesce("force-update");
@@ -48781,6 +49232,78 @@ var ForceUpdateCoordinator = class {
48781
49232
  init_launchd();
48782
49233
  init_self_update();
48783
49234
  init_systemd();
49235
+
49236
+ // apps/body/dist/host-disk-retention.js
49237
+ import { execFile as execFile17 } from "node:child_process";
49238
+ import { lstat as lstat9, readdir as readdir14, rm as rm18 } from "node:fs/promises";
49239
+ import { join as join24, resolve as resolve46 } from "node:path";
49240
+ import { promisify as promisify12 } from "node:util";
49241
+ var execFileAsync12 = promisify12(execFile17);
49242
+ var DELETED_RUNTIME_TTL_MS = 30 * 24 * 60 * 6e4;
49243
+ var REPOSITORY_CACHE_TTL_MS = 30 * 24 * 60 * 6e4;
49244
+ async function pruneDeletedRuntimes(supervisorRoot, now2 = Date.now()) {
49245
+ const root = resolve46(supervisorRoot, "beeline", "deleted-runtimes");
49246
+ const removed = [];
49247
+ for (const entry of await readdir14(root, { withFileTypes: true }).catch(() => [])) {
49248
+ const match = /^([a-f0-9]{64})-(\d{13})$/.exec(entry.name);
49249
+ if (!entry.isDirectory() || !match || now2 - Number(match[2]) < DELETED_RUNTIME_TTL_MS)
49250
+ continue;
49251
+ const path = join24(root, entry.name);
49252
+ if (!(await lstat9(path)).isDirectory())
49253
+ continue;
49254
+ await rm18(path, { recursive: true, force: true });
49255
+ removed.push(path);
49256
+ }
49257
+ return removed;
49258
+ }
49259
+ async function pruneRepositoryCaches(supervisorRoot, now2 = Date.now()) {
49260
+ const root = resolve46(supervisorRoot, "beeline", "repositories");
49261
+ const removed = [];
49262
+ for (const entry of await readdir14(root, { withFileTypes: true }).catch(() => [])) {
49263
+ if (!entry.isDirectory() || !/^[a-f0-9]{24}\.git$/.test(entry.name))
49264
+ continue;
49265
+ const path = join24(root, entry.name);
49266
+ const info = await lstat9(path);
49267
+ if (!info.isDirectory() || now2 - info.mtimeMs < REPOSITORY_CACHE_TTL_MS)
49268
+ continue;
49269
+ const listing = await execFileAsync12("git", [`--git-dir=${path}`, "worktree", "list", "--porcelain"]).then((result) => result.stdout, () => void 0);
49270
+ if (listing === void 0)
49271
+ continue;
49272
+ const attached = listing.split("\n").some((line) => line.startsWith("worktree ") && resolve46(line.slice("worktree ".length)) !== path);
49273
+ if (attached)
49274
+ continue;
49275
+ const refs = await execFileAsync12("git", [
49276
+ `--git-dir=${path}`,
49277
+ "for-each-ref",
49278
+ "--format=%(refname) %(objectname)"
49279
+ ]).then((result) => result.stdout, () => void 0);
49280
+ if (refs === void 0)
49281
+ continue;
49282
+ const byName = /* @__PURE__ */ new Map();
49283
+ for (const line of refs.trim().split("\n")) {
49284
+ const match = /^(refs\/\S+) ([a-f0-9]{40,64})$/.exec(line);
49285
+ if (match)
49286
+ byName.set(match[1], match[2]);
49287
+ }
49288
+ const unpublishedHead = [...byName].some(([name, oid]) => name.startsWith("refs/heads/") && byName.get(name.replace("refs/heads/", "refs/remotes/origin/")) !== oid);
49289
+ if (unpublishedHead)
49290
+ continue;
49291
+ const unreachable = await execFileAsync12("git", [
49292
+ `--git-dir=${path}`,
49293
+ "fsck",
49294
+ "--unreachable",
49295
+ "--no-reflogs",
49296
+ "--no-progress"
49297
+ ]).then((result) => result.stdout, () => void 0);
49298
+ if (unreachable === void 0 || /unreachable commit /.test(unreachable))
49299
+ continue;
49300
+ await rm18(path, { recursive: true, force: true });
49301
+ removed.push(path);
49302
+ }
49303
+ return removed;
49304
+ }
49305
+
49306
+ // apps/body/dist/machine-helper.js
48784
49307
  var AGENT_RESTART_BASE_MS = 5e3;
48785
49308
  var AGENT_RESTART_MAX_MS = 6e4;
48786
49309
  var PREVIOUS_HOLDER_WAIT_MS = 12e4;
@@ -48801,6 +49324,32 @@ async function runMachineHelper(options = {}) {
48801
49324
  const slots = /* @__PURE__ */ new Map();
48802
49325
  const hosted = /* @__PURE__ */ new Map();
48803
49326
  const links = /* @__PURE__ */ new Map();
49327
+ let diskSweepRunning = false;
49328
+ let lastModelSweepAt = 0;
49329
+ let lastRetentionSweepAt = 0;
49330
+ const sweepHostDisk = async () => {
49331
+ const now2 = Date.now();
49332
+ if (controller.signal.aborted || diskSweepRunning || [...slots.values()].some((slot) => slot.state === "starting" || slot.state === "restarting") || [...hosted.values()].some((agent) => !agent.core.isWorkspaceIdle()) || now2 - lastModelSweepAt < 60 * 6e4 && now2 - lastRetentionSweepAt < 24 * 60 * 6e4)
49333
+ return;
49334
+ diskSweepRunning = true;
49335
+ try {
49336
+ const modelDue = now2 - lastModelSweepAt >= 60 * 6e4;
49337
+ const removed = modelDue ? await pruneSharedModelCache(resolve47(supervisorRoot, "beeline", "model-cache")) : [];
49338
+ if (modelDue)
49339
+ lastModelSweepAt = now2;
49340
+ if (now2 - lastRetentionSweepAt >= 24 * 60 * 6e4) {
49341
+ removed.push(...await pruneDeletedRuntimes(supervisorRoot));
49342
+ removed.push(...await pruneRepositoryCaches(supervisorRoot));
49343
+ lastRetentionSweepAt = now2;
49344
+ }
49345
+ if (removed.length)
49346
+ console.log(`[helper] idle disk sweep removed ${removed.length} expired cache/runtime directories`);
49347
+ } catch (error) {
49348
+ console.warn("[helper] idle disk sweep failed:", error);
49349
+ } finally {
49350
+ diskSweepRunning = false;
49351
+ }
49352
+ };
48804
49353
  if (!options.configPaths)
48805
49354
  await writeHelperPidRecord(supervisorRoot, process.pid);
48806
49355
  const layout = beelineInstallLayout(env);
@@ -48812,7 +49361,7 @@ async function runMachineHelper(options = {}) {
48812
49361
  const paths = options.configPaths ?? await findAgentRuntimeConfigPaths(env);
48813
49362
  const live = [];
48814
49363
  for (const path of paths) {
48815
- if (!await stat9(path).then(() => true, () => false))
49364
+ if (!await stat10(path).then(() => true, () => false))
48816
49365
  continue;
48817
49366
  if (await isAgentStopped(path))
48818
49367
  continue;
@@ -48832,7 +49381,7 @@ async function runMachineHelper(options = {}) {
48832
49381
  const settle = await settleUpdateAttemptOnStart(layout);
48833
49382
  if (settle.kind === "rolled-back") {
48834
49383
  for (const path of await hostedRuntimes())
48835
- await queueUpdateRollbackAlert(dirname30(path), settle.record.releaseId);
49384
+ await queueUpdateRollbackAlert(dirname31(path), settle.record.releaseId);
48836
49385
  console.error(`[helper] self-update ROLLED BACK: bundle ${describeIdentity(settle.record.to)} never confirmed healthy; restored ${settle.record.previousReleaseId ?? "previous release"}`);
48837
49386
  return finish(await standDownForRollback());
48838
49387
  }
@@ -48873,7 +49422,7 @@ async function runMachineHelper(options = {}) {
48873
49422
  since: new Date(slot.since).toISOString()
48874
49423
  }]))
48875
49424
  };
48876
- await mkdir29(dirname30(path), { recursive: true, mode: 448 });
49425
+ await mkdir29(dirname31(path), { recursive: true, mode: 448 });
48877
49426
  const staged = `${path}.${process.pid}.tmp`;
48878
49427
  await writeFile22(staged, `${JSON.stringify(body, null, 2)}
48879
49428
  `, { mode: 384 });
@@ -48966,6 +49515,7 @@ async function runMachineHelper(options = {}) {
48966
49515
  for (const agent of hosted.values())
48967
49516
  agent.lifecycle.resumeAfterFailedUpdate(() => agent.core.resumeServing());
48968
49517
  }
49518
+ void sweepHostDisk();
48969
49519
  };
48970
49520
  let readyResolve;
48971
49521
  const allEstablished = new Promise((resolveReady) => {
@@ -49020,7 +49570,7 @@ async function runMachineHelper(options = {}) {
49020
49570
  const supervise = async (slot) => {
49021
49571
  let failures = 0;
49022
49572
  while (!controller.signal.aborted && !slot.controller.signal.aborted) {
49023
- if (!await stat9(slot.configPath).then(() => true, () => false)) {
49573
+ if (!await stat10(slot.configPath).then(() => true, () => false)) {
49024
49574
  setState(slot, "removed", "runtime no longer on this machine");
49025
49575
  break;
49026
49576
  }
@@ -49030,7 +49580,7 @@ async function runMachineHelper(options = {}) {
49030
49580
  reason = await runAgent(slot.configPath, host, slot.controller.signal);
49031
49581
  } catch (error) {
49032
49582
  console.error(`[helper] agent ${slot.agentId} failed:`, error);
49033
- const failure = await settleDaemonStartFailure(dirname30(slot.configPath), error).catch(() => ({ distressed: false }));
49583
+ const failure = await settleDaemonStartFailure(dirname31(slot.configPath), error).catch(() => ({ distressed: false }));
49034
49584
  if (failure.distressed) {
49035
49585
  console.error(`[helper] agent ${slot.agentId} failed to start ${failure.count} times; it stays stopped. operator record: ${failure.path}`);
49036
49586
  reason = "distress";
@@ -49079,7 +49629,7 @@ async function runMachineHelper(options = {}) {
49079
49629
  const runtime = await readRuntimeRecord(configPath).catch(() => void 0);
49080
49630
  const slot = existing ?? {
49081
49631
  configPath,
49082
- agentId: runtime?.agent.publicKey ?? dirname30(configPath).split("/").at(-1),
49632
+ agentId: runtime?.agent.publicKey ?? dirname31(configPath).split("/").at(-1),
49083
49633
  controller: new AbortController(),
49084
49634
  state: "starting",
49085
49635
  status: "",
@@ -49119,6 +49669,8 @@ async function runMachineHelper(options = {}) {
49119
49669
  allEstablished,
49120
49670
  new Promise((resolveAbort) => controller.signal.addEventListener("abort", () => resolveAbort(), { once: true }))
49121
49671
  ]);
49672
+ if (!controller.signal.aborted)
49673
+ void sweepHostDisk();
49122
49674
  if (!controller.signal.aborted)
49123
49675
  await notifier.ready(`ready; ${statusLine()}`).catch((error) => console.error("[helper] ready notification failed:", error));
49124
49676
  if (!controller.signal.aborted)
@@ -49185,7 +49737,7 @@ async function waitForPreviousHolder(configPath, signal) {
49185
49737
  return;
49186
49738
  if (!announced) {
49187
49739
  announced = true;
49188
- console.log(`[helper] waiting for process ${pid} to let go of ${dirname30(configPath)}`);
49740
+ console.log(`[helper] waiting for process ${pid} to let go of ${dirname31(configPath)}`);
49189
49741
  }
49190
49742
  const waited = Date.now() - startedAt;
49191
49743
  if (waited >= PREVIOUS_HOLDER_WAIT_MS && !asked) {
@@ -49310,7 +49862,7 @@ async function main() {
49310
49862
  const roomId = roomFlag >= 0 ? args[roomFlag + 1] : void 0;
49311
49863
  if (!configPath || !roomId)
49312
49864
  throw new Error("corner-read-token requires --config and --room");
49313
- const activated = await activateDaemonTransport(resolve44(configPath));
49865
+ const activated = await activateDaemonTransport(resolve48(configPath));
49314
49866
  if (!activated)
49315
49867
  throw new Error("corner-read-token requires monolith transport");
49316
49868
  const credential = await activated.client.execute("getRoomGitHubToken", { roomId });
@@ -49365,7 +49917,7 @@ async function main() {
49365
49917
  }
49366
49918
  if (!configPath && !args.includes("--machine"))
49367
49919
  throw new Error("daemon requires --machine, or --config <runtime.json> for one agent");
49368
- const { reason, lifecycle } = await runMachineHelper(configPath ? { configPaths: [resolve44(configPath)] } : {});
49920
+ const { reason, lifecycle } = await runMachineHelper(configPath ? { configPaths: [resolve48(configPath)] } : {});
49369
49921
  daemonLifecycle = lifecycle;
49370
49922
  lifecycle.exit(reason);
49371
49923
  return;
@@ -49388,7 +49940,7 @@ async function main() {
49388
49940
  if (!agentPubkey)
49389
49941
  throw new Error("stop requires --agent <pubkey>");
49390
49942
  const configs = await findAgentRuntimeConfigPaths(process.env, process.cwd());
49391
- const configPath = configs.find((candidate) => dirname31(candidate).endsWith(agentPubkey));
49943
+ const configPath = configs.find((candidate) => dirname32(candidate).endsWith(agentPubkey));
49392
49944
  if (!configPath)
49393
49945
  throw new Error(`no stored runtime found for agent ${agentPubkey}`);
49394
49946
  const runtime = await readRuntimeRecord(configPath);