@sideboard-ai/core 0.1.185 → 0.1.186

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.
@@ -402,7 +402,7 @@ async function continueSourceThread(threadId, prompt) {
402
402
  await continueOnReply(threadId, prompt);
403
403
  return;
404
404
  }
405
- const { getOrchestrator: getOrchestrator2 } = await import("./orchestrator-45PPV2LQ.js");
405
+ const { getOrchestrator: getOrchestrator2 } = await import("./orchestrator-RJEULR5I.js");
406
406
  await getOrchestrator2().send(threadId, prompt);
407
407
  } catch {
408
408
  }
@@ -2675,8 +2675,8 @@ function mcpWaitFinishedHint(status) {
2675
2675
 
2676
2676
  // src/mcp/wait-for-job.ts
2677
2677
  var MAX_JOB_CONTINUES = 8;
2678
- var MCP_WAIT_JOB_STILL_RUNNING_HINT = "Job is still running. present_artifact type=log with the same artifact_id and content=delta (new lines only). Then call wait_for_job again. If it is hanging, producing no useful output, or doing the wrong thing, call stop_job (same id) instead of looping forever. Do not end the turn or tell the user you will let them know later.";
2679
- var MCP_STOP_JOB_HINT = "Stopped. present_artifact type=log with status=failed and the last delta. Do not wait again unless you start a new command.";
2678
+ var MCP_WAIT_JOB_STILL_RUNNING_HINT = "Job is still running. The type=log pane already appended this delta. Call wait_for_job again. If it is hanging, producing no useful output, or doing the wrong thing, call stop_job (same id) instead of looping forever. Do not end the turn or tell the user you will let them know later.";
2679
+ var MCP_STOP_JOB_HINT = "Stopped. The type=log pane is status=failed with the last delta. Do not wait again unless you start a new command.";
2680
2680
  var JOB_ID_RE = /^[a-zA-Z0-9._-]{1,64}$/;
2681
2681
  function mcpWaitForJobTimeoutMs(requested) {
2682
2682
  return mcpWaitForTurnTimeoutMs(requested);
@@ -2755,7 +2755,7 @@ function formatJobStillRunningContinuePrompt(jobIds) {
2755
2755
  const ids = jobIds.join(", ");
2756
2756
  return [
2757
2757
  `Detached job still running: ${ids}.`,
2758
- "Do not end this turn. Loop wait_for_job (same id) and present_artifact type=log with content=delta until stillRunning is false.",
2758
+ "Do not end this turn. Loop wait_for_job (same id) until stillRunning is false. The log pane updates from each wait result.",
2759
2759
  "If the job is hanging or doing the wrong thing, call stop_job (same id) instead of looping forever.",
2760
2760
  "Then report the result. Do not tell the user you will let them know later."
2761
2761
  ].join(" ");
@@ -2763,7 +2763,7 @@ function formatJobStillRunningContinuePrompt(jobIds) {
2763
2763
  function formatDeferredDoneContinuePrompt() {
2764
2764
  return [
2765
2765
  "You ended the turn after promising to report later, but no detached job is running.",
2766
- "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.",
2766
+ "If tests/pack/deploy still need to run: start once with detached-job.cjs, then loop wait_for_job until stillRunning is false (the log pane updates from wait JSON).",
2767
2767
  "Do not say you will let the user know later."
2768
2768
  ].join(" ");
2769
2769
  }
@@ -2798,6 +2798,10 @@ function tailProgress(logFile, maxLines = 12) {
2798
2798
  const lines = readFileSync7(logFile, "utf8").split("\n");
2799
2799
  return lines.slice(-maxLines).join("\n");
2800
2800
  }
2801
+ function lastProgressLine(progress) {
2802
+ const last = progress.split("\n").map((l) => l.trim()).filter((l) => l && l !== "(no log yet)").at(-1);
2803
+ return last ? last.slice(0, 72) : void 0;
2804
+ }
2801
2805
  function readLogLines(file) {
2802
2806
  if (!existsSync9(file)) return [];
2803
2807
  const lines = readFileSync7(file, "utf8").split("\n");
@@ -2834,6 +2838,7 @@ function toResult(id, snap, extra) {
2834
2838
  } catch {
2835
2839
  }
2836
2840
  const status = ok ? "ok" : failed && !stillRunning ? "failed" : stillRunning ? "running" : "idle";
2841
+ const progress = extra?.progress ?? snap.progress;
2837
2842
  return {
2838
2843
  stillRunning,
2839
2844
  ok,
@@ -2842,8 +2847,9 @@ function toResult(id, snap, extra) {
2842
2847
  id,
2843
2848
  pid: snap.pid,
2844
2849
  exitCode: snap.exitCode ?? void 0,
2850
+ phase: lastProgressLine(progress),
2845
2851
  delta,
2846
- progress: extra?.progress ?? snap.progress,
2852
+ progress,
2847
2853
  hint: stillRunning ? MCP_WAIT_JOB_STILL_RUNNING_HINT : void 0
2848
2854
  };
2849
2855
  }
@@ -5490,7 +5496,7 @@ Wait JSON:
5490
5496
 
5491
5497
  ## Sideboard UI (append-only log)
5492
5498
 
5493
- The side column **is** the live view. Use \`present_artifact\` **\`type=log\`** with a stable \`artifact_id\` (the job id). Each call **appends** \u2014 send only \`delta\` from wait JSON, not the full log and not HTML.
5499
+ The side column **is** the live view. \`wait_for_job\` / \`stop_job\` (and shell \`detached-job\` wait JSON) open a \`type=log\` pane automatically (\`artifact_id\` = job id, content = \`delta\`). You may still call \`present_artifact\` **\`type=log\`** for a custom title. Each update **appends** \u2014 send only \`delta\`, not the full log and not HTML.
5494
5500
 
5495
5501
  \`\`\`
5496
5502
  present_artifact
@@ -5502,7 +5508,7 @@ present_artifact
5502
5508
  phase: <wait.phase>
5503
5509
  \`\`\`
5504
5510
 
5505
- After **start**, present once (\`status=running\`, empty or first lines). After **every wait**, present the same id with \`content=delta\`. Do **not** dump the log in chat. Do **not** also fence HTML.
5511
+ After **start**, the first \`wait_for_job\` opens the pane (\`status=running\`). Do **not** dump the log in chat. Do **not** also fence HTML.
5506
5512
 
5507
5513
  Ad-hoc pid/log (legacy or another tool\u2019s files):
5508
5514
 
@@ -5513,8 +5519,8 @@ node <detached-job.cjs> wait --pid-file FILE --log-file FILE [--ok-pattern TEXT]
5513
5519
  ## Agent loop
5514
5520
 
5515
5521
  1. \`start\` once. If JSON says \`already-running\`, do not start again.
5516
- 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.
5517
- 3. Loop \`wait_for_job\` (or shell \`wait\`). After each slice, \`present_artifact\` the same id with \`content=delta\` only.
5522
+ 2. Loop \`wait_for_job\` (or shell \`wait\`). The human should see **working** in the side column from the wait JSON \u2014 do not also dump the log in chat.
5523
+ 3. After each slice, the same log pane appends \`delta\`. Optional: \`present_artifact\` the same id for a custom title.
5518
5524
  4. On \`ok\`, present once more (\`status=ok\`, last \`delta\`) and finish the task. On \`failed\`, fix from the log.
5519
5525
  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.
5520
5526
 
@@ -5999,7 +6005,7 @@ function formatLongRunningDirective(opts) {
5999
6005
  "Long-running jobs (mandatory when a command may run more than ~30s \u2014 pack, test, deploy, `gh pr checks --watch`):",
6000
6006
  "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. Detach instead, and never ask the human to poll.",
6001
6007
  `- Start once: \`${invoke} start <id> -- <command> [args...]\` (cwd = this worktree; same tool as \`scripts/detached-job.cjs\` when the worktree has it). If JSON says already-running, do not start again.`,
6002
- "- Immediately `present_artifact` `type=log` with `artifact_id=<id>` and `status=running`, then loop Sideboard MCP `wait_for_job` (returns in ~45s). stillRunning \u2192 present the same id with `content=delta` only \u2192 wait again. Shell fallback: the same helper with `wait <id>`.",
6008
+ "- Loop Sideboard MCP `wait_for_job` (returns in ~45s). The desktop opens a `type=log` pane from wait/stop (and shell detached-job JSON) automatically \u2014 you may still `present_artifact` with `artifact_id=<id>` for a custom title. stillRunning \u2192 wait again. Shell fallback: the same helper with `wait <id>`.",
6003
6009
  "- Hanging, no useful output, or the wrong thing \u2192 `stop_job` (or the helper with `stop <id>`). Do not stop a pack/test/deploy that is clearly making progress.",
6004
6010
  "- Stay in the loop until stillRunning is false (or you stopped it). ok \u2192 finish the task. failed / stopped \u2192 read the log, fix or narrow the command, start once.",
6005
6011
  "State: `.context/.sideboard/detached-jobs/<id>/` (local scratch). Full guide: `/long-running` (always available)."
@@ -6007,7 +6013,7 @@ function formatLongRunningDirective(opts) {
6007
6013
  }
6008
6014
  function formatLongRunningReminder(opts) {
6009
6015
  const invoke = formatDetachedJobInvoke(opts?.scriptPath);
6010
- return `Long jobs: \`${invoke} start <id> -- <cmd>\`, loop wait_for_job (or detached-job wait), present_artifact type=log (delta). stop_job if hanging or wrong. Do not say you will let the user know later \u2014 stay in the turn.`;
6016
+ return `Long jobs: \`${invoke} start <id> -- <cmd>\`, loop wait_for_job (or detached-job wait). The log pane updates from wait JSON; present_artifact type=log is optional. stop_job if hanging or wrong. Do not say you will let the user know later \u2014 stay in the turn.`;
6011
6017
  }
6012
6018
  function formatArtifactDirective() {
6013
6019
  return [
@@ -6419,7 +6425,7 @@ function formatScheduledPrompt(name, prompt) {
6419
6425
  ${prompt}`;
6420
6426
  }
6421
6427
  async function defaultDeps() {
6422
- const { getOrchestrator: getOrchestrator2, startOrchestration: startOrchestration2 } = await import("./orchestrator-45PPV2LQ.js");
6428
+ const { getOrchestrator: getOrchestrator2, startOrchestration: startOrchestration2 } = await import("./orchestrator-RJEULR5I.js");
6423
6429
  const orch = getOrchestrator2();
6424
6430
  return {
6425
6431
  findThread: (id) => findThreadByRef(id),
@@ -467,7 +467,7 @@ async function continueSourceThread(threadId, prompt) {
467
467
  await continueOnReply(threadId, prompt);
468
468
  return;
469
469
  }
470
- const { getOrchestrator: getOrchestrator2 } = await import("./orchestrator-SVFF5CLQ.js");
470
+ const { getOrchestrator: getOrchestrator2 } = await import("./orchestrator-RNDMJXAY.js");
471
471
  await getOrchestrator2().send(threadId, prompt);
472
472
  } catch {
473
473
  }
@@ -2762,8 +2762,8 @@ function mcpWaitFinishedHint(status) {
2762
2762
 
2763
2763
  // src/mcp/wait-for-job.ts
2764
2764
  var MAX_JOB_CONTINUES = 8;
2765
- var MCP_WAIT_JOB_STILL_RUNNING_HINT = "Job is still running. present_artifact type=log with the same artifact_id and content=delta (new lines only). Then call wait_for_job again. If it is hanging, producing no useful output, or doing the wrong thing, call stop_job (same id) instead of looping forever. Do not end the turn or tell the user you will let them know later.";
2766
- var MCP_STOP_JOB_HINT = "Stopped. present_artifact type=log with status=failed and the last delta. Do not wait again unless you start a new command.";
2765
+ var MCP_WAIT_JOB_STILL_RUNNING_HINT = "Job is still running. The type=log pane already appended this delta. Call wait_for_job again. If it is hanging, producing no useful output, or doing the wrong thing, call stop_job (same id) instead of looping forever. Do not end the turn or tell the user you will let them know later.";
2766
+ var MCP_STOP_JOB_HINT = "Stopped. The type=log pane is status=failed with the last delta. Do not wait again unless you start a new command.";
2767
2767
  var JOB_ID_RE = /^[a-zA-Z0-9._-]{1,64}$/;
2768
2768
  function mcpWaitForJobTimeoutMs(requested) {
2769
2769
  return mcpWaitForTurnTimeoutMs(requested);
@@ -2842,7 +2842,7 @@ function formatJobStillRunningContinuePrompt(jobIds) {
2842
2842
  const ids = jobIds.join(", ");
2843
2843
  return [
2844
2844
  `Detached job still running: ${ids}.`,
2845
- "Do not end this turn. Loop wait_for_job (same id) and present_artifact type=log with content=delta until stillRunning is false.",
2845
+ "Do not end this turn. Loop wait_for_job (same id) until stillRunning is false. The log pane updates from each wait result.",
2846
2846
  "If the job is hanging or doing the wrong thing, call stop_job (same id) instead of looping forever.",
2847
2847
  "Then report the result. Do not tell the user you will let them know later."
2848
2848
  ].join(" ");
@@ -2850,7 +2850,7 @@ function formatJobStillRunningContinuePrompt(jobIds) {
2850
2850
  function formatDeferredDoneContinuePrompt() {
2851
2851
  return [
2852
2852
  "You ended the turn after promising to report later, but no detached job is running.",
2853
- "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.",
2853
+ "If tests/pack/deploy still need to run: start once with detached-job.cjs, then loop wait_for_job until stillRunning is false (the log pane updates from wait JSON).",
2854
2854
  "Do not say you will let the user know later."
2855
2855
  ].join(" ");
2856
2856
  }
@@ -2885,6 +2885,10 @@ function tailProgress(logFile, maxLines = 12) {
2885
2885
  const lines = readFileSync7(logFile, "utf8").split("\n");
2886
2886
  return lines.slice(-maxLines).join("\n");
2887
2887
  }
2888
+ function lastProgressLine(progress) {
2889
+ const last = progress.split("\n").map((l) => l.trim()).filter((l) => l && l !== "(no log yet)").at(-1);
2890
+ return last ? last.slice(0, 72) : void 0;
2891
+ }
2888
2892
  function readLogLines(file) {
2889
2893
  if (!existsSync9(file)) return [];
2890
2894
  const lines = readFileSync7(file, "utf8").split("\n");
@@ -2921,6 +2925,7 @@ function toResult(id, snap, extra) {
2921
2925
  } catch {
2922
2926
  }
2923
2927
  const status = ok ? "ok" : failed && !stillRunning ? "failed" : stillRunning ? "running" : "idle";
2928
+ const progress = extra?.progress ?? snap.progress;
2924
2929
  return {
2925
2930
  stillRunning,
2926
2931
  ok,
@@ -2929,8 +2934,9 @@ function toResult(id, snap, extra) {
2929
2934
  id,
2930
2935
  pid: snap.pid,
2931
2936
  exitCode: snap.exitCode ?? void 0,
2937
+ phase: lastProgressLine(progress),
2932
2938
  delta,
2933
- progress: extra?.progress ?? snap.progress,
2939
+ progress,
2934
2940
  hint: stillRunning ? MCP_WAIT_JOB_STILL_RUNNING_HINT : void 0
2935
2941
  };
2936
2942
  }
@@ -5644,7 +5650,7 @@ Wait JSON:
5644
5650
 
5645
5651
  ## Sideboard UI (append-only log)
5646
5652
 
5647
- The side column **is** the live view. Use \`present_artifact\` **\`type=log\`** with a stable \`artifact_id\` (the job id). Each call **appends** \u2014 send only \`delta\` from wait JSON, not the full log and not HTML.
5653
+ The side column **is** the live view. \`wait_for_job\` / \`stop_job\` (and shell \`detached-job\` wait JSON) open a \`type=log\` pane automatically (\`artifact_id\` = job id, content = \`delta\`). You may still call \`present_artifact\` **\`type=log\`** for a custom title. Each update **appends** \u2014 send only \`delta\`, not the full log and not HTML.
5648
5654
 
5649
5655
  \`\`\`
5650
5656
  present_artifact
@@ -5656,7 +5662,7 @@ present_artifact
5656
5662
  phase: <wait.phase>
5657
5663
  \`\`\`
5658
5664
 
5659
- After **start**, present once (\`status=running\`, empty or first lines). After **every wait**, present the same id with \`content=delta\`. Do **not** dump the log in chat. Do **not** also fence HTML.
5665
+ After **start**, the first \`wait_for_job\` opens the pane (\`status=running\`). Do **not** dump the log in chat. Do **not** also fence HTML.
5660
5666
 
5661
5667
  Ad-hoc pid/log (legacy or another tool\u2019s files):
5662
5668
 
@@ -5667,8 +5673,8 @@ node <detached-job.cjs> wait --pid-file FILE --log-file FILE [--ok-pattern TEXT]
5667
5673
  ## Agent loop
5668
5674
 
5669
5675
  1. \`start\` once. If JSON says \`already-running\`, do not start again.
5670
- 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.
5671
- 3. Loop \`wait_for_job\` (or shell \`wait\`). After each slice, \`present_artifact\` the same id with \`content=delta\` only.
5676
+ 2. Loop \`wait_for_job\` (or shell \`wait\`). The human should see **working** in the side column from the wait JSON \u2014 do not also dump the log in chat.
5677
+ 3. After each slice, the same log pane appends \`delta\`. Optional: \`present_artifact\` the same id for a custom title.
5672
5678
  4. On \`ok\`, present once more (\`status=ok\`, last \`delta\`) and finish the task. On \`failed\`, fix from the log.
5673
5679
  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.
5674
5680
 
@@ -6175,7 +6181,7 @@ function formatLongRunningDirective(opts) {
6175
6181
  "Long-running jobs (mandatory when a command may run more than ~30s \u2014 pack, test, deploy, `gh pr checks --watch`):",
6176
6182
  "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. Detach instead, and never ask the human to poll.",
6177
6183
  `- Start once: \`${invoke} start <id> -- <command> [args...]\` (cwd = this worktree; same tool as \`scripts/detached-job.cjs\` when the worktree has it). If JSON says already-running, do not start again.`,
6178
- "- Immediately `present_artifact` `type=log` with `artifact_id=<id>` and `status=running`, then loop Sideboard MCP `wait_for_job` (returns in ~45s). stillRunning \u2192 present the same id with `content=delta` only \u2192 wait again. Shell fallback: the same helper with `wait <id>`.",
6184
+ "- Loop Sideboard MCP `wait_for_job` (returns in ~45s). The desktop opens a `type=log` pane from wait/stop (and shell detached-job JSON) automatically \u2014 you may still `present_artifact` with `artifact_id=<id>` for a custom title. stillRunning \u2192 wait again. Shell fallback: the same helper with `wait <id>`.",
6179
6185
  "- Hanging, no useful output, or the wrong thing \u2192 `stop_job` (or the helper with `stop <id>`). Do not stop a pack/test/deploy that is clearly making progress.",
6180
6186
  "- Stay in the loop until stillRunning is false (or you stopped it). ok \u2192 finish the task. failed / stopped \u2192 read the log, fix or narrow the command, start once.",
6181
6187
  "State: `.context/.sideboard/detached-jobs/<id>/` (local scratch). Full guide: `/long-running` (always available)."
@@ -6183,7 +6189,7 @@ function formatLongRunningDirective(opts) {
6183
6189
  }
6184
6190
  function formatLongRunningReminder(opts) {
6185
6191
  const invoke = formatDetachedJobInvoke(opts?.scriptPath);
6186
- return `Long jobs: \`${invoke} start <id> -- <cmd>\`, loop wait_for_job (or detached-job wait), present_artifact type=log (delta). stop_job if hanging or wrong. Do not say you will let the user know later \u2014 stay in the turn.`;
6192
+ return `Long jobs: \`${invoke} start <id> -- <cmd>\`, loop wait_for_job (or detached-job wait). The log pane updates from wait JSON; present_artifact type=log is optional. stop_job if hanging or wrong. Do not say you will let the user know later \u2014 stay in the turn.`;
6187
6193
  }
6188
6194
  function formatArtifactDirective() {
6189
6195
  return [
@@ -6766,7 +6772,7 @@ function formatScheduledPrompt(name, prompt) {
6766
6772
  ${prompt}`;
6767
6773
  }
6768
6774
  async function defaultDeps() {
6769
- const { getOrchestrator: getOrchestrator2, startOrchestration: startOrchestration2 } = await import("./orchestrator-SVFF5CLQ.js");
6775
+ const { getOrchestrator: getOrchestrator2, startOrchestration: startOrchestration2 } = await import("./orchestrator-RNDMJXAY.js");
6770
6776
  const orch = getOrchestrator2();
6771
6777
  return {
6772
6778
  findThread: (id) => findThreadByRef(id),
package/dist/index.cjs CHANGED
@@ -15990,7 +15990,7 @@ function formatJobStillRunningContinuePrompt(jobIds) {
15990
15990
  const ids = jobIds.join(", ");
15991
15991
  return [
15992
15992
  `Detached job still running: ${ids}.`,
15993
- "Do not end this turn. Loop wait_for_job (same id) and present_artifact type=log with content=delta until stillRunning is false.",
15993
+ "Do not end this turn. Loop wait_for_job (same id) until stillRunning is false. The log pane updates from each wait result.",
15994
15994
  "If the job is hanging or doing the wrong thing, call stop_job (same id) instead of looping forever.",
15995
15995
  "Then report the result. Do not tell the user you will let them know later."
15996
15996
  ].join(" ");
@@ -15998,7 +15998,7 @@ function formatJobStillRunningContinuePrompt(jobIds) {
15998
15998
  function formatDeferredDoneContinuePrompt() {
15999
15999
  return [
16000
16000
  "You ended the turn after promising to report later, but no detached job is running.",
16001
- "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.",
16001
+ "If tests/pack/deploy still need to run: start once with detached-job.cjs, then loop wait_for_job until stillRunning is false (the log pane updates from wait JSON).",
16002
16002
  "Do not say you will let the user know later."
16003
16003
  ].join(" ");
16004
16004
  }
@@ -16033,6 +16033,10 @@ function tailProgress(logFile, maxLines = 12) {
16033
16033
  const lines = (0, import_node_fs42.readFileSync)(logFile, "utf8").split("\n");
16034
16034
  return lines.slice(-maxLines).join("\n");
16035
16035
  }
16036
+ function lastProgressLine(progress) {
16037
+ const last = progress.split("\n").map((l) => l.trim()).filter((l) => l && l !== "(no log yet)").at(-1);
16038
+ return last ? last.slice(0, 72) : void 0;
16039
+ }
16036
16040
  function readLogLines(file) {
16037
16041
  if (!(0, import_node_fs42.existsSync)(file)) return [];
16038
16042
  const lines = (0, import_node_fs42.readFileSync)(file, "utf8").split("\n");
@@ -16069,6 +16073,7 @@ function toResult(id, snap, extra) {
16069
16073
  } catch {
16070
16074
  }
16071
16075
  const status = ok ? "ok" : failed && !stillRunning ? "failed" : stillRunning ? "running" : "idle";
16076
+ const progress = extra?.progress ?? snap.progress;
16072
16077
  return {
16073
16078
  stillRunning,
16074
16079
  ok,
@@ -16077,8 +16082,9 @@ function toResult(id, snap, extra) {
16077
16082
  id,
16078
16083
  pid: snap.pid,
16079
16084
  exitCode: snap.exitCode ?? void 0,
16085
+ phase: lastProgressLine(progress),
16080
16086
  delta,
16081
- progress: extra?.progress ?? snap.progress,
16087
+ progress,
16082
16088
  hint: stillRunning ? MCP_WAIT_JOB_STILL_RUNNING_HINT : void 0
16083
16089
  };
16084
16090
  }
@@ -16218,8 +16224,8 @@ var init_wait_for_job = __esm({
16218
16224
  init_workspace_scratch();
16219
16225
  init_wait_for_turn();
16220
16226
  MAX_JOB_CONTINUES = 8;
16221
- MCP_WAIT_JOB_STILL_RUNNING_HINT = "Job is still running. present_artifact type=log with the same artifact_id and content=delta (new lines only). Then call wait_for_job again. If it is hanging, producing no useful output, or doing the wrong thing, call stop_job (same id) instead of looping forever. Do not end the turn or tell the user you will let them know later.";
16222
- MCP_STOP_JOB_HINT = "Stopped. present_artifact type=log with status=failed and the last delta. Do not wait again unless you start a new command.";
16227
+ MCP_WAIT_JOB_STILL_RUNNING_HINT = "Job is still running. The type=log pane already appended this delta. Call wait_for_job again. If it is hanging, producing no useful output, or doing the wrong thing, call stop_job (same id) instead of looping forever. Do not end the turn or tell the user you will let them know later.";
16228
+ MCP_STOP_JOB_HINT = "Stopped. The type=log pane is status=failed with the last delta. Do not wait again unless you start a new command.";
16223
16229
  JOB_ID_RE = /^[a-zA-Z0-9._-]{1,64}$/;
16224
16230
  }
16225
16231
  });
@@ -19472,7 +19478,7 @@ Wait JSON:
19472
19478
 
19473
19479
  ## Sideboard UI (append-only log)
19474
19480
 
19475
- The side column **is** the live view. Use \`present_artifact\` **\`type=log\`** with a stable \`artifact_id\` (the job id). Each call **appends** \u2014 send only \`delta\` from wait JSON, not the full log and not HTML.
19481
+ The side column **is** the live view. \`wait_for_job\` / \`stop_job\` (and shell \`detached-job\` wait JSON) open a \`type=log\` pane automatically (\`artifact_id\` = job id, content = \`delta\`). You may still call \`present_artifact\` **\`type=log\`** for a custom title. Each update **appends** \u2014 send only \`delta\`, not the full log and not HTML.
19476
19482
 
19477
19483
  \`\`\`
19478
19484
  present_artifact
@@ -19484,7 +19490,7 @@ present_artifact
19484
19490
  phase: <wait.phase>
19485
19491
  \`\`\`
19486
19492
 
19487
- After **start**, present once (\`status=running\`, empty or first lines). After **every wait**, present the same id with \`content=delta\`. Do **not** dump the log in chat. Do **not** also fence HTML.
19493
+ After **start**, the first \`wait_for_job\` opens the pane (\`status=running\`). Do **not** dump the log in chat. Do **not** also fence HTML.
19488
19494
 
19489
19495
  Ad-hoc pid/log (legacy or another tool\u2019s files):
19490
19496
 
@@ -19495,8 +19501,8 @@ node <detached-job.cjs> wait --pid-file FILE --log-file FILE [--ok-pattern TEXT]
19495
19501
  ## Agent loop
19496
19502
 
19497
19503
  1. \`start\` once. If JSON says \`already-running\`, do not start again.
19498
- 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.
19499
- 3. Loop \`wait_for_job\` (or shell \`wait\`). After each slice, \`present_artifact\` the same id with \`content=delta\` only.
19504
+ 2. Loop \`wait_for_job\` (or shell \`wait\`). The human should see **working** in the side column from the wait JSON \u2014 do not also dump the log in chat.
19505
+ 3. After each slice, the same log pane appends \`delta\`. Optional: \`present_artifact\` the same id for a custom title.
19500
19506
  4. On \`ok\`, present once more (\`status=ok\`, last \`delta\`) and finish the task. On \`failed\`, fix from the log.
19501
19507
  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.
19502
19508
 
@@ -20024,7 +20030,7 @@ function formatLongRunningDirective(opts) {
20024
20030
  "Long-running jobs (mandatory when a command may run more than ~30s \u2014 pack, test, deploy, `gh pr checks --watch`):",
20025
20031
  "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. Detach instead, and never ask the human to poll.",
20026
20032
  `- Start once: \`${invoke} start <id> -- <command> [args...]\` (cwd = this worktree; same tool as \`scripts/detached-job.cjs\` when the worktree has it). If JSON says already-running, do not start again.`,
20027
- "- Immediately `present_artifact` `type=log` with `artifact_id=<id>` and `status=running`, then loop Sideboard MCP `wait_for_job` (returns in ~45s). stillRunning \u2192 present the same id with `content=delta` only \u2192 wait again. Shell fallback: the same helper with `wait <id>`.",
20033
+ "- Loop Sideboard MCP `wait_for_job` (returns in ~45s). The desktop opens a `type=log` pane from wait/stop (and shell detached-job JSON) automatically \u2014 you may still `present_artifact` with `artifact_id=<id>` for a custom title. stillRunning \u2192 wait again. Shell fallback: the same helper with `wait <id>`.",
20028
20034
  "- Hanging, no useful output, or the wrong thing \u2192 `stop_job` (or the helper with `stop <id>`). Do not stop a pack/test/deploy that is clearly making progress.",
20029
20035
  "- Stay in the loop until stillRunning is false (or you stopped it). ok \u2192 finish the task. failed / stopped \u2192 read the log, fix or narrow the command, start once.",
20030
20036
  "State: `.context/.sideboard/detached-jobs/<id>/` (local scratch). Full guide: `/long-running` (always available)."
@@ -20032,7 +20038,7 @@ function formatLongRunningDirective(opts) {
20032
20038
  }
20033
20039
  function formatLongRunningReminder(opts) {
20034
20040
  const invoke = formatDetachedJobInvoke(opts?.scriptPath);
20035
- return `Long jobs: \`${invoke} start <id> -- <cmd>\`, loop wait_for_job (or detached-job wait), present_artifact type=log (delta). stop_job if hanging or wrong. Do not say you will let the user know later \u2014 stay in the turn.`;
20041
+ return `Long jobs: \`${invoke} start <id> -- <cmd>\`, loop wait_for_job (or detached-job wait). The log pane updates from wait JSON; present_artifact type=log is optional. stop_job if hanging or wrong. Do not say you will let the user know later \u2014 stay in the turn.`;
20036
20042
  }
20037
20043
  function formatArtifactDirective() {
20038
20044
  return [
@@ -28128,7 +28134,7 @@ async function startMcpServer() {
28128
28134
  );
28129
28135
  server.tool(
28130
28136
  "wait_for_job",
28131
- "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.",
28137
+ "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. Sideboard opens a type=log pane from this result (artifact_id = job id, content = delta). stillRunning is the source of truth \u2014 if true, 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.",
28132
28138
  {
28133
28139
  id: import_zod9.z.string().describe("Detached job id (same kebab-case id passed to detached-job.cjs start)"),
28134
28140
  timeoutMs: import_zod9.z.number().optional()
@@ -28142,7 +28148,7 @@ async function startMcpServer() {
28142
28148
  );
28143
28149
  server.tool(
28144
28150
  "stop_job",
28145
- "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.",
28151
+ "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. The type=log pane updates to status=failed with the last delta. Then decide the next step.",
28146
28152
  {
28147
28153
  id: import_zod9.z.string().describe("Detached job id (same kebab-case id passed to detached-job.cjs start)"),
28148
28154
  reason: import_zod9.z.string().optional().describe("Why you are stopping (hanging, no progress, wrong output, already have the error)")
package/dist/index.js CHANGED
@@ -238,7 +238,7 @@ import {
238
238
  worktreeCleanupSettings,
239
239
  wrapReviewSkillMarkdown,
240
240
  writeWorktreeFile
241
- } from "./chunk-G4VAMUCL.js";
241
+ } from "./chunk-VTIVVVEC.js";
242
242
  import {
243
243
  LEGACY_PLAN_FILE_REL,
244
244
  PLAN_FILE_NAME,
@@ -4912,7 +4912,7 @@ async function startMcpServer() {
4912
4912
  );
4913
4913
  server.tool(
4914
4914
  "wait_for_job",
4915
- "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.",
4915
+ "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. Sideboard opens a type=log pane from this result (artifact_id = job id, content = delta). stillRunning is the source of truth \u2014 if true, 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.",
4916
4916
  {
4917
4917
  id: z9.string().describe("Detached job id (same kebab-case id passed to detached-job.cjs start)"),
4918
4918
  timeoutMs: z9.number().optional()
@@ -4926,7 +4926,7 @@ async function startMcpServer() {
4926
4926
  );
4927
4927
  server.tool(
4928
4928
  "stop_job",
4929
- "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.",
4929
+ "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. The type=log pane updates to status=failed with the last delta. Then decide the next step.",
4930
4930
  {
4931
4931
  id: z9.string().describe("Detached job id (same kebab-case id passed to detached-job.cjs start)"),
4932
4932
  reason: z9.string().optional().describe("Why you are stopping (hanging, no progress, wrong output, already have the error)")
@@ -14340,7 +14340,7 @@ function formatJobStillRunningContinuePrompt(jobIds) {
14340
14340
  const ids = jobIds.join(", ");
14341
14341
  return [
14342
14342
  `Detached job still running: ${ids}.`,
14343
- "Do not end this turn. Loop wait_for_job (same id) and present_artifact type=log with content=delta until stillRunning is false.",
14343
+ "Do not end this turn. Loop wait_for_job (same id) until stillRunning is false. The log pane updates from each wait result.",
14344
14344
  "If the job is hanging or doing the wrong thing, call stop_job (same id) instead of looping forever.",
14345
14345
  "Then report the result. Do not tell the user you will let them know later."
14346
14346
  ].join(" ");
@@ -14348,7 +14348,7 @@ function formatJobStillRunningContinuePrompt(jobIds) {
14348
14348
  function formatDeferredDoneContinuePrompt() {
14349
14349
  return [
14350
14350
  "You ended the turn after promising to report later, but no detached job is running.",
14351
- "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.",
14351
+ "If tests/pack/deploy still need to run: start once with detached-job.cjs, then loop wait_for_job until stillRunning is false (the log pane updates from wait JSON).",
14352
14352
  "Do not say you will let the user know later."
14353
14353
  ].join(" ");
14354
14354
  }
@@ -14383,6 +14383,10 @@ function tailProgress(logFile, maxLines = 12) {
14383
14383
  const lines = (0, import_node_fs40.readFileSync)(logFile, "utf8").split("\n");
14384
14384
  return lines.slice(-maxLines).join("\n");
14385
14385
  }
14386
+ function lastProgressLine(progress) {
14387
+ const last = progress.split("\n").map((l) => l.trim()).filter((l) => l && l !== "(no log yet)").at(-1);
14388
+ return last ? last.slice(0, 72) : void 0;
14389
+ }
14386
14390
  function readLogLines(file) {
14387
14391
  if (!(0, import_node_fs40.existsSync)(file)) return [];
14388
14392
  const lines = (0, import_node_fs40.readFileSync)(file, "utf8").split("\n");
@@ -14419,6 +14423,7 @@ function toResult(id, snap, extra) {
14419
14423
  } catch {
14420
14424
  }
14421
14425
  const status = ok ? "ok" : failed && !stillRunning ? "failed" : stillRunning ? "running" : "idle";
14426
+ const progress = extra?.progress ?? snap.progress;
14422
14427
  return {
14423
14428
  stillRunning,
14424
14429
  ok,
@@ -14427,8 +14432,9 @@ function toResult(id, snap, extra) {
14427
14432
  id,
14428
14433
  pid: snap.pid,
14429
14434
  exitCode: snap.exitCode ?? void 0,
14435
+ phase: lastProgressLine(progress),
14430
14436
  delta,
14431
- progress: extra?.progress ?? snap.progress,
14437
+ progress,
14432
14438
  hint: stillRunning ? MCP_WAIT_JOB_STILL_RUNNING_HINT : void 0
14433
14439
  };
14434
14440
  }
@@ -14568,8 +14574,8 @@ var init_wait_for_job = __esm({
14568
14574
  init_workspace_scratch();
14569
14575
  init_wait_for_turn();
14570
14576
  MAX_JOB_CONTINUES = 8;
14571
- MCP_WAIT_JOB_STILL_RUNNING_HINT = "Job is still running. present_artifact type=log with the same artifact_id and content=delta (new lines only). Then call wait_for_job again. If it is hanging, producing no useful output, or doing the wrong thing, call stop_job (same id) instead of looping forever. Do not end the turn or tell the user you will let them know later.";
14572
- MCP_STOP_JOB_HINT = "Stopped. present_artifact type=log with status=failed and the last delta. Do not wait again unless you start a new command.";
14577
+ MCP_WAIT_JOB_STILL_RUNNING_HINT = "Job is still running. The type=log pane already appended this delta. Call wait_for_job again. If it is hanging, producing no useful output, or doing the wrong thing, call stop_job (same id) instead of looping forever. Do not end the turn or tell the user you will let them know later.";
14578
+ MCP_STOP_JOB_HINT = "Stopped. The type=log pane is status=failed with the last delta. Do not wait again unless you start a new command.";
14573
14579
  JOB_ID_RE = /^[a-zA-Z0-9._-]{1,64}$/;
14574
14580
  }
14575
14581
  });
@@ -17755,7 +17761,7 @@ Wait JSON:
17755
17761
 
17756
17762
  ## Sideboard UI (append-only log)
17757
17763
 
17758
- The side column **is** the live view. Use \`present_artifact\` **\`type=log\`** with a stable \`artifact_id\` (the job id). Each call **appends** \u2014 send only \`delta\` from wait JSON, not the full log and not HTML.
17764
+ The side column **is** the live view. \`wait_for_job\` / \`stop_job\` (and shell \`detached-job\` wait JSON) open a \`type=log\` pane automatically (\`artifact_id\` = job id, content = \`delta\`). You may still call \`present_artifact\` **\`type=log\`** for a custom title. Each update **appends** \u2014 send only \`delta\`, not the full log and not HTML.
17759
17765
 
17760
17766
  \`\`\`
17761
17767
  present_artifact
@@ -17767,7 +17773,7 @@ present_artifact
17767
17773
  phase: <wait.phase>
17768
17774
  \`\`\`
17769
17775
 
17770
- After **start**, present once (\`status=running\`, empty or first lines). After **every wait**, present the same id with \`content=delta\`. Do **not** dump the log in chat. Do **not** also fence HTML.
17776
+ After **start**, the first \`wait_for_job\` opens the pane (\`status=running\`). Do **not** dump the log in chat. Do **not** also fence HTML.
17771
17777
 
17772
17778
  Ad-hoc pid/log (legacy or another tool\u2019s files):
17773
17779
 
@@ -17778,8 +17784,8 @@ node <detached-job.cjs> wait --pid-file FILE --log-file FILE [--ok-pattern TEXT]
17778
17784
  ## Agent loop
17779
17785
 
17780
17786
  1. \`start\` once. If JSON says \`already-running\`, do not start again.
17781
- 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.
17782
- 3. Loop \`wait_for_job\` (or shell \`wait\`). After each slice, \`present_artifact\` the same id with \`content=delta\` only.
17787
+ 2. Loop \`wait_for_job\` (or shell \`wait\`). The human should see **working** in the side column from the wait JSON \u2014 do not also dump the log in chat.
17788
+ 3. After each slice, the same log pane appends \`delta\`. Optional: \`present_artifact\` the same id for a custom title.
17783
17789
  4. On \`ok\`, present once more (\`status=ok\`, last \`delta\`) and finish the task. On \`failed\`, fix from the log.
17784
17790
  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.
17785
17791
 
@@ -18285,7 +18291,7 @@ function formatLongRunningDirective(opts) {
18285
18291
  "Long-running jobs (mandatory when a command may run more than ~30s \u2014 pack, test, deploy, `gh pr checks --watch`):",
18286
18292
  "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. Detach instead, and never ask the human to poll.",
18287
18293
  `- Start once: \`${invoke} start <id> -- <command> [args...]\` (cwd = this worktree; same tool as \`scripts/detached-job.cjs\` when the worktree has it). If JSON says already-running, do not start again.`,
18288
- "- Immediately `present_artifact` `type=log` with `artifact_id=<id>` and `status=running`, then loop Sideboard MCP `wait_for_job` (returns in ~45s). stillRunning \u2192 present the same id with `content=delta` only \u2192 wait again. Shell fallback: the same helper with `wait <id>`.",
18294
+ "- Loop Sideboard MCP `wait_for_job` (returns in ~45s). The desktop opens a `type=log` pane from wait/stop (and shell detached-job JSON) automatically \u2014 you may still `present_artifact` with `artifact_id=<id>` for a custom title. stillRunning \u2192 wait again. Shell fallback: the same helper with `wait <id>`.",
18289
18295
  "- Hanging, no useful output, or the wrong thing \u2192 `stop_job` (or the helper with `stop <id>`). Do not stop a pack/test/deploy that is clearly making progress.",
18290
18296
  "- Stay in the loop until stillRunning is false (or you stopped it). ok \u2192 finish the task. failed / stopped \u2192 read the log, fix or narrow the command, start once.",
18291
18297
  "State: `.context/.sideboard/detached-jobs/<id>/` (local scratch). Full guide: `/long-running` (always available)."
@@ -18293,7 +18299,7 @@ function formatLongRunningDirective(opts) {
18293
18299
  }
18294
18300
  function formatLongRunningReminder(opts) {
18295
18301
  const invoke = formatDetachedJobInvoke(opts?.scriptPath);
18296
- return `Long jobs: \`${invoke} start <id> -- <cmd>\`, loop wait_for_job (or detached-job wait), present_artifact type=log (delta). stop_job if hanging or wrong. Do not say you will let the user know later \u2014 stay in the turn.`;
18302
+ return `Long jobs: \`${invoke} start <id> -- <cmd>\`, loop wait_for_job (or detached-job wait). The log pane updates from wait JSON; present_artifact type=log is optional. stop_job if hanging or wrong. Do not say you will let the user know later \u2014 stay in the turn.`;
18297
18303
  }
18298
18304
  function formatArtifactDirective() {
18299
18305
  return [
@@ -25196,7 +25202,7 @@ async function startMcpServer() {
25196
25202
  );
25197
25203
  server.tool(
25198
25204
  "wait_for_job",
25199
- "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.",
25205
+ "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. Sideboard opens a type=log pane from this result (artifact_id = job id, content = delta). stillRunning is the source of truth \u2014 if true, 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.",
25200
25206
  {
25201
25207
  id: import_zod9.z.string().describe("Detached job id (same kebab-case id passed to detached-job.cjs start)"),
25202
25208
  timeoutMs: import_zod9.z.number().optional()
@@ -25210,7 +25216,7 @@ async function startMcpServer() {
25210
25216
  );
25211
25217
  server.tool(
25212
25218
  "stop_job",
25213
- "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.",
25219
+ "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. The type=log pane updates to status=failed with the last delta. Then decide the next step.",
25214
25220
  {
25215
25221
  id: import_zod9.z.string().describe("Detached job id (same kebab-case id passed to detached-job.cjs start)"),
25216
25222
  reason: import_zod9.z.string().optional().describe("Why you are stopping (hanging, no progress, wrong output, already have the error)")
@@ -37,7 +37,7 @@ import {
37
37
  syncBoardPins,
38
38
  updateSchedule,
39
39
  waitForDetachedJob
40
- } from "../chunk-IQC35TVQ.js";
40
+ } from "../chunk-3QTEXR7L.js";
41
41
  import {
42
42
  applySystemCaEnv,
43
43
  isCursorApiKeyConfigured,
@@ -3695,7 +3695,7 @@ async function startMcpServer() {
3695
3695
  );
3696
3696
  server.tool(
3697
3697
  "wait_for_job",
3698
- "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.",
3698
+ "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. Sideboard opens a type=log pane from this result (artifact_id = job id, content = delta). stillRunning is the source of truth \u2014 if true, 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.",
3699
3699
  {
3700
3700
  id: z9.string().describe("Detached job id (same kebab-case id passed to detached-job.cjs start)"),
3701
3701
  timeoutMs: z9.number().optional()
@@ -3709,7 +3709,7 @@ async function startMcpServer() {
3709
3709
  );
3710
3710
  server.tool(
3711
3711
  "stop_job",
3712
- "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.",
3712
+ "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. The type=log pane updates to status=failed with the last delta. Then decide the next step.",
3713
3713
  {
3714
3714
  id: z9.string().describe("Detached job id (same kebab-case id passed to detached-job.cjs start)"),
3715
3715
  reason: z9.string().optional().describe("Why you are stopping (hanging, no progress, wrong output, already have the error)")
@@ -8,7 +8,7 @@ import {
8
8
  resolveSendFollowUp,
9
9
  startOrchestration,
10
10
  waitForPidExit
11
- } from "./chunk-IQC35TVQ.js";
11
+ } from "./chunk-3QTEXR7L.js";
12
12
  import "./chunk-AHV36NL3.js";
13
13
  import "./chunk-HVIEYTUK.js";
14
14
  import "./chunk-Y4MIXGPA.js";
@@ -6,7 +6,7 @@ import {
6
6
  resolveSendFollowUp,
7
7
  startOrchestration,
8
8
  waitForPidExit
9
- } from "./chunk-G4VAMUCL.js";
9
+ } from "./chunk-VTIVVVEC.js";
10
10
  import "./chunk-DJU54RYW.js";
11
11
  import "./chunk-5FTIOINZ.js";
12
12
  import "./chunk-VIODP5PT.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sideboard-ai/core",
3
- "version": "0.1.185",
3
+ "version": "0.1.186",
4
4
  "description": "Sideboard core — orchestration, agents, git worktrees, MCP server",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",