@h-rig/cli 0.0.6-alpha.78 → 0.0.6-alpha.79

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.
Files changed (69) hide show
  1. package/dist/bin/build-rig-binaries.d.ts +2 -0
  2. package/dist/bin/rig.d.ts +2 -0
  3. package/dist/bin/rig.js +37 -13
  4. package/dist/src/app/board.d.ts +23 -0
  5. package/dist/src/app/board.js +11 -8
  6. package/dist/src/app/drone-ui.d.ts +37 -0
  7. package/dist/src/app/theme.d.ts +47 -0
  8. package/dist/src/commands/_async-ui.d.ts +13 -0
  9. package/dist/src/commands/_authority-runs.d.ts +22 -0
  10. package/dist/src/commands/_cli-format.d.ts +49 -0
  11. package/dist/src/commands/_connection-state.d.ts +44 -0
  12. package/dist/src/commands/_doctor-checks.d.ts +52 -0
  13. package/dist/src/commands/_help-catalog.d.ts +51 -0
  14. package/dist/src/commands/_help-catalog.js +1 -0
  15. package/dist/src/commands/_json-output.d.ts +11 -0
  16. package/dist/src/commands/_operator-surface.d.ts +34 -0
  17. package/dist/src/commands/_operator-view.d.ts +30 -0
  18. package/dist/src/commands/_parsers.d.ts +15 -0
  19. package/dist/src/commands/_paths.d.ts +11 -0
  20. package/dist/src/commands/_pi-frontend.d.ts +27 -0
  21. package/dist/src/commands/_pi-install.d.ts +42 -0
  22. package/dist/src/commands/_pi-install.js +1 -1
  23. package/dist/src/commands/_policy.d.ts +8 -0
  24. package/dist/src/commands/_preflight.d.ts +22 -0
  25. package/dist/src/commands/_probes.d.ts +1 -0
  26. package/dist/src/commands/_run-driver-helpers.d.ts +99 -0
  27. package/dist/src/commands/_run-replay.d.ts +24 -0
  28. package/dist/src/commands/_server-client.d.ts +186 -0
  29. package/dist/src/commands/_snapshot-upload.d.ts +39 -0
  30. package/dist/src/commands/_spinner.d.ts +25 -0
  31. package/dist/src/commands/_task-picker.d.ts +9 -0
  32. package/dist/src/commands/agent.d.ts +3 -0
  33. package/dist/src/commands/browser.d.ts +65 -0
  34. package/dist/src/commands/connect.d.ts +7 -0
  35. package/dist/src/commands/dist.d.ts +28 -0
  36. package/dist/src/commands/doctor.d.ts +3 -0
  37. package/dist/src/commands/github.d.ts +3 -0
  38. package/dist/src/commands/inbox.d.ts +30 -0
  39. package/dist/src/commands/init.d.ts +74 -0
  40. package/dist/src/commands/init.js +1 -1
  41. package/dist/src/commands/inspect.d.ts +3 -0
  42. package/dist/src/commands/inspector.d.ts +3 -0
  43. package/dist/src/commands/pi.d.ts +3 -0
  44. package/dist/src/commands/plugin.d.ts +16 -0
  45. package/dist/src/commands/profile-and-review.d.ts +4 -0
  46. package/dist/src/commands/queue.d.ts +3 -0
  47. package/dist/src/commands/remote.d.ts +3 -0
  48. package/dist/src/commands/repo-git-harness.d.ts +5 -0
  49. package/dist/src/commands/run.d.ts +3 -0
  50. package/dist/src/commands/server.d.ts +7 -0
  51. package/dist/src/commands/setup.d.ts +16 -0
  52. package/dist/src/commands/stats.d.ts +12 -0
  53. package/dist/src/commands/stats.js +1 -0
  54. package/dist/src/commands/task-report-bug.d.ts +19 -0
  55. package/dist/src/commands/task-run-driver.d.ts +132 -0
  56. package/dist/src/commands/task-run-driver.js +23 -2
  57. package/dist/src/commands/task.d.ts +14 -0
  58. package/dist/src/commands/task.js +1 -0
  59. package/dist/src/commands/test.d.ts +3 -0
  60. package/dist/src/commands/workspace.d.ts +3 -0
  61. package/dist/src/commands.d.ts +29 -0
  62. package/dist/src/commands.js +37 -13
  63. package/dist/src/index.d.ts +4 -0
  64. package/dist/src/index.js +37 -13
  65. package/dist/src/launcher.d.ts +61 -0
  66. package/dist/src/report-bug.d.ts +44 -0
  67. package/dist/src/runner.d.ts +47 -0
  68. package/dist/src/withMutedConsole.d.ts +2 -0
  69. package/package.json +10 -8
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env bun
2
+ export {};
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env bun
2
+ export {};
package/dist/bin/rig.js CHANGED
@@ -3217,6 +3217,7 @@ var init__help_catalog = __esm(() => {
3217
3217
  { command: "next [filters]", description: "Render the next matching task as a selected-task card.", primary: true },
3218
3218
  { command: "show <id>|--task <id> [--raw]", description: "Show a human task summary; --raw prints the full payload.", primary: true },
3219
3219
  { command: "run [#<issue>|<task-id>|--next|--task <id>]", description: "Submit a task run; interactive follows with bundled Pi.", primary: true },
3220
+ { command: "ready", description: "List task IDs that are runnable now." },
3220
3221
  { command: "validate|verify [--task <id>]", description: "Run configured task checks/review gates." },
3221
3222
  { command: "details --task <id>", description: "Show full task info from the configured source." },
3222
3223
  { command: "reopen [--task <id> | --all] [--reason <text>]", description: "Reopen closed task(s) in the configured source." },
@@ -4011,7 +4012,7 @@ __export(exports_board, {
4011
4012
  import { randomUUID } from "crypto";
4012
4013
  import { existsSync as existsSync18 } from "fs";
4013
4014
  import { resolve as resolvePath } from "path";
4014
- import { ProcessTerminal as ProcessTerminal2, TUI as TUI2, Text as Text2, matchesKey as matchesKey2, truncateToWidth } from "@earendil-works/pi-tui";
4015
+ import { ProcessTerminal as ProcessTerminal2, TUI as TUI2, Text as Text2, isKeyRelease, matchesKey as matchesKey2, truncateToWidth } from "@earendil-works/pi-tui";
4015
4016
  function oneLine(message2) {
4016
4017
  return message2.split(`
4017
4018
  `).map((line) => line.trim()).find((line) => line.length > 0)?.slice(0, 200) ?? "unknown error";
@@ -4463,13 +4464,13 @@ async function runOperatorBoard(context, options = {}) {
4463
4464
  return;
4464
4465
  }
4465
4466
  if (view === "help") {
4466
- footer.setText(` ${accent("\u2191\u2193")}${ink3(" scroll")} ${accent("esc")}${ink3(" board")} ${accent("q")}${ink3(" quit")}`);
4467
+ footer.setText(` ${accent("\u2190")}${ink3(" back")} ${accent("\u2191\u2193")}${ink3(" scroll")} ${accent("esc")}${ink3(" board")} ${accent("q")}${ink3(" quit")}`);
4467
4468
  return;
4468
4469
  }
4469
4470
  if (view === "tasks") {
4470
4471
  footer.setText([
4471
4472
  ` ${notice ? accentDim(notice) : ink4("pick a task \u2014 a drone launches with project defaults")}`,
4472
- ` ${accent("enter")}${ink3(" dispatch")} ${accent("r")}${ink3(" reload")} ${accent("esc")}${ink3(" board")} ${accent("q")}${ink3(" quit")}`
4473
+ ` ${accent("\u2190")}${ink3(" back")} ${accent("enter")}${ink3(" dispatch")} ${accent("r")}${ink3(" reload")} ${accent("esc")}${ink3(" board")} ${accent("q")}${ink3(" quit")}`
4473
4474
  ].join(`
4474
4475
  `));
4475
4476
  return;
@@ -4477,7 +4478,7 @@ async function runOperatorBoard(context, options = {}) {
4477
4478
  if (view === "inbox") {
4478
4479
  footer.setText([
4479
4480
  ` ${notice ? accentDim(notice) : ink4("gates the fleet is waiting on \u2014 resolve them here")}`,
4480
- ` ${accent("a")}${ink3(" approve")} ${accent("d")}${ink3(" reject")} ${accent("enter")}${ink3(" answer input")} ${accent("r")}${ink3(" reload")} ${accent("esc")}${ink3(" board")}`
4481
+ ` ${accent("\u2190")}${ink3(" back")} ${accent("a")}${ink3(" approve")} ${accent("d")}${ink3(" reject")} ${accent("enter")}${ink3(" answer input")} ${accent("r")}${ink3(" reload")} ${accent("esc")}${ink3(" board")}`
4481
4482
  ].join(`
4482
4483
  `));
4483
4484
  return;
@@ -4644,6 +4645,8 @@ async function runOperatorBoard(context, options = {}) {
4644
4645
  tui.requestRender();
4645
4646
  }).catch(() => {});
4646
4647
  tui.addInputListener((data) => {
4648
+ if (isKeyRelease(data))
4649
+ return { consume: true };
4647
4650
  if (inputLine) {
4648
4651
  if (matchesKey2(data, "escape")) {
4649
4652
  if (inputLine.kind === "search")
@@ -4680,7 +4683,7 @@ async function runOperatorBoard(context, options = {}) {
4680
4683
  helpView.scroll(-15);
4681
4684
  else if (matchesKey2(data, "pageDown") || data === " ")
4682
4685
  helpView.scroll(15);
4683
- else if (matchesKey2(data, "escape") || data === "?") {
4686
+ else if (matchesKey2(data, "left") || matchesKey2(data, "escape") || data === "?") {
4684
4687
  setView("board");
4685
4688
  return { consume: true };
4686
4689
  }
@@ -4698,7 +4701,7 @@ async function runOperatorBoard(context, options = {}) {
4698
4701
  dispatchTask(task);
4699
4702
  } else if (data === "r")
4700
4703
  refreshTasks();
4701
- else if (matchesKey2(data, "escape"))
4704
+ else if (matchesKey2(data, "left") || matchesKey2(data, "escape"))
4702
4705
  setView("board");
4703
4706
  tui.requestRender();
4704
4707
  return { consume: true };
@@ -4726,7 +4729,7 @@ async function runOperatorBoard(context, options = {}) {
4726
4729
  }
4727
4730
  } else if (data === "r")
4728
4731
  refreshInbox();
4729
- else if (matchesKey2(data, "escape"))
4732
+ else if (matchesKey2(data, "left") || matchesKey2(data, "escape"))
4730
4733
  setView("board");
4731
4734
  tui.requestRender();
4732
4735
  return { consume: true };
@@ -4837,7 +4840,7 @@ async function runOperatorBoardLoop(context, attach, options = {}) {
4837
4840
  await attach(outcome.runId);
4838
4841
  }
4839
4842
  }
4840
- var BOARD_REFRESH_MS = 5000, BOARD_TICK_MS = 120, BOARD_TASK_PAGE = 20;
4843
+ var BOARD_REFRESH_MS = 5000, BOARD_TICK_MS = 250, BOARD_TASK_PAGE = 20;
4841
4844
  var init_board = __esm(() => {
4842
4845
  init_theme();
4843
4846
  init__help_catalog();
@@ -7745,7 +7748,7 @@ async function ensurePiBinaryAvailable(input) {
7745
7748
  }
7746
7749
  return { ok: true, detail: (current.stdout || current.stderr).trim() || undefined };
7747
7750
  }
7748
- const installCommand = process.env.RIG_PI_INSTALL_COMMAND?.trim() || "bunx @earendil-works/pi@latest install";
7751
+ const installCommand = process.env.RIG_PI_INSTALL_COMMAND?.trim() || "bunx @earendil-works/pi-coding-agent@latest install";
7749
7752
  const parts = splitInstallCommand(installCommand);
7750
7753
  if (parts.length === 0) {
7751
7754
  return { ok: false, error: (current.stderr || current.stdout).trim() || "pi --version failed" };
@@ -11213,6 +11216,19 @@ function looksLikeGitHubToken(value) {
11213
11216
  return false;
11214
11217
  return /^(gh[opusr]_|github_pat_)/.test(token);
11215
11218
  }
11219
+ function isSensitivePayloadKey(key) {
11220
+ return /token|secret|password|authorization|credential/i.test(key);
11221
+ }
11222
+ function redactSensitivePayload(value) {
11223
+ if (Array.isArray(value))
11224
+ return value.map(redactSensitivePayload);
11225
+ if (!value || typeof value !== "object")
11226
+ return value;
11227
+ return Object.fromEntries(Object.entries(value).map(([key, child]) => [
11228
+ key,
11229
+ isSensitivePayloadKey(key) && typeof child === "string" && child.trim() ? "[redacted]" : redactSensitivePayload(child)
11230
+ ]));
11231
+ }
11216
11232
  function githubBridgeEnv(token) {
11217
11233
  const clean = token?.trim();
11218
11234
  if (!clean)
@@ -11903,7 +11919,7 @@ function appendPiToolTimelineFromRecord(input) {
11903
11919
  }
11904
11920
  function isNonRenderablePiProtocolRecord(record) {
11905
11921
  const type = typeof record.type === "string" ? record.type : "";
11906
- return type === "agent_start" || type === "agent_end" || type === "message_start" || type === "message_end" || type === "turn_start" || type === "turn_end" || type === "tool_result" || type === "message_update" && (!record.assistantMessageEvent || typeof record.assistantMessageEvent !== "object" || Array.isArray(record.assistantMessageEvent) || record.assistantMessageEvent.type !== "text_delta");
11922
+ return type === "pi.event" || type === "status.update" || type === "activity.update" || type === "ready" || type === "agent_start" || type === "agent_end" || type === "message_start" || type === "message_end" || type === "turn_start" || type === "turn_end" || type === "tool_result" || type === "message_update" && (!record.assistantMessageEvent || typeof record.assistantMessageEvent !== "object" || Array.isArray(record.assistantMessageEvent) || record.assistantMessageEvent.type !== "text_delta");
11907
11923
  }
11908
11924
  function appendToolTimelineFromLog(input) {
11909
11925
  const title = typeof input.log.title === "string" ? input.log.title : "";
@@ -12463,7 +12479,15 @@ ${planningClassification.planningRequired ? `Before implementing, write a concis
12463
12479
  emitServerRunEvent({ type: "log", runId: input.runId, title });
12464
12480
  return true;
12465
12481
  }
12466
- return false;
12482
+ appendRunTimeline(context.projectRoot, input.runId, {
12483
+ id: `timeline:${input.runId}:${Date.now()}:wrapper:${event.type}`,
12484
+ type: "wrapper-event",
12485
+ eventType: event.type,
12486
+ payload: redactSensitivePayload(payload),
12487
+ createdAt: new Date().toISOString()
12488
+ });
12489
+ emitServerRunEvent({ type: "timeline", runId: input.runId });
12490
+ return true;
12467
12491
  };
12468
12492
  const handleAgentStdoutLine = (line) => {
12469
12493
  const trimmed = line.trim();
@@ -13520,9 +13544,9 @@ async function openApp(context, options = {}) {
13520
13544
  const { runOperatorBoardLoop: runOperatorBoardLoop2 } = await Promise.resolve().then(() => (init_board(), exports_board));
13521
13545
  await runOperatorBoardLoop2(context, async (runId) => {
13522
13546
  const scriptArg = typeof process.argv[1] === "string" && /\.(ts|js|mjs)$/.test(process.argv[1]) ? [process.argv[1]] : [];
13523
- const child = Bun.spawn([process.execPath, ...scriptArg, "run", "attach", runId], {
13547
+ const child = Bun.spawn([process.execPath, ...scriptArg, "--project", context.projectRoot, "run", "attach", runId], {
13524
13548
  stdio: ["inherit", "inherit", "inherit"],
13525
- env: process.env
13549
+ env: { ...process.env, PROJECT_RIG_ROOT: context.projectRoot }
13526
13550
  });
13527
13551
  await child.exited;
13528
13552
  }, options);
@@ -0,0 +1,23 @@
1
+ import type { RunnerContext } from "../runner";
2
+ export type BoardOutcome = {
3
+ action: "quit";
4
+ } | {
5
+ action: "attach";
6
+ runId: string;
7
+ };
8
+ export type RunSortMode = "active" | "recent" | "status";
9
+ export type BoardView = "board" | "help" | "tasks" | "inbox";
10
+ /**
11
+ * Run the operator board until the operator picks a run (→ attach) or
12
+ * quits. The caller owns the attach loop so the Pi console gets a clean
13
+ * terminal between board sessions.
14
+ */
15
+ export declare function runOperatorBoard(context: Pick<RunnerContext, "projectRoot" | "outputMode">, options?: {
16
+ initialView?: BoardView;
17
+ helpGroup?: string;
18
+ }): Promise<BoardOutcome>;
19
+ /** Board ⇆ console loop: the operator lives here. */
20
+ export declare function runOperatorBoardLoop(context: Pick<RunnerContext, "projectRoot" | "outputMode">, attach: (runId: string) => Promise<void>, options?: {
21
+ initialView?: BoardView;
22
+ helpGroup?: string;
23
+ }): Promise<void>;
@@ -3,7 +3,7 @@
3
3
  import { randomUUID } from "crypto";
4
4
  import { existsSync as existsSync3 } from "fs";
5
5
  import { resolve as resolvePath } from "path";
6
- import { ProcessTerminal as ProcessTerminal2, TUI as TUI2, Text as Text2, matchesKey as matchesKey2, truncateToWidth } from "@earendil-works/pi-tui";
6
+ import { ProcessTerminal as ProcessTerminal2, TUI as TUI2, Text as Text2, isKeyRelease, matchesKey as matchesKey2, truncateToWidth } from "@earendil-works/pi-tui";
7
7
 
8
8
  // packages/cli/src/app/theme.ts
9
9
  var RIG_PALETTE = {
@@ -223,6 +223,7 @@ var PRIMARY_GROUPS = [
223
223
  { command: "next [filters]", description: "Render the next matching task as a selected-task card.", primary: true },
224
224
  { command: "show <id>|--task <id> [--raw]", description: "Show a human task summary; --raw prints the full payload.", primary: true },
225
225
  { command: "run [#<issue>|<task-id>|--next|--task <id>]", description: "Submit a task run; interactive follows with bundled Pi.", primary: true },
226
+ { command: "ready", description: "List task IDs that are runnable now." },
226
227
  { command: "validate|verify [--task <id>]", description: "Run configured task checks/review gates." },
227
228
  { command: "details --task <id>", description: "Show full task info from the configured source." },
228
229
  { command: "reopen [--task <id> | --all] [--reason <text>]", description: "Reopen closed task(s) in the configured source." },
@@ -950,7 +951,7 @@ async function loadTaskRunProjectDefaults(projectRoot) {
950
951
 
951
952
  // packages/cli/src/app/board.ts
952
953
  var BOARD_REFRESH_MS = 5000;
953
- var BOARD_TICK_MS = 120;
954
+ var BOARD_TICK_MS = 250;
954
955
  var BOARD_TASK_PAGE = 20;
955
956
  function oneLine(message) {
956
957
  return message.split(`
@@ -1403,13 +1404,13 @@ async function runOperatorBoard(context, options = {}) {
1403
1404
  return;
1404
1405
  }
1405
1406
  if (view === "help") {
1406
- footer.setText(` ${accent("\u2191\u2193")}${ink3(" scroll")} ${accent("esc")}${ink3(" board")} ${accent("q")}${ink3(" quit")}`);
1407
+ footer.setText(` ${accent("\u2190")}${ink3(" back")} ${accent("\u2191\u2193")}${ink3(" scroll")} ${accent("esc")}${ink3(" board")} ${accent("q")}${ink3(" quit")}`);
1407
1408
  return;
1408
1409
  }
1409
1410
  if (view === "tasks") {
1410
1411
  footer.setText([
1411
1412
  ` ${notice ? accentDim(notice) : ink4("pick a task \u2014 a drone launches with project defaults")}`,
1412
- ` ${accent("enter")}${ink3(" dispatch")} ${accent("r")}${ink3(" reload")} ${accent("esc")}${ink3(" board")} ${accent("q")}${ink3(" quit")}`
1413
+ ` ${accent("\u2190")}${ink3(" back")} ${accent("enter")}${ink3(" dispatch")} ${accent("r")}${ink3(" reload")} ${accent("esc")}${ink3(" board")} ${accent("q")}${ink3(" quit")}`
1413
1414
  ].join(`
1414
1415
  `));
1415
1416
  return;
@@ -1417,7 +1418,7 @@ async function runOperatorBoard(context, options = {}) {
1417
1418
  if (view === "inbox") {
1418
1419
  footer.setText([
1419
1420
  ` ${notice ? accentDim(notice) : ink4("gates the fleet is waiting on \u2014 resolve them here")}`,
1420
- ` ${accent("a")}${ink3(" approve")} ${accent("d")}${ink3(" reject")} ${accent("enter")}${ink3(" answer input")} ${accent("r")}${ink3(" reload")} ${accent("esc")}${ink3(" board")}`
1421
+ ` ${accent("\u2190")}${ink3(" back")} ${accent("a")}${ink3(" approve")} ${accent("d")}${ink3(" reject")} ${accent("enter")}${ink3(" answer input")} ${accent("r")}${ink3(" reload")} ${accent("esc")}${ink3(" board")}`
1421
1422
  ].join(`
1422
1423
  `));
1423
1424
  return;
@@ -1584,6 +1585,8 @@ async function runOperatorBoard(context, options = {}) {
1584
1585
  tui.requestRender();
1585
1586
  }).catch(() => {});
1586
1587
  tui.addInputListener((data) => {
1588
+ if (isKeyRelease(data))
1589
+ return { consume: true };
1587
1590
  if (inputLine) {
1588
1591
  if (matchesKey2(data, "escape")) {
1589
1592
  if (inputLine.kind === "search")
@@ -1620,7 +1623,7 @@ async function runOperatorBoard(context, options = {}) {
1620
1623
  helpView.scroll(-15);
1621
1624
  else if (matchesKey2(data, "pageDown") || data === " ")
1622
1625
  helpView.scroll(15);
1623
- else if (matchesKey2(data, "escape") || data === "?") {
1626
+ else if (matchesKey2(data, "left") || matchesKey2(data, "escape") || data === "?") {
1624
1627
  setView("board");
1625
1628
  return { consume: true };
1626
1629
  }
@@ -1638,7 +1641,7 @@ async function runOperatorBoard(context, options = {}) {
1638
1641
  dispatchTask(task);
1639
1642
  } else if (data === "r")
1640
1643
  refreshTasks();
1641
- else if (matchesKey2(data, "escape"))
1644
+ else if (matchesKey2(data, "left") || matchesKey2(data, "escape"))
1642
1645
  setView("board");
1643
1646
  tui.requestRender();
1644
1647
  return { consume: true };
@@ -1666,7 +1669,7 @@ async function runOperatorBoard(context, options = {}) {
1666
1669
  }
1667
1670
  } else if (data === "r")
1668
1671
  refreshInbox();
1669
- else if (matchesKey2(data, "escape"))
1672
+ else if (matchesKey2(data, "left") || matchesKey2(data, "escape"))
1670
1673
  setView("board");
1671
1674
  tui.requestRender();
1672
1675
  return { consume: true };
@@ -0,0 +1,37 @@
1
+ export declare function droneIntro(title: string, subtitle?: string): void;
2
+ export declare function droneOutro(text: string): void;
3
+ export declare function droneNote(message: string, title?: string): void;
4
+ export declare function droneStep(text: string): void;
5
+ export declare function droneInfo(text: string): void;
6
+ export declare function droneWarn(text: string): void;
7
+ export declare function droneError(text: string): void;
8
+ export declare function droneCancel(text: string): void;
9
+ /** Clack-spinner-shaped adapter over the micro-drone TTY spinner. */
10
+ export declare function droneSpinner(): {
11
+ start(message: string): void;
12
+ stop(message?: string): void;
13
+ error(message?: string): void;
14
+ };
15
+ type DroneSelectOption<T extends string> = {
16
+ value: T;
17
+ label: string;
18
+ hint?: string;
19
+ };
20
+ /** Drone-styled select. Returns null on cancel (esc / ctrl+c / q). */
21
+ export declare function droneSelect<T extends string>(input: {
22
+ readonly message: string;
23
+ readonly options: readonly DroneSelectOption<T>[];
24
+ readonly initialValue?: T;
25
+ }): Promise<T | null>;
26
+ /** Drone-styled text input. Returns null on cancel. */
27
+ export declare function droneText(input: {
28
+ readonly message: string;
29
+ readonly placeholder?: string;
30
+ readonly initialValue?: string;
31
+ }): Promise<string | null>;
32
+ /** Drone-styled yes/no. Returns null on cancel. */
33
+ export declare function droneConfirm(input: {
34
+ readonly message: string;
35
+ readonly initialValue?: boolean;
36
+ }): Promise<boolean | null>;
37
+ export {};
@@ -0,0 +1,47 @@
1
+ export declare const RIG_PALETTE: {
2
+ /** --ink: primary text */
3
+ readonly ink: "#f2f3f6";
4
+ /** --ink-2: body text */
5
+ readonly ink2: "#aeb0ba";
6
+ /** --ink-3: muted */
7
+ readonly ink3: "#6c6e79";
8
+ /** --ink-4: faint */
9
+ readonly ink4: "#44464f";
10
+ /** --ac: acid green accent */
11
+ readonly accent: "#ccff4d";
12
+ /** --ac-dim */
13
+ readonly accentDim: "#a9d63f";
14
+ /** --ac-2: cyan secondary */
15
+ readonly cyan: "#56d8ff";
16
+ /** status colors tuned to sit on the dark site bg */
17
+ readonly red: "#ff5d5d";
18
+ readonly yellow: "#ffd24d";
19
+ };
20
+ /** 24-bit foreground colorizer. */
21
+ export declare function fg(hex: string): (text: string) => string;
22
+ export declare const ink: (text: string) => string;
23
+ export declare const ink2: (text: string) => string;
24
+ export declare const ink3: (text: string) => string;
25
+ export declare const ink4: (text: string) => string;
26
+ export declare const accent: (text: string) => string;
27
+ export declare const accentDim: (text: string) => string;
28
+ export declare const cyan: (text: string) => string;
29
+ export declare const red: (text: string) => string;
30
+ export declare const yellow: (text: string) => string;
31
+ export declare function bold(text: string): string;
32
+ /** Run-status color, matching the site's pipeline color story. */
33
+ export declare function statusColor(status: string): (text: string) => string;
34
+ /** The braille spinner the site's hero terminal mirrors. */
35
+ export declare const RIG_SPINNER_FRAMES: readonly ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
36
+ /**
37
+ * Render one animation frame of the drone. `tick` drives rotor rotation and
38
+ * the eye pulse — call with an incrementing counter (the site advances the
39
+ * rotor every 4 ticks and pulses the eye on a sine).
40
+ */
41
+ export declare function renderDroneFrame(tick: number): string[];
42
+ export declare const DRONE_WIDTH: number;
43
+ export declare const DRONE_HEIGHT: 18;
44
+ export declare function microDroneFrame(tick: number): string;
45
+ export declare const MICRO_DRONE_FRAMES: readonly string[];
46
+ /** Truecolor micro-drone: cyan rotors, acid eye — site colors. */
47
+ export declare function renderMicroDroneFrame(tick: number): string;
@@ -0,0 +1,13 @@
1
+ import type { OutputMode } from "@rig/runtime/control-plane/runtime/types";
2
+ export type SpinnerOutput = Pick<NodeJS.WriteStream, "write"> & {
3
+ readonly isTTY?: boolean;
4
+ };
5
+ export type WithSpinnerOptions = {
6
+ /** Final line left behind on success. Default: the spinner line is erased. */
7
+ readonly doneLabel?: string;
8
+ /** Pass context.outputMode; "json" suppresses all spinner output. */
9
+ readonly outputMode?: OutputMode;
10
+ /** Stream override for tests. Defaults to process.stderr. */
11
+ readonly output?: SpinnerOutput;
12
+ };
13
+ export declare function withSpinner<T>(label: string, work: (update: (label: string) => void) => Promise<T>, options?: WithSpinnerOptions): Promise<T>;
@@ -0,0 +1,22 @@
1
+ import { type AuthorityRunRecord } from "@rig/runtime/control-plane/authority-files";
2
+ import type { RunStatus } from "@rig/contracts";
3
+ export declare const RIG_WORKSPACE_ID = "rig-local-workspace";
4
+ export type RuntimeAdapter = "claude-code" | "codex" | "pi";
5
+ export declare function normalizeRuntimeAdapter(value: string | undefined): RuntimeAdapter;
6
+ export declare function readLatestBeadRecord(projectRoot: string, taskId: string): Record<string, unknown> | null;
7
+ export declare function upsertAgentAuthorityRun(projectRoot: string, input: {
8
+ runId: string;
9
+ taskId: string;
10
+ createdAt: string;
11
+ runtimeAdapter?: string;
12
+ status: RunStatus;
13
+ startedAt?: string | null;
14
+ completedAt?: string | null;
15
+ worktreePath?: string | null;
16
+ artifactRoot?: string | null;
17
+ logRoot?: string | null;
18
+ sessionPath?: string | null;
19
+ sessionLogPath?: string | null;
20
+ pid?: number | null;
21
+ errorText?: string | null;
22
+ }): AuthorityRunRecord & Record<string, unknown>;
@@ -0,0 +1,49 @@
1
+ export type CliTaskLike = Record<string, unknown>;
2
+ export type CliRunLike = Record<string, unknown>;
3
+ export declare function printFormattedOutput(message: string, options?: {
4
+ title?: string;
5
+ }): void;
6
+ export declare function formatStatusPill(status: string): string;
7
+ export declare function formatSection(title: string, subtitle?: string): string;
8
+ export declare function formatSuccessCard(title: string, rows?: Array<[string, string | number | null | undefined]>): string;
9
+ export declare function formatNextSteps(steps: readonly string[]): string[];
10
+ export declare function formatTaskList(tasks: readonly CliTaskLike[], options?: {
11
+ raw?: boolean;
12
+ }): string;
13
+ export declare function formatTaskCard(task: CliTaskLike, options?: {
14
+ title?: string;
15
+ selected?: boolean;
16
+ }): string;
17
+ export declare function formatTaskDetails(task: CliTaskLike): string;
18
+ export declare function formatRunList(runs: readonly CliRunLike[], options?: {
19
+ source?: "local" | "server";
20
+ }): string;
21
+ export declare function formatSubmittedRun(input: {
22
+ runId: string;
23
+ task?: CliTaskLike | null;
24
+ runtimeAdapter?: string | null;
25
+ runtimeMode?: string | null;
26
+ interactionMode?: string | null;
27
+ detached?: boolean;
28
+ }): string;
29
+ export declare function formatRunCard(run: CliRunLike, options?: {
30
+ title?: string;
31
+ }): string;
32
+ export declare function formatRunStatus(summary: {
33
+ activeRuns?: CliRunLike[];
34
+ recentRuns?: CliRunLike[];
35
+ runs?: CliRunLike[];
36
+ }, options?: {
37
+ source?: "local" | "server";
38
+ }): string;
39
+ export declare function formatInboxList(kind: "approvals" | "inputs", entries: readonly Record<string, unknown>[]): string;
40
+ export declare function formatConnectionList(connections: Record<string, {
41
+ kind: string;
42
+ baseUrl?: string;
43
+ mode?: string;
44
+ }>): string;
45
+ export declare function formatConnectionStatus(selected: string, connections: Record<string, {
46
+ kind: string;
47
+ baseUrl?: string;
48
+ mode?: string;
49
+ }>): string;
@@ -0,0 +1,44 @@
1
+ export type RigConnection = {
2
+ kind: "local";
3
+ mode: "auto";
4
+ } | {
5
+ kind: "remote";
6
+ baseUrl: string;
7
+ };
8
+ export type GlobalConnectionState = {
9
+ connections: Record<string, RigConnection>;
10
+ };
11
+ export type RepoConnectionState = {
12
+ selected: string;
13
+ project?: string;
14
+ linkedAt?: string;
15
+ /**
16
+ * The server-host project root this repo scopes to (multi-root serving).
17
+ * Sent as the x-rig-project-root header on every remote request.
18
+ */
19
+ serverProjectRoot?: string;
20
+ };
21
+ export declare function resolveGlobalConnectionsPath(env?: NodeJS.ProcessEnv): string;
22
+ export declare function resolveRepoConnectionPath(projectRoot: string): string;
23
+ export declare function readGlobalConnections(options?: {
24
+ env?: NodeJS.ProcessEnv;
25
+ }): GlobalConnectionState;
26
+ export declare function writeGlobalConnections(state: GlobalConnectionState, options?: {
27
+ env?: NodeJS.ProcessEnv;
28
+ }): void;
29
+ export declare function upsertGlobalConnection(alias: string, connection: RigConnection, options?: {
30
+ env?: NodeJS.ProcessEnv;
31
+ }): GlobalConnectionState;
32
+ export declare function readRepoConnection(projectRoot: string): RepoConnectionState | null;
33
+ export declare function writeRepoConnection(projectRoot: string, state: RepoConnectionState): void;
34
+ export declare function resolveSelectedConnection(projectRoot: string, options?: {
35
+ env?: NodeJS.ProcessEnv;
36
+ }): {
37
+ alias: string;
38
+ connection: RigConnection;
39
+ serverProjectRoot?: string;
40
+ } | null;
41
+ /** Persist the server-host project root this repo scopes to (multi-root serving). */
42
+ export declare function writeRepoServerProjectRoot(projectRoot: string, serverProjectRoot: string): void;
43
+ /** Whether this repo's selected connection targets a remote Rig server. */
44
+ export declare function isRemoteConnectionSelected(projectRoot: string): boolean;
@@ -0,0 +1,52 @@
1
+ type DoctorConfig = {
2
+ readonly project?: Record<string, unknown>;
3
+ readonly taskSource?: {
4
+ readonly kind?: string;
5
+ readonly owner?: string;
6
+ readonly repo?: string;
7
+ };
8
+ readonly github?: {
9
+ readonly projects?: {
10
+ readonly enabled?: boolean;
11
+ readonly projectId?: string;
12
+ readonly statusFieldId?: string;
13
+ };
14
+ };
15
+ readonly pr?: {
16
+ readonly mode?: string;
17
+ };
18
+ readonly merge?: {
19
+ readonly mode?: string;
20
+ readonly method?: string;
21
+ };
22
+ };
23
+ import { type PiInstallCheck } from "./_pi-install";
24
+ export type DoctorStatus = "pass" | "warn" | "fail";
25
+ export type RigDoctorCheck = {
26
+ readonly id: string;
27
+ readonly label: string;
28
+ readonly status: DoctorStatus;
29
+ readonly detail?: string;
30
+ readonly remediation?: string;
31
+ };
32
+ export type RigDoctorServer = {
33
+ readonly baseUrl: string;
34
+ readonly authToken: string | null;
35
+ readonly connectionKind: "local" | "remote";
36
+ };
37
+ export type RunRigDoctorChecksOptions = {
38
+ readonly projectRoot: string;
39
+ readonly resolveServer?: (projectRoot: string) => Promise<RigDoctorServer>;
40
+ readonly requestJson?: (pathname: string, init?: RequestInit) => Promise<unknown>;
41
+ readonly piChecks?: () => Promise<readonly PiInstallCheck[]>;
42
+ readonly which?: (binary: string) => string | null;
43
+ readonly bunVersion?: string;
44
+ readonly loadConfig?: (projectRoot: string) => Promise<DoctorConfig | null>;
45
+ /** Per-check status narration ("Checking GitHub auth…") for wait spinners. */
46
+ readonly onProgress?: (label: string) => void;
47
+ };
48
+ export declare function runRigDoctorChecks(options: RunRigDoctorChecksOptions): Promise<RigDoctorCheck[]>;
49
+ export declare function formatDoctorChecks(checks: readonly RigDoctorCheck[]): string;
50
+ export declare function countDoctorFailures(checks: readonly RigDoctorCheck[]): number;
51
+ export declare function throwIfDoctorFailed(checks: readonly RigDoctorCheck[]): void;
52
+ export {};
@@ -0,0 +1,51 @@
1
+ export type HelpCommand = {
2
+ command: string;
3
+ description: string;
4
+ primary?: boolean;
5
+ };
6
+ export type HelpGroup = {
7
+ name: string;
8
+ summary: string;
9
+ usage: string[];
10
+ commands: HelpCommand[];
11
+ examples?: string[];
12
+ next?: string[];
13
+ advanced?: string[];
14
+ };
15
+ export type TopLevelSection = {
16
+ title: string;
17
+ subtitle: string;
18
+ commands: HelpCommand[];
19
+ };
20
+ /** Catalog DATA for the app's help view — the view builds its own layout
21
+ * from these; the render* functions below remain for plain/script output. */
22
+ export declare function helpCatalog(): {
23
+ sections: readonly TopLevelSection[];
24
+ groups: readonly HelpGroup[];
25
+ };
26
+ /**
27
+ * Night City boot screen. Rendered only on interactive TTY launches — plain
28
+ * mode and --json never see it.
29
+ */
30
+ export declare function renderRigBanner(version?: string): string;
31
+ export declare function renderTopLevelHelp(): string;
32
+ export declare function renderAdvancedHelp(): string;
33
+ export declare function renderGroupHelp(groupName: string): string | null;
34
+ export declare function listHelpGroups(): string[];
35
+ /**
36
+ * Fuzzy-match a bare word against known group subcommand names so the
37
+ * unknown-command error can suggest the canonical `rig <group> <cmd>`
38
+ * spelling. Primary groups win ties (ALL_GROUPS is primary-first).
39
+ */
40
+ export declare function suggestGroupCommandForWord(word: string): string | null;
41
+ export type TopLevelLaunchState = {
42
+ /** True when the cwd resolves to an initialized Rig project. */
43
+ projectInitialized?: boolean;
44
+ /** Short description of the selected server connection, if known. */
45
+ selectedServer?: string | null;
46
+ /** CLI version for the banner footer. */
47
+ version?: string;
48
+ };
49
+ export declare function printTopLevelHelp(state?: TopLevelLaunchState): void;
50
+ export declare function printAdvancedHelp(): void;
51
+ export declare function printGroupHelpDocument(groupName: string): void;
@@ -94,6 +94,7 @@ var PRIMARY_GROUPS = [
94
94
  { command: "next [filters]", description: "Render the next matching task as a selected-task card.", primary: true },
95
95
  { command: "show <id>|--task <id> [--raw]", description: "Show a human task summary; --raw prints the full payload.", primary: true },
96
96
  { command: "run [#<issue>|<task-id>|--next|--task <id>]", description: "Submit a task run; interactive follows with bundled Pi.", primary: true },
97
+ { command: "ready", description: "List task IDs that are runnable now." },
97
98
  { command: "validate|verify [--task <id>]", description: "Run configured task checks/review gates." },
98
99
  { command: "details --task <id>", description: "Show full task info from the configured source." },
99
100
  { command: "reopen [--task <id> | --all] [--reason <text>]", description: "Reopen closed task(s) in the configured source." },
@@ -0,0 +1,11 @@
1
+ import { type RigCliOutputEnvelope } from "@rig/contracts";
2
+ /**
3
+ * Build the versioned `{ v: 1, command, data }` envelope for a command
4
+ * outcome, or null when the command has no output schema (legacy payload)
5
+ * or the details fail validation (warned on stderr, legacy payload).
6
+ */
7
+ export declare function buildCliJsonEnvelope(outcome: unknown, options?: {
8
+ warn?: (message: string) => void;
9
+ }): RigCliOutputEnvelope | null;
10
+ /** Commands with a versioned --json envelope (for help/docs/tests). */
11
+ export declare function listSchematizedCliCommands(): string[];
@@ -0,0 +1,34 @@
1
+ import type { WorkspaceTaskRecord } from "./_server-client";
2
+ export type OperatorSnapshot = {
3
+ readonly run: Record<string, unknown>;
4
+ readonly logs?: readonly Record<string, unknown>[];
5
+ readonly timeline?: readonly Record<string, unknown>[];
6
+ };
7
+ export declare function renderOperatorSnapshot(snapshot: OperatorSnapshot): string;
8
+ export type PiRunStreamRenderer = {
9
+ renderSnapshot(snapshot: OperatorSnapshot): void;
10
+ renderTimeline(entries: readonly Record<string, unknown>[]): void;
11
+ renderLogs(entries: readonly Record<string, unknown>[]): void;
12
+ };
13
+ export declare function createPiRunStreamRenderer(output?: Pick<NodeJS.WriteStream, "write">): PiRunStreamRenderer;
14
+ export type OperatorSurface = PiRunStreamRenderer & {
15
+ readonly mode: "text" | "pi-compatible-text";
16
+ info(message: string): void;
17
+ error(message: string): void;
18
+ attachCommandInput(handler: (line: string) => void | Promise<void>): {
19
+ close(): void;
20
+ } | null;
21
+ };
22
+ export declare function createOperatorSurface(options?: {
23
+ readonly input?: NodeJS.ReadStream;
24
+ readonly output?: Pick<NodeJS.WriteStream, "write"> & {
25
+ readonly isTTY?: boolean;
26
+ };
27
+ readonly errorOutput?: Pick<NodeJS.WriteStream, "write">;
28
+ readonly interactive?: boolean;
29
+ }): OperatorSurface;
30
+ export type TaskPickerRenderer = {
31
+ readonly writeLine: (line: string) => void;
32
+ };
33
+ export declare function renderTaskPickerRows(tasks: readonly WorkspaceTaskRecord[]): string[];
34
+ export declare function promptForTaskSelection(question: string): Promise<string>;