@sideboard-ai/core 0.1.150 → 0.1.152

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 (41) hide show
  1. package/dist/{agents-YWBQXOA2.js → agents-CUKWIM34.js} +6 -6
  2. package/dist/{agents-KKXGTEV6.js → agents-VHXCBBBD.js} +6 -6
  3. package/dist/{chunk-W6N6GQME.js → chunk-2SDMENAL.js} +1 -1
  4. package/dist/{chunk-NOTANBYC.js → chunk-2U6QF3PT.js} +7 -6
  5. package/dist/{chunk-Z2PVJKMN.js → chunk-3JBMACYX.js} +2 -2
  6. package/dist/{chunk-QGJHIJHV.js → chunk-67TIJ7S5.js} +2 -2
  7. package/dist/{chunk-NUPITVRF.js → chunk-6X7Z34XE.js} +105 -60
  8. package/dist/{chunk-DXCNW2JF.js → chunk-7BQNSUR2.js} +96 -75
  9. package/dist/{chunk-DMRIZR6M.js → chunk-7TIUOYBK.js} +7 -6
  10. package/dist/{chunk-YGGBJY5A.js → chunk-EY6QXPPO.js} +3 -3
  11. package/dist/{chunk-AF6O55PJ.js → chunk-G4MTYUWS.js} +3 -3
  12. package/dist/{chunk-ZGFYFVJF.js → chunk-GE7M3QTE.js} +2 -2
  13. package/dist/{chunk-SDN4ZYQH.js → chunk-GFQ57XAX.js} +3 -3
  14. package/dist/{chunk-WHU7YGWP.js → chunk-JRH62XC4.js} +4 -0
  15. package/dist/{chunk-HAS5EPBS.js → chunk-K2ANSHUO.js} +2 -2
  16. package/dist/{chunk-Y4NAPW5I.js → chunk-QQKDGPUI.js} +16 -13
  17. package/dist/{chunk-PTOSP4AH.js → chunk-RFMQY56R.js} +1 -1
  18. package/dist/{chunk-VO4SPEBS.js → chunk-SN6CMKF6.js} +3 -3
  19. package/dist/{chunk-VSFGPWCQ.js → chunk-SYFVUF2C.js} +16 -13
  20. package/dist/{coordinator-prompt-UCQJTFA7.js → coordinator-prompt-TBX4MOFM.js} +4 -4
  21. package/dist/{coordinator-prompt-NYR5TPBD.js → coordinator-prompt-WGFRYCHE.js} +4 -4
  22. package/dist/{global-workspace-4QHDAD2D.js → global-workspace-BHLUJ46D.js} +5 -5
  23. package/dist/{global-workspace-4SENNWBU.js → global-workspace-IY5QAV5C.js} +5 -5
  24. package/dist/index.cjs +138 -64
  25. package/dist/index.d.cts +39 -21
  26. package/dist/index.d.ts +39 -21
  27. package/dist/index.js +38 -12
  28. package/dist/mcp/run-stdio.cjs +120 -79
  29. package/dist/mcp/run-stdio.js +28 -12
  30. package/dist/{orchestrator-GZE4X3XV.js → orchestrator-256DFPSX.js} +9 -9
  31. package/dist/{orchestrator-QSBRWME5.js → orchestrator-NUA6SEV7.js} +9 -9
  32. package/dist/{plan-file-5S5TUNAW.js → plan-file-LSSSQGTQ.js} +2 -2
  33. package/dist/{plan-file-IBSU2PVW.js → plan-file-OZEBFSGQ.js} +2 -2
  34. package/dist/{workspaces-RDUSB6FD.js → workspaces-4FSXVIZM.js} +6 -6
  35. package/dist/{workspaces-7S7QKCUE.js → workspaces-NECIQTAO.js} +6 -6
  36. package/dist/{worktree-63AGPPLO.js → worktree-DPIREDFR.js} +3 -3
  37. package/dist/{worktree-JIZ3QMZX.js → worktree-HTUM35NT.js} +3 -3
  38. package/dist/{worktree-exclude-6MQWGWV5.js → worktree-exclude-N5X5I422.js} +3 -1
  39. package/dist/{worktree-exclude-TV6EV6BS.js → worktree-exclude-X54WSOXM.js} +3 -1
  40. package/package.json +1 -1
  41. /package/dist/{chunk-Y7YBWWIG.js → chunk-NVXVEGGM.js} +0 -0
@@ -8,12 +8,10 @@ import {
8
8
  import { mkdirSync, readFileSync, writeFileSync } from "fs";
9
9
  import { dirname, join } from "path";
10
10
  var WORKTREE_SIDEBOARD_EXCLUDE = ".sideboard/";
11
+ var WORKTREE_CONTEXT_EXCLUDE = ".context/";
11
12
  var EXCLUDE_COMMENT = "# Sideboard worktree scratch \u2014 do not commit";
12
- function excludeHasSideboard(body) {
13
- return body.split(/\r?\n/).some((line) => {
14
- const t = line.trim();
15
- return t === ".sideboard/" || t === ".sideboard" || t === "/.sideboard/";
16
- });
13
+ function excludeHasLine(body, ...needles) {
14
+ return body.split(/\r?\n/).some((line) => needles.includes(line.trim()));
17
15
  }
18
16
  async function ensureWorktreeSideboardIgnored(worktreePath) {
19
17
  if (!worktreePath.trim()) return;
@@ -32,16 +30,20 @@ async function ensureWorktreeSideboardIgnored(worktreePath) {
32
30
  } catch {
33
31
  body = "";
34
32
  }
35
- if (!excludeHasSideboard(body)) {
33
+ const missing = [];
34
+ if (!excludeHasLine(body, ".sideboard/", ".sideboard", "/.sideboard/")) {
35
+ missing.push(WORKTREE_SIDEBOARD_EXCLUDE);
36
+ }
37
+ if (!excludeHasLine(body, ".context/", ".context", "/.context/")) {
38
+ missing.push(WORKTREE_CONTEXT_EXCLUDE);
39
+ }
40
+ if (missing.length > 0) {
36
41
  const prefix = body && !body.endsWith("\n") ? `${body}
37
42
  ` : body;
38
- writeFileSync(
39
- excludePath,
40
- `${prefix}${EXCLUDE_COMMENT}
41
- ${WORKTREE_SIDEBOARD_EXCLUDE}
42
- `,
43
- "utf8"
44
- );
43
+ const header = body.includes(EXCLUDE_COMMENT) ? "" : `${EXCLUDE_COMMENT}
44
+ `;
45
+ writeFileSync(excludePath, `${prefix}${header}${missing.join("\n")}
46
+ `, "utf8");
45
47
  }
46
48
  const listed = await git(["ls-files", "-z", "--", ".sideboard"], worktreePath, {
47
49
  reject: false,
@@ -58,5 +60,6 @@ ${WORKTREE_SIDEBOARD_EXCLUDE}
58
60
 
59
61
  export {
60
62
  WORKTREE_SIDEBOARD_EXCLUDE,
63
+ WORKTREE_CONTEXT_EXCLUDE,
61
64
  ensureWorktreeSideboardIgnored
62
65
  };
@@ -9,11 +9,11 @@ import {
9
9
  enrichWorkspacesWithGithub,
10
10
  ensureGlobalCoordinatorCwd,
11
11
  formatWorkspaceInventory
12
- } from "./chunk-DMRIZR6M.js";
13
- import "./chunk-Z2PVJKMN.js";
14
- import "./chunk-Y7YBWWIG.js";
12
+ } from "./chunk-7TIUOYBK.js";
13
+ import "./chunk-3JBMACYX.js";
14
+ import "./chunk-NVXVEGGM.js";
15
15
  import "./chunk-EUXOHTUK.js";
16
- import "./chunk-VSFGPWCQ.js";
16
+ import "./chunk-SYFVUF2C.js";
17
17
  import "./chunk-FNQNJOHY.js";
18
18
  import "./chunk-CZD4NRDZ.js";
19
19
  import "./chunk-NSTQ6QKD.js";
@@ -7,16 +7,16 @@ import {
7
7
  enrichWorkspacesWithGithub,
8
8
  ensureGlobalCoordinatorCwd,
9
9
  formatWorkspaceInventory
10
- } from "./chunk-NOTANBYC.js";
11
- import "./chunk-ZGFYFVJF.js";
12
- import "./chunk-WHU7YGWP.js";
10
+ } from "./chunk-2U6QF3PT.js";
11
+ import "./chunk-GE7M3QTE.js";
12
+ import "./chunk-JRH62XC4.js";
13
13
  import "./chunk-4XNSGDXE.js";
14
14
  import "./chunk-4TR3HZFT.js";
15
15
  import "./chunk-JT7R45JB.js";
16
16
  import "./chunk-TUGKX5BD.js";
17
17
  import "./chunk-77WWLBCI.js";
18
18
  import "./chunk-QZQEXME2.js";
19
- import "./chunk-Y4NAPW5I.js";
19
+ import "./chunk-QQKDGPUI.js";
20
20
  import "./chunk-UFHNSFAS.js";
21
21
  export {
22
22
  COORDINATOR_TOOL_PLAYBOOK,
@@ -17,12 +17,12 @@ import {
17
17
  orchestratorSessionPoisonedByBuiltins,
18
18
  slackCoordinatorSourceRef,
19
19
  takenTeamSlugsForOrchestration
20
- } from "./chunk-VO4SPEBS.js";
21
- import "./chunk-DMRIZR6M.js";
22
- import "./chunk-Z2PVJKMN.js";
23
- import "./chunk-Y7YBWWIG.js";
20
+ } from "./chunk-SN6CMKF6.js";
21
+ import "./chunk-7TIUOYBK.js";
22
+ import "./chunk-3JBMACYX.js";
23
+ import "./chunk-NVXVEGGM.js";
24
24
  import "./chunk-EUXOHTUK.js";
25
- import "./chunk-VSFGPWCQ.js";
25
+ import "./chunk-SYFVUF2C.js";
26
26
  import "./chunk-FNQNJOHY.js";
27
27
  import "./chunk-CZD4NRDZ.js";
28
28
  import "./chunk-NSTQ6QKD.js";
@@ -15,10 +15,10 @@ import {
15
15
  orchestratorSessionPoisonedByBuiltins,
16
16
  slackCoordinatorSourceRef,
17
17
  takenTeamSlugsForOrchestration
18
- } from "./chunk-AF6O55PJ.js";
19
- import "./chunk-NOTANBYC.js";
20
- import "./chunk-ZGFYFVJF.js";
21
- import "./chunk-WHU7YGWP.js";
18
+ } from "./chunk-G4MTYUWS.js";
19
+ import "./chunk-2U6QF3PT.js";
20
+ import "./chunk-GE7M3QTE.js";
21
+ import "./chunk-JRH62XC4.js";
22
22
  import "./chunk-4XNSGDXE.js";
23
23
  import "./chunk-4TR3HZFT.js";
24
24
  import "./chunk-JT7R45JB.js";
@@ -27,7 +27,7 @@ import "./chunk-77WWLBCI.js";
27
27
  import {
28
28
  globalAgentCwd
29
29
  } from "./chunk-QZQEXME2.js";
30
- import "./chunk-Y4NAPW5I.js";
30
+ import "./chunk-QQKDGPUI.js";
31
31
  import "./chunk-UFHNSFAS.js";
32
32
  export {
33
33
  GLOBAL_WORKSPACE_ID,
package/dist/index.cjs CHANGED
@@ -2883,12 +2883,14 @@ function isWorkspaceScratchPath(relativePath) {
2883
2883
  const p = relativePath.replace(/\\/g, "/").replace(/^\.\//, "").replace(/\/$/, "");
2884
2884
  return p === ATTACHMENTS_DIR || p.startsWith(`${ATTACHMENTS_DIR}/`) || p === LEGACY_ATTACHMENTS_DIR || p.startsWith(`${LEGACY_ATTACHMENTS_DIR}/`) || p === ".sideboard" || p.startsWith(".sideboard/") || p === ".context" || p.startsWith(".context/");
2885
2885
  }
2886
- var ATTACHMENTS_DIR, LEGACY_ATTACHMENTS_DIR, ATTACHMENTS_GITIGNORE;
2886
+ var ATTACHMENTS_DIR, DETACHED_JOBS_DIR, LEGACY_ATTACHMENTS_DIR, LEGACY_DETACHED_JOBS_DIR, ATTACHMENTS_GITIGNORE;
2887
2887
  var init_workspace_scratch = __esm({
2888
2888
  "src/paths/workspace-scratch.ts"() {
2889
2889
  "use strict";
2890
2890
  ATTACHMENTS_DIR = ".context/attachments";
2891
+ DETACHED_JOBS_DIR = ".context/.sideboard/detached-jobs";
2891
2892
  LEGACY_ATTACHMENTS_DIR = ".sideboard/attachments";
2893
+ LEGACY_DETACHED_JOBS_DIR = ".sideboard/detached-jobs";
2892
2894
  ATTACHMENTS_GITIGNORE = `# Sideboard / workspace attachments (local only)
2893
2895
  *
2894
2896
  !.gitignore
@@ -4445,14 +4447,12 @@ var init_run = __esm({
4445
4447
  // src/git/worktree-exclude.ts
4446
4448
  var worktree_exclude_exports = {};
4447
4449
  __export(worktree_exclude_exports, {
4450
+ WORKTREE_CONTEXT_EXCLUDE: () => WORKTREE_CONTEXT_EXCLUDE,
4448
4451
  WORKTREE_SIDEBOARD_EXCLUDE: () => WORKTREE_SIDEBOARD_EXCLUDE,
4449
4452
  ensureWorktreeSideboardIgnored: () => ensureWorktreeSideboardIgnored
4450
4453
  });
4451
- function excludeHasSideboard(body) {
4452
- return body.split(/\r?\n/).some((line) => {
4453
- const t = line.trim();
4454
- return t === ".sideboard/" || t === ".sideboard" || t === "/.sideboard/";
4455
- });
4454
+ function excludeHasLine(body, ...needles) {
4455
+ return body.split(/\r?\n/).some((line) => needles.includes(line.trim()));
4456
4456
  }
4457
4457
  async function ensureWorktreeSideboardIgnored(worktreePath) {
4458
4458
  if (!worktreePath.trim()) return;
@@ -4471,16 +4471,20 @@ async function ensureWorktreeSideboardIgnored(worktreePath) {
4471
4471
  } catch {
4472
4472
  body = "";
4473
4473
  }
4474
- if (!excludeHasSideboard(body)) {
4474
+ const missing = [];
4475
+ if (!excludeHasLine(body, ".sideboard/", ".sideboard", "/.sideboard/")) {
4476
+ missing.push(WORKTREE_SIDEBOARD_EXCLUDE);
4477
+ }
4478
+ if (!excludeHasLine(body, ".context/", ".context", "/.context/")) {
4479
+ missing.push(WORKTREE_CONTEXT_EXCLUDE);
4480
+ }
4481
+ if (missing.length > 0) {
4475
4482
  const prefix = body && !body.endsWith("\n") ? `${body}
4476
4483
  ` : body;
4477
- (0, import_node_fs16.writeFileSync)(
4478
- excludePath,
4479
- `${prefix}${EXCLUDE_COMMENT}
4480
- ${WORKTREE_SIDEBOARD_EXCLUDE}
4481
- `,
4482
- "utf8"
4483
- );
4484
+ const header = body.includes(EXCLUDE_COMMENT) ? "" : `${EXCLUDE_COMMENT}
4485
+ `;
4486
+ (0, import_node_fs16.writeFileSync)(excludePath, `${prefix}${header}${missing.join("\n")}
4487
+ `, "utf8");
4484
4488
  }
4485
4489
  const listed = await git(["ls-files", "-z", "--", ".sideboard"], worktreePath, {
4486
4490
  reject: false,
@@ -4494,7 +4498,7 @@ ${WORKTREE_SIDEBOARD_EXCLUDE}
4494
4498
  timeoutMs: 8e3
4495
4499
  });
4496
4500
  }
4497
- var import_node_fs16, import_node_path17, WORKTREE_SIDEBOARD_EXCLUDE, EXCLUDE_COMMENT;
4501
+ var import_node_fs16, import_node_path17, WORKTREE_SIDEBOARD_EXCLUDE, WORKTREE_CONTEXT_EXCLUDE, EXCLUDE_COMMENT;
4498
4502
  var init_worktree_exclude = __esm({
4499
4503
  "src/git/worktree-exclude.ts"() {
4500
4504
  "use strict";
@@ -4502,6 +4506,7 @@ var init_worktree_exclude = __esm({
4502
4506
  import_node_path17 = require("path");
4503
4507
  init_run();
4504
4508
  WORKTREE_SIDEBOARD_EXCLUDE = ".sideboard/";
4509
+ WORKTREE_CONTEXT_EXCLUDE = ".context/";
4505
4510
  EXCLUDE_COMMENT = "# Sideboard worktree scratch \u2014 do not commit";
4506
4511
  }
4507
4512
  });
@@ -6606,7 +6611,7 @@ function ensureGlobalCoordinatorCwd(opts) {
6606
6611
  "Typical flow (Home board): list_board \u2192 create_thread (sourceType=ticket|pr|branch) \u2192 send_to_thread \u2192 wait_for_turn (loop while stillRunning) \u2192 ask_git create-draft \u2192 wait_for_turn. Merge only if the user explicitly asked (`ask_git` merge).",
6607
6612
  "Typical flow (branch / explicit source): list_workspaces \u2192 list_branches|list_prs|list_issues \u2192 create_thread \u2192 send_to_thread \u2192 wait_for_turn (loop while stillRunning) \u2192 ask_git create-draft.",
6608
6613
  "Typical flow (new app): Bash create/clone under repos dir \u2192 add_workspace \u2192 create_thread \u2192 send_to_thread (implement) \u2192 wait_for_turn (loop while stillRunning) \u2192 ask_git create-draft.",
6609
- "Always ask worktree agents to commit, push, and open draft PRs (`ask_git` / `send_to_thread`). Tell them to merge only when the user explicitly asked. The worktree agent runs git/gh; never merge from this orchestration cwd."
6614
+ "Always ask worktree agents to commit, push, and open draft PRs (`ask_git` / `send_to_thread`). If the user gave a goal (Greptile 5/5, CI green), pass that goal through so they watch-fix-push until it lands \u2014 do not start that loop on a plain push, and do not tell the human to poll. Tell them to merge only when the user explicitly asked. The worktree agent runs git/gh; never merge from this orchestration cwd."
6610
6615
  ].join("\n");
6611
6616
  try {
6612
6617
  (0, import_node_fs18.writeFileSync)((0, import_node_path20.join)(dir, "CLAUDE.md"), `${body}
@@ -6686,15 +6691,16 @@ var init_coordinator_prompt = __esm({
6686
6691
  "- list_run_scripts / run_dev_script / stop_dev_script \u2014 start/stop named run scripts",
6687
6692
  "Inspect / review / PRs:",
6688
6693
  "- get_diff \u2014 compact diff summary",
6689
- '- request_review \u2014 open a Review chat tab on a worktree thread (attaches .claude/skills/review/SKILL.md when present, else seeds that skill / local guidelines; sends "Review changes in this workspace."); then wait_for_turn (loop while stillRunning) / get_turn_result on the returned id',
6690
- "- ask_git \u2014 commit & push, open a draft PR, resolve conflicts, or merge. When the worktree is clean, Sideboard pushes / opens the PR itself. When dirty, it queues the worktree agent \u2014 then wait_for_turn (loop while stillRunning). Prefer this over paraphrasing. If ask_git / get_thread lastError says the GraphQL/PR body is too long, the branch is already pushed \u2014 send_to_thread so the worktree agent runs `gh pr create --body-file` with a short description. Do not invent SSH or auth failures from that error.",
6694
+ "- get_pr_checks \u2014 snapshot of a worktree thread's PR checks (null = no PR). Use this to inspect status. If the user gave a goal, the worktree agent watches with `gh pr checks --watch` \u2014 do not poll for the human.",
6695
+ '- request_review \u2014 open a Review chat tab on a worktree thread (attaches .claude/skills/review/SKILL.md when present, else .context/review.md copied from .sideboard/review.md / stock; sends "Review changes in this workspace."); then wait_for_turn (loop while stillRunning) / get_turn_result on the returned id',
6696
+ "- ask_git \u2014 commit & push, open a draft PR, resolve conflicts, or merge. When the worktree is clean, Sideboard pushes / opens the PR itself. When dirty, it queues the worktree agent \u2014 then wait_for_turn (loop while stillRunning). Prefer this over paraphrasing. If ask_git / get_thread lastError says the GraphQL/PR body is too long, the branch is already pushed \u2014 send_to_thread so the worktree agent runs `gh pr create --body-file` with a short description. Do not invent SSH or auth failures from that error. If the user gave a goal (Greptile 5/5, CI green), send_to_thread that goal so the worktree agent enters the watch-fix-push loop \u2014 do not tell the human to poll.",
6691
6697
  '- Merge (`ask_git` action=merge / send_to_thread "Merge PR.") only when the user explicitly asked to merge that PR. Do not merge because the work looks done, CI is green, or a typical flow includes it.',
6692
6698
  '- Or send_to_thread with those exact phrases: "Commit and push.", "Commit, push, and open a draft PR.", "Merge the remote branch (main) into your branch and resolve conflicts. Then, commit and push your changes.", "Merge PR." (draft PRs: `gh pr create --draft -R <origin-owner/name>` using the workspace `github:` slug \u2014 never upstream). Never run git/gh from this orchestration cwd, and never merge the PR yourself.',
6693
6699
  "Process guides:",
6694
6700
  "- Long child jobs (pack, test, deploy, anything that may run more than ~30s): workers always have `/long-running` (Sideboard product skill). Tell them to detach and wait; do not ask the human to poll.",
6695
6701
  "- Recurring multi-item / fan-out: if the child worktree has `.claude/skills/graph-engineering/SKILL.md`, tell the worker to follow it (`/graph-engineering`). Judge first; state on disk; grow the rulebook; do not patch three threads.",
6696
- "- Recurring shapes: have the worktree agent write `.claude/skills/<kebab-name>/SKILL.md` (commit it) so later threads and native Claude Code / attach see it. Merge-review sentences go in `.claude/skills/review/SKILL.md` (create it \u2014 that is allowed). Do not use `.sideboard/skills/` (that folder only). Codex/OpenCode: one line in AGENTS.md pointing at that file.",
6697
- "- One-offs: no guide. Same miss across threads: edit the skill or `.claude/skills/review/SKILL.md`, then rerun the batch \u2014 do not patch three threads.",
6702
+ "- Recurring shapes: have the worktree agent write `.claude/skills/<kebab-name>/SKILL.md` (commit it) so later threads and native Claude Code / attach see it. Merge-review sentences go in `.claude/skills/review/SKILL.md` when that skill already exists; otherwise `.context/review.md` (do not create a review skill). Do not use `.sideboard/skills/` (that folder only). Codex/OpenCode: one line in AGENTS.md pointing at that file.",
6703
+ "- One-offs: no guide. Same miss across threads: edit the existing skill or `.context/review.md`, then rerun the batch \u2014 do not patch three threads.",
6698
6704
  "Human-only (do not attempt): ready-for-review land (confirm_land), purge_thread.",
6699
6705
  "Thread links in replies: when mentioning a chat/thread for the user, include a markdown link `[Title](sideboard://thread/<id>)` using the full id (or the link field from create_thread / list_threads). Sideboard renders these as clickable opens.",
6700
6706
  "Bash / Read / etc: allowed for (1) inspecting target worktrees / registered repo paths from MCP, and (2) greenfield setup under ~/sideboard/repos (git clone, gh repo create, git init+remote). Never git init/clone *inside* this synthetic home cwd \u2014 emptiness here is expected, not a bug."
@@ -13275,7 +13281,7 @@ File: src/client/frontends/desktop/core/UserData.ts
13275
13281
 
13276
13282
  ## Growing the rules
13277
13283
 
13278
- If a blocking issue is a missing or ambiguous repo rule that will recur, add one sentence to \`.claude/skills/review/SKILL.md\` (create the skill if it is missing \u2014 that is allowed and should be committed). Do not only patch this diff when the same miss will happen again. Do not write new skills under \`.sideboard/skills/\`. Do not use \`.sideboard/review.md\` for new notes.
13284
+ If a blocking issue is a missing or ambiguous repo rule that will recur, add one sentence to \`.claude/skills/review/SKILL.md\` when that skill already exists. Otherwise write it to \`.context/review.md\` (do not create a review skill). Do not only patch this diff when the same miss will happen again. Do not write new skills under \`.sideboard/skills/\`.
13279
13285
  `;
13280
13286
  REVIEW_SKILL_PATH = ".claude/skills/review/SKILL.md";
13281
13287
  REVIEW_SKILL_NAME = "review";
@@ -13329,41 +13335,64 @@ function skillGuidelines(content, source) {
13329
13335
  source
13330
13336
  };
13331
13337
  }
13332
- function ensureReviewSkillFile(worktreePath) {
13333
- const abs = (0, import_node_path32.join)(worktreePath, REVIEW_SKILL_PATH);
13334
- const existing = readTextIfPresent(abs);
13335
- if (existing) {
13336
- return { path: REVIEW_SKILL_PATH, content: existing, wrote: false };
13337
- }
13338
- const fromRepo = readTextIfPresent((0, import_node_path32.join)(worktreePath, REPO_REVIEW_PATH));
13339
- const fromLocal = readLocalGuidelines(worktreePath)?.content ?? null;
13340
- const content = wrapReviewSkillMarkdown(fromRepo ?? fromLocal ?? REVIEW_REQUEST_TEMPLATE);
13338
+ function contextGuidelines(content, source) {
13339
+ return {
13340
+ path: CONTEXT_REVIEW_PATH,
13341
+ name: REPO_REVIEW_NAME,
13342
+ content,
13343
+ source
13344
+ };
13345
+ }
13346
+ function writeContextGuidelines(worktreePath, content) {
13347
+ const abs = (0, import_node_path32.join)(worktreePath, CONTEXT_REVIEW_PATH);
13341
13348
  (0, import_node_fs32.mkdirSync)((0, import_node_path32.dirname)(abs), { recursive: true });
13342
- (0, import_node_fs32.writeFileSync)(abs, content, "utf8");
13343
- return { path: REVIEW_SKILL_PATH, content, wrote: true };
13349
+ const body = content.endsWith("\n") ? content : `${content}
13350
+ `;
13351
+ (0, import_node_fs32.writeFileSync)(abs, body, "utf8");
13352
+ return body;
13344
13353
  }
13345
- function resolveReviewGuidelines(worktreePath) {
13354
+ function readSideboardReview(worktreePath, repoPath) {
13355
+ const fromWorktree = readTextIfPresent((0, import_node_path32.join)(worktreePath, REPO_REVIEW_PATH));
13356
+ if (fromWorktree) return fromWorktree;
13357
+ const repo = repoPath?.replace(/\/+$/, "");
13358
+ const wt = worktreePath.replace(/\/+$/, "");
13359
+ if (!repo || repo === wt) return null;
13360
+ return readTextIfPresent((0, import_node_path32.join)(repo, REPO_REVIEW_PATH));
13361
+ }
13362
+ function ensureReviewGuidelinesFile(worktreePath, repoPath) {
13346
13363
  const skillContent = readTextIfPresent((0, import_node_path32.join)(worktreePath, REVIEW_SKILL_PATH));
13347
- if (skillContent) return skillGuidelines(skillContent, "skill");
13348
- const local = readLocalGuidelines(worktreePath);
13349
- if (local) {
13350
- return {
13351
- path: local.path,
13352
- name: REVIEW_REQUEST_NAME,
13353
- content: local.content,
13354
- source: "local"
13355
- };
13364
+ if (skillContent) {
13365
+ return { ...skillGuidelines(skillContent, "skill"), wrote: false };
13366
+ }
13367
+ const contextContent = readTextIfPresent((0, import_node_path32.join)(worktreePath, CONTEXT_REVIEW_PATH));
13368
+ if (contextContent && !shouldRefreshReviewRequestTemplate(contextContent)) {
13369
+ return { ...contextGuidelines(contextContent, "local"), wrote: false };
13370
+ }
13371
+ const fromSideboard = readSideboardReview(worktreePath, repoPath);
13372
+ if (fromSideboard && !shouldRefreshReviewRequestTemplate(fromSideboard)) {
13373
+ const body2 = writeContextGuidelines(worktreePath, fromSideboard);
13374
+ return { ...contextGuidelines(body2, "repo"), wrote: true };
13356
13375
  }
13357
- const seeded = ensureReviewSkillFile(worktreePath);
13358
- return skillGuidelines(seeded.content, seeded.wrote ? "stock" : "skill");
13376
+ const local = readLocalGuidelines(worktreePath);
13377
+ const body = writeContextGuidelines(worktreePath, local?.content ?? REVIEW_REQUEST_TEMPLATE);
13378
+ return {
13379
+ ...contextGuidelines(body, local ? "local" : "stock"),
13380
+ wrote: true
13381
+ };
13359
13382
  }
13360
- function ensureReviewRequestFile(worktreePath) {
13361
- const seeded = ensureReviewSkillFile(worktreePath);
13362
- return skillGuidelines(seeded.content, "skill");
13383
+ function ensureReviewSkillFile(worktreePath, repoPath) {
13384
+ const g = ensureReviewGuidelinesFile(worktreePath, repoPath);
13385
+ return { path: g.path, content: g.content, wrote: g.wrote };
13386
+ }
13387
+ function resolveReviewGuidelines(worktreePath, repoPath) {
13388
+ return ensureReviewGuidelinesFile(worktreePath, repoPath);
13389
+ }
13390
+ function ensureReviewRequestFile(worktreePath, repoPath) {
13391
+ return ensureReviewGuidelinesFile(worktreePath, repoPath);
13363
13392
  }
13364
13393
  function buildReviewRequestAttachment(content, opts) {
13365
13394
  const path2 = opts?.path ?? REVIEW_SKILL_PATH;
13366
- const name = opts?.name ?? (path2 === REVIEW_SKILL_PATH ? REVIEW_SKILL_NAME : path2 === REPO_REVIEW_PATH ? REPO_REVIEW_NAME : REVIEW_REQUEST_NAME);
13395
+ const name = opts?.name ?? (path2 === REVIEW_SKILL_PATH ? REVIEW_SKILL_NAME : path2 === REPO_REVIEW_PATH || path2 === CONTEXT_REVIEW_PATH ? REPO_REVIEW_NAME : REVIEW_REQUEST_NAME);
13367
13396
  return {
13368
13397
  id: (0, import_node_crypto8.randomUUID)(),
13369
13398
  name,
@@ -13373,7 +13402,7 @@ function buildReviewRequestAttachment(content, opts) {
13373
13402
  };
13374
13403
  }
13375
13404
  function readExistingReviewRequestFile(worktreePath) {
13376
- return readTextIfPresent((0, import_node_path32.join)(worktreePath, REVIEW_SKILL_PATH)) ?? readTextIfPresent((0, import_node_path32.join)(worktreePath, REPO_REVIEW_PATH)) ?? readTextIfPresent((0, import_node_path32.join)(worktreePath, REVIEW_REQUEST_PATH)) ?? readTextIfPresent((0, import_node_path32.join)(worktreePath, LEGACY_REVIEW_REQUEST_PATH));
13405
+ return readTextIfPresent((0, import_node_path32.join)(worktreePath, REVIEW_SKILL_PATH)) ?? readTextIfPresent((0, import_node_path32.join)(worktreePath, CONTEXT_REVIEW_PATH)) ?? readTextIfPresent((0, import_node_path32.join)(worktreePath, REPO_REVIEW_PATH)) ?? readTextIfPresent((0, import_node_path32.join)(worktreePath, REVIEW_REQUEST_PATH)) ?? readTextIfPresent((0, import_node_path32.join)(worktreePath, LEGACY_REVIEW_REQUEST_PATH));
13377
13406
  }
13378
13407
  async function requestReview(threadRef, send2) {
13379
13408
  const from = findThreadByRef(threadRef);
@@ -13386,7 +13415,7 @@ async function requestReview(threadRef, send2) {
13386
13415
  if (from.status === "archived") {
13387
13416
  throw new Error(`Thread is archived: ${from.id}`);
13388
13417
  }
13389
- const guidelines = resolveReviewGuidelines(from.worktreePath);
13418
+ const guidelines = resolveReviewGuidelines(from.worktreePath, from.repoPath);
13390
13419
  const tab = createChatTab({
13391
13420
  fromThreadId: from.id,
13392
13421
  title: "Review",
@@ -13400,7 +13429,7 @@ async function requestReview(threadRef, send2) {
13400
13429
  const started = await send2(tab.id, REVIEW_REQUEST_PREFILL);
13401
13430
  return { tab: started, from };
13402
13431
  }
13403
- var import_node_crypto8, import_node_fs32, import_node_path32, REPO_REVIEW_PATH, REPO_REVIEW_NAME, REVIEW_REQUEST_PATH, LEGACY_REVIEW_REQUEST_PATH, REVIEW_REQUEST_NAME, REVIEW_REQUEST_PREFILL, LEGACY_REVIEW_TEMPLATE_MARKERS;
13432
+ var import_node_crypto8, import_node_fs32, import_node_path32, REPO_REVIEW_PATH, REPO_REVIEW_NAME, CONTEXT_REVIEW_PATH, REVIEW_REQUEST_PATH, LEGACY_REVIEW_REQUEST_PATH, REVIEW_REQUEST_NAME, REVIEW_REQUEST_PREFILL, LEGACY_REVIEW_TEMPLATE_MARKERS;
13404
13433
  var init_request_review = __esm({
13405
13434
  "src/review/request-review.ts"() {
13406
13435
  "use strict";
@@ -13414,6 +13443,7 @@ var init_request_review = __esm({
13414
13443
  init_workspace_scratch();
13415
13444
  REPO_REVIEW_PATH = ".sideboard/review.md";
13416
13445
  REPO_REVIEW_NAME = "review.md";
13446
+ CONTEXT_REVIEW_PATH = ".context/review.md";
13417
13447
  REVIEW_REQUEST_PATH = `${ATTACHMENTS_DIR}/Review request.md`;
13418
13448
  LEGACY_REVIEW_REQUEST_PATH = `${LEGACY_ATTACHMENTS_DIR}/Review request.md`;
13419
13449
  REVIEW_REQUEST_NAME = "Review request.md";
@@ -13667,11 +13697,9 @@ async function runConventionSetup(repoPath, worktreePath, onLine, opts) {
13667
13697
  }
13668
13698
  async function runWorkspaceSetup(repoPath, worktreePath, onLine, opts) {
13669
13699
  await ensureWorktreeSideboardIgnored(worktreePath);
13670
- const reviewSkill = ensureReviewSkillFile(worktreePath);
13671
- if (reviewSkill.wrote) {
13672
- onLine?.(
13673
- `[setup] wrote ${REVIEW_SKILL_PATH} \u2014 commit it so later worktrees inherit Review guidelines`
13674
- );
13700
+ const review = ensureReviewGuidelinesFile(worktreePath, repoPath);
13701
+ if (review.wrote) {
13702
+ onLine?.(`[setup] wrote ${review.path} \u2014 local Review guidelines`);
13675
13703
  }
13676
13704
  let setup = await runSetupScript(repoPath, worktreePath, onLine, opts);
13677
13705
  if (!setup.ran) {
@@ -17211,7 +17239,7 @@ node <detached-job.js> wait <id> --until-done
17211
17239
  node <detached-job.js> status <id>
17212
17240
  \`\`\`
17213
17241
 
17214
- \`<id>\` is kebab-case (\`mac-release\`, \`core-test\`, \`fly-deploy\`). State is \`.sideboard/detached-jobs/<id>/\` (local scratch).
17242
+ \`<id>\` is kebab-case (\`mac-release\`, \`core-test\`, \`fly-deploy\`). State is \`.context/.sideboard/detached-jobs/<id>/\` (local scratch).
17215
17243
 
17216
17244
  Wait JSON:
17217
17245
 
@@ -17249,6 +17277,16 @@ node <detached-job.js> wait --pid-file FILE --log-file FILE [--ok-pattern TEXT]
17249
17277
  4. On \`ok\`, present once more (\`status=ok\`, last \`delta\`) and finish the task. On \`failed\`, fix from the log.
17250
17278
 
17251
17279
  Never tell the user \u201Csay status when it\u2019s done.\u201D You wait.
17280
+
17281
+ ## PR checks (only if a goal is given)
17282
+
17283
+ Do **not** watch after every push. If the user gave a goal (Greptile 5/5, CI green, until checks pass), wait the same way:
17284
+
17285
+ \`\`\`bash
17286
+ node <detached-job.js> start pr-checks -- gh pr checks --watch
17287
+ \`\`\`
17288
+
17289
+ On miss, fix, commit, push, and watch again until the goal is met or you are blocked. Do not ask the human to poll. Do not merge unless asked.
17252
17290
  `;
17253
17291
  }
17254
17292
  });
@@ -17638,7 +17676,7 @@ function formatWorktreeDirective(thread, opts) {
17638
17676
  "Short git requests from the Sideboard UI are complete instructions \u2014 expand them using the rules above without asking for clarification:"
17639
17677
  );
17640
17678
  lines.push(
17641
- '- "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).'
17679
+ '- "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.'
17642
17680
  );
17643
17681
  lines.push(
17644
17682
  '- "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).'
@@ -17647,7 +17685,7 @@ function formatWorktreeDirective(thread, opts) {
17647
17685
  '- "Commit, push, and open a PR in the browser." \u2192 commit, push, then `gh pr create --web -R \u2026`.'
17648
17686
  );
17649
17687
  lines.push(
17650
- '- "Fix CI: <name>." \u2192 investigate that failing check, fix it, commit, and push.'
17688
+ '- "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.'
17651
17689
  );
17652
17690
  lines.push(
17653
17691
  '- "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.'
@@ -17659,11 +17697,21 @@ function formatWorktreeDirective(thread, opts) {
17659
17697
  '- "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.'
17660
17698
  );
17661
17699
  lines.push("");
17700
+ lines.push(formatPrGateDirective());
17701
+ lines.push("");
17662
17702
  lines.push(formatProcessGuideDirective());
17663
17703
  return lines.join("\n");
17664
17704
  }
17665
17705
  function formatWorktreeReminder() {
17666
- 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.";
17706
+ 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.";
17707
+ }
17708
+ function formatPrGateDirective() {
17709
+ return [
17710
+ "If a goal is given (not after every push):",
17711
+ "- Enter a watch-fix-push loop and stay in it until that goal is met or you are blocked (examples: \u201CGreptile 5/5\u201D, \u201CCI green\u201D, \u201Cuntil checks pass\u201D). Do not stop after one red run or one review cycle.",
17712
+ "- Wait with `/long-running`: `gh pr checks --watch` (add `-R <origin>` when needed). Present the log. Do not ask the human to poll.",
17713
+ "- 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."
17714
+ ].join("\n");
17667
17715
  }
17668
17716
  function formatProcessGuideDirective() {
17669
17717
  return [
@@ -17671,7 +17719,7 @@ function formatProcessGuideDirective() {
17671
17719
  "- Long jobs (pack, test, deploy, anything that may run more than ~30s): Sideboard always provides `/long-running`. Detach and wait \u2014 do not ask the human to poll.",
17672
17720
  "- 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.",
17673
17721
  "- 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.",
17674
- "- Merge-readiness notes: create or edit `.claude/skills/review/SKILL.md` and commit it. That file is allowed. Do not use `.sideboard/review.md` for new notes (legacy; setup copies it into the skill).",
17722
+ "- 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.",
17675
17723
  "- 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.",
17676
17724
  "- 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."
17677
17725
  ].join("\n");
@@ -17686,7 +17734,7 @@ function formatLongRunningDirective(opts) {
17686
17734
  "- Immediately `present_artifact` `type=log` with `artifact_id=<id>` and `status=running` \u2014 the side column is the live view.",
17687
17735
  `- Loop \`${invoke} wait <id>\` (returns in ~45s). stillRunning \u2192 present the same id with \`content=delta\` only \u2192 wait again. Do not resend the full log or HTML.`,
17688
17736
  "- ok \u2192 finish the task. failed \u2192 read the log, fix, start once.",
17689
- "State: `.sideboard/detached-jobs/<id>/` (local scratch). Full guide: `/long-running` (always available)."
17737
+ "State: `.context/.sideboard/detached-jobs/<id>/` (local scratch). Full guide: `/long-running` (always available)."
17690
17738
  ].join("\n");
17691
17739
  }
17692
17740
  function formatLongRunningReminder(opts) {
@@ -20604,10 +20652,12 @@ __export(index_exports, {
20604
20652
  CONTEXT_KEEP_RECENT_CHARS: () => CONTEXT_KEEP_RECENT_CHARS,
20605
20653
  CONTEXT_KEEP_RECENT_MESSAGES: () => CONTEXT_KEEP_RECENT_MESSAGES,
20606
20654
  CONTEXT_MIN_MESSAGES: () => CONTEXT_MIN_MESSAGES,
20655
+ CONTEXT_REVIEW_PATH: () => CONTEXT_REVIEW_PATH,
20607
20656
  CONVENTION_SETUP_RELPATHS: () => CONVENTION_SETUP_RELPATHS,
20608
20657
  COORDINATOR_TOOL_PLAYBOOK: () => COORDINATOR_TOOL_PLAYBOOK,
20609
20658
  DEFAULT_ABLETIME_HOST: () => DEFAULT_ABLETIME_HOST,
20610
20659
  DEFAULT_WORKTREE_SORT: () => DEFAULT_WORKTREE_SORT,
20660
+ DETACHED_JOBS_DIR: () => DETACHED_JOBS_DIR,
20611
20661
  FAMOUS_SOCCER_TEAMS: () => FAMOUS_SOCCER_TEAMS,
20612
20662
  FOLLOW_UP_BEHAVIORS: () => FOLLOW_UP_BEHAVIORS,
20613
20663
  GITHUB_GIT_AUTH_MODES: () => GITHUB_GIT_AUTH_MODES,
@@ -20618,6 +20668,7 @@ __export(index_exports, {
20618
20668
  HOME_BOARD_CACHE_TTL_MS: () => HOME_BOARD_CACHE_TTL_MS,
20619
20669
  ISSUE_SOURCE_LABELS: () => ISSUE_SOURCE_LABELS,
20620
20670
  LEGACY_ATTACHMENTS_DIR: () => LEGACY_ATTACHMENTS_DIR,
20671
+ LEGACY_DETACHED_JOBS_DIR: () => LEGACY_DETACHED_JOBS_DIR,
20621
20672
  LEGACY_PLAN_FILE_REL: () => LEGACY_PLAN_FILE_REL,
20622
20673
  LEGACY_REVIEW_REQUEST_PATH: () => LEGACY_REVIEW_REQUEST_PATH,
20623
20674
  LINEAR_OAUTH_CANCELLED: () => LINEAR_OAUTH_CANCELLED,
@@ -20808,6 +20859,7 @@ __export(index_exports, {
20808
20859
  ensureConnectedBrightsyTeamTokens: () => ensureConnectedBrightsyTeamTokens,
20809
20860
  ensureGhPreferOrigin: () => ensureGhPreferOrigin,
20810
20861
  ensureGlobalCoordinatorCwd: () => ensureGlobalCoordinatorCwd,
20862
+ ensureReviewGuidelinesFile: () => ensureReviewGuidelinesFile,
20811
20863
  ensureReviewRequestFile: () => ensureReviewRequestFile,
20812
20864
  ensureReviewSkillFile: () => ensureReviewSkillFile,
20813
20865
  ensureSlackCoordinator: () => ensureSlackCoordinator,
@@ -20857,6 +20909,7 @@ __export(index_exports, {
20857
20909
  formatOptionalServicesReminder: () => formatOptionalServicesReminder,
20858
20910
  formatPlanQuestionAnswers: () => formatPlanQuestionAnswers,
20859
20911
  formatPlanQuestionsForChat: () => formatPlanQuestionsForChat,
20912
+ formatPrGateDirective: () => formatPrGateDirective,
20860
20913
  formatProcessGuideDirective: () => formatProcessGuideDirective,
20861
20914
  formatRateLimitResetHint: () => formatRateLimitResetHint,
20862
20915
  formatRenameBranchDirective: () => formatRenameBranchDirective,
@@ -24760,9 +24813,25 @@ async function startMcpServer() {
24760
24813
  };
24761
24814
  }
24762
24815
  );
24816
+ server.tool(
24817
+ "get_pr_checks",
24818
+ "Snapshot of GitHub PR checks for a worktree thread (`gh pr checks` plus merge/review gates). null = no PR. If the user gave a goal (Greptile 5/5, CI green), the worktree agent watches with `gh pr checks --watch` via /long-running \u2014 this tool is a snapshot, not a waiter. Coordinators: do not run gh from the orchestration cwd.",
24819
+ { ref: import_zod5.z.string().describe("Worktree thread id/ref") },
24820
+ async ({ ref }) => {
24821
+ try {
24822
+ const checks = await orch.getPrChecks(ref);
24823
+ return {
24824
+ content: [{ type: "text", text: JSON.stringify(checks) }]
24825
+ };
24826
+ } catch (err) {
24827
+ const message = err instanceof Error ? err.message : String(err);
24828
+ return { content: [{ type: "text", text: message }], isError: true };
24829
+ }
24830
+ }
24831
+ );
24763
24832
  server.tool(
24764
24833
  "request_review",
24765
- 'Start a merge-readiness Review on a worktree agent thread (same as the desktop Review button). Opens a new Review chat tab, attaches .claude/skills/review/SKILL.md when present (else seeds that skill from .sideboard/review.md or the stock template), and sends "Review changes in this workspace." Expect Approve / Approve with nits / Request changes / Needs more information. Pass a worktree thread ref \u2014 not the orchestrator. Then wait_for_turn (loop while stillRunning) / get_turn_result on the returned review tab id.',
24834
+ 'Start a merge-readiness Review on a worktree agent thread (same as the desktop Review button). Opens a new Review chat tab, attaches .claude/skills/review/SKILL.md when present (else copies .sideboard/review.md into .context/review.md, or seeds that file from the stock template), and sends "Review changes in this workspace." Expect Approve / Approve with nits / Request changes / Needs more information. Pass a worktree thread ref \u2014 not the orchestrator. Then wait_for_turn (loop while stillRunning) / get_turn_result on the returned review tab id.',
24766
24835
  { ref: import_zod5.z.string().describe("Worktree thread id/ref to review") },
24767
24836
  async ({ ref }) => {
24768
24837
  try {
@@ -24790,7 +24859,7 @@ async function startMcpServer() {
24790
24859
  );
24791
24860
  server.tool(
24792
24861
  "ask_git",
24793
- "Commit & push, open a draft PR, resolve conflicts, or merge \u2014 same actions as the desktop git buttons. When the worktree is clean, Sideboard pushes / opens the PR itself (HTTPS via `gh` even when origin is SSH / Settings \u2192 Git is SSH). When dirty, queues the worktree agent to commit; then wait_for_turn (loop while stillRunning). Pass a worktree thread ref (not the orchestrator). action=merge only when the user explicitly asked to merge that PR. Do not run git or gh from the orchestration cwd. If this tool errors that the GraphQL/PR body is too long, the branch is already pushed \u2014 have the worktree agent retry `gh pr create --body-file` with a short description (GitHub limit 65,536 characters). Do not invent SSH/auth failures from that error.",
24862
+ "Commit & push, open a draft PR, resolve conflicts, or merge \u2014 same actions as the desktop git buttons. When the worktree is clean, Sideboard pushes / opens the PR itself (HTTPS via `gh` even when origin is SSH / Settings \u2192 Git is SSH). When dirty, queues the worktree agent to commit; then wait_for_turn (loop while stillRunning). Do not start a checks loop on a plain push \u2014 only if the user gave a goal (Greptile 5/5, CI green). Pass a worktree thread ref (not the orchestrator). action=merge only when the user explicitly asked to merge that PR. Do not run git or gh from the orchestration cwd. If this tool errors that the GraphQL/PR body is too long, the branch is already pushed \u2014 have the worktree agent retry `gh pr create --body-file` with a short description (GitHub limit 65,536 characters). Do not invent SSH/auth failures from that error.",
24794
24863
  {
24795
24864
  ref: import_zod5.z.string().describe("Worktree thread id/ref"),
24796
24865
  action: import_zod5.z.enum(AGENT_GIT_ACTIONS).describe(
@@ -27600,10 +27669,12 @@ init_outbound_watch();
27600
27669
  CONTEXT_KEEP_RECENT_CHARS,
27601
27670
  CONTEXT_KEEP_RECENT_MESSAGES,
27602
27671
  CONTEXT_MIN_MESSAGES,
27672
+ CONTEXT_REVIEW_PATH,
27603
27673
  CONVENTION_SETUP_RELPATHS,
27604
27674
  COORDINATOR_TOOL_PLAYBOOK,
27605
27675
  DEFAULT_ABLETIME_HOST,
27606
27676
  DEFAULT_WORKTREE_SORT,
27677
+ DETACHED_JOBS_DIR,
27607
27678
  FAMOUS_SOCCER_TEAMS,
27608
27679
  FOLLOW_UP_BEHAVIORS,
27609
27680
  GITHUB_GIT_AUTH_MODES,
@@ -27614,6 +27685,7 @@ init_outbound_watch();
27614
27685
  HOME_BOARD_CACHE_TTL_MS,
27615
27686
  ISSUE_SOURCE_LABELS,
27616
27687
  LEGACY_ATTACHMENTS_DIR,
27688
+ LEGACY_DETACHED_JOBS_DIR,
27617
27689
  LEGACY_PLAN_FILE_REL,
27618
27690
  LEGACY_REVIEW_REQUEST_PATH,
27619
27691
  LINEAR_OAUTH_CANCELLED,
@@ -27804,6 +27876,7 @@ init_outbound_watch();
27804
27876
  ensureConnectedBrightsyTeamTokens,
27805
27877
  ensureGhPreferOrigin,
27806
27878
  ensureGlobalCoordinatorCwd,
27879
+ ensureReviewGuidelinesFile,
27807
27880
  ensureReviewRequestFile,
27808
27881
  ensureReviewSkillFile,
27809
27882
  ensureSlackCoordinator,
@@ -27853,6 +27926,7 @@ init_outbound_watch();
27853
27926
  formatOptionalServicesReminder,
27854
27927
  formatPlanQuestionAnswers,
27855
27928
  formatPlanQuestionsForChat,
27929
+ formatPrGateDirective,
27856
27930
  formatProcessGuideDirective,
27857
27931
  formatRateLimitResetHint,
27858
27932
  formatRenameBranchDirective,