mergestorm 0.3.59 → 0.3.61

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.59 │
48
+ │ ▀▀▀▀▀▀▀▀▀▀▘ mergestorm v0.3.61 │
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.59: One-shot stack wait rides out a slow read │
53
+ │ ▀ New in v0.3.61: Watch names a job Cyclone's push skips │
54
54
  ╰──────────────────────────────────────────────────────────────────────────────╯
55
55
  mergestorm
56
56
  ╭──────────────────────────────────────────────────────────────────────────────╮
@@ -103,6 +103,7 @@ const CYCLONE_HANDOFF_WORDS = {
103
103
  ci_billing_block: "GitHub Actions is blocked by billing, so no code change turns CI green",
104
104
  ci_missing_secrets: "the failing job needs secrets its run does not have",
105
105
  ci_red_on_base: "the same check also fails on the base branch",
106
+ ci_actor_gated: "the failing job is skipped on a commit pushed by Cyclone, so a fix from Cyclone would not turn it green",
106
107
  ci_rerun_exhausted: "Cyclone already had Surge re-run this check once at this head",
107
108
  ci_rerun_unavailable: "the failure looked flaky and Surge could not re-run it",
108
109
  ci_unverified: "Cyclone's static checks did not cover its fix, so it pushed nothing",
@@ -174,12 +174,14 @@ export type StackLayerConflictResolution = {
174
174
  dispatchId: string | null;
175
175
  };
176
176
  export type StackLayerCiFixStatus = "verified" | "unverified" | "no_changes" | "held" | "failed";
177
+ export type StackLayerCiFixCheck = "passed" | "failed" | "did_not_run" | "pending";
177
178
  export type StackLayerCiFix = {
178
179
  status: StackLayerCiFixStatus;
179
180
  failingCheck: string | null;
180
181
  resultSha: string | null;
181
182
  reason: string | null;
182
183
  at: string;
184
+ checkOnResult?: StackLayerCiFixCheck;
183
185
  };
184
186
  export type StackLayerDto = {
185
187
  branch: string;
@@ -7,6 +7,7 @@ export declare const STACK_WATCH_DEFAULT_TIMEOUT_MS = 45000;
7
7
  export declare const STACK_WATCH_BUSY_RECHECK_S = 15;
8
8
  export declare const STACK_WATCH_ONE_SHOT_READ_TIMEOUT_MS = 30000;
9
9
  export declare const STACK_WATCH_DEADLINE_SNAPSHOT_TIMEOUT_MS = 5000;
10
+ export declare const STACK_WATCH_CLOSING_READ_RESERVE_MS = 10000;
10
11
  /** Resume selectors are fixed for the entire wait, including transient retries. */
11
12
  export type StackWatchCursor = {
12
13
  readonly stackId: string;
@@ -8,6 +8,7 @@ export const STACK_WATCH_DEFAULT_TIMEOUT_MS = 45_000;
8
8
  export const STACK_WATCH_BUSY_RECHECK_S = 15;
9
9
  export const STACK_WATCH_ONE_SHOT_READ_TIMEOUT_MS = DEFAULT_API_TIMEOUT_MS;
10
10
  export const STACK_WATCH_DEADLINE_SNAPSHOT_TIMEOUT_MS = 5_000;
11
+ export const STACK_WATCH_CLOSING_READ_RESERVE_MS = 10_000;
11
12
  export class StackWatchTimeoutError extends Error {
12
13
  lastEnvelope;
13
14
  constructor(lastEnvelope) {
@@ -80,7 +81,8 @@ export async function pollStackWatch(cfg, stackId, opts = {}) {
80
81
  signal: opts.signal, timeoutMs: route.includes("&wait=")
81
82
  ? Number(new URL(route, "https://local").searchParams.get("wait")) * 1000 + 5_000
82
83
  : finalSnapshot
83
- ? timeoutMs === 0 ? STACK_WATCH_ONE_SHOT_READ_TIMEOUT_MS : STACK_WATCH_DEADLINE_SNAPSHOT_TIMEOUT_MS
84
+ ? timeoutMs === 0 ? STACK_WATCH_ONE_SHOT_READ_TIMEOUT_MS
85
+ : Math.max(STACK_WATCH_DEADLINE_SNAPSHOT_TIMEOUT_MS, Math.min(DEFAULT_API_TIMEOUT_MS, deadline - now()))
84
86
  : Math.max(1, Math.min(30_000, deadline - now())),
85
87
  });
86
88
  }
@@ -172,9 +174,10 @@ export async function pollStackWatch(cfg, stackId, opts = {}) {
172
174
  evaluate(stack, queue.entries);
173
175
  if (lastEnvelope.status === "attention" || timeoutMs === 0 || terminal)
174
176
  return seal(lastEnvelope);
175
- while (now() < deadline) {
177
+ const closingReadReserveMs = Math.min(STACK_WATCH_CLOSING_READ_RESERVE_MS, timeoutMs / 4);
178
+ while (deadline - now() > closingReadReserveMs) {
176
179
  const heldAt = now();
177
- const seconds = Math.min(lastEnvelope.busy.length ? STACK_WATCH_BUSY_RECHECK_S : 45, Math.max(1, Math.ceil((deadline - heldAt) / 1000)));
180
+ const seconds = Math.min(lastEnvelope.busy.length ? STACK_WATCH_BUSY_RECHECK_S : 45, Math.max(1, Math.ceil((deadline - heldAt - closingReadReserveMs) / 1000)));
178
181
  const seen = queue.fingerprint ? `&seen=${encodeURIComponent(queue.fingerprint)}` : "";
179
182
  const held = await readQueue(`${queueRoute}&wait=${seconds}${seen}`);
180
183
  if (JSON.stringify(held.entries) === JSON.stringify(queue.entries)) {
package/dist/ui/banner.js CHANGED
@@ -215,6 +215,12 @@ const WHATS_NEW = {
215
215
  "0.3.59": [
216
216
  "One-shot stack wait rides out a slow read",
217
217
  ],
218
+ "0.3.60": [
219
+ "Timed stack wait rides out a slow last read",
220
+ ],
221
+ "0.3.61": [
222
+ "Watch names a job Cyclone's push skips",
223
+ ],
218
224
  };
219
225
  function densityFromVariant(variant) {
220
226
  if (variant === "mini" || variant === "nano")
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mergestorm",
3
- "version": "0.3.59",
3
+ "version": "0.3.61",
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",