@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,268 @@
1
+ // @bun
2
+ // packages/runtime/src/control-plane/repos/mirror/bootstrap.ts
3
+ import { existsSync as existsSync4, mkdirSync as mkdirSync2, realpathSync } from "fs";
4
+ import { resolve as resolve4 } from "path";
5
+
6
+ // packages/runtime/src/control-plane/repos/registry.ts
7
+ var MANAGED_REPOS = new Map;
8
+ function getManagedRepoEntry(repoId) {
9
+ const entry = MANAGED_REPOS.get(repoId);
10
+ if (!entry) {
11
+ throw new Error(`managed repo not registered: ${repoId}. Plugins contribute repos via RigPlugin.contributes.repoSources; ` + `make sure a plugin declares this id and the plugin host has been initialized.`);
12
+ }
13
+ return entry;
14
+ }
15
+ function listManagedRepoEntries() {
16
+ return Array.from(MANAGED_REPOS.values());
17
+ }
18
+
19
+ // packages/runtime/src/control-plane/repos/layout.ts
20
+ import { existsSync as existsSync2 } from "fs";
21
+ import { basename as basename2, dirname as dirname2, join, resolve as resolve2 } from "path";
22
+
23
+ // packages/runtime/src/layout.ts
24
+ import { existsSync } from "fs";
25
+ import { basename, dirname, resolve } from "path";
26
+ function resolveMonorepoRoot(projectRoot) {
27
+ const normalizedProjectRoot = resolve(projectRoot);
28
+ const explicit = process.env.MONOREPO_ROOT?.trim();
29
+ if (explicit) {
30
+ const explicitRoot = resolve(explicit);
31
+ const explicitParent = dirname(explicitRoot);
32
+ if (basename(explicitParent) === ".worktrees") {
33
+ const owner = dirname(explicitParent);
34
+ const ownerHasGit = existsSync(resolve(owner, ".git"));
35
+ const ownerHasTaskConfig = existsSync(resolve(owner, ".rig", "task-config.json"));
36
+ const ownerHasRigConfig = existsSync(resolve(owner, "rig.config.ts"));
37
+ if (ownerHasGit && (ownerHasTaskConfig || ownerHasRigConfig)) {
38
+ return owner;
39
+ }
40
+ throw new Error(`MONOREPO_ROOT points to worktree ${explicitRoot}, but the owner checkout is incomplete at ${owner}.`);
41
+ }
42
+ if (!existsSync(resolve(explicitRoot, ".git"))) {
43
+ throw new Error(`MONOREPO_ROOT points to ${explicitRoot}, but no git checkout was found there.`);
44
+ }
45
+ const hasTaskConfig = existsSync(resolve(explicitRoot, ".rig", "task-config.json"));
46
+ const hasRigConfig = existsSync(resolve(explicitRoot, "rig.config.ts"));
47
+ if (!hasTaskConfig && !hasRigConfig) {
48
+ throw new Error(`MONOREPO_ROOT points to ${explicitRoot}, but neither .rig/task-config.json nor rig.config.ts exists there.`);
49
+ }
50
+ return explicitRoot;
51
+ }
52
+ const projectParent = dirname(normalizedProjectRoot);
53
+ if (basename(projectParent) === ".worktrees") {
54
+ const worktreeOwner = dirname(projectParent);
55
+ const ownerHasGit = existsSync(resolve(worktreeOwner, ".git"));
56
+ const ownerHasTaskConfig = existsSync(resolve(worktreeOwner, ".rig", "task-config.json"));
57
+ const ownerHasRigConfig = existsSync(resolve(worktreeOwner, "rig.config.ts"));
58
+ if (ownerHasGit && (ownerHasTaskConfig || ownerHasRigConfig)) {
59
+ return worktreeOwner;
60
+ }
61
+ }
62
+ return normalizedProjectRoot;
63
+ }
64
+
65
+ // packages/runtime/src/control-plane/repos/layout.ts
66
+ function resolveRepoStateDir(projectRoot) {
67
+ const normalizedProjectRoot = resolve2(projectRoot);
68
+ const projectParent = dirname2(normalizedProjectRoot);
69
+ if (basename2(projectParent) === ".worktrees") {
70
+ const ownerRoot = dirname2(projectParent);
71
+ const ownerHasRepoMarkers = existsSync2(resolve2(ownerRoot, ".git")) || existsSync2(resolve2(ownerRoot, ".rig", "state"));
72
+ if (ownerHasRepoMarkers) {
73
+ return resolve2(ownerRoot, ".rig", "state");
74
+ }
75
+ }
76
+ return resolve2(projectRoot, ".rig", "state");
77
+ }
78
+ function resolveManagedRepoLayout(projectRoot, repoId) {
79
+ const normalizedProjectRoot = resolve2(projectRoot);
80
+ const entry = getManagedRepoEntry(repoId);
81
+ const stateDir = resolveRepoStateDir(normalizedProjectRoot);
82
+ const metadataRelativePath = join("repos", entry.id);
83
+ const metadataRoot = resolve2(stateDir, metadataRelativePath);
84
+ const runtimeWorkspace = process.env.RIG_TASK_WORKSPACE?.trim();
85
+ const runsInsideTaskWorktree = runtimeWorkspace && resolve2(runtimeWorkspace) === normalizedProjectRoot || basename2(dirname2(normalizedProjectRoot)) === ".worktrees";
86
+ const isPrimaryManagedRepo = listManagedRepoEntries()[0]?.id === repoId;
87
+ const checkoutRoot = isPrimaryManagedRepo && runsInsideTaskWorktree ? resolveMonorepoRoot(normalizedProjectRoot) : entry.checkoutEnvVar && process.env[entry.checkoutEnvVar]?.trim() ? resolve2(process.env[entry.checkoutEnvVar].trim()) : resolve2(normalizedProjectRoot, entry.alias);
88
+ return {
89
+ projectRoot: normalizedProjectRoot,
90
+ repoId: entry.id,
91
+ alias: entry.alias,
92
+ defaultBranch: entry.defaultBranch,
93
+ remoteUrl: entry.remoteEnvVar && process.env[entry.remoteEnvVar]?.trim() ? process.env[entry.remoteEnvVar].trim() : entry.defaultRemoteUrl,
94
+ checkoutRoot,
95
+ worktreesRoot: resolve2(checkoutRoot, ".worktrees"),
96
+ stateDir,
97
+ metadataRoot,
98
+ metadataRelativePath,
99
+ mirrorRoot: resolve2(metadataRoot, "mirror.git"),
100
+ mirrorStatePath: resolve2(metadataRoot, "mirror-state.json"),
101
+ mirrorStateRelativePath: join(metadataRelativePath, "mirror-state.json")
102
+ };
103
+ }
104
+
105
+ // packages/runtime/src/control-plane/authority-files.ts
106
+ import { existsSync as existsSync3, mkdirSync, readFileSync, writeFileSync, appendFileSync, copyFileSync, statSync, readdirSync, chmodSync } from "fs";
107
+ import { dirname as dirname3, join as join2, relative, resolve as resolve3 } from "path";
108
+ import { parse as parseToml, stringify as stringifyToml } from "smol-toml";
109
+ function resolveAuthorityProjectStateDir(projectRoot) {
110
+ const explicit = process.env.RIG_STATE_DIR?.trim();
111
+ if (explicit) {
112
+ return resolve3(explicit);
113
+ }
114
+ return resolve3(resolve3(projectRoot), ".rig", "state");
115
+ }
116
+ function readJsonAtPath(path, fallback) {
117
+ if (!existsSync3(path)) {
118
+ return fallback;
119
+ }
120
+ try {
121
+ return JSON.parse(readFileSync(path, "utf-8"));
122
+ } catch {
123
+ return fallback;
124
+ }
125
+ }
126
+ function writeJsonAtPath(path, value) {
127
+ mkdirSync(dirname3(path), { recursive: true });
128
+ writeFileSync(path, `${JSON.stringify(value, null, 2)}
129
+ `, "utf8");
130
+ return path;
131
+ }
132
+ function readAuthorityProjectStateJson(projectRoot, relativePath, fallback) {
133
+ return readJsonAtPath(resolve3(resolveAuthorityProjectStateDir(projectRoot), relativePath), fallback);
134
+ }
135
+ function writeAuthorityProjectStateJson(projectRoot, relativePath, value) {
136
+ return writeJsonAtPath(resolve3(resolveAuthorityProjectStateDir(projectRoot), relativePath), value);
137
+ }
138
+
139
+ // packages/runtime/src/control-plane/repos/mirror/state.ts
140
+ var STATE_VERSION = 1;
141
+ function defaultMirrorState(projectRoot, repoId) {
142
+ const layout = resolveManagedRepoLayout(projectRoot, repoId);
143
+ return {
144
+ version: STATE_VERSION,
145
+ repoId,
146
+ remoteUrl: layout.remoteUrl,
147
+ defaultBranch: layout.defaultBranch
148
+ };
149
+ }
150
+ function readManagedRepoMirrorState(projectRoot, repoId) {
151
+ const layout = resolveManagedRepoLayout(projectRoot, repoId);
152
+ return readAuthorityProjectStateJson(projectRoot, layout.mirrorStateRelativePath, null);
153
+ }
154
+ function writeManagedRepoMirrorState(projectRoot, repoId, patch) {
155
+ const current = readManagedRepoMirrorState(projectRoot, repoId) || defaultMirrorState(projectRoot, repoId);
156
+ const next = {
157
+ ...current,
158
+ ...patch,
159
+ version: STATE_VERSION,
160
+ repoId
161
+ };
162
+ const layout = resolveManagedRepoLayout(projectRoot, repoId);
163
+ writeAuthorityProjectStateJson(projectRoot, layout.mirrorStateRelativePath, next);
164
+ return next;
165
+ }
166
+
167
+ // packages/runtime/src/control-plane/repos/mirror/bootstrap.ts
168
+ function nowIso() {
169
+ return new Date().toISOString();
170
+ }
171
+ function runGit(command, cwd) {
172
+ const result = Bun.spawnSync(command, {
173
+ cwd,
174
+ stdout: "pipe",
175
+ stderr: "pipe",
176
+ env: process.env
177
+ });
178
+ return {
179
+ exitCode: result.exitCode,
180
+ stdout: result.stdout.toString(),
181
+ stderr: result.stderr.toString()
182
+ };
183
+ }
184
+ function ensureGitSuccess(result, command) {
185
+ if (result.exitCode !== 0) {
186
+ throw new Error(result.stderr || result.stdout || `git command failed: ${command.join(" ")}`);
187
+ }
188
+ }
189
+ function isUsableRemoteUrl(candidate, layout) {
190
+ return candidate.length > 0 && candidate !== layout.mirrorRoot && candidate !== layout.checkoutRoot;
191
+ }
192
+ function sameExistingPath(left, right) {
193
+ try {
194
+ return realpathSync(left) === realpathSync(right);
195
+ } catch {
196
+ return resolve4(left) === resolve4(right);
197
+ }
198
+ }
199
+ function repoLooksUsable(repoRoot, projectRoot) {
200
+ const probe = runGit(["git", "-C", repoRoot, "rev-parse", "--show-toplevel"], projectRoot);
201
+ return probe.exitCode === 0 && sameExistingPath(probe.stdout.trim(), repoRoot);
202
+ }
203
+ function checkoutLooksUsable(layout) {
204
+ return repoLooksUsable(layout.checkoutRoot, layout.projectRoot);
205
+ }
206
+ function resolveMirrorRemoteUrl(layout) {
207
+ const entry = getManagedRepoEntry(layout.repoId);
208
+ const explicit = entry.remoteEnvVar ? process.env[entry.remoteEnvVar]?.trim() : "";
209
+ if (explicit) {
210
+ return explicit;
211
+ }
212
+ const persisted = readManagedRepoMirrorState(layout.projectRoot, layout.repoId)?.remoteUrl?.trim();
213
+ if (persisted && isUsableRemoteUrl(persisted, layout)) {
214
+ return persisted;
215
+ }
216
+ const mirrorOrigin = runGit(["git", "--git-dir", layout.mirrorRoot, "remote", "get-url", "origin"], layout.projectRoot);
217
+ if (mirrorOrigin.exitCode === 0) {
218
+ const currentOrigin = mirrorOrigin.stdout.trim();
219
+ if (isUsableRemoteUrl(currentOrigin, layout)) {
220
+ return currentOrigin;
221
+ }
222
+ }
223
+ if (repoLooksUsable(layout.projectRoot, layout.projectRoot)) {
224
+ const projectOrigin = runGit(["git", "-C", layout.projectRoot, "remote", "get-url", "origin"], layout.projectRoot);
225
+ if (projectOrigin.exitCode === 0) {
226
+ const currentOrigin = projectOrigin.stdout.trim();
227
+ if (isUsableRemoteUrl(currentOrigin, layout)) {
228
+ return currentOrigin;
229
+ }
230
+ }
231
+ }
232
+ if (existsSync4(resolve4(layout.checkoutRoot, ".git")) && checkoutLooksUsable(layout)) {
233
+ const checkoutOrigin = runGit(["git", "-C", layout.checkoutRoot, "remote", "get-url", "origin"], layout.projectRoot);
234
+ if (checkoutOrigin.exitCode === 0) {
235
+ const currentOrigin = checkoutOrigin.stdout.trim();
236
+ if (isUsableRemoteUrl(currentOrigin, layout)) {
237
+ return currentOrigin;
238
+ }
239
+ }
240
+ }
241
+ return layout.remoteUrl;
242
+ }
243
+ function ensureManagedRepoMirror(projectRoot, repoId) {
244
+ const layout = resolveManagedRepoLayout(projectRoot, repoId);
245
+ mkdirSync2(layout.metadataRoot, { recursive: true });
246
+ const remoteUrl = resolveMirrorRemoteUrl(layout);
247
+ if (!existsSync4(resolve4(layout.mirrorRoot, "HEAD"))) {
248
+ ensureGitSuccess(runGit(["git", "init", "--bare", layout.mirrorRoot], layout.projectRoot), ["git", "init", "--bare", layout.mirrorRoot]);
249
+ }
250
+ const getOrigin = runGit(["git", "--git-dir", layout.mirrorRoot, "remote", "get-url", "origin"], layout.projectRoot);
251
+ if (getOrigin.exitCode === 0) {
252
+ const currentOrigin = getOrigin.stdout.trim();
253
+ if (currentOrigin !== remoteUrl) {
254
+ ensureGitSuccess(runGit(["git", "--git-dir", layout.mirrorRoot, "remote", "set-url", "origin", remoteUrl], layout.projectRoot), ["git", "--git-dir", layout.mirrorRoot, "remote", "set-url", "origin", remoteUrl]);
255
+ }
256
+ } else {
257
+ ensureGitSuccess(runGit(["git", "--git-dir", layout.mirrorRoot, "remote", "add", "origin", remoteUrl], layout.projectRoot), ["git", "--git-dir", layout.mirrorRoot, "remote", "add", "origin", remoteUrl]);
258
+ }
259
+ writeManagedRepoMirrorState(projectRoot, repoId, {
260
+ remoteUrl,
261
+ defaultBranch: layout.defaultBranch,
262
+ initializedAt: nowIso()
263
+ });
264
+ return layout;
265
+ }
266
+ export {
267
+ ensureManagedRepoMirror
268
+ };
@@ -0,0 +1,398 @@
1
+ // @bun
2
+ // packages/runtime/src/control-plane/repos/mirror/refresh.ts
3
+ import { existsSync as existsSync5, mkdirSync as mkdirSync3, realpathSync as realpathSync2, rmSync } from "fs";
4
+ import { resolve as resolve5 } from "path";
5
+
6
+ // packages/runtime/src/control-plane/repos/mirror/bootstrap.ts
7
+ import { existsSync as existsSync4, mkdirSync as mkdirSync2, realpathSync } from "fs";
8
+ import { resolve as resolve4 } from "path";
9
+
10
+ // packages/runtime/src/control-plane/repos/registry.ts
11
+ var MANAGED_REPOS = new Map;
12
+ function getManagedRepoEntry(repoId) {
13
+ const entry = MANAGED_REPOS.get(repoId);
14
+ if (!entry) {
15
+ throw new Error(`managed repo not registered: ${repoId}. Plugins contribute repos via RigPlugin.contributes.repoSources; ` + `make sure a plugin declares this id and the plugin host has been initialized.`);
16
+ }
17
+ return entry;
18
+ }
19
+ function listManagedRepoEntries() {
20
+ return Array.from(MANAGED_REPOS.values());
21
+ }
22
+
23
+ // packages/runtime/src/control-plane/repos/layout.ts
24
+ import { existsSync as existsSync2 } from "fs";
25
+ import { basename as basename2, dirname as dirname2, join, resolve as resolve2 } from "path";
26
+
27
+ // packages/runtime/src/layout.ts
28
+ import { existsSync } from "fs";
29
+ import { basename, dirname, resolve } from "path";
30
+ function resolveMonorepoRoot(projectRoot) {
31
+ const normalizedProjectRoot = resolve(projectRoot);
32
+ const explicit = process.env.MONOREPO_ROOT?.trim();
33
+ if (explicit) {
34
+ const explicitRoot = resolve(explicit);
35
+ const explicitParent = dirname(explicitRoot);
36
+ if (basename(explicitParent) === ".worktrees") {
37
+ const owner = dirname(explicitParent);
38
+ const ownerHasGit = existsSync(resolve(owner, ".git"));
39
+ const ownerHasTaskConfig = existsSync(resolve(owner, ".rig", "task-config.json"));
40
+ const ownerHasRigConfig = existsSync(resolve(owner, "rig.config.ts"));
41
+ if (ownerHasGit && (ownerHasTaskConfig || ownerHasRigConfig)) {
42
+ return owner;
43
+ }
44
+ throw new Error(`MONOREPO_ROOT points to worktree ${explicitRoot}, but the owner checkout is incomplete at ${owner}.`);
45
+ }
46
+ if (!existsSync(resolve(explicitRoot, ".git"))) {
47
+ throw new Error(`MONOREPO_ROOT points to ${explicitRoot}, but no git checkout was found there.`);
48
+ }
49
+ const hasTaskConfig = existsSync(resolve(explicitRoot, ".rig", "task-config.json"));
50
+ const hasRigConfig = existsSync(resolve(explicitRoot, "rig.config.ts"));
51
+ if (!hasTaskConfig && !hasRigConfig) {
52
+ throw new Error(`MONOREPO_ROOT points to ${explicitRoot}, but neither .rig/task-config.json nor rig.config.ts exists there.`);
53
+ }
54
+ return explicitRoot;
55
+ }
56
+ const projectParent = dirname(normalizedProjectRoot);
57
+ if (basename(projectParent) === ".worktrees") {
58
+ const worktreeOwner = dirname(projectParent);
59
+ const ownerHasGit = existsSync(resolve(worktreeOwner, ".git"));
60
+ const ownerHasTaskConfig = existsSync(resolve(worktreeOwner, ".rig", "task-config.json"));
61
+ const ownerHasRigConfig = existsSync(resolve(worktreeOwner, "rig.config.ts"));
62
+ if (ownerHasGit && (ownerHasTaskConfig || ownerHasRigConfig)) {
63
+ return worktreeOwner;
64
+ }
65
+ }
66
+ return normalizedProjectRoot;
67
+ }
68
+
69
+ // packages/runtime/src/control-plane/repos/layout.ts
70
+ function resolveRepoStateDir(projectRoot) {
71
+ const normalizedProjectRoot = resolve2(projectRoot);
72
+ const projectParent = dirname2(normalizedProjectRoot);
73
+ if (basename2(projectParent) === ".worktrees") {
74
+ const ownerRoot = dirname2(projectParent);
75
+ const ownerHasRepoMarkers = existsSync2(resolve2(ownerRoot, ".git")) || existsSync2(resolve2(ownerRoot, ".rig", "state"));
76
+ if (ownerHasRepoMarkers) {
77
+ return resolve2(ownerRoot, ".rig", "state");
78
+ }
79
+ }
80
+ return resolve2(projectRoot, ".rig", "state");
81
+ }
82
+ function resolveManagedRepoLayout(projectRoot, repoId) {
83
+ const normalizedProjectRoot = resolve2(projectRoot);
84
+ const entry = getManagedRepoEntry(repoId);
85
+ const stateDir = resolveRepoStateDir(normalizedProjectRoot);
86
+ const metadataRelativePath = join("repos", entry.id);
87
+ const metadataRoot = resolve2(stateDir, metadataRelativePath);
88
+ const runtimeWorkspace = process.env.RIG_TASK_WORKSPACE?.trim();
89
+ const runsInsideTaskWorktree = runtimeWorkspace && resolve2(runtimeWorkspace) === normalizedProjectRoot || basename2(dirname2(normalizedProjectRoot)) === ".worktrees";
90
+ const isPrimaryManagedRepo = listManagedRepoEntries()[0]?.id === repoId;
91
+ const checkoutRoot = isPrimaryManagedRepo && runsInsideTaskWorktree ? resolveMonorepoRoot(normalizedProjectRoot) : entry.checkoutEnvVar && process.env[entry.checkoutEnvVar]?.trim() ? resolve2(process.env[entry.checkoutEnvVar].trim()) : resolve2(normalizedProjectRoot, entry.alias);
92
+ return {
93
+ projectRoot: normalizedProjectRoot,
94
+ repoId: entry.id,
95
+ alias: entry.alias,
96
+ defaultBranch: entry.defaultBranch,
97
+ remoteUrl: entry.remoteEnvVar && process.env[entry.remoteEnvVar]?.trim() ? process.env[entry.remoteEnvVar].trim() : entry.defaultRemoteUrl,
98
+ checkoutRoot,
99
+ worktreesRoot: resolve2(checkoutRoot, ".worktrees"),
100
+ stateDir,
101
+ metadataRoot,
102
+ metadataRelativePath,
103
+ mirrorRoot: resolve2(metadataRoot, "mirror.git"),
104
+ mirrorStatePath: resolve2(metadataRoot, "mirror-state.json"),
105
+ mirrorStateRelativePath: join(metadataRelativePath, "mirror-state.json")
106
+ };
107
+ }
108
+
109
+ // packages/runtime/src/control-plane/authority-files.ts
110
+ import { existsSync as existsSync3, mkdirSync, readFileSync, writeFileSync, appendFileSync, copyFileSync, statSync, readdirSync, chmodSync } from "fs";
111
+ import { dirname as dirname3, join as join2, relative, resolve as resolve3 } from "path";
112
+ import { parse as parseToml, stringify as stringifyToml } from "smol-toml";
113
+ function resolveAuthorityProjectStateDir(projectRoot) {
114
+ const explicit = process.env.RIG_STATE_DIR?.trim();
115
+ if (explicit) {
116
+ return resolve3(explicit);
117
+ }
118
+ return resolve3(resolve3(projectRoot), ".rig", "state");
119
+ }
120
+ function readJsonAtPath(path, fallback) {
121
+ if (!existsSync3(path)) {
122
+ return fallback;
123
+ }
124
+ try {
125
+ return JSON.parse(readFileSync(path, "utf-8"));
126
+ } catch {
127
+ return fallback;
128
+ }
129
+ }
130
+ function writeJsonAtPath(path, value) {
131
+ mkdirSync(dirname3(path), { recursive: true });
132
+ writeFileSync(path, `${JSON.stringify(value, null, 2)}
133
+ `, "utf8");
134
+ return path;
135
+ }
136
+ function readAuthorityProjectStateJson(projectRoot, relativePath, fallback) {
137
+ return readJsonAtPath(resolve3(resolveAuthorityProjectStateDir(projectRoot), relativePath), fallback);
138
+ }
139
+ function writeAuthorityProjectStateJson(projectRoot, relativePath, value) {
140
+ return writeJsonAtPath(resolve3(resolveAuthorityProjectStateDir(projectRoot), relativePath), value);
141
+ }
142
+
143
+ // packages/runtime/src/control-plane/repos/mirror/state.ts
144
+ var STATE_VERSION = 1;
145
+ function defaultMirrorState(projectRoot, repoId) {
146
+ const layout = resolveManagedRepoLayout(projectRoot, repoId);
147
+ return {
148
+ version: STATE_VERSION,
149
+ repoId,
150
+ remoteUrl: layout.remoteUrl,
151
+ defaultBranch: layout.defaultBranch
152
+ };
153
+ }
154
+ function readManagedRepoMirrorState(projectRoot, repoId) {
155
+ const layout = resolveManagedRepoLayout(projectRoot, repoId);
156
+ return readAuthorityProjectStateJson(projectRoot, layout.mirrorStateRelativePath, null);
157
+ }
158
+ function writeManagedRepoMirrorState(projectRoot, repoId, patch) {
159
+ const current = readManagedRepoMirrorState(projectRoot, repoId) || defaultMirrorState(projectRoot, repoId);
160
+ const next = {
161
+ ...current,
162
+ ...patch,
163
+ version: STATE_VERSION,
164
+ repoId
165
+ };
166
+ const layout = resolveManagedRepoLayout(projectRoot, repoId);
167
+ writeAuthorityProjectStateJson(projectRoot, layout.mirrorStateRelativePath, next);
168
+ return next;
169
+ }
170
+
171
+ // packages/runtime/src/control-plane/repos/mirror/bootstrap.ts
172
+ function nowIso() {
173
+ return new Date().toISOString();
174
+ }
175
+ function runGit(command, cwd) {
176
+ const result = Bun.spawnSync(command, {
177
+ cwd,
178
+ stdout: "pipe",
179
+ stderr: "pipe",
180
+ env: process.env
181
+ });
182
+ return {
183
+ exitCode: result.exitCode,
184
+ stdout: result.stdout.toString(),
185
+ stderr: result.stderr.toString()
186
+ };
187
+ }
188
+ function ensureGitSuccess(result, command) {
189
+ if (result.exitCode !== 0) {
190
+ throw new Error(result.stderr || result.stdout || `git command failed: ${command.join(" ")}`);
191
+ }
192
+ }
193
+ function isUsableRemoteUrl(candidate, layout) {
194
+ return candidate.length > 0 && candidate !== layout.mirrorRoot && candidate !== layout.checkoutRoot;
195
+ }
196
+ function sameExistingPath(left, right) {
197
+ try {
198
+ return realpathSync(left) === realpathSync(right);
199
+ } catch {
200
+ return resolve4(left) === resolve4(right);
201
+ }
202
+ }
203
+ function repoLooksUsable(repoRoot, projectRoot) {
204
+ const probe = runGit(["git", "-C", repoRoot, "rev-parse", "--show-toplevel"], projectRoot);
205
+ return probe.exitCode === 0 && sameExistingPath(probe.stdout.trim(), repoRoot);
206
+ }
207
+ function checkoutLooksUsable(layout) {
208
+ return repoLooksUsable(layout.checkoutRoot, layout.projectRoot);
209
+ }
210
+ function resolveMirrorRemoteUrl(layout) {
211
+ const entry = getManagedRepoEntry(layout.repoId);
212
+ const explicit = entry.remoteEnvVar ? process.env[entry.remoteEnvVar]?.trim() : "";
213
+ if (explicit) {
214
+ return explicit;
215
+ }
216
+ const persisted = readManagedRepoMirrorState(layout.projectRoot, layout.repoId)?.remoteUrl?.trim();
217
+ if (persisted && isUsableRemoteUrl(persisted, layout)) {
218
+ return persisted;
219
+ }
220
+ const mirrorOrigin = runGit(["git", "--git-dir", layout.mirrorRoot, "remote", "get-url", "origin"], layout.projectRoot);
221
+ if (mirrorOrigin.exitCode === 0) {
222
+ const currentOrigin = mirrorOrigin.stdout.trim();
223
+ if (isUsableRemoteUrl(currentOrigin, layout)) {
224
+ return currentOrigin;
225
+ }
226
+ }
227
+ if (repoLooksUsable(layout.projectRoot, layout.projectRoot)) {
228
+ const projectOrigin = runGit(["git", "-C", layout.projectRoot, "remote", "get-url", "origin"], layout.projectRoot);
229
+ if (projectOrigin.exitCode === 0) {
230
+ const currentOrigin = projectOrigin.stdout.trim();
231
+ if (isUsableRemoteUrl(currentOrigin, layout)) {
232
+ return currentOrigin;
233
+ }
234
+ }
235
+ }
236
+ if (existsSync4(resolve4(layout.checkoutRoot, ".git")) && checkoutLooksUsable(layout)) {
237
+ const checkoutOrigin = runGit(["git", "-C", layout.checkoutRoot, "remote", "get-url", "origin"], layout.projectRoot);
238
+ if (checkoutOrigin.exitCode === 0) {
239
+ const currentOrigin = checkoutOrigin.stdout.trim();
240
+ if (isUsableRemoteUrl(currentOrigin, layout)) {
241
+ return currentOrigin;
242
+ }
243
+ }
244
+ }
245
+ return layout.remoteUrl;
246
+ }
247
+ function ensureManagedRepoMirror(projectRoot, repoId) {
248
+ const layout = resolveManagedRepoLayout(projectRoot, repoId);
249
+ mkdirSync2(layout.metadataRoot, { recursive: true });
250
+ const remoteUrl = resolveMirrorRemoteUrl(layout);
251
+ if (!existsSync4(resolve4(layout.mirrorRoot, "HEAD"))) {
252
+ ensureGitSuccess(runGit(["git", "init", "--bare", layout.mirrorRoot], layout.projectRoot), ["git", "init", "--bare", layout.mirrorRoot]);
253
+ }
254
+ const getOrigin = runGit(["git", "--git-dir", layout.mirrorRoot, "remote", "get-url", "origin"], layout.projectRoot);
255
+ if (getOrigin.exitCode === 0) {
256
+ const currentOrigin = getOrigin.stdout.trim();
257
+ if (currentOrigin !== remoteUrl) {
258
+ ensureGitSuccess(runGit(["git", "--git-dir", layout.mirrorRoot, "remote", "set-url", "origin", remoteUrl], layout.projectRoot), ["git", "--git-dir", layout.mirrorRoot, "remote", "set-url", "origin", remoteUrl]);
259
+ }
260
+ } else {
261
+ ensureGitSuccess(runGit(["git", "--git-dir", layout.mirrorRoot, "remote", "add", "origin", remoteUrl], layout.projectRoot), ["git", "--git-dir", layout.mirrorRoot, "remote", "add", "origin", remoteUrl]);
262
+ }
263
+ writeManagedRepoMirrorState(projectRoot, repoId, {
264
+ remoteUrl,
265
+ defaultBranch: layout.defaultBranch,
266
+ initializedAt: nowIso()
267
+ });
268
+ return layout;
269
+ }
270
+
271
+ // packages/runtime/src/control-plane/repos/mirror/refresh.ts
272
+ function nowIso2() {
273
+ return new Date().toISOString();
274
+ }
275
+ function runGit2(command, cwd) {
276
+ const result = Bun.spawnSync(command, {
277
+ cwd,
278
+ stdout: "pipe",
279
+ stderr: "pipe",
280
+ env: process.env
281
+ });
282
+ return {
283
+ exitCode: result.exitCode,
284
+ stdout: result.stdout.toString(),
285
+ stderr: result.stderr.toString()
286
+ };
287
+ }
288
+ function ensureGitSuccess2(result, command) {
289
+ if (result.exitCode !== 0) {
290
+ throw new Error(result.stderr || result.stdout || `git command failed: ${command.join(" ")}`);
291
+ }
292
+ return result.stdout.trim();
293
+ }
294
+ function sameExistingPath2(left, right) {
295
+ try {
296
+ return realpathSync2(left) === realpathSync2(right);
297
+ } catch {
298
+ return resolve5(left) === resolve5(right);
299
+ }
300
+ }
301
+ function ensureMirrorHead(layout) {
302
+ ensureGitSuccess2(runGit2([
303
+ "git",
304
+ "--git-dir",
305
+ layout.mirrorRoot,
306
+ "fetch",
307
+ "--prune",
308
+ "origin",
309
+ "+refs/heads/*:refs/heads/*",
310
+ "+refs/tags/*:refs/tags/*"
311
+ ], layout.projectRoot), [
312
+ "git",
313
+ "--git-dir",
314
+ layout.mirrorRoot,
315
+ "fetch",
316
+ "--prune",
317
+ "origin",
318
+ "+refs/heads/*:refs/heads/*",
319
+ "+refs/tags/*:refs/tags/*"
320
+ ]);
321
+ const headRef = `refs/heads/${layout.defaultBranch}`;
322
+ const headCommit = ensureGitSuccess2(runGit2(["git", "--git-dir", layout.mirrorRoot, "rev-parse", headRef], layout.projectRoot), ["git", "--git-dir", layout.mirrorRoot, "rev-parse", headRef]);
323
+ const remoteUrl = ensureGitSuccess2(runGit2(["git", "--git-dir", layout.mirrorRoot, "remote", "get-url", "origin"], layout.projectRoot), ["git", "--git-dir", layout.mirrorRoot, "remote", "get-url", "origin"]);
324
+ ensureGitSuccess2(runGit2(["git", "--git-dir", layout.mirrorRoot, "symbolic-ref", "HEAD", headRef], layout.projectRoot), ["git", "--git-dir", layout.mirrorRoot, "symbolic-ref", "HEAD", headRef]);
325
+ writeManagedRepoMirrorState(layout.projectRoot, layout.repoId, {
326
+ remoteUrl,
327
+ defaultBranch: layout.defaultBranch,
328
+ lastSyncedAt: nowIso2(),
329
+ headRef,
330
+ headCommit
331
+ });
332
+ return headCommit;
333
+ }
334
+ function refreshManagedRepoMirror(projectRoot, repoId) {
335
+ const layout = ensureManagedRepoMirror(projectRoot, repoId);
336
+ const headCommit = ensureMirrorHead(layout);
337
+ return { layout, headCommit };
338
+ }
339
+ function checkoutLooksUsable2(layout) {
340
+ const probe = runGit2(["git", "-C", layout.checkoutRoot, "rev-parse", "--show-toplevel"], layout.projectRoot);
341
+ return probe.exitCode === 0 && sameExistingPath2(probe.stdout.trim(), layout.checkoutRoot);
342
+ }
343
+ function ensureCheckoutFromMirror(layout) {
344
+ mkdirSync3(resolve5(layout.checkoutRoot, ".."), { recursive: true });
345
+ const gitPath = resolve5(layout.checkoutRoot, ".git");
346
+ if (existsSync5(layout.checkoutRoot) && (!existsSync5(gitPath) || !checkoutLooksUsable2(layout))) {
347
+ rmSync(layout.checkoutRoot, { recursive: true, force: true });
348
+ }
349
+ if (!existsSync5(gitPath)) {
350
+ ensureGitSuccess2(runGit2(["git", "clone", layout.mirrorRoot, layout.checkoutRoot], layout.projectRoot), ["git", "clone", layout.mirrorRoot, layout.checkoutRoot]);
351
+ }
352
+ const getOrigin = runGit2(["git", "-C", layout.checkoutRoot, "remote", "get-url", "origin"], layout.projectRoot);
353
+ if (getOrigin.exitCode === 0) {
354
+ const currentOrigin = getOrigin.stdout.trim();
355
+ if (currentOrigin !== layout.mirrorRoot) {
356
+ ensureGitSuccess2(runGit2(["git", "-C", layout.checkoutRoot, "remote", "set-url", "origin", layout.mirrorRoot], layout.projectRoot), ["git", "-C", layout.checkoutRoot, "remote", "set-url", "origin", layout.mirrorRoot]);
357
+ }
358
+ } else {
359
+ ensureGitSuccess2(runGit2(["git", "-C", layout.checkoutRoot, "remote", "add", "origin", layout.mirrorRoot], layout.projectRoot), ["git", "-C", layout.checkoutRoot, "remote", "add", "origin", layout.mirrorRoot]);
360
+ }
361
+ ensureGitSuccess2(runGit2(["git", "-C", layout.checkoutRoot, "fetch", "origin", layout.defaultBranch], layout.projectRoot), ["git", "-C", layout.checkoutRoot, "fetch", "origin", layout.defaultBranch]);
362
+ ensureGitSuccess2(runGit2(["git", "-C", layout.checkoutRoot, "reset", "--hard"], layout.projectRoot), ["git", "-C", layout.checkoutRoot, "reset", "--hard"]);
363
+ ensureGitSuccess2(runGit2(["git", "-C", layout.checkoutRoot, "clean", "-fd"], layout.projectRoot), ["git", "-C", layout.checkoutRoot, "clean", "-fd"]);
364
+ ensureGitSuccess2(runGit2([
365
+ "git",
366
+ "-C",
367
+ layout.checkoutRoot,
368
+ "checkout",
369
+ "--force",
370
+ "-B",
371
+ layout.defaultBranch,
372
+ `origin/${layout.defaultBranch}`
373
+ ], layout.projectRoot), [
374
+ "git",
375
+ "-C",
376
+ layout.checkoutRoot,
377
+ "checkout",
378
+ "--force",
379
+ "-B",
380
+ layout.defaultBranch,
381
+ `origin/${layout.defaultBranch}`
382
+ ]);
383
+ ensureGitSuccess2(runGit2(["git", "-C", layout.checkoutRoot, "reset", "--hard", `origin/${layout.defaultBranch}`], layout.projectRoot), ["git", "-C", layout.checkoutRoot, "reset", "--hard", `origin/${layout.defaultBranch}`]);
384
+ ensureGitSuccess2(runGit2(["git", "-C", layout.checkoutRoot, "clean", "-fd"], layout.projectRoot), ["git", "-C", layout.checkoutRoot, "clean", "-fd"]);
385
+ return ensureGitSuccess2(runGit2(["git", "-C", layout.checkoutRoot, "rev-parse", "HEAD"], layout.projectRoot), ["git", "-C", layout.checkoutRoot, "rev-parse", "HEAD"]);
386
+ }
387
+ function syncManagedRepo(projectRoot, repoId) {
388
+ const { layout, headCommit } = refreshManagedRepoMirror(projectRoot, repoId);
389
+ const checkoutCommit = ensureCheckoutFromMirror(layout);
390
+ if (checkoutCommit !== headCommit) {
391
+ throw new Error(`Managed repo checkout ${layout.alias} is out of sync with mirror: expected ${headCommit}, got ${checkoutCommit}.`);
392
+ }
393
+ return { layout, headCommit };
394
+ }
395
+ export {
396
+ syncManagedRepo,
397
+ refreshManagedRepoMirror
398
+ };