mergestorm 0.3.17 → 0.3.19
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 +4 -3
- package/dist/api.d.ts +7 -2
- package/dist/api.js +42 -2
- package/dist/automation-catalog.d.ts +48 -0
- package/dist/automation-catalog.js +11 -0
- package/dist/client/index.d.ts +3 -1
- package/dist/client/index.js +3 -1
- package/dist/commands/browse.d.ts +1 -1
- package/dist/commands/browse.js +3 -3
- package/dist/commands/help.js +1 -1
- package/dist/commands/queue.d.ts +1 -1
- package/dist/commands/queue.js +21 -6
- package/dist/commands/registry.js +15 -7
- package/dist/commands/review-client.js +6 -11
- package/dist/commands/review.js +9 -1
- package/dist/commands/settings.d.ts +12 -4
- package/dist/commands/settings.js +78 -16
- package/dist/commands/skill.d.ts +4 -3
- package/dist/commands/skill.js +16 -6
- package/dist/commands/stack.d.ts +14 -2
- package/dist/commands/stack.js +89 -4
- package/dist/errors.d.ts +1 -1
- package/dist/stack-dto.d.ts +54 -2
- package/dist/stack-dto.js +37 -1
- package/dist/stack-watch.d.ts +44 -0
- package/dist/stack-watch.js +232 -0
- package/dist/ui/banner.js +6 -0
- package/package.json +1 -1
- package/skill/SKILL.md +6 -4
- package/skill/mergestorm-bounce-watch/SKILL.md +50 -0
- package/skill/mergestorm-pr-loop/SKILL.md +8 -4
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.
|
|
48
|
+
│ ▟██▛ mergestorm v0.3.19 │
|
|
49
49
|
│ ▜▙ ● msk_live_… · maelstrom │
|
|
50
50
|
│ [████████░░░░░░░░░░░░░░░░░░░░░░] 25% used · Resets Sep 5, 10:53am (UTC)│
|
|
51
51
|
│ │
|
|
52
52
|
│ review a diff · usage for tabs · /help for all commands │
|
|
53
|
-
│ New in v0.3.
|
|
53
|
+
│ New in v0.3.19: stack wait and held GET waits │
|
|
54
54
|
╰──────────────────────────────────────────────────────────────────────────────╯
|
|
55
55
|
mergestorm
|
|
56
56
|
╭──────────────────────────────────────────────────────────────────────────────╮
|
|
@@ -86,7 +86,7 @@ mergestorm jobs [n] [--json] Recent review jobs (default 10, max 50)
|
|
|
86
86
|
mergestorm branches [n] Recently reviewed branches (arrow-pick on TTY)
|
|
87
87
|
mergestorm chain [slug] Branch review-chain timeline (default: current branch)
|
|
88
88
|
mergestorm whoami [--json] Key prefix, plan, API base, config path
|
|
89
|
-
mergestorm skill install --claude|--cursor Copy the
|
|
89
|
+
mergestorm skill install --claude|--cursor|--agents Copy the Mergestorm skills into this repo
|
|
90
90
|
mergestorm thread <slug> Jobs in a review thread
|
|
91
91
|
mergestorm stack create [name] New local stack layer (optional `--onto` / `--trunk` / `--extend`)
|
|
92
92
|
mergestorm stack submit Push layers, open PRs (`gh`), register via adopt (optional `--extend`)
|
|
@@ -94,6 +94,7 @@ mergestorm stack list [--json] List registered stacks
|
|
|
94
94
|
mergestorm stack adopt <owner/repo>#<pr> Import an existing open PR chain
|
|
95
95
|
mergestorm stack restack <stack-id> Restack descendants
|
|
96
96
|
mergestorm stack land <stack-id> Land / promote (into review unit when present)
|
|
97
|
+
mergestorm stack wait <stack-id> Wait for stack attention (default 45s, max 300s)
|
|
97
98
|
mergestorm stack reset --force Clear local authoring state (not branches/PRs)
|
|
98
99
|
```
|
|
99
100
|
|
package/dist/api.d.ts
CHANGED
|
@@ -134,6 +134,11 @@ export type PrVortexReview = {
|
|
|
134
134
|
finding_count: number;
|
|
135
135
|
findings: PrReviewFindings | null;
|
|
136
136
|
patch_policy: unknown | null;
|
|
137
|
+
/**
|
|
138
|
+
* MS-01: True when the returned row is a resting completion but a newer
|
|
139
|
+
* attempt is in flight (active lease). The CLI must continue polling.
|
|
140
|
+
*/
|
|
141
|
+
newer_pass_pending?: boolean;
|
|
137
142
|
};
|
|
138
143
|
/**
|
|
139
144
|
* Pass selection on the DB-only PR review read (#2027). `pass` names one row;
|
|
@@ -154,9 +159,9 @@ export declare function applyPrReviewQuery(query: URLSearchParams, opts: PrRevie
|
|
|
154
159
|
*/
|
|
155
160
|
export { SETTINGS_WRITABLE_KEYS };
|
|
156
161
|
export type { SettingsWritableKey };
|
|
157
|
-
export type SettingsPatch = Partial<
|
|
162
|
+
export type SettingsPatch = Partial<import("./automation-catalog.js").BearerSettingsValues>;
|
|
158
163
|
/** GET and PATCH `/api/v1/settings` both answer with this shape. */
|
|
159
|
-
export type SettingsResponse =
|
|
164
|
+
export type SettingsResponse = import("./automation-catalog.js").BearerSettingsValues & {
|
|
160
165
|
cyclone_connected: boolean;
|
|
161
166
|
github_connected: boolean;
|
|
162
167
|
};
|
package/dist/api.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { apiBase, loadConfig, resolveApiKey } from "./config.js";
|
|
2
2
|
import { BEARER_SETTINGS_KEYS as SETTINGS_WRITABLE_KEYS, } from "./automation-catalog.js";
|
|
3
|
-
import { CommandError, REVIEW_EXIT, rateLimitedMessage } from "./errors.js";
|
|
3
|
+
import { CommandError, REVIEW_EXIT, rateLimitedMessage, } from "./errors.js";
|
|
4
4
|
/** Default per-request timeout so a hung API cannot stall the shell/CI forever. */
|
|
5
5
|
export const DEFAULT_API_TIMEOUT_MS = 30_000;
|
|
6
6
|
/** Message prefix of the CommandError thrown when a request exceeds its timeout. */
|
|
@@ -382,7 +382,43 @@ export async function adoptStack(owner, repo, prNumber, cfg, policy) {
|
|
|
382
382
|
throw new CommandError(rateLimitedMessage(retryAfterSeconds), REVIEW_EXIT.rate_limited, "rate_limited", { retryAfterSeconds });
|
|
383
383
|
}
|
|
384
384
|
if (status !== 200) {
|
|
385
|
-
|
|
385
|
+
const error = body && typeof body === "object" && "error" in body && typeof body.error === "string"
|
|
386
|
+
? body.error
|
|
387
|
+
: undefined;
|
|
388
|
+
const message = body && typeof body === "object" && "message" in body && typeof body.message === "string"
|
|
389
|
+
? body.message
|
|
390
|
+
: undefined;
|
|
391
|
+
const code = error === "auth_invalid" ||
|
|
392
|
+
error === "api_timeout" ||
|
|
393
|
+
error === "not_a_repo" ||
|
|
394
|
+
error === "not_found" ||
|
|
395
|
+
error === "missing_api_key" ||
|
|
396
|
+
error === "registered_parent" ||
|
|
397
|
+
error === "usage" ||
|
|
398
|
+
error === "review_quota" ||
|
|
399
|
+
error === "review_failed" ||
|
|
400
|
+
error === "review_timeout" ||
|
|
401
|
+
error === "rate_limited" ||
|
|
402
|
+
error === "cyclone_not_installed" ||
|
|
403
|
+
error === "pr_merged" ||
|
|
404
|
+
error === "pr_closed" ||
|
|
405
|
+
error === "not_stacked" ||
|
|
406
|
+
error === "draft" ||
|
|
407
|
+
error === "reserved_branch" ||
|
|
408
|
+
error === "supabase_unconfigured" ||
|
|
409
|
+
error === "cyclone_not_connected" ||
|
|
410
|
+
error === "busy" ||
|
|
411
|
+
error === "adopt_failed"
|
|
412
|
+
? error
|
|
413
|
+
: undefined;
|
|
414
|
+
const fallbackMessage = code === "not_stacked"
|
|
415
|
+
? "This pull request is not part of a stack."
|
|
416
|
+
: code === "supabase_unconfigured"
|
|
417
|
+
? "Stacks are not configured on this server."
|
|
418
|
+
: undefined;
|
|
419
|
+
throw new CommandError(message?.trim()
|
|
420
|
+
? message
|
|
421
|
+
: fallbackMessage ?? `Failed to import stack (HTTP ${status}): ${JSON.stringify(body)}`, 1, code);
|
|
386
422
|
}
|
|
387
423
|
return body;
|
|
388
424
|
}
|
|
@@ -414,6 +450,10 @@ async function stackMutation(stackId, pathSuffix, method, json, failLabel, cfg)
|
|
|
414
450
|
throw new CommandError("Stacks API is not available on this server yet. Deploy the API update or use the dashboard.");
|
|
415
451
|
}
|
|
416
452
|
if (status !== 200) {
|
|
453
|
+
const rejection = body;
|
|
454
|
+
if (method === "PATCH" && rejection?.error === "cyclone_not_connected") {
|
|
455
|
+
throw new CommandError(typeof rejection.message === "string" ? rejection.message : rejection.error, 1, "cyclone_not_connected");
|
|
456
|
+
}
|
|
417
457
|
throw new CommandError(`${failLabel} (HTTP ${status}): ${JSON.stringify(body)}`);
|
|
418
458
|
}
|
|
419
459
|
return body;
|
|
@@ -22,6 +22,22 @@ export declare const BEARER_SETTINGS: readonly [{
|
|
|
22
22
|
readonly key: "cyclone_review_unit_land_prs_enabled";
|
|
23
23
|
readonly flag: "--cyclone-review-unit-land";
|
|
24
24
|
readonly label: "Cyclone Review Unit land PRs";
|
|
25
|
+
}, {
|
|
26
|
+
readonly key: "cyclone_skip_ci_enabled";
|
|
27
|
+
readonly flag: "--cyclone-skip-ci";
|
|
28
|
+
readonly label: "Skip CI on Cyclone commits";
|
|
29
|
+
}, {
|
|
30
|
+
readonly key: "cyclone_patch_unverified_languages";
|
|
31
|
+
readonly flag: "--cyclone-patch-unverified";
|
|
32
|
+
readonly label: "Patch languages we cannot typecheck";
|
|
33
|
+
}, {
|
|
34
|
+
readonly key: "vortex_auto_overflow_enabled";
|
|
35
|
+
readonly flag: "--vortex-auto-overflow";
|
|
36
|
+
readonly label: "Vortex auto overflow";
|
|
37
|
+
}, {
|
|
38
|
+
readonly key: "vortex_skip_all_clear_comments";
|
|
39
|
+
readonly flag: "--vortex-skip-all-clear";
|
|
40
|
+
readonly label: "Vortex skip All-clear comments";
|
|
25
41
|
}, {
|
|
26
42
|
readonly key: "vortex_seam_specialist_enabled";
|
|
27
43
|
readonly flag: "--vortex-seam";
|
|
@@ -30,8 +46,40 @@ export declare const BEARER_SETTINGS: readonly [{
|
|
|
30
46
|
readonly key: "auto_land_default";
|
|
31
47
|
readonly flag: "--auto-land";
|
|
32
48
|
readonly label: "Auto land (new stacks)";
|
|
49
|
+
}, {
|
|
50
|
+
readonly key: "ignored_bot_logins";
|
|
51
|
+
readonly flag: "--ignore-bot";
|
|
52
|
+
readonly label: "Ignored bot logins";
|
|
53
|
+
readonly kind: "logins";
|
|
54
|
+
}, {
|
|
55
|
+
readonly key: "vortex_bot_skip_check";
|
|
56
|
+
readonly flag: "--vortex-skip-check";
|
|
57
|
+
readonly label: "Vortex bot skip check";
|
|
58
|
+
readonly kind: "enum";
|
|
59
|
+
readonly values: readonly ["none", "neutral"];
|
|
60
|
+
}, {
|
|
61
|
+
readonly key: "vortex_findings_check";
|
|
62
|
+
readonly flag: "--vortex-findings";
|
|
63
|
+
readonly label: "Vortex findings check";
|
|
64
|
+
readonly kind: "enum";
|
|
65
|
+
readonly values: readonly ["failure", "neutral", "success"];
|
|
66
|
+
}, {
|
|
67
|
+
readonly key: "cyclone_patch_failure_check";
|
|
68
|
+
readonly flag: "--cyclone-fail-check";
|
|
69
|
+
readonly label: "Cyclone patch failure check";
|
|
70
|
+
readonly kind: "enum";
|
|
71
|
+
readonly values: readonly ["failure", "neutral"];
|
|
33
72
|
}];
|
|
34
73
|
export type BearerSettingsKey = (typeof BEARER_SETTINGS)[number]["key"];
|
|
35
74
|
export declare const BEARER_SETTINGS_KEYS: readonly BearerSettingsKey[];
|
|
36
75
|
export declare const BEARER_SETTINGS_FLAGS: Record<string, BearerSettingsKey>;
|
|
37
76
|
export declare const BEARER_SETTINGS_LABELS: Record<BearerSettingsKey, string>;
|
|
77
|
+
/** Omitted kind means boolean for the original toggle rows. */
|
|
78
|
+
export type BearerSettingsValues = {
|
|
79
|
+
[Row in (typeof BEARER_SETTINGS)[number] as Row["key"]]: Row extends {
|
|
80
|
+
kind: "logins";
|
|
81
|
+
} ? string[] : Row extends {
|
|
82
|
+
values: readonly (infer Value)[];
|
|
83
|
+
} ? Value : boolean;
|
|
84
|
+
};
|
|
85
|
+
export declare const BEARER_BOOLEAN_SETTINGS_KEYS: ("auto_review_enabled" | "auto_patch_enabled" | "vortex_show_thinking_traces" | "repo_overview_enabled" | "review_unit_land_prs_enabled" | "cyclone_review_unit_land_prs_enabled" | "cyclone_skip_ci_enabled" | "cyclone_patch_unverified_languages" | "vortex_auto_overflow_enabled" | "vortex_skip_all_clear_comments" | "vortex_seam_specialist_enabled" | "auto_land_default" | "ignored_bot_logins" | "vortex_bot_skip_check" | "vortex_findings_check" | "cyclone_patch_failure_check")[];
|
|
@@ -5,9 +5,20 @@ export const BEARER_SETTINGS = [
|
|
|
5
5
|
{ key: "repo_overview_enabled", flag: "--repo-overview", label: "Repo overview" },
|
|
6
6
|
{ key: "review_unit_land_prs_enabled", flag: "--review-unit-land", label: "Review Unit land PRs" },
|
|
7
7
|
{ key: "cyclone_review_unit_land_prs_enabled", flag: "--cyclone-review-unit-land", label: "Cyclone Review Unit land PRs" },
|
|
8
|
+
{ key: "cyclone_skip_ci_enabled", flag: "--cyclone-skip-ci", label: "Skip CI on Cyclone commits" },
|
|
9
|
+
{ key: "cyclone_patch_unverified_languages", flag: "--cyclone-patch-unverified", label: "Patch languages we cannot typecheck" },
|
|
10
|
+
{ key: "vortex_auto_overflow_enabled", flag: "--vortex-auto-overflow", label: "Vortex auto overflow" },
|
|
11
|
+
{ key: "vortex_skip_all_clear_comments", flag: "--vortex-skip-all-clear", label: "Vortex skip All-clear comments" },
|
|
8
12
|
{ key: "vortex_seam_specialist_enabled", flag: "--vortex-seam", label: "Vortex seam specialist" },
|
|
9
13
|
{ key: "auto_land_default", flag: "--auto-land", label: "Auto land (new stacks)" },
|
|
14
|
+
{ key: "ignored_bot_logins", flag: "--ignore-bot", label: "Ignored bot logins", kind: "logins" },
|
|
15
|
+
{ key: "vortex_bot_skip_check", flag: "--vortex-skip-check", label: "Vortex bot skip check", kind: "enum", values: ["none", "neutral"] },
|
|
16
|
+
{ key: "vortex_findings_check", flag: "--vortex-findings", label: "Vortex findings check", kind: "enum", values: ["failure", "neutral", "success"] },
|
|
17
|
+
{ key: "cyclone_patch_failure_check", flag: "--cyclone-fail-check", label: "Cyclone patch failure check", kind: "enum", values: ["failure", "neutral"] },
|
|
10
18
|
];
|
|
11
19
|
export const BEARER_SETTINGS_KEYS = BEARER_SETTINGS.map((r) => r.key);
|
|
12
20
|
export const BEARER_SETTINGS_FLAGS = Object.fromEntries(BEARER_SETTINGS.map((r) => [r.flag, r.key]));
|
|
13
21
|
export const BEARER_SETTINGS_LABELS = Object.fromEntries(BEARER_SETTINGS.map((r) => [r.key, r.label]));
|
|
22
|
+
export const BEARER_BOOLEAN_SETTINGS_KEYS = BEARER_SETTINGS
|
|
23
|
+
.filter((row) => !("kind" in row))
|
|
24
|
+
.map((row) => row.key);
|
package/dist/client/index.d.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
export { DEFAULT_API, apiBase, clearConfig, configPath, keyDisplay, loadConfig, mergestormHome, resolveApiKey, saveConfig, type Config, } from "../config.js";
|
|
2
|
-
export { BEARER_SETTINGS, BEARER_SETTINGS_FLAGS, BEARER_SETTINGS_KEYS, BEARER_SETTINGS_LABELS, type BearerSettingsKey, } from "../automation-catalog.js";
|
|
2
|
+
export { BEARER_SETTINGS, BEARER_BOOLEAN_SETTINGS_KEYS, BEARER_SETTINGS_FLAGS, BEARER_SETTINGS_KEYS, BEARER_SETTINGS_LABELS, type BearerSettingsKey, } from "../automation-catalog.js";
|
|
3
3
|
export { API_TIMEOUT_PREFIX, DEFAULT_API_TIMEOUT_MS, SETTINGS_WRITABLE_KEYS, adoptStack, apiFetch, cancelMergeQueueEntry, devicePost, enqueueStack, ensureUpperPark, getEnrichedStack, getMe, getPrVortexReview, getReview, getSettings, landNextStack, listJobs, listMergeQueueEntries, listStacks, listThreads, parseRetryAfterSeconds, patchSettings, restackStack, setStackAutoLand, setStackPolicy, stackPolicyBody, type ApiFetchInit, type ApiFetchResult, type JobListItem, type MeResponse, type MergeQueueBounceDetail, type MergeQueueBounceKind, type MergeQueueEnqueuedBy, type MergeQueueEnqueuedVia, type MergeQueueEntryDto, type MergeQueueEntryState, type PrReviewFinding, type PrReviewFindings, type PrVortexReview, type SettingsPatch, type SettingsResponse, type SettingsWritableKey, type StackDto, type StackPolicyPatch, type ThreadDetail, type ThreadListItem, } from "../api.js";
|
|
4
4
|
export { CommandError, DetachedError, RATE_LIMITED_HINT, REVIEW_EXIT, isCommandErrorCode, rateLimitedMessage, type CommandErrorCode, type CommandErrorExtras, } from "../errors.js";
|
|
5
5
|
export { REVIEW_POLL_BACKOFF_MS, REVIEW_POLL_DEFAULT_TIMEOUT_MS, REVIEW_POLL_INTERVAL_MS, REVIEW_POLL_MAX_INTERVAL_MS, REVIEW_POLL_MAX_TRANSIENT_RETRIES, REVIEW_POLL_STRETCH_AFTER_MS, REVIEW_POLL_STRETCH_SPAN_MS, REVIEW_THREAD_SLUG_RE, PrReviewPollTimeoutError, ReviewPollTimeoutError, collectReviewInput, formatReviewSubmitError, isTransientReviewPollError, isTransientReviewPollStatus, loadReviewContext, pollPrVortexReview, pollReview, stretchedPollIntervalMs, submitReview, transientRetryWaitMs, type PollReviewOptions, type PollPrVortexReviewOptions, type ReviewInput, type SubmitReviewOptions, } from "../commands/review-client.js";
|
|
6
6
|
export { REVIEW_JOB_ENVELOPE_SCHEMA, toReviewJobEnvelope, type ReviewEnvelopeFallbacks, type ReviewJobEnvelope, type ReviewJobRow, } from "../ui/job-envelope.js";
|
|
7
7
|
export { discoverTrunk } from "../git-stack.js";
|
|
8
|
+
export { BOUNCE_KIND_LABELS, mergeQueueBounceLabel } from "../stack-dto.js";
|
|
9
|
+
export { STACK_WATCH_SCHEMA, STACK_WATCH_DEFAULT_TIMEOUT_MS, StackWatchError, StackWatchTimeoutError, pollStackWatch, type PollStackWatchOptions, type StackWatchCursor, type StackWatchEnvelope, } from "../stack-watch.js";
|
package/dist/client/index.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
export { DEFAULT_API, apiBase, clearConfig, configPath, keyDisplay, loadConfig, mergestormHome, resolveApiKey, saveConfig, } from "../config.js";
|
|
2
|
-
export { BEARER_SETTINGS, BEARER_SETTINGS_FLAGS, BEARER_SETTINGS_KEYS, BEARER_SETTINGS_LABELS, } from "../automation-catalog.js";
|
|
2
|
+
export { BEARER_SETTINGS, BEARER_BOOLEAN_SETTINGS_KEYS, BEARER_SETTINGS_FLAGS, BEARER_SETTINGS_KEYS, BEARER_SETTINGS_LABELS, } from "../automation-catalog.js";
|
|
3
3
|
export { API_TIMEOUT_PREFIX, DEFAULT_API_TIMEOUT_MS, SETTINGS_WRITABLE_KEYS, adoptStack, apiFetch, cancelMergeQueueEntry, devicePost, enqueueStack, ensureUpperPark, getEnrichedStack, getMe, getPrVortexReview, getReview, getSettings, landNextStack, listJobs, listMergeQueueEntries, listStacks, listThreads, parseRetryAfterSeconds, patchSettings, restackStack, setStackAutoLand, setStackPolicy, stackPolicyBody, } from "../api.js";
|
|
4
4
|
export { CommandError, DetachedError, RATE_LIMITED_HINT, REVIEW_EXIT, isCommandErrorCode, rateLimitedMessage, } from "../errors.js";
|
|
5
5
|
export { REVIEW_POLL_BACKOFF_MS, REVIEW_POLL_DEFAULT_TIMEOUT_MS, REVIEW_POLL_INTERVAL_MS, REVIEW_POLL_MAX_INTERVAL_MS, REVIEW_POLL_MAX_TRANSIENT_RETRIES, REVIEW_POLL_STRETCH_AFTER_MS, REVIEW_POLL_STRETCH_SPAN_MS, REVIEW_THREAD_SLUG_RE, PrReviewPollTimeoutError, ReviewPollTimeoutError, collectReviewInput, formatReviewSubmitError, isTransientReviewPollError, isTransientReviewPollStatus, loadReviewContext, pollPrVortexReview, pollReview, stretchedPollIntervalMs, submitReview, transientRetryWaitMs, } from "../commands/review-client.js";
|
|
6
6
|
export { REVIEW_JOB_ENVELOPE_SCHEMA, toReviewJobEnvelope, } from "../ui/job-envelope.js";
|
|
7
7
|
export { discoverTrunk } from "../git-stack.js";
|
|
8
|
+
export { BOUNCE_KIND_LABELS, mergeQueueBounceLabel } from "../stack-dto.js";
|
|
9
|
+
export { STACK_WATCH_SCHEMA, STACK_WATCH_DEFAULT_TIMEOUT_MS, StackWatchError, StackWatchTimeoutError, pollStackWatch, } from "../stack-watch.js";
|
|
@@ -27,7 +27,7 @@ export declare function buildStatusTabLines(input: StatusTabInput): string[];
|
|
|
27
27
|
/** In-place job detail for the Jobs tab (same envelope as `status <id>`). */
|
|
28
28
|
export declare function formatJobDetailLines(row: ReviewJobRow): string[];
|
|
29
29
|
/** Human labels for the Config tab and the static `settings` printout. */
|
|
30
|
-
export declare const SETTINGS_LABELS: Record<"auto_review_enabled" | "auto_patch_enabled" | "vortex_show_thinking_traces" | "repo_overview_enabled" | "review_unit_land_prs_enabled" | "cyclone_review_unit_land_prs_enabled" | "vortex_seam_specialist_enabled" | "auto_land_default", string>;
|
|
30
|
+
export declare const SETTINGS_LABELS: Record<"auto_review_enabled" | "auto_patch_enabled" | "vortex_show_thinking_traces" | "repo_overview_enabled" | "review_unit_land_prs_enabled" | "cyclone_review_unit_land_prs_enabled" | "cyclone_skip_ci_enabled" | "cyclone_patch_unverified_languages" | "vortex_auto_overflow_enabled" | "vortex_skip_all_clear_comments" | "vortex_seam_specialist_enabled" | "auto_land_default" | "ignored_bot_logins" | "vortex_bot_skip_check" | "vortex_findings_check" | "cyclone_patch_failure_check", string>;
|
|
31
31
|
/** Config rows in a stable order: writable toggles, then connected flags. */
|
|
32
32
|
export declare function buildConfigRows(settings: SettingsResponse): TabsConfigRow[];
|
|
33
33
|
/**
|
package/dist/commands/browse.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { getMe, getReview, getSettings, listJobs, patchSettings,
|
|
2
|
-
import { BEARER_SETTINGS_LABELS } from "../automation-catalog.js";
|
|
1
|
+
import { getMe, getReview, getSettings, listJobs, patchSettings, } from "../api.js";
|
|
2
|
+
import { BEARER_BOOLEAN_SETTINGS_KEYS, BEARER_SETTINGS_LABELS } from "../automation-catalog.js";
|
|
3
3
|
import { apiBase, keyDisplay, loadConfig, resolveApiKey } from "../config.js";
|
|
4
4
|
import { CommandError } from "../errors.js";
|
|
5
5
|
import { ansi } from "../ui/ansi.js";
|
|
@@ -124,7 +124,7 @@ export const SETTINGS_LABELS = BEARER_SETTINGS_LABELS;
|
|
|
124
124
|
/** Config rows in a stable order: writable toggles, then connected flags. */
|
|
125
125
|
export function buildConfigRows(settings) {
|
|
126
126
|
return [
|
|
127
|
-
...
|
|
127
|
+
...BEARER_BOOLEAN_SETTINGS_KEYS.map((key) => ({
|
|
128
128
|
key,
|
|
129
129
|
label: SETTINGS_LABELS[key],
|
|
130
130
|
value: settings[key] === true,
|
package/dist/commands/help.js
CHANGED
|
@@ -58,7 +58,7 @@ export function buildHelpTabs() {
|
|
|
58
58
|
"",
|
|
59
59
|
rule("Single stack (from trunk)"),
|
|
60
60
|
cmd("stack create --onto main", "fresh stack, not on an existing one"),
|
|
61
|
-
cmd("stack list", "
|
|
61
|
+
cmd("stack list · wait <id>", "registered stacks · wait for attention"),
|
|
62
62
|
cmd("queue [add <stack-id>]", "list entries · queue verified landing"),
|
|
63
63
|
cmd("stack land <id>", "land now · skips queue verification"),
|
|
64
64
|
"",
|
package/dist/commands/queue.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ export type QueueCmdDeps = {
|
|
|
5
5
|
canBrowse?: () => boolean;
|
|
6
6
|
runLineTabsBrowser?: typeof runLineTabsBrowser;
|
|
7
7
|
};
|
|
8
|
-
export declare const QUEUE_USAGE = "usage:\n mergestorm queue [list] [--json]\n mergestorm queue add <stack-id> [--json]\n mergestorm queue rm <entry-id|stack-id> [--json]\n\n queue lists
|
|
8
|
+
export declare const QUEUE_USAGE = "usage:\n mergestorm queue [list] [--json]\n mergestorm queue add <stack-id> [--json]\n mergestorm queue rm <entry-id|stack-id> [--json]\n\n queue lists live and recent bounced merge-queue entries. rm prefers an entry id; a live\n stack id is resolved to its queue entry before cancellation.";
|
|
9
9
|
/** Entry ids win; otherwise a live stack id resolves to its entry id. */
|
|
10
10
|
export declare function resolveQueueEntryId(idOrStackId: string, entries: readonly MergeQueueEntryDto[]): string;
|
|
11
11
|
export declare function buildQueueListLines(entries: readonly MergeQueueEntryDto[], fullStackId?: boolean): string[];
|
package/dist/commands/queue.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { cancelMergeQueueEntry, enqueueStack, listMergeQueueEntries, } from "../api.js";
|
|
2
2
|
import { loadConfig } from "../config.js";
|
|
3
3
|
import { CommandError } from "../errors.js";
|
|
4
|
+
import { mergeQueueBounceLabel } from "../stack-dto.js";
|
|
4
5
|
import { ansi } from "../ui/ansi.js";
|
|
5
6
|
import { runLineTabsBrowser } from "../ui/line-tabs.js";
|
|
6
7
|
import { present } from "../ui/present.js";
|
|
@@ -31,7 +32,7 @@ export const QUEUE_USAGE = `usage:
|
|
|
31
32
|
mergestorm queue add <stack-id> [--json]
|
|
32
33
|
mergestorm queue rm <entry-id|stack-id> [--json]
|
|
33
34
|
|
|
34
|
-
queue lists
|
|
35
|
+
queue lists live and recent bounced merge-queue entries. rm prefers an entry id; a live
|
|
35
36
|
stack id is resolved to its queue entry before cancellation.`;
|
|
36
37
|
function positionalArgs(args) {
|
|
37
38
|
const unknown = args.filter((arg) => arg.startsWith("-") &&
|
|
@@ -66,17 +67,31 @@ export function buildQueueListLines(entries, fullStackId = false) {
|
|
|
66
67
|
];
|
|
67
68
|
}
|
|
68
69
|
return entries.map((entry) => {
|
|
69
|
-
const reason = entry.
|
|
70
|
+
const reason = entry.bounceDetail
|
|
71
|
+
? mergeQueueBounceLabel(entry)
|
|
72
|
+
: entry.waitReason ?? (entry.bounceReason ? mergeQueueBounceLabel(entry) : null);
|
|
73
|
+
const prNumber = entry.bounceDetail?.prNumber != null && entry.bounceDetail.prNumber > 0
|
|
74
|
+
? entry.bounceDetail.prNumber
|
|
75
|
+
: entry.waitReason?.match(/#([1-9]\d*)\b/)?.[1];
|
|
76
|
+
const headSha = entry.bounceDetail?.headSha ?? entry.verifyHeadSha;
|
|
77
|
+
const pr = prNumber != null
|
|
78
|
+
? ` #${prNumber}${headSha ? `@${headSha.slice(0, 7)}` : ""}`
|
|
79
|
+
: "";
|
|
70
80
|
const glyph = colorQueueGlyph(entry.state, queueStateGlyph(entry.state));
|
|
71
81
|
const id = fullStackId ? entry.stackId : entry.stackId.slice(0, 8);
|
|
72
|
-
const
|
|
73
|
-
`${glyph} ${entry.state.padEnd(8)} ${entry.owner}/${entry.repo} ${id}
|
|
74
|
-
|
|
82
|
+
const coreWithoutReason = ` ${String(entry.position).padStart(2)} ` +
|
|
83
|
+
`${glyph} ${entry.state.padEnd(8)} ${entry.owner}/${entry.repo} ${id}`;
|
|
84
|
+
const coreWithoutPr = coreWithoutReason + (reason ? ` ${reason}` : "");
|
|
85
|
+
const core = `${coreWithoutPr}${pr}`;
|
|
75
86
|
const who = entry.enqueuedBy === "human" || entry.enqueuedBy === "agent"
|
|
76
87
|
? ` by ${entry.enqueuedBy}`
|
|
77
88
|
: "";
|
|
78
89
|
const withWho = `${core}${who}`;
|
|
79
|
-
|
|
90
|
+
if (visibleWidth(withWho) <= 80)
|
|
91
|
+
return withWho;
|
|
92
|
+
if (visibleWidth(core) <= 80)
|
|
93
|
+
return core;
|
|
94
|
+
return pr ? core : coreWithoutPr;
|
|
80
95
|
});
|
|
81
96
|
}
|
|
82
97
|
async function listQueue(asJson, deps = {}) {
|
|
@@ -52,6 +52,7 @@ export const COMMAND_REGISTRY = [
|
|
|
52
52
|
" [--context text] [--context-file path] [--thread slug]",
|
|
53
53
|
" [--idempotency-key k] [--webhook-url https://…]",
|
|
54
54
|
" HTTP 429 exits 7 (rate_limited) with retry_after_seconds",
|
|
55
|
+
" Uploads over 1 MB / 1_000_000 are rejected with HTTP 413 and do not create a job",
|
|
55
56
|
],
|
|
56
57
|
async run(args, ctx) {
|
|
57
58
|
if (ctx.mode === "shell") {
|
|
@@ -164,8 +165,13 @@ export const COMMAND_REGISTRY = [
|
|
|
164
165
|
"mergestorm settings [--json] Read the automation toggles (Config tab on a TTY)",
|
|
165
166
|
" [--auto-review on|off] [--auto-patch on|off] [--vortex-thinking on|off]",
|
|
166
167
|
" [--repo-overview on|off] [--review-unit-land on|off]",
|
|
167
|
-
" [--cyclone-review-unit-land on|off] [--
|
|
168
|
-
" [--
|
|
168
|
+
" [--cyclone-review-unit-land on|off] [--cyclone-skip-ci on|off]",
|
|
169
|
+
" [--cyclone-patch-unverified on|off] Patch languages we cannot typecheck",
|
|
170
|
+
" [--vortex-seam on|off] [--vortex-skip-all-clear on|off]",
|
|
171
|
+
" [--auto-land on|off] Auto land default for new stacks",
|
|
172
|
+
" [--ignore-bot add <login>|remove <login>|clear]",
|
|
173
|
+
" [--vortex-skip-check none|neutral] [--vortex-findings failure|neutral|success]",
|
|
174
|
+
" [--cyclone-fail-check failure|neutral]",
|
|
169
175
|
" With flags: PATCH those settings and print the stored result",
|
|
170
176
|
],
|
|
171
177
|
async run(args, ctx) {
|
|
@@ -174,9 +180,9 @@ export const COMMAND_REGISTRY = [
|
|
|
174
180
|
},
|
|
175
181
|
{
|
|
176
182
|
name: "skill",
|
|
177
|
-
summary: "Install
|
|
183
|
+
summary: "Install Mergestorm skills for Claude, Cursor, or agents",
|
|
178
184
|
usage: [
|
|
179
|
-
"mergestorm skill install --claude|--cursor Copy the
|
|
185
|
+
"mergestorm skill install --claude|--cursor|--agents Copy the Mergestorm skills into this repo",
|
|
180
186
|
" [--json]",
|
|
181
187
|
],
|
|
182
188
|
async run(args) {
|
|
@@ -200,7 +206,7 @@ export const COMMAND_REGISTRY = [
|
|
|
200
206
|
name: "queue",
|
|
201
207
|
summary: "Merge queue: list, add a stack, or remove an entry",
|
|
202
208
|
usage: [
|
|
203
|
-
"mergestorm queue [list] [--json] List live merge-queue entries",
|
|
209
|
+
"mergestorm queue [list] [--json] List live and recent bounced merge-queue entries",
|
|
204
210
|
"mergestorm queue add <stack-id> [--json] Queue a stack for verified landing",
|
|
205
211
|
"mergestorm queue rm <entry-id|stack-id> [--json] Remove a live queue entry",
|
|
206
212
|
],
|
|
@@ -216,13 +222,15 @@ export const COMMAND_REGISTRY = [
|
|
|
216
222
|
"mergestorm stack submit Push/open active stack ([--extend] [--auto-land on|off] [--auto-review on|off] [--auto-patch on|off])",
|
|
217
223
|
"mergestorm stack reset --force Clear this repo's pre-submit authoring state",
|
|
218
224
|
"mergestorm stack list [--json] List registered stacks",
|
|
225
|
+
"mergestorm stack status <stack-id> [--json] Enriched stack status",
|
|
226
|
+
"mergestorm stack wait <stack-id> [--json] [--timeout <s>] Wait for stack attention (default 45s, max 300s)",
|
|
219
227
|
"mergestorm stack set <stack-id> [--auto-land on|off] [--auto-review on|off|default] [--auto-patch on|off|default] [--json] Per-stack policy",
|
|
220
228
|
"mergestorm stack adopt <owner/repo>#<pr> [--auto-land on|off] [--auto-review on|off] [--auto-patch on|off] Import an open PR chain",
|
|
221
229
|
"mergestorm stack restack <stack-id> Restack stack descendants",
|
|
222
230
|
"mergestorm stack land <stack-id> Land bottom PR (or promote into unit)",
|
|
223
231
|
],
|
|
224
|
-
async run(args) {
|
|
225
|
-
await cmdStack(args);
|
|
232
|
+
async run(args, ctx) {
|
|
233
|
+
await cmdStack(args, { signal: ctx.signal });
|
|
226
234
|
},
|
|
227
235
|
},
|
|
228
236
|
{
|
|
@@ -271,7 +271,6 @@ function shaMatches(actual, expected) {
|
|
|
271
271
|
/** Poll the DB-only PR review endpoint until the requested pass is resting. */
|
|
272
272
|
export async function pollPrVortexReview(cfg, owner, repo, prNumber, opts = {}) {
|
|
273
273
|
const timeoutMs = opts.timeoutMs ?? REVIEW_POLL_DEFAULT_TIMEOUT_MS;
|
|
274
|
-
const intervalMs = opts.intervalMs ?? REVIEW_POLL_INTERVAL_MS;
|
|
275
274
|
const now = opts.now ?? Date.now;
|
|
276
275
|
const wait = opts.sleep ?? sleep;
|
|
277
276
|
const startedAt = now();
|
|
@@ -296,17 +295,13 @@ export async function pollPrVortexReview(cfg, owner, repo, prNumber, opts = {})
|
|
|
296
295
|
if (waitMs > 0)
|
|
297
296
|
await wait(waitMs, opts.signal);
|
|
298
297
|
};
|
|
299
|
-
const sleepBeforePoll = async () => {
|
|
300
|
-
const waitMs = Math.min(stretchedPollIntervalMs(now() - startedAt, intervalMs), Math.max(0, deadline - now()));
|
|
301
|
-
if (waitMs > 0)
|
|
302
|
-
await wait(waitMs, opts.signal);
|
|
303
|
-
};
|
|
304
298
|
while (now() < deadline) {
|
|
299
|
+
query.set("wait", String(Math.min(45, Math.max(1, Math.ceil((deadline - now()) / 1000)))));
|
|
305
300
|
let poll;
|
|
306
301
|
try {
|
|
307
302
|
poll = await apiFetch(cfg, `/api/v1/stacks/pr-review?${query.toString()}`, {
|
|
308
303
|
signal: opts.signal,
|
|
309
|
-
timeoutMs:
|
|
304
|
+
timeoutMs: Number(query.get("wait")) * 1000 + 5_000,
|
|
310
305
|
});
|
|
311
306
|
}
|
|
312
307
|
catch (err) {
|
|
@@ -331,7 +326,6 @@ export async function pollPrVortexReview(cfg, owner, repo, prNumber, opts = {})
|
|
|
331
326
|
if (poll.status === 404) {
|
|
332
327
|
transientFailures = 0;
|
|
333
328
|
opts.onTick?.("progress");
|
|
334
|
-
await sleepBeforePoll();
|
|
335
329
|
continue;
|
|
336
330
|
}
|
|
337
331
|
if (poll.status !== 200) {
|
|
@@ -358,16 +352,17 @@ export async function pollPrVortexReview(cfg, owner, repo, prNumber, opts = {})
|
|
|
358
352
|
(!isPositiveInteger(envelope.pass) || (opts.pass !== undefined && envelope.pass !== opts.pass) ||
|
|
359
353
|
(opts.afterPass !== undefined && envelope.pass <= opts.afterPass))) {
|
|
360
354
|
opts.onTick?.("progress");
|
|
361
|
-
await sleepBeforePoll();
|
|
362
355
|
continue;
|
|
363
356
|
}
|
|
364
357
|
lastEnvelope = envelope;
|
|
365
358
|
const resting = (lastEnvelope.raw_status ?? lastEnvelope.status) !== "in_progress";
|
|
366
359
|
const matches = !opts.afterSha || shaMatches(lastEnvelope.head_sha, opts.afterSha);
|
|
367
|
-
|
|
360
|
+
// MS-01: A resting completion with newer_pass_pending indicates a newer
|
|
361
|
+
// attempt is in flight. Do not satisfy the wait from this stale result.
|
|
362
|
+
const stale = lastEnvelope.newer_pass_pending === true;
|
|
363
|
+
if (resting && matches && !stale)
|
|
368
364
|
return lastEnvelope;
|
|
369
365
|
opts.onTick?.("progress");
|
|
370
|
-
await sleepBeforePoll();
|
|
371
366
|
}
|
|
372
367
|
throw new PrReviewPollTimeoutError(owner, repo, prNumber, lastEnvelope);
|
|
373
368
|
}
|
package/dist/commands/review.js
CHANGED
|
@@ -40,7 +40,8 @@ function normalizeVortexSpecialistIds(value) {
|
|
|
40
40
|
const selected = new Set(value.filter((id) => typeof id === "string" && VORTEX_SPECIALIST_IDS.includes(id)));
|
|
41
41
|
return VORTEX_SPECIALIST_IDS.filter((id) => selected.has(id));
|
|
42
42
|
}
|
|
43
|
-
const REVIEW_USAGE = "usage: mergestorm review [base] [head] [--json] [--wait|--no-wait] [--timeout seconds] [--router off|standard|max|manual] [--specialists id,id] [--context text] [--context-file path] [--idempotency-key k] [--webhook-url https://…] [--thread slug]"
|
|
43
|
+
const REVIEW_USAGE = "usage: mergestorm review [base] [head] [--json] [--wait|--no-wait] [--timeout seconds] [--router off|standard|max|manual] [--specialists id,id] [--context text] [--context-file path] [--idempotency-key k] [--webhook-url https://…] [--thread slug]\n" +
|
|
44
|
+
"Uploads over 1 MB / 1_000_000 are rejected with HTTP 413 and do not create a job.";
|
|
44
45
|
function usageError(message = REVIEW_USAGE) {
|
|
45
46
|
return new CommandError(message, REVIEW_EXIT.usage, "usage");
|
|
46
47
|
}
|
|
@@ -164,6 +165,9 @@ export function parseReviewArgs(args) {
|
|
|
164
165
|
thread = slug;
|
|
165
166
|
continue;
|
|
166
167
|
}
|
|
168
|
+
if (a === "-h" || a === "--help") {
|
|
169
|
+
throw usageError();
|
|
170
|
+
}
|
|
167
171
|
if (a.startsWith("-")) {
|
|
168
172
|
throw usageError(`unknown flag: ${a}`);
|
|
169
173
|
}
|
|
@@ -227,6 +231,10 @@ function asPollCommandError(err, jobId) {
|
|
|
227
231
|
return new CommandError(withReviewJobRecovery(`Poll failed: ${detail}`, jobId));
|
|
228
232
|
}
|
|
229
233
|
export async function cmdReview(args, opts = {}) {
|
|
234
|
+
if (args.includes("-h") || args.includes("--help")) {
|
|
235
|
+
console.log(REVIEW_USAGE);
|
|
236
|
+
return;
|
|
237
|
+
}
|
|
230
238
|
const parsed = parseReviewArgs(args);
|
|
231
239
|
const base = resolveReviewBase(parsed.base);
|
|
232
240
|
const head = parsed.head || "HEAD";
|
|
@@ -1,17 +1,25 @@
|
|
|
1
1
|
import { type SettingsPatch, type SettingsResponse } from "../api.js";
|
|
2
2
|
/**
|
|
3
|
-
* CLI flag → Bearer settings key. on|off
|
|
3
|
+
* CLI flag → Bearer settings key. Boolean flags take on|off. The connected flags are
|
|
4
4
|
* read-only on the API and deliberately have no flag here.
|
|
5
5
|
*/
|
|
6
|
-
export declare const SETTINGS_FLAGS: Record<string, "auto_review_enabled" | "auto_patch_enabled" | "vortex_show_thinking_traces" | "repo_overview_enabled" | "review_unit_land_prs_enabled" | "cyclone_review_unit_land_prs_enabled" | "vortex_seam_specialist_enabled" | "auto_land_default">;
|
|
6
|
+
export declare const SETTINGS_FLAGS: Record<string, "auto_review_enabled" | "auto_patch_enabled" | "vortex_show_thinking_traces" | "repo_overview_enabled" | "review_unit_land_prs_enabled" | "cyclone_review_unit_land_prs_enabled" | "cyclone_skip_ci_enabled" | "cyclone_patch_unverified_languages" | "vortex_auto_overflow_enabled" | "vortex_skip_all_clear_comments" | "vortex_seam_specialist_enabled" | "auto_land_default" | "ignored_bot_logins" | "vortex_bot_skip_check" | "vortex_findings_check" | "cyclone_patch_failure_check">;
|
|
7
|
+
type IgnoreBotOperation = {
|
|
8
|
+
action: "add" | "remove";
|
|
9
|
+
login: string;
|
|
10
|
+
} | {
|
|
11
|
+
action: "clear";
|
|
12
|
+
};
|
|
7
13
|
export type SettingsArgs = {
|
|
8
14
|
json: boolean;
|
|
9
15
|
patch: SettingsPatch;
|
|
16
|
+
ignoreBots?: IgnoreBotOperation[];
|
|
10
17
|
};
|
|
11
|
-
/** Parse
|
|
18
|
+
/** Parse boolean and enum flags plus ordered ignore-list operations. */
|
|
12
19
|
export declare function parseSettingsArgs(args: string[]): SettingsArgs;
|
|
13
|
-
/** Static printout
|
|
20
|
+
/** Static printout includes the Config toggles plus enum and login settings. */
|
|
14
21
|
export declare function formatSettingsLines(settings: SettingsResponse): string[];
|
|
15
22
|
export declare function cmdSettings(args: string[], opts?: {
|
|
16
23
|
mode?: "oneshot" | "shell";
|
|
17
24
|
}): Promise<void>;
|
|
25
|
+
export {};
|