@h-rig/runtime 0.0.6-alpha.0

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 (176) hide show
  1. package/README.md +27 -0
  2. package/dist/bin/rig-agent-dispatch.js +9615 -0
  3. package/dist/bin/rig-agent.js +9512 -0
  4. package/dist/bin/rig-browser-tool.js +269 -0
  5. package/dist/src/agent-mode.js +48 -0
  6. package/dist/src/baked-secrets.js +121 -0
  7. package/dist/src/binary-build-worker.js +312 -0
  8. package/dist/src/binary-run.js +540 -0
  9. package/dist/src/boundaries.js +1 -0
  10. package/dist/src/build-time-config.js +25 -0
  11. package/dist/src/control-plane/agent-roles.js +27 -0
  12. package/dist/src/control-plane/agent-wrapper.js +9621 -0
  13. package/dist/src/control-plane/authority-files.js +582 -0
  14. package/dist/src/control-plane/browser-contract.js +135 -0
  15. package/dist/src/control-plane/controlled-bash.js +1111 -0
  16. package/dist/src/control-plane/errors.js +13 -0
  17. package/dist/src/control-plane/harness-main.js +10828 -0
  18. package/dist/src/control-plane/hook-materializer.js +75 -0
  19. package/dist/src/control-plane/hooks/audit-trail.js +353 -0
  20. package/dist/src/control-plane/hooks/completion-verification.js +7552 -0
  21. package/dist/src/control-plane/hooks/import-guard.js +890 -0
  22. package/dist/src/control-plane/hooks/inject-context.js +4189 -0
  23. package/dist/src/control-plane/hooks/post-edit-lint.js +43 -0
  24. package/dist/src/control-plane/hooks/safety-guard.js +910 -0
  25. package/dist/src/control-plane/hooks/scope-guard.js +907 -0
  26. package/dist/src/control-plane/hooks/shared.js +44 -0
  27. package/dist/src/control-plane/hooks/submodule-branch.js +7797 -0
  28. package/dist/src/control-plane/hooks/task-runtime-start.js +7799 -0
  29. package/dist/src/control-plane/hooks/test-integrity-guard.js +891 -0
  30. package/dist/src/control-plane/materialize-task-config.js +453 -0
  31. package/dist/src/control-plane/memory-sync/cli.js +2019 -0
  32. package/dist/src/control-plane/memory-sync/db.js +753 -0
  33. package/dist/src/control-plane/memory-sync/embed.js +281 -0
  34. package/dist/src/control-plane/memory-sync/index.js +2049 -0
  35. package/dist/src/control-plane/memory-sync/query.js +294 -0
  36. package/dist/src/control-plane/memory-sync/read.js +784 -0
  37. package/dist/src/control-plane/memory-sync/types.js +6 -0
  38. package/dist/src/control-plane/memory-sync/write.js +1547 -0
  39. package/dist/src/control-plane/native/git-native.js +490 -0
  40. package/dist/src/control-plane/native/git-ops.js +2860 -0
  41. package/dist/src/control-plane/native/harness-cli.js +9721 -0
  42. package/dist/src/control-plane/native/pr-automation.js +373 -0
  43. package/dist/src/control-plane/native/profile-ops.js +481 -0
  44. package/dist/src/control-plane/native/repo-ops.js +2342 -0
  45. package/dist/src/control-plane/native/root-resolver.js +66 -0
  46. package/dist/src/control-plane/native/run-ops.js +3281 -0
  47. package/dist/src/control-plane/native/runtime-native-sidecar.js +299 -0
  48. package/dist/src/control-plane/native/runtime-native.js +392 -0
  49. package/dist/src/control-plane/native/scope-rules.js +17 -0
  50. package/dist/src/control-plane/native/task-ops.js +6320 -0
  51. package/dist/src/control-plane/native/task-state.js +1512 -0
  52. package/dist/src/control-plane/native/utils.js +535 -0
  53. package/dist/src/control-plane/native/validator-binaries.js +889 -0
  54. package/dist/src/control-plane/native/validator.js +2197 -0
  55. package/dist/src/control-plane/native/verifier.js +3249 -0
  56. package/dist/src/control-plane/native/workspace-ops.js +1635 -0
  57. package/dist/src/control-plane/plugin-host-context.js +334 -0
  58. package/dist/src/control-plane/project-main-pre-run-sync.js +630 -0
  59. package/dist/src/control-plane/provider/claude-stream-records.js +158 -0
  60. package/dist/src/control-plane/provider/codex-app-server.js +885 -0
  61. package/dist/src/control-plane/provider/codex-exec-records.js +203 -0
  62. package/dist/src/control-plane/provider/rig-task-run-skill.js +39 -0
  63. package/dist/src/control-plane/provider/runtime-instructions.js +96 -0
  64. package/dist/src/control-plane/remote.js +854 -0
  65. package/dist/src/control-plane/repos/index.js +473 -0
  66. package/dist/src/control-plane/repos/layout.js +124 -0
  67. package/dist/src/control-plane/repos/mirror/bootstrap.js +268 -0
  68. package/dist/src/control-plane/repos/mirror/refresh.js +398 -0
  69. package/dist/src/control-plane/repos/mirror/state.js +167 -0
  70. package/dist/src/control-plane/repos/registry.js +77 -0
  71. package/dist/src/control-plane/repos/types.js +1 -0
  72. package/dist/src/control-plane/runtime/agent-mode.js +48 -0
  73. package/dist/src/control-plane/runtime/baked-secrets.js +120 -0
  74. package/dist/src/control-plane/runtime/claude-tool-router-binary.js +343 -0
  75. package/dist/src/control-plane/runtime/claude-tool-router.js +520 -0
  76. package/dist/src/control-plane/runtime/context.js +216 -0
  77. package/dist/src/control-plane/runtime/events.js +218 -0
  78. package/dist/src/control-plane/runtime/guard-types.js +6 -0
  79. package/dist/src/control-plane/runtime/guard.js +880 -0
  80. package/dist/src/control-plane/runtime/image/fingerprint-sidecar.js +1194 -0
  81. package/dist/src/control-plane/runtime/image/index.js +2255 -0
  82. package/dist/src/control-plane/runtime/image-fingerprint-sidecar.js +1191 -0
  83. package/dist/src/control-plane/runtime/image.js +2255 -0
  84. package/dist/src/control-plane/runtime/index.js +8511 -0
  85. package/dist/src/control-plane/runtime/isolation/discovery.js +599 -0
  86. package/dist/src/control-plane/runtime/isolation/home.js +1217 -0
  87. package/dist/src/control-plane/runtime/isolation/index.js +8193 -0
  88. package/dist/src/control-plane/runtime/isolation/runner.js +2651 -0
  89. package/dist/src/control-plane/runtime/isolation/shared.js +501 -0
  90. package/dist/src/control-plane/runtime/isolation/toolchain.js +1892 -0
  91. package/dist/src/control-plane/runtime/isolation/types.js +1 -0
  92. package/dist/src/control-plane/runtime/isolation/worktree.js +509 -0
  93. package/dist/src/control-plane/runtime/isolation.js +8193 -0
  94. package/dist/src/control-plane/runtime/overlay.js +67 -0
  95. package/dist/src/control-plane/runtime/plugin-mode.js +41 -0
  96. package/dist/src/control-plane/runtime/plugins.js +1131 -0
  97. package/dist/src/control-plane/runtime/provisioning-env.js +220 -0
  98. package/dist/src/control-plane/runtime/queue.js +8358 -0
  99. package/dist/src/control-plane/runtime/rig-shell.js +205 -0
  100. package/dist/src/control-plane/runtime/rig-tools.js +182 -0
  101. package/dist/src/control-plane/runtime/runner-context.js +1 -0
  102. package/dist/src/control-plane/runtime/runtime-paths.js +184 -0
  103. package/dist/src/control-plane/runtime/sandbox/backend-bwrap.js +311 -0
  104. package/dist/src/control-plane/runtime/sandbox/backend-none.js +21 -0
  105. package/dist/src/control-plane/runtime/sandbox/backend-seatbelt.js +268 -0
  106. package/dist/src/control-plane/runtime/sandbox/backend.js +1718 -0
  107. package/dist/src/control-plane/runtime/sandbox/orchestrator.js +1745 -0
  108. package/dist/src/control-plane/runtime/sandbox/utils.js +137 -0
  109. package/dist/src/control-plane/runtime/sandbox-backend-bwrap.js +311 -0
  110. package/dist/src/control-plane/runtime/sandbox-backend-none.js +21 -0
  111. package/dist/src/control-plane/runtime/sandbox-backend-seatbelt.js +268 -0
  112. package/dist/src/control-plane/runtime/sandbox-backend.js +1718 -0
  113. package/dist/src/control-plane/runtime/sandbox-orchestrator.js +1745 -0
  114. package/dist/src/control-plane/runtime/sandbox-utils.js +137 -0
  115. package/dist/src/control-plane/runtime/snapshot/index.js +454 -0
  116. package/dist/src/control-plane/runtime/snapshot/sidecar.js +502 -0
  117. package/dist/src/control-plane/runtime/snapshot/task-run.js +1578 -0
  118. package/dist/src/control-plane/runtime/snapshot-sidecar.js +498 -0
  119. package/dist/src/control-plane/runtime/snapshot.js +454 -0
  120. package/dist/src/control-plane/runtime/task-run-snapshot.js +1578 -0
  121. package/dist/src/control-plane/runtime/tool-gateway.js +422 -0
  122. package/dist/src/control-plane/runtime/tooling/browser-tools.js +32 -0
  123. package/dist/src/control-plane/runtime/tooling/claude-router-binary.js +343 -0
  124. package/dist/src/control-plane/runtime/tooling/claude-router.js +524 -0
  125. package/dist/src/control-plane/runtime/tooling/file-tools.js +182 -0
  126. package/dist/src/control-plane/runtime/tooling/gateway.js +422 -0
  127. package/dist/src/control-plane/runtime/tooling/index.js +1290 -0
  128. package/dist/src/control-plane/runtime/tooling/shell.js +205 -0
  129. package/dist/src/control-plane/runtime/types.js +1 -0
  130. package/dist/src/control-plane/setup-version.js +14 -0
  131. package/dist/src/control-plane/state-sync/index.js +1509 -0
  132. package/dist/src/control-plane/state-sync/read.js +856 -0
  133. package/dist/src/control-plane/state-sync/reconcile.js +260 -0
  134. package/dist/src/control-plane/state-sync/repo.js +302 -0
  135. package/dist/src/control-plane/state-sync/types.js +111 -0
  136. package/dist/src/control-plane/state-sync/write.js +1469 -0
  137. package/dist/src/control-plane/task-fields.js +38 -0
  138. package/dist/src/control-plane/task-source-bootstrap.js +46 -0
  139. package/dist/src/control-plane/task-source.js +30 -0
  140. package/dist/src/control-plane/tasks/legacy-task-config-source.js +130 -0
  141. package/dist/src/control-plane/tasks/plugin-task-source.js +103 -0
  142. package/dist/src/control-plane/tasks/source-aware-task-config-source.js +611 -0
  143. package/dist/src/control-plane/tasks/source-lifecycle.js +1093 -0
  144. package/dist/src/control-plane/tasks/task-record-reader.js +9 -0
  145. package/dist/src/control-plane/validators/boundary/public-apis.js +107 -0
  146. package/dist/src/control-plane/validators/integration/_shared.js +51 -0
  147. package/dist/src/control-plane/validators/integration/adm-audit-http.js +85 -0
  148. package/dist/src/control-plane/validators/integration/adm-auth-http.js +78 -0
  149. package/dist/src/control-plane/validators/integration/adm-issuer-http.js +80 -0
  150. package/dist/src/control-plane/validators/integration/adm-migration.js +78 -0
  151. package/dist/src/control-plane/validators/integration/adm-scaffold.js +78 -0
  152. package/dist/src/control-plane/validators/runtime-registration.js +64 -0
  153. package/dist/src/control-plane/validators/shared.js +683 -0
  154. package/dist/src/events.js +218 -0
  155. package/dist/src/execution.js +35 -0
  156. package/dist/src/index.js +1633 -0
  157. package/dist/src/layout.js +145 -0
  158. package/dist/src/local-server.js +202 -0
  159. package/dist/src/plugins.js +329 -0
  160. package/dist/src/remote-http.js +83 -0
  161. package/dist/src/runtime-context.js +216 -0
  162. package/dist/src/types.js +1 -0
  163. package/native/darwin-arm64/bin/rig-git +0 -0
  164. package/native/darwin-arm64/bin/rig-shell +0 -0
  165. package/native/darwin-arm64/bin/rig-tools +0 -0
  166. package/native/darwin-arm64/lib/runtime-native-darwin-arm64.dylib +0 -0
  167. package/native/darwin-arm64/lib/runtime-native.dylib +0 -0
  168. package/native/darwin-arm64/manifest.json +1 -0
  169. package/native/linux-x64/bin/rig-git +0 -0
  170. package/native/linux-x64/bin/rig-shell +0 -0
  171. package/native/linux-x64/bin/rig-tools +0 -0
  172. package/native/linux-x64/lib/runtime-native-linux-x64.so +0 -0
  173. package/native/linux-x64/lib/runtime-native.so +0 -0
  174. package/native/linux-x64/manifest.json +1 -0
  175. package/package.json +74 -0
  176. package/skills/rig-task-run.md +71 -0
@@ -0,0 +1,1578 @@
1
+ // @bun
2
+ var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
3
+
4
+ // packages/runtime/src/layout.ts
5
+ import { existsSync } from "fs";
6
+ import { basename, dirname as dirname2, resolve as resolve2 } from "path";
7
+ function resolveMonorepoRoot(projectRoot) {
8
+ const normalizedProjectRoot = resolve2(projectRoot);
9
+ const explicit = process.env.MONOREPO_ROOT?.trim();
10
+ if (explicit) {
11
+ const explicitRoot = resolve2(explicit);
12
+ const explicitParent = dirname2(explicitRoot);
13
+ if (basename(explicitParent) === ".worktrees") {
14
+ const owner = dirname2(explicitParent);
15
+ const ownerHasGit = existsSync(resolve2(owner, ".git"));
16
+ const ownerHasTaskConfig = existsSync(resolve2(owner, ".rig", "task-config.json"));
17
+ const ownerHasRigConfig = existsSync(resolve2(owner, "rig.config.ts"));
18
+ if (ownerHasGit && (ownerHasTaskConfig || ownerHasRigConfig)) {
19
+ return owner;
20
+ }
21
+ throw new Error(`MONOREPO_ROOT points to worktree ${explicitRoot}, but the owner checkout is incomplete at ${owner}.`);
22
+ }
23
+ if (!existsSync(resolve2(explicitRoot, ".git"))) {
24
+ throw new Error(`MONOREPO_ROOT points to ${explicitRoot}, but no git checkout was found there.`);
25
+ }
26
+ const hasTaskConfig = existsSync(resolve2(explicitRoot, ".rig", "task-config.json"));
27
+ const hasRigConfig = existsSync(resolve2(explicitRoot, "rig.config.ts"));
28
+ if (!hasTaskConfig && !hasRigConfig) {
29
+ throw new Error(`MONOREPO_ROOT points to ${explicitRoot}, but neither .rig/task-config.json nor rig.config.ts exists there.`);
30
+ }
31
+ return explicitRoot;
32
+ }
33
+ const projectParent = dirname2(normalizedProjectRoot);
34
+ if (basename(projectParent) === ".worktrees") {
35
+ const worktreeOwner = dirname2(projectParent);
36
+ const ownerHasGit = existsSync(resolve2(worktreeOwner, ".git"));
37
+ const ownerHasTaskConfig = existsSync(resolve2(worktreeOwner, ".rig", "task-config.json"));
38
+ const ownerHasRigConfig = existsSync(resolve2(worktreeOwner, "rig.config.ts"));
39
+ if (ownerHasGit && (ownerHasTaskConfig || ownerHasRigConfig)) {
40
+ return worktreeOwner;
41
+ }
42
+ }
43
+ return normalizedProjectRoot;
44
+ }
45
+ function resolveRuntimeWorkspaceLayout(workspaceDir) {
46
+ const root = resolve2(workspaceDir);
47
+ const rigRoot = resolve2(root, ".rig");
48
+ const logsDir = resolve2(rigRoot, "logs");
49
+ const stateDir = resolve2(rigRoot, "state");
50
+ const runtimeDir = resolve2(rigRoot, "runtime");
51
+ const binDir = resolve2(rigRoot, "bin");
52
+ return {
53
+ workspaceDir: root,
54
+ rigRoot,
55
+ stateDir,
56
+ logsDir,
57
+ artifactsRoot: resolve2(root, RIG_ARTIFACTS_DIRNAME),
58
+ runtimeDir,
59
+ homeDir: resolve2(rigRoot, "home"),
60
+ tmpDir: resolve2(rigRoot, "tmp"),
61
+ cacheDir: resolve2(rigRoot, "cache"),
62
+ sessionDir: resolve2(rigRoot, "session"),
63
+ binDir,
64
+ distDir: resolve2(rigRoot, "dist"),
65
+ pluginBinDir: resolve2(binDir, "plugins"),
66
+ contextPath: resolve2(rigRoot, "runtime-context.json"),
67
+ controlPlaneEventsFile: resolve2(logsDir, "control-plane.events.jsonl")
68
+ };
69
+ }
70
+ var RIG_ARTIFACTS_DIRNAME = "artifacts";
71
+ var init_layout = () => {};
72
+
73
+ // packages/runtime/src/control-plane/runtime/sandbox/utils.ts
74
+ var init_utils = __esm(() => {
75
+ init_layout();
76
+ });
77
+
78
+ // packages/runtime/src/control-plane/native/git-native.ts
79
+ import { tmpdir } from "os";
80
+ import { dirname, isAbsolute, resolve } from "path";
81
+ var sharedGitNativeOutputDir = resolve(tmpdir(), "rig-native");
82
+ var sharedGitNativeOutputPath = resolve(sharedGitNativeOutputDir, `rig-git-${process.platform}-${process.arch}${process.platform === "win32" ? ".exe" : ""}`);
83
+ // packages/runtime/src/control-plane/native/utils.ts
84
+ import { ptr as ptr2 } from "bun:ffi";
85
+ init_layout();
86
+
87
+ // packages/runtime/src/control-plane/native/runtime-native.ts
88
+ import { dlopen, ptr, suffix, toBuffer } from "bun:ffi";
89
+ import { copyFileSync, existsSync as existsSync2, mkdirSync, renameSync, rmSync, statSync } from "fs";
90
+ import { tmpdir as tmpdir2 } from "os";
91
+ import { dirname as dirname3, resolve as resolve3 } from "path";
92
+ var sharedNativeRuntimeOutputDir = resolve3(tmpdir2(), "rig-native");
93
+ var sharedNativeRuntimeOutputPath = resolve3(sharedNativeRuntimeOutputDir, `runtime-native-${process.platform}-${process.arch}.${suffix}`);
94
+ var colocatedNativeRuntimeFileName = `runtime-native.${suffix}`;
95
+ var nativeRuntimeLibrary = await loadNativeRuntimeLibrary();
96
+ function requireNativeRuntimeLibrary(feature) {
97
+ if (!nativeRuntimeLibrary) {
98
+ throw new Error(`Native Zig runtime is required for ${feature}`);
99
+ }
100
+ return nativeRuntimeLibrary;
101
+ }
102
+ function runtimeScanWorktreesNative(worktreesRoot) {
103
+ const response = runNativeRuntimeSidecar({
104
+ op: "scan-worktrees",
105
+ input: { worktreesRoot }
106
+ });
107
+ if (!response.ok) {
108
+ throw new Error(response.error);
109
+ }
110
+ return response.entries ?? [];
111
+ }
112
+ async function ensureNativeRuntimeLibraryPath(outputPath = sharedNativeRuntimeOutputPath, options = {}) {
113
+ if (await buildNativeRuntimeLibrary(outputPath, options)) {
114
+ return outputPath;
115
+ }
116
+ return !options.force && existsSync2(outputPath) ? outputPath : null;
117
+ }
118
+ async function loadNativeRuntimeLibrary() {
119
+ if (process.env.RIG_DISABLE_ZIG_NATIVE === "1") {
120
+ return null;
121
+ }
122
+ for (const candidate of nativeRuntimeLibraryCandidates()) {
123
+ if (!candidate || !existsSync2(candidate)) {
124
+ continue;
125
+ }
126
+ const loaded = tryDlopenNativeRuntimeLibrary(candidate);
127
+ if (loaded) {
128
+ return loaded;
129
+ }
130
+ }
131
+ const builtLibraryPath = await ensureNativeRuntimeLibraryPath(sharedNativeRuntimeOutputPath, { force: true });
132
+ if (!builtLibraryPath) {
133
+ return null;
134
+ }
135
+ return tryDlopenNativeRuntimeLibrary(builtLibraryPath);
136
+ }
137
+ function nativePackageLibraryCandidates(fromDir, names) {
138
+ const candidates = [];
139
+ let cursor = resolve3(fromDir);
140
+ for (let index = 0;index < 8; index += 1) {
141
+ for (const name of names) {
142
+ candidates.push(resolve3(cursor, "native", `${process.platform}-${process.arch}`, name), resolve3(cursor, "native", `${process.platform}-${process.arch}`, "lib", name), resolve3(cursor, "native", name), resolve3(cursor, "native", "lib", name));
143
+ }
144
+ const parent = dirname3(cursor);
145
+ if (parent === cursor)
146
+ break;
147
+ cursor = parent;
148
+ }
149
+ return candidates;
150
+ }
151
+ function nativeRuntimeLibraryCandidates() {
152
+ const explicit = process.env.RIG_NATIVE_RUNTIME_LIB?.trim() || "";
153
+ const execDir = process.execPath?.trim() ? dirname3(process.execPath.trim()) : "";
154
+ const platformSpecific = `runtime-native-${process.platform}-${process.arch}.${suffix}`;
155
+ return [...new Set([
156
+ explicit,
157
+ ...nativePackageLibraryCandidates(import.meta.dir, [colocatedNativeRuntimeFileName, platformSpecific]),
158
+ execDir ? resolve3(execDir, colocatedNativeRuntimeFileName) : "",
159
+ execDir ? resolve3(execDir, platformSpecific) : "",
160
+ execDir ? resolve3(execDir, "..", colocatedNativeRuntimeFileName) : "",
161
+ execDir ? resolve3(execDir, "..", platformSpecific) : "",
162
+ execDir ? resolve3(execDir, "lib", colocatedNativeRuntimeFileName) : "",
163
+ execDir ? resolve3(execDir, "..", "lib", colocatedNativeRuntimeFileName) : "",
164
+ sharedNativeRuntimeOutputPath
165
+ ].filter(Boolean))];
166
+ }
167
+ function resolveNativeRuntimeSourcePath() {
168
+ const explicit = process.env.RIG_NATIVE_RUNTIME_SOURCE?.trim();
169
+ if (explicit && existsSync2(explicit)) {
170
+ return explicit;
171
+ }
172
+ const bundled = resolve3(import.meta.dir, "../../../native/snapshot.zig");
173
+ return existsSync2(bundled) ? bundled : null;
174
+ }
175
+ function resolveNativeRuntimeSidecarSourcePath() {
176
+ const envRoots = [
177
+ process.cwd()?.trim(),
178
+ process.env.RIG_HOST_PROJECT_ROOT?.trim(),
179
+ process.env.PROJECT_RIG_ROOT?.trim()
180
+ ].filter(Boolean);
181
+ for (const root of envRoots) {
182
+ for (const relative of [
183
+ "packages/runtime/src/control-plane/native/runtime-native-sidecar.ts",
184
+ "packages/runtime/dist/src/control-plane/native/runtime-native-sidecar.js"
185
+ ]) {
186
+ const candidate = resolve3(root, relative);
187
+ if (existsSync2(candidate)) {
188
+ return candidate;
189
+ }
190
+ }
191
+ }
192
+ for (const localCandidate of [
193
+ resolve3(import.meta.dir, "runtime-native-sidecar.js"),
194
+ resolve3(import.meta.dir, "runtime-native-sidecar.ts")
195
+ ]) {
196
+ if (existsSync2(localCandidate))
197
+ return localCandidate;
198
+ }
199
+ return null;
200
+ }
201
+ async function buildNativeRuntimeLibrary(outputPath, options = {}) {
202
+ if (process.env.RIG_DISABLE_ZIG_NATIVE === "1") {
203
+ return false;
204
+ }
205
+ const zigBinary = Bun.which("zig");
206
+ const sourcePath = resolveNativeRuntimeSourcePath();
207
+ if (!zigBinary || !sourcePath) {
208
+ return false;
209
+ }
210
+ const tempOutputPath = `${outputPath}.${process.pid}.${Date.now()}.${Math.random().toString(36).slice(2)}.tmp`;
211
+ try {
212
+ mkdirSync(dirname3(outputPath), { recursive: true });
213
+ const needsBuild = options.force === true || !existsSync2(outputPath) || statSync(sourcePath).mtimeMs > statSync(outputPath).mtimeMs;
214
+ if (!needsBuild) {
215
+ return true;
216
+ }
217
+ const build = Bun.spawn([
218
+ zigBinary,
219
+ "build-lib",
220
+ sourcePath,
221
+ "-dynamic",
222
+ "-O",
223
+ "ReleaseFast",
224
+ `-femit-bin=${tempOutputPath}`
225
+ ], {
226
+ cwd: import.meta.dir,
227
+ stdout: "pipe",
228
+ stderr: "pipe"
229
+ });
230
+ const exitCode = await build.exited;
231
+ if (exitCode !== 0 || !existsSync2(tempOutputPath)) {
232
+ rmSync(tempOutputPath, { force: true });
233
+ return false;
234
+ }
235
+ renameSync(tempOutputPath, outputPath);
236
+ return true;
237
+ } catch {
238
+ rmSync(tempOutputPath, { force: true });
239
+ return false;
240
+ }
241
+ }
242
+ function tryDlopenNativeRuntimeLibrary(outputPath) {
243
+ try {
244
+ return dlopen(outputPath, {
245
+ rig_scope_match: {
246
+ args: ["ptr", "ptr"],
247
+ returns: "u8"
248
+ },
249
+ snapshot_capture: {
250
+ args: ["ptr", "u64", "ptr", "u64"],
251
+ returns: "ptr"
252
+ },
253
+ snapshot_delta: {
254
+ args: ["ptr", "ptr"],
255
+ returns: "ptr"
256
+ },
257
+ snapshot_store_delta: {
258
+ args: ["ptr", "ptr", "ptr", "u64", "ptr", "u64", "ptr", "u64", "ptr", "u64"],
259
+ returns: "ptr"
260
+ },
261
+ snapshot_inspect_delta: {
262
+ args: ["ptr", "u64"],
263
+ returns: "ptr"
264
+ },
265
+ snapshot_apply_delta: {
266
+ args: ["ptr", "u64", "ptr", "u64"],
267
+ returns: "ptr"
268
+ },
269
+ snapshot_release: {
270
+ args: ["ptr"],
271
+ returns: "void"
272
+ },
273
+ runtime_hash_file: {
274
+ args: ["ptr", "u64"],
275
+ returns: "ptr"
276
+ },
277
+ runtime_hash_tree: {
278
+ args: ["ptr", "u64"],
279
+ returns: "ptr"
280
+ },
281
+ runtime_prepare_paths: {
282
+ args: ["ptr", "u64", "ptr", "u64", "ptr", "u64", "ptr", "u64", "ptr", "u64"],
283
+ returns: "ptr"
284
+ },
285
+ runtime_link_dependency_layer: {
286
+ args: ["ptr", "u64", "ptr", "u64"],
287
+ returns: "ptr"
288
+ },
289
+ runtime_scan_worktrees: {
290
+ args: ["ptr", "u64"],
291
+ returns: "ptr"
292
+ }
293
+ });
294
+ } catch {
295
+ return null;
296
+ }
297
+ }
298
+ function runNativeRuntimeSidecar(request) {
299
+ const sidecarSourcePath = resolveNativeRuntimeSidecarSourcePath();
300
+ if (!sidecarSourcePath) {
301
+ throw new Error("runtime-native-sidecar.ts source file not found.");
302
+ }
303
+ const bunCli = resolveNativeRuntimeSidecarInvocation();
304
+ const proc = Bun.spawnSync([bunCli.command, sidecarSourcePath, JSON.stringify(request)], {
305
+ cwd: process.env.RIG_HOST_PROJECT_ROOT?.trim() || process.cwd(),
306
+ stdout: "pipe",
307
+ stderr: "pipe",
308
+ env: {
309
+ ...process.env,
310
+ ...bunCli.env,
311
+ RIG_NATIVE_RUNTIME_SIDECAR: "1"
312
+ }
313
+ });
314
+ if (proc.exitCode !== 0) {
315
+ throw new Error(proc.stderr.toString() || proc.stdout.toString() || `runtime native sidecar exited ${proc.exitCode}`);
316
+ }
317
+ const stdout = proc.stdout.toString().trim();
318
+ if (!stdout) {
319
+ throw new Error("runtime native sidecar returned empty output.");
320
+ }
321
+ return JSON.parse(stdout);
322
+ }
323
+ function resolveNativeRuntimeSidecarInvocation() {
324
+ const bunPath = Bun.which("bun");
325
+ if (bunPath) {
326
+ return { command: bunPath, env: {} };
327
+ }
328
+ if (process.execPath?.trim()) {
329
+ return {
330
+ command: process.execPath,
331
+ env: { BUN_BE_BUN: "1" }
332
+ };
333
+ }
334
+ throw new Error("bun is required to run the runtime native sidecar.");
335
+ }
336
+
337
+ // packages/runtime/src/control-plane/native/scope-rules.ts
338
+ var activeRules = null;
339
+ function getScopeRules() {
340
+ return activeRules;
341
+ }
342
+
343
+ // packages/runtime/src/control-plane/native/utils.ts
344
+ function resolveMonorepoRoot2(projectRoot) {
345
+ return resolveMonorepoRoot(projectRoot);
346
+ }
347
+ var nativeScopeMatcher = null;
348
+ var scopeRegexCache = new Map;
349
+ function unique(values) {
350
+ return [...new Set(values)];
351
+ }
352
+ function normalizeRelativeScopePath(inputPath) {
353
+ let normalized = inputPath.replace(/^\.\//, "");
354
+ const rules = getScopeRules();
355
+ if (rules?.stripPrefixes) {
356
+ for (const prefix of rules.stripPrefixes) {
357
+ if (normalized.startsWith(prefix)) {
358
+ normalized = normalized.slice(prefix.length);
359
+ }
360
+ }
361
+ }
362
+ return normalized;
363
+ }
364
+ function normalizePathToScope(projectRoot, monorepoRoot, inputPath) {
365
+ let normalized = inputPath.replace(/^\.\//, "");
366
+ if (normalized.startsWith(projectRoot + "/")) {
367
+ normalized = normalized.slice(projectRoot.length + 1);
368
+ }
369
+ if (normalized.startsWith(monorepoRoot + "/")) {
370
+ normalized = normalized.slice(monorepoRoot.length + 1);
371
+ }
372
+ return normalizeRelativeScopePath(normalized);
373
+ }
374
+ function scopeMatches(path, scopes) {
375
+ const matcher = getNativeScopeMatcher();
376
+ const pathVariants = unique([path, normalizeRelativeScopePath(path)]);
377
+ for (const scope of scopes) {
378
+ const scopeVariants = unique([scope, normalizeRelativeScopePath(scope)]);
379
+ for (const candidatePath of pathVariants) {
380
+ for (const candidateScope of scopeVariants) {
381
+ if (candidatePath === candidateScope) {
382
+ return true;
383
+ }
384
+ if (matcher.match(candidateScope, candidatePath)) {
385
+ return true;
386
+ }
387
+ }
388
+ }
389
+ }
390
+ return false;
391
+ }
392
+ function getNativeScopeMatcher() {
393
+ if (nativeScopeMatcher) {
394
+ return nativeScopeMatcher;
395
+ }
396
+ nativeScopeMatcher = createNativeScopeMatcher();
397
+ return nativeScopeMatcher;
398
+ }
399
+ function createNativeScopeMatcher() {
400
+ const library = requireNativeRuntimeLibrary("scope matching");
401
+ return {
402
+ match: (pattern, path) => {
403
+ const patternBuffer = Buffer.from(`${pattern}\x00`);
404
+ const pathBuffer = Buffer.from(`${path}\x00`);
405
+ return library.symbols.rig_scope_match(Number(ptr2(patternBuffer)), Number(ptr2(pathBuffer))) !== 0;
406
+ }
407
+ };
408
+ }
409
+ // packages/runtime/src/control-plane/runtime/context.ts
410
+ import { existsSync as existsSync3, mkdirSync as mkdirSync2, readFileSync, writeFileSync } from "fs";
411
+ import { dirname as dirname4, resolve as resolve4 } from "path";
412
+ var DEFAULT_RUNTIME_MEMORY_RETRIEVAL = {
413
+ topK: 5,
414
+ lexicalWeight: 0.35,
415
+ vectorWeight: 0.45,
416
+ recencyWeight: 0.1,
417
+ confidenceWeight: 0.1
418
+ };
419
+ var runtimeContextStringFields = [
420
+ "runtimeId",
421
+ "taskId",
422
+ "role",
423
+ "workspaceDir",
424
+ "stateDir",
425
+ "logsDir",
426
+ "sessionDir",
427
+ "sessionFile",
428
+ "policyFile",
429
+ "binDir",
430
+ "createdAt"
431
+ ];
432
+ var runtimeContextArrayFields = ["scopes", "validation"];
433
+ var runtimeContextOptionalStringFields = [
434
+ "artifactRoot",
435
+ "hostProjectRoot",
436
+ "monorepoMainRoot",
437
+ "monorepoBaseRef",
438
+ "monorepoBaseCommit"
439
+ ];
440
+ function loadRuntimeContext(path) {
441
+ const absPath = resolve4(path);
442
+ if (!existsSync3(absPath)) {
443
+ throw new Error(`RuntimeTaskContext file not found: ${absPath}`);
444
+ }
445
+ let raw;
446
+ try {
447
+ raw = JSON.parse(readFileSync(absPath, "utf8"));
448
+ } catch (err) {
449
+ throw new Error(`Failed to parse RuntimeTaskContext at ${absPath}: ${String(err)}`);
450
+ }
451
+ if (typeof raw !== "object" || raw === null) {
452
+ throw new Error(`RuntimeTaskContext at ${absPath} is not an object`);
453
+ }
454
+ const obj = raw;
455
+ for (const field of runtimeContextStringFields) {
456
+ if (typeof obj[field] !== "string" || obj[field].length === 0) {
457
+ throw new Error(`RuntimeTaskContext field "${field}" must be a non-empty string (at ${absPath})`);
458
+ }
459
+ }
460
+ for (const field of runtimeContextArrayFields) {
461
+ if (!Array.isArray(obj[field])) {
462
+ throw new Error(`RuntimeTaskContext field "${field}" must be an array (at ${absPath})`);
463
+ }
464
+ if (!obj[field].every((entry) => typeof entry === "string")) {
465
+ throw new Error(`RuntimeTaskContext field "${field}" must be a string[] (at ${absPath})`);
466
+ }
467
+ }
468
+ for (const field of runtimeContextOptionalStringFields) {
469
+ if (field in obj && obj[field] !== undefined && typeof obj[field] !== "string") {
470
+ throw new Error(`RuntimeTaskContext field "${field}" must be a string when present (at ${absPath})`);
471
+ }
472
+ }
473
+ if (obj.browser !== undefined) {
474
+ if (typeof obj.browser !== "object" || obj.browser === null || Array.isArray(obj.browser)) {
475
+ throw new Error(`RuntimeTaskContext field "browser" must be an object when present (at ${absPath})`);
476
+ }
477
+ const browser = obj.browser;
478
+ for (const field of [
479
+ "preset",
480
+ "mode",
481
+ "stateDir",
482
+ "defaultProfile",
483
+ "effectiveProfile",
484
+ "defaultAttachUrl",
485
+ "effectiveAttachUrl",
486
+ "launchHelper",
487
+ "checkHelper",
488
+ "attachInfoHelper",
489
+ "e2eHelper",
490
+ "resetProfileHelper"
491
+ ]) {
492
+ if (typeof browser[field] !== "string" || browser[field].length === 0) {
493
+ throw new Error(`RuntimeTaskContext field "browser.${field}" must be a non-empty string (at ${absPath})`);
494
+ }
495
+ }
496
+ for (const field of ["devCommand", "launchCommand", "checkCommand", "e2eCommand"]) {
497
+ if (browser[field] !== undefined && typeof browser[field] !== "string") {
498
+ throw new Error(`RuntimeTaskContext field "browser.${field}" must be a string when present (at ${absPath})`);
499
+ }
500
+ }
501
+ if (typeof browser.required !== "boolean") {
502
+ throw new Error(`RuntimeTaskContext field "browser.required" must be a boolean (at ${absPath})`);
503
+ }
504
+ }
505
+ if (obj.memory !== undefined) {
506
+ if (typeof obj.memory !== "object" || obj.memory === null || Array.isArray(obj.memory)) {
507
+ throw new Error(`RuntimeTaskContext field "memory" must be an object when present (at ${absPath})`);
508
+ }
509
+ const memory = obj.memory;
510
+ for (const field of ["canonicalPath", "canonicalRef", "canonicalBaseOid", "hydratedPath"]) {
511
+ if (typeof memory[field] !== "string" || memory[field].length === 0) {
512
+ throw new Error(`RuntimeTaskContext field "memory.${field}" must be a non-empty string (at ${absPath})`);
513
+ }
514
+ }
515
+ if (typeof memory.createdFresh !== "boolean") {
516
+ throw new Error(`RuntimeTaskContext field "memory.createdFresh" must be a boolean (at ${absPath})`);
517
+ }
518
+ if (typeof memory.retrieval !== "object" || memory.retrieval === null || Array.isArray(memory.retrieval)) {
519
+ throw new Error(`RuntimeTaskContext field "memory.retrieval" must be an object (at ${absPath})`);
520
+ }
521
+ const retrieval = memory.retrieval;
522
+ for (const field of ["topK", "lexicalWeight", "vectorWeight", "recencyWeight", "confidenceWeight"]) {
523
+ if (typeof retrieval[field] !== "number" || Number.isNaN(retrieval[field])) {
524
+ throw new Error(`RuntimeTaskContext field "memory.retrieval.${field}" must be a number (at ${absPath})`);
525
+ }
526
+ }
527
+ }
528
+ if (obj.initialDirtyFiles !== undefined) {
529
+ if (typeof obj.initialDirtyFiles !== "object" || obj.initialDirtyFiles === null || Array.isArray(obj.initialDirtyFiles)) {
530
+ throw new Error(`RuntimeTaskContext field "initialDirtyFiles" must be an object when present (at ${absPath})`);
531
+ }
532
+ const dirtyFiles = obj.initialDirtyFiles;
533
+ for (const key of ["project", "monorepo"]) {
534
+ if (dirtyFiles[key] === undefined) {
535
+ continue;
536
+ }
537
+ if (!Array.isArray(dirtyFiles[key]) || !dirtyFiles[key].every((entry) => typeof entry === "string")) {
538
+ throw new Error(`RuntimeTaskContext field "initialDirtyFiles.${key}" must be a string[] when present (at ${absPath})`);
539
+ }
540
+ }
541
+ }
542
+ if (obj.initialHeadCommits !== undefined) {
543
+ if (typeof obj.initialHeadCommits !== "object" || obj.initialHeadCommits === null || Array.isArray(obj.initialHeadCommits)) {
544
+ throw new Error(`RuntimeTaskContext field "initialHeadCommits" must be an object when present (at ${absPath})`);
545
+ }
546
+ const headCommits = obj.initialHeadCommits;
547
+ for (const key of ["project", "monorepo"]) {
548
+ if (headCommits[key] === undefined) {
549
+ continue;
550
+ }
551
+ if (typeof headCommits[key] !== "string") {
552
+ throw new Error(`RuntimeTaskContext field "initialHeadCommits.${key}" must be a string when present (at ${absPath})`);
553
+ }
554
+ }
555
+ }
556
+ return obj;
557
+ }
558
+
559
+ // packages/runtime/src/control-plane/memory-sync/query.ts
560
+ var DEFAULT_RESULT_LIMIT = DEFAULT_RUNTIME_MEMORY_RETRIEVAL.topK;
561
+ var DAY_MS = 24 * 60 * 60 * 1000;
562
+ // packages/runtime/src/build-time-config.ts
563
+ function normalizeBuildConfig(value) {
564
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
565
+ return {};
566
+ }
567
+ return Object.fromEntries(Object.entries(value).filter((entry) => typeof entry[1] === "string"));
568
+ }
569
+ function readBuildConfig() {
570
+ if (typeof __RIG_BUILD_CONFIG__ !== "undefined") {
571
+ return normalizeBuildConfig(__RIG_BUILD_CONFIG__);
572
+ }
573
+ const raw = process.env.RIG_BUILD_CONFIG_JSON?.trim();
574
+ if (!raw) {
575
+ return {};
576
+ }
577
+ try {
578
+ return normalizeBuildConfig(JSON.parse(raw));
579
+ } catch {
580
+ return {};
581
+ }
582
+ }
583
+
584
+ // packages/runtime/src/control-plane/runtime/tooling/shell.ts
585
+ import { tmpdir as tmpdir3 } from "os";
586
+ import { basename as basename2, dirname as dirname5, resolve as resolve5 } from "path";
587
+ var sharedNativeShellOutputDir = resolve5(tmpdir3(), "rig-native");
588
+ var sharedNativeShellOutputPath = resolve5(sharedNativeShellOutputDir, `rig-shell-${process.platform}-${process.arch}${process.platform === "win32" ? ".exe" : ""}`);
589
+ // packages/runtime/src/control-plane/runtime/tooling/file-tools.ts
590
+ import { tmpdir as tmpdir4 } from "os";
591
+ import { basename as basename3, dirname as dirname6, resolve as resolve6 } from "path";
592
+ var sharedNativeToolsOutputDir = resolve6(tmpdir4(), "rig-native");
593
+ var sharedNativeToolsOutputPath = resolve6(sharedNativeToolsOutputDir, `rig-tools-${process.platform}-${process.arch}${process.platform === "win32" ? ".exe" : ""}`);
594
+ // packages/runtime/src/control-plane/plugin-host-context.ts
595
+ import { createPluginHost } from "@rig/core";
596
+ import { loadConfig } from "@rig/core/load-config";
597
+
598
+ // packages/runtime/src/control-plane/repos/registry.ts
599
+ var MANAGED_REPOS = new Map;
600
+
601
+ // packages/runtime/src/control-plane/tasks/source-aware-task-config-source.ts
602
+ var STATUS_LABELS = new Set(["ready", "blocked", "in-progress", "under-review", "failed", "cancelled"]);
603
+
604
+ // packages/runtime/src/control-plane/state-sync/types.ts
605
+ var CANONICAL_TASK_LIFECYCLE_STATUSES = new Set([
606
+ "draft",
607
+ "open",
608
+ "ready",
609
+ "queued",
610
+ "in_progress",
611
+ "under_review",
612
+ "blocked",
613
+ "completed",
614
+ "cancelled"
615
+ ]);
616
+ // packages/runtime/src/control-plane/repos/layout.ts
617
+ init_layout();
618
+ // packages/runtime/src/control-plane/state-sync/reconcile.ts
619
+ var STALE_CLAIM_MS = 24 * 60 * 60 * 1000;
620
+ // packages/runtime/src/control-plane/native/validator.ts
621
+ init_layout();
622
+
623
+ // packages/runtime/src/binary-run.ts
624
+ init_layout();
625
+ var runtimeBinaryBuildQueue = Promise.resolve();
626
+
627
+ // packages/runtime/src/control-plane/runtime/sandbox-utils.ts
628
+ init_utils();
629
+
630
+ // packages/runtime/src/control-plane/native/git-ops.ts
631
+ var TASK_ARTIFACT_STAGE_FALLBACK = new Set([
632
+ "changed-files.txt",
633
+ "contract-changes.md",
634
+ "decision-log.md",
635
+ "git-state.txt",
636
+ "next-actions.md",
637
+ "pr-state.json",
638
+ "task-result.json",
639
+ "validation-summary.json"
640
+ ]);
641
+
642
+ // packages/runtime/src/control-plane/provider/runtime-instructions.ts
643
+ var CLAUDE_ROUTER_TOOL_NAMES = [
644
+ "`mcp__rig_runtime_tools__read`",
645
+ "`mcp__rig_runtime_tools__write`",
646
+ "`mcp__rig_runtime_tools__edit`",
647
+ "`mcp__rig_runtime_tools__glob`",
648
+ "`mcp__rig_runtime_tools__grep`"
649
+ ].join(", ");
650
+ var CODEX_DYNAMIC_TOOL_NAMES = [
651
+ "`shell`",
652
+ "`read`",
653
+ "`write`",
654
+ "`edit`",
655
+ "`glob`",
656
+ "`grep`"
657
+ ].join(", ");
658
+
659
+ // packages/runtime/src/control-plane/native/task-ops.ts
660
+ var BUILD_CONFIG = readBuildConfig();
661
+ var BAKED_INFO_OUTPUT = BUILD_CONFIG.AGENT_INFO_OUTPUT ?? "";
662
+ var BAKED_DEPS_OUTPUT = BUILD_CONFIG.AGENT_DEPS_OUTPUT ?? "";
663
+ var BAKED_STATUS_OUTPUT = BUILD_CONFIG.AGENT_STATUS_OUTPUT ?? "";
664
+ var REOPENABLE_TASK_STATUSES = new Set(["completed", "cancelled", "blocked"]);
665
+ var GENERATED_TASK_ARTIFACT_FILES = new Set([
666
+ "changed-files.txt",
667
+ "decision-log.md",
668
+ "next-actions.md",
669
+ "task-result.json",
670
+ "validation-summary.json",
671
+ "review-feedback.md",
672
+ "review-state.json",
673
+ "review-status.txt",
674
+ "review-greptile-raw.json",
675
+ "pr-state.json",
676
+ "git-state.txt"
677
+ ]);
678
+
679
+ // packages/runtime/src/control-plane/runtime/isolation/index.ts
680
+ init_layout();
681
+
682
+ // packages/runtime/src/control-plane/runtime/overlay.ts
683
+ init_layout();
684
+
685
+ // packages/runtime/src/control-plane/runtime/isolation/shared.ts
686
+ var generatedCredentialFiles = new Set;
687
+ function resolveMonorepoRoot3(projectRoot) {
688
+ return resolveMonorepoRoot2(projectRoot);
689
+ }
690
+ function sanitizeRuntimeRefSegment(value) {
691
+ const sanitized = value.trim().replace(/[^A-Za-z0-9._-]+/g, "-").replace(/^-+|-+$/g, "");
692
+ return (sanitized || "runtime").slice(0, 64);
693
+ }
694
+ function taskRuntimeId(taskId) {
695
+ return `task-${taskId}`;
696
+ }
697
+
698
+ // packages/runtime/src/control-plane/runtime/isolation/home.ts
699
+ var GITHUB_KNOWN_HOSTS = [
700
+ "github.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOMqqnkVzrm0SdG6UOoqKLsabgH5C9okWi0dh2l9GKJl",
701
+ "github.com ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBEmKSENjQEezOmxkZMy7opKgwFB9nkt5YRrYMjNuG5N87uRgg6CLrbo5wAdT/y6v0mKV0U2w0WZ2YB/++Tpockg=",
702
+ "github.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCj7ndNxQowgcQnjshcLrqPEiiphnt+VTTvDP6mHBL9j1aNUkY4Ue1gvwnGLVlOhGeYrnZaMgRK6+PKCUXaDbC7qtbW8gIkhL7aGCsOr/C56SJMy/BCZfxd1nWzAOxSDPgVsmerOBYfNqltV9/hWCqBywINIR+5dIg6JTJ72pcEpEjcYgXkE2YEFXV1JHnsKgbLWNlhScqb2UmyRkQyytRLtL+38TGxkxCflmO+5Z8CSSNY7GidjMIZ7Q4zMjA2n1nGrlTDkzwDCsw+wqFPGQA179cnfGWOWRVruj16z6XyvxvjJwbz0wQZ75XK5tKSb7FNyeIEs4TT4jk+S4dhPeAUC5y+bDYirYgM4GC7uEnztnZyaVWQ7B381AK4Qdrwt51ZqExKbQpTUNn+EjqoTwvqNj4kqx5QUCI0ThS/YkOxJCXmPUWZbhjpCg56i+2aB6CmK2JGhn57K5mj0MNdBXA4/WnwH6XoPWJzK5Nyu2zB3nAZp+S5hpQs+p1vN1/wsjk="
703
+ ].join(`
704
+ `);
705
+
706
+ // packages/runtime/src/control-plane/runtime/tooling/claude-router.ts
707
+ if (false) {}
708
+ // packages/runtime/src/control-plane/runtime/isolation/discovery.ts
709
+ init_layout();
710
+ import { existsSync as existsSync4 } from "fs";
711
+ import { resolve as resolve8 } from "path";
712
+
713
+ // packages/runtime/src/control-plane/runtime/tooling/claude-router-binary.ts
714
+ import { tmpdir as tmpdir5 } from "os";
715
+ import { dirname as dirname7, resolve as resolve7 } from "path";
716
+ var sharedRouterOutputDir = resolve7(tmpdir5(), "rig-native");
717
+ var sharedRouterOutputPath = resolve7(sharedRouterOutputDir, `rig-tool-router-${process.platform}-${process.arch}${process.platform === "win32" ? ".exe" : ""}`);
718
+ // packages/runtime/src/control-plane/runtime/isolation/toolchain.ts
719
+ function runtimeWorktreeId(workspaceDir) {
720
+ return workspaceDir.split("/").at(-1) || "runtime";
721
+ }
722
+
723
+ // packages/runtime/src/control-plane/runtime/isolation/discovery.ts
724
+ async function readRuntimeMetadata(metadataPath) {
725
+ if (!existsSync4(metadataPath)) {
726
+ return null;
727
+ }
728
+ try {
729
+ return await Bun.file(metadataPath).json();
730
+ } catch {
731
+ return null;
732
+ }
733
+ }
734
+ async function listAgentRuntimes(projectRoot) {
735
+ const runtimes = [];
736
+ const monorepoRoot = resolveMonorepoRoot3(projectRoot);
737
+ const worktreesRoot = resolve8(monorepoRoot, ".worktrees");
738
+ if (!existsSync4(worktreesRoot)) {
739
+ return [];
740
+ }
741
+ const workspaces = runtimeScanWorktreesNative(worktreesRoot);
742
+ for (let scan of workspaces) {
743
+ let workspacePath = scan.workspaceDir;
744
+ const workspaceLayout = resolveRuntimeWorkspaceLayout(workspacePath);
745
+ const rootDir = scan.runtimeDir || workspaceLayout.runtimeDir;
746
+ const metadataPath = scan.metadataPath || resolve8(rootDir, "runtime.json");
747
+ const contextFile = scan.contextPath || workspaceLayout.contextPath;
748
+ let mode = "worktree";
749
+ let createdAt = new Date().toISOString();
750
+ let taskId = "";
751
+ let runtimeId = "";
752
+ let binDir = workspaceLayout.binDir;
753
+ let logsDir = workspaceLayout.logsDir;
754
+ let stateDir = workspaceLayout.stateDir;
755
+ let sessionDir = workspaceLayout.sessionDir;
756
+ const metadata = await readRuntimeMetadata(metadataPath);
757
+ if (metadata) {
758
+ runtimeId = metadata.id;
759
+ mode = metadata.mode;
760
+ createdAt = metadata.createdAt;
761
+ }
762
+ if (existsSync4(contextFile)) {
763
+ try {
764
+ const ctx = loadRuntimeContext(contextFile);
765
+ taskId = ctx.taskId;
766
+ workspacePath = ctx.workspaceDir;
767
+ binDir = ctx.binDir;
768
+ logsDir = ctx.logsDir;
769
+ stateDir = ctx.stateDir;
770
+ sessionDir = ctx.sessionDir;
771
+ } catch {}
772
+ }
773
+ if (!runtimeId) {
774
+ runtimeId = taskRuntimeId(taskId || runtimeWorktreeId(workspacePath));
775
+ }
776
+ runtimes.push({
777
+ id: runtimeId,
778
+ taskId,
779
+ mode,
780
+ rootDir,
781
+ workspaceDir: workspacePath,
782
+ homeDir: resolve8(rootDir, "home"),
783
+ tmpDir: resolve8(rootDir, "tmp"),
784
+ cacheDir: resolve8(rootDir, "cache"),
785
+ logsDir,
786
+ stateDir,
787
+ sessionDir,
788
+ claudeHomeDir: resolve8(rootDir, "home", ".claude"),
789
+ contextFile,
790
+ binDir,
791
+ createdAt
792
+ });
793
+ }
794
+ return runtimes;
795
+ }
796
+
797
+ // packages/runtime/src/control-plane/runtime/isolation/runner.ts
798
+ import { existsSync as existsSync6, rmSync as rmSync2, writeFileSync as writeFileSync2 } from "fs";
799
+ import { basename as basename4, resolve as resolve10 } from "path";
800
+
801
+ // packages/runtime/src/control-plane/runtime/guard.ts
802
+ import { optimizeNextInvocation } from "bun:jsc";
803
+ import { existsSync as existsSync5, readFileSync as readFileSync2, statSync as statSync2 } from "fs";
804
+ import { resolve as resolve9 } from "path";
805
+
806
+ // packages/runtime/src/control-plane/runtime/guard-types.ts
807
+ var POLICY_VERSION = 1;
808
+
809
+ // packages/runtime/src/control-plane/runtime/guard.ts
810
+ var DEFAULT_SCOPE = {
811
+ fail_closed: true,
812
+ harness_paths_exempt: true,
813
+ runtime_paths_exempt: true
814
+ };
815
+ var DEFAULT_SANDBOX = {
816
+ mode: "enforce",
817
+ network: true,
818
+ read_deny: [],
819
+ write_allow_from_runtime: true
820
+ };
821
+ var DEFAULT_ISOLATION = {
822
+ default_mode: "worktree",
823
+ repo_symlink_fallback: false,
824
+ strict_provisioning: true,
825
+ fail_closed_on_provision_error: true
826
+ };
827
+ var DEFAULT_COMPLETION = {
828
+ derive_checks_from_scope: true,
829
+ checks: [],
830
+ typescript_config_probe: ["tsconfig.json"],
831
+ eslint_config_probe: [".eslintrc.js", ".eslintrc.json", "eslint.config.js"]
832
+ };
833
+ var DEFAULT_RUNTIME_IMAGE = {
834
+ deps: {
835
+ monorepo_install: false,
836
+ hp_next_install: false
837
+ },
838
+ plugins_require_binaries: true
839
+ };
840
+ var DEFAULT_RUNTIME_SNAPSHOT = {
841
+ enabled: true
842
+ };
843
+ function defaultPolicy() {
844
+ return {
845
+ version: POLICY_VERSION,
846
+ mode: "enforce",
847
+ scope: { ...DEFAULT_SCOPE },
848
+ rules: [],
849
+ sandbox: { ...DEFAULT_SANDBOX },
850
+ isolation: { ...DEFAULT_ISOLATION },
851
+ completion: { ...DEFAULT_COMPLETION },
852
+ runtime_image: {
853
+ deps: { ...DEFAULT_RUNTIME_IMAGE.deps },
854
+ plugins_require_binaries: DEFAULT_RUNTIME_IMAGE.plugins_require_binaries
855
+ },
856
+ runtime_snapshot: { ...DEFAULT_RUNTIME_SNAPSHOT }
857
+ };
858
+ }
859
+ var policyCache = null;
860
+ var policyCachePath = null;
861
+ var seededPolicyConfig = null;
862
+ var compiledRegexCache = new Map;
863
+ function loadPolicy(projectRoot) {
864
+ if (seededPolicyConfig) {
865
+ return seededPolicyConfig;
866
+ }
867
+ const configPath = resolve9(projectRoot, "rig/policy/policy.json");
868
+ if (!existsSync5(configPath)) {
869
+ return defaultPolicy();
870
+ }
871
+ let mtimeMs;
872
+ try {
873
+ mtimeMs = statSync2(configPath).mtimeMs;
874
+ } catch {
875
+ return defaultPolicy();
876
+ }
877
+ if (policyCache && policyCachePath === configPath && policyCache.mtimeMs === mtimeMs) {
878
+ return policyCache.config;
879
+ }
880
+ let parsed;
881
+ try {
882
+ parsed = JSON.parse(readFileSync2(configPath, "utf-8"));
883
+ } catch {
884
+ return defaultPolicy();
885
+ }
886
+ const config = mergeWithDefaults(parsed);
887
+ policyCache = { mtimeMs, config };
888
+ policyCachePath = configPath;
889
+ return config;
890
+ }
891
+ function mergeWithDefaults(parsed) {
892
+ const base = defaultPolicy();
893
+ if (typeof parsed.mode === "string" && isValidMode(parsed.mode)) {
894
+ base.mode = parsed.mode;
895
+ }
896
+ if (parsed.scope && typeof parsed.scope === "object" && !Array.isArray(parsed.scope)) {
897
+ const s = parsed.scope;
898
+ if (typeof s.fail_closed === "boolean")
899
+ base.scope.fail_closed = s.fail_closed;
900
+ if (typeof s.harness_paths_exempt === "boolean")
901
+ base.scope.harness_paths_exempt = s.harness_paths_exempt;
902
+ if (typeof s.runtime_paths_exempt === "boolean")
903
+ base.scope.runtime_paths_exempt = s.runtime_paths_exempt;
904
+ }
905
+ if (Array.isArray(parsed.rules)) {
906
+ base.rules = precompilePolicyRuleRegexes(parsed.rules.filter(isValidRule));
907
+ }
908
+ if (Array.isArray(parsed.deny) && base.rules.length === 0) {
909
+ base.rules = precompilePolicyRuleRegexes(migrateLegacyDeny(parsed.deny));
910
+ }
911
+ if (parsed.sandbox && typeof parsed.sandbox === "object" && !Array.isArray(parsed.sandbox)) {
912
+ const sb = parsed.sandbox;
913
+ if (typeof sb.mode === "string" && isValidMode(sb.mode))
914
+ base.sandbox.mode = sb.mode;
915
+ if (typeof sb.network === "boolean")
916
+ base.sandbox.network = sb.network;
917
+ if (Array.isArray(sb.read_deny))
918
+ base.sandbox.read_deny = sb.read_deny.filter((v) => typeof v === "string");
919
+ if (typeof sb.write_allow_from_runtime === "boolean")
920
+ base.sandbox.write_allow_from_runtime = sb.write_allow_from_runtime;
921
+ }
922
+ if (parsed.isolation && typeof parsed.isolation === "object" && !Array.isArray(parsed.isolation)) {
923
+ const iso = parsed.isolation;
924
+ if (iso.default_mode === "worktree")
925
+ base.isolation.default_mode = iso.default_mode;
926
+ if (typeof iso.repo_symlink_fallback === "boolean")
927
+ base.isolation.repo_symlink_fallback = iso.repo_symlink_fallback;
928
+ if (typeof iso.strict_provisioning === "boolean")
929
+ base.isolation.strict_provisioning = iso.strict_provisioning;
930
+ if (typeof iso.fail_closed_on_provision_error === "boolean")
931
+ base.isolation.fail_closed_on_provision_error = iso.fail_closed_on_provision_error;
932
+ }
933
+ if (parsed.completion && typeof parsed.completion === "object" && !Array.isArray(parsed.completion)) {
934
+ const comp = parsed.completion;
935
+ if (typeof comp.derive_checks_from_scope === "boolean")
936
+ base.completion.derive_checks_from_scope = comp.derive_checks_from_scope;
937
+ if (Array.isArray(comp.checks))
938
+ base.completion.checks = comp.checks.filter((v) => typeof v === "string");
939
+ if (Array.isArray(comp.typescript_config_probe))
940
+ base.completion.typescript_config_probe = comp.typescript_config_probe.filter((v) => typeof v === "string");
941
+ if (Array.isArray(comp.eslint_config_probe))
942
+ base.completion.eslint_config_probe = comp.eslint_config_probe.filter((v) => typeof v === "string");
943
+ }
944
+ if (parsed.runtime_image && typeof parsed.runtime_image === "object" && !Array.isArray(parsed.runtime_image)) {
945
+ const runtimeImage = parsed.runtime_image;
946
+ if (runtimeImage.deps && typeof runtimeImage.deps === "object" && !Array.isArray(runtimeImage.deps)) {
947
+ const deps = runtimeImage.deps;
948
+ if (typeof deps.monorepo_install === "boolean") {
949
+ base.runtime_image.deps.monorepo_install = deps.monorepo_install;
950
+ }
951
+ if (typeof deps.hp_next_install === "boolean") {
952
+ base.runtime_image.deps.hp_next_install = deps.hp_next_install;
953
+ }
954
+ }
955
+ if (typeof runtimeImage.plugins_require_binaries === "boolean") {
956
+ base.runtime_image.plugins_require_binaries = runtimeImage.plugins_require_binaries;
957
+ }
958
+ }
959
+ if (parsed.runtime_snapshot && typeof parsed.runtime_snapshot === "object" && !Array.isArray(parsed.runtime_snapshot)) {
960
+ const runtimeSnapshot = parsed.runtime_snapshot;
961
+ if (typeof runtimeSnapshot.enabled === "boolean") {
962
+ base.runtime_snapshot.enabled = runtimeSnapshot.enabled;
963
+ }
964
+ }
965
+ return base;
966
+ }
967
+ function isValidMode(value) {
968
+ return value === "off" || value === "observe" || value === "enforce";
969
+ }
970
+ function isValidRule(value) {
971
+ if (!value || typeof value !== "object" || Array.isArray(value))
972
+ return false;
973
+ const r = value;
974
+ return typeof r.id === "string" && typeof r.category === "string" && r.match != null && typeof r.match === "object";
975
+ }
976
+ function migrateLegacyDeny(deny) {
977
+ const rules = [];
978
+ for (const entry of deny) {
979
+ if (typeof entry.id !== "string")
980
+ continue;
981
+ const match = {};
982
+ if (typeof entry.pattern === "string")
983
+ match.pattern = entry.pattern;
984
+ if (typeof entry.regex === "string")
985
+ match.regex = entry.regex;
986
+ if (!match.pattern && !match.regex)
987
+ continue;
988
+ rules.push({
989
+ id: entry.id,
990
+ category: "command",
991
+ match,
992
+ action: "block",
993
+ ...typeof entry.description === "string" ? { description: entry.description } : {}
994
+ });
995
+ }
996
+ return rules;
997
+ }
998
+ function precompilePolicyRuleRegexes(rules) {
999
+ return rules.map((rule) => {
1000
+ const compiledRegex = rule.match.regex ? compileSafeRegex(rule.match.regex, `rules.${rule.id}.match.regex`, true) : undefined;
1001
+ const compiledUnlessRegex = rule.unless?.regex ? compileSafeRegex(rule.unless.regex, `rules.${rule.id}.unless.regex`, true) : undefined;
1002
+ return {
1003
+ ...rule,
1004
+ ...compiledRegex ? { compiledRegex } : {},
1005
+ ...compiledUnlessRegex ? { compiledUnlessRegex } : {}
1006
+ };
1007
+ });
1008
+ }
1009
+ function getRegexUnsafeReason(pattern) {
1010
+ if (pattern.length > 512) {
1011
+ return "pattern exceeds max safe length (512 chars)";
1012
+ }
1013
+ if (/\\[1-9]/.test(pattern)) {
1014
+ return "pattern uses backreferences";
1015
+ }
1016
+ if (/\((?:[^()\\]|\\.)*[+*](?:[^()\\]|\\.)*\)\s*[*+{]/.test(pattern)) {
1017
+ return "pattern contains nested quantifiers";
1018
+ }
1019
+ if (/\((?:[^()\\]|\\.)*\.\\?[+*](?:[^()\\]|\\.)*\)\s*[*+{]/.test(pattern)) {
1020
+ return "pattern contains nested broad quantifiers";
1021
+ }
1022
+ return null;
1023
+ }
1024
+ function compileSafeRegex(pattern, sourceLabel, logOnFailure) {
1025
+ const cached = compiledRegexCache.get(pattern);
1026
+ if (cached !== undefined) {
1027
+ return cached ?? undefined;
1028
+ }
1029
+ const unsafeReason = getRegexUnsafeReason(pattern);
1030
+ if (unsafeReason) {
1031
+ if (logOnFailure) {
1032
+ console.warn(`[policy] Skipping unsafe regex in ${sourceLabel}: ${unsafeReason}`);
1033
+ }
1034
+ compiledRegexCache.set(pattern, null);
1035
+ return;
1036
+ }
1037
+ try {
1038
+ const compiled = new RegExp(pattern);
1039
+ compiledRegexCache.set(pattern, compiled);
1040
+ return compiled;
1041
+ } catch (error) {
1042
+ if (logOnFailure) {
1043
+ const message = error instanceof Error ? error.message : String(error);
1044
+ console.warn(`[policy] Skipping invalid regex in ${sourceLabel}: ${message}`);
1045
+ }
1046
+ compiledRegexCache.set(pattern, null);
1047
+ return;
1048
+ }
1049
+ }
1050
+ function matchRule(rule, input) {
1051
+ const { match } = rule;
1052
+ if (match.pattern && input.includes(match.pattern)) {
1053
+ return true;
1054
+ }
1055
+ if (match.regex) {
1056
+ const compiled = rule.compiledRegex || compileSafeRegex(match.regex, `rules.${rule.id}.match.regex`, false);
1057
+ if (!compiled) {
1058
+ return false;
1059
+ }
1060
+ try {
1061
+ return compiled.test(input);
1062
+ } catch {
1063
+ return false;
1064
+ }
1065
+ }
1066
+ return false;
1067
+ }
1068
+ function matchRuleUnless(rule, command, taskId) {
1069
+ if (!rule.unless)
1070
+ return false;
1071
+ if (rule.unless.regex) {
1072
+ const compiled = rule.compiledUnlessRegex || compileSafeRegex(rule.unless.regex, `rules.${rule.id}.unless.regex`, false);
1073
+ if (!compiled) {
1074
+ return false;
1075
+ }
1076
+ try {
1077
+ if (compiled.test(command))
1078
+ return true;
1079
+ } catch {}
1080
+ }
1081
+ if (rule.unless.task_in && taskId) {
1082
+ if (rule.unless.task_in.includes(taskId))
1083
+ return true;
1084
+ }
1085
+ return false;
1086
+ }
1087
+ function resolveAction(mode, matched) {
1088
+ if (matched.length === 0)
1089
+ return "allow";
1090
+ if (mode === "off")
1091
+ return "allow";
1092
+ if (mode === "observe")
1093
+ return "warn";
1094
+ return "block";
1095
+ }
1096
+ function resolveAbsolutePath(projectRoot, rawPath) {
1097
+ if (rawPath.startsWith("/"))
1098
+ return resolve9(rawPath);
1099
+ return resolve9(projectRoot, rawPath);
1100
+ }
1101
+ function isHarnessPath(projectRoot, rawPath) {
1102
+ const absPath = resolveAbsolutePath(projectRoot, rawPath);
1103
+ const managedRoots = [
1104
+ resolve9(projectRoot, "rig"),
1105
+ resolve9(projectRoot, ".rig"),
1106
+ resolve9(projectRoot, "artifacts")
1107
+ ];
1108
+ return managedRoots.some((root) => absPath === root || absPath.startsWith(root + "/"));
1109
+ }
1110
+ function isRuntimePath(projectRoot, rawPath, taskWorkspace) {
1111
+ const absPath = resolveAbsolutePath(projectRoot, rawPath);
1112
+ if (taskWorkspace) {
1113
+ const workspaceRigRoot = resolve9(taskWorkspace, ".rig");
1114
+ const workspaceArtifactsRoot = resolve9(taskWorkspace, "artifacts");
1115
+ if (absPath === workspaceRigRoot || absPath.startsWith(workspaceRigRoot + "/") || absPath === workspaceArtifactsRoot || absPath.startsWith(workspaceArtifactsRoot + "/")) {
1116
+ return true;
1117
+ }
1118
+ }
1119
+ const runtimeRoot = resolve9(projectRoot, ".rig/runtime/agents");
1120
+ return absPath === runtimeRoot || absPath.startsWith(runtimeRoot + "/");
1121
+ }
1122
+ function isTestFile(path) {
1123
+ return /\.(test|spec)\.(ts|tsx|js|jsx)$/.test(path) || /\/(__tests__|tests|test)\//.test(path);
1124
+ }
1125
+ function evaluate(context) {
1126
+ const policy = loadPolicy(context.projectRoot);
1127
+ switch (context.evaluation.type) {
1128
+ case "tool-call":
1129
+ return evaluateToolCall(policy, context);
1130
+ case "command":
1131
+ return evaluateCommand(policy, context);
1132
+ case "content-write":
1133
+ return evaluateContent(policy, context);
1134
+ case "file-access":
1135
+ return evaluateScope(policy, context, context.evaluation.file_path, context.evaluation.access);
1136
+ }
1137
+ }
1138
+ function evaluateScope(policy, context, filePath, access) {
1139
+ const allowed = () => ({
1140
+ allowed: true,
1141
+ matchedRules: [],
1142
+ action: "allow",
1143
+ failClosed: false
1144
+ });
1145
+ if (policy.scope.harness_paths_exempt && isHarnessPath(context.projectRoot, filePath)) {
1146
+ return allowed();
1147
+ }
1148
+ if (policy.scope.runtime_paths_exempt && isRuntimePath(context.projectRoot, filePath, context.taskWorkspace)) {
1149
+ return allowed();
1150
+ }
1151
+ if (!context.taskId) {
1152
+ if (access === "write" && policy.scope.fail_closed) {
1153
+ return {
1154
+ allowed: false,
1155
+ matchedRules: [],
1156
+ action: resolveAction(policy.mode, [{ id: "scope:no-task", category: "command", reason: "No active task; fail-closed for write operations" }]),
1157
+ failClosed: true
1158
+ };
1159
+ }
1160
+ return allowed();
1161
+ }
1162
+ const scopes = context.taskScopes || [];
1163
+ if (scopes.length === 0) {
1164
+ return allowed();
1165
+ }
1166
+ if (context.taskWorkspace && context.taskWorkspace !== context.projectRoot && filePath.startsWith("/")) {
1167
+ const absPath = resolve9(filePath);
1168
+ if (!absPath.startsWith(context.taskWorkspace + "/") && !isHarnessPath(context.projectRoot, filePath)) {
1169
+ const reason2 = `Absolute path '${filePath}' is outside task runtime boundary. Allowed root: ${context.taskWorkspace}`;
1170
+ const matched2 = [{ id: "scope:workspace-boundary", category: "command", reason: reason2 }];
1171
+ return {
1172
+ allowed: policy.mode !== "enforce",
1173
+ matchedRules: matched2,
1174
+ action: resolveAction(policy.mode, matched2),
1175
+ failClosed: false
1176
+ };
1177
+ }
1178
+ }
1179
+ const monorepoRoot = context.monorepoRoot || process.env.MONOREPO_ROOT?.trim() || context.taskWorkspace || context.projectRoot;
1180
+ let normalizedPath = filePath;
1181
+ if (context.taskWorkspace && context.taskWorkspace !== context.projectRoot && filePath.startsWith(context.taskWorkspace + "/")) {
1182
+ normalizedPath = filePath.slice(context.taskWorkspace.length + 1);
1183
+ }
1184
+ normalizedPath = normalizePathToScope(context.projectRoot, monorepoRoot, normalizedPath);
1185
+ if (scopeMatches(filePath, scopes) || scopeMatches(normalizedPath, scopes)) {
1186
+ return allowed();
1187
+ }
1188
+ const reason = `File '${filePath}' (normalized: '${normalizedPath}') is outside scope of task ${context.taskId}`;
1189
+ const matched = [{ id: "scope:out-of-scope", category: "command", reason }];
1190
+ return {
1191
+ allowed: policy.mode !== "enforce",
1192
+ matchedRules: matched,
1193
+ action: resolveAction(policy.mode, matched),
1194
+ failClosed: false
1195
+ };
1196
+ }
1197
+ function evaluateCommand(policy, context) {
1198
+ const evaluation = context.evaluation;
1199
+ if (evaluation.type !== "command") {
1200
+ return { allowed: true, matchedRules: [], action: "allow", failClosed: false };
1201
+ }
1202
+ const command = evaluation.command;
1203
+ const matchedRules = [];
1204
+ for (const rule of policy.rules) {
1205
+ if (rule.category !== "command")
1206
+ continue;
1207
+ if (!matchRule(rule, command))
1208
+ continue;
1209
+ if (matchRuleUnless(rule, command, context.taskId))
1210
+ continue;
1211
+ matchedRules.push({
1212
+ id: rule.id,
1213
+ category: rule.category,
1214
+ description: rule.description,
1215
+ reason: rule.description || `Matched rule ${rule.id}`
1216
+ });
1217
+ }
1218
+ const writeTarget = extractWriteTarget(command);
1219
+ if (writeTarget && !/^\/dev\//.test(writeTarget) && !/^\/proc\//.test(writeTarget)) {
1220
+ const scopeResult = evaluateScope(policy, context, writeTarget, "write");
1221
+ if (!scopeResult.allowed || scopeResult.matchedRules.length > 0) {
1222
+ matchedRules.push(...scopeResult.matchedRules);
1223
+ }
1224
+ }
1225
+ const action = resolveAction(policy.mode, matchedRules);
1226
+ return {
1227
+ allowed: action !== "block",
1228
+ matchedRules,
1229
+ action,
1230
+ failClosed: false
1231
+ };
1232
+ }
1233
+ function extractWriteTarget(command) {
1234
+ const redirect = command.match(/>>?\s+([^\s;|&]+)/);
1235
+ if (redirect?.[1])
1236
+ return redirect[1];
1237
+ const tee = command.match(/tee\s+(-a\s+)?([^\s;|&]+)/);
1238
+ if (tee?.[2])
1239
+ return tee[2];
1240
+ return "";
1241
+ }
1242
+ function evaluateContent(policy, context) {
1243
+ const evaluation = context.evaluation;
1244
+ if (evaluation.type !== "content-write") {
1245
+ return { allowed: true, matchedRules: [], action: "allow", failClosed: false };
1246
+ }
1247
+ const { content, file_path } = evaluation;
1248
+ const matchedRules = [];
1249
+ const scopeResult = evaluateScope(policy, context, file_path, "write");
1250
+ if (scopeResult.matchedRules.length > 0) {
1251
+ matchedRules.push(...scopeResult.matchedRules);
1252
+ }
1253
+ for (const rule of policy.rules) {
1254
+ if (rule.category !== "content" && rule.category !== "import" && rule.category !== "test-integrity")
1255
+ continue;
1256
+ if (rule.applies_to === "test-files" && !isTestFile(file_path))
1257
+ continue;
1258
+ if (!matchRule(rule, content))
1259
+ continue;
1260
+ if (matchRuleUnless(rule, content, context.taskId))
1261
+ continue;
1262
+ matchedRules.push({
1263
+ id: rule.id,
1264
+ category: rule.category,
1265
+ description: rule.description,
1266
+ reason: rule.description || `Matched rule ${rule.id}`
1267
+ });
1268
+ }
1269
+ const action = resolveAction(policy.mode, matchedRules);
1270
+ return {
1271
+ allowed: action !== "block",
1272
+ matchedRules,
1273
+ action,
1274
+ failClosed: false
1275
+ };
1276
+ }
1277
+ function evaluateToolCall(policy, context) {
1278
+ const evaluation = context.evaluation;
1279
+ if (evaluation.type !== "tool-call") {
1280
+ return { allowed: true, matchedRules: [], action: "allow", failClosed: false };
1281
+ }
1282
+ const { tool_name, tool_input } = evaluation;
1283
+ const allMatched = [];
1284
+ const filePaths = extractFilePathsFromToolInput(tool_name, tool_input);
1285
+ for (const fp of filePaths) {
1286
+ const access = isWriteTool(tool_name) ? "write" : "read";
1287
+ const scopeResult = evaluateScope(policy, context, fp, access);
1288
+ if (scopeResult.matchedRules.length > 0) {
1289
+ allMatched.push(...scopeResult.matchedRules);
1290
+ }
1291
+ }
1292
+ const content = extractContentFromToolInput(tool_input);
1293
+ if (content) {
1294
+ const filePath = filePaths[0] || "";
1295
+ const contentContext = {
1296
+ ...context,
1297
+ evaluation: { type: "content-write", file_path: filePath, content }
1298
+ };
1299
+ const contentPolicy = loadPolicy(context.projectRoot);
1300
+ for (const rule of contentPolicy.rules) {
1301
+ if (rule.category !== "content" && rule.category !== "import" && rule.category !== "test-integrity")
1302
+ continue;
1303
+ if (rule.applies_to === "test-files" && !isTestFile(filePath))
1304
+ continue;
1305
+ if (!matchRule(rule, content))
1306
+ continue;
1307
+ if (matchRuleUnless(rule, content, context.taskId))
1308
+ continue;
1309
+ allMatched.push({
1310
+ id: rule.id,
1311
+ category: rule.category,
1312
+ description: rule.description,
1313
+ reason: rule.description || `Matched rule ${rule.id}`
1314
+ });
1315
+ }
1316
+ }
1317
+ if (tool_name === "Bash") {
1318
+ const command = String(tool_input.command || tool_input.cmd || "");
1319
+ if (command) {
1320
+ const cmdContext = {
1321
+ ...context,
1322
+ evaluation: { type: "command", command }
1323
+ };
1324
+ const cmdResult = evaluateCommand(policy, cmdContext);
1325
+ if (cmdResult.matchedRules.length > 0) {
1326
+ allMatched.push(...cmdResult.matchedRules);
1327
+ }
1328
+ }
1329
+ }
1330
+ const seen = new Set;
1331
+ const deduplicated = [];
1332
+ for (const rule of allMatched) {
1333
+ if (!seen.has(rule.id)) {
1334
+ seen.add(rule.id);
1335
+ deduplicated.push(rule);
1336
+ }
1337
+ }
1338
+ const action = resolveAction(policy.mode, deduplicated);
1339
+ return {
1340
+ allowed: action !== "block",
1341
+ matchedRules: deduplicated,
1342
+ action,
1343
+ failClosed: false
1344
+ };
1345
+ }
1346
+ function isWriteTool(toolName) {
1347
+ return toolName === "Write" || toolName === "Edit" || toolName === "MultiEdit";
1348
+ }
1349
+ function extractFilePathsFromToolInput(toolName, input) {
1350
+ const paths = [];
1351
+ const add = (value) => {
1352
+ if (typeof value === "string" && value.trim()) {
1353
+ paths.push(value.trim());
1354
+ }
1355
+ };
1356
+ if (toolName === "Read" || toolName === "Write" || toolName === "Edit" || toolName === "MultiEdit") {
1357
+ add(input.file_path);
1358
+ add(input.path);
1359
+ } else if (toolName === "Glob") {
1360
+ add(input.path);
1361
+ } else if (toolName === "Grep") {
1362
+ add(input.path);
1363
+ } else {
1364
+ add(input.file_path);
1365
+ add(input.path);
1366
+ }
1367
+ return paths;
1368
+ }
1369
+ function extractContentFromToolInput(input) {
1370
+ if (typeof input.content === "string")
1371
+ return input.content;
1372
+ if (typeof input.new_string === "string")
1373
+ return input.new_string;
1374
+ return "";
1375
+ }
1376
+ var guardHotPathPrimed = false;
1377
+ function primeGuardHotPaths() {
1378
+ if (guardHotPathPrimed) {
1379
+ return;
1380
+ }
1381
+ guardHotPathPrimed = true;
1382
+ try {
1383
+ optimizeNextInvocation(matchRule);
1384
+ optimizeNextInvocation(evaluate);
1385
+ } catch {}
1386
+ }
1387
+ primeGuardHotPaths();
1388
+
1389
+ // packages/runtime/src/control-plane/runtime/sandbox/backend.ts
1390
+ init_utils();
1391
+ // packages/runtime/src/control-plane/runtime/isolation/runner.ts
1392
+ init_layout();
1393
+ var SNAPSHOT_SIDECAR_READY_TIMEOUT_MS = 1e4;
1394
+ async function startRuntimeSnapshotSidecar(runtime, options = {}) {
1395
+ const instanceId = sanitizeRuntimeRefSegment(options.instanceId?.trim() || runtime.id);
1396
+ const readyFile = resolve10(runtime.stateDir, `runtime-snapshot-sidecar-${instanceId}.ready`);
1397
+ const requestFile = resolve10(runtime.stateDir, `runtime-snapshot-sidecar-${instanceId}.request.json`);
1398
+ rmSync2(readyFile, { force: true });
1399
+ rmSync2(requestFile, { force: true });
1400
+ const sidecarBinary = resolveSnapshotSidecarBinaryPath(runtime.binDir);
1401
+ const useCompiledSidecar = shouldUseCompiledSnapshotSidecar(sidecarBinary);
1402
+ const bunCli = useCompiledSidecar ? null : resolveBunCliInvocation();
1403
+ const command = useCompiledSidecar ? [sidecarBinary] : [bunCli.command, resolveSnapshotSidecarScriptPath()];
1404
+ const proc = Bun.spawn([
1405
+ ...command,
1406
+ "--workspace",
1407
+ runtime.workspaceDir,
1408
+ "--task",
1409
+ runtime.taskId,
1410
+ "--runtime-id",
1411
+ runtime.id,
1412
+ "--instance-id",
1413
+ instanceId,
1414
+ "--ready-file",
1415
+ readyFile,
1416
+ "--request-file",
1417
+ requestFile
1418
+ ], {
1419
+ cwd: runtime.workspaceDir,
1420
+ stdin: "ignore",
1421
+ stdout: "pipe",
1422
+ stderr: "pipe",
1423
+ env: {
1424
+ ...process.env,
1425
+ ...bunCli?.env ?? {}
1426
+ }
1427
+ });
1428
+ const stdoutTextPromise = drainStream(proc.stdout);
1429
+ const stderrTextPromise = drainStream(proc.stderr);
1430
+ await waitForSnapshotSidecarReady(readyFile, proc, stdoutTextPromise, stderrTextPromise);
1431
+ return {
1432
+ cancel: async () => {
1433
+ try {
1434
+ proc.kill("SIGTERM");
1435
+ } catch {}
1436
+ await proc.exited;
1437
+ rmSync2(readyFile, { force: true });
1438
+ rmSync2(requestFile, { force: true });
1439
+ },
1440
+ finalize: async (commandParts, exitCode) => {
1441
+ writeFileSync2(requestFile, `${JSON.stringify({ command: commandParts, exitCode })}
1442
+ `, "utf-8");
1443
+ const [sidecarExitCode, stdout, stderr] = await Promise.all([
1444
+ proc.exited,
1445
+ stdoutTextPromise,
1446
+ stderrTextPromise
1447
+ ]);
1448
+ rmSync2(readyFile, { force: true });
1449
+ rmSync2(requestFile, { force: true });
1450
+ if (sidecarExitCode !== 0) {
1451
+ throw new Error(`snapshot sidecar failed (${sidecarExitCode}): ${stderr || stdout}`);
1452
+ }
1453
+ }
1454
+ };
1455
+ }
1456
+ async function drainStream(stream) {
1457
+ if (!stream)
1458
+ return "";
1459
+ try {
1460
+ return await new Response(stream).text();
1461
+ } catch {
1462
+ return "";
1463
+ }
1464
+ }
1465
+ function resolveSnapshotSidecarScriptPath() {
1466
+ return resolveRuntimeSourceScriptPath("snapshot-sidecar.ts");
1467
+ }
1468
+ function resolveSnapshotSidecarBinaryPath(binDir) {
1469
+ return resolve10(binDir, "snapshot-sidecar");
1470
+ }
1471
+ function shouldUseCompiledSnapshotSidecar(binaryPath) {
1472
+ if (!existsSync6(binaryPath)) {
1473
+ return false;
1474
+ }
1475
+ const preference = process.env.RIG_USE_COMPILED_SNAPSHOT_SIDECAR?.trim().toLowerCase();
1476
+ if (!preference) {
1477
+ return false;
1478
+ }
1479
+ return preference === "1" || preference === "true" || preference === "yes";
1480
+ }
1481
+ function resolveRuntimeSourceScriptPath(fileName) {
1482
+ const hostRoots = [
1483
+ process.env.RIG_HOST_PROJECT_ROOT?.trim(),
1484
+ process.env.PROJECT_RIG_ROOT?.trim()
1485
+ ].filter((value) => Boolean(value));
1486
+ for (const root of hostRoots) {
1487
+ const candidate = resolve10(root, "packages/runtime/src/control-plane/runtime", fileName);
1488
+ if (existsSync6(candidate)) {
1489
+ return candidate;
1490
+ }
1491
+ }
1492
+ return resolve10(import.meta.dir, "..", fileName);
1493
+ }
1494
+ function resolveBunCliInvocation() {
1495
+ if (process.env.RIG_BUN_PATH?.trim()) {
1496
+ return {
1497
+ command: process.env.RIG_BUN_PATH.trim(),
1498
+ env: {}
1499
+ };
1500
+ }
1501
+ const systemBun = Bun.which("bun")?.trim();
1502
+ if (systemBun) {
1503
+ return {
1504
+ command: systemBun,
1505
+ env: {}
1506
+ };
1507
+ }
1508
+ if (process.execPath?.trim()) {
1509
+ return {
1510
+ command: process.execPath,
1511
+ env: { BUN_BE_BUN: "1" }
1512
+ };
1513
+ }
1514
+ return { command: "bun", env: {} };
1515
+ }
1516
+ async function waitForSnapshotSidecarReady(readyFile, proc, stdoutTextPromise, stderrTextPromise) {
1517
+ const deadline = Date.now() + SNAPSHOT_SIDECAR_READY_TIMEOUT_MS;
1518
+ while (Date.now() < deadline) {
1519
+ if (existsSync6(readyFile)) {
1520
+ return;
1521
+ }
1522
+ const exitCode = proc.exitCode;
1523
+ if (exitCode !== null) {
1524
+ const [stderr, stdout] = await Promise.all([stderrTextPromise, stdoutTextPromise]);
1525
+ throw new Error(`snapshot sidecar exited before ready (${exitCode}): ${stderr || stdout}`);
1526
+ }
1527
+ await Bun.sleep(25);
1528
+ }
1529
+ throw new Error(`snapshot sidecar did not become ready within ${SNAPSHOT_SIDECAR_READY_TIMEOUT_MS}ms`);
1530
+ }
1531
+ // packages/runtime/src/control-plane/runtime/task-run-snapshot.ts
1532
+ async function resolveTaskRunSnapshotSidecar(input) {
1533
+ const listRuntimes = input.listRuntimes ?? listAgentRuntimes;
1534
+ const startSidecar = input.startSidecar ?? startRuntimeSnapshotSidecar;
1535
+ const runtimes = await listRuntimes(input.projectRoot);
1536
+ const runtime = runtimes.find((candidate) => candidate.id === input.runtimeId) ?? (input.workspaceDir ? runtimes.find((candidate) => candidate.workspaceDir === input.workspaceDir) : undefined);
1537
+ if (!runtime) {
1538
+ return {
1539
+ sidecar: null,
1540
+ error: `Could not locate runtime metadata for ${input.runtimeId}.`
1541
+ };
1542
+ }
1543
+ try {
1544
+ return {
1545
+ sidecar: await startSidecar(runtime),
1546
+ error: null
1547
+ };
1548
+ } catch (error) {
1549
+ return {
1550
+ sidecar: null,
1551
+ error: error instanceof Error ? error.message : String(error)
1552
+ };
1553
+ }
1554
+ }
1555
+ async function finalizeTaskRunSnapshot(input) {
1556
+ const snapshotSidecar = await (input.snapshotSidecarPromise ?? Promise.resolve(null));
1557
+ if (!snapshotSidecar) {
1558
+ return "unavailable";
1559
+ }
1560
+ if (input.exit.error) {
1561
+ await snapshotSidecar.cancel();
1562
+ return "cancelled";
1563
+ }
1564
+ const exitCode = typeof input.exit.code === "number" ? input.exit.code : 1;
1565
+ try {
1566
+ await snapshotSidecar.finalize(input.latestProviderCommand ?? input.hostAgentCommand, exitCode);
1567
+ return "finalized";
1568
+ } catch (error) {
1569
+ if (exitCode !== 0) {
1570
+ throw error;
1571
+ }
1572
+ return "unavailable";
1573
+ }
1574
+ }
1575
+ export {
1576
+ resolveTaskRunSnapshotSidecar,
1577
+ finalizeTaskRunSnapshot
1578
+ };