@h-rig/runtime 0.0.6-alpha.33 → 0.0.6-alpha.35

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 (25) hide show
  1. package/dist/bin/rig-agent-dispatch.js +518 -459
  2. package/dist/bin/rig-agent.js +431 -362
  3. package/dist/src/control-plane/agent-wrapper.js +523 -464
  4. package/dist/src/control-plane/harness-main.js +529 -459
  5. package/dist/src/control-plane/hooks/completion-verification.js +353 -283
  6. package/dist/src/control-plane/hooks/inject-context.js +158 -99
  7. package/dist/src/control-plane/hooks/submodule-branch.js +538 -479
  8. package/dist/src/control-plane/hooks/task-runtime-start.js +538 -479
  9. package/dist/src/control-plane/materialize-task-config.js +68 -8
  10. package/dist/src/control-plane/native/git-ops.js +11 -1
  11. package/dist/src/control-plane/native/harness-cli.js +514 -444
  12. package/dist/src/control-plane/native/task-ops.js +392 -322
  13. package/dist/src/control-plane/native/validator.js +159 -100
  14. package/dist/src/control-plane/native/verifier.js +227 -166
  15. package/dist/src/control-plane/pi-sessiond/bin.js +62 -0
  16. package/dist/src/control-plane/pi-sessiond/server.js +62 -0
  17. package/dist/src/control-plane/pi-sessiond/session-service.js +62 -0
  18. package/dist/src/control-plane/pi-settings-materializer.js +52 -0
  19. package/dist/src/control-plane/plugin-host-context.js +59 -0
  20. package/dist/src/control-plane/runtime/index.js +469 -410
  21. package/dist/src/control-plane/runtime/isolation/index.js +493 -434
  22. package/dist/src/control-plane/runtime/isolation.js +493 -434
  23. package/dist/src/control-plane/runtime/queue.js +411 -352
  24. package/dist/src/control-plane/tasks/source-lifecycle.js +87 -28
  25. package/package.json +8 -8
@@ -1,7 +1,7 @@
1
1
  // @bun
2
2
  // packages/runtime/src/control-plane/native/task-ops.ts
3
- import { appendFileSync, existsSync as existsSync21, mkdirSync as mkdirSync11, readFileSync as readFileSync11, writeFileSync as writeFileSync11 } from "fs";
4
- import { resolve as resolve24 } from "path";
3
+ import { appendFileSync, existsSync as existsSync23, mkdirSync as mkdirSync12, readFileSync as readFileSync12, writeFileSync as writeFileSync12 } from "fs";
4
+ import { resolve as resolve25 } from "path";
5
5
 
6
6
  // packages/runtime/src/build-time-config.ts
7
7
  function normalizeBuildConfig(value) {
@@ -680,6 +680,8 @@ function buildBrowserGuidanceLines(browser) {
680
680
  }
681
681
 
682
682
  // packages/runtime/src/control-plane/plugin-host-context.ts
683
+ import { existsSync as existsSync7 } from "fs";
684
+ import { resolve as resolvePath } from "path";
683
685
  import { createPluginHost } from "@rig/core";
684
686
  import { loadConfig } from "@rig/core/load-config";
685
687
 
@@ -1019,6 +1021,55 @@ async function materializeSkills(projectRoot, entries) {
1019
1021
  return written;
1020
1022
  }
1021
1023
 
1024
+ // packages/runtime/src/control-plane/pi-settings-materializer.ts
1025
+ import { existsSync as existsSync6, mkdirSync as mkdirSync5, readFileSync as readFileSync5, writeFileSync as writeFileSync5 } from "fs";
1026
+ import { dirname as dirname6, resolve as resolve8 } from "path";
1027
+ var SETTINGS_RELATIVE_PATH = ".pi/settings.json";
1028
+ var MANAGED_RECORD_RELATIVE_PATH = ".rig/state/pi-managed-packages.json";
1029
+ function readJson(path, fallback) {
1030
+ if (!existsSync6(path))
1031
+ return fallback;
1032
+ try {
1033
+ return JSON.parse(readFileSync5(path, "utf-8"));
1034
+ } catch {
1035
+ return fallback;
1036
+ }
1037
+ }
1038
+ function packageKey(entry) {
1039
+ if (typeof entry === "string")
1040
+ return entry;
1041
+ if (entry && typeof entry === "object" && typeof entry.source === "string") {
1042
+ return entry.source;
1043
+ }
1044
+ return JSON.stringify(entry);
1045
+ }
1046
+ function materializePiPackages(projectRoot, declaredPackages) {
1047
+ const settingsPath = resolve8(projectRoot, SETTINGS_RELATIVE_PATH);
1048
+ const managedRecordPath = resolve8(projectRoot, MANAGED_RECORD_RELATIVE_PATH);
1049
+ const settings = readJson(settingsPath, {});
1050
+ const previouslyManaged = new Set(readJson(managedRecordPath, []));
1051
+ const existing = Array.isArray(settings.packages) ? settings.packages : [];
1052
+ const operatorEntries = existing.filter((entry) => !previouslyManaged.has(packageKey(entry)));
1053
+ const operatorKeys = new Set(operatorEntries.map(packageKey));
1054
+ const managedToAdd = declaredPackages.filter((pkg) => !operatorKeys.has(pkg));
1055
+ const nextPackages = [...operatorEntries, ...managedToAdd];
1056
+ if (nextPackages.length > 0 || existsSync6(settingsPath)) {
1057
+ const nextSettings = { ...settings };
1058
+ if (nextPackages.length > 0) {
1059
+ nextSettings.packages = nextPackages;
1060
+ } else {
1061
+ delete nextSettings.packages;
1062
+ }
1063
+ mkdirSync5(dirname6(settingsPath), { recursive: true });
1064
+ writeFileSync5(settingsPath, `${JSON.stringify(nextSettings, null, 2)}
1065
+ `, "utf-8");
1066
+ }
1067
+ mkdirSync5(dirname6(managedRecordPath), { recursive: true });
1068
+ writeFileSync5(managedRecordPath, `${JSON.stringify(managedToAdd, null, 2)}
1069
+ `, "utf-8");
1070
+ return { settingsPath, packages: managedToAdd };
1071
+ }
1072
+
1022
1073
  // packages/runtime/src/control-plane/plugin-host-context.ts
1023
1074
  async function buildPluginHostContext(projectRoot) {
1024
1075
  let config;
@@ -1066,6 +1117,14 @@ async function buildPluginHostContext(projectRoot) {
1066
1117
  } catch (err) {
1067
1118
  console.warn(`[plugin-host] skill materialization failed: ${err instanceof Error ? err.message : err}`);
1068
1119
  }
1120
+ try {
1121
+ const piPackages = config.runtime?.pi?.packages ?? [];
1122
+ if (piPackages.length > 0 || existsSync7(resolvePath(projectRoot, ".rig/state/pi-managed-packages.json"))) {
1123
+ materializePiPackages(projectRoot, piPackages);
1124
+ }
1125
+ } catch (err) {
1126
+ console.warn(`[plugin-host] Pi package materialization failed: ${err instanceof Error ? err.message : err}`);
1127
+ }
1069
1128
  return {
1070
1129
  config,
1071
1130
  pluginHost,
@@ -1079,12 +1138,12 @@ async function buildPluginHostContext(projectRoot) {
1079
1138
 
1080
1139
  // packages/runtime/src/control-plane/tasks/source-aware-task-config-source.ts
1081
1140
  import { spawnSync } from "child_process";
1082
- import { existsSync as existsSync7, readFileSync as readFileSync6, readdirSync as readdirSync2, statSync, writeFileSync as writeFileSync5 } from "fs";
1083
- import { basename as basename3, join as join2, resolve as resolve9 } from "path";
1141
+ import { existsSync as existsSync9, readFileSync as readFileSync7, readdirSync as readdirSync2, statSync, writeFileSync as writeFileSync6 } from "fs";
1142
+ import { basename as basename3, join as join2, resolve as resolve10 } from "path";
1084
1143
 
1085
1144
  // packages/runtime/src/control-plane/tasks/legacy-task-config-source.ts
1086
- import { existsSync as existsSync6, readFileSync as readFileSync5 } from "fs";
1087
- import { resolve as resolve8 } from "path";
1145
+ import { existsSync as existsSync8, readFileSync as readFileSync6 } from "fs";
1146
+ import { resolve as resolve9 } from "path";
1088
1147
 
1089
1148
  // packages/runtime/src/control-plane/tasks/task-record-reader.ts
1090
1149
  async function findTaskById(reader, id) {
@@ -1107,7 +1166,7 @@ class LegacyTaskConfigReadError extends Error {
1107
1166
  }
1108
1167
  }
1109
1168
  function createLegacyTaskConfigRecordReader(projectRoot, options = {}) {
1110
- const configPath = options.configPath ?? resolve8(projectRoot, ".rig", "task-config.json");
1169
+ const configPath = options.configPath ?? resolve9(projectRoot, ".rig", "task-config.json");
1111
1170
  const reader = {
1112
1171
  async listTasks() {
1113
1172
  return readLegacyTaskRecords(projectRoot, configPath);
@@ -1118,8 +1177,8 @@ function createLegacyTaskConfigRecordReader(projectRoot, options = {}) {
1118
1177
  };
1119
1178
  return reader;
1120
1179
  }
1121
- function readLegacyTaskRecords(projectRoot, configPath = resolve8(projectRoot, ".rig", "task-config.json")) {
1122
- if (!existsSync6(configPath)) {
1180
+ function readLegacyTaskRecords(projectRoot, configPath = resolve9(projectRoot, ".rig", "task-config.json")) {
1181
+ if (!existsSync8(configPath)) {
1123
1182
  return [];
1124
1183
  }
1125
1184
  const rawConfig = readLegacyTaskConfigJson(projectRoot, configPath);
@@ -1127,7 +1186,7 @@ function readLegacyTaskRecords(projectRoot, configPath = resolve8(projectRoot, "
1127
1186
  }
1128
1187
  function readLegacyTaskConfigJson(projectRoot, configPath) {
1129
1188
  try {
1130
- const parsed = JSON.parse(readFileSync5(configPath, "utf8"));
1189
+ const parsed = JSON.parse(readFileSync6(configPath, "utf8"));
1131
1190
  if (isPlainRecord(parsed)) {
1132
1191
  return parsed;
1133
1192
  }
@@ -1211,7 +1270,7 @@ function isPlainRecord(candidate) {
1211
1270
  var STATUS_LABELS = new Set(["ready", "blocked", "in-progress", "under-review", "failed", "cancelled"]);
1212
1271
  var FILE_TASK_PATTERN = /\.(task\.)?json$/;
1213
1272
  function createSourceAwareTaskConfigRecordReader(projectRoot, options = {}) {
1214
- const configPath = options.configPath ?? resolve9(projectRoot, ".rig", "task-config.json");
1273
+ const configPath = options.configPath ?? resolve10(projectRoot, ".rig", "task-config.json");
1215
1274
  const legacy = createLegacyTaskConfigRecordReader(projectRoot, { configPath });
1216
1275
  const spawnFn = options.spawn ?? spawnSync;
1217
1276
  const ghBinary = options.ghBinary ?? "gh";
@@ -1294,10 +1353,10 @@ function readMaterializedTaskMetadata(entry) {
1294
1353
  return metadata;
1295
1354
  }
1296
1355
  function readConfiguredFilesTaskSourcePath(projectRoot) {
1297
- const jsonPath = resolve9(projectRoot, "rig.config.json");
1298
- if (existsSync7(jsonPath)) {
1356
+ const jsonPath = resolve10(projectRoot, "rig.config.json");
1357
+ if (existsSync9(jsonPath)) {
1299
1358
  try {
1300
- const parsed = JSON.parse(readFileSync6(jsonPath, "utf8"));
1359
+ const parsed = JSON.parse(readFileSync7(jsonPath, "utf8"));
1301
1360
  if (isPlainRecord2(parsed) && isPlainRecord2(parsed.taskSource)) {
1302
1361
  const source = parsed.taskSource;
1303
1362
  return source.kind === "files" && typeof source.path === "string" ? source.path : null;
@@ -1306,12 +1365,12 @@ function readConfiguredFilesTaskSourcePath(projectRoot) {
1306
1365
  return null;
1307
1366
  }
1308
1367
  }
1309
- const tsPath = resolve9(projectRoot, "rig.config.ts");
1310
- if (!existsSync7(tsPath)) {
1368
+ const tsPath = resolve10(projectRoot, "rig.config.ts");
1369
+ if (!existsSync9(tsPath)) {
1311
1370
  return null;
1312
1371
  }
1313
1372
  try {
1314
- const source = readFileSync6(tsPath, "utf8");
1373
+ const source = readFileSync7(tsPath, "utf8");
1315
1374
  const taskSourceBlock = source.match(/taskSource\s*:\s*\{[\s\S]*?\}/m)?.[0] ?? "";
1316
1375
  const kind = taskSourceBlock.match(/kind\s*:\s*["']([^"']+)["']/)?.[1];
1317
1376
  if (kind !== "files") {
@@ -1331,10 +1390,10 @@ function readRawTaskEntry(configPath, taskId) {
1331
1390
  return isPlainRecord2(entry) ? entry : null;
1332
1391
  }
1333
1392
  function readRawTaskConfig(configPath) {
1334
- if (!existsSync7(configPath)) {
1393
+ if (!existsSync9(configPath)) {
1335
1394
  return null;
1336
1395
  }
1337
- const parsed = JSON.parse(readFileSync6(configPath, "utf8"));
1396
+ const parsed = JSON.parse(readFileSync7(configPath, "utf8"));
1338
1397
  return isPlainRecord2(parsed) ? parsed : null;
1339
1398
  }
1340
1399
  function stripLegacyTaskConfigMetadata2(raw) {
@@ -1342,8 +1401,8 @@ function stripLegacyTaskConfigMetadata2(raw) {
1342
1401
  return tasks;
1343
1402
  }
1344
1403
  function listFileBackedTasks(projectRoot, sourcePath) {
1345
- const directory = resolve9(projectRoot, sourcePath);
1346
- if (!existsSync7(directory)) {
1404
+ const directory = resolve10(projectRoot, sourcePath);
1405
+ if (!existsSync9(directory)) {
1347
1406
  return [];
1348
1407
  }
1349
1408
  const tasks = [];
@@ -1358,11 +1417,11 @@ function listFileBackedTasks(projectRoot, sourcePath) {
1358
1417
  return tasks;
1359
1418
  }
1360
1419
  function readFileBackedTask(projectRoot, sourcePath, taskId, rawEntry) {
1361
- const file = findFileBackedTaskFile(resolve9(projectRoot, sourcePath), taskId);
1420
+ const file = findFileBackedTaskFile(resolve10(projectRoot, sourcePath), taskId);
1362
1421
  if (!file) {
1363
1422
  return null;
1364
1423
  }
1365
- const raw = JSON.parse(readFileSync6(file, "utf8"));
1424
+ const raw = JSON.parse(readFileSync7(file, "utf8"));
1366
1425
  if (!isPlainRecord2(raw)) {
1367
1426
  return null;
1368
1427
  }
@@ -1375,7 +1434,7 @@ function readFileBackedTask(projectRoot, sourcePath, taskId, rawEntry) {
1375
1434
  };
1376
1435
  }
1377
1436
  function findFileBackedTaskFile(directory, taskId) {
1378
- if (!existsSync7(directory)) {
1437
+ if (!existsSync9(directory)) {
1379
1438
  return null;
1380
1439
  }
1381
1440
  for (const name of readdirSync2(directory)) {
@@ -1385,7 +1444,7 @@ function findFileBackedTaskFile(directory, taskId) {
1385
1444
  try {
1386
1445
  if (!statSync(file).isFile())
1387
1446
  continue;
1388
- const raw = JSON.parse(readFileSync6(file, "utf8"));
1447
+ const raw = JSON.parse(readFileSync7(file, "utf8"));
1389
1448
  const inferredId = basename3(file).replace(FILE_TASK_PATTERN, "");
1390
1449
  const id = isPlainRecord2(raw) && typeof raw.id === "string" ? raw.id : inferredId;
1391
1450
  if (id === taskId) {
@@ -1545,8 +1604,8 @@ async function readConfiguredTaskSourceTask(projectRoot, taskId) {
1545
1604
  }
1546
1605
 
1547
1606
  // packages/runtime/src/control-plane/native/task-state.ts
1548
- import { existsSync as existsSync14, readFileSync as readFileSync9, readdirSync as readdirSync3, statSync as statSync3, writeFileSync as writeFileSync6 } from "fs";
1549
- import { basename as basename6, resolve as resolve16 } from "path";
1607
+ import { existsSync as existsSync16, readFileSync as readFileSync10, readdirSync as readdirSync3, statSync as statSync3, writeFileSync as writeFileSync7 } from "fs";
1608
+ import { basename as basename6, resolve as resolve17 } from "path";
1550
1609
 
1551
1610
  // packages/runtime/src/control-plane/state-sync/types.ts
1552
1611
  var SUPPORTED_TASK_STATE_SCHEMA_VERSION = 1;
@@ -1654,50 +1713,50 @@ function readTaskStateMetadataEnvelope(raw) {
1654
1713
  };
1655
1714
  }
1656
1715
  // packages/runtime/src/control-plane/state-sync/read.ts
1657
- import { existsSync as existsSync13, readFileSync as readFileSync8 } from "fs";
1658
- import { resolve as resolve15 } from "path";
1716
+ import { existsSync as existsSync15, readFileSync as readFileSync9 } from "fs";
1717
+ import { resolve as resolve16 } from "path";
1659
1718
 
1660
1719
  // packages/runtime/src/control-plane/native/utils.ts
1661
- import { existsSync as existsSync10, readFileSync as readFileSync7 } from "fs";
1662
- import { resolve as resolve12 } from "path";
1720
+ import { existsSync as existsSync12, readFileSync as readFileSync8 } from "fs";
1721
+ import { resolve as resolve13 } from "path";
1663
1722
 
1664
1723
  // packages/runtime/src/layout.ts
1665
- import { existsSync as existsSync8 } from "fs";
1666
- import { basename as basename4, dirname as dirname6, resolve as resolve10 } from "path";
1724
+ import { existsSync as existsSync10 } from "fs";
1725
+ import { basename as basename4, dirname as dirname7, resolve as resolve11 } from "path";
1667
1726
  var RIG_DEFINITION_DIRNAME = "rig";
1668
1727
  var RIG_ARTIFACTS_DIRNAME = "artifacts";
1669
1728
  function resolveMonorepoRoot(projectRoot) {
1670
- const normalizedProjectRoot = resolve10(projectRoot);
1729
+ const normalizedProjectRoot = resolve11(projectRoot);
1671
1730
  const explicit = process.env.MONOREPO_ROOT?.trim();
1672
1731
  if (explicit) {
1673
- const explicitRoot = resolve10(explicit);
1674
- const explicitParent = dirname6(explicitRoot);
1732
+ const explicitRoot = resolve11(explicit);
1733
+ const explicitParent = dirname7(explicitRoot);
1675
1734
  if (basename4(explicitParent) === ".worktrees") {
1676
- const owner = dirname6(explicitParent);
1677
- const ownerHasGit = existsSync8(resolve10(owner, ".git"));
1678
- const ownerHasTaskConfig = existsSync8(resolve10(owner, ".rig", "task-config.json"));
1679
- const ownerHasRigConfig = existsSync8(resolve10(owner, "rig.config.ts"));
1735
+ const owner = dirname7(explicitParent);
1736
+ const ownerHasGit = existsSync10(resolve11(owner, ".git"));
1737
+ const ownerHasTaskConfig = existsSync10(resolve11(owner, ".rig", "task-config.json"));
1738
+ const ownerHasRigConfig = existsSync10(resolve11(owner, "rig.config.ts"));
1680
1739
  if (ownerHasGit && (ownerHasTaskConfig || ownerHasRigConfig)) {
1681
1740
  return owner;
1682
1741
  }
1683
1742
  throw new Error(`MONOREPO_ROOT points to worktree ${explicitRoot}, but the owner checkout is incomplete at ${owner}.`);
1684
1743
  }
1685
- if (!existsSync8(resolve10(explicitRoot, ".git"))) {
1744
+ if (!existsSync10(resolve11(explicitRoot, ".git"))) {
1686
1745
  throw new Error(`MONOREPO_ROOT points to ${explicitRoot}, but no git checkout was found there.`);
1687
1746
  }
1688
- const hasTaskConfig = existsSync8(resolve10(explicitRoot, ".rig", "task-config.json"));
1689
- const hasRigConfig = existsSync8(resolve10(explicitRoot, "rig.config.ts"));
1747
+ const hasTaskConfig = existsSync10(resolve11(explicitRoot, ".rig", "task-config.json"));
1748
+ const hasRigConfig = existsSync10(resolve11(explicitRoot, "rig.config.ts"));
1690
1749
  if (!hasTaskConfig && !hasRigConfig) {
1691
1750
  throw new Error(`MONOREPO_ROOT points to ${explicitRoot}, but neither .rig/task-config.json nor rig.config.ts exists there.`);
1692
1751
  }
1693
1752
  return explicitRoot;
1694
1753
  }
1695
- const projectParent = dirname6(normalizedProjectRoot);
1754
+ const projectParent = dirname7(normalizedProjectRoot);
1696
1755
  if (basename4(projectParent) === ".worktrees") {
1697
- const worktreeOwner = dirname6(projectParent);
1698
- const ownerHasGit = existsSync8(resolve10(worktreeOwner, ".git"));
1699
- const ownerHasTaskConfig = existsSync8(resolve10(worktreeOwner, ".rig", "task-config.json"));
1700
- const ownerHasRigConfig = existsSync8(resolve10(worktreeOwner, "rig.config.ts"));
1756
+ const worktreeOwner = dirname7(projectParent);
1757
+ const ownerHasGit = existsSync10(resolve11(worktreeOwner, ".git"));
1758
+ const ownerHasTaskConfig = existsSync10(resolve11(worktreeOwner, ".rig", "task-config.json"));
1759
+ const ownerHasRigConfig = existsSync10(resolve11(worktreeOwner, "rig.config.ts"));
1701
1760
  if (ownerHasGit && (ownerHasTaskConfig || ownerHasRigConfig)) {
1702
1761
  return worktreeOwner;
1703
1762
  }
@@ -1705,28 +1764,28 @@ function resolveMonorepoRoot(projectRoot) {
1705
1764
  return normalizedProjectRoot;
1706
1765
  }
1707
1766
  function resolveRuntimeWorkspaceLayout(workspaceDir) {
1708
- const root = resolve10(workspaceDir);
1709
- const rigRoot = resolve10(root, ".rig");
1710
- const logsDir = resolve10(rigRoot, "logs");
1711
- const stateDir = resolve10(rigRoot, "state");
1712
- const runtimeDir = resolve10(rigRoot, "runtime");
1713
- const binDir = resolve10(rigRoot, "bin");
1767
+ const root = resolve11(workspaceDir);
1768
+ const rigRoot = resolve11(root, ".rig");
1769
+ const logsDir = resolve11(rigRoot, "logs");
1770
+ const stateDir = resolve11(rigRoot, "state");
1771
+ const runtimeDir = resolve11(rigRoot, "runtime");
1772
+ const binDir = resolve11(rigRoot, "bin");
1714
1773
  return {
1715
1774
  workspaceDir: root,
1716
1775
  rigRoot,
1717
1776
  stateDir,
1718
1777
  logsDir,
1719
- artifactsRoot: resolve10(root, RIG_ARTIFACTS_DIRNAME),
1778
+ artifactsRoot: resolve11(root, RIG_ARTIFACTS_DIRNAME),
1720
1779
  runtimeDir,
1721
- homeDir: resolve10(rigRoot, "home"),
1722
- tmpDir: resolve10(rigRoot, "tmp"),
1723
- cacheDir: resolve10(rigRoot, "cache"),
1724
- sessionDir: resolve10(rigRoot, "session"),
1780
+ homeDir: resolve11(rigRoot, "home"),
1781
+ tmpDir: resolve11(rigRoot, "tmp"),
1782
+ cacheDir: resolve11(rigRoot, "cache"),
1783
+ sessionDir: resolve11(rigRoot, "session"),
1725
1784
  binDir,
1726
- distDir: resolve10(rigRoot, "dist"),
1727
- pluginBinDir: resolve10(binDir, "plugins"),
1728
- contextPath: resolve10(rigRoot, "runtime-context.json"),
1729
- controlPlaneEventsFile: resolve10(logsDir, "control-plane.events.jsonl")
1785
+ distDir: resolve11(rigRoot, "dist"),
1786
+ pluginBinDir: resolve11(binDir, "plugins"),
1787
+ contextPath: resolve11(rigRoot, "runtime-context.json"),
1788
+ controlPlaneEventsFile: resolve11(logsDir, "control-plane.events.jsonl")
1730
1789
  };
1731
1790
  }
1732
1791
  function resolveActiveRuntimeWorkspaceRoot(monorepoRoot) {
@@ -1734,14 +1793,14 @@ function resolveActiveRuntimeWorkspaceRoot(monorepoRoot) {
1734
1793
  if (!explicit) {
1735
1794
  throw new Error("No active runtime workspace. Set RIG_TASK_WORKSPACE or provision a task runtime first.");
1736
1795
  }
1737
- return resolve10(explicit);
1796
+ return resolve11(explicit);
1738
1797
  }
1739
1798
  function resolveRigLayout(projectRoot) {
1740
1799
  const monorepoRoot = resolveMonorepoRoot(projectRoot);
1741
- const definitionRoot = resolve10(projectRoot, RIG_DEFINITION_DIRNAME);
1800
+ const definitionRoot = resolve11(projectRoot, RIG_DEFINITION_DIRNAME);
1742
1801
  const runtimeWorkspaceRoot = resolveActiveRuntimeWorkspaceRoot(monorepoRoot);
1743
1802
  const runtimeLayout = resolveRuntimeWorkspaceLayout(runtimeWorkspaceRoot);
1744
- const policyDir = resolve10(definitionRoot, "policy");
1803
+ const policyDir = resolve11(definitionRoot, "policy");
1745
1804
  return {
1746
1805
  projectRoot,
1747
1806
  monorepoRoot,
@@ -1749,48 +1808,48 @@ function resolveRigLayout(projectRoot) {
1749
1808
  runtimeWorkspaceRoot,
1750
1809
  stateRoot: runtimeLayout.rigRoot,
1751
1810
  artifactsRoot: runtimeLayout.artifactsRoot,
1752
- configPath: resolve10(definitionRoot, "config.sh"),
1753
- taskConfigPath: resolve10(runtimeWorkspaceRoot, ".rig", "task-config.json"),
1811
+ configPath: resolve11(definitionRoot, "config.sh"),
1812
+ taskConfigPath: resolve11(runtimeWorkspaceRoot, ".rig", "task-config.json"),
1754
1813
  policyDir,
1755
- policyFile: resolve10(policyDir, "policy.json"),
1756
- pluginsDir: resolve10(definitionRoot, "plugins"),
1757
- hooksDir: resolve10(definitionRoot, "hooks"),
1758
- toolsDir: resolve10(definitionRoot, "tools"),
1759
- templatesDir: resolve10(definitionRoot, "templates"),
1760
- validationDir: resolve10(definitionRoot, "validation"),
1814
+ policyFile: resolve11(policyDir, "policy.json"),
1815
+ pluginsDir: resolve11(definitionRoot, "plugins"),
1816
+ hooksDir: resolve11(definitionRoot, "hooks"),
1817
+ toolsDir: resolve11(definitionRoot, "tools"),
1818
+ templatesDir: resolve11(definitionRoot, "templates"),
1819
+ validationDir: resolve11(definitionRoot, "validation"),
1761
1820
  stateDir: runtimeLayout.stateDir,
1762
1821
  logsDir: runtimeLayout.logsDir,
1763
- notificationsDir: resolve10(definitionRoot, "notifications"),
1822
+ notificationsDir: resolve11(definitionRoot, "notifications"),
1764
1823
  runtimeDir: runtimeLayout.runtimeDir,
1765
1824
  distDir: runtimeLayout.distDir,
1766
1825
  binDir: runtimeLayout.binDir,
1767
1826
  pluginBinDir: runtimeLayout.pluginBinDir,
1768
- keybindingsPath: resolve10(definitionRoot, "keybindings.json"),
1827
+ keybindingsPath: resolve11(definitionRoot, "keybindings.json"),
1769
1828
  controlPlaneEventsFile: runtimeLayout.controlPlaneEventsFile
1770
1829
  };
1771
1830
  }
1772
1831
 
1773
1832
  // packages/runtime/src/control-plane/native/runtime-native.ts
1774
1833
  import { dlopen, ptr, suffix, toBuffer } from "bun:ffi";
1775
- import { copyFileSync as copyFileSync2, existsSync as existsSync9, mkdirSync as mkdirSync5, renameSync as renameSync2, rmSync as rmSync3, statSync as statSync2 } from "fs";
1834
+ import { copyFileSync as copyFileSync2, existsSync as existsSync11, mkdirSync as mkdirSync6, renameSync as renameSync2, rmSync as rmSync3, statSync as statSync2 } from "fs";
1776
1835
  import { tmpdir as tmpdir4 } from "os";
1777
- import { dirname as dirname7, resolve as resolve11 } from "path";
1778
- var sharedNativeRuntimeOutputDir = resolve11(tmpdir4(), "rig-native");
1779
- var sharedNativeRuntimeOutputPath = resolve11(sharedNativeRuntimeOutputDir, `runtime-native-${process.platform}-${process.arch}.${suffix}`);
1836
+ import { dirname as dirname8, resolve as resolve12 } from "path";
1837
+ var sharedNativeRuntimeOutputDir = resolve12(tmpdir4(), "rig-native");
1838
+ var sharedNativeRuntimeOutputPath = resolve12(sharedNativeRuntimeOutputDir, `runtime-native-${process.platform}-${process.arch}.${suffix}`);
1780
1839
  var colocatedNativeRuntimeFileName = `runtime-native.${suffix}`;
1781
1840
  var nativeRuntimeLibrary = await loadNativeRuntimeLibrary();
1782
1841
  async function ensureNativeRuntimeLibraryPath(outputPath = sharedNativeRuntimeOutputPath, options = {}) {
1783
1842
  if (await buildNativeRuntimeLibrary(outputPath, options)) {
1784
1843
  return outputPath;
1785
1844
  }
1786
- return !options.force && existsSync9(outputPath) ? outputPath : null;
1845
+ return !options.force && existsSync11(outputPath) ? outputPath : null;
1787
1846
  }
1788
1847
  async function loadNativeRuntimeLibrary() {
1789
1848
  if (process.env.RIG_DISABLE_ZIG_NATIVE === "1") {
1790
1849
  return null;
1791
1850
  }
1792
1851
  for (const candidate of nativeRuntimeLibraryCandidates()) {
1793
- if (!candidate || !existsSync9(candidate)) {
1852
+ if (!candidate || !existsSync11(candidate)) {
1794
1853
  continue;
1795
1854
  }
1796
1855
  const loaded = tryDlopenNativeRuntimeLibrary(candidate);
@@ -1806,12 +1865,12 @@ async function loadNativeRuntimeLibrary() {
1806
1865
  }
1807
1866
  function nativePackageLibraryCandidates(fromDir, names) {
1808
1867
  const candidates = [];
1809
- let cursor = resolve11(fromDir);
1868
+ let cursor = resolve12(fromDir);
1810
1869
  for (let index = 0;index < 8; index += 1) {
1811
1870
  for (const name of names) {
1812
- candidates.push(resolve11(cursor, "native", `${process.platform}-${process.arch}`, name), resolve11(cursor, "native", `${process.platform}-${process.arch}`, "lib", name), resolve11(cursor, "native", name), resolve11(cursor, "native", "lib", name));
1871
+ candidates.push(resolve12(cursor, "native", `${process.platform}-${process.arch}`, name), resolve12(cursor, "native", `${process.platform}-${process.arch}`, "lib", name), resolve12(cursor, "native", name), resolve12(cursor, "native", "lib", name));
1813
1872
  }
1814
- const parent = dirname7(cursor);
1873
+ const parent = dirname8(cursor);
1815
1874
  if (parent === cursor)
1816
1875
  break;
1817
1876
  cursor = parent;
@@ -1820,27 +1879,27 @@ function nativePackageLibraryCandidates(fromDir, names) {
1820
1879
  }
1821
1880
  function nativeRuntimeLibraryCandidates() {
1822
1881
  const explicit = process.env.RIG_NATIVE_RUNTIME_LIB?.trim() || "";
1823
- const execDir = process.execPath?.trim() ? dirname7(process.execPath.trim()) : "";
1882
+ const execDir = process.execPath?.trim() ? dirname8(process.execPath.trim()) : "";
1824
1883
  const platformSpecific = `runtime-native-${process.platform}-${process.arch}.${suffix}`;
1825
1884
  return [...new Set([
1826
1885
  explicit,
1827
1886
  ...nativePackageLibraryCandidates(import.meta.dir, [colocatedNativeRuntimeFileName, platformSpecific]),
1828
- execDir ? resolve11(execDir, colocatedNativeRuntimeFileName) : "",
1829
- execDir ? resolve11(execDir, platformSpecific) : "",
1830
- execDir ? resolve11(execDir, "..", colocatedNativeRuntimeFileName) : "",
1831
- execDir ? resolve11(execDir, "..", platformSpecific) : "",
1832
- execDir ? resolve11(execDir, "lib", colocatedNativeRuntimeFileName) : "",
1833
- execDir ? resolve11(execDir, "..", "lib", colocatedNativeRuntimeFileName) : "",
1887
+ execDir ? resolve12(execDir, colocatedNativeRuntimeFileName) : "",
1888
+ execDir ? resolve12(execDir, platformSpecific) : "",
1889
+ execDir ? resolve12(execDir, "..", colocatedNativeRuntimeFileName) : "",
1890
+ execDir ? resolve12(execDir, "..", platformSpecific) : "",
1891
+ execDir ? resolve12(execDir, "lib", colocatedNativeRuntimeFileName) : "",
1892
+ execDir ? resolve12(execDir, "..", "lib", colocatedNativeRuntimeFileName) : "",
1834
1893
  sharedNativeRuntimeOutputPath
1835
1894
  ].filter(Boolean))];
1836
1895
  }
1837
1896
  function resolveNativeRuntimeSourcePath() {
1838
1897
  const explicit = process.env.RIG_NATIVE_RUNTIME_SOURCE?.trim();
1839
- if (explicit && existsSync9(explicit)) {
1898
+ if (explicit && existsSync11(explicit)) {
1840
1899
  return explicit;
1841
1900
  }
1842
- const bundled = resolve11(import.meta.dir, "../../../native/snapshot.zig");
1843
- return existsSync9(bundled) ? bundled : null;
1901
+ const bundled = resolve12(import.meta.dir, "../../../native/snapshot.zig");
1902
+ return existsSync11(bundled) ? bundled : null;
1844
1903
  }
1845
1904
  async function buildNativeRuntimeLibrary(outputPath, options = {}) {
1846
1905
  if (process.env.RIG_DISABLE_ZIG_NATIVE === "1") {
@@ -1853,8 +1912,8 @@ async function buildNativeRuntimeLibrary(outputPath, options = {}) {
1853
1912
  }
1854
1913
  const tempOutputPath = `${outputPath}.${process.pid}.${Date.now()}.${Math.random().toString(36).slice(2)}.tmp`;
1855
1914
  try {
1856
- mkdirSync5(dirname7(outputPath), { recursive: true });
1857
- const needsBuild = options.force === true || !existsSync9(outputPath) || statSync2(sourcePath).mtimeMs > statSync2(outputPath).mtimeMs;
1915
+ mkdirSync6(dirname8(outputPath), { recursive: true });
1916
+ const needsBuild = options.force === true || !existsSync11(outputPath) || statSync2(sourcePath).mtimeMs > statSync2(outputPath).mtimeMs;
1858
1917
  if (!needsBuild) {
1859
1918
  return true;
1860
1919
  }
@@ -1872,7 +1931,7 @@ async function buildNativeRuntimeLibrary(outputPath, options = {}) {
1872
1931
  stderr: "pipe"
1873
1932
  });
1874
1933
  const exitCode = await build.exited;
1875
- if (exitCode !== 0 || !existsSync9(tempOutputPath)) {
1934
+ if (exitCode !== 0 || !existsSync11(tempOutputPath)) {
1876
1935
  rmSync3(tempOutputPath, { force: true });
1877
1936
  return false;
1878
1937
  }
@@ -2002,11 +2061,11 @@ async function runCaptureAsync(command, cwd, env, timeoutMs) {
2002
2061
  return { exitCode, stdout, stderr };
2003
2062
  }
2004
2063
  function readJsonFile(path, fallback) {
2005
- if (!existsSync10(path)) {
2064
+ if (!existsSync12(path)) {
2006
2065
  return fallback;
2007
2066
  }
2008
2067
  try {
2009
- return JSON.parse(readFileSync7(path, "utf-8"));
2068
+ return JSON.parse(readFileSync8(path, "utf-8"));
2010
2069
  } catch {
2011
2070
  return fallback;
2012
2071
  }
@@ -2020,31 +2079,31 @@ function unique(values) {
2020
2079
  function resolveHarnessPaths(projectRoot) {
2021
2080
  const hasRuntimeWorkspace = Boolean(process.env.RIG_TASK_WORKSPACE?.trim());
2022
2081
  const monorepoRoot = resolveMonorepoRoot2(projectRoot);
2023
- const harnessRoot = resolve12(projectRoot, "rig");
2024
- const stateRoot = resolve12(projectRoot, ".rig");
2082
+ const harnessRoot = resolve13(projectRoot, "rig");
2083
+ const stateRoot = resolve13(projectRoot, ".rig");
2025
2084
  const layout = hasRuntimeWorkspace ? resolveRigLayout(projectRoot) : null;
2026
- const stateDir = layout?.stateDir ?? resolve12(stateRoot, "state");
2027
- const logsDir = layout?.logsDir ?? resolve12(stateRoot, "logs");
2028
- const artifactsDir = layout?.artifactsRoot ?? resolve12(monorepoRoot, "artifacts");
2029
- const taskConfigPath = layout?.taskConfigPath ?? resolve12(monorepoRoot, ".rig", "task-config.json");
2030
- const binDir = layout?.binDir ?? resolve12(stateRoot, "bin");
2085
+ const stateDir = layout?.stateDir ?? resolve13(stateRoot, "state");
2086
+ const logsDir = layout?.logsDir ?? resolve13(stateRoot, "logs");
2087
+ const artifactsDir = layout?.artifactsRoot ?? resolve13(monorepoRoot, "artifacts");
2088
+ const taskConfigPath = layout?.taskConfigPath ?? resolve13(monorepoRoot, ".rig", "task-config.json");
2089
+ const binDir = layout?.binDir ?? resolve13(stateRoot, "bin");
2031
2090
  return {
2032
2091
  harnessRoot,
2033
2092
  stateDir: process.env.RIG_STATE_DIR || stateDir,
2034
2093
  artifactsDir,
2035
2094
  logsDir: process.env.RIG_LOGS_DIR || logsDir,
2036
2095
  binDir,
2037
- hooksDir: resolve12(harnessRoot, "hooks"),
2038
- validationDir: resolve12(harnessRoot, "validation"),
2096
+ hooksDir: resolve13(harnessRoot, "hooks"),
2097
+ validationDir: resolve13(harnessRoot, "validation"),
2039
2098
  taskConfigPath,
2040
- sessionPath: process.env.RIG_SESSION_FILE || resolve12(stateRoot, "session", "session.json"),
2099
+ sessionPath: process.env.RIG_SESSION_FILE || resolve13(stateRoot, "session", "session.json"),
2041
2100
  monorepoRoot,
2042
- tsApiTestsDir: process.env.TS_API_TESTS_DIR || resolve12(monorepoRoot, "TSAPITests"),
2043
- taskRepoCommitsPath: resolve12(stateDir, "task-repo-commits.json"),
2044
- baseRepoPinsPath: resolve12(stateDir, "base-repo-pins.json"),
2045
- failedApproachesPath: resolve12(stateDir, "failed_approaches.md"),
2046
- agentProfilePath: resolve12(stateDir, "agent-profile.json"),
2047
- reviewProfilePath: resolve12(stateDir, "review-profile.json")
2101
+ tsApiTestsDir: process.env.TS_API_TESTS_DIR || resolve13(monorepoRoot, "TSAPITests"),
2102
+ taskRepoCommitsPath: resolve13(stateDir, "task-repo-commits.json"),
2103
+ baseRepoPinsPath: resolve13(stateDir, "base-repo-pins.json"),
2104
+ failedApproachesPath: resolve13(stateDir, "failed_approaches.md"),
2105
+ agentProfilePath: resolve13(stateDir, "agent-profile.json"),
2106
+ reviewProfilePath: resolve13(stateDir, "review-profile.json")
2048
2107
  };
2049
2108
  }
2050
2109
  function normalizeRelativeScopePath(inputPath) {
@@ -2102,34 +2161,34 @@ function monorepoSearchCandidates(inputPath) {
2102
2161
  }
2103
2162
 
2104
2163
  // packages/runtime/src/control-plane/state-sync/repo.ts
2105
- import { existsSync as existsSync12 } from "fs";
2106
- import { resolve as resolve14 } from "path";
2164
+ import { existsSync as existsSync14 } from "fs";
2165
+ import { resolve as resolve15 } from "path";
2107
2166
 
2108
2167
  // packages/runtime/src/control-plane/repos/layout.ts
2109
- import { existsSync as existsSync11 } from "fs";
2110
- import { basename as basename5, dirname as dirname8, join as join3, resolve as resolve13 } from "path";
2168
+ import { existsSync as existsSync13 } from "fs";
2169
+ import { basename as basename5, dirname as dirname9, join as join3, resolve as resolve14 } from "path";
2111
2170
  function resolveRepoStateDir(projectRoot) {
2112
- const normalizedProjectRoot = resolve13(projectRoot);
2113
- const projectParent = dirname8(normalizedProjectRoot);
2171
+ const normalizedProjectRoot = resolve14(projectRoot);
2172
+ const projectParent = dirname9(normalizedProjectRoot);
2114
2173
  if (basename5(projectParent) === ".worktrees") {
2115
- const ownerRoot = dirname8(projectParent);
2116
- const ownerHasRepoMarkers = existsSync11(resolve13(ownerRoot, ".git")) || existsSync11(resolve13(ownerRoot, ".rig", "state"));
2174
+ const ownerRoot = dirname9(projectParent);
2175
+ const ownerHasRepoMarkers = existsSync13(resolve14(ownerRoot, ".git")) || existsSync13(resolve14(ownerRoot, ".rig", "state"));
2117
2176
  if (ownerHasRepoMarkers) {
2118
- return resolve13(ownerRoot, ".rig", "state");
2177
+ return resolve14(ownerRoot, ".rig", "state");
2119
2178
  }
2120
2179
  }
2121
- return resolve13(projectRoot, ".rig", "state");
2180
+ return resolve14(projectRoot, ".rig", "state");
2122
2181
  }
2123
2182
  function resolveManagedRepoLayout(projectRoot, repoId) {
2124
- const normalizedProjectRoot = resolve13(projectRoot);
2183
+ const normalizedProjectRoot = resolve14(projectRoot);
2125
2184
  const entry = getManagedRepoEntry(repoId);
2126
2185
  const stateDir = resolveRepoStateDir(normalizedProjectRoot);
2127
2186
  const metadataRelativePath = join3("repos", entry.id);
2128
- const metadataRoot = resolve13(stateDir, metadataRelativePath);
2187
+ const metadataRoot = resolve14(stateDir, metadataRelativePath);
2129
2188
  const runtimeWorkspace = process.env.RIG_TASK_WORKSPACE?.trim();
2130
- const runsInsideTaskWorktree = runtimeWorkspace && resolve13(runtimeWorkspace) === normalizedProjectRoot || basename5(dirname8(normalizedProjectRoot)) === ".worktrees";
2189
+ const runsInsideTaskWorktree = runtimeWorkspace && resolve14(runtimeWorkspace) === normalizedProjectRoot || basename5(dirname9(normalizedProjectRoot)) === ".worktrees";
2131
2190
  const isPrimaryManagedRepo = listManagedRepoEntries()[0]?.id === repoId;
2132
- const checkoutRoot = isPrimaryManagedRepo && runsInsideTaskWorktree ? resolveMonorepoRoot(normalizedProjectRoot) : entry.checkoutEnvVar && process.env[entry.checkoutEnvVar]?.trim() ? resolve13(process.env[entry.checkoutEnvVar].trim()) : resolve13(normalizedProjectRoot, entry.alias);
2191
+ const checkoutRoot = isPrimaryManagedRepo && runsInsideTaskWorktree ? resolveMonorepoRoot(normalizedProjectRoot) : entry.checkoutEnvVar && process.env[entry.checkoutEnvVar]?.trim() ? resolve14(process.env[entry.checkoutEnvVar].trim()) : resolve14(normalizedProjectRoot, entry.alias);
2133
2192
  return {
2134
2193
  projectRoot: normalizedProjectRoot,
2135
2194
  repoId: entry.id,
@@ -2137,12 +2196,12 @@ function resolveManagedRepoLayout(projectRoot, repoId) {
2137
2196
  defaultBranch: entry.defaultBranch,
2138
2197
  remoteUrl: entry.remoteEnvVar && process.env[entry.remoteEnvVar]?.trim() ? process.env[entry.remoteEnvVar].trim() : entry.defaultRemoteUrl,
2139
2198
  checkoutRoot,
2140
- worktreesRoot: resolve13(checkoutRoot, ".worktrees"),
2199
+ worktreesRoot: resolve14(checkoutRoot, ".worktrees"),
2141
2200
  stateDir,
2142
2201
  metadataRoot,
2143
2202
  metadataRelativePath,
2144
- mirrorRoot: resolve13(metadataRoot, "mirror.git"),
2145
- mirrorStatePath: resolve13(metadataRoot, "mirror-state.json"),
2203
+ mirrorRoot: resolve14(metadataRoot, "mirror.git"),
2204
+ mirrorStatePath: resolve14(metadataRoot, "mirror-state.json"),
2146
2205
  mirrorStateRelativePath: join3(metadataRelativePath, "mirror-state.json")
2147
2206
  };
2148
2207
  }
@@ -2160,7 +2219,7 @@ function resolveTrackerRepoPath(projectRoot) {
2160
2219
  const monorepoRoot = resolveMonorepoRoot2(projectRoot);
2161
2220
  try {
2162
2221
  const layout = resolveMonorepoRepoLayout(projectRoot);
2163
- if (existsSync12(resolve14(layout.mirrorRoot, "HEAD"))) {
2222
+ if (existsSync14(resolve15(layout.mirrorRoot, "HEAD"))) {
2164
2223
  return layout.mirrorRoot;
2165
2224
  }
2166
2225
  } catch {}
@@ -2171,8 +2230,8 @@ function resolveTrackerRepoPath(projectRoot) {
2171
2230
  var DEFAULT_READ_DEPS = {
2172
2231
  fetchRef: nativeFetchRef,
2173
2232
  readBlobAtRef: nativeReadBlobAtRef,
2174
- exists: existsSync13,
2175
- readFile: (path) => readFileSync8(path, "utf8")
2233
+ exists: existsSync15,
2234
+ readFile: (path) => readFileSync9(path, "utf8")
2176
2235
  };
2177
2236
  function parseIssueStatus(rawStatus) {
2178
2237
  const normalized = normalizeTaskLifecycleStatus(rawStatus);
@@ -2253,12 +2312,12 @@ function shouldPreferLocalTrackerState(options) {
2253
2312
  if (runtimeContextPath) {
2254
2313
  return true;
2255
2314
  }
2256
- return existsSync13(resolve15(runtimeWorkspace, ".rig", "runtime-context.json"));
2315
+ return existsSync15(resolve16(runtimeWorkspace, ".rig", "runtime-context.json"));
2257
2316
  }
2258
2317
  function readLocalTrackerState(projectRoot, deps) {
2259
2318
  const monorepoRoot = resolveMonorepoRoot2(projectRoot);
2260
- const issuesPath = resolve15(monorepoRoot, ".beads", "issues.jsonl");
2261
- const taskStatePath = resolve15(monorepoRoot, ".beads", "task-state.json");
2319
+ const issuesPath = resolve16(monorepoRoot, ".beads", "issues.jsonl");
2320
+ const taskStatePath = resolve16(monorepoRoot, ".beads", "task-state.json");
2262
2321
  return projectSyncedTrackerSnapshot({
2263
2322
  source: "local",
2264
2323
  issuesBaseOid: null,
@@ -2572,7 +2631,7 @@ function readValidationDescriptions(projectRoot) {
2572
2631
  return readValidationDescriptionMap(raw);
2573
2632
  }
2574
2633
  function readSourceValidationDescriptions(projectRoot) {
2575
- const rootRaw = readJsonFile(resolve16(projectRoot, "rig", "task-config.json"), {});
2634
+ const rootRaw = readJsonFile(resolve17(projectRoot, "rig", "task-config.json"), {});
2576
2635
  const sourcePath = findSourceTaskConfigPath(projectRoot);
2577
2636
  const sourceRaw = sourcePath ? readJsonFile(sourcePath, {}) : {};
2578
2637
  const rootDescriptions = readValidationDescriptionMap(rootRaw);
@@ -2648,15 +2707,15 @@ function readValidationDescriptionsFromMeta(meta) {
2648
2707
  return meta.validation_descriptions;
2649
2708
  }
2650
2709
  function readLocalSourceTaskStateEnvelope(projectRoot) {
2651
- const taskStatePath = resolve16(resolveMonorepoRoot2(projectRoot), ".beads", "task-state.json");
2710
+ const taskStatePath = resolve17(resolveMonorepoRoot2(projectRoot), ".beads", "task-state.json");
2652
2711
  return readTaskStateMetadataEnvelope(readJsonFile(taskStatePath, {}));
2653
2712
  }
2654
2713
  function readLocalSourceTaskLifecycleStatus(projectRoot, taskId) {
2655
- const issuesPath = resolve16(resolveMonorepoRoot2(projectRoot), ".beads", "issues.jsonl");
2656
- if (!existsSync14(issuesPath)) {
2714
+ const issuesPath = resolve17(resolveMonorepoRoot2(projectRoot), ".beads", "issues.jsonl");
2715
+ if (!existsSync16(issuesPath)) {
2657
2716
  return null;
2658
2717
  }
2659
- for (const line of readFileSync9(issuesPath, "utf8").split(/\r?\n/)) {
2718
+ for (const line of readFileSync10(issuesPath, "utf8").split(/\r?\n/)) {
2660
2719
  const trimmed = line.trim();
2661
2720
  if (!trimmed) {
2662
2721
  continue;
@@ -2697,25 +2756,25 @@ function lookupTask(projectRoot, input) {
2697
2756
  function artifactDirForId(projectRoot, id) {
2698
2757
  const workspaceDir = process.env.RIG_TASK_WORKSPACE?.trim();
2699
2758
  if (workspaceDir) {
2700
- const worktreeArtifacts = resolve16(workspaceDir, "artifacts", id);
2701
- if (existsSync14(worktreeArtifacts) || existsSync14(resolve16(workspaceDir, "artifacts"))) {
2759
+ const worktreeArtifacts = resolve17(workspaceDir, "artifacts", id);
2760
+ if (existsSync16(worktreeArtifacts) || existsSync16(resolve17(workspaceDir, "artifacts"))) {
2702
2761
  return worktreeArtifacts;
2703
2762
  }
2704
2763
  }
2705
2764
  try {
2706
2765
  const paths = resolveHarnessPaths(projectRoot);
2707
- return resolve16(paths.artifactsDir, id);
2766
+ return resolve17(paths.artifactsDir, id);
2708
2767
  } catch {
2709
- return resolve16(resolveMonorepoRoot2(projectRoot), "artifacts", id);
2768
+ return resolve17(resolveMonorepoRoot2(projectRoot), "artifacts", id);
2710
2769
  }
2711
2770
  }
2712
2771
  function resolveTaskConfigPath(projectRoot) {
2713
2772
  const paths = resolveHarnessPaths(projectRoot);
2714
- if (existsSync14(paths.taskConfigPath)) {
2773
+ if (existsSync16(paths.taskConfigPath)) {
2715
2774
  return paths.taskConfigPath;
2716
2775
  }
2717
2776
  for (const candidate of sourceTaskConfigCandidates(projectRoot)) {
2718
- if (existsSync14(candidate)) {
2777
+ if (existsSync16(candidate)) {
2719
2778
  return candidate;
2720
2779
  }
2721
2780
  }
@@ -2723,7 +2782,7 @@ function resolveTaskConfigPath(projectRoot) {
2723
2782
  }
2724
2783
  function findSourceTaskConfigPath(projectRoot) {
2725
2784
  for (const candidate of sourceTaskConfigCandidates(projectRoot)) {
2726
- if (existsSync14(candidate)) {
2785
+ if (existsSync16(candidate)) {
2727
2786
  return candidate;
2728
2787
  }
2729
2788
  }
@@ -2736,7 +2795,7 @@ function readAndSyncSourceTaskConfig(projectRoot) {
2736
2795
  const synced = synchronizeTaskConfigWithTracker(projectRoot, raw);
2737
2796
  if (sourcePath && synced.updated) {
2738
2797
  try {
2739
- writeFileSync6(sourcePath, `${JSON.stringify(synced.config, null, 2)}
2798
+ writeFileSync7(sourcePath, `${JSON.stringify(synced.config, null, 2)}
2740
2799
  `, "utf-8");
2741
2800
  } catch {}
2742
2801
  }
@@ -2788,12 +2847,12 @@ function shouldRefreshAutoSyncedTaskConfigEntry(entry) {
2788
2847
  return !candidate.role;
2789
2848
  }
2790
2849
  function readSourceIssueRecords(projectRoot) {
2791
- const issuesPath = resolve16(resolveMonorepoRoot2(projectRoot), ".beads", "issues.jsonl");
2792
- if (!existsSync14(issuesPath)) {
2850
+ const issuesPath = resolve17(resolveMonorepoRoot2(projectRoot), ".beads", "issues.jsonl");
2851
+ if (!existsSync16(issuesPath)) {
2793
2852
  return [];
2794
2853
  }
2795
2854
  const records = [];
2796
- for (const line of readFileSync9(issuesPath, "utf-8").split(/\r?\n/)) {
2855
+ for (const line of readFileSync10(issuesPath, "utf-8").split(/\r?\n/)) {
2797
2856
  const trimmed = line.trim();
2798
2857
  if (!trimmed) {
2799
2858
  continue;
@@ -2849,19 +2908,19 @@ function readConfiguredFileTaskConfig(projectRoot) {
2849
2908
  if (!sourcePath) {
2850
2909
  return {};
2851
2910
  }
2852
- const directory = resolve16(projectRoot, sourcePath);
2853
- if (!existsSync14(directory)) {
2911
+ const directory = resolve17(projectRoot, sourcePath);
2912
+ if (!existsSync16(directory)) {
2854
2913
  return {};
2855
2914
  }
2856
2915
  const config = {};
2857
2916
  for (const name of readdirSync3(directory)) {
2858
2917
  if (!FILE_TASK_PATTERN2.test(name))
2859
2918
  continue;
2860
- const file = resolve16(directory, name);
2919
+ const file = resolve17(directory, name);
2861
2920
  try {
2862
2921
  if (!statSync3(file).isFile())
2863
2922
  continue;
2864
- const raw = JSON.parse(readFileSync9(file, "utf8"));
2923
+ const raw = JSON.parse(readFileSync10(file, "utf8"));
2865
2924
  if (!raw || typeof raw !== "object" || Array.isArray(raw))
2866
2925
  continue;
2867
2926
  const record = raw;
@@ -2903,10 +2962,10 @@ function firstStringList2(...candidates) {
2903
2962
  return [];
2904
2963
  }
2905
2964
  function readConfiguredFilesTaskSourcePath2(projectRoot) {
2906
- const jsonPath = resolve16(projectRoot, "rig.config.json");
2907
- if (existsSync14(jsonPath)) {
2965
+ const jsonPath = resolve17(projectRoot, "rig.config.json");
2966
+ if (existsSync16(jsonPath)) {
2908
2967
  try {
2909
- const parsed = JSON.parse(readFileSync9(jsonPath, "utf8"));
2968
+ const parsed = JSON.parse(readFileSync10(jsonPath, "utf8"));
2910
2969
  if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
2911
2970
  const taskSource = parsed.taskSource;
2912
2971
  if (taskSource && typeof taskSource === "object" && !Array.isArray(taskSource)) {
@@ -2918,12 +2977,12 @@ function readConfiguredFilesTaskSourcePath2(projectRoot) {
2918
2977
  return null;
2919
2978
  }
2920
2979
  }
2921
- const tsPath = resolve16(projectRoot, "rig.config.ts");
2922
- if (!existsSync14(tsPath)) {
2980
+ const tsPath = resolve17(projectRoot, "rig.config.ts");
2981
+ if (!existsSync16(tsPath)) {
2923
2982
  return null;
2924
2983
  }
2925
2984
  try {
2926
- const source = readFileSync9(tsPath, "utf8");
2985
+ const source = readFileSync10(tsPath, "utf8");
2927
2986
  const taskSourceBlock = source.match(/taskSource\s*:\s*\{[\s\S]*?\}/m)?.[0] ?? "";
2928
2987
  const kind = taskSourceBlock.match(/kind\s*:\s*["']([^"']+)["']/)?.[1];
2929
2988
  if (kind !== "files") {
@@ -2937,23 +2996,23 @@ function readConfiguredFilesTaskSourcePath2(projectRoot) {
2937
2996
  function sourceTaskConfigCandidates(projectRoot) {
2938
2997
  const runtimeContext = loadRuntimeContextFromEnv();
2939
2998
  return [
2940
- runtimeContext?.monorepoMainRoot ? resolve16(runtimeContext.monorepoMainRoot, ".rig", "task-config.json") : "",
2941
- process.env.MONOREPO_MAIN_ROOT?.trim() ? resolve16(process.env.MONOREPO_MAIN_ROOT.trim(), ".rig", "task-config.json") : "",
2942
- resolve16(resolveMonorepoRoot2(projectRoot), ".rig", "task-config.json")
2999
+ runtimeContext?.monorepoMainRoot ? resolve17(runtimeContext.monorepoMainRoot, ".rig", "task-config.json") : "",
3000
+ process.env.MONOREPO_MAIN_ROOT?.trim() ? resolve17(process.env.MONOREPO_MAIN_ROOT.trim(), ".rig", "task-config.json") : "",
3001
+ resolve17(resolveMonorepoRoot2(projectRoot), ".rig", "task-config.json")
2943
3002
  ].filter(Boolean);
2944
3003
  }
2945
3004
 
2946
3005
  // packages/runtime/src/control-plane/native/validator.ts
2947
- import { existsSync as existsSync18, mkdirSync as mkdirSync8, writeFileSync as writeFileSync8 } from "fs";
2948
- import { resolve as resolve21 } from "path";
3006
+ import { existsSync as existsSync20, mkdirSync as mkdirSync9, writeFileSync as writeFileSync9 } from "fs";
3007
+ import { resolve as resolve22 } from "path";
2949
3008
 
2950
3009
  // packages/runtime/src/control-plane/native/validator-binaries.ts
2951
- import { existsSync as existsSync17, mkdirSync as mkdirSync7, rmSync as rmSync5, statSync as statSync4 } from "fs";
2952
- import { dirname as dirname10, resolve as resolve20 } from "path";
3010
+ import { existsSync as existsSync19, mkdirSync as mkdirSync8, rmSync as rmSync5, statSync as statSync4 } from "fs";
3011
+ import { dirname as dirname11, resolve as resolve21 } from "path";
2953
3012
 
2954
3013
  // packages/runtime/src/binary-run.ts
2955
- import { chmodSync as chmodSync2, cpSync, existsSync as existsSync15, mkdirSync as mkdirSync6, renameSync as renameSync3, rmSync as rmSync4, writeFileSync as writeFileSync7 } from "fs";
2956
- import { basename as basename7, dirname as dirname9, resolve as resolve17 } from "path";
3014
+ import { chmodSync as chmodSync2, cpSync, existsSync as existsSync17, mkdirSync as mkdirSync7, renameSync as renameSync3, rmSync as rmSync4, writeFileSync as writeFileSync8 } from "fs";
3015
+ import { basename as basename7, dirname as dirname10, resolve as resolve18 } from "path";
2957
3016
  import { fileURLToPath } from "url";
2958
3017
  import { drainMicrotasks, gcAndSweep } from "bun:jsc";
2959
3018
  var runtimeBinaryBuildQueue = Promise.resolve();
@@ -2979,9 +3038,9 @@ async function buildRuntimeBinary(options) {
2979
3038
  });
2980
3039
  }
2981
3040
  async function buildRuntimeBinaryInProcess(options, manifest) {
2982
- const tempBuildDir = resolve17(dirname9(options.outputPath), `.bun-build-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`);
2983
- const tempOutputPath = resolve17(tempBuildDir, basename7(options.outputPath));
2984
- mkdirSync6(tempBuildDir, { recursive: true });
3041
+ const tempBuildDir = resolve18(dirname10(options.outputPath), `.bun-build-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`);
3042
+ const tempOutputPath = resolve18(tempBuildDir, basename7(options.outputPath));
3043
+ mkdirSync7(tempBuildDir, { recursive: true });
2985
3044
  await withTemporaryEnv({
2986
3045
  ...options.env,
2987
3046
  ...options.define ? { RIG_BUILD_CONFIG_JSON: JSON.stringify(options.define) } : {}
@@ -3006,7 +3065,7 @@ async function buildRuntimeBinaryInProcess(options, manifest) {
3006
3065
  `);
3007
3066
  throw new Error(`Failed to build ${options.entrypoint}: ${details || "Bun.build() returned errors"}`);
3008
3067
  }
3009
- if (!existsSync15(tempOutputPath)) {
3068
+ if (!existsSync17(tempOutputPath)) {
3010
3069
  const emitted = buildResult.outputs.map((output) => output.path).join(", ") || "(none)";
3011
3070
  throw new Error(`Failed to build ${options.entrypoint}: Bun.build() did not emit ${tempOutputPath}. Emitted: ${emitted}`);
3012
3071
  }
@@ -3038,8 +3097,8 @@ function runtimeBinaryCacheManifestPath(outputPath) {
3038
3097
  function resolveRuntimeBinaryBuildOptions(options) {
3039
3098
  return {
3040
3099
  ...options,
3041
- entrypoint: resolve17(options.cwd, options.sourcePath),
3042
- outputPath: resolve17(options.outputPath)
3100
+ entrypoint: resolve18(options.cwd, options.sourcePath),
3101
+ outputPath: resolve18(options.outputPath)
3043
3102
  };
3044
3103
  }
3045
3104
  function shouldUseRuntimeBinaryBuildWorker() {
@@ -3053,7 +3112,7 @@ function shouldUseRuntimeBinaryBuildWorker() {
3053
3112
  }
3054
3113
  async function buildRuntimeBinaryViaWorker(options) {
3055
3114
  const workerSourcePath = resolveRuntimeBinaryBuildWorkerSourcePath(options);
3056
- if (!workerSourcePath || !existsSync15(workerSourcePath)) {
3115
+ if (!workerSourcePath || !existsSync17(workerSourcePath)) {
3057
3116
  await buildRuntimeBinaryInProcess(options, {
3058
3117
  manifestPath: runtimeBinaryCacheManifestPath(options.outputPath),
3059
3118
  buildKey: createRuntimeBinaryBuildKey({
@@ -3090,7 +3149,7 @@ async function buildRuntimeBinaryViaWorker(options) {
3090
3149
  }
3091
3150
  }
3092
3151
  function createRuntimeBinaryBuildWorkerPayloadPath(outputPath) {
3093
- return resolve17(dirname9(outputPath), `.bun-build-worker-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}.json`);
3152
+ return resolve18(dirname10(outputPath), `.bun-build-worker-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}.json`);
3094
3153
  }
3095
3154
  function resolveRuntimeBinaryBuildWorkerSourcePath(options) {
3096
3155
  const envRoots = [
@@ -3099,13 +3158,13 @@ function resolveRuntimeBinaryBuildWorkerSourcePath(options) {
3099
3158
  process.env.PROJECT_RIG_ROOT?.trim()
3100
3159
  ].filter(Boolean);
3101
3160
  for (const root of envRoots) {
3102
- const candidate = resolve17(root, "packages/runtime/src/binary-build-worker.ts");
3103
- if (existsSync15(candidate)) {
3161
+ const candidate = resolve18(root, "packages/runtime/src/binary-build-worker.ts");
3162
+ if (existsSync17(candidate)) {
3104
3163
  return candidate;
3105
3164
  }
3106
3165
  }
3107
- const localCandidate = resolve17(import.meta.dir, "binary-build-worker.ts");
3108
- return existsSync15(localCandidate) ? localCandidate : null;
3166
+ const localCandidate = resolve18(import.meta.dir, "binary-build-worker.ts");
3167
+ return existsSync17(localCandidate) ? localCandidate : null;
3109
3168
  }
3110
3169
  function resolveRuntimeBinaryBuildWorkerInvocation() {
3111
3170
  const bunPath = Bun.which("bun");
@@ -3141,7 +3200,7 @@ function createRuntimeBinaryBuildKey(input) {
3141
3200
  });
3142
3201
  }
3143
3202
  async function isRuntimeBinaryBuildFresh(input) {
3144
- if (!existsSync15(input.outputPath) || !existsSync15(input.manifestPath)) {
3203
+ if (!existsSync17(input.outputPath) || !existsSync17(input.manifestPath)) {
3145
3204
  return false;
3146
3205
  }
3147
3206
  let manifest = null;
@@ -3154,7 +3213,7 @@ async function isRuntimeBinaryBuildFresh(input) {
3154
3213
  return false;
3155
3214
  }
3156
3215
  for (const [filePath, expectedDigest] of Object.entries(manifest.inputs || {})) {
3157
- if (!existsSync15(filePath)) {
3216
+ if (!existsSync17(filePath)) {
3158
3217
  return false;
3159
3218
  }
3160
3219
  if (await sha256File(filePath) !== expectedDigest) {
@@ -3167,7 +3226,7 @@ async function writeRuntimeBinaryCacheManifest(input) {
3167
3226
  const inputs = {};
3168
3227
  for (const inputPath of Object.keys(input.metafile?.inputs || {}).sort()) {
3169
3228
  const normalized = normalizeBuildInputPath(input.cwd, inputPath);
3170
- if (!normalized || !existsSync15(normalized)) {
3229
+ if (!normalized || !existsSync17(normalized)) {
3171
3230
  continue;
3172
3231
  }
3173
3232
  inputs[normalized] = await sha256File(normalized);
@@ -3190,7 +3249,7 @@ function normalizeBuildInputPath(cwd, inputPath) {
3190
3249
  if (inputPath.startsWith("<")) {
3191
3250
  return null;
3192
3251
  }
3193
- return resolve17(cwd, inputPath);
3252
+ return resolve18(cwd, inputPath);
3194
3253
  }
3195
3254
  async function sha256File(path) {
3196
3255
  const hasher = new Bun.CryptoHasher("sha256");
@@ -3206,8 +3265,8 @@ function sortRecord(value) {
3206
3265
  async function runSerializedRuntimeBinaryBuild(action) {
3207
3266
  const previous = runtimeBinaryBuildQueue;
3208
3267
  let release;
3209
- runtimeBinaryBuildQueue = new Promise((resolve18) => {
3210
- release = resolve18;
3268
+ runtimeBinaryBuildQueue = new Promise((resolve19) => {
3269
+ release = resolve19;
3211
3270
  });
3212
3271
  await previous;
3213
3272
  try {
@@ -3252,11 +3311,11 @@ async function withTemporaryCwd(cwd, action) {
3252
3311
  }
3253
3312
 
3254
3313
  // packages/runtime/src/control-plane/runtime/provisioning-env.ts
3255
- import { delimiter, resolve as resolve19 } from "path";
3314
+ import { delimiter, resolve as resolve20 } from "path";
3256
3315
 
3257
3316
  // packages/runtime/src/control-plane/runtime/runtime-paths.ts
3258
- import { existsSync as existsSync16, readdirSync as readdirSync4, realpathSync } from "fs";
3259
- import { resolve as resolve18 } from "path";
3317
+ import { existsSync as existsSync18, readdirSync as readdirSync4, realpathSync } from "fs";
3318
+ import { resolve as resolve19 } from "path";
3260
3319
 
3261
3320
  // packages/runtime/src/control-plane/runtime/sandbox/utils.ts
3262
3321
  function uniq(values) {
@@ -3274,7 +3333,7 @@ function resolveBunBinaryPath() {
3274
3333
  }
3275
3334
  const home = process.env.HOME?.trim();
3276
3335
  const fallbackCandidates = [
3277
- home ? resolve18(home, ".bun/bin/bun") : "",
3336
+ home ? resolve19(home, ".bun/bin/bun") : "",
3278
3337
  "/opt/homebrew/bin/bun",
3279
3338
  "/usr/local/bin/bun",
3280
3339
  "/usr/bin/bun"
@@ -3302,8 +3361,8 @@ function resolveClaudeBinaryPath() {
3302
3361
  }
3303
3362
  const home = process.env.HOME?.trim();
3304
3363
  const fallbackCandidates = [
3305
- home ? resolve18(home, ".local/bin/claude") : "",
3306
- home ? resolve18(home, ".local/share/claude/local/claude") : "",
3364
+ home ? resolve19(home, ".local/bin/claude") : "",
3365
+ home ? resolve19(home, ".local/share/claude/local/claude") : "",
3307
3366
  "/opt/homebrew/bin/claude",
3308
3367
  "/usr/local/bin/claude",
3309
3368
  "/usr/bin/claude"
@@ -3317,51 +3376,51 @@ function resolveClaudeBinaryPath() {
3317
3376
  throw new Error("claude not found in PATH");
3318
3377
  }
3319
3378
  function resolveBunInstallDir(bunBinaryPath = resolveBunBinaryPath()) {
3320
- return resolve18(bunBinaryPath, "../..");
3379
+ return resolve19(bunBinaryPath, "../..");
3321
3380
  }
3322
3381
  function resolveClaudeInstallDir() {
3323
3382
  const realPath = resolveClaudeBinaryPath();
3324
- return resolve18(realPath, "..");
3383
+ return resolve19(realPath, "..");
3325
3384
  }
3326
3385
  function resolveNodeInstallDir() {
3327
3386
  const preferredNode = resolvePreferredNodeBinary();
3328
3387
  if (!preferredNode)
3329
3388
  return null;
3330
3389
  const explicitNode = process.env.RIG_NODE_BIN?.trim();
3331
- if (explicitNode && resolve18(explicitNode) === resolve18(preferredNode)) {
3332
- return preferredNode.endsWith("/bin/node") ? resolve18(preferredNode, "../..") : resolve18(preferredNode, "..");
3390
+ if (explicitNode && resolve19(explicitNode) === resolve19(preferredNode)) {
3391
+ return preferredNode.endsWith("/bin/node") ? resolve19(preferredNode, "../..") : resolve19(preferredNode, "..");
3333
3392
  }
3334
3393
  try {
3335
3394
  const realPath = realpathSync(preferredNode);
3336
3395
  if (realPath.endsWith("/bin/node")) {
3337
- return resolve18(realPath, "../..");
3396
+ return resolve19(realPath, "../..");
3338
3397
  }
3339
- return resolve18(realPath, "..");
3398
+ return resolve19(realPath, "..");
3340
3399
  } catch {
3341
- return resolve18(preferredNode, "..");
3400
+ return resolve19(preferredNode, "..");
3342
3401
  }
3343
3402
  }
3344
3403
  function resolvePreferredNodeBinary() {
3345
3404
  const candidates = [];
3346
3405
  const envNode = process.env.RIG_NODE_BIN?.trim();
3347
3406
  if (envNode) {
3348
- const explicit = resolve18(envNode);
3349
- if (existsSync16(explicit)) {
3407
+ const explicit = resolve19(envNode);
3408
+ if (existsSync18(explicit)) {
3350
3409
  return explicit;
3351
3410
  }
3352
3411
  }
3353
3412
  const nvmBin = process.env.NVM_BIN?.trim();
3354
3413
  if (nvmBin) {
3355
- candidates.push(resolve18(nvmBin, "node"));
3414
+ candidates.push(resolve19(nvmBin, "node"));
3356
3415
  }
3357
3416
  const home = process.env.HOME?.trim();
3358
3417
  if (home) {
3359
- const nvmVersionsDir = resolve18(home, ".nvm/versions/node");
3360
- if (existsSync16(nvmVersionsDir)) {
3418
+ const nvmVersionsDir = resolve19(home, ".nvm/versions/node");
3419
+ if (existsSync18(nvmVersionsDir)) {
3361
3420
  try {
3362
3421
  const versionDirs = readdirSync4(nvmVersionsDir).map((entry) => entry.trim()).filter((entry) => /^v\d+\.\d+\.\d+$/.test(entry)).sort((a, b) => Bun.semver.order(b.replace(/^v/, ""), a.replace(/^v/, "")));
3363
3422
  for (const versionDir of versionDirs) {
3364
- candidates.push(resolve18(nvmVersionsDir, versionDir, "bin/node"));
3423
+ candidates.push(resolve19(nvmVersionsDir, versionDir, "bin/node"));
3365
3424
  }
3366
3425
  } catch {}
3367
3426
  }
@@ -3370,8 +3429,8 @@ function resolvePreferredNodeBinary() {
3370
3429
  if (whichNode) {
3371
3430
  candidates.push(whichNode);
3372
3431
  }
3373
- const deduped = uniq(candidates.map((candidate) => resolve18(candidate)));
3374
- const existing = deduped.filter((candidate) => existsSync16(candidate));
3432
+ const deduped = uniq(candidates.map((candidate) => resolve19(candidate)));
3433
+ const existing = deduped.filter((candidate) => existsSync18(candidate));
3375
3434
  if (existing.length === 0) {
3376
3435
  return null;
3377
3436
  }
@@ -3385,7 +3444,7 @@ function resolvePreferredNodeBinary() {
3385
3444
  return existing[0] ?? null;
3386
3445
  }
3387
3446
  function inferNodeMajor(nodeBinaryPath) {
3388
- const normalized = resolve18(nodeBinaryPath).replace(/\\/g, "/");
3447
+ const normalized = resolve19(nodeBinaryPath).replace(/\\/g, "/");
3389
3448
  const match = normalized.match(/(?:^|\/)(?:node-)?v?(\d+)\.\d+\.\d+(?:\/|$)/);
3390
3449
  if (!match) {
3391
3450
  return null;
@@ -3397,8 +3456,8 @@ function normalizeExecutablePath(candidate) {
3397
3456
  if (!candidate) {
3398
3457
  return "";
3399
3458
  }
3400
- const normalized = resolve18(candidate);
3401
- if (!existsSync16(normalized)) {
3459
+ const normalized = resolve19(candidate);
3460
+ if (!existsSync18(normalized)) {
3402
3461
  return "";
3403
3462
  }
3404
3463
  try {
@@ -3408,7 +3467,7 @@ function normalizeExecutablePath(candidate) {
3408
3467
  }
3409
3468
  }
3410
3469
  function looksLikeRuntimeGateway(candidate) {
3411
- const normalized = resolve18(candidate).replace(/\\/g, "/");
3470
+ const normalized = resolve19(candidate).replace(/\\/g, "/");
3412
3471
  return normalized.includes("/.rig/bin/") || normalized.endsWith("/rig-shell") || normalized.endsWith("/rig-agent");
3413
3472
  }
3414
3473
 
@@ -3429,7 +3488,7 @@ function runtimeProvisioningEnv(baseEnv = process.env) {
3429
3488
  try {
3430
3489
  return resolveClaudeInstallDir();
3431
3490
  } catch {
3432
- return resolve19(claudeBinary, "..");
3491
+ return resolve20(claudeBinary, "..");
3433
3492
  }
3434
3493
  })() : "";
3435
3494
  const nodeDir = resolveNodeInstallDir();
@@ -3439,8 +3498,8 @@ function runtimeProvisioningEnv(baseEnv = process.env) {
3439
3498
  `${bunDir}/bin`,
3440
3499
  claudeDir,
3441
3500
  nodeDir ? `${nodeDir}/bin` : "",
3442
- realHome ? resolve19(realHome, ".local/bin") : "",
3443
- realHome ? resolve19(realHome, ".cargo/bin") : "",
3501
+ realHome ? resolve20(realHome, ".local/bin") : "",
3502
+ realHome ? resolve20(realHome, ".cargo/bin") : "",
3444
3503
  ...inheritedPath,
3445
3504
  "/usr/local/bin",
3446
3505
  "/usr/local/sbin",
@@ -3471,9 +3530,9 @@ function runtimeProvisioningEnv(baseEnv = process.env) {
3471
3530
  // packages/runtime/src/control-plane/native/validator-binaries.ts
3472
3531
  function resolveValidatorBinaryPath(projectRoot, binaryName, runtimeContext) {
3473
3532
  if (runtimeContext) {
3474
- return resolve20(runtimeContext.binDir, "validators", binaryName);
3533
+ return resolve21(runtimeContext.binDir, "validators", binaryName);
3475
3534
  }
3476
- return resolve20(resolveHarnessPaths(projectRoot).binDir, "validators", binaryName);
3535
+ return resolve21(resolveHarnessPaths(projectRoot).binDir, "validators", binaryName);
3477
3536
  }
3478
3537
  async function ensureValidatorBinary(projectRoot, checkId, runtimeContext) {
3479
3538
  const match = checkId.match(/^([a-z][\w-]*):([a-z][\w-]*)$/);
@@ -3488,19 +3547,19 @@ async function ensureValidatorBinary(projectRoot, checkId, runtimeContext) {
3488
3547
  const binaryName = `${category}-${check}`;
3489
3548
  const binaryPath = resolveValidatorBinaryPath(projectRoot, binaryName, runtimeContext);
3490
3549
  const hostProjectRoot = runtimeContext?.hostProjectRoot?.trim() || projectRoot;
3491
- const sourcePath = resolve20(hostProjectRoot, "packages/runtime/src/control-plane/validators", category, `${check}.ts`);
3492
- if (!existsSync17(sourcePath)) {
3550
+ const sourcePath = resolve21(hostProjectRoot, "packages/runtime/src/control-plane/validators", category, `${check}.ts`);
3551
+ if (!existsSync19(sourcePath)) {
3493
3552
  return null;
3494
3553
  }
3495
3554
  const sourceMtime = statSync4(sourcePath).mtimeMs;
3496
- const binaryExists = existsSync17(binaryPath);
3555
+ const binaryExists = existsSync19(binaryPath);
3497
3556
  const binaryMtime = binaryExists ? statSync4(binaryPath).mtimeMs : 0;
3498
3557
  if (!binaryExists || sourceMtime > binaryMtime) {
3499
3558
  if (binaryExists) {
3500
3559
  rmSync5(binaryPath, { force: true });
3501
3560
  rmSync5(`${binaryPath}.build-manifest.json`, { force: true });
3502
3561
  }
3503
- mkdirSync7(dirname10(binaryPath), { recursive: true });
3562
+ mkdirSync8(dirname11(binaryPath), { recursive: true });
3504
3563
  await buildRuntimeBinary({
3505
3564
  sourcePath: `packages/runtime/src/control-plane/validators/${category}/${check}.ts`,
3506
3565
  outputPath: binaryPath,
@@ -3509,7 +3568,7 @@ async function ensureValidatorBinary(projectRoot, checkId, runtimeContext) {
3509
3568
  env: runtimeProvisioningEnv()
3510
3569
  });
3511
3570
  }
3512
- return existsSync17(binaryPath) ? binaryPath : null;
3571
+ return existsSync19(binaryPath) ? binaryPath : null;
3513
3572
  }
3514
3573
 
3515
3574
  // packages/runtime/src/control-plane/native/validator.ts
@@ -3546,20 +3605,20 @@ async function readTaskSourceValidation(projectRoot, taskId) {
3546
3605
  function resolveValidationPaths(projectRoot, taskId, runtimeContext) {
3547
3606
  if (runtimeContext) {
3548
3607
  return {
3549
- taskLogDir: resolve21(runtimeContext.logsDir, taskId),
3550
- artifactDir: resolve21(runtimeContext.workspaceDir, "artifacts", taskId)
3608
+ taskLogDir: resolve22(runtimeContext.logsDir, taskId),
3609
+ artifactDir: resolve22(runtimeContext.workspaceDir, "artifacts", taskId)
3551
3610
  };
3552
3611
  }
3553
3612
  const paths = resolveHarnessPaths(projectRoot);
3554
3613
  return {
3555
- taskLogDir: resolve21(paths.logsDir, taskId),
3556
- artifactDir: resolve21(paths.artifactsDir, taskId)
3614
+ taskLogDir: resolve22(paths.logsDir, taskId),
3615
+ artifactDir: resolve22(paths.artifactsDir, taskId)
3557
3616
  };
3558
3617
  }
3559
3618
  async function runValidatorBinary(projectRoot, taskId, checkId, runtimeContext) {
3560
3619
  const binaryName = checkId.replace(":", "-");
3561
3620
  const binaryPath = await ensureValidatorBinary(projectRoot, checkId, runtimeContext) ?? resolveValidatorBinaryPath(projectRoot, binaryName, runtimeContext);
3562
- if (!existsSync18(binaryPath)) {
3621
+ if (!existsSync20(binaryPath)) {
3563
3622
  return {
3564
3623
  result: {
3565
3624
  id: checkId,
@@ -3570,7 +3629,7 @@ async function runValidatorBinary(projectRoot, taskId, checkId, runtimeContext)
3570
3629
  };
3571
3630
  }
3572
3631
  const validatorCwd = runtimeContext?.workspaceDir || resolveMonorepoRoot(projectRoot);
3573
- const runtimeShellPath = runtimeContext ? resolve21(runtimeContext.binDir, "rig-shell") : "";
3632
+ const runtimeShellPath = runtimeContext ? resolve22(runtimeContext.binDir, "rig-shell") : "";
3574
3633
  const monorepoMainRoot = runtimeContext?.monorepoMainRoot || process.env.MONOREPO_MAIN_ROOT?.trim() || resolveMonorepoRoot(projectRoot);
3575
3634
  const validatorEnv = {
3576
3635
  PROJECT_RIG_ROOT: runtimeContext?.hostProjectRoot || projectRoot,
@@ -3585,7 +3644,7 @@ async function runValidatorBinary(projectRoot, taskId, checkId, runtimeContext)
3585
3644
  validatorEnv.RIG_LOGS_DIR = runtimeContext.logsDir;
3586
3645
  validatorEnv.RIG_RUNTIME_BIN_DIR = runtimeContext.binDir;
3587
3646
  }
3588
- const { exitCode, stdout, stderr } = await runCaptureAsync(runtimeShellPath && existsSync18(runtimeShellPath) ? [runtimeShellPath, "run-binary", binaryPath] : [binaryPath], validatorCwd, validatorEnv);
3647
+ const { exitCode, stdout, stderr } = await runCaptureAsync(runtimeShellPath && existsSync20(runtimeShellPath) ? [runtimeShellPath, "run-binary", binaryPath] : [binaryPath], validatorCwd, validatorEnv);
3589
3648
  try {
3590
3649
  const result = JSON.parse(stdout.trim());
3591
3650
  return { result, exitCode };
@@ -3625,8 +3684,8 @@ async function validateTask(projectRoot, taskId, runtimeContext, registry, optio
3625
3684
  const configuredValidation = stringArray(taskConfig[taskId]?.validation);
3626
3685
  const commands = resolvedContext?.validation?.length ? resolvedContext.validation : configuredValidation.length > 0 ? configuredValidation : sourceValidation.validation;
3627
3686
  const { taskLogDir, artifactDir } = resolveValidationPaths(projectRoot, taskId, resolvedContext);
3628
- mkdirSync8(taskLogDir, { recursive: true });
3629
- mkdirSync8(artifactDir, { recursive: true });
3687
+ mkdirSync9(taskLogDir, { recursive: true });
3688
+ mkdirSync9(artifactDir, { recursive: true });
3630
3689
  if (commands.length === 0) {
3631
3690
  const skipped = {
3632
3691
  status: "skipped",
@@ -3635,7 +3694,7 @@ async function validateTask(projectRoot, taskId, runtimeContext, registry, optio
3635
3694
  failed: 0,
3636
3695
  categories: []
3637
3696
  };
3638
- writeFileSync8(resolve21(artifactDir, "validation-summary.json"), `${JSON.stringify(skipped, null, 2)}
3697
+ writeFileSync9(resolve22(artifactDir, "validation-summary.json"), `${JSON.stringify(skipped, null, 2)}
3639
3698
  `, "utf-8");
3640
3699
  return skipped;
3641
3700
  }
@@ -3670,18 +3729,18 @@ async function validateTask(projectRoot, taskId, runtimeContext, registry, optio
3670
3729
  exit_code: 2,
3671
3730
  duration_seconds: 0
3672
3731
  });
3673
- const logFile2 = resolve21(taskLogDir, `invalid-entry-validation.log`);
3674
- mkdirSync8(taskLogDir, { recursive: true });
3675
- writeFileSync8(logFile2, `=== ${nowIso()} :: ${cmd} ===
3732
+ const logFile2 = resolve22(taskLogDir, `invalid-entry-validation.log`);
3733
+ mkdirSync9(taskLogDir, { recursive: true });
3734
+ writeFileSync9(logFile2, `=== ${nowIso()} :: ${cmd} ===
3676
3735
  Invalid validation entry: not a check-ID. All entries must use format "category:check-name".
3677
3736
  `, "utf-8");
3678
3737
  continue;
3679
3738
  }
3680
3739
  const { result, exitCode } = await dispatchValidator(cmd, effectiveRegistry, validatorCtx, (id) => runValidatorBinary(projectRoot, taskId, id, resolvedContext));
3681
3740
  const durationSeconds = Math.max(0, Math.round((Date.now() - startedAt) / 1000));
3682
- const logFile = resolve21(taskLogDir, `${cmd.replace(":", "-")}-validation.log`);
3683
- mkdirSync8(taskLogDir, { recursive: true });
3684
- writeFileSync8(logFile, `=== ${nowIso()} :: ${cmd} ===
3741
+ const logFile = resolve22(taskLogDir, `${cmd.replace(":", "-")}-validation.log`);
3742
+ mkdirSync9(taskLogDir, { recursive: true });
3743
+ writeFileSync9(logFile, `=== ${nowIso()} :: ${cmd} ===
3685
3744
  ${JSON.stringify(result, null, 2)}
3686
3745
  `, "utf-8");
3687
3746
  if (result.passed) {
@@ -3703,15 +3762,15 @@ ${JSON.stringify(result, null, 2)}
3703
3762
  failed,
3704
3763
  categories
3705
3764
  };
3706
- mkdirSync8(artifactDir, { recursive: true });
3707
- writeFileSync8(resolve21(artifactDir, "validation-summary.json"), `${JSON.stringify(summary, null, 2)}
3765
+ mkdirSync9(artifactDir, { recursive: true });
3766
+ writeFileSync9(resolve22(artifactDir, "validation-summary.json"), `${JSON.stringify(summary, null, 2)}
3708
3767
  `, "utf-8");
3709
3768
  return summary;
3710
3769
  }
3711
3770
 
3712
3771
  // packages/runtime/src/control-plane/native/verifier.ts
3713
- import { existsSync as existsSync20, mkdirSync as mkdirSync10, writeFileSync as writeFileSync10 } from "fs";
3714
- import { resolve as resolve23 } from "path";
3772
+ import { existsSync as existsSync22, mkdirSync as mkdirSync11, writeFileSync as writeFileSync11 } from "fs";
3773
+ import { resolve as resolve24 } from "path";
3715
3774
 
3716
3775
  // packages/runtime/src/control-plane/runtime/baked-secrets.ts
3717
3776
  var BAKED_RUNTIME_SECRETS = {
@@ -3757,8 +3816,8 @@ function resolveRuntimeSecrets(env, baked = BAKED_RUNTIME_SECRETS) {
3757
3816
  }
3758
3817
 
3759
3818
  // packages/runtime/src/control-plane/native/git-ops.ts
3760
- import { existsSync as existsSync19, lstatSync, mkdirSync as mkdirSync9, readFileSync as readFileSync10, writeFileSync as writeFileSync9 } from "fs";
3761
- import { dirname as dirname11, isAbsolute as isAbsolute2, resolve as resolve22 } from "path";
3819
+ import { existsSync as existsSync21, lstatSync, mkdirSync as mkdirSync10, readFileSync as readFileSync11, writeFileSync as writeFileSync10 } from "fs";
3820
+ import { dirname as dirname12, isAbsolute as isAbsolute2, resolve as resolve23 } from "path";
3762
3821
 
3763
3822
  // packages/runtime/src/control-plane/native/pr-review-gate.ts
3764
3823
  function parseJsonObject(value) {
@@ -5015,12 +5074,12 @@ var TASK_ARTIFACT_STAGE_FALLBACK = new Set([
5015
5074
  "validation-summary.json"
5016
5075
  ]);
5017
5076
  function readPrMetadata(projectRoot, taskId) {
5018
- const path = resolve22(artifactDirForId(projectRoot, taskId), "pr-state.json");
5019
- if (!existsSync19(path)) {
5077
+ const path = resolve23(artifactDirForId(projectRoot, taskId), "pr-state.json");
5078
+ if (!existsSync21(path)) {
5020
5079
  return [];
5021
5080
  }
5022
5081
  try {
5023
- const parsed = JSON.parse(readFileSync10(path, "utf-8"));
5082
+ const parsed = JSON.parse(readFileSync11(path, "utf-8"));
5024
5083
  if (!parsed || typeof parsed !== "object") {
5025
5084
  return [];
5026
5085
  }
@@ -5046,11 +5105,11 @@ async function verifyTask(options) {
5046
5105
  const taskId = options.taskId;
5047
5106
  const normalizedTaskId = lookupTask(options.projectRoot, taskId);
5048
5107
  const artifactDir = artifactDirForId(options.projectRoot, taskId);
5049
- mkdirSync10(artifactDir, { recursive: true });
5050
- const validationSummaryPath = resolve23(artifactDir, "validation-summary.json");
5051
- const reviewFeedbackPath = resolve23(artifactDir, "review-feedback.md");
5052
- const reviewStatePath = resolve23(artifactDir, "review-state.json");
5053
- const greptileRawPath = resolve23(artifactDir, "review-greptile-raw.json");
5108
+ mkdirSync11(artifactDir, { recursive: true });
5109
+ const validationSummaryPath = resolve24(artifactDir, "validation-summary.json");
5110
+ const reviewFeedbackPath = resolve24(artifactDir, "review-feedback.md");
5111
+ const reviewStatePath = resolve24(artifactDir, "review-state.json");
5112
+ const greptileRawPath = resolve24(artifactDir, "review-greptile-raw.json");
5054
5113
  const prStates = readPrMetadata(options.projectRoot, taskId);
5055
5114
  const prState = prStates[0] || null;
5056
5115
  const localReasons = [];
@@ -5062,7 +5121,7 @@ async function verifyTask(options) {
5062
5121
  if (!normalizedTaskId && !await hasConfiguredSourceTask(options.projectRoot, taskId)) {
5063
5122
  localReasons.push(`[Task Config] Unknown task id '${taskId}' in task-config or configured task source.`);
5064
5123
  }
5065
- if (!existsSync20(validationSummaryPath)) {
5124
+ if (!existsSync22(validationSummaryPath)) {
5066
5125
  localReasons.push(`[Artifact Quality] validation-summary.json not found at ${validationSummaryPath}.`);
5067
5126
  } else {
5068
5127
  const summary = await parseValidationSummary(validationSummaryPath);
@@ -5071,13 +5130,13 @@ async function verifyTask(options) {
5071
5130
  }
5072
5131
  }
5073
5132
  for (const file of ["task-result.json", "decision-log.md", "next-actions.md", "changed-files.txt"]) {
5074
- const requiredPath = resolve23(artifactDir, file);
5075
- if (!existsSync20(requiredPath)) {
5133
+ const requiredPath = resolve24(artifactDir, file);
5134
+ if (!existsSync22(requiredPath)) {
5076
5135
  localReasons.push(`[Artifact Quality] Missing required artifact file: ${requiredPath}`);
5077
5136
  }
5078
5137
  }
5079
- const taskResultPath = resolve23(artifactDir, "task-result.json");
5080
- if (existsSync20(taskResultPath)) {
5138
+ const taskResultPath = resolve24(artifactDir, "task-result.json");
5139
+ if (existsSync22(taskResultPath)) {
5081
5140
  const taskResult = await readJsonFile2(taskResultPath);
5082
5141
  const artifactStatus = typeof taskResult?.status === "string" ? taskResult.status.trim().toLowerCase() : "";
5083
5142
  if (artifactStatus === "partial") {
@@ -5090,8 +5149,8 @@ async function verifyTask(options) {
5090
5149
  localReasons.push("[Artifact Quality] task-result.json next actions indicate remaining implementation scope.");
5091
5150
  }
5092
5151
  }
5093
- const nextActionsPath = resolve23(artifactDir, "next-actions.md");
5094
- if (existsSync20(nextActionsPath)) {
5152
+ const nextActionsPath = resolve24(artifactDir, "next-actions.md");
5153
+ if (existsSync22(nextActionsPath)) {
5095
5154
  const nextActionsContent = await Bun.file(nextActionsPath).text();
5096
5155
  if (nextActionsContent.includes("TODO: Replace this scaffold") || nextActionsContent.includes("bd-<downstream-task-id>")) {
5097
5156
  localReasons.push("[Artifact Quality] next-actions.md still contains scaffold placeholder text. Replace with real recommendations.");
@@ -5122,7 +5181,7 @@ async function verifyTask(options) {
5122
5181
  aiReasons.push(`[AI Review] Required mode needs a completed Greptile approval; current verdict is ${ai.verdict}.`);
5123
5182
  }
5124
5183
  if (persistArtifacts && ai.rawResponse) {
5125
- writeFileSync10(greptileRawPath, `${ai.rawResponse}
5184
+ writeFileSync11(greptileRawPath, `${ai.rawResponse}
5126
5185
  `, "utf-8");
5127
5186
  }
5128
5187
  } else if (!options.skipAiReview && reviewMode === "off") {
@@ -5365,7 +5424,7 @@ function evaluateSourceCloseoutChecks(prState, prLabel) {
5365
5424
  if (!Array.isArray(checks) || checks.length === 0) {
5366
5425
  return [`[Source Issue] PR ${prLabel} must have green check evidence before completion.`];
5367
5426
  }
5368
- const ciGate = evaluatePullRequestCiChecks(checks, "PR", 0);
5427
+ const ciGate = evaluatePullRequestCiChecks(checks, "PR", 0, { mergeStateStatus: prState.mergeStateStatus });
5369
5428
  if (ciGate.verdict === "APPROVE") {
5370
5429
  return [];
5371
5430
  }
@@ -5461,7 +5520,7 @@ function isAcceptedValidationSummary(summary) {
5461
5520
  return summary.status === "skipped" && summary.total === 0 && summary.failed === 0;
5462
5521
  }
5463
5522
  async function loadReviewMode(reviewProfilePath, fallback) {
5464
- const parsed = existsSync20(reviewProfilePath) ? await readJsonFile2(reviewProfilePath) : null;
5523
+ const parsed = existsSync22(reviewProfilePath) ? await readJsonFile2(reviewProfilePath) : null;
5465
5524
  const mode = parsed?.mode;
5466
5525
  if (mode === "off" || mode === "advisory" || mode === "required") {
5467
5526
  return mode;
@@ -5472,7 +5531,7 @@ async function loadReviewMode(reviewProfilePath, fallback) {
5472
5531
  return "advisory";
5473
5532
  }
5474
5533
  async function loadReviewProvider(reviewProfilePath, fallback) {
5475
- const parsed = existsSync20(reviewProfilePath) ? await readJsonFile2(reviewProfilePath) : null;
5534
+ const parsed = existsSync22(reviewProfilePath) ? await readJsonFile2(reviewProfilePath) : null;
5476
5535
  const provider = parsed?.provider;
5477
5536
  if (typeof provider === "string" && provider.trim().length > 0) {
5478
5537
  return provider;
@@ -5631,7 +5690,7 @@ function writeFeedbackFile(options) {
5631
5690
  if (options.aiRawFeedback) {
5632
5691
  lines.push("## Raw Reviewer Feedback", "", "```text", options.aiRawFeedback, "```", "");
5633
5692
  }
5634
- writeFileSync10(options.output, `${lines.join(`
5693
+ writeFileSync11(options.output, `${lines.join(`
5635
5694
  `)}
5636
5695
  `, "utf-8");
5637
5696
  }
@@ -5648,7 +5707,7 @@ function writeReviewStateFile(options) {
5648
5707
  ai_warnings: options.aiWarnings,
5649
5708
  updated_at: nowIso()
5650
5709
  };
5651
- writeFileSync10(options.output, `${JSON.stringify(payload, null, 2)}
5710
+ writeFileSync11(options.output, `${JSON.stringify(payload, null, 2)}
5652
5711
  `, "utf-8");
5653
5712
  }
5654
5713
  async function runGreptileReviewForPr(options) {
@@ -5729,7 +5788,7 @@ async function runGreptileReviewForPr(options) {
5729
5788
  }
5730
5789
  await Bun.sleep(options.pollIntervalMs);
5731
5790
  }
5732
- const ciGate = evaluatePullRequestCiChecks(githubCheckRollup, repoName, prNumber);
5791
+ const ciGate = evaluatePullRequestCiChecks(githubCheckRollup, repoName, prNumber, { mergeStateStatus: options.prState.mergeStateStatus });
5733
5792
  if (ciGate.verdict !== "APPROVE") {
5734
5793
  return {
5735
5794
  verdict: ciGate.verdict,
@@ -5987,7 +6046,7 @@ async function runGithubGreptileFallbackReviewForPr(options) {
5987
6046
  }
5988
6047
  await Bun.sleep(options.pollIntervalMs);
5989
6048
  }
5990
- const ciGate = evaluatePullRequestCiChecks(checkRollup, repoName, prNumber);
6049
+ const ciGate = evaluatePullRequestCiChecks(checkRollup, repoName, prNumber, { mergeStateStatus: options.prState.mergeStateStatus });
5991
6050
  if (ciGate.verdict !== "APPROVE") {
5992
6051
  return {
5993
6052
  verdict: ciGate.verdict,
@@ -6342,7 +6401,7 @@ function loadGithubPullRequestCheckRollup(projectRoot, repoName, prNumber) {
6342
6401
  ]);
6343
6402
  return response.statusCheckRollup || [];
6344
6403
  }
6345
- function evaluatePullRequestCiChecks(checks, repoName, prNumber) {
6404
+ function evaluatePullRequestCiChecks(checks, repoName, prNumber, options = {}) {
6346
6405
  const nonGreptileChecks = checks.filter((check) => {
6347
6406
  const label = (check.name || check.context || "").toLowerCase();
6348
6407
  return label.length > 0 && !label.includes("greptile");
@@ -6354,7 +6413,8 @@ function evaluatePullRequestCiChecks(checks, repoName, prNumber) {
6354
6413
  const state = (check.state || check.status || "").toUpperCase();
6355
6414
  return state === "PENDING" || state === "EXPECTED" || state === "QUEUED" || state === "IN_PROGRESS";
6356
6415
  });
6357
- if (pending.length > 0) {
6416
+ const mergeClean = (options.mergeStateStatus || "").toUpperCase() === "CLEAN";
6417
+ if (pending.length > 0 && !mergeClean) {
6358
6418
  return {
6359
6419
  verdict: "SKIP",
6360
6420
  reasons: pending.map((check) => `[CI] ${repoName}#${prNumber} check is still pending: ${check.name || check.context || "unknown"}.`)
@@ -6435,7 +6495,7 @@ function filterActionableGithubGreptileThreads(threads) {
6435
6495
  }
6436
6496
  function resolvePrRepoRoot(projectRoot, prState) {
6437
6497
  const runtimeWorkspace = process.env.RIG_TASK_WORKSPACE?.trim();
6438
- if (prState.target === "monorepo" && runtimeWorkspace && existsSync20(resolve23(runtimeWorkspace, ".git"))) {
6498
+ if (prState.target === "monorepo" && runtimeWorkspace && existsSync22(resolve24(runtimeWorkspace, ".git"))) {
6439
6499
  return runtimeWorkspace;
6440
6500
  }
6441
6501
  const paths = resolveHarnessPaths(projectRoot);
@@ -6815,16 +6875,16 @@ async function taskDeps(projectRoot, taskId) {
6815
6875
  for (const dep of deps) {
6816
6876
  const artifactDir = artifactDirForId(projectRoot, dep);
6817
6877
  console.log(`=== ${dep} ===`);
6818
- if (!existsSync21(artifactDir)) {
6878
+ if (!existsSync23(artifactDir)) {
6819
6879
  console.log(` (no artifacts yet)
6820
6880
  `);
6821
6881
  continue;
6822
6882
  }
6823
- printArtifactSection(resolve24(artifactDir, "decision-log.md"), "--- Decisions ---");
6824
- printArtifactSection(resolve24(artifactDir, "next-actions.md"), "--- Next Actions (for you) ---");
6825
- const changedFiles = resolve24(artifactDir, "changed-files.txt");
6826
- if (existsSync21(changedFiles)) {
6827
- const lines = readFileSync11(changedFiles, "utf-8").split(/\r?\n/).filter(Boolean);
6883
+ printArtifactSection(resolve25(artifactDir, "decision-log.md"), "--- Decisions ---");
6884
+ printArtifactSection(resolve25(artifactDir, "next-actions.md"), "--- Next Actions (for you) ---");
6885
+ const changedFiles = resolve25(artifactDir, "changed-files.txt");
6886
+ if (existsSync23(changedFiles)) {
6887
+ const lines = readFileSync12(changedFiles, "utf-8").split(/\r?\n/).filter(Boolean);
6828
6888
  console.log(`--- Changed Files (${lines.length}) ---`);
6829
6889
  for (const line of lines) {
6830
6890
  console.log(line);
@@ -6869,12 +6929,12 @@ function taskRecord(projectRoot, type, text, taskId) {
6869
6929
  throw new Error("No active task.");
6870
6930
  }
6871
6931
  const paths = resolveHarnessPaths(projectRoot);
6872
- mkdirSync11(paths.stateDir, { recursive: true });
6932
+ mkdirSync12(paths.stateDir, { recursive: true });
6873
6933
  if (type === "decision") {
6874
- const artifactDir = resolve24(paths.artifactsDir, activeTask);
6875
- mkdirSync11(artifactDir, { recursive: true });
6934
+ const artifactDir = resolve25(paths.artifactsDir, activeTask);
6935
+ mkdirSync12(artifactDir, { recursive: true });
6876
6936
  const timestamp = nowIso();
6877
- appendFileSync(resolve24(artifactDir, "decision-log.md"), `
6937
+ appendFileSync(resolve25(artifactDir, "decision-log.md"), `
6878
6938
  ### ${timestamp}
6879
6939
 
6880
6940
  ${text}
@@ -6884,14 +6944,14 @@ ${text}
6884
6944
  return;
6885
6945
  }
6886
6946
  const failedPath = paths.failedApproachesPath;
6887
- if (!existsSync21(failedPath)) {
6888
- writeFileSync11(failedPath, `# Failed Approaches Log
6947
+ if (!existsSync23(failedPath)) {
6948
+ writeFileSync12(failedPath, `# Failed Approaches Log
6889
6949
 
6890
6950
  This file records approaches that did not work.
6891
6951
 
6892
6952
  `, "utf-8");
6893
6953
  }
6894
- const content = readFileSync11(failedPath, "utf-8");
6954
+ const content = readFileSync12(failedPath, "utf-8");
6895
6955
  const attempts = (content.match(new RegExp(`^## ${escapeRegExp(activeTask)}\\b`, "gm")) || []).length + 1;
6896
6956
  appendFileSync(failedPath, `
6897
6957
  ## ${activeTask} - Attempt ${attempts} (${nowIso()})
@@ -6908,40 +6968,40 @@ function taskArtifacts(projectRoot, taskId) {
6908
6968
  throw new Error("No active task.");
6909
6969
  }
6910
6970
  const paths = resolveHarnessPaths(projectRoot);
6911
- const artifactDir = resolve24(paths.artifactsDir, activeTask);
6912
- mkdirSync11(artifactDir, { recursive: true });
6971
+ const artifactDir = resolve25(paths.artifactsDir, activeTask);
6972
+ mkdirSync12(artifactDir, { recursive: true });
6913
6973
  const changed = changedFilesForTask(projectRoot, activeTask, true);
6914
- writeFileSync11(resolve24(artifactDir, "changed-files.txt"), `${changed.join(`
6974
+ writeFileSync12(resolve25(artifactDir, "changed-files.txt"), `${changed.join(`
6915
6975
  `)}
6916
6976
  `, "utf-8");
6917
6977
  console.log(`changed-files.txt: ${changed.length} files`);
6918
- const taskResultPath = resolve24(artifactDir, "task-result.json");
6919
- if (!existsSync21(taskResultPath)) {
6978
+ const taskResultPath = resolve25(artifactDir, "task-result.json");
6979
+ if (!existsSync23(taskResultPath)) {
6920
6980
  const template = {
6921
6981
  task_id: activeTask,
6922
6982
  status: "completed",
6923
6983
  summary: "TODO: Write a one-line summary of what you did",
6924
6984
  completed_at: nowIso()
6925
6985
  };
6926
- writeFileSync11(taskResultPath, `${JSON.stringify(template, null, 2)}
6986
+ writeFileSync12(taskResultPath, `${JSON.stringify(template, null, 2)}
6927
6987
  `, "utf-8");
6928
6988
  console.log("task-result.json: created (update the summary!)");
6929
6989
  } else {
6930
6990
  console.log("task-result.json: already exists");
6931
6991
  }
6932
- const decisionLogPath = resolve24(artifactDir, "decision-log.md");
6933
- if (!existsSync21(decisionLogPath)) {
6992
+ const decisionLogPath = resolve25(artifactDir, "decision-log.md");
6993
+ if (!existsSync23(decisionLogPath)) {
6934
6994
  const content = `# Decision Log: ${activeTask}
6935
6995
 
6936
6996
  Record key decisions here using: rig-agent record decision "..."
6937
6997
  `;
6938
- writeFileSync11(decisionLogPath, content, "utf-8");
6998
+ writeFileSync12(decisionLogPath, content, "utf-8");
6939
6999
  console.log("decision-log.md: created (record your decisions!)");
6940
7000
  } else {
6941
7001
  console.log("decision-log.md: already exists");
6942
7002
  }
6943
- const nextActionsPath = resolve24(artifactDir, "next-actions.md");
6944
- if (!existsSync21(nextActionsPath)) {
7003
+ const nextActionsPath = resolve25(artifactDir, "next-actions.md");
7004
+ if (!existsSync23(nextActionsPath)) {
6945
7005
  const content = [
6946
7006
  `# Next Actions: ${activeTask}`,
6947
7007
  "",
@@ -6958,13 +7018,13 @@ Record key decisions here using: rig-agent record decision "..."
6958
7018
  ""
6959
7019
  ].join(`
6960
7020
  `);
6961
- writeFileSync11(nextActionsPath, content, "utf-8");
7021
+ writeFileSync12(nextActionsPath, content, "utf-8");
6962
7022
  console.log("next-actions.md: created (add recommendations for downstream tasks!)");
6963
7023
  } else {
6964
7024
  console.log("next-actions.md: already exists");
6965
7025
  }
6966
- const validationSummaryPath = resolve24(artifactDir, "validation-summary.json");
6967
- if (existsSync21(validationSummaryPath)) {
7026
+ const validationSummaryPath = resolve25(artifactDir, "validation-summary.json");
7027
+ if (existsSync23(validationSummaryPath)) {
6968
7028
  console.log("validation-summary.json: already exists");
6969
7029
  } else {
6970
7030
  console.log("validation-summary.json: not yet created (run: rig-agent validate)");
@@ -6978,8 +7038,8 @@ function taskArtifactDir(projectRoot, taskId) {
6978
7038
  throw new Error("No active task.");
6979
7039
  }
6980
7040
  const paths = resolveHarnessPaths(projectRoot);
6981
- const artifactDir = resolve24(paths.artifactsDir, activeTask);
6982
- mkdirSync11(artifactDir, { recursive: true });
7041
+ const artifactDir = resolve25(paths.artifactsDir, activeTask);
7042
+ mkdirSync12(artifactDir, { recursive: true });
6983
7043
  return artifactDir;
6984
7044
  }
6985
7045
  function taskArtifactWrite(projectRoot, filename, content, taskId) {
@@ -6988,10 +7048,10 @@ function taskArtifactWrite(projectRoot, filename, content, taskId) {
6988
7048
  throw new Error("No active task.");
6989
7049
  }
6990
7050
  const paths = resolveHarnessPaths(projectRoot);
6991
- const artifactDir = resolve24(paths.artifactsDir, activeTask);
6992
- mkdirSync11(artifactDir, { recursive: true });
6993
- const targetPath = resolve24(artifactDir, filename);
6994
- writeFileSync11(targetPath, content, "utf-8");
7051
+ const artifactDir = resolve25(paths.artifactsDir, activeTask);
7052
+ mkdirSync12(artifactDir, { recursive: true });
7053
+ const targetPath = resolve25(artifactDir, filename);
7054
+ writeFileSync12(targetPath, content, "utf-8");
6995
7055
  console.log(`Wrote: ${targetPath}`);
6996
7056
  }
6997
7057
  function taskArtifactRead(projectRoot, filename, options) {
@@ -7000,11 +7060,11 @@ function taskArtifactRead(projectRoot, filename, options) {
7000
7060
  throw new Error("No active task.");
7001
7061
  }
7002
7062
  const maxBytes = options?.maxBytes ?? 64 * 1024;
7003
- const targetPath = resolve24(taskArtifactDir(projectRoot, activeTask), filename);
7004
- if (!existsSync21(targetPath)) {
7063
+ const targetPath = resolve25(taskArtifactDir(projectRoot, activeTask), filename);
7064
+ if (!existsSync23(targetPath)) {
7005
7065
  throw new Error(`Artifact not found: ${targetPath}`);
7006
7066
  }
7007
- const buffer = readFileSync11(targetPath);
7067
+ const buffer = readFileSync12(targetPath);
7008
7068
  const preview = buffer.subarray(0, maxBytes);
7009
7069
  return {
7010
7070
  path: targetPath,
@@ -7154,7 +7214,7 @@ function collectTaskChangedFiles(projectRoot, taskId, includeCommitted) {
7154
7214
  [projectRoot, ""],
7155
7215
  [monorepoRepoRoot, ""]
7156
7216
  ]) {
7157
- if (!existsSync21(resolve24(repo, ".git"))) {
7217
+ if (!existsSync23(resolve25(repo, ".git"))) {
7158
7218
  continue;
7159
7219
  }
7160
7220
  if (includeCommitted && repo === monorepoRepoRoot) {
@@ -7179,12 +7239,22 @@ function filterTaskChangedFiles(projectRoot, taskId, files, scoped) {
7179
7239
  }
7180
7240
  function resolveTaskMonorepoRoot(projectRoot) {
7181
7241
  const runtimeWorkspace = loadRuntimeContextFromEnv()?.workspaceDir || process.env.RIG_TASK_WORKSPACE?.trim();
7182
- if (runtimeWorkspace && existsSync21(resolve24(runtimeWorkspace, ".git"))) {
7183
- return resolve24(runtimeWorkspace);
7242
+ if (runtimeWorkspace && existsSync23(resolve25(runtimeWorkspace, ".git"))) {
7243
+ return resolve25(runtimeWorkspace);
7184
7244
  }
7185
7245
  return resolveHarnessPaths(projectRoot).monorepoRoot;
7186
7246
  }
7187
7247
  function collectCommittedMonorepoFiles(projectRoot, repo) {
7248
+ const defaultRef = runCapture(["git", "-C", repo, "rev-parse", "--abbrev-ref", "origin/HEAD"], projectRoot);
7249
+ if (defaultRef.exitCode === 0 && defaultRef.stdout.trim()) {
7250
+ const mergeBase = runCapture(["git", "-C", repo, "merge-base", "HEAD", defaultRef.stdout.trim()], projectRoot);
7251
+ if (mergeBase.exitCode === 0 && mergeBase.stdout.trim()) {
7252
+ const result = runCapture(["git", "-C", repo, "diff", "--name-only", `${mergeBase.stdout.trim()}..HEAD`], projectRoot);
7253
+ if (result.exitCode === 0) {
7254
+ return result.stdout.split(/\r?\n/).map((line) => line.trim()).filter(Boolean);
7255
+ }
7256
+ }
7257
+ }
7188
7258
  const initialHeadCommit = resolveRuntimeInitialHeadCommit(projectRoot, repo);
7189
7259
  if (initialHeadCommit) {
7190
7260
  const result = runCapture(["git", "-C", repo, "diff", "--name-only", `${initialHeadCommit}..HEAD`], projectRoot);
@@ -7208,7 +7278,7 @@ function resolveRuntimeInitialHeadCommit(projectRoot, repo) {
7208
7278
  const runtimeContext = loadRuntimeContextFromEnv();
7209
7279
  if (runtimeContext?.initialHeadCommits?.monorepo?.trim()) {
7210
7280
  const monorepoRoot = resolveTaskMonorepoRoot(projectRoot);
7211
- if (resolve24(monorepoRoot) === resolve24(repo)) {
7281
+ if (resolve25(monorepoRoot) === resolve25(repo)) {
7212
7282
  return runtimeContext.initialHeadCommits.monorepo.trim();
7213
7283
  }
7214
7284
  }
@@ -7218,7 +7288,7 @@ function resolveMonorepoBaseCommit(projectRoot, repo) {
7218
7288
  const runtimeContext = loadRuntimeContextFromEnv();
7219
7289
  if (runtimeContext?.monorepoBaseCommit?.trim()) {
7220
7290
  const monorepoRoot = resolveTaskMonorepoRoot(projectRoot);
7221
- if (resolve24(monorepoRoot) === resolve24(repo)) {
7291
+ if (resolve25(monorepoRoot) === resolve25(repo)) {
7222
7292
  return runtimeContext.monorepoBaseCommit.trim();
7223
7293
  }
7224
7294
  }
@@ -7263,7 +7333,7 @@ function resolveRuntimeDirtyBaseline(projectRoot, repo) {
7263
7333
  return new Set;
7264
7334
  }
7265
7335
  const monorepoRoot = resolveTaskMonorepoRoot(projectRoot);
7266
- const selected = resolve24(repo) === resolve24(monorepoRoot) ? dirtyFiles.monorepo : resolve24(repo) === resolve24(projectRoot) ? dirtyFiles.project : undefined;
7336
+ const selected = resolve25(repo) === resolve25(monorepoRoot) ? dirtyFiles.monorepo : resolve25(repo) === resolve25(projectRoot) ? dirtyFiles.project : undefined;
7267
7337
  return new Set((selected || []).map((file) => normalizeChangedFilePath(file)).filter(Boolean));
7268
7338
  }
7269
7339
  function normalizeChangedFilePath(file) {
@@ -7363,12 +7433,12 @@ function printIndented(text) {
7363
7433
  }
7364
7434
  }
7365
7435
  function readLocalBeadsTasks(projectRoot) {
7366
- const issuesPath = resolve24(resolveMonorepoRoot2(projectRoot), ".beads/issues.jsonl");
7367
- if (!existsSync21(issuesPath)) {
7436
+ const issuesPath = resolve25(resolveMonorepoRoot2(projectRoot), ".beads/issues.jsonl");
7437
+ if (!existsSync23(issuesPath)) {
7368
7438
  return [];
7369
7439
  }
7370
7440
  const tasks = [];
7371
- for (const line of readFileSync11(issuesPath, "utf-8").split(/\r?\n/)) {
7441
+ for (const line of readFileSync12(issuesPath, "utf-8").split(/\r?\n/)) {
7372
7442
  const trimmed = line.trim();
7373
7443
  if (!trimmed) {
7374
7444
  continue;
@@ -7539,11 +7609,11 @@ function taskDependencies(projectRoot, taskId, tracker) {
7539
7609
  return [...ids].sort();
7540
7610
  }
7541
7611
  function printArtifactSection(path, header) {
7542
- if (!existsSync21(path)) {
7612
+ if (!existsSync23(path)) {
7543
7613
  return;
7544
7614
  }
7545
7615
  console.log(header);
7546
- process.stdout.write(readFileSync11(path, "utf-8"));
7616
+ process.stdout.write(readFileSync12(path, "utf-8"));
7547
7617
  console.log("");
7548
7618
  }
7549
7619
  function escapeRegExp(value) {