mergestorm 0.3.29 → 0.3.30
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 +2 -2
- package/dist/commands/stack.js +1 -0
- package/dist/stack-dto.d.ts +5 -0
- package/dist/stack-dto.js +5 -1
- package/dist/stack-watch-loop.d.ts +1 -0
- package/dist/stack-watch-loop.js +13 -9
- package/dist/ui/banner.js +3 -0
- package/package.json +1 -1
- package/skill/mergestorm-bounce-watch/SKILL.md +1 -1
package/README.md
CHANGED
|
@@ -45,7 +45,7 @@ On a TTY, bare `mergestorm` (or `mergestorm shell`) opens a branded REPL: a comp
|
|
|
45
45
|
|
|
46
46
|
```
|
|
47
47
|
╭──────────────────────────────────────────────────────────────────────────────╮
|
|
48
|
-
│ ▀▀▀▀▀▀▀▀▀▀▘ mergestorm v0.3.
|
|
48
|
+
│ ▀▀▀▀▀▀▀▀▀▀▘ mergestorm v0.3.30 │
|
|
49
49
|
│ ▀▀▀▀▀▀▀▀▀ ● msk_live_… · maelstrom │
|
|
50
50
|
│ ▀▀▀▀▀▀ [████████░░░░░░░░░░░░░░░░░░░░░░] 25% used │
|
|
51
51
|
│ ▝▀▀▀▀▀ local reviews + stacked PRs · mergestorm.ai │
|
|
@@ -114,7 +114,7 @@ mergestorm dismiss <owner/repo>#<n> --head <sha> --review <id> --finding <id> --
|
|
|
114
114
|
- `--ignore <text>` keeps it silent on the first attention whose blocker contains that text (case-insensitive), until the blocker, its PR or its head changes. Use it for a blocker a human has taken over. Repeat the flag for more than one.
|
|
115
115
|
- `--until landed` keeps running after an attention, printing each new attention once, and exits only when the watch is done or reads keep failing.
|
|
116
116
|
- `--max <minutes>` caps the whole watch; when it runs out it prints `MS-WATCH TIMEOUT` and exits 5. The stack is not landed then.
|
|
117
|
-
- `--json`
|
|
117
|
+
- `--json` writes exactly one JSON document to stdout: the final `mergestorm.stack_watch/v1` envelope, or `{ stackId, outcome }` when there is none (a repeated failed read, `--max` timeout, or abort). The MS-WATCH marker lines go to stderr, so do not merge the streams (2>&1) before parsing stdout.
|
|
118
118
|
|
|
119
119
|
```bash
|
|
120
120
|
mg stack watch 11111111-1111-4111-8111-111111111111 --head "$(git rev-parse HEAD)"
|
package/dist/commands/stack.js
CHANGED
|
@@ -56,6 +56,7 @@ const STACK_USAGE = `usage:
|
|
|
56
56
|
Loops stack wait with the cursor and stays silent while the stack is waiting or in progress.
|
|
57
57
|
Prints one MS-WATCH ATTENTION line and exits 3 on attention or a repeated failed read; prints
|
|
58
58
|
MS-WATCH LANDED and exits 0 once the watch is done. Run it as a background command.
|
|
59
|
+
--json writes exactly one JSON document to stdout and sends the MS-WATCH lines to stderr.
|
|
59
60
|
mergestorm stack set <stack-id> [--auto-land on|off] [--auto-review on|off|default] [--auto-patch on|off|default] [--json]
|
|
60
61
|
mergestorm stack adopt <owner/repo>#<pr> [--auto-land on|off] [--auto-review on|off] [--auto-patch on|off] [--json]
|
|
61
62
|
mergestorm stack restack <stack-id> [--json]
|
package/dist/stack-dto.d.ts
CHANGED
|
@@ -392,6 +392,11 @@ export type MergeQueueBounceDetail = {
|
|
|
392
392
|
conflictPaths?: string[];
|
|
393
393
|
message?: string;
|
|
394
394
|
warning?: string;
|
|
395
|
+
batch?: MergeQueueBounceBatch;
|
|
396
|
+
};
|
|
397
|
+
export type MergeQueueBounceBatch = {
|
|
398
|
+
id: string;
|
|
399
|
+
withPrNumbers: number[];
|
|
395
400
|
};
|
|
396
401
|
export type MergeQueueBatchState = "verifying" | "landing" | "landed" | "stopped" | "bounced" | "abandoned";
|
|
397
402
|
export type MergeQueueEntryBatchDto = {
|
package/dist/stack-dto.js
CHANGED
|
@@ -84,7 +84,11 @@ export function mergeQueueBounceLabel(entry) {
|
|
|
84
84
|
(detail?.conflictPaths?.length ? detail.conflictPaths.join(", ") : null) ??
|
|
85
85
|
detail?.message ??
|
|
86
86
|
(detail?.prNumber != null ? `PR #${detail.prNumber}` : null);
|
|
87
|
-
|
|
87
|
+
const withPrNumbers = detail?.batch?.withPrNumbers ?? [];
|
|
88
|
+
const batch = withPrNumbers.length
|
|
89
|
+
? ` in a red batch with ${withPrNumbers.map((prNumber) => `#${prNumber}`).join(", ")}`
|
|
90
|
+
: "";
|
|
91
|
+
return specifics ? `${kindLabel} — ${specifics}${batch}` : `${kindLabel}${batch}`;
|
|
88
92
|
}
|
|
89
93
|
return entry.bounceReason?.trim() || "bounced";
|
|
90
94
|
}
|
|
@@ -20,6 +20,7 @@ export type RunStackWatchOptions = {
|
|
|
20
20
|
cursor?: StackWatchCursor;
|
|
21
21
|
signal?: AbortSignal;
|
|
22
22
|
write?: (line: string) => void;
|
|
23
|
+
writeMarker?: (line: string) => void;
|
|
23
24
|
poll?: typeof pollStackWatch;
|
|
24
25
|
sleep?: (ms: number, signal?: AbortSignal) => Promise<void>;
|
|
25
26
|
now?: () => number;
|
package/dist/stack-watch-loop.js
CHANGED
|
@@ -29,14 +29,15 @@ export async function runStackWatch(cfg, stackId, opts = {}) {
|
|
|
29
29
|
const until = opts.until ?? "attention";
|
|
30
30
|
const ignore = opts.ignore ?? [];
|
|
31
31
|
const write = opts.write ?? ((line) => console.log(line));
|
|
32
|
+
const writeMarker = opts.json ? opts.writeMarker ?? ((line) => console.error(line)) : write;
|
|
32
33
|
const poll = opts.poll ?? pollStackWatch;
|
|
33
34
|
const now = opts.now ?? Date.now;
|
|
34
35
|
const wait = opts.sleep ?? ((ms, signal) => sleep(ms, undefined, { signal }));
|
|
35
36
|
const deadline = opts.maxMs !== undefined ? now() + opts.maxMs : Number.POSITIVE_INFINITY;
|
|
36
|
-
const emit = (line, envelope) => {
|
|
37
|
-
|
|
38
|
-
if (opts.json &&
|
|
39
|
-
write(JSON.stringify(envelope));
|
|
37
|
+
const emit = (line, envelope, outcome) => {
|
|
38
|
+
writeMarker(line);
|
|
39
|
+
if (opts.json && outcome)
|
|
40
|
+
write(JSON.stringify(envelope ?? { stackId: id, outcome }));
|
|
40
41
|
};
|
|
41
42
|
const pause = async (ms) => {
|
|
42
43
|
const remaining = Math.min(ms, Math.max(0, deadline - now()));
|
|
@@ -48,7 +49,7 @@ export async function runStackWatch(cfg, stackId, opts = {}) {
|
|
|
48
49
|
const ignoredKeys = new Map();
|
|
49
50
|
let reportedKey = null;
|
|
50
51
|
const landed = (envelope) => {
|
|
51
|
-
emit(stackWatchLandedLine(envelope), envelope);
|
|
52
|
+
emit(stackWatchLandedLine(envelope), envelope, "landed");
|
|
52
53
|
if (!opts.json)
|
|
53
54
|
write(envelope.watch.message);
|
|
54
55
|
return { outcome: "landed", exitCode: STACK_WATCH_EXIT.landed, envelope };
|
|
@@ -56,7 +57,7 @@ export async function runStackWatch(cfg, stackId, opts = {}) {
|
|
|
56
57
|
const failed = async (message, envelope) => {
|
|
57
58
|
failures += 1;
|
|
58
59
|
if (failures >= 2) {
|
|
59
|
-
emit(stackWatchFailedLine(id, message), envelope);
|
|
60
|
+
emit(stackWatchFailedLine(id, message), envelope, "failed");
|
|
60
61
|
return { outcome: "failed", exitCode: STACK_WATCH_EXIT.attention, envelope };
|
|
61
62
|
}
|
|
62
63
|
await pause(STACK_WATCH_FAILED_RETRY_MS);
|
|
@@ -106,7 +107,7 @@ export async function runStackWatch(cfg, stackId, opts = {}) {
|
|
|
106
107
|
}
|
|
107
108
|
const silent = [...ignoredKeys.values()].includes(key) || key === reportedKey;
|
|
108
109
|
if (!silent) {
|
|
109
|
-
emit(stackWatchAttentionLine(envelope), envelope);
|
|
110
|
+
emit(stackWatchAttentionLine(envelope), envelope, until === "attention" ? "attention" : null);
|
|
110
111
|
if (until === "attention")
|
|
111
112
|
return { outcome: "attention", exitCode: STACK_WATCH_EXIT.attention, envelope };
|
|
112
113
|
reportedKey = key;
|
|
@@ -116,10 +117,13 @@ export async function runStackWatch(cfg, stackId, opts = {}) {
|
|
|
116
117
|
}
|
|
117
118
|
}
|
|
118
119
|
catch (err) {
|
|
119
|
-
if (isAbort(err, opts.signal))
|
|
120
|
+
if (isAbort(err, opts.signal)) {
|
|
121
|
+
if (opts.json)
|
|
122
|
+
write(JSON.stringify({ stackId: id, outcome: "aborted" }));
|
|
120
123
|
return { outcome: "aborted", exitCode: 130, envelope: null };
|
|
124
|
+
}
|
|
121
125
|
throw err;
|
|
122
126
|
}
|
|
123
|
-
emit(stackWatchTimeoutLine(id, opts.maxMs ?? 0), null);
|
|
127
|
+
emit(stackWatchTimeoutLine(id, opts.maxMs ?? 0), null, "timeout");
|
|
124
128
|
return { outcome: "timeout", exitCode: STACK_WATCH_EXIT.timeout, envelope: null };
|
|
125
129
|
}
|
package/dist/ui/banner.js
CHANGED
|
@@ -120,6 +120,9 @@ const WHATS_NEW = {
|
|
|
120
120
|
"0.3.29": [
|
|
121
121
|
"mg stack watch waits in the background",
|
|
122
122
|
],
|
|
123
|
+
"0.3.30": [
|
|
124
|
+
"stack watch --json prints one JSON document",
|
|
125
|
+
],
|
|
123
126
|
};
|
|
124
127
|
function densityFromVariant(variant) {
|
|
125
128
|
if (variant === "mini" || variant === "nano")
|
package/package.json
CHANGED
|
@@ -20,7 +20,7 @@ If your host cannot hold a long turn open (Cursor, Claude Code, Codex, and other
|
|
|
20
20
|
- `MS-WATCH ATTENTION pr=<n> head=<sha> blocker="<blocker>" repair=<kind>` (exit 3): the watch returned `attention`.
|
|
21
21
|
- `MS-WATCH ATTENTION failed stack=<id> error="<message>"` (exit 3): a read failed and its one retry failed too.
|
|
22
22
|
- `MS-WATCH LANDED stack=<id> reason=<reason>` (exit 0): `watch.done` is `true`. Only `reason=landed` is a landed stack; for `closed`, `archived`, or `not_found`, follow "Not done until landed".
|
|
23
|
-
With `--max <minutes>` it can also stop with `MS-WATCH TIMEOUT` (exit 5). The stack is not landed then; start the watcher again. `--json`
|
|
23
|
+
With `--max <minutes>` it can also stop with `MS-WATCH TIMEOUT` (exit 5). The stack is not landed then; start the watcher again. `--json` writes exactly one JSON document to stdout: the final `mergestorm.stack_watch/v1` envelope, or `{ stackId, outcome }` when there is no envelope (a repeated failed read, timeout, or abort). MS-WATCH marker lines go to stderr; do not merge the streams before parsing stdout.
|
|
24
24
|
3. When it wakes you on `MS-WATCH ATTENTION pr=`, call `stack_status` once for that stack, then fix the blocker as steps 3 to 7 of "Watch and patch" say, push, and start the watcher again with `--head` set to the SHA you pushed. On `MS-WATCH ATTENTION failed`, the watcher already retried once: tell the human the stack is not landed and is no longer being watched.
|
|
25
25
|
4. When the human has taken one blocker over and asked you to keep watching the rest, pass `--ignore <blocker-substring>`. The watcher stays silent on the first attention whose blocker contains that text until the blocker, its PR, or its head changes; any other attention still wakes you.
|
|
26
26
|
5. `--until landed` keeps the watcher running after an attention: it prints each new attention line once and exits only when the watch is done or a read fails twice. Use it only when your host streams output lines to you while the command runs.
|