@sideboard-ai/core 0.1.168 → 0.1.170

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/dist/{abletime-BMS53RIZ.js → abletime-ESVTHTFH.js} +2 -2
  2. package/dist/{abletime-AGF54TNA.js → abletime-IC2V7CNB.js} +2 -2
  3. package/dist/{agents-TSO4MB3X.js → agents-GOBVOXFG.js} +9 -9
  4. package/dist/{agents-KWJXZAHB.js → agents-ZCIMZHXZ.js} +9 -9
  5. package/dist/{app-settings-BRLZQA7N.js → app-settings-LF3TS7XS.js} +5 -1
  6. package/dist/{app-settings-JJQDWPEK.js → app-settings-VMOTQORT.js} +5 -1
  7. package/dist/{chunk-74TWOSQP.js → chunk-3C4B52TS.js} +78 -42
  8. package/dist/{chunk-CVZ4KXVP.js → chunk-7IUO67CW.js} +122 -2
  9. package/dist/{chunk-HSGSQA42.js → chunk-DHPZW2EA.js} +8 -34
  10. package/dist/{chunk-KJFFQAMA.js → chunk-DKLGWRWC.js} +1 -1
  11. package/dist/{chunk-NYMFNUT5.js → chunk-GQHVICNT.js} +194 -147
  12. package/dist/{chunk-ILXKJ4ZD.js → chunk-NB7TEKCF.js} +1 -1
  13. package/dist/{chunk-RS756MKF.js → chunk-P2VCMIZU.js} +8 -34
  14. package/dist/{chunk-UIR4VDYA.js → chunk-SAZIRJR4.js} +30 -10
  15. package/dist/{chunk-UVLPL2FJ.js → chunk-TEI72FYD.js} +198 -216
  16. package/dist/{chunk-3A54S244.js → chunk-UDEWGTP6.js} +29 -10
  17. package/dist/{chunk-TW5A2HFY.js → chunk-Y7DJA3UW.js} +78 -42
  18. package/dist/{chunk-LTXS26K5.js → chunk-YMF5WCIA.js} +122 -2
  19. package/dist/{coordinator-prompt-75N74HAO.js → coordinator-prompt-JTDCEU74.js} +3 -3
  20. package/dist/{coordinator-prompt-Y372QRFE.js → coordinator-prompt-RRUU2OYO.js} +3 -3
  21. package/dist/{global-workspace-JNNFVSP7.js → global-workspace-4SI3CRRT.js} +3 -3
  22. package/dist/{global-workspace-TPE4LKVM.js → global-workspace-ZF6EJAM3.js} +3 -3
  23. package/dist/index.cjs +421 -278
  24. package/dist/index.d.cts +135 -37
  25. package/dist/index.d.ts +135 -37
  26. package/dist/index.js +33 -19
  27. package/dist/mcp/run-stdio.cjs +401 -207
  28. package/dist/mcp/run-stdio.js +8 -8
  29. package/dist/{orchestrator-XG3QCMOS.js → orchestrator-LE6L6MJC.js} +5 -5
  30. package/dist/{orchestrator-IIME6KXQ.js → orchestrator-UZSFTDKA.js} +5 -5
  31. package/dist/{workspaces-2IGQNFPL.js → workspaces-A7C3WA54.js} +3 -3
  32. package/dist/{workspaces-BWZSDSGG.js → workspaces-NOC2MWQV.js} +3 -3
  33. package/dist/{worktree-7X7XNSYL.js → worktree-GXO2VDQF.js} +12 -4
  34. package/dist/{worktree-5BFEK6PF.js → worktree-PODE23PD.js} +12 -4
  35. package/package.json +1 -1
@@ -24,13 +24,11 @@ import {
24
24
  stripBrightsyNdjsonNoise,
25
25
  sumUsageList,
26
26
  toolDescription
27
- } from "./chunk-UIR4VDYA.js";
27
+ } from "./chunk-SAZIRJR4.js";
28
28
  import {
29
29
  SLACK_REPLY_FORMATTING,
30
30
  addWorkspace,
31
- assertOrchestratorCapableAgent,
32
31
  attachmentsFromWorktreePaths,
33
- coerceOrchestratorAgent,
34
32
  coordinatorSystemPrompt,
35
33
  coordinatorTurnReminder,
36
34
  createGlobalChat,
@@ -41,7 +39,6 @@ import {
41
39
  isCloudCoordinatorThread,
42
40
  isGlobalRepoPath,
43
41
  isGlobalThread,
44
- isOrchestratorCapableAgent,
45
42
  isOrchestratorThread,
46
43
  isSlackCoordinatorThread,
47
44
  orchestratorSessionPoisonedByBuiltins,
@@ -50,7 +47,7 @@ import {
50
47
  stageAbsolutePathsAsAttachments,
51
48
  stageBuffersAsAttachments,
52
49
  syncWorkspacesFromThreads
53
- } from "./chunk-HSGSQA42.js";
50
+ } from "./chunk-DHPZW2EA.js";
54
51
  import {
55
52
  addPrStackLayer,
56
53
  allocateTeamName,
@@ -95,10 +92,12 @@ import {
95
92
  resolveRepoRoot,
96
93
  takenSlugsFromThread,
97
94
  threadDisplayLabel,
95
+ ticketSlugForBranch,
98
96
  withRepoGitLock,
99
97
  worktreeDisplayLabelForGroup,
100
- worktreeNameFromPath
101
- } from "./chunk-74TWOSQP.js";
98
+ worktreeNameFromPath,
99
+ worktreeSlugForTicket
100
+ } from "./chunk-3C4B52TS.js";
102
101
  import {
103
102
  ATTACHMENTS_DIR,
104
103
  DETACHED_JOBS_DIR,
@@ -127,12 +126,15 @@ import {
127
126
  turnFailChatText
128
127
  } from "./chunk-XXIH6XYR.js";
129
128
  import {
129
+ assertOrchestratorCapableAgent,
130
130
  childEnvWithAppSettings,
131
+ coerceOrchestratorAgent,
131
132
  formatViewerContextDirective,
132
133
  formatViewerContextReminder,
133
134
  getIssueSource,
134
135
  isAbleTimeConnected,
135
136
  isLinearConnected,
137
+ isOrchestratorCapableAgent,
136
138
  isSecureFileEncrypted,
137
139
  loadAppSettings,
138
140
  orchestrationQuotaFallbackAgent,
@@ -140,13 +142,13 @@ import {
140
142
  readSecureJson,
141
143
  resolveEffectiveIssueSource,
142
144
  resolveNewThreadOptions,
143
- resolveThreadDefaults,
145
+ resolveOrchestratorDefaults,
144
146
  resolveVaultKey,
145
147
  resolveViewerProfileForRepo,
146
148
  saveAppSettings,
147
149
  updateAdvancedSettings,
148
150
  writeSecureJson
149
- } from "./chunk-CVZ4KXVP.js";
151
+ } from "./chunk-7IUO67CW.js";
150
152
  import {
151
153
  stripNestedElectronEnv
152
154
  } from "./chunk-4TR3HZFT.js";
@@ -464,7 +466,7 @@ async function continueSourceThread(threadId, prompt) {
464
466
  await continueOnReply(threadId, prompt);
465
467
  return;
466
468
  }
467
- const { getOrchestrator: getOrchestrator2 } = await import("./orchestrator-IIME6KXQ.js");
469
+ const { getOrchestrator: getOrchestrator2 } = await import("./orchestrator-UZSFTDKA.js");
468
470
  await getOrchestrator2().send(threadId, prompt);
469
471
  } catch {
470
472
  }
@@ -746,9 +748,9 @@ async function spawnAgentTurn(thread, input, onEvent) {
746
748
  `Cannot spawn ${thread.agent}: thread ${thread.id} has no worktreePath`
747
749
  );
748
750
  }
749
- const { isGlobalThread: isGlobalThread2 } = await import("./global-workspace-TPE4LKVM.js");
751
+ const { isGlobalThread: isGlobalThread2 } = await import("./global-workspace-ZF6EJAM3.js");
750
752
  if (isGlobalThread2(thread)) {
751
- const { ensureGlobalCoordinatorCwd: ensureGlobalCoordinatorCwd2 } = await import("./coordinator-prompt-75N74HAO.js");
753
+ const { ensureGlobalCoordinatorCwd: ensureGlobalCoordinatorCwd2 } = await import("./coordinator-prompt-JTDCEU74.js");
752
754
  ensureGlobalCoordinatorCwd2(
753
755
  isOrchestratorThread(thread) ? { orchestratorThreadId: thread.id } : void 0
754
756
  );
@@ -959,6 +961,51 @@ function agentGitPrompt(action, opts) {
959
961
  return "Merge PR.";
960
962
  }
961
963
  }
964
+ var RESOLVE_CONFLICTS_RE = /^Merge the remote branch(?: \(([^)]+)\))? into your branch and resolve conflicts\. Then, commit and push your changes\.$/;
965
+ function gitActionExpansion(action, base) {
966
+ switch (action) {
967
+ case "commit-push":
968
+ return "Commit any uncommitted work with a purpose-stating message, then push to origin (`git push -u origin HEAD`; this updates an existing PR when one is linked). Do not start a checks loop unless a goal was given.";
969
+ case "create-draft":
970
+ return "Commit, push, then create a draft PR with `gh pr create --draft -R <origin-owner/name>` (title/body from the change purpose). Update the existing PR instead if one is linked.";
971
+ case "create-web":
972
+ return "Commit, push, then `gh pr create --web -R <origin-owner/name>`.";
973
+ case "resolve-conflicts":
974
+ return `Fetch the PR base${base ? ` (\`${base}\`)` : ""}, merge it into this branch, resolve conflicts carefully, then commit and push until the PR is mergeable.`;
975
+ case "merge":
976
+ return "This phrase is the explicit ask to merge this thread's open pull request on GitHub. If `gh stack view` shows a stack, use `gh stack merge`; otherwise `gh pr merge` (respect repo defaults / squash vs merge). Do not force-push main/master or merge locally into the main checkout.";
977
+ }
978
+ }
979
+ function expandCanonicalGitRequest(prompt) {
980
+ const trimmed = prompt.trim();
981
+ let action = null;
982
+ let base = null;
983
+ for (const candidate of AGENT_GIT_ACTIONS) {
984
+ if (candidate === "resolve-conflicts") continue;
985
+ if (agentGitPrompt(candidate) === trimmed) {
986
+ action = candidate;
987
+ break;
988
+ }
989
+ }
990
+ if (!action) {
991
+ const m = RESOLVE_CONFLICTS_RE.exec(trimmed);
992
+ if (m) {
993
+ action = "resolve-conflicts";
994
+ base = m[1] ?? null;
995
+ }
996
+ }
997
+ let expansion = action ? gitActionExpansion(action, base) : null;
998
+ if (!expansion && trimmed === "Address review comments.") {
999
+ expansion = "Read the PR review feedback (`gh pr view --comments`, `gh api` review comments), make the requested changes, commit, and push.";
1000
+ } else if (!expansion && FIX_CI_RE.test(trimmed)) {
1001
+ expansion = "Investigate that failing check (`gh pr checks`, `gh run view --log-failed`), fix it, commit, and push. Loop only if a goal to keep going until it passes was given.";
1002
+ }
1003
+ if (!expansion) return prompt;
1004
+ return `${trimmed}
1005
+
1006
+ (Sideboard git request \u2014 do not ask for clarification: ${expansion})`;
1007
+ }
1008
+ var FIX_CI_RE = /^Fix CI: .+\.$/;
962
1009
 
963
1010
  // src/git/pr-merge-archive.ts
964
1011
  function normalizePrState(state) {
@@ -1220,47 +1267,84 @@ function formatToolPart(t, detail) {
1220
1267
  }
1221
1268
  function formatMessagesAsTranscript(messages, opts) {
1222
1269
  const tools = opts?.tools ?? "full";
1223
- const blocks = [];
1224
- for (const m of messages) {
1225
- if (m.role === "summary") {
1226
- blocks.push(`## Prior summary
1227
- ${m.text}`);
1228
- continue;
1229
- }
1230
- if (m.role === "user") {
1231
- blocks.push(`### User
1270
+ const thinking = opts?.thinking ?? true;
1271
+ return messages.map((m) => formatMessageBlock(m, { tools, thinking })).join("\n\n");
1272
+ }
1273
+ function formatMessageBlock(m, opts) {
1274
+ if (m.role === "summary") return `## Prior summary
1275
+ ${m.text}`;
1276
+ if (m.role === "user") return `### User
1277
+ ${m.text}`;
1278
+ const bits = [];
1279
+ if (m.text?.trim()) {
1280
+ bits.push(`### Agent
1232
1281
  ${m.text}`);
1233
- continue;
1234
- }
1235
- const bits = [];
1236
- if (m.text?.trim()) {
1237
- bits.push(`### Agent
1238
- ${m.text}`);
1239
- } else {
1240
- bits.push("### Agent");
1241
- }
1242
- const thinking = (m.parts ?? []).filter((p) => p.type === "thinking");
1243
- for (const th of thinking) {
1282
+ } else {
1283
+ bits.push("### Agent");
1284
+ }
1285
+ if (opts.thinking) {
1286
+ for (const th of m.parts ?? []) {
1244
1287
  if (th.type !== "thinking" || !th.text.trim()) continue;
1245
1288
  bits.push("Thinking:");
1246
1289
  bits.push(th.text);
1247
1290
  }
1248
- const toolParts = (m.parts ?? []).filter(
1249
- (p) => p.type === "tool"
1250
- );
1251
- if (tools !== "none" && toolParts.length > 0) {
1252
- if (tools === "summary") bits.push("Tools:");
1253
- for (const t of toolParts) {
1254
- bits.push(formatToolPart(t, tools));
1255
- }
1291
+ }
1292
+ const toolParts = (m.parts ?? []).filter(
1293
+ (p) => p.type === "tool"
1294
+ );
1295
+ if (opts.tools !== "none" && toolParts.length > 0) {
1296
+ if (opts.tools === "summary") bits.push("Tools:");
1297
+ for (const t of toolParts) {
1298
+ bits.push(formatToolPart(t, opts.tools));
1256
1299
  }
1257
- blocks.push(bits.join("\n"));
1258
1300
  }
1259
- return blocks.join("\n\n");
1301
+ return bits.join("\n");
1260
1302
  }
1303
+ var SEED_MAX_CHARS = 6e4;
1304
+ var SEED_FULL_TOOL_MESSAGES = 6;
1261
1305
  function buildSessionSeed(messages, opts) {
1262
1306
  if (messages.length === 0) return null;
1263
- const body = formatMessagesAsTranscript(messages, { tools: opts?.tools ?? "full" });
1307
+ const tools = opts?.tools ?? "full";
1308
+ const fullCount = opts?.fullToolMessages ?? SEED_FULL_TOOL_MESSAGES;
1309
+ const maxChars = opts?.maxChars ?? SEED_MAX_CHARS;
1310
+ const olderTools = tools === "none" ? "none" : "summary";
1311
+ const fullFrom = Math.max(0, messages.length - fullCount);
1312
+ const blocks = messages.map(
1313
+ (m, i) => formatMessageBlock(m, {
1314
+ tools: i >= fullFrom ? tools : olderTools,
1315
+ thinking: false
1316
+ })
1317
+ );
1318
+ const keep = new Array(blocks.length).fill(false);
1319
+ let used = 0;
1320
+ for (let i = 0; i < blocks.length; i++) {
1321
+ if (messages[i].role === "summary") {
1322
+ keep[i] = true;
1323
+ used += blocks[i].length + 2;
1324
+ }
1325
+ }
1326
+ for (let i = blocks.length - 1; i >= 0; i--) {
1327
+ if (keep[i]) continue;
1328
+ const next = used + blocks[i].length + 2;
1329
+ if (next > maxChars && used > 0) break;
1330
+ keep[i] = true;
1331
+ used = next;
1332
+ }
1333
+ const dropped = keep.filter((k) => !k).length;
1334
+ const kept = [];
1335
+ let markerPlaced = false;
1336
+ for (let i = 0; i < blocks.length; i++) {
1337
+ if (!keep[i]) continue;
1338
+ if (dropped > 0 && !markerPlaced && messages[i].role !== "summary") {
1339
+ kept.push(`_(${dropped} older message${dropped === 1 ? "" : "s"} omitted for length)_`);
1340
+ markerPlaced = true;
1341
+ }
1342
+ kept.push(blocks[i]);
1343
+ }
1344
+ if (dropped > 0 && !markerPlaced) {
1345
+ kept.push(`_(${dropped} older message${dropped === 1 ? "" : "s"} omitted for length)_`);
1346
+ }
1347
+ const body = kept.join("\n\n");
1264
1348
  if (!body.trim()) return null;
1265
1349
  return [
1266
1350
  "Sideboard conversation context (restored after compaction or a new session):",
@@ -1319,7 +1403,7 @@ function messagesSinceLastBrightsyContextSummary(messages) {
1319
1403
  function buildBrightsySessionSeed(messages) {
1320
1404
  const match = findLastBrightsyContextSummary(messages);
1321
1405
  const tail = match ? messages.slice(match.index + 1) : messages;
1322
- const body = formatMessagesAsTranscript(tail, { tools: "none" });
1406
+ const body = formatMessagesAsTranscript(tail, { tools: "none", thinking: false });
1323
1407
  if (!match && !body.trim()) return null;
1324
1408
  const blocks = [
1325
1409
  "Sideboard conversation context (restored after compaction or a new session):",
@@ -3486,7 +3570,7 @@ async function createThread(input, _onSetupLine) {
3486
3570
  });
3487
3571
  await requireAgent(resolved.agent);
3488
3572
  if (input.cowboy) {
3489
- const { cowboyModeEnabled } = await import("./app-settings-JJQDWPEK.js");
3573
+ const { cowboyModeEnabled } = await import("./app-settings-VMOTQORT.js");
3490
3574
  if (!cowboyModeEnabled()) {
3491
3575
  throw new Error(
3492
3576
  "Cowboy mode is off. Enable it in Settings \u2192 Advanced."
@@ -3544,7 +3628,7 @@ async function createThread(input, _onSetupLine) {
3544
3628
  let sourceIsFork = false;
3545
3629
  if (!input.cowboy && sourceType === "branch" && (!sourceRef || sourceRef === "HEAD" || sourceRef === "default")) {
3546
3630
  if (isAbleTimeConnected() && getIssueSource() === "abletime") {
3547
- const { ensureAbleTimeTask, issueAttachmentForAbleTimeTask } = await import("./abletime-AGF54TNA.js");
3631
+ const { ensureAbleTimeTask, issueAttachmentForAbleTimeTask } = await import("./abletime-IC2V7CNB.js");
3548
3632
  const task = await ensureAbleTimeTask({
3549
3633
  title: title?.trim() || "Untitled work",
3550
3634
  description: input.prompt?.trim() || void 0
@@ -3608,10 +3692,11 @@ async function createThread(input, _onSetupLine) {
3608
3692
  throw new Error("Use adoptThread() for adopt sources");
3609
3693
  }
3610
3694
  const team = allocateTeamSlug(repoPath);
3695
+ const slug = sourceType === "ticket" ? worktreeSlugForTicket(persistedSourceRef, team.slug) : team.slug;
3611
3696
  const { branchName, worktreePath } = await createThreadWorktree({
3612
3697
  repoPath,
3613
3698
  sourceRef,
3614
- slug: team.slug
3699
+ slug
3615
3700
  });
3616
3701
  copyConfiguredFiles(repoPath, worktreePath);
3617
3702
  const explicitTitle = title?.trim();
@@ -3641,7 +3726,7 @@ async function createThread(input, _onSetupLine) {
3641
3726
  return readThread(thread.id) ?? thread;
3642
3727
  }
3643
3728
  async function listLinearIssues(agent, repoPath) {
3644
- const { getAdapter: getAdapter2 } = await import("./agents-TSO4MB3X.js");
3729
+ const { getAdapter: getAdapter2 } = await import("./agents-GOBVOXFG.js");
3645
3730
  await requireAgent(agent, { requireLinear: true });
3646
3731
  const adapter = getAdapter2(agent);
3647
3732
  if (!adapter.listLinearIssues) {
@@ -4063,7 +4148,7 @@ async function adoptThread(input) {
4063
4148
  messages: input.messages ?? []
4064
4149
  });
4065
4150
  writeThread(thread);
4066
- const { ensureWorkspace: ensureWorkspace2 } = await import("./workspaces-2IGQNFPL.js");
4151
+ const { ensureWorkspace: ensureWorkspace2 } = await import("./workspaces-A7C3WA54.js");
4067
4152
  await ensureWorkspace2(repoPath);
4068
4153
  const { ensureWorktreeSideboardIgnored: ensureWorktreeSideboardIgnored2 } = await import("./worktree-exclude-X54WSOXM.js");
4069
4154
  await ensureWorktreeSideboardIgnored2(input.worktreePath);
@@ -5748,7 +5833,7 @@ function expandComposerPrompt(worktreePath, prompt, opts) {
5748
5833
  }
5749
5834
 
5750
5835
  // src/agents/instructions.ts
5751
- import { existsSync as existsSync16, readFileSync as readFileSync12, statSync as statSync4 } from "fs";
5836
+ import { existsSync as existsSync16 } from "fs";
5752
5837
  import { join as join15 } from "path";
5753
5838
 
5754
5839
  // src/skills/detached-job-path.ts
@@ -5794,12 +5879,17 @@ function normPath(p) {
5794
5879
  function formatRenameBranchDirective(thread, opts) {
5795
5880
  if (!isPlaceholderBranch(thread.branchName, thread.worktreePath)) return null;
5796
5881
  const dir = worktreeNameFromPath(thread.worktreePath);
5882
+ const ticket = thread.sourceType === "ticket" ? ticketSlugForBranch(thread.sourceRef ?? "") : null;
5883
+ const example = ticket ? `\`feat/${ticket}-dark-mode\` or \`fix/${ticket}-panel-width\`` : "`fix/panel-width` or `feat/dark-mode`";
5797
5884
  const lines = [
5798
5885
  "Branch naming (do this early in the turn):",
5799
- `- Current branch \`${thread.branchName}\` is a temporary placeholder. The worktree folder \`${dir}\` is a stable soccer-team nickname \u2014 do not rename or leave that directory.`,
5800
- "- Rename the git branch to a short kebab-case name that describes this task (what you are changing), e.g. `fix/panel-width` or `feat/dark-mode`:",
5886
+ `- Current branch \`${thread.branchName}\` is a temporary placeholder. The worktree folder \`${dir}\` is a stable nickname \u2014 do not rename or leave that directory.`,
5887
+ `- Rename the git branch to a short kebab-case name that describes this task (what you are changing), e.g. ${example}:`,
5801
5888
  " `git branch -m <new-name>`",
5802
5889
  "- Prefer Conventional Commits style prefixes when they fit (`fix/`, `feat/`, `chore/`, `docs/`).",
5890
+ ...ticket ? [
5891
+ `- Keep ticket \`${ticket}\` in the new branch name so the issue stays findable.`
5892
+ ] : [],
5803
5893
  "- Never push this placeholder to main/master."
5804
5894
  ];
5805
5895
  const custom = opts?.customPrompt?.trim();
@@ -5833,67 +5923,38 @@ function formatWorktreeDirective(thread, opts) {
5833
5923
  lines.push(
5834
5924
  "- Always use this worktree's `origin` remote (`git remote get-url origin` from this cwd). Never push to or open PRs against `upstream` (template remotes)."
5835
5925
  );
5836
- lines.push(
5837
- "- Push with `git push -u origin HEAD` (or the current branch name). Do not `git push upstream`."
5838
- );
5839
- lines.push("");
5840
5926
  lines.push(formatGitAuthModeDirective(opts?.gitAuthMode ?? "auto"));
5841
5927
  lines.push(
5842
- "- Derive the PR title and body from what the changes actually do and why \u2014 inspect the diff/commits and the user request. Do not use the soccer-team worktree nickname or placeholder branch as the PR title."
5843
- );
5844
- lines.push(
5845
- "- Prefer a concise imperative title (Conventional Commits style when it fits: feat:/fix:/chore:/docs:). Body should summarize intent, key changes, and test notes."
5928
+ "- PR title/body and commit messages state what the change does and why (inspect the diff/commits and the user request) \u2014 never the worktree nickname or placeholder branch. Concise imperative title (Conventional Commits when it fits: feat:/fix:/chore:/docs:); body = intent, key changes, test notes."
5846
5929
  );
5847
5930
  lines.push(
5848
- "- Commit with messages that state the purpose of the change (same standard as the PR). Stay on this thread branch. Never push directly to main/master or merge locally into the main checkout. Do not merge the PR unless this turn is a Merge PR request or the user explicitly asked. When merging, use GitHub from this worktree (`gh pr merge` / `gh stack merge`)."
5931
+ "- Stay on this thread branch. Never push to main/master or merge locally into the main checkout. Merge the PR only when this turn is a Merge PR request or the user explicitly asked \u2014 via GitHub from this worktree (`gh pr merge` / `gh stack merge`)."
5849
5932
  );
5850
5933
  if (thread.prUrl) {
5851
5934
  lines.push(
5852
5935
  `- A PR already exists (${thread.prUrl}). Update it (push + edit title/body if the purpose drifted) instead of opening a duplicate.`
5853
5936
  );
5854
- } else if (opts?.githubSlug) {
5855
- lines.push(
5856
- `- Prefer a draft PR first: \`gh pr create --draft -R ${opts.githubSlug}\` (or update via \`gh pr edit -R ${opts.githubSlug}\`) once the change set is coherent. Always pass \`-R ${opts.githubSlug}\` (this worktree's origin). Bare \`gh pr create\` may target upstream instead of origin on dual-remote checkouts. Mark ready for review only when asked. Title/body must reflect the change purpose, not the worktree name. If GitHub rejects the GraphQL body as too long, retry with a short \`--body-file\` (limit 65,536 characters) \u2014 do not paste a changelog or diff into \`--body\`.`
5857
- );
5858
5937
  } else {
5938
+ const slug = opts?.githubSlug ?? "<origin-owner/name>";
5939
+ const resolve = opts?.githubSlug ? "" : " Resolve `<origin-owner/name>` with `git remote get-url origin` in this worktree.";
5859
5940
  lines.push(
5860
- "- Prefer a draft PR first: `gh pr create --draft -R <origin-owner/name>` (or update via `gh pr edit -R \u2026`) once the change set is coherent. Resolve `<origin-owner/name>` with `git remote get-url origin` in this worktree \u2014 never from `upstream`. Mark ready for review only when asked. Title/body must reflect the change purpose, not the worktree name. If GitHub rejects the GraphQL body as too long, retry with a short `--body-file` (limit 65,536 characters) \u2014 do not paste a changelog or diff into `--body`."
5941
+ `- Prefer a draft PR first: \`gh pr create --draft -R ${slug}\` (update via \`gh pr edit -R ${slug}\`). Always pass \`-R\` \u2014 bare \`gh pr create\` may target upstream on dual-remote checkouts.${resolve} Mark ready for review only when asked. If GitHub rejects the body as too long, retry with a short \`--body-file\` \u2014 do not paste a changelog or diff into \`--body\`.`
5861
5942
  );
5862
5943
  }
5863
- lines.push("");
5864
- lines.push(
5865
- "Short git requests from the Sideboard UI are complete instructions \u2014 expand them using the rules above without asking for clarification:"
5866
- );
5867
- lines.push(
5868
- '- "Commit and push." \u2192 commit any uncommitted work with a purpose-stating message, then push to origin (updates an existing PR if one is linked). Do not start a checks loop unless they gave a goal.'
5869
- );
5870
- lines.push(
5871
- '- "Commit, push, and open a draft PR." \u2192 commit, push, then create a draft PR with `gh pr create --draft -R \u2026` (title/body from the change purpose).'
5872
- );
5873
- lines.push(
5874
- '- "Commit, push, and open a PR in the browser." \u2192 commit, push, then `gh pr create --web -R \u2026`.'
5875
- );
5876
- lines.push(
5877
- '- "Fix CI: <name>." \u2192 investigate that failing check, fix it, commit, and push. Loop only if they gave a goal to keep going until it passes.'
5878
- );
5879
- lines.push(
5880
- '- "Merge the remote branch (<base>) into your branch and resolve conflicts. Then, commit and push your changes." \u2192 fetch the PR base, merge it into this branch, resolve conflicts carefully, commit, and push until the PR is mergeable.'
5881
- );
5882
5944
  lines.push(
5883
- '- "Address review comments." \u2192 read PR review feedback, make the requested changes, commit, and push.'
5945
+ '- Sideboard git buttons send short phrases ("Commit and push.", "Merge PR.", \u2026) with their meaning attached \u2014 act on them without asking for clarification. If the user gives a goal (Greptile 5/5, CI green, until checks pass), you get the watch-fix-push playbook with that request.'
5884
5946
  );
5885
- lines.push(
5886
- '- "Merge PR." \u2192 merge this thread\'s open pull request on GitHub (this phrase is the explicit ask). If `gh stack view` shows a stack, use `gh stack merge`; otherwise `gh pr merge` (respect repo defaults / squash vs merge). Do not force-push main/master or merge locally into the main checkout.'
5887
- );
5888
- lines.push("");
5889
- lines.push(formatPrGateDirective());
5890
5947
  lines.push("");
5891
- lines.push(formatProcessGuideDirective());
5948
+ lines.push(formatProcessGuideDirective({ worktreePath: thread.worktreePath }));
5892
5949
  return lines.join("\n");
5893
5950
  }
5894
5951
  function formatWorktreeReminder() {
5895
5952
  return "Sideboard worktree: stay in this cwd for all file and git work. Push and open PRs against origin, never upstream. Do not edit the main repo checkout. If a goal is given (Greptile 5/5, CI green), watch-fix-push until it lands \u2014 do not watch after every push.";
5896
5953
  }
5954
+ var PR_GOAL_RE = /greptile|\bci\b.*\b(green|pass)|checks?\s+(pass|green)|until\s+.*\b(pass|green|merge|clean)|\bfix ci\b|watch[- ]fix[- ]push/i;
5955
+ function mentionsPrGoal(prompt) {
5956
+ return PR_GOAL_RE.test(prompt);
5957
+ }
5897
5958
  var GITHUB_TICKET_REF = /^(?:#?\d+|gh-\d+)$/i;
5898
5959
  var KEYED_TICKET_REF = /^(?:[A-Z][A-Z0-9]{0,9}-\d+|[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})$/i;
5899
5960
  function issueTicketFromThread(thread, preferredSource = "github") {
@@ -5984,29 +6045,27 @@ function formatPrGateDirective() {
5984
6045
  "- Greptile 5/5: wait for the greptile check; read the latest `N/5` from the PR body or Greptile\u2019s most recently *updated* issue comment; also fetch unresolved review comments / the \u201CPrompt to fix all with AI\u201D block. Done = **5/5 and zero unresolved Greptile comments**. If Greptile is idle, comment `@greptile review`. Cap about 5 iterations, then report leftovers. Do not merge unless asked."
5985
6046
  ].join("\n");
5986
6047
  }
5987
- function formatProcessGuideDirective() {
6048
+ function formatProcessGuideDirective(opts) {
6049
+ const worktree = opts?.worktreePath?.trim();
6050
+ const hasGraphSkill = !!worktree && existsSync16(join15(worktree, ".claude/skills/graph-engineering/SKILL.md"));
6051
+ const hasReviewSkill = !!worktree && existsSync16(join15(worktree, ".claude/skills/review/SKILL.md"));
5988
6052
  return [
5989
6053
  "Process guides (recurring work only):",
5990
- "- Long jobs (pack, test, deploy, anything that may run more than ~30s): Sideboard always provides `/long-running`. Detach and wait; `stop_job` if hanging or wrong. Do not ask the human to poll.",
5991
- "- If `.claude/skills/graph-engineering/SKILL.md` exists, follow it (`/graph-engineering`) for migrations, ports, batch fixes, and other fan-out. Judge first; state on disk; grow the rulebook; do not patch around it.",
5992
- "- If this same shape of work will happen again, write `.claude/skills/<kebab-name>/SKILL.md` in this worktree (Claude Code project skill). Sideboard `/name`, Claude Code, and `attach` all load that path. Do not leave the method only in chat.",
5993
- "- Merge-readiness notes: if `.claude/skills/review/SKILL.md` already exists, edit it. Otherwise write them to `.context/review.md` (copied from `.sideboard/review.md` when that file exists). Do not create a review skill.",
5994
- "- Do not write new skills under `.sideboard/skills/` (that folder only \u2014 other `.sideboard/` files such as settings.toml are fine). Point Codex/OpenCode at the Claude skill from `AGENTS.md`. Optional: symlink `.cursor/skills/<name>` to the Claude skill.",
6054
+ hasGraphSkill ? "- Migrations, ports, batch fixes, and other fan-out: follow `.claude/skills/graph-engineering/SKILL.md` (`/graph-engineering`). Judge first; state on disk; grow the rulebook; do not patch around it." : null,
6055
+ "- If this same shape of work will happen again, write `.claude/skills/<kebab-name>/SKILL.md` in this worktree (Claude Code project skill; Sideboard `/name`, Claude Code, and `attach` all load it). Not under `.sideboard/skills/`. Point Codex/OpenCode at it from `AGENTS.md`.",
6056
+ hasReviewSkill ? "- Merge-readiness notes go in `.claude/skills/review/SKILL.md` (edit it; do not create another review skill)." : "- Merge-readiness notes go in `.context/review.md` (copied from `.sideboard/review.md` when that file exists). Do not create a review skill.",
5995
6057
  "- Skip a guide for a one-off. If a matching skill exists, follow it. Same miss twice \u2192 edit the skill, do not patch around it."
5996
- ].join("\n");
6058
+ ].filter(Boolean).join("\n");
5997
6059
  }
5998
6060
  function formatLongRunningDirective(opts) {
5999
6061
  const invoke = formatDetachedJobInvoke(opts?.scriptPath);
6000
6062
  return [
6001
- "Long-running jobs (mandatory when a command may run more than ~30s):",
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.",
6003
- `Helper (same tool as \`scripts/detached-job.cjs\` when that file exists in the worktree): \`${invoke}\``,
6004
- `- Start once: \`${invoke} start <id> -- <command> [args...]\` (cwd = this worktree). If JSON says already-running, do not start again.`,
6005
- "- Immediately `present_artifact` `type=log` with `artifact_id=<id>` and `status=running` \u2014 the side column is the live view.",
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.`,
6007
- `- If it is hanging, producing no useful output, or doing the wrong thing: MCP \`stop_job\` (same id, optional reason) or \`${invoke} stop <id>\`. Do not loop forever. Do not stop a pack/test/deploy that is clearly making progress.`,
6008
- "- Do not end the turn with \u201CI\u2019ll let you know when it\u2019s done.\u201D Stay in the loop until stillRunning is false (or you stopped it).",
6009
- "- ok \u2192 finish the task. failed / stopped \u2192 read the log, fix or narrow the command, start once.",
6063
+ "Long-running jobs (mandatory when a command may run more than ~30s \u2014 pack, test, deploy, `gh pr checks --watch`):",
6064
+ "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.",
6065
+ `- 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.`,
6066
+ "- 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>`.",
6067
+ "- 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.",
6068
+ "- 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.",
6010
6069
  "State: `.context/.sideboard/detached-jobs/<id>/` (local scratch). Full guide: `/long-running` (always available)."
6011
6070
  ].join("\n");
6012
6071
  }
@@ -6016,97 +6075,16 @@ function formatLongRunningReminder(opts) {
6016
6075
  }
6017
6076
  function formatArtifactDirective() {
6018
6077
  return [
6019
- "Sideboard side column (desktop UI):",
6020
- "claude.ai\u2019s \u201CArtifact\u201D tool does NOT exist in Claude Code. That is expected.",
6021
- "Do not unprompted-duplicate a payload. Chat markdown (including tables) already renders in the transcript \u2014 do not also call present_schema with those same rows just to display them. If the user asks for an editable / interactive table, call present_schema even if markdown already showed the data. Do not also call present_artifact for a document you already fenced in chat.",
6022
- "Documents (HTML/SVG/markdown):",
6023
- "1) Emit a fenced code block tagged `html` (preferred), `svg`, or `markdown` with the FULL document \u2014 Sideboard opens a side column. Example:",
6024
- "```html",
6025
- "<!DOCTYPE html><html><head><title>Demo</title></head><body><h1>Hi</h1></body></html>",
6026
- "```",
6027
- "2) Or call Sideboard MCP `present_artifact` with title, type (html|svg|markdown|react|log), and content \u2014 not both a fence and this tool for the same body.",
6028
- " type=log is append-only: same `artifact_id`, `content` = new lines only (plus optional status/phase). Do not resend the full log or wrap it in HTML.",
6029
- "CMS / JSON Schema forms & tables (Brightsy or any schema+schemaUi source):",
6030
- "3) Call Sideboard MCP `present_schema` when the user needs to filter, edit, publish, or persist rows \u2014 including after you already showed a markdown table, if they then ask for an editable table. If they only need to read the data, a markdown table is enough. When you do call it, pass title, mode (table|form), and either:",
6031
- " - datasource=brightsy + resource_id (record type UUID) after fetching types via Brightsy MCP, or",
6032
- " - datasource=inline + resource: { id, title, schema, schemaUi } and optional records/record.",
6033
- "Files / media browser (CMS file manager column):",
6034
- "4) Call Sideboard MCP `present_files` with optional title, path, and datasource (brightsy|memory).",
6035
- " Opens the Files column for browse/upload/pick. Do NOT say a file manager UI is missing.",
6036
- "Multiple-choice questions:",
6037
- "5) Call Sideboard MCP `ask_user` only when work is blocked on choosing among a few concrete options (approach forks, which API, auth vs cookies). First write a short chat message that explains the decision and what each option means (tradeoffs, when to pick it). Include a description on every option. After calling, stop and wait for their next message with answers. If you are asking a real multiple-choice, use ask_user rather than chat bullets so Sideboard shows the composer picker.",
6038
- "Do not call ask_user for greetings, check-ins, \u201Chello\u201D, open-ended how-can-I-help, or to invent a menu of possible next tasks \u2014 reply in chat. If one option is the obvious default, proceed without asking.",
6039
- "Never say artifacts, CMS UI, or the Files column are unavailable. present_schema is for interactive list/edit/publish (use it when they ask to edit, even if chat already had a markdown table); present_files for storage UI; html fences for standalone pages; ask_user only for those blocked predefined-option questions."
6078
+ "Sideboard side column (desktop UI) \u2014 Sideboard MCP tools present_artifact, present_schema, present_files, ask_user (see their descriptions). claude.ai\u2019s \u201CArtifact\u201D tool does not exist here; never say artifacts, the CMS UI, or the Files column are unavailable.",
6079
+ "- Standalone documents: a fenced block tagged `html` (preferred), `svg`, or `markdown` containing the FULL document opens the side column by itself. Use that or present_artifact \u2014 never both for the same body.",
6080
+ "- present_artifact type=log appends: same artifact_id, content = new lines only (plus status/phase). Do not resend the full log or wrap it in HTML.",
6081
+ "- Data: a markdown table is enough to read. Call present_schema only when the user needs to filter/edit/publish/persist rows \u2014 including when they ask for an editable table after you already showed markdown. Never re-present rows you already wrote just to display them.",
6082
+ "- ask_user only when work is blocked on a few concrete options (approach fork, which API, auth vs cookies): first a short chat message explaining the decision and each option, then the call (description on every option), then stop and wait. Not for greetings, check-ins, or an invented menu of next tasks \u2014 reply in chat. If one option is the obvious default, proceed."
6040
6083
  ].join("\n");
6041
6084
  }
6042
6085
  function formatUiReminder() {
6043
6086
  return "Sideboard UI: markdown table is enough to read data; present_schema if they ask to edit/filter (even after markdown); present_files for the file manager. html fence or present_artifact, not both for the same document. type=log appends (same artifact_id, new lines only). ask_user only for a real multiple-choice (not hellos or \u201Cwhat next?\u201D) \u2014 reply in chat. Do not say artifacts/CMS UI are unavailable.";
6044
6087
  }
6045
- var FILES_BY_AGENT = {
6046
- claude: [
6047
- "CLAUDE.md",
6048
- ".claude/CLAUDE.md",
6049
- "CLAUDE.local.md",
6050
- "AGENTS.md",
6051
- "AGENT.md"
6052
- ],
6053
- codex: ["AGENTS.md", "AGENT.md", ".codex/AGENTS.md", "CLAUDE.md"],
6054
- opencode: ["AGENTS.md", "AGENT.md", "OPENCODE.md", "CLAUDE.md"],
6055
- brightsy: ["AGENTS.md", "AGENT.md", "CLAUDE.md"],
6056
- cursor: ["AGENTS.md", "AGENT.md", ".cursor/rules", "CLAUDE.md"]
6057
- };
6058
- var MAX_CHARS_PER_FILE = 48e3;
6059
- function loadAgentInstructions(worktreePath, agent) {
6060
- const candidates = FILES_BY_AGENT[agent] ?? FILES_BY_AGENT.claude;
6061
- const seenPaths = /* @__PURE__ */ new Set();
6062
- const seenBodies = /* @__PURE__ */ new Set();
6063
- const out = [];
6064
- for (const rel of candidates) {
6065
- if (seenPaths.has(rel)) continue;
6066
- const abs = join15(worktreePath, rel);
6067
- if (!existsSync16(abs)) continue;
6068
- try {
6069
- if (!statSync4(abs).isFile()) continue;
6070
- let content = readFileSync12(abs, "utf8");
6071
- if (!content.trim()) continue;
6072
- if (content.length > MAX_CHARS_PER_FILE) {
6073
- content = `${content.slice(0, MAX_CHARS_PER_FILE)}
6074
-
6075
- \u2026(truncated)`;
6076
- }
6077
- const body = content.trim().replace(/\r\n/g, "\n");
6078
- if (seenBodies.has(body)) continue;
6079
- seenPaths.add(rel);
6080
- seenBodies.add(body);
6081
- out.push({ relativePath: rel, content });
6082
- } catch {
6083
- }
6084
- }
6085
- return out;
6086
- }
6087
- function formatAgentInstructions(files) {
6088
- if (files.length === 0) return null;
6089
- const parts = [
6090
- "Project agent instructions (from the worktree \u2014 follow these):",
6091
- ""
6092
- ];
6093
- for (const f of files) {
6094
- parts.push(`## ${f.relativePath}`);
6095
- parts.push("");
6096
- parts.push(f.content.trim());
6097
- parts.push("");
6098
- parts.push("---");
6099
- parts.push("");
6100
- }
6101
- return parts.join("\n").trimEnd();
6102
- }
6103
- function withAgentInstructions(prompt, files) {
6104
- const prefix = formatAgentInstructions(files);
6105
- if (!prefix) return prompt;
6106
- return `${prefix}
6107
-
6108
- ${prompt}`;
6109
- }
6110
6088
 
6111
6089
  // src/integrations/optional-services.ts
6112
6090
  var OPTIONAL_SERVICE_IDS = ["vercel", "supabase", "posthog", "sentry"];
@@ -6405,7 +6383,7 @@ async function syncThreadBranchFromGit(threadId) {
6405
6383
 
6406
6384
  // src/store/schedules.ts
6407
6385
  import { randomUUID as randomUUID4 } from "crypto";
6408
- import { existsSync as existsSync17, readFileSync as readFileSync13 } from "fs";
6386
+ import { existsSync as existsSync17, readFileSync as readFileSync12 } from "fs";
6409
6387
  import { join as join16 } from "path";
6410
6388
  import { Cron } from "croner";
6411
6389
  var DURATION_RE = /^(\d+)(s|m|h|d)$/i;
@@ -6524,7 +6502,7 @@ function readAll() {
6524
6502
  const path = schedulesPath();
6525
6503
  if (!existsSync17(path)) return [];
6526
6504
  try {
6527
- const parsed = JSON.parse(readFileSync13(path, "utf8"));
6505
+ const parsed = JSON.parse(readFileSync12(path, "utf8"));
6528
6506
  if (!Array.isArray(parsed)) return [];
6529
6507
  return parsed.map((row) => {
6530
6508
  try {
@@ -6650,7 +6628,7 @@ function formatScheduledPrompt(name, prompt) {
6650
6628
  ${prompt}`;
6651
6629
  }
6652
6630
  async function defaultDeps() {
6653
- const { getOrchestrator: getOrchestrator2, startOrchestration: startOrchestration2 } = await import("./orchestrator-IIME6KXQ.js");
6631
+ const { getOrchestrator: getOrchestrator2, startOrchestration: startOrchestration2 } = await import("./orchestrator-UZSFTDKA.js");
6654
6632
  const orch = getOrchestrator2();
6655
6633
  return {
6656
6634
  findThread: (id) => findThreadByRef(id),
@@ -6660,7 +6638,7 @@ async function defaultDeps() {
6660
6638
  }
6661
6639
  function pickAgent(schedule) {
6662
6640
  if (schedule.agent) return schedule.agent;
6663
- return coerceOrchestratorAgent(resolveThreadDefaults().agent);
6641
+ return coerceOrchestratorAgent(resolveOrchestratorDefaults().agent);
6664
6642
  }
6665
6643
  async function fireSchedule(id) {
6666
6644
  const schedule = getSchedule(id);
@@ -6912,7 +6890,7 @@ var Orchestrator = class {
6912
6890
  orphans: orphans.map((o) => ({ path: o.path, repoPath: o.repoPath }))
6913
6891
  });
6914
6892
  }
6915
- const { autoCleanupOrphansEnabled } = await import("./app-settings-JJQDWPEK.js");
6893
+ const { autoCleanupOrphansEnabled } = await import("./app-settings-VMOTQORT.js");
6916
6894
  if (autoCleanupOrphansEnabled() && shouldRunWorktreeCleanup() && orphans.length > 0) {
6917
6895
  await cleanupOrphanWorktrees({ repoPaths });
6918
6896
  }
@@ -7191,7 +7169,7 @@ var Orchestrator = class {
7191
7169
  }
7192
7170
  await setup;
7193
7171
  if (skipSetup) return;
7194
- const { autoRunAfterSetupEnabled } = await import("./app-settings-JJQDWPEK.js");
7172
+ const { autoRunAfterSetupEnabled } = await import("./app-settings-VMOTQORT.js");
7195
7173
  if (autoRunAfterSetupEnabled()) {
7196
7174
  try {
7197
7175
  await this.startDev(threadId);
@@ -7474,17 +7452,21 @@ var Orchestrator = class {
7474
7452
  const slackReplyContext = formatSlackRepliesForTurn(
7475
7453
  pendingSlackExternalReplies(thread.messages)
7476
7454
  );
7477
- const agentPrompt = [
7478
- thread.planMode ? PLAN_MODE_INSTRUCTION : null,
7479
- orchestrationReminder,
7455
+ const turnReminders = [
7480
7456
  worktreeReminder,
7481
7457
  optionalServicesReminder,
7482
7458
  issueToolsReminder,
7483
7459
  viewerContextReminder,
7484
7460
  artifactReminder,
7485
- longRunningReminder,
7461
+ longRunningReminder
7462
+ ].filter(Boolean).join("\n\n") || void 0;
7463
+ const prGateDirective = thread.agent !== "brightsy" && !isOrchestratorThread(thread) && mentionsPrGoal(expandedPrompt) ? formatPrGateDirective() : null;
7464
+ const agentPrompt = [
7465
+ thread.planMode ? PLAN_MODE_INSTRUCTION : null,
7466
+ orchestrationReminder,
7467
+ prGateDirective,
7486
7468
  slackReplyContext,
7487
- expandedPrompt
7469
+ expandCanonicalGitRequest(expandedPrompt)
7488
7470
  ].filter(Boolean).join("\n\n");
7489
7471
  if (thread.attachments.length > 0) {
7490
7472
  updateThread(threadId, { attachments: [] });
@@ -7502,7 +7484,7 @@ var Orchestrator = class {
7502
7484
  }
7503
7485
  const isBrightsy = fresh.agent === "brightsy";
7504
7486
  const isOrchestration = isOrchestratorThread(fresh);
7505
- const { autoRenameBranchEnabled, getGithubGitAuthMode } = await import("./app-settings-JJQDWPEK.js");
7487
+ const { autoRenameBranchEnabled, getGithubGitAuthMode } = await import("./app-settings-VMOTQORT.js");
7506
7488
  const gitAuthMode = getGithubGitAuthMode();
7507
7489
  const worktreeDirective = isBrightsy || isOrchestration ? null : formatWorktreeDirective(fresh, {
7508
7490
  githubSlug: await resolveGithubRepoSlug(fresh.worktreePath).catch(
@@ -7574,7 +7556,7 @@ var Orchestrator = class {
7574
7556
  const stderrTail = [];
7575
7557
  const handle = await spawnAgentTurn(
7576
7558
  fresh,
7577
- { cachedPrefix, prompt: agentPrompt },
7559
+ { cachedPrefix, prompt: agentPrompt, systemPrompt: turnReminders },
7578
7560
  (event) => {
7579
7561
  this.emit({ type: "turn_output", threadId, event });
7580
7562
  noteTurnLiveEvent(threadId, event);
@@ -7683,7 +7665,7 @@ var Orchestrator = class {
7683
7665
  ].filter(Boolean).join("\n\n---\n\n");
7684
7666
  const retryHandle = await spawnAgentTurn(
7685
7667
  retryThread,
7686
- { cachedPrefix: retryPrefix, prompt: agentPrompt },
7668
+ { cachedPrefix: retryPrefix, prompt: agentPrompt, systemPrompt: turnReminders },
7687
7669
  (event) => {
7688
7670
  this.emit({ type: "turn_output", threadId, event });
7689
7671
  if (event.type === "session_id") {
@@ -8414,7 +8396,7 @@ var Orchestrator = class {
8414
8396
  updateThread(thread.id, { title: meta.title });
8415
8397
  }
8416
8398
  }
8417
- const { autoArchiveOnMergeEnabled } = await import("./app-settings-JJQDWPEK.js");
8399
+ const { autoArchiveOnMergeEnabled } = await import("./app-settings-VMOTQORT.js");
8418
8400
  const latest = this.requireThread(thread.id);
8419
8401
  if (!shouldAutoArchiveOnPrMerge({
8420
8402
  previousPrState: prevState || null,
@@ -8731,7 +8713,7 @@ var Orchestrator = class {
8731
8713
  this.emit({ type: "status_changed", threadId: archived.id, status: "archived" });
8732
8714
  if (thread.repoPath && !isGlobalRepoPath(thread.repoPath)) {
8733
8715
  try {
8734
- const { ensureWorkspace: ensureWorkspace2 } = await import("./workspaces-2IGQNFPL.js");
8716
+ const { ensureWorkspace: ensureWorkspace2 } = await import("./workspaces-A7C3WA54.js");
8735
8717
  await ensureWorkspace2(thread.repoPath);
8736
8718
  } catch {
8737
8719
  }
@@ -8758,7 +8740,7 @@ var Orchestrator = class {
8758
8740
  await runArchiveScript(thread.repoPath, thread.worktreePath);
8759
8741
  } catch {
8760
8742
  }
8761
- const { deleteBranchOnPurgeEnabled } = await import("./app-settings-JJQDWPEK.js");
8743
+ const { deleteBranchOnPurgeEnabled } = await import("./app-settings-VMOTQORT.js");
8762
8744
  const deleteBranch = opts?.deleteBranch ?? deleteBranchOnPurgeEnabled();
8763
8745
  await removeWorktree(thread.repoPath, thread.worktreePath, {
8764
8746
  deleteBranch: deleteBranch ? thread.branchName : void 0
@@ -8785,7 +8767,7 @@ var Orchestrator = class {
8785
8767
  `Cowboy checkout missing: ${thread.worktreePath}. Re-add the project folder, then restore.`
8786
8768
  );
8787
8769
  }
8788
- const { createThreadWorktree: createThreadWorktree2 } = await import("./worktree-5BFEK6PF.js");
8770
+ const { createThreadWorktree: createThreadWorktree2 } = await import("./worktree-PODE23PD.js");
8789
8771
  const slug = thread.worktreePath.split("/").pop();
8790
8772
  const dest = thread.worktreePath;
8791
8773
  await withRepoGitLock(thread.repoPath, async () => {
@@ -8895,7 +8877,7 @@ async function startOrchestration(opts) {
8895
8877
  sourceRef: "default",
8896
8878
  ...createOpts
8897
8879
  }).catch(async () => {
8898
- const { resolveDefaultBranch: resolveDefaultBranch2, resolveRepoRoot: resolveRepoRoot2 } = await import("./worktree-5BFEK6PF.js");
8880
+ const { resolveDefaultBranch: resolveDefaultBranch2, resolveRepoRoot: resolveRepoRoot2 } = await import("./worktree-PODE23PD.js");
8899
8881
  const repo = await resolveRepoRoot2(repoPath);
8900
8882
  const def = await resolveDefaultBranch2(repo);
8901
8883
  return orch.createThread({
@@ -8982,6 +8964,8 @@ export {
8982
8964
  shouldCompactContext,
8983
8965
  splitForCompaction,
8984
8966
  formatMessagesAsTranscript,
8967
+ SEED_MAX_CHARS,
8968
+ SEED_FULL_TOOL_MESSAGES,
8985
8969
  buildSessionSeed,
8986
8970
  BRIGHTSY_SUMMARIZE_CONTEXT_TOOL,
8987
8971
  extractBrightsyContextSummary,
@@ -9119,6 +9103,7 @@ export {
9119
9103
  formatRenameBranchDirective,
9120
9104
  formatWorktreeDirective,
9121
9105
  formatWorktreeReminder,
9106
+ mentionsPrGoal,
9122
9107
  issueTicketFromThread,
9123
9108
  linearTicketIdFromThread,
9124
9109
  formatIssueToolsDirective,
@@ -9131,9 +9116,6 @@ export {
9131
9116
  formatLongRunningReminder,
9132
9117
  formatArtifactDirective,
9133
9118
  formatUiReminder,
9134
- loadAgentInstructions,
9135
- formatAgentInstructions,
9136
- withAgentInstructions,
9137
9119
  OPTIONAL_SERVICE_IDS,
9138
9120
  OPTIONAL_SERVICES,
9139
9121
  optionalServiceSpec,