@h-rig/cli 0.0.6-alpha.9 → 0.0.6-alpha.90
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 +1 -1
- package/dist/bin/build-rig-binaries.d.ts +2 -0
- package/dist/bin/rig.d.ts +2 -0
- package/dist/bin/rig.js +11052 -6668
- package/dist/src/app/board.d.ts +23 -0
- package/dist/src/app/board.js +1786 -0
- package/dist/src/app/drone-ui.d.ts +37 -0
- package/dist/src/app/drone-ui.js +294 -0
- package/dist/src/app/theme.d.ts +47 -0
- package/dist/src/app/theme.js +150 -0
- package/dist/src/commands/_async-ui.d.ts +13 -0
- package/dist/src/commands/_async-ui.js +223 -0
- package/dist/src/commands/_authority-runs.d.ts +22 -0
- package/dist/src/commands/_authority-runs.js +2 -3
- package/dist/src/commands/_cli-format.d.ts +49 -0
- package/dist/src/commands/_cli-format.js +447 -0
- package/dist/src/commands/_connection-state.d.ts +44 -0
- package/dist/src/commands/_connection-state.js +30 -11
- package/dist/src/commands/_doctor-checks.d.ts +52 -0
- package/dist/src/commands/_doctor-checks.js +180 -44
- package/dist/src/commands/_help-catalog.d.ts +51 -0
- package/dist/src/commands/_help-catalog.js +442 -0
- package/dist/src/commands/_json-output.d.ts +11 -0
- package/dist/src/commands/_json-output.js +56 -0
- package/dist/src/commands/_operator-surface.d.ts +34 -0
- package/dist/src/commands/_operator-surface.js +220 -0
- package/dist/src/commands/_operator-view.d.ts +30 -0
- package/dist/src/commands/_operator-view.js +803 -73
- package/dist/src/commands/_parsers.d.ts +15 -0
- package/dist/src/commands/_parsers.js +18 -11
- package/dist/src/commands/_paths.d.ts +11 -0
- package/dist/src/commands/_pi-frontend.d.ts +27 -0
- package/dist/src/commands/_pi-frontend.js +742 -0
- package/dist/src/commands/_pi-install.d.ts +42 -0
- package/dist/src/commands/_pi-install.js +5 -4
- package/dist/src/commands/_policy.d.ts +8 -0
- package/dist/src/commands/_policy.js +12 -5
- package/dist/src/commands/_preflight.d.ts +22 -0
- package/dist/src/commands/_preflight.js +190 -128
- package/dist/src/commands/_probes.d.ts +1 -0
- package/dist/src/commands/_run-driver-helpers.d.ts +99 -0
- package/dist/src/commands/_run-driver-helpers.js +75 -22
- package/dist/src/commands/_run-replay.d.ts +24 -0
- package/dist/src/commands/_run-replay.js +142 -0
- package/dist/src/commands/_server-client.d.ts +186 -0
- package/dist/src/commands/_server-client.js +360 -61
- package/dist/src/commands/_snapshot-upload.d.ts +39 -0
- package/dist/src/commands/_snapshot-upload.js +163 -39
- package/dist/src/commands/_spinner.d.ts +25 -0
- package/dist/src/commands/_spinner.js +65 -0
- package/dist/src/commands/_task-picker.d.ts +9 -0
- package/dist/src/commands/_task-picker.js +172 -19
- package/dist/src/commands/agent.d.ts +3 -0
- package/dist/src/commands/agent.js +39 -20
- package/dist/src/commands/browser.d.ts +65 -0
- package/dist/src/commands/browser.js +334 -51
- package/dist/src/commands/connect.d.ts +7 -0
- package/dist/src/commands/connect.js +272 -33
- package/dist/src/commands/dist.d.ts +28 -0
- package/dist/src/commands/dist.js +19 -12
- package/dist/src/commands/doctor.d.ts +3 -0
- package/dist/src/commands/doctor.js +378 -45
- package/dist/src/commands/github.d.ts +3 -0
- package/dist/src/commands/github.js +375 -53
- package/dist/src/commands/inbox.d.ts +30 -0
- package/dist/src/commands/inbox.js +760 -70
- package/dist/src/commands/init.d.ts +74 -0
- package/dist/src/commands/init.js +963 -119
- package/dist/src/commands/inspect.d.ts +3 -0
- package/dist/src/commands/inspect.js +588 -32
- package/dist/src/commands/inspector.d.ts +3 -0
- package/dist/src/commands/inspector.js +20 -13
- package/dist/src/commands/pi.d.ts +3 -0
- package/dist/src/commands/pi.js +177 -0
- package/dist/src/commands/plugin.d.ts +16 -0
- package/dist/src/commands/plugin.js +95 -27
- package/dist/src/commands/profile-and-review.d.ts +4 -0
- package/dist/src/commands/profile-and-review.js +26 -19
- package/dist/src/commands/queue.d.ts +3 -0
- package/dist/src/commands/queue.js +32 -12
- package/dist/src/commands/remote.d.ts +3 -0
- package/dist/src/commands/remote.js +43 -36
- package/dist/src/commands/repo-git-harness.d.ts +5 -0
- package/dist/src/commands/repo-git-harness.js +22 -15
- package/dist/src/commands/run.d.ts +3 -0
- package/dist/src/commands/run.js +1379 -159
- package/dist/src/commands/server.d.ts +7 -0
- package/dist/src/commands/server.js +502 -57
- package/dist/src/commands/setup.d.ts +16 -0
- package/dist/src/commands/setup.js +390 -63
- package/dist/src/commands/stats.d.ts +12 -0
- package/dist/src/commands/stats.js +1051 -0
- package/dist/src/commands/task-report-bug.d.ts +19 -0
- package/dist/src/commands/task-report-bug.js +260 -62
- package/dist/src/commands/task-run-driver.d.ts +132 -0
- package/dist/src/commands/task-run-driver.js +886 -130
- package/dist/src/commands/task.d.ts +14 -0
- package/dist/src/commands/task.js +1644 -314
- package/dist/src/commands/test.d.ts +3 -0
- package/dist/src/commands/test.js +15 -8
- package/dist/src/commands/workspace.d.ts +3 -0
- package/dist/src/commands/workspace.js +18 -11
- package/dist/src/commands.d.ts +29 -0
- package/dist/src/commands.js +10967 -6637
- package/dist/src/index.d.ts +4 -0
- package/dist/src/index.js +10168 -5787
- package/dist/src/launcher.d.ts +61 -0
- package/dist/src/launcher.js +77 -13
- package/dist/src/report-bug.d.ts +44 -0
- package/dist/src/report-bug.js +3 -3
- package/dist/src/runner.d.ts +47 -0
- package/dist/src/runner.js +16 -22
- package/dist/src/withMutedConsole.d.ts +2 -0
- package/package.json +13 -6
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { type RunnerContext } from "../runner";
|
|
2
|
+
import type { CommandOutcome } from "@rig/runtime/control-plane/runtime/types";
|
|
3
|
+
type BugPromptStyleOptions = {
|
|
4
|
+
color?: boolean;
|
|
5
|
+
};
|
|
6
|
+
export declare function executeTaskReportBug(context: RunnerContext, args: string[]): Promise<CommandOutcome>;
|
|
7
|
+
export declare function promptBugText(message: string, defaultValue: string | undefined, options?: {
|
|
8
|
+
placeholder?: string;
|
|
9
|
+
required?: boolean;
|
|
10
|
+
}): Promise<string>;
|
|
11
|
+
export declare function validateRequiredBugPromptValue(value: string | undefined, label: string): string | undefined;
|
|
12
|
+
type BugPromptExampleSection = "incident" | "reproduction" | "evidence" | "routing" | "browser";
|
|
13
|
+
export declare function bugPromptExampleText(section: BugPromptExampleSection, options?: BugPromptStyleOptions): string;
|
|
14
|
+
export declare function promptBugConfirm(message: string, initialValue: boolean): Promise<boolean>;
|
|
15
|
+
export declare function formatDroppedAssetDefault(value: string): string;
|
|
16
|
+
export declare function splitDroppedAssetList(value: string | undefined, options?: {
|
|
17
|
+
splitWhitespace?: boolean;
|
|
18
|
+
}): string[];
|
|
19
|
+
export {};
|
|
@@ -2,17 +2,213 @@
|
|
|
2
2
|
// packages/cli/src/commands/task-report-bug.ts
|
|
3
3
|
import { existsSync as existsSync2, readFileSync, writeFileSync as writeFileSync2 } from "fs";
|
|
4
4
|
import { resolve as resolve3 } from "path";
|
|
5
|
-
|
|
5
|
+
|
|
6
|
+
// packages/cli/src/app/drone-ui.ts
|
|
7
|
+
import { ProcessTerminal, TUI, Text, Input, SelectList, matchesKey } from "@earendil-works/pi-tui";
|
|
8
|
+
|
|
9
|
+
// packages/cli/src/app/theme.ts
|
|
10
|
+
var RIG_PALETTE = {
|
|
11
|
+
ink: "#f2f3f6",
|
|
12
|
+
ink2: "#aeb0ba",
|
|
13
|
+
ink3: "#6c6e79",
|
|
14
|
+
ink4: "#44464f",
|
|
15
|
+
accent: "#ccff4d",
|
|
16
|
+
accentDim: "#a9d63f",
|
|
17
|
+
cyan: "#56d8ff",
|
|
18
|
+
red: "#ff5d5d",
|
|
19
|
+
yellow: "#ffd24d"
|
|
20
|
+
};
|
|
21
|
+
function hexToRgb(hex) {
|
|
22
|
+
const value = hex.replace("#", "");
|
|
23
|
+
return [
|
|
24
|
+
Number.parseInt(value.slice(0, 2), 16),
|
|
25
|
+
Number.parseInt(value.slice(2, 4), 16),
|
|
26
|
+
Number.parseInt(value.slice(4, 6), 16)
|
|
27
|
+
];
|
|
28
|
+
}
|
|
29
|
+
function fg(hex) {
|
|
30
|
+
const [r, g, b] = hexToRgb(hex);
|
|
31
|
+
return (text) => `\x1B[38;2;${r};${g};${b}m${text}\x1B[39m`;
|
|
32
|
+
}
|
|
33
|
+
var ink = fg(RIG_PALETTE.ink);
|
|
34
|
+
var ink2 = fg(RIG_PALETTE.ink2);
|
|
35
|
+
var ink3 = fg(RIG_PALETTE.ink3);
|
|
36
|
+
var ink4 = fg(RIG_PALETTE.ink4);
|
|
37
|
+
var accent = fg(RIG_PALETTE.accent);
|
|
38
|
+
var accentDim = fg(RIG_PALETTE.accentDim);
|
|
39
|
+
var cyan = fg(RIG_PALETTE.cyan);
|
|
40
|
+
var red = fg(RIG_PALETTE.red);
|
|
41
|
+
var yellow = fg(RIG_PALETTE.yellow);
|
|
42
|
+
function bold(text) {
|
|
43
|
+
return `\x1B[1m${text}\x1B[22m`;
|
|
44
|
+
}
|
|
45
|
+
var DRONE_ART = [
|
|
46
|
+
" .-=-. .-=-. ",
|
|
47
|
+
" ( !!! ) ( !!! ) ",
|
|
48
|
+
" '-=-'._ _.'-=-' ",
|
|
49
|
+
" '._ _.' ",
|
|
50
|
+
" '=$$$$$$$=.' ",
|
|
51
|
+
" =$$$$$$$$$$$= ",
|
|
52
|
+
" $$$@@@@@@@@@@$$$ ",
|
|
53
|
+
" $$$@@ @@$$$ ",
|
|
54
|
+
" $$@ ? @$$$ ",
|
|
55
|
+
" $$$@ '-' @$$$ ",
|
|
56
|
+
" $$$@@ @@$$$ ",
|
|
57
|
+
" $$$@@@@@@@@@@$$$ ",
|
|
58
|
+
" =$$$$$$$$$$$= ",
|
|
59
|
+
" '=$$$$$$$=.' ",
|
|
60
|
+
" _.' '._ ",
|
|
61
|
+
" .-=-.' '.-=-. ",
|
|
62
|
+
" ( !!! ) ( !!! ) ",
|
|
63
|
+
" '-=-' '-=-' "
|
|
64
|
+
];
|
|
65
|
+
var EYE_FRAMES = ["@", "o", "."];
|
|
66
|
+
var DRONE_WIDTH = DRONE_ART[0].length;
|
|
67
|
+
var DRONE_HEIGHT = DRONE_ART.length;
|
|
68
|
+
var MICRO_BLADES = ["---", "\\\\\\", "|||", "///"];
|
|
69
|
+
function microDroneFrame(tick) {
|
|
70
|
+
const blade = MICRO_BLADES[tick % MICRO_BLADES.length];
|
|
71
|
+
const eye = EYE_FRAMES[Math.floor(tick / 2) % EYE_FRAMES.length];
|
|
72
|
+
return `(${blade})${eye}(${blade})`;
|
|
73
|
+
}
|
|
74
|
+
var MICRO_DRONE_FRAMES = Array.from({ length: 12 }, (_, index) => microDroneFrame(index));
|
|
75
|
+
|
|
76
|
+
// packages/cli/src/app/drone-ui.ts
|
|
77
|
+
var isTty = () => Boolean(process.stdout.isTTY);
|
|
78
|
+
function hairline(width = Math.min(process.stdout.columns ?? 80, 100)) {
|
|
79
|
+
return ink4("\u2500".repeat(Math.max(10, width)));
|
|
80
|
+
}
|
|
81
|
+
function droneIntro(title, subtitle) {
|
|
82
|
+
console.log("");
|
|
83
|
+
console.log(` ${accent("\u258D")}${bold(ink(title))}${subtitle ? ink3(` \u2014 ${subtitle}`) : ""}`);
|
|
84
|
+
console.log(hairline());
|
|
85
|
+
}
|
|
86
|
+
function droneOutro(text) {
|
|
87
|
+
console.log(hairline());
|
|
88
|
+
console.log(` ${accent("\u25C6")} ${ink2(text)}`);
|
|
89
|
+
console.log("");
|
|
90
|
+
}
|
|
91
|
+
function droneNote(message, title) {
|
|
92
|
+
if (title)
|
|
93
|
+
console.log(` ${accentDim("\u25C7")} ${bold(ink2(title))}`);
|
|
94
|
+
for (const line of message.split(`
|
|
95
|
+
`)) {
|
|
96
|
+
console.log(` ${ink4("\u2502")} ${line}`);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
function droneStep(text) {
|
|
100
|
+
console.log(` ${accent("\u203A")} ${ink(text)}`);
|
|
101
|
+
}
|
|
102
|
+
function droneInfo(text) {
|
|
103
|
+
console.log(` ${cyan("\xB7")} ${ink2(text)}`);
|
|
104
|
+
}
|
|
105
|
+
function droneCancel(text) {
|
|
106
|
+
console.log(` ${red("\u2716")} ${ink3(text)}`);
|
|
107
|
+
}
|
|
108
|
+
var SELECT_THEME = {
|
|
109
|
+
selectedPrefix: (text) => accent(text),
|
|
110
|
+
selectedText: (text) => bold(ink(text)),
|
|
111
|
+
description: (text) => ink3(text),
|
|
112
|
+
scrollInfo: (text) => ink4(text),
|
|
113
|
+
noMatch: (text) => ink3(text)
|
|
114
|
+
};
|
|
115
|
+
async function runMiniTui(build) {
|
|
116
|
+
const terminal = new ProcessTerminal;
|
|
117
|
+
const tui = new TUI(terminal);
|
|
118
|
+
let settled = false;
|
|
119
|
+
return await new Promise((resolve) => {
|
|
120
|
+
const finish = (result) => {
|
|
121
|
+
if (settled)
|
|
122
|
+
return;
|
|
123
|
+
settled = true;
|
|
124
|
+
tui.stop();
|
|
125
|
+
resolve(result);
|
|
126
|
+
};
|
|
127
|
+
build(tui, finish);
|
|
128
|
+
tui.start();
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
async function droneSelect(input) {
|
|
132
|
+
if (!isTty() || input.options.length === 0) {
|
|
133
|
+
return input.initialValue ?? input.options[0]?.value ?? null;
|
|
134
|
+
}
|
|
135
|
+
return runMiniTui((tui, finish) => {
|
|
136
|
+
tui.addChild(new Text(` ${accent("\u258D")}${bold(ink(input.message))}`));
|
|
137
|
+
const items = input.options.map((option) => ({
|
|
138
|
+
value: option.value,
|
|
139
|
+
label: option.label,
|
|
140
|
+
...option.hint ? { description: option.hint } : {}
|
|
141
|
+
}));
|
|
142
|
+
const list = new SelectList(items, Math.min(items.length, 12), SELECT_THEME);
|
|
143
|
+
const initialIndex = input.initialValue ? items.findIndex((item) => item.value === input.initialValue) : -1;
|
|
144
|
+
if (initialIndex > 0)
|
|
145
|
+
list.setSelectedIndex(initialIndex);
|
|
146
|
+
list.onSelect = (item) => finish(item.value);
|
|
147
|
+
list.onCancel = () => finish(null);
|
|
148
|
+
tui.addChild(list);
|
|
149
|
+
tui.addChild(new Text(ink4(" \u2191\u2193 navigate \xB7 enter select \xB7 esc cancel")));
|
|
150
|
+
tui.setFocus(list);
|
|
151
|
+
tui.addInputListener((data) => {
|
|
152
|
+
if (matchesKey(data, "ctrl+c") || matchesKey(data, "escape")) {
|
|
153
|
+
finish(null);
|
|
154
|
+
return { consume: true };
|
|
155
|
+
}
|
|
156
|
+
return;
|
|
157
|
+
});
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
async function droneText(input) {
|
|
161
|
+
if (!isTty())
|
|
162
|
+
return input.initialValue ?? null;
|
|
163
|
+
return runMiniTui((tui, finish) => {
|
|
164
|
+
tui.addChild(new Text(` ${accent("\u258D")}${bold(ink(input.message))}${input.placeholder ? ink4(` (${input.placeholder})`) : ""}`));
|
|
165
|
+
const field = new Input;
|
|
166
|
+
if (input.initialValue)
|
|
167
|
+
field.setValue(input.initialValue);
|
|
168
|
+
field.onSubmit = (value) => finish(value);
|
|
169
|
+
field.onEscape = () => finish(null);
|
|
170
|
+
tui.addChild(field);
|
|
171
|
+
tui.addChild(new Text(ink4(" enter submit \xB7 esc cancel")));
|
|
172
|
+
tui.setFocus(field);
|
|
173
|
+
tui.addInputListener((data) => {
|
|
174
|
+
if (matchesKey(data, "ctrl+c")) {
|
|
175
|
+
finish(null);
|
|
176
|
+
return { consume: true };
|
|
177
|
+
}
|
|
178
|
+
return;
|
|
179
|
+
});
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
async function droneConfirm(input) {
|
|
183
|
+
const answer = await droneSelect({
|
|
184
|
+
message: input.message,
|
|
185
|
+
options: [
|
|
186
|
+
{ value: "yes", label: "Yes" },
|
|
187
|
+
{ value: "no", label: "No" }
|
|
188
|
+
],
|
|
189
|
+
initialValue: input.initialValue === false ? "no" : "yes"
|
|
190
|
+
});
|
|
191
|
+
return answer === null ? null : answer === "yes";
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// packages/cli/src/commands/task-report-bug.ts
|
|
6
195
|
import pc from "picocolors";
|
|
7
196
|
|
|
8
197
|
// packages/cli/src/runner.ts
|
|
9
198
|
import { EventBus } from "@rig/runtime/control-plane/runtime/events";
|
|
10
|
-
import { CliError } from "@rig/runtime/control-plane/errors";
|
|
199
|
+
import { CliError as RuntimeCliError } from "@rig/runtime/control-plane/errors";
|
|
11
200
|
import { evaluate, loadPolicy, resolveAction } from "@rig/runtime/control-plane/runtime/guard";
|
|
12
|
-
import { PluginManager } from "@rig/runtime/control-plane/runtime/plugins";
|
|
13
|
-
import { loadRuntimeContextFromEnv } from "@rig/runtime/control-plane/runtime/context";
|
|
14
201
|
import { buildBinary } from "@rig/runtime/control-plane/runtime/isolation";
|
|
15
|
-
|
|
202
|
+
|
|
203
|
+
class CliError extends RuntimeCliError {
|
|
204
|
+
hint;
|
|
205
|
+
constructor(message, exitCode = 1, options = {}) {
|
|
206
|
+
super(message, exitCode);
|
|
207
|
+
if (options.hint?.trim()) {
|
|
208
|
+
this.hint = options.hint.trim();
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
}
|
|
16
212
|
function formatCommand(parts) {
|
|
17
213
|
return parts.map((part) => /[^a-zA-Z0-9_./:-]/.test(part) ? JSON.stringify(part) : part).join(" ");
|
|
18
214
|
}
|
|
@@ -36,7 +232,7 @@ function takeOption(args, option) {
|
|
|
36
232
|
if (current === option) {
|
|
37
233
|
const next = args[index + 1];
|
|
38
234
|
if (!next || next.startsWith("-")) {
|
|
39
|
-
throw new CliError(`Missing value for ${option}`);
|
|
235
|
+
throw new CliError(`Missing value for ${option}`, 1, { hint: `Provide a value after ${option}, e.g. \`${option} <value>\`.` });
|
|
40
236
|
}
|
|
41
237
|
value = next;
|
|
42
238
|
index += 1;
|
|
@@ -241,15 +437,15 @@ function buildBugReportMarkdown(input, browser, screenshots, assets) {
|
|
|
241
437
|
...input.issueId ? [
|
|
242
438
|
`- Canonical task assets live under \`artifacts/${input.issueId}/bug-report/\`.`,
|
|
243
439
|
`- Start with \`artifacts/${input.issueId}/bug-report/task.md\` and the files in \`artifacts/${input.issueId}/bug-report/assets/\`.`,
|
|
244
|
-
browserRequired ? `- Run \`
|
|
440
|
+
browserRequired ? `- Run \`rig task info --task ${input.issueId}\` to confirm browser wiring before debugging.` : `- Run \`rig task info --task ${input.issueId}\` to confirm scope and artifact links before debugging.`
|
|
245
441
|
] : [
|
|
246
|
-
"- Draft-only report: convert this into a
|
|
442
|
+
"- Draft-only report: convert this into a Rig task before assigning it to an agent run."
|
|
247
443
|
],
|
|
248
444
|
"",
|
|
249
445
|
"## Validation",
|
|
250
446
|
"",
|
|
251
447
|
"```bash",
|
|
252
|
-
...input.issueId ? [`
|
|
448
|
+
...input.issueId ? [`rig task validate --task ${input.issueId}`] : [],
|
|
253
449
|
...browserRequired ? [
|
|
254
450
|
"bun run app:check:browser:hp-next",
|
|
255
451
|
"bun run app:e2e:browser:hp-next"
|
|
@@ -344,7 +540,7 @@ async function executeTaskReportBug(context, args) {
|
|
|
344
540
|
const noBrowserFlag = takeFlag(pending, "--no-browser");
|
|
345
541
|
pending = noBrowserFlag.rest;
|
|
346
542
|
if (browserFlag.value && noBrowserFlag.value) {
|
|
347
|
-
throw new
|
|
543
|
+
throw new CliError("Pass only one of --browser or --no-browser.", 1, { hint: "Re-run `rig task report-bug` with just one of the flags." });
|
|
348
544
|
}
|
|
349
545
|
const overwriteFlag = takeFlag(pending, "--overwrite");
|
|
350
546
|
pending = overwriteFlag.rest;
|
|
@@ -396,7 +592,7 @@ async function executeTaskReportBug(context, args) {
|
|
|
396
592
|
pending = outputRootResult.rest;
|
|
397
593
|
const slugResult = takeOption(pending, "--slug");
|
|
398
594
|
pending = slugResult.rest;
|
|
399
|
-
requireNoExtraArgs(pending, "
|
|
595
|
+
requireNoExtraArgs(pending, "rig report-bug [--no-prompt] [--no-beads] [--browser|--no-browser] --title <text> --url <url> [--asset <dragged-file>]");
|
|
400
596
|
let draft = {
|
|
401
597
|
outputRoot: outputRootResult.value || "",
|
|
402
598
|
title: titleResult.value,
|
|
@@ -428,7 +624,7 @@ async function executeTaskReportBug(context, args) {
|
|
|
428
624
|
const shouldPrompt = !noPromptFlag.value;
|
|
429
625
|
if (shouldPrompt) {
|
|
430
626
|
if (context.outputMode !== "text" || !process.stdin.isTTY || !process.stdout.isTTY) {
|
|
431
|
-
throw new
|
|
627
|
+
throw new CliError("Interactive bug reporting requires a TTY in text mode. Pass --no-prompt with flags for automation.");
|
|
432
628
|
}
|
|
433
629
|
draft = await promptForBugReportDetails(draft);
|
|
434
630
|
}
|
|
@@ -501,7 +697,7 @@ async function executeTaskReportBug(context, args) {
|
|
|
501
697
|
console.log(`Evidence assets: ${result.assetDir}`);
|
|
502
698
|
if (taskConfigPath) {
|
|
503
699
|
console.log(`Task config: ${taskConfigPath}`);
|
|
504
|
-
console.log(`Run:
|
|
700
|
+
console.log(`Run: rig task info --task ${issueId}`);
|
|
505
701
|
}
|
|
506
702
|
}
|
|
507
703
|
return {
|
|
@@ -532,7 +728,7 @@ function validateBugReportInputFiles(input) {
|
|
|
532
728
|
for (const { path, label } of files.map((item) => ({ ...item, path: item.path.trim() })).filter((item) => item.path)) {
|
|
533
729
|
const source = resolve3(input.projectRoot, path);
|
|
534
730
|
if (!existsSync2(source)) {
|
|
535
|
-
throw new
|
|
731
|
+
throw new CliError(`${label} does not exist: ${source}`, 1, { hint: "Check the path and re-run `rig task report-bug` with an existing file." });
|
|
536
732
|
}
|
|
537
733
|
}
|
|
538
734
|
}
|
|
@@ -572,7 +768,7 @@ function createBugReportBeadsTask(monorepoRoot, input, draft) {
|
|
|
572
768
|
const issue = tryRunBrJson(monorepoRoot, command);
|
|
573
769
|
if (!issue.ok) {
|
|
574
770
|
if (!isRecoverableBeadsJsonlFailure(issue.error)) {
|
|
575
|
-
throw new
|
|
771
|
+
throw new CliError(issue.error);
|
|
576
772
|
}
|
|
577
773
|
return {
|
|
578
774
|
issueId: generateBugReportIssueId(monorepoRoot, input.title),
|
|
@@ -583,7 +779,7 @@ function createBugReportBeadsTask(monorepoRoot, input, draft) {
|
|
|
583
779
|
}
|
|
584
780
|
const issueId = issue.value.id?.trim();
|
|
585
781
|
if (!issueId) {
|
|
586
|
-
throw new
|
|
782
|
+
throw new CliError("br create did not return an issue id.", 1, { hint: "Re-run `rig task report-bug`; if it persists, file the bug via your task source directly." });
|
|
587
783
|
}
|
|
588
784
|
return {
|
|
589
785
|
issueId,
|
|
@@ -690,12 +886,12 @@ ${serializedEntry}
|
|
|
690
886
|
}
|
|
691
887
|
const insertAt = raw.lastIndexOf("}");
|
|
692
888
|
if (insertAt < 0) {
|
|
693
|
-
throw new
|
|
889
|
+
throw new CliError(`Invalid task config JSON object: ${taskConfigPath}`, 1, { hint: "Fix or reset that file (it must be a JSON object), then re-run `rig task report-bug`." });
|
|
694
890
|
}
|
|
695
891
|
const before = raw.slice(0, insertAt).replace(/\s*$/, "");
|
|
696
892
|
const after = raw.slice(insertAt + 1).trim();
|
|
697
893
|
if (after) {
|
|
698
|
-
throw new
|
|
894
|
+
throw new CliError(`Invalid trailing content in task config: ${taskConfigPath}`, 1, { hint: "Remove the trailing content so the file is a single JSON object, then retry." });
|
|
699
895
|
}
|
|
700
896
|
const comma = before.trim() === "{" ? "" : ",";
|
|
701
897
|
writeFileSync2(taskConfigPath, `${before}${comma}
|
|
@@ -763,7 +959,7 @@ function generateBugReportIssueId(monorepoRoot, title) {
|
|
|
763
959
|
return id;
|
|
764
960
|
}
|
|
765
961
|
}
|
|
766
|
-
throw new
|
|
962
|
+
throw new CliError("Could not generate a unique bug task id.", 1, { hint: "Re-run `rig task report-bug`; pass an explicit title to vary the generated id." });
|
|
767
963
|
}
|
|
768
964
|
function isRecoverableBeadsJsonlFailure(message) {
|
|
769
965
|
return /Invalid JSON|missing field|JSONL is newer than DB|stale database/i.test(message);
|
|
@@ -771,7 +967,7 @@ function isRecoverableBeadsJsonlFailure(message) {
|
|
|
771
967
|
function runBrJson(cwd, command) {
|
|
772
968
|
const result = tryRunBrJson(cwd, command);
|
|
773
969
|
if (!result.ok) {
|
|
774
|
-
throw new
|
|
970
|
+
throw new CliError(result.error);
|
|
775
971
|
}
|
|
776
972
|
return result.value;
|
|
777
973
|
}
|
|
@@ -797,14 +993,14 @@ ${result.stdout.trim() || String(error)}`
|
|
|
797
993
|
}
|
|
798
994
|
}
|
|
799
995
|
async function promptForBugReportDetails(initial) {
|
|
800
|
-
|
|
801
|
-
|
|
996
|
+
droneIntro("rig report-bug");
|
|
997
|
+
droneNote([
|
|
802
998
|
"Creates an agent-ready issue with copied evidence files.",
|
|
803
999
|
"When prompted for assets, drag screenshots/videos into the terminal and press Enter."
|
|
804
1000
|
].join(`
|
|
805
1001
|
`), "Bug report wizard");
|
|
806
|
-
|
|
807
|
-
|
|
1002
|
+
droneStep("1/5 Incident");
|
|
1003
|
+
droneNote(bugPromptExampleText("incident"), "Input examples");
|
|
808
1004
|
const title = await promptBugText("Bug title", initial.title, {
|
|
809
1005
|
required: true,
|
|
810
1006
|
placeholder: "Login page never leaves loading"
|
|
@@ -825,8 +1021,8 @@ async function promptForBugReportDetails(initial) {
|
|
|
825
1021
|
const summary = await promptBugText("Short summary", initial.summary, {
|
|
826
1022
|
placeholder: "Email field never appears after navigating from credentials."
|
|
827
1023
|
});
|
|
828
|
-
|
|
829
|
-
|
|
1024
|
+
droneStep("2/5 Reproduction");
|
|
1025
|
+
droneNote(bugPromptExampleText("reproduction"), "Input examples");
|
|
830
1026
|
const steps = splitPromptList(await promptBugText("Repro steps (semicolon-separated)", initial.steps.join("; "), {
|
|
831
1027
|
placeholder: "Open /login; Enter qa@example.com; Press Continue"
|
|
832
1028
|
}));
|
|
@@ -836,14 +1032,14 @@ async function promptForBugReportDetails(initial) {
|
|
|
836
1032
|
const actual = await promptBugText("Actual behavior", initial.actual, {
|
|
837
1033
|
placeholder: "Loading shell stays forever."
|
|
838
1034
|
});
|
|
839
|
-
|
|
840
|
-
|
|
1035
|
+
droneStep("3/5 Evidence");
|
|
1036
|
+
droneNote(bugPromptExampleText("evidence"), "Input examples");
|
|
841
1037
|
const evidence = splitPromptList(await promptBugText("Evidence notes (console/network/API; semicolon-separated)", initial.evidence.join("; "), {
|
|
842
1038
|
placeholder: "Console: ChunkLoadError for credentials route; Network: /assets/app.js 404"
|
|
843
1039
|
}));
|
|
844
1040
|
const assets = splitDroppedAssetList(await promptBugText("Drag screenshots/videos here (Enter to skip)", initial.assets.map(formatDroppedAssetDefault).join(" "), { placeholder: "/Users/me/Desktop/login-loading.png /Users/me/Desktop/otp-flow.webm" }));
|
|
845
|
-
|
|
846
|
-
|
|
1041
|
+
droneStep("4/5 Routing");
|
|
1042
|
+
droneNote(bugPromptExampleText("routing"), "Input examples");
|
|
847
1043
|
const priority = await promptBugSelect("Priority", [
|
|
848
1044
|
{ value: "P0", label: "P0", hint: "urgent / blocking" },
|
|
849
1045
|
{ value: "P1", label: "P1", hint: "high" },
|
|
@@ -857,13 +1053,13 @@ async function promptForBugReportDetails(initial) {
|
|
|
857
1053
|
const parent = await promptBugText("Parent task or epic id (optional)", initial.parent, {
|
|
858
1054
|
placeholder: "bd-auth-epic-123"
|
|
859
1055
|
});
|
|
860
|
-
|
|
861
|
-
|
|
1056
|
+
droneStep("5/5 Browser");
|
|
1057
|
+
droneNote(bugPromptExampleText("browser"), "Input examples");
|
|
862
1058
|
const browserRequired = await promptBugConfirm("Does this task need Rig Browser wiring?", initial.browserRequired);
|
|
863
1059
|
let viewport = initial.viewport || "1440x900";
|
|
864
1060
|
let profile = initial.profile;
|
|
865
1061
|
if (browserRequired) {
|
|
866
|
-
|
|
1062
|
+
droneNote([
|
|
867
1063
|
"A profile is the browser state bucket: cookies, localStorage, auth session, and cache.",
|
|
868
1064
|
"Use a bug-specific profile for clean login/OTP runs; use a shared profile only when saved auth matters."
|
|
869
1065
|
].join(`
|
|
@@ -871,11 +1067,11 @@ async function promptForBugReportDetails(initial) {
|
|
|
871
1067
|
viewport = await promptBugText("Viewport", viewport, { placeholder: "1440x900" });
|
|
872
1068
|
profile = await promptBugText("Rig Browser profile", initial.profile || (title ? defaultBrowserBugProfile(title) : undefined), { placeholder: "hp-next-login-loading-clean" });
|
|
873
1069
|
} else {
|
|
874
|
-
|
|
1070
|
+
droneInfo("Browser wiring skipped. The task will keep assets and steps, but no browser block or browser validation.");
|
|
875
1071
|
}
|
|
876
1072
|
const outputRoot = initial.createBeadsTask ? initial.outputRoot : await promptBugText("Output directory", initial.outputRoot || "docs/bug-reports");
|
|
877
1073
|
const overwrite = await promptBugConfirm("Overwrite if report exists?", initial.overwrite);
|
|
878
|
-
|
|
1074
|
+
droneOutro("Bug report input captured.");
|
|
879
1075
|
return {
|
|
880
1076
|
...initial,
|
|
881
1077
|
outputRoot,
|
|
@@ -902,13 +1098,21 @@ async function promptForBugReportDetails(initial) {
|
|
|
902
1098
|
};
|
|
903
1099
|
}
|
|
904
1100
|
async function promptBugText(message, defaultValue, options = {}) {
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
1101
|
+
for (;; ) {
|
|
1102
|
+
const result = await droneText({
|
|
1103
|
+
message,
|
|
1104
|
+
...options.placeholder ? { placeholder: options.placeholder } : {},
|
|
1105
|
+
...defaultValue?.trim() ? { initialValue: defaultValue } : {}
|
|
1106
|
+
});
|
|
1107
|
+
if (result === null) {
|
|
1108
|
+
droneCancel("Bug report cancelled.");
|
|
1109
|
+
throw new CliError("Bug report cancelled by user.");
|
|
1110
|
+
}
|
|
1111
|
+
const invalid = options.required ? validateRequiredBugPromptValue(result, message) : undefined;
|
|
1112
|
+
if (!invalid)
|
|
1113
|
+
return result.trim();
|
|
1114
|
+
droneInfo(invalid);
|
|
1115
|
+
}
|
|
912
1116
|
}
|
|
913
1117
|
function validateRequiredBugPromptValue(value, label) {
|
|
914
1118
|
return value?.trim() ? undefined : `${label} is required.`;
|
|
@@ -917,7 +1121,7 @@ function bugPromptExampleText(section, options = {}) {
|
|
|
917
1121
|
const c = pc.createColors(options.color ?? shouldColorizeCliOutput());
|
|
918
1122
|
const label = (value) => c.bold(c.cyan(value));
|
|
919
1123
|
const example = (value) => c.green(value);
|
|
920
|
-
const
|
|
1124
|
+
const note = (value) => c.dim(value);
|
|
921
1125
|
const rows = {
|
|
922
1126
|
incident: [
|
|
923
1127
|
["Bug title", "Login page never leaves loading", "short user-visible failure"],
|
|
@@ -946,30 +1150,24 @@ function bugPromptExampleText(section, options = {}) {
|
|
|
946
1150
|
]
|
|
947
1151
|
};
|
|
948
1152
|
return rows[section].map(([name, value, detail]) => {
|
|
949
|
-
const suffix = detail ? ` ${
|
|
1153
|
+
const suffix = detail ? ` ${note(`(${detail})`)}` : "";
|
|
950
1154
|
return `${label(name)}: ${example(value)}${suffix}`;
|
|
951
1155
|
}).join(`
|
|
952
1156
|
`);
|
|
953
1157
|
}
|
|
954
1158
|
async function promptBugConfirm(message, initialValue) {
|
|
955
|
-
const result = await
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
1159
|
+
const result = await droneConfirm({ message, initialValue });
|
|
1160
|
+
if (result === null) {
|
|
1161
|
+
droneCancel("Bug report cancelled.");
|
|
1162
|
+
throw new CliError("Bug report cancelled by user.");
|
|
1163
|
+
}
|
|
1164
|
+
return result;
|
|
960
1165
|
}
|
|
961
1166
|
async function promptBugSelect(message, options, initialValue) {
|
|
962
|
-
const result = await
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
});
|
|
967
|
-
return unwrapClackPrompt(result);
|
|
968
|
-
}
|
|
969
|
-
function unwrapClackPrompt(result) {
|
|
970
|
-
if (clack.isCancel(result)) {
|
|
971
|
-
clack.cancel("Bug report cancelled.");
|
|
972
|
-
throw new CliError2("Bug report cancelled by user.");
|
|
1167
|
+
const result = await droneSelect({ message, options, initialValue });
|
|
1168
|
+
if (result === null) {
|
|
1169
|
+
droneCancel("Bug report cancelled.");
|
|
1170
|
+
throw new CliError("Bug report cancelled by user.");
|
|
973
1171
|
}
|
|
974
1172
|
return result;
|
|
975
1173
|
}
|
|
@@ -979,7 +1177,7 @@ function normalizeBugEnvironmentChoice(environment) {
|
|
|
979
1177
|
function requireReportBugValue(value, option) {
|
|
980
1178
|
const normalized = value?.trim();
|
|
981
1179
|
if (!normalized) {
|
|
982
|
-
throw new
|
|
1180
|
+
throw new CliError(`Missing ${option}. Run interactively or pass ${option} <value>.`);
|
|
983
1181
|
}
|
|
984
1182
|
return normalized;
|
|
985
1183
|
}
|
|
@@ -1060,7 +1258,7 @@ function takeRepeatedOption(args, option) {
|
|
|
1060
1258
|
if (current === option) {
|
|
1061
1259
|
const next = args[index + 1];
|
|
1062
1260
|
if (!next || next.startsWith("-")) {
|
|
1063
|
-
throw new
|
|
1261
|
+
throw new CliError(`Missing value for ${option}`, 1, { hint: `Provide a value after ${option}, e.g. \`${option} <value>\`.` });
|
|
1064
1262
|
}
|
|
1065
1263
|
values.push(next);
|
|
1066
1264
|
index += 1;
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import { type RunnerContext } from "../runner";
|
|
2
|
+
import { updateConfiguredTaskSourceTask } from "@rig/runtime/control-plane/tasks/source-lifecycle";
|
|
3
|
+
import { runPrAutomation, type GitCommandRunner, type GitHubCommandRunner, type PrAutomationResult, type RigAutomationConfig } from "@rig/runtime/control-plane/native/pr-automation";
|
|
4
|
+
import { type SourceTaskContract } from "./_run-driver-helpers";
|
|
5
|
+
export type TaskRunReviewState = {
|
|
6
|
+
approved?: boolean;
|
|
7
|
+
provider?: string;
|
|
8
|
+
mode?: string;
|
|
9
|
+
verdict?: string;
|
|
10
|
+
local_reasons?: string[];
|
|
11
|
+
ai_reasons?: string[];
|
|
12
|
+
ai_warnings?: string[];
|
|
13
|
+
};
|
|
14
|
+
declare const PI_CANONICAL_RUN_STAGES: readonly ["Connect", "GitHub/task sync", "Prepare workspace", "Launch Pi", "Plan", "Implement", "Validate", "Commit", "Open PR", "Review/CI", "Merge", "Complete"];
|
|
15
|
+
export declare function canonicalPiRunStages(): string[];
|
|
16
|
+
export declare function buildPiRigBridgeEnv(input: {
|
|
17
|
+
readonly projectRoot: string;
|
|
18
|
+
readonly runId: string;
|
|
19
|
+
readonly taskId: string;
|
|
20
|
+
readonly serverUrl?: string | null;
|
|
21
|
+
readonly authToken?: string | null;
|
|
22
|
+
readonly githubToken?: string | null;
|
|
23
|
+
}): Record<string, string>;
|
|
24
|
+
export declare function applyDirtyBaselineSnapshot(input: {
|
|
25
|
+
readonly sourceRoot: string;
|
|
26
|
+
readonly targetRoot: string;
|
|
27
|
+
}): {
|
|
28
|
+
applied: boolean;
|
|
29
|
+
copiedUntracked: number;
|
|
30
|
+
detail: string;
|
|
31
|
+
};
|
|
32
|
+
export declare function buildTaskRunReviewEnv(config?: TaskRunAutomationConfig | null): Record<string, string>;
|
|
33
|
+
export declare function buildDirtyBaselineHandshakeEnv(input: {
|
|
34
|
+
readonly projectRoot: string;
|
|
35
|
+
readonly runId: string;
|
|
36
|
+
readonly baselineMode?: "head" | "dirty-snapshot";
|
|
37
|
+
}): Record<string, string>;
|
|
38
|
+
type TaskRunAutomationConfig = RigAutomationConfig & {
|
|
39
|
+
readonly github?: {
|
|
40
|
+
readonly issueUpdates?: "lifecycle" | "minimal" | "off";
|
|
41
|
+
};
|
|
42
|
+
readonly planning?: {
|
|
43
|
+
readonly mode?: "auto" | "always" | "off";
|
|
44
|
+
readonly requireForLabels?: readonly string[];
|
|
45
|
+
readonly skipForLabels?: readonly string[];
|
|
46
|
+
};
|
|
47
|
+
};
|
|
48
|
+
export declare function resolveTaskRunAutomationLimits(config?: TaskRunAutomationConfig | null, env?: Record<string, string | undefined>): {
|
|
49
|
+
maxValidationAttempts: number;
|
|
50
|
+
maxPrFixIterations: number;
|
|
51
|
+
};
|
|
52
|
+
export type PlanningClassification = {
|
|
53
|
+
readonly planningRequired: boolean;
|
|
54
|
+
readonly size: "small" | "medium" | "large";
|
|
55
|
+
readonly risk: "low" | "medium" | "high";
|
|
56
|
+
readonly reason: string;
|
|
57
|
+
readonly policy: "always" | "off" | "auto";
|
|
58
|
+
};
|
|
59
|
+
export declare function classifyPlanningNeed(input: {
|
|
60
|
+
readonly config?: TaskRunAutomationConfig | null;
|
|
61
|
+
readonly sourceTask?: SourceTaskContract | null;
|
|
62
|
+
}): PlanningClassification;
|
|
63
|
+
export declare function buildPiValidationRetrySteeringPrompt(input: {
|
|
64
|
+
taskId: string;
|
|
65
|
+
attempt: number;
|
|
66
|
+
maxAttempts: number;
|
|
67
|
+
failureDetail: string;
|
|
68
|
+
validationOutput?: string | null;
|
|
69
|
+
}): string;
|
|
70
|
+
export declare function classifyValidationRetryOutcome(input: {
|
|
71
|
+
attempt: number;
|
|
72
|
+
maxAttempts: number;
|
|
73
|
+
failureDetail: string;
|
|
74
|
+
}): {
|
|
75
|
+
stage: "Validate failed";
|
|
76
|
+
status: "retry" | "needs_attention";
|
|
77
|
+
failureDetail: string;
|
|
78
|
+
};
|
|
79
|
+
export type TaskRunStageName = typeof PI_CANONICAL_RUN_STAGES[number] | "Needs attention" | "Failed";
|
|
80
|
+
export declare function taskRunStageLogId(runId: string, stage: TaskRunStageName): string;
|
|
81
|
+
export type TaskRunPostValidationLifecycleResult = {
|
|
82
|
+
readonly status: "completed" | "skipped" | "needs_attention";
|
|
83
|
+
readonly pr?: PrAutomationResult;
|
|
84
|
+
};
|
|
85
|
+
export declare function runTaskRunPostValidationLifecycle(input: {
|
|
86
|
+
readonly projectRoot: string;
|
|
87
|
+
readonly runId: string;
|
|
88
|
+
readonly taskId?: string;
|
|
89
|
+
readonly runtimeTaskId: string;
|
|
90
|
+
readonly runtimeWorkspace?: string | null;
|
|
91
|
+
readonly branch?: string | null;
|
|
92
|
+
readonly config?: TaskRunAutomationConfig | null;
|
|
93
|
+
readonly sourceTask: SourceTaskContract | null;
|
|
94
|
+
readonly uploadedSnapshot?: boolean;
|
|
95
|
+
readonly appendStage?: (stage: TaskRunStageName, detail?: string | null, status?: string, tone?: "info" | "tool" | "error") => void;
|
|
96
|
+
readonly ghCommand?: GitHubCommandRunner;
|
|
97
|
+
readonly gitCommand?: GitCommandRunner;
|
|
98
|
+
readonly prAutomation?: typeof runPrAutomation;
|
|
99
|
+
readonly steerPi?: (message: string) => Promise<void>;
|
|
100
|
+
readonly updateTaskSource?: typeof updateConfiguredTaskSourceTask;
|
|
101
|
+
}): Promise<TaskRunPostValidationLifecycleResult>;
|
|
102
|
+
export declare function classifyCompletionVerificationLine(line: string): {
|
|
103
|
+
isCompletionLine: boolean;
|
|
104
|
+
isVerifierReview: boolean;
|
|
105
|
+
};
|
|
106
|
+
export declare function createRunLogIdFactory(runId: string): () => string;
|
|
107
|
+
export declare function summarizeTaskRunProcessFailure(input: {
|
|
108
|
+
exitCode: number | null;
|
|
109
|
+
signal: string | null;
|
|
110
|
+
stderrLines?: readonly string[];
|
|
111
|
+
}): string;
|
|
112
|
+
export declare function readTaskRunAcceptedArtifactState(input: {
|
|
113
|
+
taskId: string | null;
|
|
114
|
+
workspaceDir: string | null;
|
|
115
|
+
artifactNotBeforeMs?: number;
|
|
116
|
+
}): {
|
|
117
|
+
accepted: boolean;
|
|
118
|
+
reason: string | null;
|
|
119
|
+
};
|
|
120
|
+
export declare function executeRigOwnedTaskRun(context: RunnerContext, input: {
|
|
121
|
+
runId: string;
|
|
122
|
+
taskId?: string;
|
|
123
|
+
title?: string;
|
|
124
|
+
runtimeAdapter: "claude-code" | "codex" | "pi";
|
|
125
|
+
model?: string;
|
|
126
|
+
runtimeMode: string;
|
|
127
|
+
interactionMode: string;
|
|
128
|
+
initialPrompt?: string;
|
|
129
|
+
baselineMode?: "head" | "dirty-snapshot";
|
|
130
|
+
prMode?: "auto" | "ask" | "off";
|
|
131
|
+
}): Promise<void>;
|
|
132
|
+
export {};
|