mergestorm-mcp 0.2.9 → 0.2.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +21 -16
  2. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -537,6 +537,7 @@ async function reviewSubmit(input, cfg, opts = {}) {
537
537
  import {
538
538
  PrReviewPollTimeoutError,
539
539
  loadConfig as loadConfig5,
540
+ noPrReviewYetMessage,
540
541
  pollPrVortexReview
541
542
  } from "mergestorm/client";
542
543
 
@@ -648,20 +649,21 @@ async function reviewWaitPr(owner, repo, prNumber, afterSha, timeout_s, cfg, opt
648
649
  );
649
650
  } catch (err) {
650
651
  if (err instanceof PrReviewPollTimeoutError) {
651
- const status = "in_progress";
652
+ const status = err.reviewSeen ? "in_progress" : "none";
652
653
  const expectedSha = afterSha?.trim().toLowerCase() ?? "";
653
654
  const observedSha = err.lastEnvelope?.head_sha?.trim().toLowerCase() ?? "";
654
655
  const headShaMatches = Boolean(
655
656
  observedSha && expectedSha.length >= 7 && (observedSha.startsWith(expectedSha) || expectedSha.startsWith(observedSha))
656
657
  );
657
658
  const findingCount = headShaMatches ? err.lastEnvelope?.finding_count ?? null : null;
659
+ const summary = prReviewSummary(target.owner, target.repo, target.prNumber, {
660
+ status,
661
+ head_sha: err.lastEnvelope?.head_sha ?? null,
662
+ finding_count: findingCount,
663
+ phase: err.lastEnvelope?.phase ?? null
664
+ });
658
665
  return {
659
- summary: prReviewSummary(target.owner, target.repo, target.prNumber, {
660
- status,
661
- head_sha: err.lastEnvelope?.head_sha ?? null,
662
- finding_count: findingCount,
663
- phase: err.lastEnvelope?.phase ?? null
664
- }),
666
+ summary: err.reviewSeen ? summary : `${summary} \xB7 ${noPrReviewYetMessage(target.owner, target.repo, target.prNumber, { afterSha, pass: opts.pass, afterPass: opts.afterPass })}`,
665
667
  data: {
666
668
  status,
667
669
  head_sha: err.lastEnvelope?.head_sha ?? null,
@@ -791,10 +793,11 @@ function settingsPatchFromArgs(args) {
791
793
  const value = args[key];
792
794
  if (value === void 0) continue;
793
795
  const row = BEARER_SETTINGS.find((row2) => row2.key === key);
794
- if ("kind" in row && row.kind === "seconds") {
796
+ if ("kind" in row && (row.kind === "seconds" || row.kind === "count")) {
795
797
  if (typeof value !== "number" || !Number.isInteger(value) || value < row.min || value > row.max) {
798
+ const unit = row.kind === "seconds" ? " of seconds" : "";
796
799
  throw new CommandError8(
797
- `${key} takes a whole number of seconds from ${row.min} through ${row.max}.`,
800
+ `${key} takes a whole number${unit} from ${row.min} through ${row.max}.`,
798
801
  2,
799
802
  "usage"
800
803
  );
@@ -1139,19 +1142,21 @@ var MCP_STACK_WATCH_INSTRUCTIONS = [
1139
1142
  "- stack.autoEnqueueSettle with action ready or promote means Auto land found Cyclone and Vortex idle on that PR's green head and started its settle clock. action mergeability is published earlier, on a head that may not be green or idle yet.",
1140
1143
  "- mg-park-* is a frozen GitHub base, not a repair target: never merge or rebase onto mg-park-*.",
1141
1144
  "- merge_failed, gh_error, and ci_timeout bounces turn Auto land off, and stack autoLandOff then reads reason bounced with that queue entry's id; any other autoLandOff reason (user, archive, watcher, cancelled, landed) is not a bounce to undo. The watching agent turns Auto land back on with stack_set auto_land: true once it has handled that bounce, at most once per bounce and 3 times per watch; mergestorm-bounce-watch has the conditions.",
1145
+ `- A stack whose layers are all merged into mg-stack-N but which has no open land PR (the branch was deleted, or the land PR cannot be opened) returns attention: blocker "No open land PR for mg-stack-N ...", repair kind land_pr_unavailable. Do not patch or push; tell the human to restore the branch from the closed land PR's head or close the stack.`,
1142
1146
  '- While stack autoLandOff reads reason bounced, the watch returns attention: blocker "Auto land off after <kind> bounce", the bounce in issues[], repair kind auto_land_off.',
1143
1147
  '- A stack whose review unit was abandoned (a human moved its bottom PR off mg-stack-N) returns attention: blocker "Review unit abandoned: based on <base>", repair kind unit_abandoned. Do not patch or retarget; ask the human whether to re-root it. If at least two PRs remain open, tell them that mg stack adopt owner/repo#<bottom PR> re-roots it on a new review unit. With only one open PR, re-adopting will not create a review unit, so tell them to close and resubmit it to create a fresh stack.',
1144
- '- Auto land records why it is waiting (stack autoLandWait: reason, prNumber, headSha, since). The watch returns attention on that PR when the wait cannot clear on its own: a failing check Auto land reads live on GitHub, even while the ledger shows CI green (blocker "CI failed \u2014 Auto land reads a failing check on GitHub at this head", repair kind ci_failure); a check pending for 45 minutes (repair kind ci_pending); no approving Vortex review for 30 minutes with no Vortex run working (repair kind vortex_not_green); and a promote GitHub refused 3 times with merge_failed, after which Auto land stops retrying that head (repair kind promote_failed). A more specific blocker on that PR is named first. A new head clears the wait.',
1145
- `- While the stack has a live merge queue entry, stack_wait carries queueWait (the entry's wait reason, how long it has been held, and the stack queued ahead of it) and the status line names it. The watch returns attention, blocker "Merge queue stuck: ..." and repair kind queue_stalled, when the entry (or the entry ahead of it) has been held for 45 minutes without landing or bouncing.`,
1148
+ `- Auto land records why it is waiting (stack autoLandWait: reason, prNumber, headSha, since). The watch returns attention on that PR when the wait cannot clear on its own: a failing check Auto land reads live on GitHub, even while the ledger shows CI green (blocker "CI failed \u2014 Auto land reads a failing check on GitHub at this head", repair kind ci_failure); a check pending for 45 minutes (repair kind ci_pending); no approving Vortex review for 30 minutes with no Vortex run working (repair kind vortex_not_green); and a promote GitHub refused 3 times with merge_failed, after which Auto land stops retrying that head (repair kind promote_failed). It also returns attention when GitHub refuses to let Mergestorm read the head's check runs or commit statuses (blocker "Mergestorm cannot read ... on this head", repair kind ci_unreadable: do not patch or push; tell the human to grant the Mergestorm GitHub App the permission the repair names), and when any other wait reason has held for 45 minutes, a land gate left pending or running on the land PR included (blocker "Auto land has waited <N>m: <reason in plain words>", repair kind auto_land_waiting: read stack_status, fix what a commit on the named branch can fix, otherwise tell the human what Auto land waits for and since when). A more specific blocker on that PR is named first. A new head clears the wait.`,
1149
+ `- While the stack has a live merge queue entry, stack_wait carries queueWait (the entry's wait reason, how long it has been held, and the stack queued ahead of it) and the status line names it. The watch returns attention, blocker "Merge queue stuck: ..." and repair kind queue_stalled, when the entry (or the entry ahead of it) has been held for 45 minutes without landing or bouncing, or has sat queued for 45 minutes with nothing working on it or ahead of it.`,
1146
1150
  '- When no Vortex run works on the head and its review was skipped because auto-review is off (blocker "Vortex auto-review is off, so this head was not reviewed") or because billing could not be confirmed ("Vortex skipped this head: it could not confirm billing"), or it covered only part of the PR ("Vortex reviewed only part of this PR"), the watch returns attention at once with repair kind vortex_skipped. Do not patch for it; the repair names the mention or setting that gets the head reviewed.',
1147
1151
  '- A live-head Vortex request_changes handoff returns attention with blocker "Vortex findings need a person" and repair kind vortex_findings; verify the review and inline findings against the live head before repair.',
1148
1152
  "- Tempest never patches. Cyclone patches a land PR when auto-patch is on for that stack (its override, else the account setting); otherwise the watching agent fixes tempest_findings on the land PR, and repair kind tempest_findings names it. A Tempest run that breaks without a result is re-run by Mergestorm at the same head a few times; after that the land gate reads tempest_failed with repair kind tempest_rerun: there is nothing to patch, so re-run Tempest with the comment the repair names. tempest_stopped (a person stopped the review) also carries repair kind tempest_rerun: ask the human before re-running it.",
1153
+ '- More states the watch names: a Vortex review skipped because the PR author is on the ignored authors list or because reviews are turned off for the repository is attention at once with repair kind vortex_skipped; a Vortex retry that is scheduled ("Vortex hit a temporary error on this head and will retry by itself") is a wait listed in issues[], never attention; "Review failed" carries repair kind vortex_failed (comment @mergestorm-vortex review or push a new commit; if it fails again tell the human); a PR open on mg-stack-N that is not a layer of the stack is attention at once, blocker "The land PR cannot be queued: ...", repair kind members_remaining (do not patch or push; close, retarget or adopt that PR); tempest_skipped on the land PR carries repair kind tempest_rerun (comment @mergestorm-tempest review); tempest_trigger_failed carries repair kind tempest_trigger_failed (Mergestorm keeps trying every 5 minutes; nothing to fix in the PR; if it stays, tell the human).',
1149
1154
  "- Use the mergestorm-bounce-watch skill for the fix-then-watch policy."
1150
1155
  ].join("\n");
1151
1156
 
1152
1157
  // src/server.ts
1153
1158
  var MCP_SERVER_NAME = "mergestorm";
1154
- var MCP_SERVER_VERSION = "0.2.9";
1159
+ var MCP_SERVER_VERSION = "0.2.11";
1155
1160
  var MCP_SERVER_INSTRUCTIONS = [
1156
1161
  MCP_STACK_DONE_INSTRUCTIONS,
1157
1162
  MCP_PR_LOOP_INSTRUCTIONS,
@@ -1298,7 +1303,7 @@ function createMergestormMcpServer() {
1298
1303
  "review_wait_pr",
1299
1304
  {
1300
1305
  title: "Wait for GitHub PR Vortex review",
1301
- description: "Read the Vortex pass on a GitHub PR from the DB-only endpoint; review identity is head SHA + pass. timeout_s: 0 reads it once without polling; otherwise it polls for one 45s slice by default (max 300) and returns in_progress on timeout so you can call again. Pass after_sha for the head you pushed and pass to read one exact attempt; when you already hold a resting envelope for that head, also pass after_pass set to its pass and keep it unchanged across retries; never replace it with the pass of an in-progress envelope, and omit after_pass for a head you hold no envelope for. With timeout_s: 0, a pass that does not exist yet returns not_found, so after a push use a positive timeout. Do not pass 300; hosts drop long MCP calls. On rate_limited, wait retry_after_seconds before trying again. After a resting pass, verify each finding; prefer the smallest correct patch; if you skip, post a PR comment starting with mergestorm-loop: dismiss.",
1306
+ description: "Read the Vortex pass on a GitHub PR from the DB-only endpoint; review identity is head SHA + pass. timeout_s: 0 reads it once without polling; otherwise it polls for one 45s slice by default (max 300) and returns in_progress on timeout so you can call again, or none when no review exists for that PR and head yet (call once more; if it is none again, Vortex is not reviewing that head: comment @mergestorm-vortex review on the PR, run mg review, or push a new commit). Pass after_sha for the head you pushed and pass to read one exact attempt; when you already hold a resting envelope for that head, also pass after_pass set to its pass and keep it unchanged across retries; never replace it with the pass of an in-progress envelope, and omit after_pass for a head you hold no envelope for. With timeout_s: 0, a pass that does not exist yet returns not_found, so after a push use a positive timeout. Do not pass 300; hosts drop long MCP calls. On rate_limited, wait retry_after_seconds before trying again. After a resting pass, verify each finding; prefer the smallest correct patch; if you skip, post a PR comment starting with mergestorm-loop: dismiss.",
1302
1307
  inputSchema: {
1303
1308
  owner: z3.string().min(1),
1304
1309
  repo: z3.string().min(1),
@@ -1470,7 +1475,7 @@ function createMergestormMcpServer() {
1470
1475
  "settings_get",
1471
1476
  {
1472
1477
  title: "Get settings",
1473
- description: "Read the Bearer /api/v1/settings toggles, including auto_patch_enabled, auto_land_settle_seconds (how long Auto land waits before queueing), and cyclone_connected.",
1478
+ description: "Read the Bearer /api/v1/settings toggles, including auto_patch_enabled, auto_land_settle_seconds (how long Auto land waits before queueing), merge_queue_batch_enabled and merge_queue_batch_size (whether the merge queue tests several pull requests on one CI run, and how many), and cyclone_connected.",
1474
1479
  annotations: { readOnlyHint: true }
1475
1480
  },
1476
1481
  async () => {
@@ -1485,12 +1490,12 @@ function createMergestormMcpServer() {
1485
1490
  "settings_set",
1486
1491
  {
1487
1492
  title: "Update settings",
1488
- description: "Update writable Bearer /api/v1/settings values and return the stored result. At least one key is required. auto_land_settle_seconds is a whole number of seconds from 15 through 300; it applies to settle clocks that start after the write. cyclone_connected and github_connected are read-only and cannot be set.",
1493
+ description: "Update writable Bearer /api/v1/settings values and return the stored result. At least one key is required. auto_land_settle_seconds is a whole number of seconds from 15 through 300; it applies to settle clocks that start after the write. merge_queue_batch_enabled turns merge queue batching on or off for the account, and merge_queue_batch_size is a whole number from 2 through 8. cyclone_connected and github_connected are read-only and cannot be set.",
1489
1494
  inputSchema: {
1490
1495
  ...Object.fromEntries(
1491
1496
  BEARER_SETTINGS2.map((row) => [
1492
1497
  row.key,
1493
- ("kind" in row ? row.kind === "logins" ? z3.array(z3.string()) : row.kind === "seconds" ? z3.number().int().min(row.min).max(row.max) : z3.enum(row.values) : z3.boolean()).optional()
1498
+ ("kind" in row ? row.kind === "logins" ? z3.array(z3.string()) : row.kind === "seconds" || row.kind === "count" ? z3.number().int().min(row.min).max(row.max) : z3.enum(row.values) : z3.boolean()).optional()
1494
1499
  ])
1495
1500
  ),
1496
1501
  // Preserve these args so the handler rejects them even alongside a writable key.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mergestorm-mcp",
3
- "version": "0.2.9",
3
+ "version": "0.2.11",
4
4
  "description": "Mergestorm MCP server — identity, review, and read-only stack tools over stdio",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -29,7 +29,7 @@
29
29
  },
30
30
  "dependencies": {
31
31
  "@modelcontextprotocol/sdk": "^1.30.0",
32
- "mergestorm": "0.3.36",
32
+ "mergestorm": "0.3.39",
33
33
  "zod": "^3.24.2"
34
34
  },
35
35
  "devDependencies": {