mergestorm 0.3.58 → 0.3.59

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
@@ -45,12 +45,12 @@ On a TTY, bare `mergestorm` (or `mergestorm shell`) opens a branded REPL: a comp
45
45
 
46
46
  ```
47
47
  ╭──────────────────────────────────────────────────────────────────────────────╮
48
- │ ▀▀▀▀▀▀▀▀▀▀▘ mergestorm v0.3.58 │
48
+ │ ▀▀▀▀▀▀▀▀▀▀▘ mergestorm v0.3.59 │
49
49
  │ ▀▀▀▀▀▀▀▀▀ ● msk_live_… · maelstrom │
50
50
  │ ▀▀▀▀▀▀ [████████░░░░░░░░░░░░░░░░░░░░░░] 25% used │
51
51
  │ ▝▀▀▀▀▀ local reviews + stacked PRs · mergestorm.ai │
52
52
  │ ▝▀▀▘ review a diff · usage for tabs · /help for all commands │
53
- │ ▀ New in v0.3.58: Watch reports Auto land switched off │
53
+ │ ▀ New in v0.3.59: One-shot stack wait rides out a slow read │
54
54
  ╰──────────────────────────────────────────────────────────────────────────────╯
55
55
  mergestorm
56
56
  ╭──────────────────────────────────────────────────────────────────────────────╮
@@ -1,4 +1,4 @@
1
- import { CYCLONE_FIX_HELD_REASON, deriveStackAgentsBusy, mergeQueueBounceLabel, restackRetryPending, } from "./stack-dto.js";
1
+ import { CYCLONE_CI_FIX_HELD_REASON, CYCLONE_FIX_HELD_REASON, deriveStackAgentsBusy, mergeQueueBounceLabel, restackRetryPending, } from "./stack-dto.js";
2
2
  export function landGateIsPending(reason) {
3
3
  const token = reason?.trim().replace(/^landing blocked:\s*/i, "").match(/^[a-z_]+/i)?.[0] ?? "";
4
4
  return /_(?:pending|running)$/i.test(token);
@@ -108,13 +108,15 @@ const CYCLONE_HANDOFF_WORDS = {
108
108
  ci_unverified: "Cyclone's static checks did not cover its fix, so it pushed nothing",
109
109
  ci_unreadable: "Cyclone could not read the failing checks",
110
110
  ci_needs_actions_read: "Cyclone's GitHub App cannot read the Actions logs on this repo",
111
+ ci_fix_held: "Cyclone wrote a CI fix and held it on purpose, so it pushed nothing",
111
112
  ci_unresolved: "Cyclone's CI fix failed",
112
113
  stack_auto_fix_ci_off: "auto-fix CI is off for this stack",
113
114
  account_auto_fix_ci_off: "auto-fix CI is off for the account and this stack does not turn it on",
114
115
  };
115
116
  function cycloneHandoffWords(reason, detail) {
116
117
  const words = CYCLONE_HANDOFF_WORDS[reason] ?? reason.replaceAll("_", " ");
117
- return reason === CYCLONE_FIX_HELD_REASON && detail?.trim() ? `${words}: ${detail.trim()}` : words;
118
+ const held = reason === CYCLONE_FIX_HELD_REASON || reason === CYCLONE_CI_FIX_HELD_REASON;
119
+ return held && detail?.trim() ? `${words}: ${detail.trim()}` : words;
118
120
  }
119
121
  export function cycloneStatusWords(layer) {
120
122
  if (!layer.cycloneStatus)
@@ -161,7 +163,7 @@ function ciHandoffNote(stack, layer) {
161
163
  return null;
162
164
  const handoff = layer.cycloneCiHandoff;
163
165
  if (handoff && sameHead(handoff.headSha, layer.headSha)) {
164
- return `Cyclone tried to fix this failing CI at ${layer.headSha ?? handoff.headSha} and left it for a person (${cycloneHandoffWords(handoff.reason)}), so it will not try this head again.`;
166
+ return `Cyclone tried to fix this failing CI at ${layer.headSha ?? handoff.headSha} and left it for a person (${cycloneHandoffWords(handoff.reason, handoff.detail)}), so it will not try this head again.`;
165
167
  }
166
168
  if (stack.cycloneCiOff) {
167
169
  return `Cyclone will not fix this failing CI by itself: ${cycloneHandoffWords(stack.cycloneCiOff)}.`;
@@ -66,6 +66,7 @@ export type StackVortexReviewView = {
66
66
  };
67
67
  export type StackCycloneStatus = "patching" | "awaiting_fix" | "held" | "failed";
68
68
  export declare const CYCLONE_FIX_HELD_REASON = "fix_held";
69
+ export declare const CYCLONE_CI_FIX_HELD_REASON = "ci_fix_held";
69
70
  export type StackCycloneHandoff = {
70
71
  headSha: string;
71
72
  reason: string;
@@ -172,7 +173,7 @@ export type StackLayerConflictResolution = {
172
173
  */
173
174
  dispatchId: string | null;
174
175
  };
175
- export type StackLayerCiFixStatus = "verified" | "unverified" | "no_changes" | "failed";
176
+ export type StackLayerCiFixStatus = "verified" | "unverified" | "no_changes" | "held" | "failed";
176
177
  export type StackLayerCiFix = {
177
178
  status: StackLayerCiFixStatus;
178
179
  failingCheck: string | null;
@@ -440,7 +441,7 @@ export type MergeQueueBounceBatch = {
440
441
  withPrNumbers: number[];
441
442
  };
442
443
  export type MergeQueueBatchState = "verifying" | "landing" | "landed" | "stopped" | "bounced" | "abandoned";
443
- export type MergeQueueBatchCiCheckState = "passed" | "skipped" | "failed" | "running" | "queued";
444
+ export type MergeQueueBatchCiCheckState = "passed" | "skipped" | "cancelled" | "failed" | "running" | "queued";
444
445
  export type MergeQueueBatchCiCheckDto = {
445
446
  name: string;
446
447
  state: MergeQueueBatchCiCheckState;
package/dist/stack-dto.js CHANGED
@@ -24,6 +24,7 @@ export function restackRetryPending(error, layer) {
24
24
  */
25
25
  export const AUTO_LAND_OFF_REASONS = ["user", "archive", "watcher", "cancelled", "landed", "bounced"];
26
26
  export const CYCLONE_FIX_HELD_REASON = "fix_held";
27
+ export const CYCLONE_CI_FIX_HELD_REASON = "ci_fix_held";
27
28
  export const STACK_AGENT_QUEUED_STALE_MS = 15 * 60 * 1000;
28
29
  export const AUTO_RESOLVE_ENQUEUE_GRACE_MS = 2 * 60_000;
29
30
  function agentShaMayBeHead(sha, head) {
@@ -5,6 +5,8 @@ import type { Config } from "./config.js";
5
5
  export declare const STACK_WATCH_SCHEMA: "mergestorm.stack_watch/v1";
6
6
  export declare const STACK_WATCH_DEFAULT_TIMEOUT_MS = 45000;
7
7
  export declare const STACK_WATCH_BUSY_RECHECK_S = 15;
8
+ export declare const STACK_WATCH_ONE_SHOT_READ_TIMEOUT_MS = 30000;
9
+ export declare const STACK_WATCH_DEADLINE_SNAPSHOT_TIMEOUT_MS = 5000;
8
10
  /** Resume selectors are fixed for the entire wait, including transient retries. */
9
11
  export type StackWatchCursor = {
10
12
  readonly stackId: string;
@@ -1,11 +1,13 @@
1
1
  import { currentLayer, layerAgents, stackBlockers, } from "./stack-blockers.js";
2
2
  import { stackTerminalReason, stackWatchObligation, } from "./stack-watch-obligation.js";
3
3
  import { setTimeout as sleep } from "node:timers/promises";
4
- import { apiFetch } from "./api.js";
4
+ import { apiFetch, DEFAULT_API_TIMEOUT_MS } from "./api.js";
5
5
  import { REVIEW_POLL_INTERVAL_MS, REVIEW_POLL_MAX_TRANSIENT_RETRIES, isTransientReviewPollError, isTransientReviewPollStatus, transientRetryWaitMs, } from "./commands/review-client.js";
6
6
  export const STACK_WATCH_SCHEMA = "mergestorm.stack_watch/v1";
7
7
  export const STACK_WATCH_DEFAULT_TIMEOUT_MS = 45_000;
8
8
  export const STACK_WATCH_BUSY_RECHECK_S = 15;
9
+ export const STACK_WATCH_ONE_SHOT_READ_TIMEOUT_MS = DEFAULT_API_TIMEOUT_MS;
10
+ export const STACK_WATCH_DEADLINE_SNAPSHOT_TIMEOUT_MS = 5_000;
9
11
  export class StackWatchTimeoutError extends Error {
10
12
  lastEnvelope;
11
13
  constructor(lastEnvelope) {
@@ -77,7 +79,9 @@ export async function pollStackWatch(cfg, stackId, opts = {}) {
77
79
  response = await fetch(cfg, route, {
78
80
  signal: opts.signal, timeoutMs: route.includes("&wait=")
79
81
  ? Number(new URL(route, "https://local").searchParams.get("wait")) * 1000 + 5_000
80
- : finalSnapshot ? 5_000 : Math.max(1, Math.min(30_000, deadline - now())),
82
+ : finalSnapshot
83
+ ? timeoutMs === 0 ? STACK_WATCH_ONE_SHOT_READ_TIMEOUT_MS : STACK_WATCH_DEADLINE_SNAPSHOT_TIMEOUT_MS
84
+ : Math.max(1, Math.min(30_000, deadline - now())),
81
85
  });
82
86
  }
83
87
  catch (err) {
package/dist/ui/banner.js CHANGED
@@ -212,6 +212,9 @@ const WHATS_NEW = {
212
212
  "0.3.58": [
213
213
  "Watch reports Auto land switched off",
214
214
  ],
215
+ "0.3.59": [
216
+ "One-shot stack wait rides out a slow read",
217
+ ],
215
218
  };
216
219
  function densityFromVariant(variant) {
217
220
  if (variant === "mini" || variant === "nano")
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mergestorm",
3
- "version": "0.3.58",
3
+ "version": "0.3.59",
4
4
  "description": "Mergestorm CLI (mg) — local reviews & stacked PRs. MIT; build from source: https://github.com/marginsystems/mergestorm-cli",
5
5
  "license": "MIT",
6
6
  "type": "module",