@sideboard-ai/core 0.1.167 → 0.1.168

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.
@@ -399,7 +399,7 @@ async function continueSourceThread(threadId, prompt) {
399
399
  await continueOnReply(threadId, prompt);
400
400
  return;
401
401
  }
402
- const { getOrchestrator: getOrchestrator2 } = await import("./orchestrator-GJN4LATM.js");
402
+ const { getOrchestrator: getOrchestrator2 } = await import("./orchestrator-XG3QCMOS.js");
403
403
  await getOrchestrator2().send(threadId, prompt);
404
404
  } catch {
405
405
  }
@@ -2609,7 +2609,7 @@ function formatJobStillRunningContinuePrompt(jobIds) {
2609
2609
  function formatDeferredDoneContinuePrompt() {
2610
2610
  return [
2611
2611
  "You ended the turn after promising to report later, but no detached job is running.",
2612
- "If tests/pack/deploy still need to run: start once with detached-job.js, present_artifact type=log, then loop wait_for_job until stillRunning is false.",
2612
+ "If tests/pack/deploy still need to run: start once with detached-job.cjs, present_artifact type=log, then loop wait_for_job until stillRunning is false.",
2613
2613
  "Do not say you will let the user know later."
2614
2614
  ].join(" ");
2615
2615
  }
@@ -2618,7 +2618,7 @@ function turnWatchedDetachedJob(parts) {
2618
2618
  if (p.type !== "tool") return false;
2619
2619
  if (/wait_for_job$/i.test(p.name ?? "") || /stop_job$/i.test(p.name ?? "")) return true;
2620
2620
  const blob = [p.name, p.detail, p.description, p.input ? JSON.stringify(p.input) : ""].filter(Boolean).join(" ");
2621
- return /detached-job\.js\b/i.test(blob);
2621
+ return /detached-job\.(?:js|cjs)\b/i.test(blob);
2622
2622
  });
2623
2623
  }
2624
2624
  function planJobContinue(opts) {
@@ -2711,7 +2711,7 @@ async function waitForDetachedJob(cwd, id, opts) {
2711
2711
  id: jobId,
2712
2712
  delta: "",
2713
2713
  progress: "No detached job. Start one first.",
2714
- hint: "Start with detached-job.js start <id> -- <command>, then call wait_for_job again."
2714
+ hint: "Start with detached-job.cjs start <id> -- <command>, then call wait_for_job again."
2715
2715
  };
2716
2716
  }
2717
2717
  const deadline = Date.now() + timeoutMs;
@@ -2770,7 +2770,7 @@ async function stopDetachedJob(cwd, id, opts) {
2770
2770
  id: jobId,
2771
2771
  delta: "",
2772
2772
  progress: "No detached job. Start one first.",
2773
- hint: "Start with detached-job.js start <id> -- <command>, then wait_for_job or stop_job.",
2773
+ hint: "Start with detached-job.cjs start <id> -- <command>, then wait_for_job or stop_job.",
2774
2774
  stopped: false,
2775
2775
  reason: "not-found"
2776
2776
  };
@@ -5270,21 +5270,21 @@ Do **not** ask the human to check back. Detach, then **wait** in 45s slices (MCP
5270
5270
 
5271
5271
  ## Tool
5272
5272
 
5273
- Use the helper from the Sideboard playbook \u2014 an absolute \`node "\u2026" start\` path injected each turn. If this worktree has \`scripts/detached-job.js\`, that is the same tool.
5273
+ Use the helper from the Sideboard playbook \u2014 an absolute \`node "\u2026" start\` path injected each turn. If this worktree has \`scripts/detached-job.cjs\`, that is the same tool.
5274
5274
 
5275
5275
  \`\`\`bash
5276
5276
  # Start (exits in ~1s; job survives this turn)
5277
- node <detached-job.js> start <id> -- <command> [args...]
5277
+ node <detached-job.cjs> start <id> -- <command> [args...]
5278
5278
 
5279
5279
  # Wait \u2014 prefer MCP wait_for_job (same 45s / stillRunning contract).
5280
5280
  # Shell fallback:
5281
- node <detached-job.js> wait <id>
5281
+ node <detached-job.cjs> wait <id>
5282
5282
 
5283
5283
  # Block until the process exits (humans / a turn that will not be interrupted)
5284
- node <detached-job.js> wait <id> --until-done
5284
+ node <detached-job.cjs> wait <id> --until-done
5285
5285
 
5286
- node <detached-job.js> stop <id> [--reason TEXT]
5287
- node <detached-job.js> status <id>
5286
+ node <detached-job.cjs> stop <id> [--reason TEXT]
5287
+ node <detached-job.cjs> status <id>
5288
5288
  \`\`\`
5289
5289
 
5290
5290
  \`<id>\` is kebab-case (\`mac-release\`, \`core-test\`, \`fly-deploy\`). State is \`.context/.sideboard/detached-jobs/<id>/\` (local scratch).
@@ -5315,7 +5315,7 @@ After **start**, present once (\`status=running\`, empty or first lines). After
5315
5315
  Ad-hoc pid/log (legacy or another tool\u2019s files):
5316
5316
 
5317
5317
  \`\`\`bash
5318
- node <detached-job.js> wait --pid-file FILE --log-file FILE [--ok-pattern TEXT]
5318
+ node <detached-job.cjs> wait --pid-file FILE --log-file FILE [--ok-pattern TEXT]
5319
5319
  \`\`\`
5320
5320
 
5321
5321
  ## Agent loop
@@ -5324,7 +5324,7 @@ node <detached-job.js> wait --pid-file FILE --log-file FILE [--ok-pattern TEXT]
5324
5324
  2. Immediately \`present_artifact\` \`type=log\` (same \`artifact_id\`, \`status=running\`) \u2014 the human should see **working** in the side column, not a \u201Ccheck back later\u201D message.
5325
5325
  3. Loop \`wait_for_job\` (or shell \`wait\`). After each slice, \`present_artifact\` the same id with \`content=delta\` only.
5326
5326
  4. On \`ok\`, present once more (\`status=ok\`, last \`delta\`) and finish the task. On \`failed\`, fix from the log.
5327
- 5. **Stop** when the job is hanging, buffering forever, watching the wrong thing, or you already have the answer. MCP \`stop_job\` (same id, optional \`reason\`) or \`detached-job.js stop <id>\`. Do **not** stop a pack/test/deploy that is clearly making progress.
5327
+ 5. **Stop** when the job is hanging, buffering forever, watching the wrong thing, or you already have the answer. MCP \`stop_job\` (same id, optional \`reason\`) or \`detached-job.cjs stop <id>\`. Do **not** stop a pack/test/deploy that is clearly making progress.
5328
5328
 
5329
5329
  Never tell the user \u201Csay status when it\u2019s done.\u201D You wait \u2014 unless you decided to stop.
5330
5330
 
@@ -5337,7 +5337,7 @@ Huge \`--json\` / \`--expand\` dumps crash any worktree agent mid-turn (Claude /
5337
5337
  Do **not** watch after every push. If the user gave a goal (Greptile 5/5, CI green, until checks pass), wait the same way:
5338
5338
 
5339
5339
  \`\`\`bash
5340
- node <detached-job.js> start pr-checks -- gh pr checks --watch
5340
+ node <detached-job.cjs> start pr-checks -- gh pr checks --watch
5341
5341
  \`\`\`
5342
5342
 
5343
5343
  On miss, fix, commit, push, and watch again until the goal is met or you are blocked. Do not ask the human to poll. Do not merge unless asked.
@@ -5603,19 +5603,26 @@ import { join as join15 } from "path";
5603
5603
  import { existsSync as existsSync15 } from "fs";
5604
5604
  import { dirname as dirname5, join as join14 } from "path";
5605
5605
  import { fileURLToPath } from "url";
5606
+ var DETACHED_JOB_FILENAMES = ["detached-job.cjs", "detached-job.js"];
5607
+ function detachedJobScriptIn(dir) {
5608
+ for (const name of DETACHED_JOB_FILENAMES) {
5609
+ const script = join14(dir, "scripts", name);
5610
+ if (existsSync15(script)) return script;
5611
+ }
5612
+ return null;
5613
+ }
5606
5614
  function packagedDetachedJobPath() {
5607
5615
  const dir = packagedMcpDir();
5608
5616
  if (!dir) return null;
5609
- const script = join14(dir, "scripts", "detached-job.js");
5610
- return existsSync15(script) ? script : null;
5617
+ return detachedJobScriptIn(dir);
5611
5618
  }
5612
5619
  function resolveDetachedJobScript() {
5613
5620
  const packaged = packagedDetachedJobPath();
5614
5621
  if (packaged) return packaged;
5615
5622
  let dir = dirname5(fileURLToPath(import.meta.url));
5616
5623
  for (let i = 0; i < 8; i++) {
5617
- const candidate = join14(dir, "scripts", "detached-job.js");
5618
- if (existsSync15(candidate)) return candidate;
5624
+ const candidate = detachedJobScriptIn(dir);
5625
+ if (candidate) return candidate;
5619
5626
  const parent = dirname5(dir);
5620
5627
  if (parent === dir) break;
5621
5628
  dir = parent;
@@ -5625,7 +5632,7 @@ function resolveDetachedJobScript() {
5625
5632
  function formatDetachedJobInvoke(scriptPath) {
5626
5633
  const resolved = scriptPath === void 0 ? resolveDetachedJobScript() : scriptPath;
5627
5634
  if (resolved) return `node ${JSON.stringify(resolved)}`;
5628
- return "node scripts/detached-job.js";
5635
+ return "node scripts/detached-job.cjs";
5629
5636
  }
5630
5637
 
5631
5638
  // src/agents/instructions.ts
@@ -5819,7 +5826,7 @@ function formatLongRunningDirective(opts) {
5819
5826
  return [
5820
5827
  "Long-running jobs (mandatory when a command may run more than ~30s):",
5821
5828
  "A Sideboard worktree turn SIGTERMs the agent shell (and its process group) when the user sends another message or the turn is interrupted. `block_until_ms: 0` is not enough. Do not ask the human to poll.",
5822
- `Helper (same tool as \`scripts/detached-job.js\` when that file exists in the worktree): \`${invoke}\``,
5829
+ `Helper (same tool as \`scripts/detached-job.cjs\` when that file exists in the worktree): \`${invoke}\``,
5823
5830
  `- Start once: \`${invoke} start <id> -- <command> [args...]\` (cwd = this worktree). If JSON says already-running, do not start again.`,
5824
5831
  "- Immediately `present_artifact` `type=log` with `artifact_id=<id>` and `status=running` \u2014 the side column is the live view.",
5825
5832
  `- Loop Sideboard MCP \`wait_for_job\` with the same id (returns in ~45s). stillRunning \u2192 present the same id with \`content=delta\` only \u2192 wait_for_job again. Shell fallback: \`${invoke} wait <id>\`. Do not resend the full log or HTML.`,
@@ -6233,7 +6240,7 @@ function formatScheduledPrompt(name, prompt) {
6233
6240
  ${prompt}`;
6234
6241
  }
6235
6242
  async function defaultDeps() {
6236
- const { getOrchestrator: getOrchestrator2, startOrchestration: startOrchestration2 } = await import("./orchestrator-GJN4LATM.js");
6243
+ const { getOrchestrator: getOrchestrator2, startOrchestration: startOrchestration2 } = await import("./orchestrator-XG3QCMOS.js");
6237
6244
  const orch = getOrchestrator2();
6238
6245
  return {
6239
6246
  findThread: (id) => findThreadByRef(id),
@@ -464,7 +464,7 @@ async function continueSourceThread(threadId, prompt) {
464
464
  await continueOnReply(threadId, prompt);
465
465
  return;
466
466
  }
467
- const { getOrchestrator: getOrchestrator2 } = await import("./orchestrator-VIMO2DP2.js");
467
+ const { getOrchestrator: getOrchestrator2 } = await import("./orchestrator-IIME6KXQ.js");
468
468
  await getOrchestrator2().send(threadId, prompt);
469
469
  } catch {
470
470
  }
@@ -2694,7 +2694,7 @@ function formatJobStillRunningContinuePrompt(jobIds) {
2694
2694
  function formatDeferredDoneContinuePrompt() {
2695
2695
  return [
2696
2696
  "You ended the turn after promising to report later, but no detached job is running.",
2697
- "If tests/pack/deploy still need to run: start once with detached-job.js, present_artifact type=log, then loop wait_for_job until stillRunning is false.",
2697
+ "If tests/pack/deploy still need to run: start once with detached-job.cjs, present_artifact type=log, then loop wait_for_job until stillRunning is false.",
2698
2698
  "Do not say you will let the user know later."
2699
2699
  ].join(" ");
2700
2700
  }
@@ -2703,7 +2703,7 @@ function turnWatchedDetachedJob(parts) {
2703
2703
  if (p.type !== "tool") return false;
2704
2704
  if (/wait_for_job$/i.test(p.name ?? "") || /stop_job$/i.test(p.name ?? "")) return true;
2705
2705
  const blob = [p.name, p.detail, p.description, p.input ? JSON.stringify(p.input) : ""].filter(Boolean).join(" ");
2706
- return /detached-job\.js\b/i.test(blob);
2706
+ return /detached-job\.(?:js|cjs)\b/i.test(blob);
2707
2707
  });
2708
2708
  }
2709
2709
  function planJobContinue(opts) {
@@ -2796,7 +2796,7 @@ async function waitForDetachedJob(cwd, id, opts) {
2796
2796
  id: jobId,
2797
2797
  delta: "",
2798
2798
  progress: "No detached job. Start one first.",
2799
- hint: "Start with detached-job.js start <id> -- <command>, then call wait_for_job again."
2799
+ hint: "Start with detached-job.cjs start <id> -- <command>, then call wait_for_job again."
2800
2800
  };
2801
2801
  }
2802
2802
  const deadline = Date.now() + timeoutMs;
@@ -2855,7 +2855,7 @@ async function stopDetachedJob(cwd, id, opts) {
2855
2855
  id: jobId,
2856
2856
  delta: "",
2857
2857
  progress: "No detached job. Start one first.",
2858
- hint: "Start with detached-job.js start <id> -- <command>, then wait_for_job or stop_job.",
2858
+ hint: "Start with detached-job.cjs start <id> -- <command>, then wait_for_job or stop_job.",
2859
2859
  stopped: false,
2860
2860
  reason: "not-found"
2861
2861
  };
@@ -5422,21 +5422,21 @@ Do **not** ask the human to check back. Detach, then **wait** in 45s slices (MCP
5422
5422
 
5423
5423
  ## Tool
5424
5424
 
5425
- Use the helper from the Sideboard playbook \u2014 an absolute \`node "\u2026" start\` path injected each turn. If this worktree has \`scripts/detached-job.js\`, that is the same tool.
5425
+ Use the helper from the Sideboard playbook \u2014 an absolute \`node "\u2026" start\` path injected each turn. If this worktree has \`scripts/detached-job.cjs\`, that is the same tool.
5426
5426
 
5427
5427
  \`\`\`bash
5428
5428
  # Start (exits in ~1s; job survives this turn)
5429
- node <detached-job.js> start <id> -- <command> [args...]
5429
+ node <detached-job.cjs> start <id> -- <command> [args...]
5430
5430
 
5431
5431
  # Wait \u2014 prefer MCP wait_for_job (same 45s / stillRunning contract).
5432
5432
  # Shell fallback:
5433
- node <detached-job.js> wait <id>
5433
+ node <detached-job.cjs> wait <id>
5434
5434
 
5435
5435
  # Block until the process exits (humans / a turn that will not be interrupted)
5436
- node <detached-job.js> wait <id> --until-done
5436
+ node <detached-job.cjs> wait <id> --until-done
5437
5437
 
5438
- node <detached-job.js> stop <id> [--reason TEXT]
5439
- node <detached-job.js> status <id>
5438
+ node <detached-job.cjs> stop <id> [--reason TEXT]
5439
+ node <detached-job.cjs> status <id>
5440
5440
  \`\`\`
5441
5441
 
5442
5442
  \`<id>\` is kebab-case (\`mac-release\`, \`core-test\`, \`fly-deploy\`). State is \`.context/.sideboard/detached-jobs/<id>/\` (local scratch).
@@ -5467,7 +5467,7 @@ After **start**, present once (\`status=running\`, empty or first lines). After
5467
5467
  Ad-hoc pid/log (legacy or another tool\u2019s files):
5468
5468
 
5469
5469
  \`\`\`bash
5470
- node <detached-job.js> wait --pid-file FILE --log-file FILE [--ok-pattern TEXT]
5470
+ node <detached-job.cjs> wait --pid-file FILE --log-file FILE [--ok-pattern TEXT]
5471
5471
  \`\`\`
5472
5472
 
5473
5473
  ## Agent loop
@@ -5476,7 +5476,7 @@ node <detached-job.js> wait --pid-file FILE --log-file FILE [--ok-pattern TEXT]
5476
5476
  2. Immediately \`present_artifact\` \`type=log\` (same \`artifact_id\`, \`status=running\`) \u2014 the human should see **working** in the side column, not a \u201Ccheck back later\u201D message.
5477
5477
  3. Loop \`wait_for_job\` (or shell \`wait\`). After each slice, \`present_artifact\` the same id with \`content=delta\` only.
5478
5478
  4. On \`ok\`, present once more (\`status=ok\`, last \`delta\`) and finish the task. On \`failed\`, fix from the log.
5479
- 5. **Stop** when the job is hanging, buffering forever, watching the wrong thing, or you already have the answer. MCP \`stop_job\` (same id, optional \`reason\`) or \`detached-job.js stop <id>\`. Do **not** stop a pack/test/deploy that is clearly making progress.
5479
+ 5. **Stop** when the job is hanging, buffering forever, watching the wrong thing, or you already have the answer. MCP \`stop_job\` (same id, optional \`reason\`) or \`detached-job.cjs stop <id>\`. Do **not** stop a pack/test/deploy that is clearly making progress.
5480
5480
 
5481
5481
  Never tell the user \u201Csay status when it\u2019s done.\u201D You wait \u2014 unless you decided to stop.
5482
5482
 
@@ -5489,7 +5489,7 @@ Huge \`--json\` / \`--expand\` dumps crash any worktree agent mid-turn (Claude /
5489
5489
  Do **not** watch after every push. If the user gave a goal (Greptile 5/5, CI green, until checks pass), wait the same way:
5490
5490
 
5491
5491
  \`\`\`bash
5492
- node <detached-job.js> start pr-checks -- gh pr checks --watch
5492
+ node <detached-job.cjs> start pr-checks -- gh pr checks --watch
5493
5493
  \`\`\`
5494
5494
 
5495
5495
  On miss, fix, commit, push, and watch again until the goal is met or you are blocked. Do not ask the human to poll. Do not merge unless asked.
@@ -5755,19 +5755,26 @@ import { join as join15 } from "path";
5755
5755
  import { existsSync as existsSync15 } from "fs";
5756
5756
  import { dirname as dirname5, join as join14 } from "path";
5757
5757
  import { fileURLToPath } from "url";
5758
+ var DETACHED_JOB_FILENAMES = ["detached-job.cjs", "detached-job.js"];
5759
+ function detachedJobScriptIn(dir) {
5760
+ for (const name of DETACHED_JOB_FILENAMES) {
5761
+ const script = join14(dir, "scripts", name);
5762
+ if (existsSync15(script)) return script;
5763
+ }
5764
+ return null;
5765
+ }
5758
5766
  function packagedDetachedJobPath() {
5759
5767
  const dir = packagedMcpDir();
5760
5768
  if (!dir) return null;
5761
- const script = join14(dir, "scripts", "detached-job.js");
5762
- return existsSync15(script) ? script : null;
5769
+ return detachedJobScriptIn(dir);
5763
5770
  }
5764
5771
  function resolveDetachedJobScript() {
5765
5772
  const packaged = packagedDetachedJobPath();
5766
5773
  if (packaged) return packaged;
5767
5774
  let dir = dirname5(fileURLToPath(import.meta.url));
5768
5775
  for (let i = 0; i < 8; i++) {
5769
- const candidate = join14(dir, "scripts", "detached-job.js");
5770
- if (existsSync15(candidate)) return candidate;
5776
+ const candidate = detachedJobScriptIn(dir);
5777
+ if (candidate) return candidate;
5771
5778
  const parent = dirname5(dir);
5772
5779
  if (parent === dir) break;
5773
5780
  dir = parent;
@@ -5777,7 +5784,7 @@ function resolveDetachedJobScript() {
5777
5784
  function formatDetachedJobInvoke(scriptPath) {
5778
5785
  const resolved = scriptPath === void 0 ? resolveDetachedJobScript() : scriptPath;
5779
5786
  if (resolved) return `node ${JSON.stringify(resolved)}`;
5780
- return "node scripts/detached-job.js";
5787
+ return "node scripts/detached-job.cjs";
5781
5788
  }
5782
5789
 
5783
5790
  // src/agents/instructions.ts
@@ -5993,7 +6000,7 @@ function formatLongRunningDirective(opts) {
5993
6000
  return [
5994
6001
  "Long-running jobs (mandatory when a command may run more than ~30s):",
5995
6002
  "A Sideboard worktree turn SIGTERMs the agent shell (and its process group) when the user sends another message or the turn is interrupted. `block_until_ms: 0` is not enough. Do not ask the human to poll.",
5996
- `Helper (same tool as \`scripts/detached-job.js\` when that file exists in the worktree): \`${invoke}\``,
6003
+ `Helper (same tool as \`scripts/detached-job.cjs\` when that file exists in the worktree): \`${invoke}\``,
5997
6004
  `- Start once: \`${invoke} start <id> -- <command> [args...]\` (cwd = this worktree). If JSON says already-running, do not start again.`,
5998
6005
  "- Immediately `present_artifact` `type=log` with `artifact_id=<id>` and `status=running` \u2014 the side column is the live view.",
5999
6006
  `- Loop Sideboard MCP \`wait_for_job\` with the same id (returns in ~45s). stillRunning \u2192 present the same id with \`content=delta\` only \u2192 wait_for_job again. Shell fallback: \`${invoke} wait <id>\`. Do not resend the full log or HTML.`,
@@ -6643,7 +6650,7 @@ function formatScheduledPrompt(name, prompt) {
6643
6650
  ${prompt}`;
6644
6651
  }
6645
6652
  async function defaultDeps() {
6646
- const { getOrchestrator: getOrchestrator2, startOrchestration: startOrchestration2 } = await import("./orchestrator-VIMO2DP2.js");
6653
+ const { getOrchestrator: getOrchestrator2, startOrchestration: startOrchestration2 } = await import("./orchestrator-IIME6KXQ.js");
6647
6654
  const orch = getOrchestrator2();
6648
6655
  return {
6649
6656
  findThread: (id) => findThreadByRef(id),
package/dist/index.cjs CHANGED
@@ -15508,7 +15508,7 @@ function formatJobStillRunningContinuePrompt(jobIds) {
15508
15508
  function formatDeferredDoneContinuePrompt() {
15509
15509
  return [
15510
15510
  "You ended the turn after promising to report later, but no detached job is running.",
15511
- "If tests/pack/deploy still need to run: start once with detached-job.js, present_artifact type=log, then loop wait_for_job until stillRunning is false.",
15511
+ "If tests/pack/deploy still need to run: start once with detached-job.cjs, present_artifact type=log, then loop wait_for_job until stillRunning is false.",
15512
15512
  "Do not say you will let the user know later."
15513
15513
  ].join(" ");
15514
15514
  }
@@ -15517,7 +15517,7 @@ function turnWatchedDetachedJob(parts) {
15517
15517
  if (p.type !== "tool") return false;
15518
15518
  if (/wait_for_job$/i.test(p.name ?? "") || /stop_job$/i.test(p.name ?? "")) return true;
15519
15519
  const blob = [p.name, p.detail, p.description, p.input ? JSON.stringify(p.input) : ""].filter(Boolean).join(" ");
15520
- return /detached-job\.js\b/i.test(blob);
15520
+ return /detached-job\.(?:js|cjs)\b/i.test(blob);
15521
15521
  });
15522
15522
  }
15523
15523
  function planJobContinue(opts) {
@@ -15610,7 +15610,7 @@ async function waitForDetachedJob(cwd, id, opts) {
15610
15610
  id: jobId,
15611
15611
  delta: "",
15612
15612
  progress: "No detached job. Start one first.",
15613
- hint: "Start with detached-job.js start <id> -- <command>, then call wait_for_job again."
15613
+ hint: "Start with detached-job.cjs start <id> -- <command>, then call wait_for_job again."
15614
15614
  };
15615
15615
  }
15616
15616
  const deadline = Date.now() + timeoutMs;
@@ -15669,7 +15669,7 @@ async function stopDetachedJob(cwd, id, opts) {
15669
15669
  id: jobId,
15670
15670
  delta: "",
15671
15671
  progress: "No detached job. Start one first.",
15672
- hint: "Start with detached-job.js start <id> -- <command>, then wait_for_job or stop_job.",
15672
+ hint: "Start with detached-job.cjs start <id> -- <command>, then wait_for_job or stop_job.",
15673
15673
  stopped: false,
15674
15674
  reason: "not-found"
15675
15675
  };
@@ -18905,21 +18905,21 @@ Do **not** ask the human to check back. Detach, then **wait** in 45s slices (MCP
18905
18905
 
18906
18906
  ## Tool
18907
18907
 
18908
- Use the helper from the Sideboard playbook \u2014 an absolute \`node "\u2026" start\` path injected each turn. If this worktree has \`scripts/detached-job.js\`, that is the same tool.
18908
+ Use the helper from the Sideboard playbook \u2014 an absolute \`node "\u2026" start\` path injected each turn. If this worktree has \`scripts/detached-job.cjs\`, that is the same tool.
18909
18909
 
18910
18910
  \`\`\`bash
18911
18911
  # Start (exits in ~1s; job survives this turn)
18912
- node <detached-job.js> start <id> -- <command> [args...]
18912
+ node <detached-job.cjs> start <id> -- <command> [args...]
18913
18913
 
18914
18914
  # Wait \u2014 prefer MCP wait_for_job (same 45s / stillRunning contract).
18915
18915
  # Shell fallback:
18916
- node <detached-job.js> wait <id>
18916
+ node <detached-job.cjs> wait <id>
18917
18917
 
18918
18918
  # Block until the process exits (humans / a turn that will not be interrupted)
18919
- node <detached-job.js> wait <id> --until-done
18919
+ node <detached-job.cjs> wait <id> --until-done
18920
18920
 
18921
- node <detached-job.js> stop <id> [--reason TEXT]
18922
- node <detached-job.js> status <id>
18921
+ node <detached-job.cjs> stop <id> [--reason TEXT]
18922
+ node <detached-job.cjs> status <id>
18923
18923
  \`\`\`
18924
18924
 
18925
18925
  \`<id>\` is kebab-case (\`mac-release\`, \`core-test\`, \`fly-deploy\`). State is \`.context/.sideboard/detached-jobs/<id>/\` (local scratch).
@@ -18950,7 +18950,7 @@ After **start**, present once (\`status=running\`, empty or first lines). After
18950
18950
  Ad-hoc pid/log (legacy or another tool\u2019s files):
18951
18951
 
18952
18952
  \`\`\`bash
18953
- node <detached-job.js> wait --pid-file FILE --log-file FILE [--ok-pattern TEXT]
18953
+ node <detached-job.cjs> wait --pid-file FILE --log-file FILE [--ok-pattern TEXT]
18954
18954
  \`\`\`
18955
18955
 
18956
18956
  ## Agent loop
@@ -18959,7 +18959,7 @@ node <detached-job.js> wait --pid-file FILE --log-file FILE [--ok-pattern TEXT]
18959
18959
  2. Immediately \`present_artifact\` \`type=log\` (same \`artifact_id\`, \`status=running\`) \u2014 the human should see **working** in the side column, not a \u201Ccheck back later\u201D message.
18960
18960
  3. Loop \`wait_for_job\` (or shell \`wait\`). After each slice, \`present_artifact\` the same id with \`content=delta\` only.
18961
18961
  4. On \`ok\`, present once more (\`status=ok\`, last \`delta\`) and finish the task. On \`failed\`, fix from the log.
18962
- 5. **Stop** when the job is hanging, buffering forever, watching the wrong thing, or you already have the answer. MCP \`stop_job\` (same id, optional \`reason\`) or \`detached-job.js stop <id>\`. Do **not** stop a pack/test/deploy that is clearly making progress.
18962
+ 5. **Stop** when the job is hanging, buffering forever, watching the wrong thing, or you already have the answer. MCP \`stop_job\` (same id, optional \`reason\`) or \`detached-job.cjs stop <id>\`. Do **not** stop a pack/test/deploy that is clearly making progress.
18963
18963
 
18964
18964
  Never tell the user \u201Csay status when it\u2019s done.\u201D You wait \u2014 unless you decided to stop.
18965
18965
 
@@ -18972,7 +18972,7 @@ Huge \`--json\` / \`--expand\` dumps crash any worktree agent mid-turn (Claude /
18972
18972
  Do **not** watch after every push. If the user gave a goal (Greptile 5/5, CI green, until checks pass), wait the same way:
18973
18973
 
18974
18974
  \`\`\`bash
18975
- node <detached-job.js> start pr-checks -- gh pr checks --watch
18975
+ node <detached-job.cjs> start pr-checks -- gh pr checks --watch
18976
18976
  \`\`\`
18977
18977
 
18978
18978
  On miss, fix, commit, push, and watch again until the goal is met or you are blocked. Do not ask the human to poll. Do not merge unless asked.
@@ -19251,19 +19251,25 @@ var init_expand = __esm({
19251
19251
  });
19252
19252
 
19253
19253
  // src/skills/detached-job-path.ts
19254
+ function detachedJobScriptIn(dir) {
19255
+ for (const name of DETACHED_JOB_FILENAMES) {
19256
+ const script = (0, import_node_path44.join)(dir, "scripts", name);
19257
+ if ((0, import_node_fs47.existsSync)(script)) return script;
19258
+ }
19259
+ return null;
19260
+ }
19254
19261
  function packagedDetachedJobPath() {
19255
19262
  const dir = packagedMcpDir();
19256
19263
  if (!dir) return null;
19257
- const script = (0, import_node_path44.join)(dir, "scripts", "detached-job.js");
19258
- return (0, import_node_fs47.existsSync)(script) ? script : null;
19264
+ return detachedJobScriptIn(dir);
19259
19265
  }
19260
19266
  function resolveDetachedJobScript() {
19261
19267
  const packaged = packagedDetachedJobPath();
19262
19268
  if (packaged) return packaged;
19263
19269
  let dir = (0, import_node_path44.dirname)((0, import_node_url3.fileURLToPath)(import_meta3.url));
19264
19270
  for (let i = 0; i < 8; i++) {
19265
- const candidate = (0, import_node_path44.join)(dir, "scripts", "detached-job.js");
19266
- if ((0, import_node_fs47.existsSync)(candidate)) return candidate;
19271
+ const candidate = detachedJobScriptIn(dir);
19272
+ if (candidate) return candidate;
19267
19273
  const parent = (0, import_node_path44.dirname)(dir);
19268
19274
  if (parent === dir) break;
19269
19275
  dir = parent;
@@ -19273,9 +19279,9 @@ function resolveDetachedJobScript() {
19273
19279
  function formatDetachedJobInvoke(scriptPath) {
19274
19280
  const resolved = scriptPath === void 0 ? resolveDetachedJobScript() : scriptPath;
19275
19281
  if (resolved) return `node ${JSON.stringify(resolved)}`;
19276
- return "node scripts/detached-job.js";
19282
+ return "node scripts/detached-job.cjs";
19277
19283
  }
19278
- var import_node_fs47, import_node_path44, import_node_url3, import_meta3;
19284
+ var import_node_fs47, import_node_path44, import_node_url3, import_meta3, DETACHED_JOB_FILENAMES;
19279
19285
  var init_detached_job_path = __esm({
19280
19286
  "src/skills/detached-job-path.ts"() {
19281
19287
  "use strict";
@@ -19284,6 +19290,7 @@ var init_detached_job_path = __esm({
19284
19290
  import_node_url3 = require("url");
19285
19291
  init_packaged_runtime();
19286
19292
  import_meta3 = {};
19293
+ DETACHED_JOB_FILENAMES = ["detached-job.cjs", "detached-job.js"];
19287
19294
  }
19288
19295
  });
19289
19296
 
@@ -19498,7 +19505,7 @@ function formatLongRunningDirective(opts) {
19498
19505
  return [
19499
19506
  "Long-running jobs (mandatory when a command may run more than ~30s):",
19500
19507
  "A Sideboard worktree turn SIGTERMs the agent shell (and its process group) when the user sends another message or the turn is interrupted. `block_until_ms: 0` is not enough. Do not ask the human to poll.",
19501
- `Helper (same tool as \`scripts/detached-job.js\` when that file exists in the worktree): \`${invoke}\``,
19508
+ `Helper (same tool as \`scripts/detached-job.cjs\` when that file exists in the worktree): \`${invoke}\``,
19502
19509
  `- Start once: \`${invoke} start <id> -- <command> [args...]\` (cwd = this worktree). If JSON says already-running, do not start again.`,
19503
19510
  "- Immediately `present_artifact` `type=log` with `artifact_id=<id>` and `status=running` \u2014 the side column is the live view.",
19504
19511
  `- Loop Sideboard MCP \`wait_for_job\` with the same id (returns in ~45s). stillRunning \u2192 present the same id with \`content=delta\` only \u2192 wait_for_job again. Shell fallback: \`${invoke} wait <id>\`. Do not resend the full log or HTML.`,
@@ -27204,9 +27211,9 @@ async function startMcpServer() {
27204
27211
  );
27205
27212
  server.tool(
27206
27213
  "wait_for_job",
27207
- "Wait on a detached long job (tests, pack, deploy, connector CLI) started with detached-job.js. MCP clients kill tools around 60s, so this returns within 45s. stillRunning is the source of truth \u2014 if true, present_artifact type=log with content=delta (same artifact_id) and call wait_for_job again. If the job is hanging, producing no useful output, or doing the wrong thing, call stop_job instead of looping forever. Do not end the turn or tell the user you will let them know later. If false, ok/failed is the result.",
27214
+ "Wait on a detached long job (tests, pack, deploy, connector CLI) started with detached-job.cjs. MCP clients kill tools around 60s, so this returns within 45s. stillRunning is the source of truth \u2014 if true, present_artifact type=log with content=delta (same artifact_id) and call wait_for_job again. If the job is hanging, producing no useful output, or doing the wrong thing, call stop_job instead of looping forever. Do not end the turn or tell the user you will let them know later. If false, ok/failed is the result.",
27208
27215
  {
27209
- id: import_zod8.z.string().describe("Detached job id (same kebab-case id passed to detached-job.js start)"),
27216
+ id: import_zod8.z.string().describe("Detached job id (same kebab-case id passed to detached-job.cjs start)"),
27210
27217
  timeoutMs: import_zod8.z.number().optional()
27211
27218
  },
27212
27219
  async ({ id, timeoutMs }) => {
@@ -27218,9 +27225,9 @@ async function startMcpServer() {
27218
27225
  );
27219
27226
  server.tool(
27220
27227
  "stop_job",
27221
- "Stop a detached job you started with detached-job.js when it is hanging, producing no useful output, buffering forever, or doing the wrong thing (wrong project, infinite watch, huge dump). Do not stop a pack/test/deploy that is clearly making progress. After stop, present_artifact type=log with status=failed and the last delta, then decide the next step.",
27228
+ "Stop a detached job you started with detached-job.cjs when it is hanging, producing no useful output, buffering forever, or doing the wrong thing (wrong project, infinite watch, huge dump). Do not stop a pack/test/deploy that is clearly making progress. After stop, present_artifact type=log with status=failed and the last delta, then decide the next step.",
27222
27229
  {
27223
- id: import_zod8.z.string().describe("Detached job id (same kebab-case id passed to detached-job.js start)"),
27230
+ id: import_zod8.z.string().describe("Detached job id (same kebab-case id passed to detached-job.cjs start)"),
27224
27231
  reason: import_zod8.z.string().optional().describe("Why you are stopping (hanging, no progress, wrong output, already have the error)")
27225
27232
  },
27226
27233
  async ({ id, reason }) => {
package/dist/index.d.cts CHANGED
@@ -3500,14 +3500,14 @@ declare const BUNDLED_SKILL_PREFIX = "bundled:";
3500
3500
  declare function discoverSkills(worktreePath: string): SkillInfo[];
3501
3501
  declare function readSkillBody(skillPath: string, maxChars?: number): string;
3502
3502
 
3503
- /** Packaged extraResources copy (`Contents/Resources/sideboard-mcp/scripts/detached-job.js`). */
3503
+ /** Packaged extraResources copy (`Contents/Resources/sideboard-mcp/scripts/detached-job.cjs`). */
3504
3504
  declare function packagedDetachedJobPath(): string | null;
3505
3505
  /**
3506
3506
  * Absolute path to the detach helper agents should exec.
3507
3507
  * Packaged app first, then walk up from this module to the repo `scripts/` copy.
3508
3508
  */
3509
3509
  declare function resolveDetachedJobScript(): string | null;
3510
- /** Shell invocation agents can copy (`node "/abs/path/detached-job.js"`). */
3510
+ /** Shell invocation agents can copy (`node "/abs/path/detached-job.cjs"`). */
3511
3511
  declare function formatDetachedJobInvoke(scriptPath?: string | null): string;
3512
3512
 
3513
3513
  /** Sideboard product skill — available in every worktree, not only this repo. */
package/dist/index.d.ts CHANGED
@@ -3500,14 +3500,14 @@ declare const BUNDLED_SKILL_PREFIX = "bundled:";
3500
3500
  declare function discoverSkills(worktreePath: string): SkillInfo[];
3501
3501
  declare function readSkillBody(skillPath: string, maxChars?: number): string;
3502
3502
 
3503
- /** Packaged extraResources copy (`Contents/Resources/sideboard-mcp/scripts/detached-job.js`). */
3503
+ /** Packaged extraResources copy (`Contents/Resources/sideboard-mcp/scripts/detached-job.cjs`). */
3504
3504
  declare function packagedDetachedJobPath(): string | null;
3505
3505
  /**
3506
3506
  * Absolute path to the detach helper agents should exec.
3507
3507
  * Packaged app first, then walk up from this module to the repo `scripts/` copy.
3508
3508
  */
3509
3509
  declare function resolveDetachedJobScript(): string | null;
3510
- /** Shell invocation agents can copy (`node "/abs/path/detached-job.js"`). */
3510
+ /** Shell invocation agents can copy (`node "/abs/path/detached-job.cjs"`). */
3511
3511
  declare function formatDetachedJobInvoke(scriptPath?: string | null): string;
3512
3512
 
3513
3513
  /** Sideboard product skill — available in every worktree, not only this repo. */
package/dist/index.js CHANGED
@@ -237,7 +237,7 @@ import {
237
237
  worktreeCleanupSettings,
238
238
  wrapReviewSkillMarkdown,
239
239
  writeWorktreeFile
240
- } from "./chunk-YZUUFSBL.js";
240
+ } from "./chunk-UVLPL2FJ.js";
241
241
  import {
242
242
  LEGACY_PLAN_FILE_REL,
243
243
  PLAN_FILE_NAME,
@@ -4512,9 +4512,9 @@ async function startMcpServer() {
4512
4512
  );
4513
4513
  server.tool(
4514
4514
  "wait_for_job",
4515
- "Wait on a detached long job (tests, pack, deploy, connector CLI) started with detached-job.js. MCP clients kill tools around 60s, so this returns within 45s. stillRunning is the source of truth \u2014 if true, present_artifact type=log with content=delta (same artifact_id) and call wait_for_job again. If the job is hanging, producing no useful output, or doing the wrong thing, call stop_job instead of looping forever. Do not end the turn or tell the user you will let them know later. If false, ok/failed is the result.",
4515
+ "Wait on a detached long job (tests, pack, deploy, connector CLI) started with detached-job.cjs. MCP clients kill tools around 60s, so this returns within 45s. stillRunning is the source of truth \u2014 if true, present_artifact type=log with content=delta (same artifact_id) and call wait_for_job again. If the job is hanging, producing no useful output, or doing the wrong thing, call stop_job instead of looping forever. Do not end the turn or tell the user you will let them know later. If false, ok/failed is the result.",
4516
4516
  {
4517
- id: z8.string().describe("Detached job id (same kebab-case id passed to detached-job.js start)"),
4517
+ id: z8.string().describe("Detached job id (same kebab-case id passed to detached-job.cjs start)"),
4518
4518
  timeoutMs: z8.number().optional()
4519
4519
  },
4520
4520
  async ({ id, timeoutMs }) => {
@@ -4526,9 +4526,9 @@ async function startMcpServer() {
4526
4526
  );
4527
4527
  server.tool(
4528
4528
  "stop_job",
4529
- "Stop a detached job you started with detached-job.js when it is hanging, producing no useful output, buffering forever, or doing the wrong thing (wrong project, infinite watch, huge dump). Do not stop a pack/test/deploy that is clearly making progress. After stop, present_artifact type=log with status=failed and the last delta, then decide the next step.",
4529
+ "Stop a detached job you started with detached-job.cjs when it is hanging, producing no useful output, buffering forever, or doing the wrong thing (wrong project, infinite watch, huge dump). Do not stop a pack/test/deploy that is clearly making progress. After stop, present_artifact type=log with status=failed and the last delta, then decide the next step.",
4530
4530
  {
4531
- id: z8.string().describe("Detached job id (same kebab-case id passed to detached-job.js start)"),
4531
+ id: z8.string().describe("Detached job id (same kebab-case id passed to detached-job.cjs start)"),
4532
4532
  reason: z8.string().optional().describe("Why you are stopping (hanging, no progress, wrong output, already have the error)")
4533
4533
  },
4534
4534
  async ({ id, reason }) => {
@@ -13860,7 +13860,7 @@ function formatJobStillRunningContinuePrompt(jobIds) {
13860
13860
  function formatDeferredDoneContinuePrompt() {
13861
13861
  return [
13862
13862
  "You ended the turn after promising to report later, but no detached job is running.",
13863
- "If tests/pack/deploy still need to run: start once with detached-job.js, present_artifact type=log, then loop wait_for_job until stillRunning is false.",
13863
+ "If tests/pack/deploy still need to run: start once with detached-job.cjs, present_artifact type=log, then loop wait_for_job until stillRunning is false.",
13864
13864
  "Do not say you will let the user know later."
13865
13865
  ].join(" ");
13866
13866
  }
@@ -13869,7 +13869,7 @@ function turnWatchedDetachedJob(parts) {
13869
13869
  if (p.type !== "tool") return false;
13870
13870
  if (/wait_for_job$/i.test(p.name ?? "") || /stop_job$/i.test(p.name ?? "")) return true;
13871
13871
  const blob = [p.name, p.detail, p.description, p.input ? JSON.stringify(p.input) : ""].filter(Boolean).join(" ");
13872
- return /detached-job\.js\b/i.test(blob);
13872
+ return /detached-job\.(?:js|cjs)\b/i.test(blob);
13873
13873
  });
13874
13874
  }
13875
13875
  function planJobContinue(opts) {
@@ -13962,7 +13962,7 @@ async function waitForDetachedJob(cwd, id, opts) {
13962
13962
  id: jobId,
13963
13963
  delta: "",
13964
13964
  progress: "No detached job. Start one first.",
13965
- hint: "Start with detached-job.js start <id> -- <command>, then call wait_for_job again."
13965
+ hint: "Start with detached-job.cjs start <id> -- <command>, then call wait_for_job again."
13966
13966
  };
13967
13967
  }
13968
13968
  const deadline = Date.now() + timeoutMs;
@@ -14021,7 +14021,7 @@ async function stopDetachedJob(cwd, id, opts) {
14021
14021
  id: jobId,
14022
14022
  delta: "",
14023
14023
  progress: "No detached job. Start one first.",
14024
- hint: "Start with detached-job.js start <id> -- <command>, then wait_for_job or stop_job.",
14024
+ hint: "Start with detached-job.cjs start <id> -- <command>, then wait_for_job or stop_job.",
14025
14025
  stopped: false,
14026
14026
  reason: "not-found"
14027
14027
  };
@@ -17190,21 +17190,21 @@ Do **not** ask the human to check back. Detach, then **wait** in 45s slices (MCP
17190
17190
 
17191
17191
  ## Tool
17192
17192
 
17193
- Use the helper from the Sideboard playbook \u2014 an absolute \`node "\u2026" start\` path injected each turn. If this worktree has \`scripts/detached-job.js\`, that is the same tool.
17193
+ Use the helper from the Sideboard playbook \u2014 an absolute \`node "\u2026" start\` path injected each turn. If this worktree has \`scripts/detached-job.cjs\`, that is the same tool.
17194
17194
 
17195
17195
  \`\`\`bash
17196
17196
  # Start (exits in ~1s; job survives this turn)
17197
- node <detached-job.js> start <id> -- <command> [args...]
17197
+ node <detached-job.cjs> start <id> -- <command> [args...]
17198
17198
 
17199
17199
  # Wait \u2014 prefer MCP wait_for_job (same 45s / stillRunning contract).
17200
17200
  # Shell fallback:
17201
- node <detached-job.js> wait <id>
17201
+ node <detached-job.cjs> wait <id>
17202
17202
 
17203
17203
  # Block until the process exits (humans / a turn that will not be interrupted)
17204
- node <detached-job.js> wait <id> --until-done
17204
+ node <detached-job.cjs> wait <id> --until-done
17205
17205
 
17206
- node <detached-job.js> stop <id> [--reason TEXT]
17207
- node <detached-job.js> status <id>
17206
+ node <detached-job.cjs> stop <id> [--reason TEXT]
17207
+ node <detached-job.cjs> status <id>
17208
17208
  \`\`\`
17209
17209
 
17210
17210
  \`<id>\` is kebab-case (\`mac-release\`, \`core-test\`, \`fly-deploy\`). State is \`.context/.sideboard/detached-jobs/<id>/\` (local scratch).
@@ -17235,7 +17235,7 @@ After **start**, present once (\`status=running\`, empty or first lines). After
17235
17235
  Ad-hoc pid/log (legacy or another tool\u2019s files):
17236
17236
 
17237
17237
  \`\`\`bash
17238
- node <detached-job.js> wait --pid-file FILE --log-file FILE [--ok-pattern TEXT]
17238
+ node <detached-job.cjs> wait --pid-file FILE --log-file FILE [--ok-pattern TEXT]
17239
17239
  \`\`\`
17240
17240
 
17241
17241
  ## Agent loop
@@ -17244,7 +17244,7 @@ node <detached-job.js> wait --pid-file FILE --log-file FILE [--ok-pattern TEXT]
17244
17244
  2. Immediately \`present_artifact\` \`type=log\` (same \`artifact_id\`, \`status=running\`) \u2014 the human should see **working** in the side column, not a \u201Ccheck back later\u201D message.
17245
17245
  3. Loop \`wait_for_job\` (or shell \`wait\`). After each slice, \`present_artifact\` the same id with \`content=delta\` only.
17246
17246
  4. On \`ok\`, present once more (\`status=ok\`, last \`delta\`) and finish the task. On \`failed\`, fix from the log.
17247
- 5. **Stop** when the job is hanging, buffering forever, watching the wrong thing, or you already have the answer. MCP \`stop_job\` (same id, optional \`reason\`) or \`detached-job.js stop <id>\`. Do **not** stop a pack/test/deploy that is clearly making progress.
17247
+ 5. **Stop** when the job is hanging, buffering forever, watching the wrong thing, or you already have the answer. MCP \`stop_job\` (same id, optional \`reason\`) or \`detached-job.cjs stop <id>\`. Do **not** stop a pack/test/deploy that is clearly making progress.
17248
17248
 
17249
17249
  Never tell the user \u201Csay status when it\u2019s done.\u201D You wait \u2014 unless you decided to stop.
17250
17250
 
@@ -17257,7 +17257,7 @@ Huge \`--json\` / \`--expand\` dumps crash any worktree agent mid-turn (Claude /
17257
17257
  Do **not** watch after every push. If the user gave a goal (Greptile 5/5, CI green, until checks pass), wait the same way:
17258
17258
 
17259
17259
  \`\`\`bash
17260
- node <detached-job.js> start pr-checks -- gh pr checks --watch
17260
+ node <detached-job.cjs> start pr-checks -- gh pr checks --watch
17261
17261
  \`\`\`
17262
17262
 
17263
17263
  On miss, fix, commit, push, and watch again until the goal is met or you are blocked. Do not ask the human to poll. Do not merge unless asked.
@@ -17536,19 +17536,25 @@ var init_expand = __esm({
17536
17536
  });
17537
17537
 
17538
17538
  // src/skills/detached-job-path.ts
17539
+ function detachedJobScriptIn(dir) {
17540
+ for (const name of DETACHED_JOB_FILENAMES) {
17541
+ const script = (0, import_node_path42.join)(dir, "scripts", name);
17542
+ if ((0, import_node_fs45.existsSync)(script)) return script;
17543
+ }
17544
+ return null;
17545
+ }
17539
17546
  function packagedDetachedJobPath() {
17540
17547
  const dir = packagedMcpDir();
17541
17548
  if (!dir) return null;
17542
- const script = (0, import_node_path42.join)(dir, "scripts", "detached-job.js");
17543
- return (0, import_node_fs45.existsSync)(script) ? script : null;
17549
+ return detachedJobScriptIn(dir);
17544
17550
  }
17545
17551
  function resolveDetachedJobScript() {
17546
17552
  const packaged = packagedDetachedJobPath();
17547
17553
  if (packaged) return packaged;
17548
17554
  let dir = (0, import_node_path42.dirname)((0, import_node_url3.fileURLToPath)(import_meta3.url));
17549
17555
  for (let i = 0; i < 8; i++) {
17550
- const candidate = (0, import_node_path42.join)(dir, "scripts", "detached-job.js");
17551
- if ((0, import_node_fs45.existsSync)(candidate)) return candidate;
17556
+ const candidate = detachedJobScriptIn(dir);
17557
+ if (candidate) return candidate;
17552
17558
  const parent = (0, import_node_path42.dirname)(dir);
17553
17559
  if (parent === dir) break;
17554
17560
  dir = parent;
@@ -17558,9 +17564,9 @@ function resolveDetachedJobScript() {
17558
17564
  function formatDetachedJobInvoke(scriptPath) {
17559
17565
  const resolved = scriptPath === void 0 ? resolveDetachedJobScript() : scriptPath;
17560
17566
  if (resolved) return `node ${JSON.stringify(resolved)}`;
17561
- return "node scripts/detached-job.js";
17567
+ return "node scripts/detached-job.cjs";
17562
17568
  }
17563
- var import_node_fs45, import_node_path42, import_node_url3, import_meta3;
17569
+ var import_node_fs45, import_node_path42, import_node_url3, import_meta3, DETACHED_JOB_FILENAMES;
17564
17570
  var init_detached_job_path = __esm({
17565
17571
  "src/skills/detached-job-path.ts"() {
17566
17572
  "use strict";
@@ -17569,6 +17575,7 @@ var init_detached_job_path = __esm({
17569
17575
  import_node_url3 = require("url");
17570
17576
  init_packaged_runtime();
17571
17577
  import_meta3 = {};
17578
+ DETACHED_JOB_FILENAMES = ["detached-job.cjs", "detached-job.js"];
17572
17579
  }
17573
17580
  });
17574
17581
 
@@ -17761,7 +17768,7 @@ function formatLongRunningDirective(opts) {
17761
17768
  return [
17762
17769
  "Long-running jobs (mandatory when a command may run more than ~30s):",
17763
17770
  "A Sideboard worktree turn SIGTERMs the agent shell (and its process group) when the user sends another message or the turn is interrupted. `block_until_ms: 0` is not enough. Do not ask the human to poll.",
17764
- `Helper (same tool as \`scripts/detached-job.js\` when that file exists in the worktree): \`${invoke}\``,
17771
+ `Helper (same tool as \`scripts/detached-job.cjs\` when that file exists in the worktree): \`${invoke}\``,
17765
17772
  `- Start once: \`${invoke} start <id> -- <command> [args...]\` (cwd = this worktree). If JSON says already-running, do not start again.`,
17766
17773
  "- Immediately `present_artifact` `type=log` with `artifact_id=<id>` and `status=running` \u2014 the side column is the live view.",
17767
17774
  `- Loop Sideboard MCP \`wait_for_job\` with the same id (returns in ~45s). stillRunning \u2192 present the same id with \`content=delta\` only \u2192 wait_for_job again. Shell fallback: \`${invoke} wait <id>\`. Do not resend the full log or HTML.`,
@@ -24178,9 +24185,9 @@ async function startMcpServer() {
24178
24185
  );
24179
24186
  server.tool(
24180
24187
  "wait_for_job",
24181
- "Wait on a detached long job (tests, pack, deploy, connector CLI) started with detached-job.js. MCP clients kill tools around 60s, so this returns within 45s. stillRunning is the source of truth \u2014 if true, present_artifact type=log with content=delta (same artifact_id) and call wait_for_job again. If the job is hanging, producing no useful output, or doing the wrong thing, call stop_job instead of looping forever. Do not end the turn or tell the user you will let them know later. If false, ok/failed is the result.",
24188
+ "Wait on a detached long job (tests, pack, deploy, connector CLI) started with detached-job.cjs. MCP clients kill tools around 60s, so this returns within 45s. stillRunning is the source of truth \u2014 if true, present_artifact type=log with content=delta (same artifact_id) and call wait_for_job again. If the job is hanging, producing no useful output, or doing the wrong thing, call stop_job instead of looping forever. Do not end the turn or tell the user you will let them know later. If false, ok/failed is the result.",
24182
24189
  {
24183
- id: import_zod8.z.string().describe("Detached job id (same kebab-case id passed to detached-job.js start)"),
24190
+ id: import_zod8.z.string().describe("Detached job id (same kebab-case id passed to detached-job.cjs start)"),
24184
24191
  timeoutMs: import_zod8.z.number().optional()
24185
24192
  },
24186
24193
  async ({ id, timeoutMs }) => {
@@ -24192,9 +24199,9 @@ async function startMcpServer() {
24192
24199
  );
24193
24200
  server.tool(
24194
24201
  "stop_job",
24195
- "Stop a detached job you started with detached-job.js when it is hanging, producing no useful output, buffering forever, or doing the wrong thing (wrong project, infinite watch, huge dump). Do not stop a pack/test/deploy that is clearly making progress. After stop, present_artifact type=log with status=failed and the last delta, then decide the next step.",
24202
+ "Stop a detached job you started with detached-job.cjs when it is hanging, producing no useful output, buffering forever, or doing the wrong thing (wrong project, infinite watch, huge dump). Do not stop a pack/test/deploy that is clearly making progress. After stop, present_artifact type=log with status=failed and the last delta, then decide the next step.",
24196
24203
  {
24197
- id: import_zod8.z.string().describe("Detached job id (same kebab-case id passed to detached-job.js start)"),
24204
+ id: import_zod8.z.string().describe("Detached job id (same kebab-case id passed to detached-job.cjs start)"),
24198
24205
  reason: import_zod8.z.string().optional().describe("Why you are stopping (hanging, no progress, wrong output, already have the error)")
24199
24206
  },
24200
24207
  async ({ id, reason }) => {
@@ -37,7 +37,7 @@ import {
37
37
  syncBoardPins,
38
38
  updateSchedule,
39
39
  waitForDetachedJob
40
- } from "../chunk-IHLRYIPY.js";
40
+ } from "../chunk-NYMFNUT5.js";
41
41
  import {
42
42
  isInternalAgentStatusText,
43
43
  listModelsForAgent,
@@ -3261,9 +3261,9 @@ async function startMcpServer() {
3261
3261
  );
3262
3262
  server.tool(
3263
3263
  "wait_for_job",
3264
- "Wait on a detached long job (tests, pack, deploy, connector CLI) started with detached-job.js. MCP clients kill tools around 60s, so this returns within 45s. stillRunning is the source of truth \u2014 if true, present_artifact type=log with content=delta (same artifact_id) and call wait_for_job again. If the job is hanging, producing no useful output, or doing the wrong thing, call stop_job instead of looping forever. Do not end the turn or tell the user you will let them know later. If false, ok/failed is the result.",
3264
+ "Wait on a detached long job (tests, pack, deploy, connector CLI) started with detached-job.cjs. MCP clients kill tools around 60s, so this returns within 45s. stillRunning is the source of truth \u2014 if true, present_artifact type=log with content=delta (same artifact_id) and call wait_for_job again. If the job is hanging, producing no useful output, or doing the wrong thing, call stop_job instead of looping forever. Do not end the turn or tell the user you will let them know later. If false, ok/failed is the result.",
3265
3265
  {
3266
- id: z8.string().describe("Detached job id (same kebab-case id passed to detached-job.js start)"),
3266
+ id: z8.string().describe("Detached job id (same kebab-case id passed to detached-job.cjs start)"),
3267
3267
  timeoutMs: z8.number().optional()
3268
3268
  },
3269
3269
  async ({ id, timeoutMs }) => {
@@ -3275,9 +3275,9 @@ async function startMcpServer() {
3275
3275
  );
3276
3276
  server.tool(
3277
3277
  "stop_job",
3278
- "Stop a detached job you started with detached-job.js when it is hanging, producing no useful output, buffering forever, or doing the wrong thing (wrong project, infinite watch, huge dump). Do not stop a pack/test/deploy that is clearly making progress. After stop, present_artifact type=log with status=failed and the last delta, then decide the next step.",
3278
+ "Stop a detached job you started with detached-job.cjs when it is hanging, producing no useful output, buffering forever, or doing the wrong thing (wrong project, infinite watch, huge dump). Do not stop a pack/test/deploy that is clearly making progress. After stop, present_artifact type=log with status=failed and the last delta, then decide the next step.",
3279
3279
  {
3280
- id: z8.string().describe("Detached job id (same kebab-case id passed to detached-job.js start)"),
3280
+ id: z8.string().describe("Detached job id (same kebab-case id passed to detached-job.cjs start)"),
3281
3281
  reason: z8.string().optional().describe("Why you are stopping (hanging, no progress, wrong output, already have the error)")
3282
3282
  },
3283
3283
  async ({ id, reason }) => {
@@ -5,7 +5,7 @@ import {
5
5
  isPidAlive,
6
6
  startOrchestration,
7
7
  waitForPidExit
8
- } from "./chunk-YZUUFSBL.js";
8
+ } from "./chunk-UVLPL2FJ.js";
9
9
  import "./chunk-DJU54RYW.js";
10
10
  import "./chunk-UIR4VDYA.js";
11
11
  import "./chunk-HSGSQA42.js";
@@ -7,7 +7,7 @@ import {
7
7
  isPidAlive,
8
8
  startOrchestration,
9
9
  waitForPidExit
10
- } from "./chunk-IHLRYIPY.js";
10
+ } from "./chunk-NYMFNUT5.js";
11
11
  import "./chunk-3A54S244.js";
12
12
  import "./chunk-LZ6QMEQC.js";
13
13
  import "./chunk-S42XV45P.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sideboard-ai/core",
3
- "version": "0.1.167",
3
+ "version": "0.1.168",
4
4
  "description": "Sideboard core — orchestration, agents, git worktrees, MCP server",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",