mergestorm-mcp 0.2.2 → 0.2.4

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.
package/README.md CHANGED
@@ -22,7 +22,9 @@ The stack tools expose reads plus one scoped policy write:
22
22
  - `stack_list` returns the current API key owner's registered stacks.
23
23
  - `stack_set({ stack_id, auto_land?, auto_review?, auto_patch? })` sets per-stack policy on one owned stack. `auto_land` flips Auto land. `auto_review` and `auto_patch` pin Vortex auto-review or Cyclone auto-patch for that stack in either direction (`true` or `false`); `null` clears the pin so the stack follows the account setting. Pass at least one key. Account settings are never changed here.
24
24
  - `stack_status({ stack_id })` returns one owned stack with enriched checks and agent state, plus `attention`, `issues`, and `currentCandidate` from the same blocker rules as `stack_wait`, read against that stack's own merge queue. It returns a structured `stack_not_found` or `rate_limited` error.
25
- - `stack_wait({ stack_id, timeout_s?, enrolled_head_sha?, after_finished_at?, bounce_id? })` waits for a stack or queue state change and returns the latest snapshots. `timeout_s: 0` returns one snapshot; a positive timeout after a snapshot with no attention returns the current `waiting` or `in_progress` status with selectors to use for the next call. An unread deadline returns `failed`. While Cyclone or Vortex is still working on the blocked PR, `stack_wait` and `stack_status` return `in_progress` instead of `attention`, with `busy[]` naming the PR, blocker, and agent, and `agents` carrying that PR's `vortexStatus`, `cycloneStatus`, `vortexReview`, and busy flags. A nonempty `busy[]` means wait. A queued Vortex run holds for at most 15 minutes, `seam_pending` alone does not hold, and reviewing or patching holds until the run finishes or its lease or check run is cleared. A blocker no agent run clears (a merge conflict vs the live parent, a restack `Conflict` or `Restack failed`, a Draft PR) is still named during that `in_progress`, in `blocker`, `prNumber`, `headSha`, and `issues[]`, with `actAfter: "agents_idle"` and `waitingOn` listing the busy agents; act when a snapshot after the agents finish returns `attention`, re-reading the blocker then. `repair` is included when a concrete repair hint is available. Blockers the agents can change keep `blocker` and `actAfter` null. If a hold looks stuck, refresh `stack_status` and tell the human.
25
+ - `stack_wait({ stack_id, timeout_s?, enrolled_head_sha?, after_finished_at?, bounce_id? })` waits for a stack or queue state change and returns the latest snapshots. `timeout_s: 0` returns one snapshot; a positive timeout after a snapshot with no attention returns the current `waiting` or `in_progress` status with selectors to use for the next call. An unread deadline returns `failed`. While Cyclone or Vortex is still working on the blocked PR, `stack_wait` and `stack_status` return `in_progress` instead of `attention`, with `busy[]` naming the PR, blocker, and agent, and `agents` carrying that PR's `vortexStatus`, `cycloneStatus`, `vortexReview`, and busy flags. A nonempty `busy[]` means wait. A queued Vortex run holds for at most 15 minutes, `seam_pending` alone does not hold, and reviewing or patching holds until the run finishes or its lease or check run is cleared. A blocker no agent run clears (a merge conflict vs the live parent, a restack `Conflict` or `Restack failed`, a Draft PR, a seam review pending with no review running) is still named during that `in_progress`, in `blocker`, `prNumber`, `headSha`, and `issues[]`, with `actAfter: "agents_idle"` and `waitingOn` listing the busy agents; act when a snapshot after the agents finish returns `attention`, re-reading the blocker then. `repair` is included when a concrete repair hint is available. Blockers the agents can change keep `blocker` and `actAfter` null. If a hold looks stuck, refresh `stack_status` and tell the human.
26
+
27
+ Agents that cannot hold a long turn open should not poll `stack_wait` inside their turn. The server instructions tell them to run `mg stack watch <stack-id>` from the `mergestorm` CLI as a background command, notify on output matching `MS-WATCH (ATTENTION|LANDED)`, and end the turn. The watcher loops the same stack wait against the Mergestorm API with the cursor, stays silent while the stack is waiting or in progress, and exits on attention (exit 3), a failed read that failed again on retry (exit 3), or a finished watch (exit 0). On wake the agent reads `stack_status` once, fixes the blocker, pushes, and restarts the watcher with `--head <pushed-sha>`. The stack is still not done until it lands. Agents are told not to subscribe to GitHub events to wait on a stack.
26
28
 
27
29
  Auth is `MERGESTORM_API_KEY`, then `~/.mergestorm/config.json` (same as `mg`).
28
30
 
package/dist/index.js CHANGED
@@ -1101,14 +1101,16 @@ var MCP_PR_LOOP_INSTRUCTIONS = [
1101
1101
  var MCP_STACK_DONE_INSTRUCTIONS = [
1102
1102
  "When stack work is done:",
1103
1103
  "- Stack work is done only when the stack is landed, or when the human takes it back (archives it or tells you to stop). A clean push, a submit, an adopt, or one merged layer is not done: merging a lower layer can break a layer above it.",
1104
- "- Every stack_wait, stack_status, stack_adopt, and stack_set result carries watch: {done, until, reason, next, message}. While watch.done is false, keep calling stack_wait with watch.next.args (the returned cursor), 45s at a time, and do not end your task. Stop only when watch.done is true.",
1104
+ "- Every stack_wait, stack_status, stack_adopt, and stack_set result carries watch: {done, until, reason, next, message}. While watch.done is false, keep calling stack_wait with watch.next.args (the returned cursor), 45s at a time, or hand the waiting to the background watcher below, and do not end your task. Stop only when watch.done is true.",
1105
+ "- If your host cannot hold a long turn open (Cursor, Claude Code, Codex, and other turn-based agents), do not poll stack_wait inside your turn: run `mg stack watch <stack-id>` as a background command with a notification on output matching `MS-WATCH (ATTENTION|LANDED)`, then end your turn. The watcher runs stack_wait against the Mergestorm API in slices of at most 300s, carries the cursor, stays silent while the stack is waiting or in_progress (busy[] holds and actAfter included), and costs no model tokens. It exits on attention (`MS-WATCH ATTENTION pr=<n> head=<sha> blocker=... repair=<kind>`, exit 3), on a read that failed twice (`MS-WATCH ATTENTION failed`, exit 3; tell the human the stack is no longer watched), or when watch.done is true (`MS-WATCH LANDED stack=<id> reason=<reason>`, exit 0; only reason=landed is landed). On an attention wake, read stack_status once, fix the blocker per mergestorm-bounce-watch, push, and start `mg stack watch <stack-id> --head <pushed-sha>` again. Ending your turn while the watcher runs is not ending the task. Do not subscribe to GitHub events to wait on a stack.",
1106
+ "- A layer PR shown as merged is merged into mg-stack-<n>, not main. The stack is landed only when the land PR (head mg-stack-<n>) merges into main or watch.done says landed. Never judge landing from GitHub PR state alone.",
1105
1107
  "- attention means something for you to fix; repair, when present, names the concrete fix. A pending land gate (landGatePending: ci_pending, tempest_pending, tempest_running) is a wait, not attention."
1106
1108
  ].join("\n");
1107
1109
  var MCP_STACK_BASE_INSTRUCTIONS = [
1108
1110
  "Stack PR bases (Mergestorm sets these; leave them):",
1109
1111
  "- Stack of 2+ PRs: after adopt (stack_adopt, mg stack adopt, or mg stack submit) the bottom PR's GitHub base is the owned trunk mg-stack-<n>, not main. That is correct. Layer 2 is based on layer 1; layer 3+ on the mg-park-* freeze; the git parent of layer 2+ is still the layer below. A 1-PR stack stays on main and gets no mg-stack-<n>.",
1110
1112
  "- Never retarget a stack PR's GitHub base (gh pr edit --base, a REST base change, or the UI). Moving the bottom to main makes Mergestorm abandon the stack's review unit; setting mg-stack-<n> again does not restore it. If a base was already moved, stop and tell the human; do not run stack land or re-adopt to repair it.",
1111
- "- mg-stack-<n> is the bottom PR's live parent: merging it into the bottom branch is that PR's conflict repair (bounce-watch rules). Never push to mg-stack-<n> except as the land PR's own repair: once every layer is promoted, the land PR's head is mg-stack-<n> and its live parent is its base (main), so merging main into mg-stack-<n>, or a CI fix on it, with an ordinary push (no force) is that repair. Never rebase or merge layer 2+ onto mg-stack-<n> or onto main. mg-park-* is never a merge or rebase target.",
1113
+ "- mg-stack-<n> is the bottom PR's live parent: merging it into the bottom branch is that PR's conflict repair (bounce-watch rules). Never push to mg-stack-<n> except as the land PR's own repair: once every layer is promoted, the land PR's head is mg-stack-<n> and its live parent is its base (main), so merging main into mg-stack-<n>, a CI fix on it, or a fix for tempest_findings on it, with an ordinary push (no force) is that repair. Fix tempest_findings only when busy[] shows no Cyclone run on the land PR, and verify each finding first, as for Vortex findings. Never rebase or merge layer 2+ onto mg-stack-<n> or onto main. mg-park-* is never a merge or rebase target.",
1112
1114
  "- mg stack submit prints the base each PR opened with; the bottom moves to mg-stack-<n> right after. stack_status trunkBranch is the current trunk."
1113
1115
  ].join("\n");
1114
1116
  var MCP_STACK_WATCH_INSTRUCTIONS = [
@@ -1120,15 +1122,18 @@ var MCP_STACK_WATCH_INSTRUCTIONS = [
1120
1122
  "- verifyHeadSha is a queue verification SHA, not the live PR head.",
1121
1123
  "- Do not patch a bounced PR while Cyclone or Vortex is still working on it. stack_wait and stack_status enforce this: they return in_progress instead of attention, with busy[] naming the PR, blocker, and agent, and agents carrying that PR's vortexStatus, cycloneStatus, vortexReview, and busy flags. in_progress with a nonempty busy[] means wait. Recheck the live remote PR head right before pushing.",
1122
1124
  "- seam_pending alone, and a queued Vortex run older than 15 minutes, do not hold. A queued Vortex run holds for at most 15 minutes; reviewing and patching hold until the run finishes or its lease or check run is cleared; if it looks stuck, refresh stack_status and tell the human.",
1123
- '- A blocker no Vortex or Cyclone run clears (a merge conflict vs the live parent, a restack Conflict or Restack failed, a Draft PR) stays in_progress during the hold but is named in blocker, prNumber, headSha, and issues[], with actAfter: "agents_idle" and waitingOn listing the busy agents. Plan the fix; act only when a snapshot after the agents finish returns attention, and re-read the blocker then. Blockers the agents can change keep blocker null and appear only in busy[].',
1125
+ '- A blocker no Vortex or Cyclone run clears (a merge conflict vs the live parent, a restack Conflict or Restack failed, a Draft PR, a seam review pending with no review running, or a review skipped for review quota) stays in_progress during the hold but is named in blocker, prNumber, headSha, and issues[], with actAfter: "agents_idle" and waitingOn listing the busy agents. Plan the fix; act only when a snapshot after the agents finish returns attention, and re-read the blocker then. Blockers the agents can change keep blocker null and appear only in busy[].',
1124
1126
  "- 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.",
1125
1127
  "- mg-park-* is a frozen GitHub base, not a repair target: never merge or rebase onto mg-park-*.",
1128
+ "- 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.",
1129
+ '- 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.',
1130
+ "- 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.",
1126
1131
  "- Use the mergestorm-bounce-watch skill for the fix-then-watch policy."
1127
1132
  ].join("\n");
1128
1133
 
1129
1134
  // src/server.ts
1130
1135
  var MCP_SERVER_NAME = "mergestorm";
1131
- var MCP_SERVER_VERSION = "0.2.2";
1136
+ var MCP_SERVER_VERSION = "0.2.4";
1132
1137
  var MCP_SERVER_INSTRUCTIONS = [
1133
1138
  MCP_STACK_DONE_INSTRUCTIONS,
1134
1139
  MCP_PR_LOOP_INSTRUCTIONS,
@@ -1394,7 +1399,7 @@ function createMergestormMcpServer() {
1394
1399
  "stack_status",
1395
1400
  {
1396
1401
  title: "Get stack status",
1397
- description: "Fetch one owned Mergestorm stack with enriched checks and agent state, plus attention, issues, and currentCandidate from the same blocker rules as stack_wait, read against that stack's own merge queue. trunkBranch is mg-stack-<n> for an adopted 2+ PR stack and matches the bottom open PR's GitHub base; an mg-park-* parentBranch is a freeze. Neither is drift to fix. repair names the concrete fix for attention; landGatePending is a wait, not attention. held names a blocker no agent run clears while Vortex or Cyclone is still busy on that PR (actAfter agents_idle, waitingOn); repair then describes the fix to plan, not to apply yet." + STACK_WATCH_RESULT_NOTE,
1402
+ description: `Fetch one owned Mergestorm stack with enriched checks and agent state, plus attention, issues, and currentCandidate from the same blocker rules as stack_wait, read against that stack's own merge queue. trunkBranch is mg-stack-<n> for an adopted 2+ PR stack and matches the bottom open PR's GitHub base; an mg-park-* parentBranch is a freeze. Neither is drift to fix. repair names the concrete fix for attention; landGatePending is a wait, not attention. held names a blocker no agent run clears while Vortex or Cyclone is still busy on that PR (actAfter agents_idle, waitingOn); repair then describes the fix to plan, not to apply yet. Auto land off after a merge_failed, gh_error, or ci_timeout bounce (the stack's autoLandOff reads reason bounced) returns attention with the blocker "Auto land off after <kind> bounce", the bounce in issues[], and a repair of kind auto_land_off: fix the cause, then turn Auto land back on or enqueue.` + STACK_WATCH_RESULT_NOTE,
1398
1403
  inputSchema: {
1399
1404
  stack_id: z3.string().min(1)
1400
1405
  },
@@ -1412,7 +1417,7 @@ function createMergestormMcpServer() {
1412
1417
  "stack_wait",
1413
1418
  {
1414
1419
  title: "Wait for stack attention",
1415
- description: `Wait for a stack to need attention. Returns a mergestorm.stack_watch/v1 envelope; timeout_s: 0 returns one snapshot and timeout_s: 1-45 waits up to that many seconds, returning the current status (waiting or in_progress) if a snapshot was read and no attention is found. A timeout with either of those statuses is not a failure; waiting and in_progress end this slice, and the next call is stack_wait again with the same cursor. A timeout of failed means no assessment was produced. A stack that no longer exists returns status failed with watch.done true (reason not_found) and is not an error. While Cyclone or Vortex is still working on the blocked PR it returns in_progress, not attention, with busy[] naming the PR, blocker, and agent; agents carries that PR's vortexStatus, cycloneStatus, vortexReview, and busy flags. A blocker no agent run clears (a merge conflict vs the live parent, a restack Conflict or Restack failed, a Draft PR) is still named during that in_progress, in blocker, prNumber, headSha, and issues[], with actAfter: "agents_idle" and waitingOn listing the busy agents: plan the fix, and act when a snapshot after the agents finish returns attention, re-reading the blocker then. Blockers the agents can change keep blocker and actAfter null. Attention never calls for changing a PR's GitHub base. When present, repair names the concrete fix for attention (restack_conflict and merge_conflict carry liveParent, never mg-park-*). A pending land gate (landGatePending) returns in_progress, not attention.` + STACK_WATCH_RESULT_NOTE,
1420
+ description: `Wait for a stack to need attention. Returns a mergestorm.stack_watch/v1 envelope; timeout_s: 0 returns one snapshot and timeout_s: 1-45 waits up to that many seconds, returning the current status (waiting or in_progress) if a snapshot was read and no attention is found. A timeout with either of those statuses is not a failure; waiting and in_progress end this slice, and the next call is stack_wait again with the same cursor. A timeout of failed means no assessment was produced. A stack that no longer exists returns status failed with watch.done true (reason not_found) and is not an error. While Cyclone or Vortex is still working on the blocked PR it returns in_progress, not attention, with busy[] naming the PR, blocker, and agent; agents carries that PR's vortexStatus, cycloneStatus, vortexReview, and busy flags. A blocker no agent run clears (a merge conflict vs the live parent, a restack Conflict or Restack failed, a Draft PR, a seam review pending with no review running, or a review skipped for review quota) is still named during that in_progress, in blocker, prNumber, headSha, and issues[], with actAfter: "agents_idle" and waitingOn listing the busy agents: plan the fix, and act when a snapshot after the agents finish returns attention, re-reading the blocker then. Blockers the agents can change keep blocker and actAfter null. Attention never calls for changing a PR's GitHub base. When present, repair names the concrete fix for attention (restack_conflict and merge_conflict carry liveParent, never mg-park-*). A pending land gate (landGatePending) returns in_progress, not attention. Auto land off after a merge_failed, gh_error, or ci_timeout bounce (the stack's autoLandOff reads reason bounced) returns attention with the blocker "Auto land off after <kind> bounce", the bounce in issues[], and a repair of kind auto_land_off: fix the cause, then turn Auto land back on or enqueue.` + STACK_WATCH_RESULT_NOTE,
1416
1421
  inputSchema: stackWaitSchema,
1417
1422
  annotations: { readOnlyHint: true }
1418
1423
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mergestorm-mcp",
3
- "version": "0.2.2",
3
+ "version": "0.2.4",
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.27",
32
+ "mergestorm": "0.3.29",
33
33
  "zod": "^3.24.2"
34
34
  },
35
35
  "devDependencies": {