@h-rig/cli-surface-plugin 0.0.6-alpha.157 → 0.0.6-alpha.159
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/dist/src/app/drone-ui.d.ts +0 -11
- package/dist/src/app/drone-ui.js +0 -114
- package/dist/src/commands/_async-ui.d.ts +1 -1
- package/dist/src/commands/_cli-format.d.ts +0 -29
- package/dist/src/commands/_cli-format.js +59 -113
- package/dist/src/commands/_connection-state.d.ts +6 -33
- package/dist/src/commands/_connection-state.js +654 -138
- package/dist/src/commands/_doctor-checks.d.ts +2 -5
- package/dist/src/commands/_doctor-checks.js +10 -9
- package/dist/src/commands/_help-catalog.d.ts +2 -1
- package/dist/src/commands/_help-catalog.js +654 -7
- package/dist/src/commands/_inprocess-services.d.ts +5 -5
- package/dist/src/commands/_inprocess-services.js +1 -1
- package/dist/src/commands/_parsers.js +651 -12
- package/dist/src/commands/_paths.d.ts +0 -2
- package/dist/src/commands/_paths.js +2 -10
- package/dist/src/commands/_pi-install.d.ts +2 -12
- package/dist/src/commands/_pi-install.js +3 -36
- package/dist/src/commands/_policy.js +659 -20
- package/dist/src/commands/agent.d.ts +1 -1
- package/dist/src/commands/agent.js +675 -24
- package/dist/src/commands/config.d.ts +1 -1
- package/dist/src/commands/config.js +656 -21
- package/dist/src/commands/dist.d.ts +1 -1
- package/dist/src/commands/dist.js +828 -102
- package/dist/src/commands/doctor.d.ts +1 -1
- package/dist/src/commands/doctor.js +658 -12
- package/dist/src/commands/github.d.ts +1 -1
- package/dist/src/commands/github.js +658 -19
- package/dist/src/commands/inbox.d.ts +12 -8
- package/dist/src/commands/inbox.js +741 -22
- package/dist/src/commands/init.d.ts +17 -19
- package/dist/src/commands/init.js +836 -306
- package/dist/src/commands/inspect.d.ts +5 -6
- package/dist/src/commands/inspect.js +754 -42
- package/dist/src/commands/pi.d.ts +1 -1
- package/dist/src/commands/pi.js +655 -16
- package/dist/src/commands/plugin.d.ts +9 -9
- package/dist/src/commands/plugin.js +652 -13
- package/dist/src/commands/profile-and-review.d.ts +1 -1
- package/dist/src/commands/profile-and-review.js +655 -16
- package/dist/src/commands/queue.d.ts +1 -1
- package/dist/src/commands/queue.js +871 -12
- package/dist/src/commands/remote-client.d.ts +152 -0
- package/dist/src/commands/remote-client.js +475 -0
- package/dist/src/commands/remote.d.ts +1 -1
- package/dist/src/commands/remote.js +1100 -29
- package/dist/src/commands/repo-git-harness.d.ts +1 -1
- package/dist/src/commands/repo-git-harness.js +2321 -47
- package/dist/src/commands/run.d.ts +10 -6
- package/dist/src/commands/run.js +830 -50
- package/dist/src/commands/server.d.ts +1 -1
- package/dist/src/commands/server.js +649 -11
- package/dist/src/commands/setup.d.ts +2 -2
- package/dist/src/commands/setup.js +829 -18
- package/dist/src/commands/stats.d.ts +2 -4
- package/dist/src/commands/stats.js +1299 -20
- package/dist/src/commands/test.d.ts +1 -1
- package/dist/src/commands/test.js +648 -9
- package/dist/src/commands/triage.d.ts +2 -3
- package/dist/src/commands/triage.js +657 -11
- package/dist/src/commands/workspace.d.ts +1 -1
- package/dist/src/commands/workspace.js +1280 -15
- package/dist/src/control-plane/agent-binary-build.d.ts +9 -0
- package/dist/src/control-plane/agent-binary-build.js +88 -0
- package/dist/src/control-plane/embedded-native-assets.d.ts +7 -0
- package/dist/src/control-plane/embedded-native-assets.js +6 -0
- package/dist/src/control-plane/guard.d.ts +17 -0
- package/dist/src/control-plane/guard.js +684 -0
- package/dist/src/control-plane/harness-cli.d.ts +12 -0
- package/dist/src/control-plane/harness-cli.js +1623 -0
- package/dist/src/control-plane/native/git-ops.d.ts +67 -0
- package/dist/src/control-plane/native/git-ops.js +1381 -0
- package/dist/src/control-plane/native/github-auth-env.d.ts +1 -0
- package/dist/src/control-plane/native/github-auth-env.js +21 -0
- package/dist/src/control-plane/native/host-git.d.ts +4 -0
- package/dist/src/control-plane/native/host-git.js +51 -0
- package/dist/src/control-plane/priority-queue.d.ts +22 -0
- package/dist/src/control-plane/priority-queue.js +212 -0
- package/dist/src/control-plane/rigfig.d.ts +9 -0
- package/dist/src/control-plane/rigfig.js +70 -0
- package/dist/src/control-plane/scope.d.ts +3 -0
- package/dist/src/control-plane/scope.js +58 -0
- package/dist/src/control-plane/setup-status.d.ts +44 -0
- package/dist/src/control-plane/setup-status.js +164 -0
- package/dist/src/control-plane/task-data.d.ts +2 -0
- package/dist/src/control-plane/task-data.js +12 -0
- package/dist/src/control-plane/workspace-ops.d.ts +79 -0
- package/dist/src/control-plane/workspace-ops.js +639 -0
- package/dist/src/help-catalog-data.d.ts +7 -0
- package/dist/src/help-catalog-data.js +660 -0
- package/dist/src/kernel-dispatch.js +1 -3
- package/dist/src/plugin.js +10072 -30
- package/dist/src/runner.d.ts +7 -9
- package/dist/src/runner.js +750 -30
- package/package.json +12 -13
- package/dist/src/commands/_json-output.d.ts +0 -11
- package/dist/src/commands/_json-output.js +0 -54
- package/dist/src/commands/_pi-frontend.d.ts +0 -35
- package/dist/src/commands/_pi-frontend.js +0 -64
- package/dist/src/commands/_run-driver-helpers.d.ts +0 -26
- package/dist/src/commands/_run-driver-helpers.js +0 -132
- package/dist/src/commands/task-run-driver.d.ts +0 -93
- package/dist/src/commands/task-run-driver.js +0 -136
- package/dist/src/commands/task.d.ts +0 -46
- package/dist/src/commands/task.js +0 -555
- package/dist/src/provider-model.d.ts +0 -34
- package/dist/src/provider-model.js +0 -56
- package/dist/src/rig-config-package-deps.d.ts +0 -10
- package/dist/src/rig-config-package-deps.js +0 -272
- package/dist/src/version.d.ts +0 -8
- package/dist/src/version.js +0 -47
|
@@ -1,20 +1,661 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
// packages/cli-surface-plugin/src/commands/stats.ts
|
|
3
|
-
import {
|
|
3
|
+
import { RUN_READ_MODEL } from "@rig/contracts";
|
|
4
|
+
import { defineCapability } from "@rig/core/capability";
|
|
5
|
+
import { requireCapabilityForRoot } from "@rig/core/capability-loaders";
|
|
4
6
|
|
|
5
7
|
// packages/cli-surface-plugin/src/runner.ts
|
|
6
|
-
import { EventBus } from "@rig/runtime
|
|
7
|
-
import { CliError as RuntimeCliError } from "@rig/
|
|
8
|
-
import { evaluate, loadPolicy, resolveAction } from "@rig/runtime/control-plane/runtime/guard";
|
|
9
|
-
import { buildBinary } from "@rig/runtime/control-plane/runtime/isolation";
|
|
8
|
+
import { EventBus } from "@rig/core/runtime-events";
|
|
9
|
+
import { CliError as RuntimeCliError } from "@rig/contracts";
|
|
10
10
|
|
|
11
|
+
// packages/cli-surface-plugin/src/control-plane/guard.ts
|
|
12
|
+
import { optimizeNextInvocation } from "bun:jsc";
|
|
13
|
+
import { existsSync, readFileSync, statSync } from "fs";
|
|
14
|
+
import { resolve } from "path";
|
|
15
|
+
|
|
16
|
+
// packages/cli-surface-plugin/src/control-plane/scope.ts
|
|
17
|
+
import { getScopeRules } from "@rig/core/scope-rules";
|
|
18
|
+
var scopeRegexCache = new Map;
|
|
19
|
+
function unique(values) {
|
|
20
|
+
return [...new Set(values)];
|
|
21
|
+
}
|
|
22
|
+
function normalizeRelativeScopePath(inputPath) {
|
|
23
|
+
let normalized = inputPath.replace(/^\.\//, "");
|
|
24
|
+
const rules = getScopeRules();
|
|
25
|
+
if (rules?.stripPrefixes) {
|
|
26
|
+
for (const prefix of rules.stripPrefixes) {
|
|
27
|
+
if (normalized.startsWith(prefix)) {
|
|
28
|
+
normalized = normalized.slice(prefix.length);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return normalized;
|
|
33
|
+
}
|
|
34
|
+
function normalizePathToScope(projectRoot, monorepoRoot, inputPath) {
|
|
35
|
+
let normalized = inputPath.replace(/^\.\//, "");
|
|
36
|
+
if (normalized.startsWith(projectRoot + "/")) {
|
|
37
|
+
normalized = normalized.slice(projectRoot.length + 1);
|
|
38
|
+
}
|
|
39
|
+
if (normalized.startsWith(monorepoRoot + "/")) {
|
|
40
|
+
normalized = normalized.slice(monorepoRoot.length + 1);
|
|
41
|
+
}
|
|
42
|
+
return normalizeRelativeScopePath(normalized);
|
|
43
|
+
}
|
|
44
|
+
function scopeGlobToRegex(glob) {
|
|
45
|
+
const cached = scopeRegexCache.get(glob);
|
|
46
|
+
if (cached) {
|
|
47
|
+
return cached;
|
|
48
|
+
}
|
|
49
|
+
const escaped = glob.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*\*/g, "__GLOBSTAR__").replace(/\*/g, "[^/]*").replace(/__GLOBSTAR__/g, ".*");
|
|
50
|
+
const compiled = new RegExp(`^${escaped}$`);
|
|
51
|
+
scopeRegexCache.set(glob, compiled);
|
|
52
|
+
return compiled;
|
|
53
|
+
}
|
|
54
|
+
function scopeMatches(path, scopes) {
|
|
55
|
+
const pathVariants = unique([path, normalizeRelativeScopePath(path)]);
|
|
56
|
+
for (const scope of scopes) {
|
|
57
|
+
const scopeVariants = unique([scope, normalizeRelativeScopePath(scope)]);
|
|
58
|
+
for (const candidatePath of pathVariants) {
|
|
59
|
+
for (const candidateScope of scopeVariants) {
|
|
60
|
+
if (candidatePath === candidateScope || scopeGlobToRegex(candidateScope).test(candidatePath)) {
|
|
61
|
+
return true;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// packages/cli-surface-plugin/src/control-plane/guard.ts
|
|
70
|
+
import {
|
|
71
|
+
POLICY_VERSION
|
|
72
|
+
} from "@rig/contracts";
|
|
73
|
+
var DEFAULT_SCOPE = {
|
|
74
|
+
fail_closed: true,
|
|
75
|
+
harness_paths_exempt: true,
|
|
76
|
+
runtime_paths_exempt: true
|
|
77
|
+
};
|
|
78
|
+
var DEFAULT_SANDBOX = {
|
|
79
|
+
mode: "enforce",
|
|
80
|
+
network: true,
|
|
81
|
+
read_deny: [],
|
|
82
|
+
write_allow_from_runtime: true
|
|
83
|
+
};
|
|
84
|
+
var DEFAULT_ISOLATION = {
|
|
85
|
+
default_mode: "worktree",
|
|
86
|
+
repo_symlink_fallback: false,
|
|
87
|
+
strict_provisioning: true,
|
|
88
|
+
fail_closed_on_provision_error: true
|
|
89
|
+
};
|
|
90
|
+
var DEFAULT_COMPLETION = {
|
|
91
|
+
derive_checks_from_scope: true,
|
|
92
|
+
checks: [],
|
|
93
|
+
typescript_config_probe: ["tsconfig.json"],
|
|
94
|
+
eslint_config_probe: [".eslintrc.js", ".eslintrc.json", "eslint.config.js"]
|
|
95
|
+
};
|
|
96
|
+
var DEFAULT_RUNTIME_IMAGE = {
|
|
97
|
+
deps: {
|
|
98
|
+
monorepo_install: false,
|
|
99
|
+
hp_next_install: false
|
|
100
|
+
},
|
|
101
|
+
plugins_require_binaries: true
|
|
102
|
+
};
|
|
103
|
+
var DEFAULT_RUNTIME_SNAPSHOT = {
|
|
104
|
+
enabled: true
|
|
105
|
+
};
|
|
106
|
+
function defaultPolicy() {
|
|
107
|
+
return {
|
|
108
|
+
version: POLICY_VERSION,
|
|
109
|
+
mode: "enforce",
|
|
110
|
+
scope: { ...DEFAULT_SCOPE },
|
|
111
|
+
rules: [],
|
|
112
|
+
sandbox: { ...DEFAULT_SANDBOX },
|
|
113
|
+
isolation: { ...DEFAULT_ISOLATION },
|
|
114
|
+
completion: { ...DEFAULT_COMPLETION },
|
|
115
|
+
runtime_image: {
|
|
116
|
+
deps: { ...DEFAULT_RUNTIME_IMAGE.deps },
|
|
117
|
+
plugins_require_binaries: DEFAULT_RUNTIME_IMAGE.plugins_require_binaries
|
|
118
|
+
},
|
|
119
|
+
runtime_snapshot: { ...DEFAULT_RUNTIME_SNAPSHOT }
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
var policyCache = null;
|
|
123
|
+
var policyCachePath = null;
|
|
124
|
+
var seededPolicyConfig = null;
|
|
125
|
+
var compiledRegexCache = new Map;
|
|
126
|
+
function loadPolicy(projectRoot) {
|
|
127
|
+
if (seededPolicyConfig) {
|
|
128
|
+
return seededPolicyConfig;
|
|
129
|
+
}
|
|
130
|
+
const configPath = resolve(projectRoot, "rig/policy/policy.json");
|
|
131
|
+
if (!existsSync(configPath)) {
|
|
132
|
+
return defaultPolicy();
|
|
133
|
+
}
|
|
134
|
+
let mtimeMs;
|
|
135
|
+
try {
|
|
136
|
+
mtimeMs = statSync(configPath).mtimeMs;
|
|
137
|
+
} catch {
|
|
138
|
+
return defaultPolicy();
|
|
139
|
+
}
|
|
140
|
+
if (policyCache && policyCachePath === configPath && policyCache.mtimeMs === mtimeMs) {
|
|
141
|
+
return policyCache.config;
|
|
142
|
+
}
|
|
143
|
+
let parsed;
|
|
144
|
+
try {
|
|
145
|
+
parsed = JSON.parse(readFileSync(configPath, "utf-8"));
|
|
146
|
+
} catch {
|
|
147
|
+
return defaultPolicy();
|
|
148
|
+
}
|
|
149
|
+
const config = mergeWithDefaults(parsed);
|
|
150
|
+
policyCache = { mtimeMs, config };
|
|
151
|
+
policyCachePath = configPath;
|
|
152
|
+
return config;
|
|
153
|
+
}
|
|
154
|
+
function mergeWithDefaults(parsed) {
|
|
155
|
+
const base = defaultPolicy();
|
|
156
|
+
if (typeof parsed.mode === "string" && isValidMode(parsed.mode)) {
|
|
157
|
+
base.mode = parsed.mode;
|
|
158
|
+
}
|
|
159
|
+
if (parsed.scope && typeof parsed.scope === "object" && !Array.isArray(parsed.scope)) {
|
|
160
|
+
const s = parsed.scope;
|
|
161
|
+
if (typeof s.fail_closed === "boolean")
|
|
162
|
+
base.scope.fail_closed = s.fail_closed;
|
|
163
|
+
if (typeof s.harness_paths_exempt === "boolean")
|
|
164
|
+
base.scope.harness_paths_exempt = s.harness_paths_exempt;
|
|
165
|
+
if (typeof s.runtime_paths_exempt === "boolean")
|
|
166
|
+
base.scope.runtime_paths_exempt = s.runtime_paths_exempt;
|
|
167
|
+
}
|
|
168
|
+
if (Array.isArray(parsed.rules)) {
|
|
169
|
+
base.rules = precompilePolicyRuleRegexes(parsed.rules.filter(isValidRule));
|
|
170
|
+
}
|
|
171
|
+
if (Array.isArray(parsed.deny) && base.rules.length === 0) {
|
|
172
|
+
base.rules = precompilePolicyRuleRegexes(migrateLegacyDeny(parsed.deny));
|
|
173
|
+
}
|
|
174
|
+
if (parsed.sandbox && typeof parsed.sandbox === "object" && !Array.isArray(parsed.sandbox)) {
|
|
175
|
+
const sb = parsed.sandbox;
|
|
176
|
+
if (typeof sb.mode === "string" && isValidMode(sb.mode))
|
|
177
|
+
base.sandbox.mode = sb.mode;
|
|
178
|
+
if (typeof sb.network === "boolean")
|
|
179
|
+
base.sandbox.network = sb.network;
|
|
180
|
+
if (Array.isArray(sb.read_deny))
|
|
181
|
+
base.sandbox.read_deny = sb.read_deny.filter((v) => typeof v === "string");
|
|
182
|
+
if (typeof sb.write_allow_from_runtime === "boolean")
|
|
183
|
+
base.sandbox.write_allow_from_runtime = sb.write_allow_from_runtime;
|
|
184
|
+
}
|
|
185
|
+
if (parsed.isolation && typeof parsed.isolation === "object" && !Array.isArray(parsed.isolation)) {
|
|
186
|
+
const iso = parsed.isolation;
|
|
187
|
+
if (iso.default_mode === "worktree")
|
|
188
|
+
base.isolation.default_mode = iso.default_mode;
|
|
189
|
+
if (typeof iso.repo_symlink_fallback === "boolean")
|
|
190
|
+
base.isolation.repo_symlink_fallback = iso.repo_symlink_fallback;
|
|
191
|
+
if (typeof iso.strict_provisioning === "boolean")
|
|
192
|
+
base.isolation.strict_provisioning = iso.strict_provisioning;
|
|
193
|
+
if (typeof iso.fail_closed_on_provision_error === "boolean")
|
|
194
|
+
base.isolation.fail_closed_on_provision_error = iso.fail_closed_on_provision_error;
|
|
195
|
+
}
|
|
196
|
+
if (parsed.completion && typeof parsed.completion === "object" && !Array.isArray(parsed.completion)) {
|
|
197
|
+
const comp = parsed.completion;
|
|
198
|
+
if (typeof comp.derive_checks_from_scope === "boolean")
|
|
199
|
+
base.completion.derive_checks_from_scope = comp.derive_checks_from_scope;
|
|
200
|
+
if (Array.isArray(comp.checks))
|
|
201
|
+
base.completion.checks = comp.checks.filter((v) => typeof v === "string");
|
|
202
|
+
if (Array.isArray(comp.typescript_config_probe))
|
|
203
|
+
base.completion.typescript_config_probe = comp.typescript_config_probe.filter((v) => typeof v === "string");
|
|
204
|
+
if (Array.isArray(comp.eslint_config_probe))
|
|
205
|
+
base.completion.eslint_config_probe = comp.eslint_config_probe.filter((v) => typeof v === "string");
|
|
206
|
+
}
|
|
207
|
+
if (parsed.runtime_image && typeof parsed.runtime_image === "object" && !Array.isArray(parsed.runtime_image)) {
|
|
208
|
+
const runtimeImage = parsed.runtime_image;
|
|
209
|
+
if (runtimeImage.deps && typeof runtimeImage.deps === "object" && !Array.isArray(runtimeImage.deps)) {
|
|
210
|
+
const deps = runtimeImage.deps;
|
|
211
|
+
if (typeof deps.monorepo_install === "boolean") {
|
|
212
|
+
base.runtime_image.deps.monorepo_install = deps.monorepo_install;
|
|
213
|
+
}
|
|
214
|
+
if (typeof deps.hp_next_install === "boolean") {
|
|
215
|
+
base.runtime_image.deps.hp_next_install = deps.hp_next_install;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
if (typeof runtimeImage.plugins_require_binaries === "boolean") {
|
|
219
|
+
base.runtime_image.plugins_require_binaries = runtimeImage.plugins_require_binaries;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
if (parsed.runtime_snapshot && typeof parsed.runtime_snapshot === "object" && !Array.isArray(parsed.runtime_snapshot)) {
|
|
223
|
+
const runtimeSnapshot = parsed.runtime_snapshot;
|
|
224
|
+
if (typeof runtimeSnapshot.enabled === "boolean") {
|
|
225
|
+
base.runtime_snapshot.enabled = runtimeSnapshot.enabled;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
return base;
|
|
229
|
+
}
|
|
230
|
+
function isValidMode(value) {
|
|
231
|
+
return value === "off" || value === "observe" || value === "enforce";
|
|
232
|
+
}
|
|
233
|
+
function isValidRule(value) {
|
|
234
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
235
|
+
return false;
|
|
236
|
+
const r = value;
|
|
237
|
+
return typeof r.id === "string" && typeof r.category === "string" && r.match != null && typeof r.match === "object";
|
|
238
|
+
}
|
|
239
|
+
function migrateLegacyDeny(deny) {
|
|
240
|
+
const rules = [];
|
|
241
|
+
for (const entry of deny) {
|
|
242
|
+
if (typeof entry.id !== "string")
|
|
243
|
+
continue;
|
|
244
|
+
const match = {};
|
|
245
|
+
if (typeof entry.pattern === "string")
|
|
246
|
+
match.pattern = entry.pattern;
|
|
247
|
+
if (typeof entry.regex === "string")
|
|
248
|
+
match.regex = entry.regex;
|
|
249
|
+
if (!match.pattern && !match.regex)
|
|
250
|
+
continue;
|
|
251
|
+
rules.push({
|
|
252
|
+
id: entry.id,
|
|
253
|
+
category: "command",
|
|
254
|
+
match,
|
|
255
|
+
action: "block",
|
|
256
|
+
...typeof entry.description === "string" ? { description: entry.description } : {}
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
return rules;
|
|
260
|
+
}
|
|
261
|
+
function precompilePolicyRuleRegexes(rules) {
|
|
262
|
+
return rules.map((rule) => {
|
|
263
|
+
const compiledRegex = rule.match.regex ? compileSafeRegex(rule.match.regex, `rules.${rule.id}.match.regex`, true) : undefined;
|
|
264
|
+
const compiledUnlessRegex = rule.unless?.regex ? compileSafeRegex(rule.unless.regex, `rules.${rule.id}.unless.regex`, true) : undefined;
|
|
265
|
+
return {
|
|
266
|
+
...rule,
|
|
267
|
+
...compiledRegex ? { compiledRegex } : {},
|
|
268
|
+
...compiledUnlessRegex ? { compiledUnlessRegex } : {}
|
|
269
|
+
};
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
function getRegexUnsafeReason(pattern) {
|
|
273
|
+
if (pattern.length > 512) {
|
|
274
|
+
return "pattern exceeds max safe length (512 chars)";
|
|
275
|
+
}
|
|
276
|
+
if (/\\[1-9]/.test(pattern)) {
|
|
277
|
+
return "pattern uses backreferences";
|
|
278
|
+
}
|
|
279
|
+
if (/\((?:[^()\\]|\\.)*[+*](?:[^()\\]|\\.)*\)\s*[*+{]/.test(pattern)) {
|
|
280
|
+
return "pattern contains nested quantifiers";
|
|
281
|
+
}
|
|
282
|
+
if (/\((?:[^()\\]|\\.)*\.\\?[+*](?:[^()\\]|\\.)*\)\s*[*+{]/.test(pattern)) {
|
|
283
|
+
return "pattern contains nested broad quantifiers";
|
|
284
|
+
}
|
|
285
|
+
return null;
|
|
286
|
+
}
|
|
287
|
+
function compileSafeRegex(pattern, sourceLabel, logOnFailure) {
|
|
288
|
+
const cached = compiledRegexCache.get(pattern);
|
|
289
|
+
if (cached !== undefined) {
|
|
290
|
+
return cached ?? undefined;
|
|
291
|
+
}
|
|
292
|
+
const unsafeReason = getRegexUnsafeReason(pattern);
|
|
293
|
+
if (unsafeReason) {
|
|
294
|
+
if (logOnFailure) {
|
|
295
|
+
console.warn(`[policy] Skipping unsafe regex in ${sourceLabel}: ${unsafeReason}`);
|
|
296
|
+
}
|
|
297
|
+
compiledRegexCache.set(pattern, null);
|
|
298
|
+
return;
|
|
299
|
+
}
|
|
300
|
+
try {
|
|
301
|
+
const compiled = new RegExp(pattern);
|
|
302
|
+
compiledRegexCache.set(pattern, compiled);
|
|
303
|
+
return compiled;
|
|
304
|
+
} catch (error) {
|
|
305
|
+
if (logOnFailure) {
|
|
306
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
307
|
+
console.warn(`[policy] Skipping invalid regex in ${sourceLabel}: ${message}`);
|
|
308
|
+
}
|
|
309
|
+
compiledRegexCache.set(pattern, null);
|
|
310
|
+
return;
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
function matchRule(rule, input) {
|
|
314
|
+
const { match } = rule;
|
|
315
|
+
if (match.pattern && input.includes(match.pattern)) {
|
|
316
|
+
return true;
|
|
317
|
+
}
|
|
318
|
+
if (match.regex) {
|
|
319
|
+
const compiled = rule.compiledRegex || compileSafeRegex(match.regex, `rules.${rule.id}.match.regex`, false);
|
|
320
|
+
if (!compiled) {
|
|
321
|
+
return false;
|
|
322
|
+
}
|
|
323
|
+
try {
|
|
324
|
+
return compiled.test(input);
|
|
325
|
+
} catch {
|
|
326
|
+
return false;
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
return false;
|
|
330
|
+
}
|
|
331
|
+
function matchRuleUnless(rule, command, taskId) {
|
|
332
|
+
if (!rule.unless)
|
|
333
|
+
return false;
|
|
334
|
+
if (rule.unless.regex) {
|
|
335
|
+
const compiled = rule.compiledUnlessRegex || compileSafeRegex(rule.unless.regex, `rules.${rule.id}.unless.regex`, false);
|
|
336
|
+
if (!compiled) {
|
|
337
|
+
return false;
|
|
338
|
+
}
|
|
339
|
+
try {
|
|
340
|
+
if (compiled.test(command))
|
|
341
|
+
return true;
|
|
342
|
+
} catch {}
|
|
343
|
+
}
|
|
344
|
+
if (rule.unless.task_in && taskId) {
|
|
345
|
+
if (rule.unless.task_in.includes(taskId))
|
|
346
|
+
return true;
|
|
347
|
+
}
|
|
348
|
+
return false;
|
|
349
|
+
}
|
|
350
|
+
function resolveAction(mode, matched) {
|
|
351
|
+
if (matched.length === 0)
|
|
352
|
+
return "allow";
|
|
353
|
+
if (mode === "off")
|
|
354
|
+
return "allow";
|
|
355
|
+
if (mode === "observe")
|
|
356
|
+
return "warn";
|
|
357
|
+
return "block";
|
|
358
|
+
}
|
|
359
|
+
function resolveAbsolutePath(projectRoot, rawPath) {
|
|
360
|
+
if (rawPath.startsWith("/"))
|
|
361
|
+
return resolve(rawPath);
|
|
362
|
+
return resolve(projectRoot, rawPath);
|
|
363
|
+
}
|
|
364
|
+
function isHarnessPath(projectRoot, rawPath) {
|
|
365
|
+
const absPath = resolveAbsolutePath(projectRoot, rawPath);
|
|
366
|
+
const managedRoots = [
|
|
367
|
+
resolve(projectRoot, "rig"),
|
|
368
|
+
resolve(projectRoot, ".rig"),
|
|
369
|
+
resolve(projectRoot, "artifacts")
|
|
370
|
+
];
|
|
371
|
+
return managedRoots.some((root) => absPath === root || absPath.startsWith(root + "/"));
|
|
372
|
+
}
|
|
373
|
+
function isRuntimePath(projectRoot, rawPath, taskWorkspace) {
|
|
374
|
+
const absPath = resolveAbsolutePath(projectRoot, rawPath);
|
|
375
|
+
if (taskWorkspace) {
|
|
376
|
+
const workspaceRigRoot = resolve(taskWorkspace, ".rig");
|
|
377
|
+
const workspaceArtifactsRoot = resolve(taskWorkspace, "artifacts");
|
|
378
|
+
if (absPath === workspaceRigRoot || absPath.startsWith(workspaceRigRoot + "/") || absPath === workspaceArtifactsRoot || absPath.startsWith(workspaceArtifactsRoot + "/")) {
|
|
379
|
+
return true;
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
const runtimeRoot = resolve(projectRoot, ".rig/runtime/agents");
|
|
383
|
+
return absPath === runtimeRoot || absPath.startsWith(runtimeRoot + "/");
|
|
384
|
+
}
|
|
385
|
+
function isTestFile(path) {
|
|
386
|
+
return /\.(test|spec)\.(ts|tsx|js|jsx)$/.test(path) || /\/(__tests__|tests|test)\//.test(path);
|
|
387
|
+
}
|
|
388
|
+
function evaluate(context) {
|
|
389
|
+
const policy = loadPolicy(context.projectRoot);
|
|
390
|
+
switch (context.evaluation.type) {
|
|
391
|
+
case "tool-call":
|
|
392
|
+
return evaluateToolCall(policy, context);
|
|
393
|
+
case "command":
|
|
394
|
+
return evaluateCommand(policy, context);
|
|
395
|
+
case "content-write":
|
|
396
|
+
return evaluateContent(policy, context);
|
|
397
|
+
case "file-access":
|
|
398
|
+
return evaluateScope(policy, context, context.evaluation.file_path, context.evaluation.access);
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
function evaluateScope(policy, context, filePath, access) {
|
|
402
|
+
const allowed = () => ({
|
|
403
|
+
allowed: true,
|
|
404
|
+
matchedRules: [],
|
|
405
|
+
action: "allow",
|
|
406
|
+
failClosed: false
|
|
407
|
+
});
|
|
408
|
+
if (policy.scope.harness_paths_exempt && isHarnessPath(context.projectRoot, filePath)) {
|
|
409
|
+
return allowed();
|
|
410
|
+
}
|
|
411
|
+
if (policy.scope.runtime_paths_exempt && isRuntimePath(context.projectRoot, filePath, context.taskWorkspace)) {
|
|
412
|
+
return allowed();
|
|
413
|
+
}
|
|
414
|
+
if (!context.taskId) {
|
|
415
|
+
if (access === "write" && policy.scope.fail_closed) {
|
|
416
|
+
return {
|
|
417
|
+
allowed: false,
|
|
418
|
+
matchedRules: [],
|
|
419
|
+
action: resolveAction(policy.mode, [{ id: "scope:no-task", category: "command", reason: "No active task; fail-closed for write operations" }]),
|
|
420
|
+
failClosed: true
|
|
421
|
+
};
|
|
422
|
+
}
|
|
423
|
+
return allowed();
|
|
424
|
+
}
|
|
425
|
+
const scopes = context.taskScopes || [];
|
|
426
|
+
if (scopes.length === 0) {
|
|
427
|
+
return allowed();
|
|
428
|
+
}
|
|
429
|
+
if (context.taskWorkspace && context.taskWorkspace !== context.projectRoot && filePath.startsWith("/")) {
|
|
430
|
+
const absPath = resolve(filePath);
|
|
431
|
+
if (!absPath.startsWith(context.taskWorkspace + "/") && !isHarnessPath(context.projectRoot, filePath)) {
|
|
432
|
+
const reason2 = `Absolute path '${filePath}' is outside task runtime boundary. Allowed root: ${context.taskWorkspace}`;
|
|
433
|
+
const matched2 = [{ id: "scope:workspace-boundary", category: "command", reason: reason2 }];
|
|
434
|
+
return {
|
|
435
|
+
allowed: policy.mode !== "enforce",
|
|
436
|
+
matchedRules: matched2,
|
|
437
|
+
action: resolveAction(policy.mode, matched2),
|
|
438
|
+
failClosed: false
|
|
439
|
+
};
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
const monorepoRoot = context.monorepoRoot || process.env.MONOREPO_ROOT?.trim() || context.taskWorkspace || context.projectRoot;
|
|
443
|
+
let normalizedPath = filePath;
|
|
444
|
+
if (context.taskWorkspace && context.taskWorkspace !== context.projectRoot && filePath.startsWith(context.taskWorkspace + "/")) {
|
|
445
|
+
normalizedPath = filePath.slice(context.taskWorkspace.length + 1);
|
|
446
|
+
}
|
|
447
|
+
normalizedPath = normalizePathToScope(context.projectRoot, monorepoRoot, normalizedPath);
|
|
448
|
+
if (scopeMatches(filePath, scopes) || scopeMatches(normalizedPath, scopes)) {
|
|
449
|
+
return allowed();
|
|
450
|
+
}
|
|
451
|
+
const reason = `File '${filePath}' (normalized: '${normalizedPath}') is outside scope of task ${context.taskId}`;
|
|
452
|
+
const matched = [{ id: "scope:out-of-scope", category: "command", reason }];
|
|
453
|
+
return {
|
|
454
|
+
allowed: policy.mode !== "enforce",
|
|
455
|
+
matchedRules: matched,
|
|
456
|
+
action: resolveAction(policy.mode, matched),
|
|
457
|
+
failClosed: false
|
|
458
|
+
};
|
|
459
|
+
}
|
|
460
|
+
function evaluateCommand(policy, context) {
|
|
461
|
+
const evaluation = context.evaluation;
|
|
462
|
+
if (evaluation.type !== "command") {
|
|
463
|
+
return { allowed: true, matchedRules: [], action: "allow", failClosed: false };
|
|
464
|
+
}
|
|
465
|
+
const command = evaluation.command;
|
|
466
|
+
const matchedRules = [];
|
|
467
|
+
for (const rule of policy.rules) {
|
|
468
|
+
if (rule.category !== "command")
|
|
469
|
+
continue;
|
|
470
|
+
if (!matchRule(rule, command))
|
|
471
|
+
continue;
|
|
472
|
+
if (matchRuleUnless(rule, command, context.taskId))
|
|
473
|
+
continue;
|
|
474
|
+
matchedRules.push({
|
|
475
|
+
id: rule.id,
|
|
476
|
+
category: rule.category,
|
|
477
|
+
...rule.description !== undefined ? { description: rule.description } : {},
|
|
478
|
+
reason: rule.description || `Matched rule ${rule.id}`
|
|
479
|
+
});
|
|
480
|
+
}
|
|
481
|
+
const writeTarget = extractWriteTarget(command);
|
|
482
|
+
if (writeTarget && !/^\/dev\//.test(writeTarget) && !/^\/proc\//.test(writeTarget)) {
|
|
483
|
+
const scopeResult = evaluateScope(policy, context, writeTarget, "write");
|
|
484
|
+
if (!scopeResult.allowed || scopeResult.matchedRules.length > 0) {
|
|
485
|
+
matchedRules.push(...scopeResult.matchedRules);
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
const action = resolveAction(policy.mode, matchedRules);
|
|
489
|
+
return {
|
|
490
|
+
allowed: action !== "block",
|
|
491
|
+
matchedRules,
|
|
492
|
+
action,
|
|
493
|
+
failClosed: false
|
|
494
|
+
};
|
|
495
|
+
}
|
|
496
|
+
function extractWriteTarget(command) {
|
|
497
|
+
const redirect = command.match(/>>?\s+([^\s;|&]+)/);
|
|
498
|
+
if (redirect?.[1])
|
|
499
|
+
return redirect[1];
|
|
500
|
+
const tee = command.match(/tee\s+(-a\s+)?([^\s;|&]+)/);
|
|
501
|
+
if (tee?.[2])
|
|
502
|
+
return tee[2];
|
|
503
|
+
return "";
|
|
504
|
+
}
|
|
505
|
+
function evaluateContent(policy, context) {
|
|
506
|
+
const evaluation = context.evaluation;
|
|
507
|
+
if (evaluation.type !== "content-write") {
|
|
508
|
+
return { allowed: true, matchedRules: [], action: "allow", failClosed: false };
|
|
509
|
+
}
|
|
510
|
+
const { content, file_path } = evaluation;
|
|
511
|
+
const matchedRules = [];
|
|
512
|
+
const scopeResult = evaluateScope(policy, context, file_path, "write");
|
|
513
|
+
if (scopeResult.matchedRules.length > 0) {
|
|
514
|
+
matchedRules.push(...scopeResult.matchedRules);
|
|
515
|
+
}
|
|
516
|
+
for (const rule of policy.rules) {
|
|
517
|
+
if (rule.category !== "content" && rule.category !== "import" && rule.category !== "test-integrity")
|
|
518
|
+
continue;
|
|
519
|
+
if (rule.applies_to === "test-files" && !isTestFile(file_path))
|
|
520
|
+
continue;
|
|
521
|
+
if (!matchRule(rule, content))
|
|
522
|
+
continue;
|
|
523
|
+
if (matchRuleUnless(rule, content, context.taskId))
|
|
524
|
+
continue;
|
|
525
|
+
matchedRules.push({
|
|
526
|
+
id: rule.id,
|
|
527
|
+
category: rule.category,
|
|
528
|
+
...rule.description !== undefined ? { description: rule.description } : {},
|
|
529
|
+
reason: rule.description || `Matched rule ${rule.id}`
|
|
530
|
+
});
|
|
531
|
+
}
|
|
532
|
+
const action = resolveAction(policy.mode, matchedRules);
|
|
533
|
+
return {
|
|
534
|
+
allowed: action !== "block",
|
|
535
|
+
matchedRules,
|
|
536
|
+
action,
|
|
537
|
+
failClosed: false
|
|
538
|
+
};
|
|
539
|
+
}
|
|
540
|
+
function evaluateToolCall(policy, context) {
|
|
541
|
+
const evaluation = context.evaluation;
|
|
542
|
+
if (evaluation.type !== "tool-call") {
|
|
543
|
+
return { allowed: true, matchedRules: [], action: "allow", failClosed: false };
|
|
544
|
+
}
|
|
545
|
+
const { tool_name, tool_input } = evaluation;
|
|
546
|
+
const allMatched = [];
|
|
547
|
+
const filePaths = extractFilePathsFromToolInput(tool_name, tool_input);
|
|
548
|
+
for (const fp of filePaths) {
|
|
549
|
+
const access = isWriteTool(tool_name) ? "write" : "read";
|
|
550
|
+
const scopeResult = evaluateScope(policy, context, fp, access);
|
|
551
|
+
if (scopeResult.matchedRules.length > 0) {
|
|
552
|
+
allMatched.push(...scopeResult.matchedRules);
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
const content = extractContentFromToolInput(tool_input);
|
|
556
|
+
if (content) {
|
|
557
|
+
const filePath = filePaths[0] || "";
|
|
558
|
+
const contentContext = {
|
|
559
|
+
...context,
|
|
560
|
+
evaluation: { type: "content-write", file_path: filePath, content }
|
|
561
|
+
};
|
|
562
|
+
const contentPolicy = loadPolicy(context.projectRoot);
|
|
563
|
+
for (const rule of contentPolicy.rules) {
|
|
564
|
+
if (rule.category !== "content" && rule.category !== "import" && rule.category !== "test-integrity")
|
|
565
|
+
continue;
|
|
566
|
+
if (rule.applies_to === "test-files" && !isTestFile(filePath))
|
|
567
|
+
continue;
|
|
568
|
+
if (!matchRule(rule, content))
|
|
569
|
+
continue;
|
|
570
|
+
if (matchRuleUnless(rule, content, context.taskId))
|
|
571
|
+
continue;
|
|
572
|
+
allMatched.push({
|
|
573
|
+
id: rule.id,
|
|
574
|
+
category: rule.category,
|
|
575
|
+
...rule.description !== undefined ? { description: rule.description } : {},
|
|
576
|
+
reason: rule.description || `Matched rule ${rule.id}`
|
|
577
|
+
});
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
if (tool_name === "Bash") {
|
|
581
|
+
const command = String(tool_input.command || tool_input.cmd || "");
|
|
582
|
+
if (command) {
|
|
583
|
+
const cmdContext = {
|
|
584
|
+
...context,
|
|
585
|
+
evaluation: { type: "command", command }
|
|
586
|
+
};
|
|
587
|
+
const cmdResult = evaluateCommand(policy, cmdContext);
|
|
588
|
+
if (cmdResult.matchedRules.length > 0) {
|
|
589
|
+
allMatched.push(...cmdResult.matchedRules);
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
const seen = new Set;
|
|
594
|
+
const deduplicated = [];
|
|
595
|
+
for (const rule of allMatched) {
|
|
596
|
+
if (!seen.has(rule.id)) {
|
|
597
|
+
seen.add(rule.id);
|
|
598
|
+
deduplicated.push(rule);
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
const action = resolveAction(policy.mode, deduplicated);
|
|
602
|
+
return {
|
|
603
|
+
allowed: action !== "block",
|
|
604
|
+
matchedRules: deduplicated,
|
|
605
|
+
action,
|
|
606
|
+
failClosed: false
|
|
607
|
+
};
|
|
608
|
+
}
|
|
609
|
+
function isWriteTool(toolName) {
|
|
610
|
+
return toolName === "Write" || toolName === "Edit" || toolName === "MultiEdit";
|
|
611
|
+
}
|
|
612
|
+
function extractFilePathsFromToolInput(toolName, input) {
|
|
613
|
+
const paths = [];
|
|
614
|
+
const add = (value) => {
|
|
615
|
+
if (typeof value === "string" && value.trim()) {
|
|
616
|
+
paths.push(value.trim());
|
|
617
|
+
}
|
|
618
|
+
};
|
|
619
|
+
if (toolName === "Read" || toolName === "Write" || toolName === "Edit" || toolName === "MultiEdit") {
|
|
620
|
+
add(input.file_path);
|
|
621
|
+
add(input.path);
|
|
622
|
+
} else if (toolName === "Glob") {
|
|
623
|
+
add(input.path);
|
|
624
|
+
} else if (toolName === "Grep") {
|
|
625
|
+
add(input.path);
|
|
626
|
+
} else {
|
|
627
|
+
add(input.file_path);
|
|
628
|
+
add(input.path);
|
|
629
|
+
}
|
|
630
|
+
return paths;
|
|
631
|
+
}
|
|
632
|
+
function extractContentFromToolInput(input) {
|
|
633
|
+
if (typeof input.content === "string")
|
|
634
|
+
return input.content;
|
|
635
|
+
if (typeof input.new_string === "string")
|
|
636
|
+
return input.new_string;
|
|
637
|
+
return "";
|
|
638
|
+
}
|
|
639
|
+
var guardHotPathPrimed = false;
|
|
640
|
+
function primeGuardHotPaths() {
|
|
641
|
+
if (guardHotPathPrimed) {
|
|
642
|
+
return;
|
|
643
|
+
}
|
|
644
|
+
guardHotPathPrimed = true;
|
|
645
|
+
try {
|
|
646
|
+
optimizeNextInvocation(matchRule);
|
|
647
|
+
optimizeNextInvocation(evaluate);
|
|
648
|
+
} catch {}
|
|
649
|
+
}
|
|
650
|
+
primeGuardHotPaths();
|
|
651
|
+
|
|
652
|
+
// packages/cli-surface-plugin/src/control-plane/agent-binary-build.ts
|
|
653
|
+
import { runtimeProvisioningEnv } from "@rig/core/runtime-provisioning-env";
|
|
654
|
+
|
|
655
|
+
// packages/cli-surface-plugin/src/runner.ts
|
|
11
656
|
class CliError extends RuntimeCliError {
|
|
12
|
-
hint;
|
|
13
657
|
constructor(message, exitCode = 1, options = {}) {
|
|
14
|
-
super(message, exitCode);
|
|
15
|
-
if (options.hint?.trim()) {
|
|
16
|
-
this.hint = options.hint.trim();
|
|
17
|
-
}
|
|
658
|
+
super(message, exitCode, options);
|
|
18
659
|
}
|
|
19
660
|
}
|
|
20
661
|
function takeOption(args, option) {
|
|
@@ -46,7 +687,6 @@ Usage: ${usage}`);
|
|
|
46
687
|
|
|
47
688
|
// packages/cli-surface-plugin/src/commands/_cli-format.ts
|
|
48
689
|
import pc from "picocolors";
|
|
49
|
-
import { runStatusColorRole, runStatusText, statusColorRole } from "@rig/run-worker/runs";
|
|
50
690
|
var dim = pc.dim;
|
|
51
691
|
var faintBar = pc.dim("\u2502");
|
|
52
692
|
var accent = pc.cyan;
|
|
@@ -69,13 +709,646 @@ function formatStatsTable(rows) {
|
|
|
69
709
|
|
|
70
710
|
// packages/cli-surface-plugin/src/commands/_help-catalog.ts
|
|
71
711
|
import pc2 from "picocolors";
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
712
|
+
|
|
713
|
+
// packages/cli-surface-plugin/src/help-catalog-data.ts
|
|
714
|
+
var TOP_LEVEL_SECTIONS = [
|
|
715
|
+
{
|
|
716
|
+
title: "Open Rig",
|
|
717
|
+
subtitle: "the cockpit \u2014 bare rig opens the Rig Cockpit inside an OMP collab session",
|
|
718
|
+
commands: [
|
|
719
|
+
{
|
|
720
|
+
command: "rig",
|
|
721
|
+
description: "Open the Rig Cockpit (OMP collaboration substrate) for the current workspace.",
|
|
722
|
+
usecase: "Day-to-day entry point: drive everything (tasks, runs, inbox) from the board.",
|
|
723
|
+
examples: ["cd my-project && rig", "rig # in a repo with rig.config.ts"]
|
|
724
|
+
},
|
|
725
|
+
{
|
|
726
|
+
command: "rig --workspace <path>",
|
|
727
|
+
description: "Open the cockpit for another workspace instead of the current dir.",
|
|
728
|
+
usecase: "Operate a project without cd-ing into it.",
|
|
729
|
+
examples: ["rig --workspace ~/work/humanwork", "rig --workspace ../other-repo"]
|
|
730
|
+
},
|
|
731
|
+
{
|
|
732
|
+
command: "rig join <link>",
|
|
733
|
+
description: "Join an encrypted OMP collaborative session from another operator.",
|
|
734
|
+
usecase: "Pair on a teammate's live run from the join link they shared.",
|
|
735
|
+
examples: ["rig join where.rig-does.work/r/AbC123\u2026"]
|
|
736
|
+
},
|
|
737
|
+
{ command: "/rig", description: "From inside an OMP session, (re)open the Rig Cockpit screen.", usecase: "Jump back to the board after dropping into the raw agent session." },
|
|
738
|
+
{ command: "rig --version", description: "Print the installed Rig CLI version.", examples: ["rig --version"] }
|
|
739
|
+
]
|
|
740
|
+
},
|
|
741
|
+
{
|
|
742
|
+
title: "Runs \u2014 dispatch & control task runs",
|
|
743
|
+
subtitle: "every run is an isolated, collaborative OMP session on the selected target",
|
|
744
|
+
commands: [
|
|
745
|
+
{
|
|
746
|
+
command: "rig run [start] <task|#issue|--next>",
|
|
747
|
+
description: "Dispatch a run for a task (refuses if one is already active; --force overrides).",
|
|
748
|
+
usecase: "Kick off work on a specific issue, or let Rig pick the next ready one.",
|
|
749
|
+
examples: [
|
|
750
|
+
"rig run 204 # by task/issue id",
|
|
751
|
+
"rig run --next # next ready task by deps/priority",
|
|
752
|
+
"rig run --title 'Fix API' 204 # title override before the task ref",
|
|
753
|
+
"rig run start 204 --force # dispatch even if a run is already active",
|
|
754
|
+
"rig run start 204 --model opus-4.8 --prompt 'focus tests'"
|
|
755
|
+
]
|
|
756
|
+
},
|
|
757
|
+
{
|
|
758
|
+
command: "rig run start-parallel [--limit n]",
|
|
759
|
+
description: "Dispatch all ready tasks concurrently up to the limit.",
|
|
760
|
+
usecase: "Burn down a backlog of independent tasks at once.",
|
|
761
|
+
examples: ["rig run start-parallel", "rig run start-parallel --limit 3"]
|
|
762
|
+
},
|
|
763
|
+
{
|
|
764
|
+
command: "rig run start-serial",
|
|
765
|
+
description: "Dispatch the next ready task; re-run to continue the serial queue.",
|
|
766
|
+
usecase: "Work a queue one-at-a-time (e.g. dependent tasks, limited capacity).",
|
|
767
|
+
examples: ["rig run start-serial"]
|
|
768
|
+
},
|
|
769
|
+
{
|
|
770
|
+
command: "rig run list",
|
|
771
|
+
description: "List every discoverable run (live registry + local) with status and links.",
|
|
772
|
+
usecase: "See what's running anywhere (local + remote) and grab ids/join links.",
|
|
773
|
+
examples: ["rig run list", "rig run list | grep running"]
|
|
774
|
+
},
|
|
775
|
+
{ command: "rig run status", description: "Active vs recent runs at a glance.", examples: ["rig run status"] },
|
|
776
|
+
{
|
|
777
|
+
command: "rig run show <id>",
|
|
778
|
+
description: "Run card: status, task, PR, join link, pending approvals/inputs, error summary.",
|
|
779
|
+
usecase: "Get the full picture of one run before attaching or steering.",
|
|
780
|
+
examples: ["rig run show 019ee11f", "rig run show 019ee11f # copy the join link"]
|
|
781
|
+
},
|
|
782
|
+
{
|
|
783
|
+
command: "rig run attach <id>",
|
|
784
|
+
description: "Attach to a run's live OMP collab session (write access).",
|
|
785
|
+
usecase: "Watch/drive a run interactively \u2014 type to the agent, see its work live.",
|
|
786
|
+
examples: ["rig run attach 019ee11f"]
|
|
787
|
+
},
|
|
788
|
+
{
|
|
789
|
+
command: "rig run steer <id> --message <text>",
|
|
790
|
+
description: "Send a steering message into a running session (remote routes to its host).",
|
|
791
|
+
usecase: "Course-correct an autonomous run without attaching.",
|
|
792
|
+
examples: [
|
|
793
|
+
"rig run steer 019ee11f --message 'focus on the API first'",
|
|
794
|
+
"rig run steer 019ee11f --message 'stop and open the PR now'"
|
|
795
|
+
]
|
|
796
|
+
},
|
|
797
|
+
{
|
|
798
|
+
command: "rig run stop <id> [--reason <text>]",
|
|
799
|
+
description: "Request a graceful stop of a run (terminal).",
|
|
800
|
+
usecase: "Halt a run that's off-track or no longer needed.",
|
|
801
|
+
examples: ["rig run stop 019ee11f", "rig run stop 019ee11f --reason 'superseded by #210'"]
|
|
802
|
+
},
|
|
803
|
+
{
|
|
804
|
+
command: "rig run pause <id>",
|
|
805
|
+
description: "Park a live run (running \u2192 paused) without finalizing; the session stays attachable.",
|
|
806
|
+
usecase: "Hold an autonomous run mid-flight \u2014 free the agent without losing its place.",
|
|
807
|
+
examples: ["rig run pause 019ee11f"]
|
|
808
|
+
},
|
|
809
|
+
{
|
|
810
|
+
command: "rig run resume <id>",
|
|
811
|
+
description: "Resume a paused run (paused \u2192 running); the agent continues. A dead/stale run is re-dispatched fresh instead.",
|
|
812
|
+
usecase: "Un-pause a parked run, or retry a finished one.",
|
|
813
|
+
examples: ["rig run resume 019ee11f"]
|
|
814
|
+
},
|
|
815
|
+
{
|
|
816
|
+
command: "rig run restart <id>",
|
|
817
|
+
description: "Re-dispatch a task as a fresh run (new runId, clean runtime).",
|
|
818
|
+
usecase: "Retry a failed/stopped run from a clean slate.",
|
|
819
|
+
examples: ["rig run restart 019ee11f"]
|
|
820
|
+
},
|
|
821
|
+
{
|
|
822
|
+
command: "rig run timeline|replay <id>",
|
|
823
|
+
description: "Inspect a run's folded timeline / replay its journal.",
|
|
824
|
+
usecase: "Audit what an agent did, step by step, after the fact.",
|
|
825
|
+
examples: ["rig run timeline 019ee11f", "rig run replay 019ee11f"]
|
|
826
|
+
},
|
|
827
|
+
{ command: "rig run cleanup", description: "Prune dead/stale run state.", usecase: "Clear out finished/orphaned run entries cluttering the board.", examples: ["rig run cleanup"] }
|
|
828
|
+
]
|
|
829
|
+
},
|
|
830
|
+
{
|
|
831
|
+
title: "Tasks \u2014 the configured task source",
|
|
832
|
+
subtitle: "github-issues / files task sources feed dispatch",
|
|
833
|
+
commands: [
|
|
834
|
+
{
|
|
835
|
+
command: "rig task list [--search <t>] [--state <open|closed>]",
|
|
836
|
+
description: "List tasks from the configured source, with filters.",
|
|
837
|
+
usecase: "Find what's available to dispatch; filter by text or lifecycle status.",
|
|
838
|
+
examples: [
|
|
839
|
+
"rig task list",
|
|
840
|
+
"rig task list --state open",
|
|
841
|
+
"rig task list --search 'auth'"
|
|
842
|
+
]
|
|
843
|
+
},
|
|
844
|
+
{ command: "rig task next", description: "Show the next ready task by dependency/priority.", usecase: "Decide what to run next without scanning the whole list.", examples: ["rig task next"] },
|
|
845
|
+
{
|
|
846
|
+
command: "rig task show|info <id>",
|
|
847
|
+
description: "Task detail: title, body, status, labels, scope, deps, URL.",
|
|
848
|
+
usecase: "Read the full issue before dispatching a run for it.",
|
|
849
|
+
examples: ["rig task show 204", "rig task info 204"]
|
|
850
|
+
},
|
|
851
|
+
{
|
|
852
|
+
command: "rig task scope|deps --task <id>; rig task status",
|
|
853
|
+
description: "Inspect a task's scope globs/dependencies, or show project task status.",
|
|
854
|
+
usecase: "Check what files a run may touch / what's blocking it.",
|
|
855
|
+
examples: ["rig task scope --task 204", "rig task deps --task 204", "rig task status"]
|
|
856
|
+
},
|
|
857
|
+
{ command: "rig task lookup <term>", description: "Find a task by id/title substring.", examples: ["rig task lookup revoke-invite"] },
|
|
858
|
+
{ command: "rig task record \u2026", description: "Write task state/metadata back to the source.", usecase: "Programmatically update task lifecycle from scripts/CI." },
|
|
859
|
+
{ command: "rig task artifacts <id>", description: "List/inspect a task's run artifacts.", examples: ["rig task artifacts 204"] },
|
|
860
|
+
{ command: "rig triage", description: "Run the configured issueAnalysis pass once (schedule via cron/CI for continuous).", usecase: "Auto-classify/label/scope new issues in a batch.", examples: ["rig triage"] }
|
|
861
|
+
]
|
|
862
|
+
},
|
|
863
|
+
{
|
|
864
|
+
title: "Planning, graph & supervisor",
|
|
865
|
+
subtitle: "dependency graph, blocker classification, rollups, planning, drift, and autonomous loop control",
|
|
866
|
+
commands: [
|
|
867
|
+
{ command: "rig pipeline show [--json]", description: "Show the resolved default lifecycle pipeline.", examples: ["rig pipeline show", "rig pipeline show --json"] },
|
|
868
|
+
{ command: "rig graph [--json|--dot]", description: "Render the workspace dependency graph from the configured task source.", examples: ["rig graph --json", "rig graph --dot"] },
|
|
869
|
+
{ command: "rig blockers [--json]", description: "Classify task, human, approval, and external-input blockers.", examples: ["rig blockers"] },
|
|
870
|
+
{ command: "rig status [--json]", description: "Show graph/run/blocker workspace status at a glance.", examples: ["rig status"] },
|
|
871
|
+
{ command: "rig summary [--json]", description: "Roll up progress by epic and assignee.", examples: ["rig summary"] },
|
|
872
|
+
{ command: "rig loop [--task <id>] [--max-tasks <n>] [--concurrency <n>]", description: "Run the autonomous supervisor loop over ready tasks, optionally restricted to one task.", examples: ["rig loop --task 106 --max-tasks 1", "rig loop --max-tasks 3 --concurrency 2"] },
|
|
873
|
+
{ command: "rig unblock [task-id]", description: "Pick and optionally dispatch the highest-unblock task or blockers for one task.", examples: ["rig unblock --dry-run", "rig unblock 204 --dry-run"] },
|
|
874
|
+
{ command: "rig plan --text <prd>|--prd <file>|--issue <id>", description: "Generate and optionally materialize a task plan.", examples: ["rig plan --issue 20 --json", "rig plan --prd docs/product/prd.md"] },
|
|
875
|
+
{ command: "rig drift [--docs <csv>]", description: "Scan documentation for stale source references.", examples: ["rig drift", "rig drift --docs docs/**"] }
|
|
876
|
+
]
|
|
877
|
+
},
|
|
878
|
+
{
|
|
879
|
+
title: "Config \u2014 everything through rig.config.ts",
|
|
880
|
+
subtitle: "resolution: ambient env \u2192 rig.config.ts \u2192 computed default",
|
|
881
|
+
commands: [
|
|
882
|
+
{
|
|
883
|
+
command: "rig config get [<key>]",
|
|
884
|
+
description: "Effective value(s) + which layer won (env / rig.config.ts / default).",
|
|
885
|
+
usecase: "Debug why a value is what it is \u2014 see the winning layer.",
|
|
886
|
+
examples: [
|
|
887
|
+
"rig config get # all effective values + sources",
|
|
888
|
+
"rig config get sshTarget # one key + winning layer",
|
|
889
|
+
"rig config get relayUrl"
|
|
890
|
+
]
|
|
891
|
+
},
|
|
892
|
+
{
|
|
893
|
+
command: "rig config set <key> <value>",
|
|
894
|
+
description: "Write an override (relayUrl/registryUrl/sshTarget or any RIG_*) into rig.config.ts.",
|
|
895
|
+
usecase: "Persist a setting so it survives across runs without env vars.",
|
|
896
|
+
examples: [
|
|
897
|
+
"rig config set sshTarget ubuntu@host # remote placement",
|
|
898
|
+
"rig config set relayUrl wss://my-relay",
|
|
899
|
+
"rig config set RIG_ANYTHING value # any RIG_* knob"
|
|
900
|
+
]
|
|
901
|
+
},
|
|
902
|
+
{
|
|
903
|
+
command: "rig init",
|
|
904
|
+
description: "Create rig.config.ts (project, task source, placement/sshTarget) interactively.",
|
|
905
|
+
usecase: "First-time setup of a repo for Rig.",
|
|
906
|
+
examples: ["rig init"]
|
|
907
|
+
},
|
|
908
|
+
{
|
|
909
|
+
command: "runtime.server in rig.config.ts",
|
|
910
|
+
description: "Backbone (relay/registry/secret) + remote placement (sshTarget); defaults under the hood.",
|
|
911
|
+
usecase: "Pin a project's relay/registry and remote host in code.",
|
|
912
|
+
examples: [
|
|
913
|
+
"runtime: { server: { sshTarget: 'ubuntu@host' } } // remote placement",
|
|
914
|
+
"runtime: { server: { relayUrl: 'wss://\u2026', registryUrl: 'https://\u2026/registry' } }"
|
|
915
|
+
]
|
|
916
|
+
}
|
|
917
|
+
]
|
|
918
|
+
},
|
|
919
|
+
{
|
|
920
|
+
title: "Placement & target \u2014 local vs remote execution",
|
|
921
|
+
subtitle: "where runs execute; the backbone relay/registry is shared",
|
|
922
|
+
commands: [
|
|
923
|
+
{ command: "rig server status", description: "Show the selected placement (local/remote) and task source.", examples: ["rig server status"] },
|
|
924
|
+
{ command: "rig server list", description: "List configured server targets.", examples: ["rig server list"] },
|
|
925
|
+
{
|
|
926
|
+
command: "rig server use <local|alias>",
|
|
927
|
+
description: "Select a server target (execution placement).",
|
|
928
|
+
usecase: "Switch a repo between local and a remote host for run execution.",
|
|
929
|
+
examples: ["rig server use local", "rig server use prod-box"]
|
|
930
|
+
},
|
|
931
|
+
{
|
|
932
|
+
command: "rig server add --alias <alias> --host <host> [--port <n>] | remove <alias>",
|
|
933
|
+
description: "Configure or remove a remote server target.",
|
|
934
|
+
examples: ["rig server add --alias prod-box --host ubuntu@host", "rig server remove prod-box"]
|
|
935
|
+
},
|
|
936
|
+
{
|
|
937
|
+
command: "rig remote <list|add|test|status|\u2026>",
|
|
938
|
+
description: "Lower-level remote endpoint management + run control over a remote.",
|
|
939
|
+
examples: ["rig remote list", "rig remote test prod-box", "rig remote status"]
|
|
940
|
+
}
|
|
941
|
+
]
|
|
942
|
+
},
|
|
943
|
+
{
|
|
944
|
+
title: "Inbox & Doctor \u2014 approvals and health",
|
|
945
|
+
subtitle: "answer pending workflow entries; probe setup",
|
|
946
|
+
commands: [
|
|
947
|
+
{
|
|
948
|
+
command: "rig inbox approvals|inputs",
|
|
949
|
+
description: "List pending approval / user-input workflow entries.",
|
|
950
|
+
usecase: "See what a run is blocked on waiting for you.",
|
|
951
|
+
examples: ["rig inbox approvals", "rig inbox inputs"]
|
|
952
|
+
},
|
|
953
|
+
{
|
|
954
|
+
command: "rig inbox approve --run <id> --request <id> --decision approve|reject | respond --run <id> --request <id> --text <answer>",
|
|
955
|
+
description: "Attempt to resolve an approval or answer a user-input prompt; attach if one-shot delivery is unavailable.",
|
|
956
|
+
usecase: "Resolve pending requests from automation when the live run accepts out-of-band resolution.",
|
|
957
|
+
examples: ["rig inbox approve --run run1 --request abc123 --decision approve", "rig inbox respond --run run1 --request abc123 --text 'use option B'"]
|
|
958
|
+
},
|
|
959
|
+
{ command: "rig inbox watch", description: "Stream inbox changes live.", examples: ["rig inbox watch"] },
|
|
960
|
+
{ command: "rig doctor", description: "Cheap health checks: session discovery, registry, selected target, workflow entries.", usecase: "First thing to run when something seems off.", examples: ["rig doctor"] }
|
|
961
|
+
]
|
|
962
|
+
},
|
|
963
|
+
{
|
|
964
|
+
title: "Inspect & stats \u2014 observability",
|
|
965
|
+
subtitle: "logs, artifacts, diffs, failure analysis",
|
|
966
|
+
commands: [
|
|
967
|
+
{
|
|
968
|
+
command: "rig inspect run-logs --run <id> | logs --task <id>",
|
|
969
|
+
description: "Print run/session log lines.",
|
|
970
|
+
usecase: "Debug why a run failed or stalled.",
|
|
971
|
+
examples: ["rig inspect run-logs --run 019ee11f", "rig inspect logs --task 204"]
|
|
972
|
+
},
|
|
973
|
+
{ command: "rig inspect runs", description: "List runs from on-disk runtime state.", examples: ["rig inspect runs"] },
|
|
974
|
+
{ command: "rig inspect artifact --task <id> --file <name> | artifacts --task <id>", description: "Inspect a task/run's artifacts.", examples: ["rig inspect artifacts --task 204", "rig inspect artifact --task 204 --file task-result.json"] },
|
|
975
|
+
{ command: "rig inspect diff --task <id> | graph [--task <id>]", description: "Run diff / task dependency graph.", examples: ["rig inspect diff --task 204", "rig inspect graph --task 204"] },
|
|
976
|
+
{ command: "rig inspect failures --task <id>", description: "Classified failure diagnostics for a task's runs.", usecase: "Triage repeated failures on one task.", examples: ["rig inspect failures --task 204"] },
|
|
977
|
+
{ command: "rig stats", description: "Aggregate run stats over a window.", examples: ["rig stats", "rig stats --since 7d"] }
|
|
978
|
+
]
|
|
979
|
+
},
|
|
980
|
+
{
|
|
981
|
+
title: "Setup & integrations",
|
|
982
|
+
subtitle: "initialize, authenticate, and wire the project",
|
|
983
|
+
commands: [
|
|
984
|
+
{ command: "rig init", description: "Set up a new repo: rig.config.ts, task source, placement, state.", examples: ["rig init"] },
|
|
985
|
+
{ command: "rig setup", description: "Run/repair the full setup wizard (repo, placement, GitHub auth, labels, verify).", usecase: "Re-run when auth/labels/placement drift or after onboarding.", examples: ["rig setup"] },
|
|
986
|
+
{
|
|
987
|
+
command: "rig github status|token|import-gh",
|
|
988
|
+
description: "GitHub auth status, token management, issue import.",
|
|
989
|
+
examples: ["rig github status", "rig github import-gh"]
|
|
990
|
+
},
|
|
991
|
+
{ command: "rig repo|git \u2026", description: "Repo/source helpers (clone, credentials, git ops).", examples: ["rig repo status", "rig git \u2026"] },
|
|
992
|
+
{ command: "rig review", description: "Inspect or change the completion-review (Greptile) gate policy.", examples: ["rig review"] }
|
|
993
|
+
]
|
|
994
|
+
},
|
|
995
|
+
{
|
|
996
|
+
title: "Extend & build",
|
|
997
|
+
subtitle: "plugins, OMP/Pi packages, binaries, workspaces",
|
|
998
|
+
commands: [
|
|
999
|
+
{ command: "rig plugin list|validate|run", description: "Inspect and exercise plugin-contributed channels.", examples: ["rig plugin list", "rig plugin validate", "rig plugin run <name>"] },
|
|
1000
|
+
{ command: "rig pi list|add|remove|search", description: "Manage OMP/Pi extension packages for sessions/workers.", examples: ["rig pi list", "rig pi add <pkg>", "rig pi search <term>"] },
|
|
1001
|
+
{
|
|
1002
|
+
command: "rig dist build|install",
|
|
1003
|
+
description: "Build/install the self-contained rig binary distribution.",
|
|
1004
|
+
usecase: "Produce/refresh the single-file rig binary.",
|
|
1005
|
+
examples: ["rig dist build", "rig dist install"]
|
|
1006
|
+
},
|
|
1007
|
+
{ command: "rig workspace summary|topology", description: "Multi-root workspace inspection.", examples: ["rig workspace summary", "rig workspace topology"] },
|
|
1008
|
+
{ command: "rig.config.ts plugins / runtime.pi.packages", description: "Declare task sources, validators, hooks, skills, roles + team OMP/Pi packages.", examples: ["plugins: [...standardPlugins()]", "runtime: { pi: { packages: ['@me/my-ext'] } }"] }
|
|
1009
|
+
]
|
|
1010
|
+
}
|
|
1011
|
+
];
|
|
1012
|
+
var PRIMARY_GROUPS = [
|
|
1013
|
+
{
|
|
1014
|
+
name: "pipeline",
|
|
1015
|
+
summary: "Default lifecycle pipeline inspection.",
|
|
1016
|
+
usage: ["rig pipeline show [--json]"],
|
|
1017
|
+
commands: [{ command: "show [--json]", description: "Show resolved default lifecycle stages, mutation annotations, dropped anchors, and cycles.", primary: true }],
|
|
1018
|
+
examples: ["rig pipeline show", "rig pipeline show --json"]
|
|
1019
|
+
},
|
|
1020
|
+
{
|
|
1021
|
+
name: "graph",
|
|
1022
|
+
summary: "Workspace dependency graph.",
|
|
1023
|
+
usage: ["rig graph [--json|--dot]"],
|
|
1024
|
+
commands: [{ command: "[--json|--dot]", description: "Build the workspace dependency graph and print summary, JSON, or DOT.", primary: true }],
|
|
1025
|
+
examples: ["rig graph", "rig graph --json", "rig graph --dot"]
|
|
1026
|
+
},
|
|
1027
|
+
{
|
|
1028
|
+
name: "blockers",
|
|
1029
|
+
summary: "Workspace blocker classification.",
|
|
1030
|
+
usage: ["rig blockers [--json]"],
|
|
1031
|
+
commands: [{ command: "[--json]", description: "Classify machine, human, approval, and external-input blockers.", primary: true }],
|
|
1032
|
+
examples: ["rig blockers", "rig blockers --json"]
|
|
1033
|
+
},
|
|
1034
|
+
{
|
|
1035
|
+
name: "status",
|
|
1036
|
+
summary: "Workspace graph/run status.",
|
|
1037
|
+
usage: ["rig status [--json]"],
|
|
1038
|
+
commands: [{ command: "[--json]", description: "Show active runs, attention counts, rollup counts, and blocker counts.", primary: true }],
|
|
1039
|
+
examples: ["rig status"]
|
|
1040
|
+
},
|
|
1041
|
+
{
|
|
1042
|
+
name: "summary",
|
|
1043
|
+
summary: "Workspace progress rollups.",
|
|
1044
|
+
usage: ["rig summary [--json]"],
|
|
1045
|
+
commands: [{ command: "[--json]", description: "Roll up progress by epic and assignee.", primary: true }],
|
|
1046
|
+
examples: ["rig summary", "rig summary --json"]
|
|
1047
|
+
},
|
|
1048
|
+
{
|
|
1049
|
+
name: "loop",
|
|
1050
|
+
summary: "Autonomous supervisor loop.",
|
|
1051
|
+
usage: ["rig loop [--task <id>] [--max-tasks <n>] [--concurrency <n>] [--stop-when <csv>] [--dry-run] [--json]"],
|
|
1052
|
+
commands: [{ command: "[--task <id>] [--max-tasks <n>] [--concurrency <n>] [--dry-run]", description: "Select ready tasks, dispatch runs, and await terminal outcomes.", primary: true }],
|
|
1053
|
+
examples: ["rig loop --task 106 --max-tasks 1", "rig loop --max-tasks 3 --concurrency 2"]
|
|
1054
|
+
},
|
|
1055
|
+
{
|
|
1056
|
+
name: "unblock",
|
|
1057
|
+
summary: "Highest-unblock task dispatcher.",
|
|
1058
|
+
usage: ["rig unblock [task-id] [--dry-run] [--json]"],
|
|
1059
|
+
commands: [{ command: "[task-id] [--dry-run]", description: "Dispatch the highest-unblock ready task, or blockers for one task.", primary: true }],
|
|
1060
|
+
examples: ["rig unblock --dry-run", "rig unblock 204 --dry-run"]
|
|
1061
|
+
},
|
|
1062
|
+
{
|
|
1063
|
+
name: "plan",
|
|
1064
|
+
summary: "PRD-to-task planning.",
|
|
1065
|
+
usage: ["rig plan --text <prd>|--prd <file>|--issue <id> [--title <title>] [--materialize] [--json]"],
|
|
1066
|
+
commands: [{ command: "--text <prd>|--prd <file>|--issue <id> [--materialize]", description: "Generate a plan and optionally create tasks through the configured task source.", primary: true }],
|
|
1067
|
+
examples: ["rig plan --issue 20 --json", "rig plan --prd docs/product/prd.md"]
|
|
1068
|
+
},
|
|
1069
|
+
{
|
|
1070
|
+
name: "drift",
|
|
1071
|
+
summary: "Documentation drift scanner.",
|
|
1072
|
+
usage: ["rig drift [--docs <csv>] [--ignore <csv>] [--json]"],
|
|
1073
|
+
commands: [{ command: "[--docs <csv>] [--ignore <csv>] [--json]", description: "Scan documentation for stale code references with the standard drift plugin.", primary: true }],
|
|
1074
|
+
examples: ["rig drift", "rig drift --docs docs/**"]
|
|
1075
|
+
},
|
|
1076
|
+
{
|
|
1077
|
+
name: "server",
|
|
1078
|
+
summary: "Compatibility server selector; the product Server target screen lives in Rig Cockpit.",
|
|
1079
|
+
usage: ["rig server <status|list|add|use|remove> [options]"],
|
|
1080
|
+
commands: [
|
|
1081
|
+
{ command: "status", description: "Legacy automation-only: show the selected placement and task source.", primary: true },
|
|
1082
|
+
{ command: "use local", description: "Legacy automation-only: switch this repo to local execution placement.", primary: true },
|
|
1083
|
+
{ command: "add --alias <alias> --host <host> [--port <n>]", description: "Legacy automation-only: save a remote execution target.", primary: true },
|
|
1084
|
+
{ command: "use <alias>", description: "Legacy automation-only: select a remote execution target alias.", primary: true },
|
|
1085
|
+
{ command: "remove <alias>", description: "Legacy automation-only: remove a saved remote execution target.", primary: true },
|
|
1086
|
+
{ command: "list", description: "Legacy automation-only: list saved local/remote server aliases.", primary: true }
|
|
1087
|
+
],
|
|
1088
|
+
examples: [
|
|
1089
|
+
"rig server status # legacy automation only",
|
|
1090
|
+
"rig server use local # legacy automation only"
|
|
1091
|
+
],
|
|
1092
|
+
next: ["For normal UX, run bare `rig`, open Cockpit Server, then continue to Tasks."]
|
|
1093
|
+
},
|
|
1094
|
+
{
|
|
1095
|
+
name: "task",
|
|
1096
|
+
summary: "Legacy automation-only task-source inspection and dispatch helpers.",
|
|
1097
|
+
usage: ["rig task <list|next|show|run> [options]"],
|
|
1098
|
+
commands: [
|
|
1099
|
+
{ command: "list [--assignee <login|me|@me>] [--state open|closed]", description: "Legacy automation-only: list tasks from the configured source.", primary: true },
|
|
1100
|
+
{ command: "next [filters]", description: "Legacy automation-only: render the next matching task card.", primary: true },
|
|
1101
|
+
{ command: "show <id>|--task <id> [--raw]", description: "Legacy automation-only: show a task payload for scripts.", primary: true },
|
|
1102
|
+
{ command: "run [#<issue>|<task-id>|--task <id>] [--title <t>] [--model <m>] [--prompt <p>|--initial-prompt <p>]", description: "Legacy/fenced: dispatch through the CLI run path; not the task-detail dispatch path.", primary: true },
|
|
1103
|
+
{ command: "ready", description: "Legacy automation-only: list task IDs that old dispatch can run now." },
|
|
1104
|
+
{ command: "validate|verify [--task <id>]", description: "Legacy automation-only: run configured task checks/review gates; failing checks exit nonzero." },
|
|
1105
|
+
{ command: "details --task <id>", description: "Legacy automation-only: show full task info from the configured source." },
|
|
1106
|
+
{ command: "reopen [--task <id> | --all] [--reason <text>]", description: "Legacy automation-only: reopen closed task(s) in the configured source." },
|
|
1107
|
+
{ command: "artifacts|artifact-dir|artifact-write", description: "Legacy automation-only: inspect or write task artifacts." }
|
|
1108
|
+
],
|
|
1109
|
+
examples: [
|
|
1110
|
+
"rig task list --assignee @me --limit 20 # legacy automation only",
|
|
1111
|
+
"rig task show 123 --raw # legacy automation only",
|
|
1112
|
+
"rig task run #123 --model opus-4.8 --prompt 'focus tests'"
|
|
1113
|
+
],
|
|
1114
|
+
next: ["For normal UX, run bare `rig`, use Cockpit Server/Tasks, then dispatch from Task detail."]
|
|
1115
|
+
},
|
|
1116
|
+
{
|
|
1117
|
+
name: "run",
|
|
1118
|
+
summary: "Legacy automation-only run-record inspection; OMP Runs/collab is the live surface.",
|
|
1119
|
+
usage: ["rig run [start] <task|#issue|--next> [--title <t>] [--model <m>] [--prompt <p>|--initial-prompt <p>]", "rig run <list|status|show|steer|stop|resume|restart> [options]"],
|
|
1120
|
+
commands: [
|
|
1121
|
+
{ command: "[start] <task|#issue|--next> [--title <t>] [--model <m>] [--prompt <p>|--initial-prompt <p>]", description: "Legacy automation-only: dispatch a task run through the unified run launcher.", primary: true },
|
|
1122
|
+
{ command: "list", description: "Legacy automation-only: list old run records from selected server/local state.", primary: true },
|
|
1123
|
+
{ command: "status", description: "Legacy automation-only: render old active/recent run-record groups; not live OMP status.", primary: true },
|
|
1124
|
+
{ command: "show <id>|--run <id> [--raw]", description: "Legacy automation-only: show an old run-record payload for scripts.", primary: true },
|
|
1125
|
+
{ command: "attach <run-id>|--run <id>", description: "Legacy/fenced: not the Rig Cockpit attach path; use OMP Runs or `rig join <link>`.", primary: true },
|
|
1126
|
+
{ command: "steer <run-id> --message <text>", description: "Legacy automation-only: queue steering into an old live worker.", primary: true },
|
|
1127
|
+
{ command: "stop <run-id>|--run <id> [--reason <text>]", description: "Legacy automation-only: request stop for old run records.", primary: true },
|
|
1128
|
+
{ command: "resume <run-id>|--run <id>", description: "Legacy automation-only: resume an interrupted old run record." },
|
|
1129
|
+
{ command: "restart <run-id>|--run <id>", description: "Legacy automation-only: re-dispatch an old run from a clean runtime." },
|
|
1130
|
+
{ command: "timeline|replay <run-id>|--run <id> [--with-session]", description: "Legacy automation-only: print an old consolidated run timeline." },
|
|
1131
|
+
{ command: "delete|cleanup [<run-id>|--run <id>]", description: "Legacy automation-only: remove stale live-registry entries; journals are retained." }
|
|
1132
|
+
],
|
|
1133
|
+
examples: [
|
|
1134
|
+
"rig run 204 # dispatch task 204",
|
|
1135
|
+
"rig run --title 'Fix API' 204",
|
|
1136
|
+
"rig run stop <run-id> # legacy automation only"
|
|
1137
|
+
],
|
|
1138
|
+
next: [
|
|
1139
|
+
"For live sessions, use bare `rig`, the OMP Runs screen, or `rig join <collab-link>`.",
|
|
1140
|
+
"Use `--json` only for scripts that still consume legacy compatibility records."
|
|
1141
|
+
]
|
|
1142
|
+
},
|
|
1143
|
+
{
|
|
1144
|
+
name: "inbox",
|
|
1145
|
+
summary: "Legacy automation-only request view; normal UX is the OMP Inbox screen.",
|
|
1146
|
+
usage: ["rig inbox <approvals|approve|inputs|respond> [options]"],
|
|
1147
|
+
commands: [
|
|
1148
|
+
{ command: "approvals [--run <id>] [--task <id>]", description: "Legacy automation-only: list pending approval records.", primary: true },
|
|
1149
|
+
{ command: "inputs [--run <id>] [--task <id>]", description: "Legacy automation-only: list pending user-input records.", primary: true },
|
|
1150
|
+
{ command: "approve --run <id> --request <id> --decision approve|reject", description: "Legacy automation-only: resolve an approval record." },
|
|
1151
|
+
{ command: "respond --run <id> --request <id> --text <answer> | --answer <answer>", description: "Legacy automation-only: answer a user-input record." }
|
|
1152
|
+
],
|
|
1153
|
+
examples: [
|
|
1154
|
+
"rig inbox approvals # legacy automation only"
|
|
1155
|
+
],
|
|
1156
|
+
next: ["For normal UX, use bare `rig`, then the OMP Inbox screen."]
|
|
1157
|
+
},
|
|
1158
|
+
{
|
|
1159
|
+
name: "stats",
|
|
1160
|
+
summary: "Legacy automation-only metrics over old run records; not the OMP live UX.",
|
|
1161
|
+
usage: ["rig stats [show] [--since <7d|30d|ISO date>]"],
|
|
1162
|
+
commands: [
|
|
1163
|
+
{ command: "show [--since <window>]", description: "Legacy automation-only: totals, completion/failure rates, run time, steering, stalls, approvals.", primary: true }
|
|
1164
|
+
],
|
|
1165
|
+
examples: [
|
|
1166
|
+
"rig stats --json # legacy automation only"
|
|
1167
|
+
],
|
|
1168
|
+
next: ["For normal UX, use the OMP Runs screen."]
|
|
1169
|
+
},
|
|
1170
|
+
{
|
|
1171
|
+
name: "inspect",
|
|
1172
|
+
summary: "Legacy automation-only artifact/log inspection; normal UX is OMP session history.",
|
|
1173
|
+
usage: ["rig inspect <logs|artifact|artifacts|run-logs|runs|failures|graph|diff> [options]"],
|
|
1174
|
+
commands: [
|
|
1175
|
+
{ command: "logs --task <id>", description: "Legacy automation-only: latest old run log for a task.", primary: true },
|
|
1176
|
+
{ command: "run-logs --run <id>", description: "Legacy automation-only: log lines for a specific run.", primary: true },
|
|
1177
|
+
{ command: "runs", description: "Legacy automation-only: list projected runs." },
|
|
1178
|
+
{ command: "artifact --task <id> --file <name>", description: "Legacy automation-only: preview one completion artifact." },
|
|
1179
|
+
{ command: "artifacts --task <id>", description: "Legacy automation-only: list completion artifacts.", primary: true },
|
|
1180
|
+
{ command: "diff --task <id>", description: "Legacy automation-only: list task changed files." },
|
|
1181
|
+
{ command: "failures --task <id>", description: "Legacy automation-only: recorded failures for a task.", primary: true },
|
|
1182
|
+
{ command: "graph [--task <id>]", description: "Legacy automation-only: task dependency graph." }
|
|
1183
|
+
],
|
|
1184
|
+
next: ["For normal UX, use the OMP Runs screen and OMP session history."]
|
|
1185
|
+
},
|
|
1186
|
+
{
|
|
1187
|
+
name: "repo",
|
|
1188
|
+
summary: "Repository sync/baseline helpers for the Rig-managed checkout.",
|
|
1189
|
+
usage: ["rig repo <sync|reset-baseline>"],
|
|
1190
|
+
commands: [
|
|
1191
|
+
{ command: "sync", description: "Sync project repository state.", primary: true },
|
|
1192
|
+
{ command: "reset-baseline", description: "Reset the managed baseline for the repo." }
|
|
1193
|
+
],
|
|
1194
|
+
examples: ["rig repo sync"]
|
|
1195
|
+
},
|
|
1196
|
+
{
|
|
1197
|
+
name: "plugin",
|
|
1198
|
+
summary: "Plugin listing, validation, and plugin-contributed commands.",
|
|
1199
|
+
usage: ["rig plugin <list|validate|run> [options]"],
|
|
1200
|
+
commands: [
|
|
1201
|
+
{ command: "list", description: "List plugins declared in rig.config.ts and their contributions.", primary: true },
|
|
1202
|
+
{ command: "validate --task <id>", description: "Run plugin-contributed validators for a task.", primary: true },
|
|
1203
|
+
{ command: "run <command-id> [args...]", description: "Execute a plugin-contributed CLI command (also callable as `rig <command-id>`)." }
|
|
1204
|
+
],
|
|
1205
|
+
examples: ["rig plugin list", "rig plugin run <command-id>"]
|
|
1206
|
+
},
|
|
1207
|
+
{
|
|
1208
|
+
name: "init",
|
|
1209
|
+
summary: "Legacy automation-only config bootstrap/repair helper; not root onboarding.",
|
|
1210
|
+
usage: ["rig init [--yes] [--server local|remote] [--repo owner/repo] [--remote-url <url>]"],
|
|
1211
|
+
commands: [
|
|
1212
|
+
{ command: "init", description: "Legacy/fenced setup wizard for compatibility projects; not onboarding.", primary: true },
|
|
1213
|
+
{ command: "init --demo", description: "Legacy/fenced offline demo project for compatibility tests.", primary: true },
|
|
1214
|
+
{ command: "init --yes", description: "Legacy/fenced non-interactive setup for old automation.", primary: true },
|
|
1215
|
+
{ command: "init --server remote --remote-url <url>", description: "Legacy/fenced remote server link setup.", primary: true },
|
|
1216
|
+
{ command: "init --repair", description: "Legacy/fenced repair of missing private compatibility state." }
|
|
1217
|
+
],
|
|
1218
|
+
examples: [
|
|
1219
|
+
"rig init --demo # legacy compatibility only",
|
|
1220
|
+
"rig init --repair # legacy compatibility only"
|
|
1221
|
+
],
|
|
1222
|
+
next: ["For onboarding and normal UX, run bare `rig`, then use Cockpit Server/Tasks and dispatch from Task detail."]
|
|
1223
|
+
},
|
|
1224
|
+
{
|
|
1225
|
+
name: "doctor",
|
|
1226
|
+
summary: "Diagnostic-only compatibility checks; normal health lives in the OMP Doctor screen.",
|
|
1227
|
+
usage: ["rig doctor"],
|
|
1228
|
+
commands: [
|
|
1229
|
+
{ command: "doctor", description: "Diagnostic/legacy-only: check compatibility setup/runtime state; not onboarding.", primary: true },
|
|
1230
|
+
{ command: "check", description: "Diagnostic/legacy-only spelling for compatibility checks." }
|
|
1231
|
+
],
|
|
1232
|
+
examples: ["rig doctor --json # legacy diagnostic automation only"],
|
|
1233
|
+
next: ["For normal UX, use the OMP Doctor screen."]
|
|
1234
|
+
},
|
|
1235
|
+
{
|
|
1236
|
+
name: "github",
|
|
1237
|
+
summary: "Legacy automation-only GitHub auth helpers for selected compatibility servers.",
|
|
1238
|
+
usage: ["rig github auth <status|import-gh|token>"],
|
|
1239
|
+
commands: [
|
|
1240
|
+
{ command: "auth status", description: "Legacy automation-only: show GitHub auth state.", primary: true },
|
|
1241
|
+
{ command: "auth import-gh", description: "Legacy automation-only: import the current `gh` token into the selected server." },
|
|
1242
|
+
{ command: "auth token --token <token>", description: "Legacy automation-only: store a token on the selected server." }
|
|
1243
|
+
],
|
|
1244
|
+
examples: ["rig github auth status # legacy automation only"],
|
|
1245
|
+
next: ["For normal UX, use bare `rig` and the OMP extension cockpit."]
|
|
1246
|
+
}
|
|
1247
|
+
];
|
|
1248
|
+
var ADVANCED_GROUPS = [
|
|
1249
|
+
{
|
|
1250
|
+
name: "setup",
|
|
1251
|
+
summary: "Legacy automation-only setup bootstrap/check helpers.",
|
|
1252
|
+
usage: ["rig setup <bootstrap|check|preflight>"],
|
|
1253
|
+
commands: [
|
|
1254
|
+
{ command: "bootstrap", description: "Legacy automation-only: bootstrap local setup dependencies.", primary: true },
|
|
1255
|
+
{ command: "check", description: "Legacy automation-only: check local setup state (toolchain, deps, config).", primary: true },
|
|
1256
|
+
{ command: "preflight", description: "Legacy automation-only: run preflight checks before an old run.", primary: true }
|
|
1257
|
+
]
|
|
1258
|
+
},
|
|
1259
|
+
{
|
|
1260
|
+
name: "profile",
|
|
1261
|
+
summary: "Runtime profile/model defaults.",
|
|
1262
|
+
usage: ["rig profile <show|set>"],
|
|
1263
|
+
commands: [
|
|
1264
|
+
{ command: "show", description: "Show the active execution profile.", primary: true },
|
|
1265
|
+
{ command: "set [--model <model>] [--runtime <runtime>] [--plugin <plugin>]", description: "Set model/runtime/plugin profile defaults.", primary: true }
|
|
1266
|
+
]
|
|
1267
|
+
},
|
|
1268
|
+
{
|
|
1269
|
+
name: "review",
|
|
1270
|
+
summary: "Inspect or change completion review gate policy.",
|
|
1271
|
+
usage: ["rig review <show|set>"],
|
|
1272
|
+
commands: [
|
|
1273
|
+
{ command: "show", description: "Show current review gate settings." },
|
|
1274
|
+
{ command: "set <off|advisory|required> [--provider <provider>]", description: "Change review strictness/provider (e.g. --provider greptile)." }
|
|
1275
|
+
],
|
|
1276
|
+
examples: ["rig review show", "rig review set required --provider greptile"],
|
|
1277
|
+
next: ["For normal workflow handoffs, use the OMP Inbox screen."]
|
|
1278
|
+
},
|
|
1279
|
+
{
|
|
1280
|
+
name: "pi",
|
|
1281
|
+
summary: "Manage Pi extension packages for this project (community extensions from npm/git).",
|
|
1282
|
+
usage: ["rig pi <list|add|remove|search> [args]"],
|
|
1283
|
+
commands: [
|
|
1284
|
+
{ command: "list", description: "Show project and user Pi extension packages." },
|
|
1285
|
+
{ command: "add <source>", description: "Add an npm/git Pi extension to .pi/settings.json (auto-installs at next session)." },
|
|
1286
|
+
{ command: "remove <source>", description: "Remove an operator-added Pi extension." },
|
|
1287
|
+
{ command: "search [term]", description: "Discover Pi extension packages on the npm registry." }
|
|
1288
|
+
],
|
|
1289
|
+
examples: ["rig pi search subagents", "rig pi add pi-subagents", "rig pi list"],
|
|
1290
|
+
next: ["Config-managed extensions: declare `runtime: { pi: { packages: [...] } }` in rig.config.ts \u2014 workers pick them up automatically."]
|
|
1291
|
+
},
|
|
1292
|
+
{
|
|
1293
|
+
name: "queue",
|
|
1294
|
+
summary: "Run task queues locally.",
|
|
1295
|
+
usage: ["rig queue run [--workers <n>] [--max-tasks <n>] [--action validate|verify|pipeline] [--isolation off|worktree] [--no-runtime-reuse] [--fail-fast] [--skip-project-sync]"],
|
|
1296
|
+
commands: [
|
|
1297
|
+
{ command: "run [--workers <n>] [--max-tasks <n>] [--action validate|verify|pipeline] [--isolation off|worktree] [--no-runtime-reuse] [--fail-fast] [--skip-project-sync]", description: "Process queue work: drain matching tasks with N workers, optional per-task action and isolation.", primary: true }
|
|
1298
|
+
]
|
|
1299
|
+
},
|
|
1300
|
+
{
|
|
1301
|
+
name: "agent",
|
|
1302
|
+
summary: "Runtime agent workspace helpers.",
|
|
1303
|
+
usage: ["rig agent <list|prepare|run|cleanup>"],
|
|
1304
|
+
commands: [
|
|
1305
|
+
{ command: "list", description: "List prepared agent runtimes.", primary: true },
|
|
1306
|
+
{ command: "prepare [--id <id>] [--mode <mode>] [--task <task>]", description: "Prepare an isolated agent runtime workspace.", primary: true },
|
|
1307
|
+
{ command: "run [--id <id>] [--mode <mode>] [--task <task>] [--skip-project-sync]", description: "Prepare (if needed) and run an agent in its workspace.", primary: true },
|
|
1308
|
+
{ command: "cleanup [--all] [--id <id>]", description: "Remove prepared agent workspaces.", primary: true }
|
|
1309
|
+
]
|
|
1310
|
+
},
|
|
1311
|
+
{
|
|
1312
|
+
name: "dist",
|
|
1313
|
+
summary: "Build/install packaged Rig CLI.",
|
|
1314
|
+
usage: ["rig dist <build|install|doctor|rebuild-agent>"],
|
|
1315
|
+
commands: [
|
|
1316
|
+
{ command: "build [--output-dir <dir>]", description: "Build the distributable Rig CLI.", primary: true },
|
|
1317
|
+
{ command: "install [--scope <scope>] [--path <path>]", description: "Install the built CLI to a scope/path.", primary: true },
|
|
1318
|
+
{ command: "doctor", description: "Diagnose the dist toolchain and install state.", primary: true },
|
|
1319
|
+
{ command: "rebuild-agent", description: "Rebuild the agent runtime image, pruning stale images.", primary: true }
|
|
1320
|
+
]
|
|
1321
|
+
},
|
|
1322
|
+
{ name: "workspace", summary: "Workspace topology/service helpers.", usage: ["rig workspace <summary|topology|remote-hosts>"], commands: [{ command: "summary", description: "Show workspace summary." }] },
|
|
1323
|
+
{
|
|
1324
|
+
name: "remote",
|
|
1325
|
+
summary: "Legacy automation-only remote orchestration controls.",
|
|
1326
|
+
usage: ["rig remote <status|tasks|watch|pause|resume|continue|stop|refresh|add-iterations|remove-iterations|endpoint ...>"],
|
|
1327
|
+
commands: [
|
|
1328
|
+
{ command: "status [--remote <alias>]", description: "Legacy automation-only: show old remote orchestration state.", primary: true },
|
|
1329
|
+
{ command: "tasks [--remote <alias>]", description: "Legacy automation-only: list the old remote's tracked tasks.", primary: true },
|
|
1330
|
+
{ command: "watch [--remote <alias>] [--seconds <n>] [--event <type>]", description: "Legacy automation-only: stream old remote orchestration events.", primary: true },
|
|
1331
|
+
{ command: "pause [--remote <alias>]", description: "Legacy automation-only: pause old remote orchestration.", primary: true },
|
|
1332
|
+
{ command: "resume [--remote <alias>] [--max-workers <n>] [--max-iterations <n>] [--direct-merge]", description: "Legacy automation-only: resume old remote orchestration with optional tuning.", primary: true },
|
|
1333
|
+
{ command: "continue [--remote <alias>]", description: "Legacy automation-only: continue a paused old remote.", primary: true },
|
|
1334
|
+
{ command: "stop [--remote <alias>]", description: "Legacy automation-only: stop old remote orchestration.", primary: true },
|
|
1335
|
+
{ command: "refresh [--remote <alias>]", description: "Legacy automation-only: refresh old remote state.", primary: true },
|
|
1336
|
+
{ command: "add-iterations [--count <n>] [--remote <alias>]", description: "Legacy automation-only: grant an old remote more iterations.", primary: true },
|
|
1337
|
+
{ command: "remove-iterations [--count <n>] [--remote <alias>]", description: "Legacy automation-only: reduce an old remote's iteration budget.", primary: true },
|
|
1338
|
+
{ command: "endpoint list", description: "Legacy automation-only: list configured remote endpoints.", primary: true },
|
|
1339
|
+
{ command: "endpoint add --alias <alias> --host <host> --port <n> [--token <token>]", description: "Legacy automation-only: register a remote endpoint.", primary: true },
|
|
1340
|
+
{ command: "endpoint remove --alias <alias>", description: "Legacy automation-only: remove a remote endpoint.", primary: true },
|
|
1341
|
+
{ command: "endpoint test [--alias <alias>]", description: "Legacy diagnostic-only: test connectivity to a remote endpoint.", primary: true },
|
|
1342
|
+
{ command: "endpoint doctor", description: "Legacy diagnostic-only: diagnose remote endpoint configuration.", primary: true }
|
|
1343
|
+
]
|
|
1344
|
+
},
|
|
1345
|
+
{ name: "git", summary: "Pass through to Rig git-flow helper.", usage: ["rig git <args...>"], commands: [{ command: "<args...>", description: "Advanced git flow operations." }] },
|
|
1346
|
+
{ name: "harness", summary: "Pass through to runtime harness CLI.", usage: ["rig harness <args...>"], commands: [{ command: "<args...>", description: "Advanced harness operations." }] },
|
|
1347
|
+
{ name: "test", summary: "Project test wrappers.", usage: ["rig test <unit|e2e|all>"], commands: [{ command: "all", description: "Run configured project tests." }] }
|
|
1348
|
+
];
|
|
1349
|
+
var ALL_GROUPS = [...PRIMARY_GROUPS, ...ADVANCED_GROUPS];
|
|
1350
|
+
|
|
1351
|
+
// packages/cli-surface-plugin/src/commands/_help-catalog.ts
|
|
79
1352
|
function heading(title) {
|
|
80
1353
|
return pc2.bold(pc2.cyan(title));
|
|
81
1354
|
}
|
|
@@ -149,6 +1422,7 @@ function printGroupHelpDocument(groupName) {
|
|
|
149
1422
|
|
|
150
1423
|
// packages/cli-surface-plugin/src/commands/stats.ts
|
|
151
1424
|
var DAY_MS = 24 * 60 * 60 * 1000;
|
|
1425
|
+
var RunReadModelCap = defineCapability(RUN_READ_MODEL);
|
|
152
1426
|
function parseSinceOption(value, now = new Date) {
|
|
153
1427
|
if (!value?.trim())
|
|
154
1428
|
return null;
|
|
@@ -206,8 +1480,13 @@ async function executeStats(context, args, deps = {}) {
|
|
|
206
1480
|
throw new CliError(`Unknown stats command: ${command}`, 1, { hint: "Run `rig stats --help` \u2014 the default command is `show`." });
|
|
207
1481
|
const sinceResult = takeOption(commandArgs, "--since");
|
|
208
1482
|
requireNoExtraArgs(sinceResult.rest, "rig stats [show] [--since <7d|30d|ISO date>]");
|
|
209
|
-
const
|
|
210
|
-
const
|
|
1483
|
+
const since = parseSinceOption(sinceResult.value);
|
|
1484
|
+
const readModel = await requireCapabilityForRoot(context.projectRoot, RunReadModelCap, "No run-worker plugin provides run read model for this project root.");
|
|
1485
|
+
const details = await readModel.getStats({
|
|
1486
|
+
projectRoot: context.projectRoot,
|
|
1487
|
+
since: since ? since.toISOString() : null,
|
|
1488
|
+
...deps.listRuns ? { runs: await deps.listRuns(context.projectRoot) } : {}
|
|
1489
|
+
});
|
|
211
1490
|
if (context.outputMode === "text")
|
|
212
1491
|
printFormattedOutput(formatStatsTable(formatStatsRows(details)));
|
|
213
1492
|
return { ok: true, group: "stats", command, details };
|