@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.
Files changed (112) hide show
  1. package/dist/src/app/drone-ui.d.ts +0 -11
  2. package/dist/src/app/drone-ui.js +0 -114
  3. package/dist/src/commands/_async-ui.d.ts +1 -1
  4. package/dist/src/commands/_cli-format.d.ts +0 -29
  5. package/dist/src/commands/_cli-format.js +59 -113
  6. package/dist/src/commands/_connection-state.d.ts +6 -33
  7. package/dist/src/commands/_connection-state.js +654 -138
  8. package/dist/src/commands/_doctor-checks.d.ts +2 -5
  9. package/dist/src/commands/_doctor-checks.js +10 -9
  10. package/dist/src/commands/_help-catalog.d.ts +2 -1
  11. package/dist/src/commands/_help-catalog.js +654 -7
  12. package/dist/src/commands/_inprocess-services.d.ts +5 -5
  13. package/dist/src/commands/_inprocess-services.js +1 -1
  14. package/dist/src/commands/_parsers.js +651 -12
  15. package/dist/src/commands/_paths.d.ts +0 -2
  16. package/dist/src/commands/_paths.js +2 -10
  17. package/dist/src/commands/_pi-install.d.ts +2 -12
  18. package/dist/src/commands/_pi-install.js +3 -36
  19. package/dist/src/commands/_policy.js +659 -20
  20. package/dist/src/commands/agent.d.ts +1 -1
  21. package/dist/src/commands/agent.js +675 -24
  22. package/dist/src/commands/config.d.ts +1 -1
  23. package/dist/src/commands/config.js +656 -21
  24. package/dist/src/commands/dist.d.ts +1 -1
  25. package/dist/src/commands/dist.js +828 -102
  26. package/dist/src/commands/doctor.d.ts +1 -1
  27. package/dist/src/commands/doctor.js +658 -12
  28. package/dist/src/commands/github.d.ts +1 -1
  29. package/dist/src/commands/github.js +658 -19
  30. package/dist/src/commands/inbox.d.ts +12 -8
  31. package/dist/src/commands/inbox.js +741 -22
  32. package/dist/src/commands/init.d.ts +17 -19
  33. package/dist/src/commands/init.js +836 -306
  34. package/dist/src/commands/inspect.d.ts +5 -6
  35. package/dist/src/commands/inspect.js +754 -42
  36. package/dist/src/commands/pi.d.ts +1 -1
  37. package/dist/src/commands/pi.js +655 -16
  38. package/dist/src/commands/plugin.d.ts +9 -9
  39. package/dist/src/commands/plugin.js +652 -13
  40. package/dist/src/commands/profile-and-review.d.ts +1 -1
  41. package/dist/src/commands/profile-and-review.js +655 -16
  42. package/dist/src/commands/queue.d.ts +1 -1
  43. package/dist/src/commands/queue.js +871 -12
  44. package/dist/src/commands/remote-client.d.ts +152 -0
  45. package/dist/src/commands/remote-client.js +475 -0
  46. package/dist/src/commands/remote.d.ts +1 -1
  47. package/dist/src/commands/remote.js +1100 -29
  48. package/dist/src/commands/repo-git-harness.d.ts +1 -1
  49. package/dist/src/commands/repo-git-harness.js +2321 -47
  50. package/dist/src/commands/run.d.ts +10 -6
  51. package/dist/src/commands/run.js +830 -50
  52. package/dist/src/commands/server.d.ts +1 -1
  53. package/dist/src/commands/server.js +649 -11
  54. package/dist/src/commands/setup.d.ts +2 -2
  55. package/dist/src/commands/setup.js +829 -18
  56. package/dist/src/commands/stats.d.ts +2 -4
  57. package/dist/src/commands/stats.js +1299 -20
  58. package/dist/src/commands/test.d.ts +1 -1
  59. package/dist/src/commands/test.js +648 -9
  60. package/dist/src/commands/triage.d.ts +2 -3
  61. package/dist/src/commands/triage.js +657 -11
  62. package/dist/src/commands/workspace.d.ts +1 -1
  63. package/dist/src/commands/workspace.js +1280 -15
  64. package/dist/src/control-plane/agent-binary-build.d.ts +9 -0
  65. package/dist/src/control-plane/agent-binary-build.js +88 -0
  66. package/dist/src/control-plane/embedded-native-assets.d.ts +7 -0
  67. package/dist/src/control-plane/embedded-native-assets.js +6 -0
  68. package/dist/src/control-plane/guard.d.ts +17 -0
  69. package/dist/src/control-plane/guard.js +684 -0
  70. package/dist/src/control-plane/harness-cli.d.ts +12 -0
  71. package/dist/src/control-plane/harness-cli.js +1623 -0
  72. package/dist/src/control-plane/native/git-ops.d.ts +67 -0
  73. package/dist/src/control-plane/native/git-ops.js +1381 -0
  74. package/dist/src/control-plane/native/github-auth-env.d.ts +1 -0
  75. package/dist/src/control-plane/native/github-auth-env.js +21 -0
  76. package/dist/src/control-plane/native/host-git.d.ts +4 -0
  77. package/dist/src/control-plane/native/host-git.js +51 -0
  78. package/dist/src/control-plane/priority-queue.d.ts +22 -0
  79. package/dist/src/control-plane/priority-queue.js +212 -0
  80. package/dist/src/control-plane/rigfig.d.ts +9 -0
  81. package/dist/src/control-plane/rigfig.js +70 -0
  82. package/dist/src/control-plane/scope.d.ts +3 -0
  83. package/dist/src/control-plane/scope.js +58 -0
  84. package/dist/src/control-plane/setup-status.d.ts +44 -0
  85. package/dist/src/control-plane/setup-status.js +164 -0
  86. package/dist/src/control-plane/task-data.d.ts +2 -0
  87. package/dist/src/control-plane/task-data.js +12 -0
  88. package/dist/src/control-plane/workspace-ops.d.ts +79 -0
  89. package/dist/src/control-plane/workspace-ops.js +639 -0
  90. package/dist/src/help-catalog-data.d.ts +7 -0
  91. package/dist/src/help-catalog-data.js +660 -0
  92. package/dist/src/kernel-dispatch.js +1 -3
  93. package/dist/src/plugin.js +10072 -30
  94. package/dist/src/runner.d.ts +7 -9
  95. package/dist/src/runner.js +750 -30
  96. package/package.json +12 -13
  97. package/dist/src/commands/_json-output.d.ts +0 -11
  98. package/dist/src/commands/_json-output.js +0 -54
  99. package/dist/src/commands/_pi-frontend.d.ts +0 -35
  100. package/dist/src/commands/_pi-frontend.js +0 -64
  101. package/dist/src/commands/_run-driver-helpers.d.ts +0 -26
  102. package/dist/src/commands/_run-driver-helpers.js +0 -132
  103. package/dist/src/commands/task-run-driver.d.ts +0 -93
  104. package/dist/src/commands/task-run-driver.js +0 -136
  105. package/dist/src/commands/task.d.ts +0 -46
  106. package/dist/src/commands/task.js +0 -555
  107. package/dist/src/provider-model.d.ts +0 -34
  108. package/dist/src/provider-model.js +0 -56
  109. package/dist/src/rig-config-package-deps.d.ts +0 -10
  110. package/dist/src/rig-config-package-deps.js +0 -272
  111. package/dist/src/version.d.ts +0 -8
  112. package/dist/src/version.js +0 -47
@@ -2,21 +2,660 @@
2
2
  // packages/cli-surface-plugin/src/commands/github.ts
3
3
  import { spawnSync } from "child_process";
4
4
  import { mkdirSync as mkdirSync2, writeFileSync as writeFileSync2 } from "fs";
5
- import { dirname as dirname2, resolve as resolve3 } from "path";
5
+ import { dirname as dirname2, resolve as resolve4 } from "path";
6
6
 
7
7
  // packages/cli-surface-plugin/src/runner.ts
8
- import { EventBus } from "@rig/runtime/control-plane/runtime/events";
9
- import { CliError as RuntimeCliError } from "@rig/runtime/control-plane/errors";
10
- import { evaluate, loadPolicy, resolveAction } from "@rig/runtime/control-plane/runtime/guard";
11
- 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";
12
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
13
656
  class CliError extends RuntimeCliError {
14
- hint;
15
657
  constructor(message, exitCode = 1, options = {}) {
16
- super(message, exitCode);
17
- if (options.hint?.trim()) {
18
- this.hint = options.hint.trim();
19
- }
658
+ super(message, exitCode, options);
20
659
  }
21
660
  }
22
661
  function takeOption(args, option) {
@@ -41,7 +680,7 @@ function takeOption(args, option) {
41
680
  }
42
681
 
43
682
  // packages/cli-surface-plugin/src/commands/_inprocess-services.ts
44
- import { resolve } from "path";
683
+ import { resolve as resolve2 } from "path";
45
684
  import {
46
685
  beginGitHubDeviceFlow,
47
686
  checkGitHubRepoPermissions,
@@ -51,7 +690,7 @@ import {
51
690
  resolveGitHubAuthStatus,
52
691
  resolveProjectStatusField,
53
692
  saveGitHubTokenForProject
54
- } from "@rig/github-provider-plugin";
693
+ } from "@rig/github-lib";
55
694
  var scopedGitHubBearerTokens = new Map;
56
695
  function cleanToken(value) {
57
696
  const trimmed = value?.trim();
@@ -61,7 +700,7 @@ function oauthClientId() {
61
700
  return cleanToken(process.env.RIG_GITHUB_OAUTH_CLIENT_ID);
62
701
  }
63
702
  function setGitHubBearerTokenForCurrentProcess(token, projectRoot) {
64
- scopedGitHubBearerTokens.set(resolve(projectRoot ?? process.cwd()), cleanToken(token));
703
+ scopedGitHubBearerTokens.set(resolve2(projectRoot ?? process.cwd()), cleanToken(token));
65
704
  }
66
705
  async function getGitHubAuthStatusInProcess(context) {
67
706
  return { ok: true, ...resolveGitHubAuthStatus({ projectRoot: context.projectRoot, oauthConfigured: Boolean(oauthClientId()) }) };
@@ -83,16 +722,16 @@ async function postGitHubTokenInProcess(context, token, options = {}) {
83
722
  }
84
723
 
85
724
  // packages/cli-surface-plugin/src/commands/_connection-state.ts
86
- import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
87
- import { dirname, resolve as resolve2 } from "path";
725
+ import { existsSync as existsSync2, mkdirSync, readFileSync as readFileSync2, writeFileSync } from "fs";
726
+ import { dirname, resolve as resolve3 } from "path";
88
727
  function resolveRepoConnectionPath(projectRoot) {
89
- return resolve2(projectRoot, ".rig", "state", "connection.json");
728
+ return resolve3(projectRoot, ".rig", "state", "connection.json");
90
729
  }
91
730
  function readJsonFile(path) {
92
- if (!existsSync(path))
731
+ if (!existsSync2(path))
93
732
  return null;
94
733
  try {
95
- return JSON.parse(readFileSync(path, "utf8"));
734
+ return JSON.parse(readFileSync2(path, "utf8"));
96
735
  } catch (error) {
97
736
  throw new CliError(`Invalid Rig connection state at ${path}: ${error instanceof Error ? error.message : String(error)}`, 1, { hint: "Fix or delete that file, then re-select a server with `rig server use <alias|local>`." });
98
737
  }
@@ -270,7 +909,7 @@ function persistRemoteAuthSession(context, source, result, fallbackToken) {
270
909
  if (!apiSessionToken)
271
910
  return;
272
911
  const repo = readRepoConnection(context.projectRoot);
273
- const path = resolve3(context.projectRoot, ".rig", "state", "github-auth.json");
912
+ const path = resolve4(context.projectRoot, ".rig", "state", "github-auth.json");
274
913
  mkdirSync2(dirname2(path), { recursive: true });
275
914
  writeFileSync2(path, `${JSON.stringify({
276
915
  authenticated: true,