@h-rig/cli-surface-plugin 0.0.6-alpha.146

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 (94) hide show
  1. package/README.md +1 -0
  2. package/dist/src/app/drone-ui.d.ts +34 -0
  3. package/dist/src/app/drone-ui.js +278 -0
  4. package/dist/src/commands/_async-ui.d.ts +10 -0
  5. package/dist/src/commands/_async-ui.js +121 -0
  6. package/dist/src/commands/_cli-format.d.ts +56 -0
  7. package/dist/src/commands/_cli-format.js +332 -0
  8. package/dist/src/commands/_connection-state.d.ts +54 -0
  9. package/dist/src/commands/_connection-state.js +187 -0
  10. package/dist/src/commands/_doctor-checks.d.ts +9 -0
  11. package/dist/src/commands/_doctor-checks.js +24 -0
  12. package/dist/src/commands/_help-catalog.d.ts +29 -0
  13. package/dist/src/commands/_help-catalog.js +157 -0
  14. package/dist/src/commands/_inprocess-services.d.ts +33 -0
  15. package/dist/src/commands/_inprocess-services.js +102 -0
  16. package/dist/src/commands/_json-output.d.ts +11 -0
  17. package/dist/src/commands/_json-output.js +54 -0
  18. package/dist/src/commands/_parsers.d.ts +15 -0
  19. package/dist/src/commands/_parsers.js +114 -0
  20. package/dist/src/commands/_paths.d.ts +11 -0
  21. package/dist/src/commands/_paths.js +50 -0
  22. package/dist/src/commands/_pi-frontend.d.ts +35 -0
  23. package/dist/src/commands/_pi-frontend.js +64 -0
  24. package/dist/src/commands/_pi-install.d.ts +42 -0
  25. package/dist/src/commands/_pi-install.js +167 -0
  26. package/dist/src/commands/_policy.d.ts +8 -0
  27. package/dist/src/commands/_policy.js +138 -0
  28. package/dist/src/commands/_probes.d.ts +1 -0
  29. package/dist/src/commands/_probes.js +13 -0
  30. package/dist/src/commands/_run-driver-helpers.d.ts +26 -0
  31. package/dist/src/commands/_run-driver-helpers.js +132 -0
  32. package/dist/src/commands/_run-subcommands.d.ts +3 -0
  33. package/dist/src/commands/_run-subcommands.js +31 -0
  34. package/dist/src/commands/_spinner.d.ts +25 -0
  35. package/dist/src/commands/_spinner.js +65 -0
  36. package/dist/src/commands/agent.d.ts +3 -0
  37. package/dist/src/commands/agent.js +322 -0
  38. package/dist/src/commands/config.d.ts +3 -0
  39. package/dist/src/commands/config.js +193 -0
  40. package/dist/src/commands/dist.d.ts +28 -0
  41. package/dist/src/commands/dist.js +435 -0
  42. package/dist/src/commands/doctor.d.ts +3 -0
  43. package/dist/src/commands/doctor.js +171 -0
  44. package/dist/src/commands/github.d.ts +3 -0
  45. package/dist/src/commands/github.js +342 -0
  46. package/dist/src/commands/inbox.d.ts +19 -0
  47. package/dist/src/commands/inbox.js +241 -0
  48. package/dist/src/commands/init.d.ts +64 -0
  49. package/dist/src/commands/init.js +1449 -0
  50. package/dist/src/commands/inspect.d.ts +20 -0
  51. package/dist/src/commands/inspect.js +337 -0
  52. package/dist/src/commands/pi.d.ts +3 -0
  53. package/dist/src/commands/pi.js +177 -0
  54. package/dist/src/commands/plugin.d.ts +20 -0
  55. package/dist/src/commands/plugin.js +238 -0
  56. package/dist/src/commands/profile-and-review.d.ts +4 -0
  57. package/dist/src/commands/profile-and-review.js +223 -0
  58. package/dist/src/commands/queue.d.ts +3 -0
  59. package/dist/src/commands/queue.js +197 -0
  60. package/dist/src/commands/remote.d.ts +3 -0
  61. package/dist/src/commands/remote.js +516 -0
  62. package/dist/src/commands/repo-git-harness.d.ts +5 -0
  63. package/dist/src/commands/repo-git-harness.js +282 -0
  64. package/dist/src/commands/run.d.ts +22 -0
  65. package/dist/src/commands/run.js +645 -0
  66. package/dist/src/commands/server.d.ts +3 -0
  67. package/dist/src/commands/server.js +155 -0
  68. package/dist/src/commands/setup.d.ts +16 -0
  69. package/dist/src/commands/setup.js +356 -0
  70. package/dist/src/commands/stats.d.ts +11 -0
  71. package/dist/src/commands/stats.js +219 -0
  72. package/dist/src/commands/task-run-driver.d.ts +93 -0
  73. package/dist/src/commands/task-run-driver.js +136 -0
  74. package/dist/src/commands/task.d.ts +46 -0
  75. package/dist/src/commands/task.js +555 -0
  76. package/dist/src/commands/test.d.ts +3 -0
  77. package/dist/src/commands/test.js +46 -0
  78. package/dist/src/commands/triage.d.ts +11 -0
  79. package/dist/src/commands/triage.js +224 -0
  80. package/dist/src/commands/workspace.d.ts +3 -0
  81. package/dist/src/commands/workspace.js +130 -0
  82. package/dist/src/kernel-dispatch.d.ts +15 -0
  83. package/dist/src/kernel-dispatch.js +16 -0
  84. package/dist/src/plugin.d.ts +3 -0
  85. package/dist/src/plugin.js +5440 -0
  86. package/dist/src/rig-config-package-deps.d.ts +10 -0
  87. package/dist/src/rig-config-package-deps.js +272 -0
  88. package/dist/src/runner.d.ts +47 -0
  89. package/dist/src/runner.js +267 -0
  90. package/dist/src/version.d.ts +8 -0
  91. package/dist/src/version.js +47 -0
  92. package/dist/src/withMutedConsole.d.ts +2 -0
  93. package/dist/src/withMutedConsole.js +42 -0
  94. package/package.json +34 -0
@@ -0,0 +1,157 @@
1
+ // @bun
2
+ // packages/cli-surface-plugin/src/commands/_help-catalog.ts
3
+ import pc from "picocolors";
4
+ import {
5
+ ADVANCED_COMMANDS,
6
+ ADVANCED_GROUPS,
7
+ ALL_GROUPS,
8
+ helpCatalog,
9
+ TOP_LEVEL_SECTIONS
10
+ } from "@rig/contracts";
11
+ function heading(title) {
12
+ return pc.bold(pc.cyan(title));
13
+ }
14
+ function renderRigBanner(version) {
15
+ const m = (s) => pc.bold(pc.magenta(s));
16
+ const c = (s) => pc.bold(pc.cyan(s));
17
+ const y = (s) => pc.yellow(s);
18
+ const d = (s) => pc.dim(s);
19
+ const lines = [
20
+ m(" \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 ") + d(" \u2591\u2592\u2593\u2588 "),
21
+ m(" \u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D ") + d("\u2593\u2592\u2591"),
22
+ c(" \u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2588\u2557") + d(" \u2591\u2592"),
23
+ c(" \u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551") + d(" \u2588\u2593\u2591"),
24
+ y(" \u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D") + d(" \u2592\u2591"),
25
+ y(" \u255A\u2550\u255D \u255A\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D "),
26
+ "",
27
+ ` ${c("\u25E2\u25E4")} ${pc.bold("OMP extension cockpit for autonomous coding agents")} ${m("//")} ${d("you are the operator")}`,
28
+ version ? ` ${d(`v${version} \xB7 jack in: rig`)}` : ` ${d("jack in: rig")}`
29
+ ];
30
+ return lines.join(`
31
+ `);
32
+ }
33
+ function commandLine(command, description) {
34
+ const commandColumn = command.length >= 38 ? `${command} ` : command.padEnd(38);
35
+ return `${pc.dim("\u2502")} ${pc.bold(commandColumn)} ${description}`;
36
+ }
37
+ function renderCommandBlock(commands) {
38
+ const indent = `${pc.dim("\u2502")} ${" ".repeat(38)} `;
39
+ return commands.map((entry) => {
40
+ const lines = [commandLine(entry.command, entry.description)];
41
+ if (entry.usecase) {
42
+ lines.push(`${indent}${pc.dim("when:")} ${pc.dim(entry.usecase)}`);
43
+ }
44
+ for (const example of entry.examples ?? []) {
45
+ lines.push(`${indent}${pc.dim("$")} ${pc.cyan(example)}`);
46
+ }
47
+ return lines.join(`
48
+ `);
49
+ }).join(`
50
+ `);
51
+ }
52
+ function renderGroup(group) {
53
+ const lines = [
54
+ `${heading(`rig ${group.name}`)} \u2014 ${group.summary}`,
55
+ "",
56
+ pc.bold("Usage"),
57
+ ...group.usage.map((line) => ` ${line}`),
58
+ "",
59
+ pc.bold("Commands"),
60
+ ...group.commands.map((entry) => commandLine(entry.command, entry.description))
61
+ ];
62
+ if (group.examples?.length) {
63
+ lines.push("", pc.bold("Examples"), ...group.examples.map((line) => ` ${pc.dim("$")} ${line}`));
64
+ }
65
+ if (group.next?.length) {
66
+ lines.push("", pc.bold("Next steps"), ...group.next.map((line) => ` ${pc.dim("\u203A")} ${line}`));
67
+ }
68
+ if (group.advanced?.length) {
69
+ lines.push("", pc.bold("Compatibility / advanced"), ...group.advanced.map((line) => ` ${pc.dim("\u203A")} ${line}`));
70
+ }
71
+ return lines.join(`
72
+ `);
73
+ }
74
+ function renderTopLevelHelp() {
75
+ return [
76
+ `${heading("rig")} ${pc.dim("\u2014 Rig Cockpit for autonomous coding agents")}`,
77
+ pc.dim("The loop: bare `rig` \u2192 Cockpit \u2192 Server target \u2192 Tasks \u2192 Task detail \u2192 Dispatch/Attach; every run uses OMP collaboration as the session substrate."),
78
+ "",
79
+ ...TOP_LEVEL_SECTIONS.flatMap((section) => [
80
+ `${pc.bold(pc.magenta(`\u25C7 ${section.title}`))} \u2014 ${pc.dim(section.subtitle)}`,
81
+ renderCommandBlock(section.commands),
82
+ ""
83
+ ]),
84
+ pc.dim("More: `rig help --advanced` for fenced legacy/diagnostic commands; `rig <group> --help` for per-group compatibility help; `rig --version` for the installed version."),
85
+ "",
86
+ pc.bold("Root options"),
87
+ commandLine("--workspace <path>", "Open Rig Cockpit for a workspace instead of the current directory."),
88
+ commandLine("--json", "Compatibility flag for fenced legacy/diagnostic subcommands."),
89
+ commandLine("--dry-run", "Compatibility flag for fenced legacy/diagnostic subcommands.")
90
+ ].join(`
91
+ `).trimEnd();
92
+ }
93
+ function renderAdvancedHelp() {
94
+ return [
95
+ `${heading("rig advanced")} \u2014 fenced legacy compatibility, diagnostics, and internal surfaces`,
96
+ "",
97
+ pc.bold("Normal public UX"),
98
+ " rig, rig --workspace <path>, rig join <collab-link>, and /rig inside OMP",
99
+ "",
100
+ pc.bold("Legacy/diagnostic groups"),
101
+ " init, server, task, run, inbox, inspect, stats, doctor, github, setup, remote",
102
+ "",
103
+ pc.bold("Advanced commands"),
104
+ ...ADVANCED_COMMANDS.map((entry) => commandLine(entry.command, entry.description)),
105
+ "",
106
+ pc.bold("Advanced groups"),
107
+ ...ADVANCED_GROUPS.map((group) => commandLine(group.name, group.summary)),
108
+ "",
109
+ pc.dim("Legacy groups remain callable for old automation and diagnostics. Prefer bare `rig` and the OMP cockpit for day-to-day work.")
110
+ ].join(`
111
+ `);
112
+ }
113
+ function renderGroupHelp(groupName) {
114
+ const group = ALL_GROUPS.find((candidate) => candidate.name === groupName);
115
+ return group ? renderGroup(group) : null;
116
+ }
117
+ function listHelpGroups() {
118
+ return ALL_GROUPS.map((group) => group.name);
119
+ }
120
+ function suggestGroupCommandForWord(word, liveGroups) {
121
+ const normalized = word.trim().toLowerCase();
122
+ if (!normalized)
123
+ return null;
124
+ for (const group of ALL_GROUPS) {
125
+ if (liveGroups && !liveGroups.has(group.name))
126
+ continue;
127
+ for (const entry of group.commands) {
128
+ const firstToken = entry.command.split(/\s+/)[0] ?? "";
129
+ const names = firstToken.split("|").map((name) => name.trim().toLowerCase());
130
+ if (names.includes(normalized)) {
131
+ return `rig ${group.name} ${normalized}`;
132
+ }
133
+ }
134
+ }
135
+ return null;
136
+ }
137
+ function printTopLevelHelp(state = {}) {
138
+ console.log(renderTopLevelHelp());
139
+ }
140
+ function printAdvancedHelp() {
141
+ console.log(renderAdvancedHelp());
142
+ }
143
+ function printGroupHelpDocument(groupName) {
144
+ console.log(renderGroupHelp(groupName) ?? renderTopLevelHelp());
145
+ }
146
+ export {
147
+ suggestGroupCommandForWord,
148
+ renderTopLevelHelp,
149
+ renderRigBanner,
150
+ renderGroupHelp,
151
+ renderAdvancedHelp,
152
+ printTopLevelHelp,
153
+ printGroupHelpDocument,
154
+ printAdvancedHelp,
155
+ listHelpGroups,
156
+ helpCatalog
157
+ };
@@ -0,0 +1,33 @@
1
+ import { saveGitHubTokenForProject, type GitHubAuthStatus } from "@rig/runtime/control-plane/github/index";
2
+ export type GitHubAuthStatusResponse = {
3
+ readonly ok: true;
4
+ } & GitHubAuthStatus;
5
+ export type GitHubTokenPostResponse = Awaited<ReturnType<typeof saveGitHubTokenForProject>> & {
6
+ readonly authenticated: boolean;
7
+ readonly apiSessionToken: string;
8
+ };
9
+ export declare function setGitHubBearerTokenForCurrentProcess(token: string | null, projectRoot?: string): void;
10
+ export declare function getGitHubAuthStatusInProcess(context: {
11
+ projectRoot: string;
12
+ }): Promise<GitHubAuthStatusResponse>;
13
+ export declare function postGitHubTokenInProcess(context: {
14
+ projectRoot: string;
15
+ }, token: string, options?: {
16
+ readonly selectedRepo?: string;
17
+ readonly projectRoot?: string;
18
+ }): Promise<GitHubTokenPostResponse>;
19
+ export declare function listGitHubProjectsInProcess(context: {
20
+ projectRoot: string;
21
+ }, owner: string, options?: {
22
+ readonly authToken?: string | null;
23
+ readonly baseUrl?: string | null;
24
+ }): Promise<Record<string, unknown>>;
25
+ export declare function getGitHubProjectStatusFieldInProcess(context: {
26
+ projectRoot: string;
27
+ }, projectId: string, options?: {
28
+ readonly authToken?: string | null;
29
+ readonly baseUrl?: string | null;
30
+ }): Promise<Record<string, unknown>>;
31
+ export declare function requestGitHubAuthJsonInProcess(context: {
32
+ projectRoot: string;
33
+ }, pathname: string, init?: RequestInit): Promise<unknown>;
@@ -0,0 +1,102 @@
1
+ // @bun
2
+ // packages/cli-surface-plugin/src/commands/_inprocess-services.ts
3
+ import { resolve } from "path";
4
+ import {
5
+ beginGitHubDeviceFlow,
6
+ checkGitHubRepoPermissions,
7
+ createGitHubAuthStore,
8
+ listGitHubProjects,
9
+ pollGitHubDeviceFlow,
10
+ resolveGitHubAuthStatus,
11
+ resolveProjectStatusField,
12
+ saveGitHubTokenForProject
13
+ } from "@rig/runtime/control-plane/github/index";
14
+ var scopedGitHubBearerTokens = new Map;
15
+ function cleanToken(value) {
16
+ const trimmed = value?.trim();
17
+ return trimmed ? trimmed : null;
18
+ }
19
+ function cleanString(value) {
20
+ return typeof value === "string" && value.trim() ? value.trim() : null;
21
+ }
22
+ function oauthClientId() {
23
+ return cleanToken(process.env.RIG_GITHUB_OAUTH_CLIENT_ID);
24
+ }
25
+ function tokenForProject(projectRoot, override) {
26
+ const scoped = scopedGitHubBearerTokens.get(resolve(projectRoot));
27
+ return cleanToken(override) ?? scoped ?? createGitHubAuthStore(projectRoot).readToken() ?? cleanToken(process.env.RIG_GITHUB_TOKEN);
28
+ }
29
+ function setGitHubBearerTokenForCurrentProcess(token, projectRoot) {
30
+ scopedGitHubBearerTokens.set(resolve(projectRoot ?? process.cwd()), cleanToken(token));
31
+ }
32
+ async function getGitHubAuthStatusInProcess(context) {
33
+ return { ok: true, ...resolveGitHubAuthStatus({ projectRoot: context.projectRoot, oauthConfigured: Boolean(oauthClientId()) }) };
34
+ }
35
+ async function postGitHubTokenInProcess(context, token, options = {}) {
36
+ const targetRoot = options.projectRoot?.trim() || context.projectRoot;
37
+ const result = await saveGitHubTokenForProject({
38
+ projectRoot: targetRoot,
39
+ token,
40
+ tokenSource: "manual-token",
41
+ selectedRepo: options.selectedRepo ?? null
42
+ });
43
+ const store = createGitHubAuthStore(targetRoot);
44
+ const session = store.createApiSession();
45
+ if (targetRoot !== context.projectRoot) {
46
+ store.copyToLocalProjectRoot(context.projectRoot);
47
+ }
48
+ return { ...result, authenticated: result.signedIn, apiSessionToken: session.token };
49
+ }
50
+ async function listGitHubProjectsInProcess(context, owner, options = {}) {
51
+ const token = tokenForProject(context.projectRoot, options.authToken);
52
+ if (!token)
53
+ return { ok: false, error: "missing-token", projects: [] };
54
+ const projects = await listGitHubProjects({ owner, token });
55
+ return { ok: true, projects };
56
+ }
57
+ async function getGitHubProjectStatusFieldInProcess(context, projectId, options = {}) {
58
+ const token = tokenForProject(context.projectRoot, options.authToken);
59
+ if (!token)
60
+ return { ok: false, error: "missing-token" };
61
+ const field = await resolveProjectStatusField({ projectId, token });
62
+ return { ok: true, field };
63
+ }
64
+ async function requestGitHubAuthJsonInProcess(context, pathname, init = {}) {
65
+ const method = (init.method ?? "GET").toUpperCase();
66
+ if (pathname === "/api/github/auth/status")
67
+ return getGitHubAuthStatusInProcess(context);
68
+ if (pathname === "/api/github/repo/permissions") {
69
+ return checkGitHubRepoPermissions({ projectRoot: context.projectRoot, oauthConfigured: Boolean(oauthClientId()) });
70
+ }
71
+ if (pathname === "/api/github/auth/device/start" && method === "POST") {
72
+ const clientId = oauthClientId();
73
+ if (!clientId)
74
+ return { ok: false, oauthConfigured: false, error: "RIG_GITHUB_OAUTH_CLIENT_ID is not configured." };
75
+ const body = init.body ? JSON.parse(String(init.body)) : {};
76
+ return beginGitHubDeviceFlow({
77
+ projectRoot: context.projectRoot,
78
+ clientId,
79
+ ...cleanString(body.scope) ? { scope: cleanString(body.scope) } : {},
80
+ selectedRepo: cleanString(body.repoSlug)
81
+ });
82
+ }
83
+ if (pathname === "/api/github/auth/device/poll" && method === "POST") {
84
+ const clientId = oauthClientId();
85
+ if (!clientId)
86
+ return { ok: false, oauthConfigured: false, error: "RIG_GITHUB_OAUTH_CLIENT_ID is not configured." };
87
+ const body = init.body ? JSON.parse(String(init.body)) : {};
88
+ const pollId = cleanString(body.pollId);
89
+ if (!pollId)
90
+ return { ok: false, status: "error", error: "pollId is required" };
91
+ return pollGitHubDeviceFlow({ projectRoot: context.projectRoot, clientId, pollId, selectedRepo: cleanString(body.repoSlug) });
92
+ }
93
+ throw new Error(`No in-process GitHub auth API for ${method} ${pathname}`);
94
+ }
95
+ export {
96
+ setGitHubBearerTokenForCurrentProcess,
97
+ requestGitHubAuthJsonInProcess,
98
+ postGitHubTokenInProcess,
99
+ listGitHubProjectsInProcess,
100
+ getGitHubProjectStatusFieldInProcess,
101
+ getGitHubAuthStatusInProcess
102
+ };
@@ -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,54 @@
1
+ // @bun
2
+ // packages/cli-surface-plugin/src/commands/_json-output.ts
3
+ import { Schema } from "effect";
4
+ import {
5
+ RigDoctorCheckOutput,
6
+ RigInboxApprovalsOutput,
7
+ RigInboxInputsOutput,
8
+ RigRunListOutput,
9
+ RigRunShowOutput,
10
+ RigStatsOutput,
11
+ RigTaskListOutput,
12
+ RigTaskShowOutput
13
+ } from "@rig/contracts";
14
+ var CLI_OUTPUT_SCHEMAS = {
15
+ "task list": RigTaskListOutput,
16
+ "task show": RigTaskShowOutput,
17
+ "run list": RigRunListOutput,
18
+ "run show": RigRunShowOutput,
19
+ "inbox approvals": RigInboxApprovalsOutput,
20
+ "inbox inputs": RigInboxInputsOutput,
21
+ "doctor check": RigDoctorCheckOutput,
22
+ "stats show": RigStatsOutput
23
+ };
24
+ function isCommandOutcomeLike(value) {
25
+ if (!value || typeof value !== "object" || Array.isArray(value))
26
+ return false;
27
+ const record = value;
28
+ return typeof record.group === "string" && typeof record.command === "string";
29
+ }
30
+ function buildCliJsonEnvelope(outcome, options = {}) {
31
+ if (!isCommandOutcomeLike(outcome))
32
+ return null;
33
+ const commandKey = `${outcome.group} ${outcome.command}`;
34
+ const schema = CLI_OUTPUT_SCHEMAS[commandKey];
35
+ if (!schema)
36
+ return null;
37
+ const warn = options.warn ?? ((message) => console.error(message));
38
+ const envelope = { v: 1, command: commandKey, data: outcome.details ?? {} };
39
+ try {
40
+ Schema.decodeUnknownSync(schema)(JSON.parse(JSON.stringify(envelope)));
41
+ return envelope;
42
+ } catch (error) {
43
+ warn(`[rig] --json output for "${commandKey}" failed schema validation; printing legacy payload. ` + `(${error instanceof Error ? error.message.split(`
44
+ `)[0] : String(error)})`);
45
+ return null;
46
+ }
47
+ }
48
+ function listSchematizedCliCommands() {
49
+ return Object.keys(CLI_OUTPUT_SCHEMAS).sort();
50
+ }
51
+ export {
52
+ listSchematizedCliCommands,
53
+ buildCliJsonEnvelope
54
+ };
@@ -0,0 +1,15 @@
1
+ import type { TaskSourceConfig } from "@rig/contracts";
2
+ import type { RigPluginWithRuntime } from "@rig/core";
3
+ export declare function parsePositiveInt(value: string | undefined, option: string, fallback: number): number;
4
+ export declare function parseOptionalPositiveInt(value: string | undefined, option: string): number | undefined;
5
+ export declare function parseRequiredPositiveInt(value: string | undefined, option: string): number;
6
+ export declare function parseAction(value: string | undefined): "validate" | "verify" | "pipeline";
7
+ export declare function parseIsolationMode(value: string | undefined, allowOff: true): "off" | "worktree";
8
+ export declare function parseIsolationMode(value: string | undefined, allowOff: false): "worktree";
9
+ export declare function parseInstallScope(value: string | undefined): "user" | "system";
10
+ export declare function resolveInstallDir(scope: "user" | "system", explicitPath: string | undefined): string;
11
+ export type CliRigConfig = {
12
+ plugins?: readonly RigPluginWithRuntime[];
13
+ taskSource?: TaskSourceConfig;
14
+ };
15
+ export declare function loadRigConfigOrNull(projectRoot: string): Promise<CliRigConfig | null>;
@@ -0,0 +1,114 @@
1
+ // @bun
2
+ var __require = import.meta.require;
3
+
4
+ // packages/cli-surface-plugin/src/commands/_parsers.ts
5
+ import { homedir } from "os";
6
+ import { resolve } from "path";
7
+
8
+ // packages/cli-surface-plugin/src/runner.ts
9
+ import { EventBus } from "@rig/runtime/control-plane/runtime/events";
10
+ import { CliError as RuntimeCliError } from "@rig/runtime/control-plane/errors";
11
+ import { evaluate, loadPolicy, resolveAction } from "@rig/runtime/control-plane/runtime/guard";
12
+ import { buildBinary } from "@rig/runtime/control-plane/runtime/isolation";
13
+
14
+ class CliError extends RuntimeCliError {
15
+ hint;
16
+ constructor(message, exitCode = 1, options = {}) {
17
+ super(message, exitCode);
18
+ if (options.hint?.trim()) {
19
+ this.hint = options.hint.trim();
20
+ }
21
+ }
22
+ }
23
+
24
+ // packages/cli-surface-plugin/src/commands/_parsers.ts
25
+ function parsePositiveInt(value, option, fallback) {
26
+ if (!value) {
27
+ return fallback;
28
+ }
29
+ const parsed = Number.parseInt(value, 10);
30
+ if (!Number.isFinite(parsed) || parsed <= 0) {
31
+ throw new CliError(`Invalid ${option} value: ${value}`, 1, { hint: `Pass a positive integer, e.g. \`${option} 10\`.` });
32
+ }
33
+ return parsed;
34
+ }
35
+ function parseOptionalPositiveInt(value, option) {
36
+ if (!value) {
37
+ return;
38
+ }
39
+ const parsed = Number.parseInt(value, 10);
40
+ if (!Number.isFinite(parsed) || parsed <= 0) {
41
+ throw new CliError(`Invalid ${option} value: ${value}`, 1, { hint: `Pass a positive integer, e.g. \`${option} 10\`.` });
42
+ }
43
+ return parsed;
44
+ }
45
+ function parseRequiredPositiveInt(value, option) {
46
+ if (!value) {
47
+ throw new CliError(`Missing value for ${option}.`, 1, { hint: `Provide a value after ${option}, e.g. \`${option} 10\`.` });
48
+ }
49
+ const parsed = Number.parseInt(value, 10);
50
+ if (!Number.isFinite(parsed) || parsed <= 0) {
51
+ throw new CliError(`Invalid ${option} value: ${value}`, 1, { hint: `Pass a positive integer, e.g. \`${option} 10\`.` });
52
+ }
53
+ return parsed;
54
+ }
55
+ function parseAction(value) {
56
+ if (!value || value === "validate") {
57
+ return "validate";
58
+ }
59
+ if (value === "verify") {
60
+ return "verify";
61
+ }
62
+ if (value === "pipeline") {
63
+ return "pipeline";
64
+ }
65
+ throw new CliError(`Invalid --action value: ${value}. Use validate, verify, or pipeline.`);
66
+ }
67
+ function parseIsolationMode(value, allowOff) {
68
+ if (!value) {
69
+ return "worktree";
70
+ }
71
+ if (value === "worktree") {
72
+ return value;
73
+ }
74
+ if (allowOff && value === "off") {
75
+ return value;
76
+ }
77
+ throw new CliError(`Invalid isolation mode: ${value}. Use ${allowOff ? "off|" : ""}worktree.`);
78
+ }
79
+ function parseInstallScope(value) {
80
+ if (!value || value === "user") {
81
+ return "user";
82
+ }
83
+ if (value === "system") {
84
+ return "system";
85
+ }
86
+ throw new CliError(`Invalid --scope value: ${value}. Use user|system.`);
87
+ }
88
+ function resolveInstallDir(scope, explicitPath) {
89
+ if (explicitPath) {
90
+ return resolve(explicitPath);
91
+ }
92
+ if (scope === "system") {
93
+ return "/usr/local/bin";
94
+ }
95
+ return resolve(homedir(), ".local/bin");
96
+ }
97
+ async function loadRigConfigOrNull(projectRoot) {
98
+ try {
99
+ const { loadConfig } = await import("@rig/core/load-config");
100
+ return await loadConfig(projectRoot);
101
+ } catch {
102
+ return null;
103
+ }
104
+ }
105
+ export {
106
+ resolveInstallDir,
107
+ parseRequiredPositiveInt,
108
+ parsePositiveInt,
109
+ parseOptionalPositiveInt,
110
+ parseIsolationMode,
111
+ parseInstallScope,
112
+ parseAction,
113
+ loadRigConfigOrNull
114
+ };
@@ -0,0 +1,11 @@
1
+ export declare function resolveControlPlaneMonorepoRoot(projectRoot: string): string;
2
+ export declare function resolveControlPlaneTaskConfigPath(projectRoot: string): string;
3
+ export declare function resolveControlPlaneHostStateRoot(projectRoot: string): string;
4
+ export declare function resolveControlPlaneHostStateDir(projectRoot: string): string;
5
+ export declare function resolveControlPlaneHostLogsDir(projectRoot: string): string;
6
+ export declare function resolveControlPlaneHostBinDir(projectRoot: string): string;
7
+ export declare function resolveControlPlaneHostDistDir(projectRoot: string): string;
8
+ export declare function resolveControlPlaneMonorepoStateRoot(projectRoot: string): string;
9
+ export declare function resolveControlPlaneMonorepoRuntimeDir(projectRoot: string): string;
10
+ export declare function resolveControlPlaneArtifactsDir(projectRoot: string): string;
11
+ export declare function resolveControlPlaneDefinitionRoot(projectRoot: string): string;
@@ -0,0 +1,50 @@
1
+ // @bun
2
+ // packages/cli-surface-plugin/src/commands/_paths.ts
3
+ import { resolve } from "path";
4
+ import { resolveMonorepoRoot } from "@rig/runtime/layout";
5
+ function resolveControlPlaneMonorepoRoot(projectRoot) {
6
+ return resolveMonorepoRoot(projectRoot);
7
+ }
8
+ function resolveControlPlaneTaskConfigPath(projectRoot) {
9
+ return resolve(resolveControlPlaneMonorepoRoot(projectRoot), ".rig", "task-config.json");
10
+ }
11
+ function resolveControlPlaneHostStateRoot(projectRoot) {
12
+ return resolve(projectRoot, ".rig");
13
+ }
14
+ function resolveControlPlaneHostStateDir(projectRoot) {
15
+ return resolve(resolveControlPlaneHostStateRoot(projectRoot), "state");
16
+ }
17
+ function resolveControlPlaneHostLogsDir(projectRoot) {
18
+ return resolve(resolveControlPlaneHostStateRoot(projectRoot), "logs");
19
+ }
20
+ function resolveControlPlaneHostBinDir(projectRoot) {
21
+ return resolve(resolveControlPlaneHostStateRoot(projectRoot), "bin");
22
+ }
23
+ function resolveControlPlaneHostDistDir(projectRoot) {
24
+ return resolve(resolveControlPlaneHostStateRoot(projectRoot), "dist");
25
+ }
26
+ function resolveControlPlaneMonorepoStateRoot(projectRoot) {
27
+ return resolve(resolveControlPlaneMonorepoRoot(projectRoot), ".rig");
28
+ }
29
+ function resolveControlPlaneMonorepoRuntimeDir(projectRoot) {
30
+ return resolve(resolveControlPlaneMonorepoStateRoot(projectRoot), "runtime");
31
+ }
32
+ function resolveControlPlaneArtifactsDir(projectRoot) {
33
+ return resolve(resolveControlPlaneMonorepoRoot(projectRoot), "artifacts");
34
+ }
35
+ function resolveControlPlaneDefinitionRoot(projectRoot) {
36
+ return resolve(projectRoot, "rig");
37
+ }
38
+ export {
39
+ resolveControlPlaneTaskConfigPath,
40
+ resolveControlPlaneMonorepoStateRoot,
41
+ resolveControlPlaneMonorepoRuntimeDir,
42
+ resolveControlPlaneMonorepoRoot,
43
+ resolveControlPlaneHostStateRoot,
44
+ resolveControlPlaneHostStateDir,
45
+ resolveControlPlaneHostLogsDir,
46
+ resolveControlPlaneHostDistDir,
47
+ resolveControlPlaneHostBinDir,
48
+ resolveControlPlaneDefinitionRoot,
49
+ resolveControlPlaneArtifactsDir
50
+ };
@@ -0,0 +1,35 @@
1
+ import type { RunnerContext } from "../runner";
2
+ type AttachResult = {
3
+ readonly run: Record<string, unknown>;
4
+ readonly logs: Record<string, unknown>[];
5
+ readonly timeline: Record<string, unknown>[];
6
+ readonly timelineCursor: string | null;
7
+ readonly steered: boolean;
8
+ readonly rendered: string;
9
+ readonly detached?: boolean;
10
+ };
11
+ export declare function resolveOperatorDroneCwd(runId: string, homeDir?: string): string;
12
+ /**
13
+ * Compose the operator-session environment used by the legacy interactive
14
+ * attach shim. Exported for tests that pin the env contract.
15
+ */
16
+ export declare function buildOperatorPiEnv(input: {
17
+ readonly runId: string;
18
+ readonly serverUrl: string;
19
+ readonly authToken?: string | null;
20
+ readonly serverProjectRoot?: string | null;
21
+ readonly sessionDir: string;
22
+ }): Record<string, string>;
23
+ export declare function shouldRequireOperatorTranscript(status: unknown): boolean;
24
+ export declare function missingOperatorTranscriptMessage(runId: string, status: unknown): string;
25
+ /**
26
+ * Run `body` in-process while RETURNING (instead of terminating) when it calls
27
+ * `process.exit`. Exported for unit tests that pin the guard semantics.
28
+ */
29
+ export declare function runWithProcessExitGuard(body: () => Promise<unknown>): Promise<number>;
30
+ export declare function attachRunBundledPiFrontend(context: Pick<RunnerContext, "projectRoot" | "outputMode">, input: {
31
+ readonly runId: string;
32
+ readonly steered?: boolean;
33
+ readonly returnOnQuit?: boolean;
34
+ }): Promise<AttachResult>;
35
+ export {};
@@ -0,0 +1,64 @@
1
+ // @bun
2
+ // packages/cli-surface-plugin/src/commands/_pi-frontend.ts
3
+ import { homedir } from "os";
4
+ import { join } from "path";
5
+ import { assertPathInsideRoot, assertSafeRunId, safePathSegment } from "@rig/shared/safe-identifiers";
6
+ var TERMINAL_RUN_STATUSES = { completed: true, failed: true, stopped: true, cancelled: true, canceled: true, closed: true, merged: true, needs_attention: true, "needs-attention": true };
7
+ function resolveOperatorDroneCwd(runId, homeDir = homedir()) {
8
+ const safeRunId = assertSafeRunId(runId);
9
+ const dronesRoot = join(homeDir, ".rig", "drones");
10
+ return assertPathInsideRoot(dronesRoot, join(dronesRoot, safePathSegment(String(safeRunId).slice(0, 8), { fallback: "run", maxLength: 32 })), "operator drone cwd");
11
+ }
12
+ function buildOperatorPiEnv(input) {
13
+ return {
14
+ PI_CODING_AGENT_SESSION_DIR: input.sessionDir,
15
+ PI_SKIP_VERSION_CHECK: "1",
16
+ PI_HIDDEN_COMMANDS: "import,fork,clone,tree,new,resume,trust",
17
+ RIG_PI_OPERATOR_SESSION: "1",
18
+ RIG_RUN_ID: input.runId,
19
+ RIG_SERVER_URL: input.serverUrl,
20
+ ...input.authToken ? { RIG_AUTH_TOKEN: input.authToken } : {},
21
+ ...input.serverProjectRoot ? { RIG_PROJECT_ROOT: input.serverProjectRoot } : {}
22
+ };
23
+ }
24
+ function shouldRequireOperatorTranscript(status) {
25
+ return typeof status === "string" && TERMINAL_RUN_STATUSES[status.trim().toLowerCase()] === true;
26
+ }
27
+ function missingOperatorTranscriptMessage(runId, status) {
28
+ const shortRun = runId.trim().slice(0, 8) || "unknown";
29
+ const statusText = typeof status === "string" && status.trim() ? status.trim() : "terminal";
30
+ return `Run ${shortRun} is ${statusText}, but no worker Pi session transcript is recorded for this run. It likely failed before Pi started or predates full-session capture. Use \`rig run show ${runId}\` and \`rig run logs ${runId}\` for the lifecycle details.`;
31
+ }
32
+ async function runWithProcessExitGuard(body) {
33
+ const realExit = process.exit;
34
+ let exitCode = 0;
35
+ let signalQuit = () => {};
36
+ const quit = new Promise((resolve) => {
37
+ signalQuit = resolve;
38
+ });
39
+ const guardedExit = (code) => {
40
+ exitCode = typeof code === "number" ? code : 0;
41
+ signalQuit();
42
+ return;
43
+ };
44
+ process.exit = guardedExit;
45
+ try {
46
+ await Promise.race([Promise.resolve().then(body), quit]);
47
+ } finally {
48
+ process.exit = realExit;
49
+ }
50
+ return exitCode;
51
+ }
52
+ async function attachRunBundledPiFrontend(context, input) {
53
+ input.steered;
54
+ input.returnOnQuit;
55
+ throw new Error(`Interactive Pi attach for run ${input.runId} was removed in the OMP-collab cutover. Run bare \`rig\` and use the OMP cockpit run detail for the live session; legacy automation can request a non-interactive text snapshot with --once or --json.`);
56
+ }
57
+ export {
58
+ shouldRequireOperatorTranscript,
59
+ runWithProcessExitGuard,
60
+ resolveOperatorDroneCwd,
61
+ missingOperatorTranscriptMessage,
62
+ buildOperatorPiEnv,
63
+ attachRunBundledPiFrontend
64
+ };