@h-rig/runtime 0.0.6-alpha.28 → 0.0.6-alpha.29

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 (39) hide show
  1. package/dist/bin/rig-agent-dispatch.js +552 -483
  2. package/dist/bin/rig-agent.js +418 -364
  3. package/dist/src/control-plane/agent-wrapper.js +557 -488
  4. package/dist/src/control-plane/harness-main.js +559 -1418
  5. package/dist/src/control-plane/hooks/completion-verification.js +451 -808
  6. package/dist/src/control-plane/hooks/inject-context.js +191 -137
  7. package/dist/src/control-plane/hooks/submodule-branch.js +596 -542
  8. package/dist/src/control-plane/hooks/task-runtime-start.js +596 -542
  9. package/dist/src/control-plane/materialize-task-config.js +64 -8
  10. package/dist/src/control-plane/native/git-ops.js +3 -0
  11. package/dist/src/control-plane/native/harness-cli.js +544 -496
  12. package/dist/src/control-plane/native/repo-ops.js +3 -0
  13. package/dist/src/control-plane/native/run-ops.js +3 -0
  14. package/dist/src/control-plane/native/task-ops.js +418 -370
  15. package/dist/src/control-plane/native/validator.js +161 -107
  16. package/dist/src/control-plane/native/verifier.js +217 -169
  17. package/dist/src/control-plane/pi-sessiond/launcher.js +12 -2
  18. package/dist/src/control-plane/plugin-host-context.js +54 -0
  19. package/dist/src/control-plane/runtime/image/fingerprint-sidecar.js +3 -0
  20. package/dist/src/control-plane/runtime/image/index.js +3 -0
  21. package/dist/src/control-plane/runtime/image-fingerprint-sidecar.js +3 -0
  22. package/dist/src/control-plane/runtime/image.js +3 -0
  23. package/dist/src/control-plane/runtime/index.js +487 -718
  24. package/dist/src/control-plane/runtime/isolation/index.js +511 -457
  25. package/dist/src/control-plane/runtime/isolation.js +511 -457
  26. package/dist/src/control-plane/runtime/plugin-mode.js +3 -27
  27. package/dist/src/control-plane/runtime/queue.js +428 -381
  28. package/dist/src/control-plane/runtime/snapshot/task-run.js +3 -0
  29. package/dist/src/control-plane/runtime/task-run-snapshot.js +3 -0
  30. package/dist/src/control-plane/skill-materializer.js +46 -0
  31. package/dist/src/control-plane/tasks/source-lifecycle.js +84 -30
  32. package/dist/src/index.js +0 -278
  33. package/native/darwin-arm64/rig-shell +0 -0
  34. package/native/darwin-arm64/rig-shell.build-manifest.json +1 -1
  35. package/native/darwin-arm64/rig-tools +0 -0
  36. package/native/darwin-arm64/rig-tools.build-manifest.json +1 -1
  37. package/package.json +8 -7
  38. package/dist/src/control-plane/runtime/plugins.js +0 -1131
  39. package/dist/src/plugins.js +0 -329
@@ -2,15 +2,15 @@
2
2
  // @bun
3
3
 
4
4
  // packages/runtime/src/control-plane/harness-main.ts
5
- import { resolve as resolve34 } from "path";
5
+ import { resolve as resolve33 } from "path";
6
6
 
7
7
  // packages/runtime/src/control-plane/native/harness-cli.ts
8
- import { existsSync as existsSync28 } from "fs";
9
- import { resolve as resolve29 } from "path";
8
+ import { existsSync as existsSync29 } from "fs";
9
+ import { resolve as resolve30 } from "path";
10
10
 
11
11
  // packages/runtime/src/control-plane/native/git-ops.ts
12
- import { existsSync as existsSync21, lstatSync, mkdirSync as mkdirSync10, readFileSync as readFileSync11, writeFileSync as writeFileSync10 } from "fs";
13
- import { dirname as dirname11, isAbsolute as isAbsolute2, resolve as resolve24 } from "path";
12
+ import { existsSync as existsSync22, lstatSync, mkdirSync as mkdirSync11, readFileSync as readFileSync12, writeFileSync as writeFileSync11 } from "fs";
13
+ import { dirname as dirname11, isAbsolute as isAbsolute2, resolve as resolve25 } from "path";
14
14
  import { fileURLToPath as fileURLToPath2 } from "url";
15
15
 
16
16
  // packages/runtime/src/control-plane/runtime/baked-secrets.ts
@@ -279,8 +279,8 @@ function isAgentRuntimeContextPath(path) {
279
279
  }
280
280
 
281
281
  // packages/runtime/src/control-plane/native/task-ops.ts
282
- import { appendFileSync, existsSync as existsSync20, mkdirSync as mkdirSync9, readFileSync as readFileSync10, writeFileSync as writeFileSync9 } from "fs";
283
- import { resolve as resolve23 } from "path";
282
+ import { appendFileSync, existsSync as existsSync21, mkdirSync as mkdirSync10, readFileSync as readFileSync11, writeFileSync as writeFileSync10 } from "fs";
283
+ import { resolve as resolve24 } from "path";
284
284
 
285
285
  // packages/runtime/src/build-time-config.ts
286
286
  function normalizeBuildConfig(value) {
@@ -765,6 +765,49 @@ function safeReadJson(path) {
765
765
  }
766
766
  }
767
767
 
768
+ // packages/runtime/src/control-plane/skill-materializer.ts
769
+ import { existsSync as existsSync5, mkdirSync as mkdirSync3, readFileSync as readFileSync4, readdirSync, rmSync, writeFileSync as writeFileSync3 } from "fs";
770
+ import { resolve as resolve7 } from "path";
771
+ import { loadSkill } from "@rig/skill-loader";
772
+ var MARKER_FILENAME = ".rig-plugin";
773
+ function skillDirName(id) {
774
+ return id.replace(/[^a-zA-Z0-9._-]+/g, "-");
775
+ }
776
+ async function materializeSkills(projectRoot, entries) {
777
+ const skillsRoot = resolve7(projectRoot, ".pi", "skills");
778
+ if (existsSync5(skillsRoot)) {
779
+ for (const name of readdirSync(skillsRoot)) {
780
+ const dir = resolve7(skillsRoot, name);
781
+ if (existsSync5(resolve7(dir, MARKER_FILENAME))) {
782
+ rmSync(dir, { recursive: true, force: true });
783
+ }
784
+ }
785
+ }
786
+ const written = [];
787
+ for (const { pluginName, skill } of entries) {
788
+ const sourcePath = resolve7(projectRoot, skill.path);
789
+ if (!existsSync5(sourcePath)) {
790
+ console.warn(`[plugin-host] skill "${skill.id}" from plugin "${pluginName}" not materialized: ${sourcePath} does not exist`);
791
+ continue;
792
+ }
793
+ let body;
794
+ try {
795
+ await loadSkill(sourcePath);
796
+ body = readFileSync4(sourcePath, "utf-8");
797
+ } catch (err) {
798
+ console.warn(`[plugin-host] skill "${skill.id}" from plugin "${pluginName}" not materialized: ${err instanceof Error ? err.message : err}`);
799
+ continue;
800
+ }
801
+ const dir = resolve7(skillsRoot, skillDirName(skill.id));
802
+ mkdirSync3(dir, { recursive: true });
803
+ writeFileSync3(resolve7(dir, "SKILL.md"), body, "utf-8");
804
+ writeFileSync3(resolve7(dir, MARKER_FILENAME), `${JSON.stringify({ plugin: pluginName, skillId: skill.id }, null, 2)}
805
+ `, "utf-8");
806
+ written.push({ id: skill.id, pluginName, directory: dir });
807
+ }
808
+ return written;
809
+ }
810
+
768
811
  // packages/runtime/src/control-plane/plugin-host-context.ts
769
812
  async function buildPluginHostContext(projectRoot) {
770
813
  let config;
@@ -801,6 +844,17 @@ async function buildPluginHostContext(projectRoot) {
801
844
  } catch (err) {
802
845
  console.warn(`[plugin-host] hook materialization failed: ${err instanceof Error ? err.message : err}`);
803
846
  }
847
+ try {
848
+ const skillEntries = config.plugins.flatMap((plugin) => (plugin.contributes?.skills ?? []).map((skill) => ({
849
+ pluginName: plugin.name,
850
+ skill
851
+ })));
852
+ if (skillEntries.length > 0) {
853
+ await materializeSkills(projectRoot, skillEntries);
854
+ }
855
+ } catch (err) {
856
+ console.warn(`[plugin-host] skill materialization failed: ${err instanceof Error ? err.message : err}`);
857
+ }
804
858
  return {
805
859
  config,
806
860
  pluginHost,
@@ -814,12 +868,12 @@ async function buildPluginHostContext(projectRoot) {
814
868
 
815
869
  // packages/runtime/src/control-plane/tasks/source-aware-task-config-source.ts
816
870
  import { spawnSync } from "child_process";
817
- import { existsSync as existsSync6, readFileSync as readFileSync5, readdirSync, statSync, writeFileSync as writeFileSync3 } from "fs";
818
- import { basename as basename3, join as join2, resolve as resolve8 } from "path";
871
+ import { existsSync as existsSync7, readFileSync as readFileSync6, readdirSync as readdirSync2, statSync, writeFileSync as writeFileSync4 } from "fs";
872
+ import { basename as basename3, join as join2, resolve as resolve9 } from "path";
819
873
 
820
874
  // packages/runtime/src/control-plane/tasks/legacy-task-config-source.ts
821
- import { existsSync as existsSync5, readFileSync as readFileSync4 } from "fs";
822
- import { resolve as resolve7 } from "path";
875
+ import { existsSync as existsSync6, readFileSync as readFileSync5 } from "fs";
876
+ import { resolve as resolve8 } from "path";
823
877
 
824
878
  // packages/runtime/src/control-plane/tasks/task-record-reader.ts
825
879
  async function findTaskById(reader, id) {
@@ -842,7 +896,7 @@ class LegacyTaskConfigReadError extends Error {
842
896
  }
843
897
  }
844
898
  function createLegacyTaskConfigRecordReader(projectRoot, options = {}) {
845
- const configPath = options.configPath ?? resolve7(projectRoot, ".rig", "task-config.json");
899
+ const configPath = options.configPath ?? resolve8(projectRoot, ".rig", "task-config.json");
846
900
  const reader = {
847
901
  async listTasks() {
848
902
  return readLegacyTaskRecords(projectRoot, configPath);
@@ -853,8 +907,8 @@ function createLegacyTaskConfigRecordReader(projectRoot, options = {}) {
853
907
  };
854
908
  return reader;
855
909
  }
856
- function readLegacyTaskRecords(projectRoot, configPath = resolve7(projectRoot, ".rig", "task-config.json")) {
857
- if (!existsSync5(configPath)) {
910
+ function readLegacyTaskRecords(projectRoot, configPath = resolve8(projectRoot, ".rig", "task-config.json")) {
911
+ if (!existsSync6(configPath)) {
858
912
  return [];
859
913
  }
860
914
  const rawConfig = readLegacyTaskConfigJson(projectRoot, configPath);
@@ -862,7 +916,7 @@ function readLegacyTaskRecords(projectRoot, configPath = resolve7(projectRoot, "
862
916
  }
863
917
  function readLegacyTaskConfigJson(projectRoot, configPath) {
864
918
  try {
865
- const parsed = JSON.parse(readFileSync4(configPath, "utf8"));
919
+ const parsed = JSON.parse(readFileSync5(configPath, "utf8"));
866
920
  if (isPlainRecord(parsed)) {
867
921
  return parsed;
868
922
  }
@@ -946,7 +1000,7 @@ function isPlainRecord(candidate) {
946
1000
  var STATUS_LABELS = new Set(["ready", "blocked", "in-progress", "under-review", "failed", "cancelled"]);
947
1001
  var FILE_TASK_PATTERN = /\.(task\.)?json$/;
948
1002
  function createSourceAwareTaskConfigRecordReader(projectRoot, options = {}) {
949
- const configPath = options.configPath ?? resolve8(projectRoot, ".rig", "task-config.json");
1003
+ const configPath = options.configPath ?? resolve9(projectRoot, ".rig", "task-config.json");
950
1004
  const legacy = createLegacyTaskConfigRecordReader(projectRoot, { configPath });
951
1005
  const spawnFn = options.spawn ?? spawnSync;
952
1006
  const ghBinary = options.ghBinary ?? "gh";
@@ -1029,10 +1083,10 @@ function readMaterializedTaskMetadata(entry) {
1029
1083
  return metadata;
1030
1084
  }
1031
1085
  function readConfiguredFilesTaskSourcePath(projectRoot) {
1032
- const jsonPath = resolve8(projectRoot, "rig.config.json");
1033
- if (existsSync6(jsonPath)) {
1086
+ const jsonPath = resolve9(projectRoot, "rig.config.json");
1087
+ if (existsSync7(jsonPath)) {
1034
1088
  try {
1035
- const parsed = JSON.parse(readFileSync5(jsonPath, "utf8"));
1089
+ const parsed = JSON.parse(readFileSync6(jsonPath, "utf8"));
1036
1090
  if (isPlainRecord2(parsed) && isPlainRecord2(parsed.taskSource)) {
1037
1091
  const source = parsed.taskSource;
1038
1092
  return source.kind === "files" && typeof source.path === "string" ? source.path : null;
@@ -1041,12 +1095,12 @@ function readConfiguredFilesTaskSourcePath(projectRoot) {
1041
1095
  return null;
1042
1096
  }
1043
1097
  }
1044
- const tsPath = resolve8(projectRoot, "rig.config.ts");
1045
- if (!existsSync6(tsPath)) {
1098
+ const tsPath = resolve9(projectRoot, "rig.config.ts");
1099
+ if (!existsSync7(tsPath)) {
1046
1100
  return null;
1047
1101
  }
1048
1102
  try {
1049
- const source = readFileSync5(tsPath, "utf8");
1103
+ const source = readFileSync6(tsPath, "utf8");
1050
1104
  const taskSourceBlock = source.match(/taskSource\s*:\s*\{[\s\S]*?\}/m)?.[0] ?? "";
1051
1105
  const kind = taskSourceBlock.match(/kind\s*:\s*["']([^"']+)["']/)?.[1];
1052
1106
  if (kind !== "files") {
@@ -1066,10 +1120,10 @@ function readRawTaskEntry(configPath, taskId) {
1066
1120
  return isPlainRecord2(entry) ? entry : null;
1067
1121
  }
1068
1122
  function readRawTaskConfig(configPath) {
1069
- if (!existsSync6(configPath)) {
1123
+ if (!existsSync7(configPath)) {
1070
1124
  return null;
1071
1125
  }
1072
- const parsed = JSON.parse(readFileSync5(configPath, "utf8"));
1126
+ const parsed = JSON.parse(readFileSync6(configPath, "utf8"));
1073
1127
  return isPlainRecord2(parsed) ? parsed : null;
1074
1128
  }
1075
1129
  function stripLegacyTaskConfigMetadata2(raw) {
@@ -1077,12 +1131,12 @@ function stripLegacyTaskConfigMetadata2(raw) {
1077
1131
  return tasks;
1078
1132
  }
1079
1133
  function listFileBackedTasks(projectRoot, sourcePath) {
1080
- const directory = resolve8(projectRoot, sourcePath);
1081
- if (!existsSync6(directory)) {
1134
+ const directory = resolve9(projectRoot, sourcePath);
1135
+ if (!existsSync7(directory)) {
1082
1136
  return [];
1083
1137
  }
1084
1138
  const tasks = [];
1085
- for (const name of readdirSync(directory)) {
1139
+ for (const name of readdirSync2(directory)) {
1086
1140
  if (!FILE_TASK_PATTERN.test(name))
1087
1141
  continue;
1088
1142
  const inferredId = basename3(name).replace(FILE_TASK_PATTERN, "");
@@ -1093,11 +1147,11 @@ function listFileBackedTasks(projectRoot, sourcePath) {
1093
1147
  return tasks;
1094
1148
  }
1095
1149
  function readFileBackedTask(projectRoot, sourcePath, taskId, rawEntry) {
1096
- const file = findFileBackedTaskFile(resolve8(projectRoot, sourcePath), taskId);
1150
+ const file = findFileBackedTaskFile(resolve9(projectRoot, sourcePath), taskId);
1097
1151
  if (!file) {
1098
1152
  return null;
1099
1153
  }
1100
- const raw = JSON.parse(readFileSync5(file, "utf8"));
1154
+ const raw = JSON.parse(readFileSync6(file, "utf8"));
1101
1155
  if (!isPlainRecord2(raw)) {
1102
1156
  return null;
1103
1157
  }
@@ -1110,17 +1164,17 @@ function readFileBackedTask(projectRoot, sourcePath, taskId, rawEntry) {
1110
1164
  };
1111
1165
  }
1112
1166
  function findFileBackedTaskFile(directory, taskId) {
1113
- if (!existsSync6(directory)) {
1167
+ if (!existsSync7(directory)) {
1114
1168
  return null;
1115
1169
  }
1116
- for (const name of readdirSync(directory)) {
1170
+ for (const name of readdirSync2(directory)) {
1117
1171
  if (!FILE_TASK_PATTERN.test(name))
1118
1172
  continue;
1119
1173
  const file = join2(directory, name);
1120
1174
  try {
1121
1175
  if (!statSync(file).isFile())
1122
1176
  continue;
1123
- const raw = JSON.parse(readFileSync5(file, "utf8"));
1177
+ const raw = JSON.parse(readFileSync6(file, "utf8"));
1124
1178
  const inferredId = basename3(file).replace(FILE_TASK_PATTERN, "");
1125
1179
  const id = isPlainRecord2(raw) && typeof raw.id === "string" ? raw.id : inferredId;
1126
1180
  if (id === taskId) {
@@ -1280,8 +1334,8 @@ async function readConfiguredTaskSourceTask(projectRoot, taskId) {
1280
1334
  }
1281
1335
 
1282
1336
  // packages/runtime/src/control-plane/native/task-state.ts
1283
- import { existsSync as existsSync14, readFileSync as readFileSync9, readdirSync as readdirSync2, statSync as statSync3, writeFileSync as writeFileSync5 } from "fs";
1284
- import { basename as basename6, resolve as resolve16 } from "path";
1337
+ import { existsSync as existsSync15, readFileSync as readFileSync10, readdirSync as readdirSync3, statSync as statSync3, writeFileSync as writeFileSync6 } from "fs";
1338
+ import { basename as basename6, resolve as resolve17 } from "path";
1285
1339
 
1286
1340
  // packages/runtime/src/control-plane/state-sync/types.ts
1287
1341
  var SUPPORTED_TASK_STATE_SCHEMA_VERSION = 1;
@@ -1389,30 +1443,30 @@ function readTaskStateMetadataEnvelope(raw) {
1389
1443
  };
1390
1444
  }
1391
1445
  // packages/runtime/src/control-plane/state-sync/read.ts
1392
- import { existsSync as existsSync13, readFileSync as readFileSync8 } from "fs";
1393
- import { resolve as resolve15 } from "path";
1446
+ import { existsSync as existsSync14, readFileSync as readFileSync9 } from "fs";
1447
+ import { resolve as resolve16 } from "path";
1394
1448
 
1395
1449
  // packages/runtime/src/control-plane/native/git-native.ts
1396
- import { chmodSync, copyFileSync, existsSync as existsSync7, mkdirSync as mkdirSync3, readFileSync as readFileSync6, renameSync, rmSync, writeFileSync as writeFileSync4 } from "fs";
1450
+ import { chmodSync, copyFileSync, existsSync as existsSync8, mkdirSync as mkdirSync4, readFileSync as readFileSync7, renameSync, rmSync as rmSync2, writeFileSync as writeFileSync5 } from "fs";
1397
1451
  import { tmpdir as tmpdir3 } from "os";
1398
- import { dirname as dirname5, isAbsolute, resolve as resolve9 } from "path";
1452
+ import { dirname as dirname5, isAbsolute, resolve as resolve10 } from "path";
1399
1453
  import { createHash } from "crypto";
1400
1454
  function isTextTreeCommitUpdate(update) {
1401
1455
  return typeof update.content === "string";
1402
1456
  }
1403
- var sharedGitNativeOutputDir = resolve9(tmpdir3(), "rig-native");
1404
- var sharedGitNativeOutputPath = resolve9(sharedGitNativeOutputDir, `rig-git-${process.platform}-${process.arch}${process.platform === "win32" ? ".exe" : ""}`);
1457
+ var sharedGitNativeOutputDir = resolve10(tmpdir3(), "rig-native");
1458
+ var sharedGitNativeOutputPath = resolve10(sharedGitNativeOutputDir, `rig-git-${process.platform}-${process.arch}${process.platform === "win32" ? ".exe" : ""}`);
1405
1459
  var trackerCommandUsageProbe = "usage: rig-git fetch-ref <repo-path> <remote> <branch>";
1406
1460
  function temporaryGitBinaryOutputPath(outputPath) {
1407
1461
  const suffix = process.platform === "win32" ? ".exe" : "";
1408
- return resolve9(dirname5(outputPath), `.rig-git-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}${suffix}`);
1462
+ return resolve10(dirname5(outputPath), `.rig-git-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}${suffix}`);
1409
1463
  }
1410
1464
  function publishGitBinary(tempOutputPath, outputPath) {
1411
1465
  try {
1412
1466
  renameSync(tempOutputPath, outputPath);
1413
1467
  } catch (error) {
1414
- if (process.platform === "win32" && existsSync7(outputPath)) {
1415
- rmSync(outputPath, { force: true });
1468
+ if (process.platform === "win32" && existsSync8(outputPath)) {
1469
+ rmSync2(outputPath, { force: true });
1416
1470
  renameSync(tempOutputPath, outputPath);
1417
1471
  return;
1418
1472
  }
@@ -1427,22 +1481,22 @@ function rigGitSourceCandidates() {
1427
1481
  const cwd = process.cwd()?.trim() || "";
1428
1482
  const projectRoot = process.env.PROJECT_RIG_ROOT?.trim() || "";
1429
1483
  const hostProjectRoot = process.env.RIG_HOST_PROJECT_ROOT?.trim() || "";
1430
- const moduleRelativeSource = resolve9(import.meta.dir, "../../../native/rig-git.zig");
1484
+ const moduleRelativeSource = resolve10(import.meta.dir, "../../../native/rig-git.zig");
1431
1485
  return [...new Set([
1432
1486
  process.env.RIG_NATIVE_GIT_SOURCE?.trim() || "",
1433
1487
  moduleRelativeSource,
1434
- projectRoot ? resolve9(projectRoot, "packages/runtime/native/rig-git.zig") : "",
1435
- hostProjectRoot ? resolve9(hostProjectRoot, "packages/runtime/native/rig-git.zig") : "",
1436
- cwd ? resolve9(cwd, "packages/runtime/native/rig-git.zig") : "",
1437
- execDir ? resolve9(execDir, "..", "..", "packages/runtime/native/rig-git.zig") : "",
1438
- execDir ? resolve9(execDir, "..", "native", "rig-git.zig") : ""
1488
+ projectRoot ? resolve10(projectRoot, "packages/runtime/native/rig-git.zig") : "",
1489
+ hostProjectRoot ? resolve10(hostProjectRoot, "packages/runtime/native/rig-git.zig") : "",
1490
+ cwd ? resolve10(cwd, "packages/runtime/native/rig-git.zig") : "",
1491
+ execDir ? resolve10(execDir, "..", "..", "packages/runtime/native/rig-git.zig") : "",
1492
+ execDir ? resolve10(execDir, "..", "native", "rig-git.zig") : ""
1439
1493
  ].filter(Boolean))];
1440
1494
  }
1441
1495
  function nativePackageBinaryCandidates(fromDir, fileName) {
1442
1496
  const candidates = [];
1443
- let cursor = resolve9(fromDir);
1497
+ let cursor = resolve10(fromDir);
1444
1498
  for (let index = 0;index < 8; index += 1) {
1445
- candidates.push(resolve9(cursor, "native", `${process.platform}-${process.arch}`, fileName), resolve9(cursor, "native", `${process.platform}-${process.arch}`, "bin", fileName), resolve9(cursor, "native", fileName), resolve9(cursor, "native", "bin", fileName));
1499
+ candidates.push(resolve10(cursor, "native", `${process.platform}-${process.arch}`, fileName), resolve10(cursor, "native", `${process.platform}-${process.arch}`, "bin", fileName), resolve10(cursor, "native", fileName), resolve10(cursor, "native", "bin", fileName));
1446
1500
  const parent = dirname5(cursor);
1447
1501
  if (parent === cursor)
1448
1502
  break;
@@ -1457,15 +1511,15 @@ function rigGitBinaryCandidates() {
1457
1511
  return [...new Set([
1458
1512
  explicit,
1459
1513
  ...nativePackageBinaryCandidates(import.meta.dir, fileName),
1460
- execDir ? resolve9(execDir, fileName) : "",
1461
- execDir ? resolve9(execDir, "..", fileName) : "",
1462
- execDir ? resolve9(execDir, "..", "bin", fileName) : "",
1514
+ execDir ? resolve10(execDir, fileName) : "",
1515
+ execDir ? resolve10(execDir, "..", fileName) : "",
1516
+ execDir ? resolve10(execDir, "..", "bin", fileName) : "",
1463
1517
  sharedGitNativeOutputPath
1464
1518
  ].filter(Boolean))];
1465
1519
  }
1466
1520
  function resolveGitSourcePath() {
1467
1521
  for (const candidate of rigGitSourceCandidates()) {
1468
- if (candidate && existsSync7(candidate)) {
1522
+ if (candidate && existsSync8(candidate)) {
1469
1523
  return candidate;
1470
1524
  }
1471
1525
  }
@@ -1476,7 +1530,7 @@ function resolveGitBinaryPath() {
1476
1530
  return null;
1477
1531
  }
1478
1532
  for (const candidate of rigGitBinaryCandidates()) {
1479
- if (candidate && existsSync7(candidate)) {
1533
+ if (candidate && existsSync8(candidate)) {
1480
1534
  return candidate;
1481
1535
  }
1482
1536
  }
@@ -1506,18 +1560,18 @@ function nativeBuildManifestPath(outputPath) {
1506
1560
  return `${outputPath}.build-manifest.json`;
1507
1561
  }
1508
1562
  function hasMatchingNativeBuildManifestSync(manifestPath, buildKey) {
1509
- if (!existsSync7(manifestPath)) {
1563
+ if (!existsSync8(manifestPath)) {
1510
1564
  return false;
1511
1565
  }
1512
1566
  try {
1513
- const manifest = JSON.parse(readFileSync6(manifestPath, "utf8"));
1567
+ const manifest = JSON.parse(readFileSync7(manifestPath, "utf8"));
1514
1568
  return manifest.version === 1 && manifest.buildKey === buildKey;
1515
1569
  } catch {
1516
1570
  return false;
1517
1571
  }
1518
1572
  }
1519
1573
  function sha256FileSync(path) {
1520
- return createHash("sha256").update(readFileSync6(path)).digest("hex");
1574
+ return createHash("sha256").update(readFileSync7(path)).digest("hex");
1521
1575
  }
1522
1576
  function ensureRigGitBinaryPathSync(outputPath = preferredGitBinaryOutputPath()) {
1523
1577
  if (process.env.RIG_DISABLE_ZIG_NATIVE === "1") {
@@ -1535,7 +1589,7 @@ function ensureRigGitBinaryPathSync(outputPath = preferredGitBinaryOutputPath())
1535
1589
  if (!zigBinary) {
1536
1590
  throw new Error("zig is required to build native Rig git tools.");
1537
1591
  }
1538
- mkdirSync3(dirname5(outputPath), { recursive: true });
1592
+ mkdirSync4(dirname5(outputPath), { recursive: true });
1539
1593
  const sourceDigest = sha256FileSync(sourcePath);
1540
1594
  const buildKey = JSON.stringify({
1541
1595
  version: 1,
@@ -1546,7 +1600,7 @@ function ensureRigGitBinaryPathSync(outputPath = preferredGitBinaryOutputPath())
1546
1600
  sourceDigest
1547
1601
  });
1548
1602
  const manifestPath = nativeBuildManifestPath(outputPath);
1549
- const needsBuild = !existsSync7(outputPath) || !hasMatchingNativeBuildManifestSync(manifestPath, buildKey) || !binarySupportsTrackerCommandsSync(outputPath);
1603
+ const needsBuild = !existsSync8(outputPath) || !hasMatchingNativeBuildManifestSync(manifestPath, buildKey) || !binarySupportsTrackerCommandsSync(outputPath);
1550
1604
  if (!needsBuild) {
1551
1605
  chmodSync(outputPath, 493);
1552
1606
  return outputPath;
@@ -1564,7 +1618,7 @@ function ensureRigGitBinaryPathSync(outputPath = preferredGitBinaryOutputPath())
1564
1618
  stdout: "pipe",
1565
1619
  stderr: "pipe"
1566
1620
  });
1567
- if (build.exitCode !== 0 || !existsSync7(tempOutputPath)) {
1621
+ if (build.exitCode !== 0 || !existsSync8(tempOutputPath)) {
1568
1622
  const stderr = build.stderr.toString().trim();
1569
1623
  const stdout = build.stdout.toString().trim();
1570
1624
  const details = [stderr, stdout].filter(Boolean).join(`
@@ -1572,17 +1626,17 @@ function ensureRigGitBinaryPathSync(outputPath = preferredGitBinaryOutputPath())
1572
1626
  throw new Error(`Failed to build native Rig git tools: ${details || `zig exited with code ${build.exitCode}`}`);
1573
1627
  }
1574
1628
  chmodSync(tempOutputPath, 493);
1575
- if (existsSync7(outputPath) && hasMatchingNativeBuildManifestSync(manifestPath, buildKey)) {
1576
- rmSync(tempOutputPath, { force: true });
1629
+ if (existsSync8(outputPath) && hasMatchingNativeBuildManifestSync(manifestPath, buildKey)) {
1630
+ rmSync2(tempOutputPath, { force: true });
1577
1631
  chmodSync(outputPath, 493);
1578
1632
  return outputPath;
1579
1633
  }
1580
1634
  publishGitBinary(tempOutputPath, outputPath);
1581
1635
  if (!binarySupportsTrackerCommandsSync(outputPath)) {
1582
- rmSync(outputPath, { force: true });
1636
+ rmSync2(outputPath, { force: true });
1583
1637
  throw new Error("Failed to build native Rig git tools: tracker command probe failed");
1584
1638
  }
1585
- writeFileSync4(manifestPath, `${JSON.stringify({ version: 1, buildKey }, null, 2)}
1639
+ writeFileSync5(manifestPath, `${JSON.stringify({ version: 1, buildKey }, null, 2)}
1586
1640
  `, "utf8");
1587
1641
  return outputPath;
1588
1642
  }
@@ -1604,7 +1658,7 @@ function runGitNative(command, args) {
1604
1658
  }
1605
1659
  } else {
1606
1660
  const explicitBinaryPath = process.env.RIG_NATIVE_GIT_BIN?.trim() || "";
1607
- binaryPath = explicitBinaryPath && existsSync7(explicitBinaryPath) ? explicitBinaryPath : !explicitBinaryPath ? resolveGitBinaryPath() : null;
1661
+ binaryPath = explicitBinaryPath && existsSync8(explicitBinaryPath) ? explicitBinaryPath : !explicitBinaryPath ? resolveGitBinaryPath() : null;
1608
1662
  if (!binaryPath) {
1609
1663
  try {
1610
1664
  binaryPath = ensureRigGitBinaryPathSync(preferredGitBinaryOutputPath());
@@ -1701,25 +1755,25 @@ function nativeFetchRef(repoPath, remote, branch) {
1701
1755
  return requireGitNativeString("fetch-ref", [repoPath, remote, branch]);
1702
1756
  }
1703
1757
  function nativeReadBlobAtRef(repoPath, ref, path) {
1704
- const requestDir = resolve9(sharedGitNativeOutputDir, "reads", `${Date.now()}-${Math.random().toString(36).slice(2, 10)}`);
1705
- mkdirSync3(requestDir, { recursive: true });
1706
- const outputPath = resolve9(requestDir, "blob.txt");
1758
+ const requestDir = resolve10(sharedGitNativeOutputDir, "reads", `${Date.now()}-${Math.random().toString(36).slice(2, 10)}`);
1759
+ mkdirSync4(requestDir, { recursive: true });
1760
+ const outputPath = resolve10(requestDir, "blob.txt");
1707
1761
  try {
1708
1762
  requireGitNative("read-blob-at-ref", [repoPath, ref, path, outputPath]);
1709
- return readFileSync6(outputPath, "utf8");
1763
+ return readFileSync7(outputPath, "utf8");
1710
1764
  } finally {
1711
- rmSync(requestDir, { recursive: true, force: true });
1765
+ rmSync2(requestDir, { recursive: true, force: true });
1712
1766
  }
1713
1767
  }
1714
1768
  function nativeReadBlobBytesAtRef(repoPath, ref, path) {
1715
- const requestDir = resolve9(sharedGitNativeOutputDir, "reads", `${Date.now()}-${Math.random().toString(36).slice(2, 10)}`);
1716
- mkdirSync3(requestDir, { recursive: true });
1717
- const outputPath = resolve9(requestDir, "blob.bin");
1769
+ const requestDir = resolve10(sharedGitNativeOutputDir, "reads", `${Date.now()}-${Math.random().toString(36).slice(2, 10)}`);
1770
+ mkdirSync4(requestDir, { recursive: true });
1771
+ const outputPath = resolve10(requestDir, "blob.bin");
1718
1772
  try {
1719
1773
  requireGitNative("read-blob-at-ref", [repoPath, ref, path, outputPath]);
1720
- return readFileSync6(outputPath);
1774
+ return readFileSync7(outputPath);
1721
1775
  } finally {
1722
- rmSync(requestDir, { recursive: true, force: true });
1776
+ rmSync2(requestDir, { recursive: true, force: true });
1723
1777
  }
1724
1778
  }
1725
1779
  function serializeTreeCommitUpdates(updates) {
@@ -1738,16 +1792,16 @@ function buildTreeCommitUpdatesJson(updates) {
1738
1792
  `;
1739
1793
  }
1740
1794
  function nativeWriteTreeCommit(repoPath, baseRef, updates, message) {
1741
- const requestDir = resolve9(sharedGitNativeOutputDir, "requests", `${Date.now()}-${Math.random().toString(36).slice(2, 10)}`);
1742
- mkdirSync3(requestDir, { recursive: true });
1743
- const messagePath = resolve9(requestDir, "message.txt");
1744
- const updatesPath = resolve9(requestDir, "updates.json");
1795
+ const requestDir = resolve10(sharedGitNativeOutputDir, "requests", `${Date.now()}-${Math.random().toString(36).slice(2, 10)}`);
1796
+ mkdirSync4(requestDir, { recursive: true });
1797
+ const messagePath = resolve10(requestDir, "message.txt");
1798
+ const updatesPath = resolve10(requestDir, "updates.json");
1745
1799
  try {
1746
- writeFileSync4(messagePath, message, "utf8");
1747
- writeFileSync4(updatesPath, buildTreeCommitUpdatesJson(updates), "utf8");
1800
+ writeFileSync5(messagePath, message, "utf8");
1801
+ writeFileSync5(updatesPath, buildTreeCommitUpdatesJson(updates), "utf8");
1748
1802
  return requireGitNativeString("write-tree-commit", [repoPath, baseRef, messagePath, updatesPath]);
1749
1803
  } finally {
1750
- rmSync(requestDir, { recursive: true, force: true });
1804
+ rmSync2(requestDir, { recursive: true, force: true });
1751
1805
  }
1752
1806
  }
1753
1807
  function nativePushRefWithLease(repoPath, localOid, remoteRef, expectedOldOid, remote = "origin") {
@@ -1762,36 +1816,36 @@ function nativePushRefWithLease(repoPath, localOid, remoteRef, expectedOldOid, r
1762
1816
 
1763
1817
  // packages/runtime/src/control-plane/native/utils.ts
1764
1818
  import { ptr as ptr2 } from "bun:ffi";
1765
- import { existsSync as existsSync10, readFileSync as readFileSync7 } from "fs";
1766
- import { resolve as resolve12 } from "path";
1819
+ import { existsSync as existsSync11, readFileSync as readFileSync8 } from "fs";
1820
+ import { resolve as resolve13 } from "path";
1767
1821
 
1768
1822
  // packages/runtime/src/layout.ts
1769
- import { existsSync as existsSync8 } from "fs";
1770
- import { basename as basename4, dirname as dirname6, resolve as resolve10 } from "path";
1823
+ import { existsSync as existsSync9 } from "fs";
1824
+ import { basename as basename4, dirname as dirname6, resolve as resolve11 } from "path";
1771
1825
  var RIG_DEFINITION_DIRNAME = "rig";
1772
1826
  var RIG_STATE_DIRNAME = ".rig";
1773
1827
  var RIG_ARTIFACTS_DIRNAME = "artifacts";
1774
1828
  function resolveMonorepoRoot(projectRoot) {
1775
- const normalizedProjectRoot = resolve10(projectRoot);
1829
+ const normalizedProjectRoot = resolve11(projectRoot);
1776
1830
  const explicit = process.env.MONOREPO_ROOT?.trim();
1777
1831
  if (explicit) {
1778
- const explicitRoot = resolve10(explicit);
1832
+ const explicitRoot = resolve11(explicit);
1779
1833
  const explicitParent = dirname6(explicitRoot);
1780
1834
  if (basename4(explicitParent) === ".worktrees") {
1781
1835
  const owner = dirname6(explicitParent);
1782
- const ownerHasGit = existsSync8(resolve10(owner, ".git"));
1783
- const ownerHasTaskConfig = existsSync8(resolve10(owner, ".rig", "task-config.json"));
1784
- const ownerHasRigConfig = existsSync8(resolve10(owner, "rig.config.ts"));
1836
+ const ownerHasGit = existsSync9(resolve11(owner, ".git"));
1837
+ const ownerHasTaskConfig = existsSync9(resolve11(owner, ".rig", "task-config.json"));
1838
+ const ownerHasRigConfig = existsSync9(resolve11(owner, "rig.config.ts"));
1785
1839
  if (ownerHasGit && (ownerHasTaskConfig || ownerHasRigConfig)) {
1786
1840
  return owner;
1787
1841
  }
1788
1842
  throw new Error(`MONOREPO_ROOT points to worktree ${explicitRoot}, but the owner checkout is incomplete at ${owner}.`);
1789
1843
  }
1790
- if (!existsSync8(resolve10(explicitRoot, ".git"))) {
1844
+ if (!existsSync9(resolve11(explicitRoot, ".git"))) {
1791
1845
  throw new Error(`MONOREPO_ROOT points to ${explicitRoot}, but no git checkout was found there.`);
1792
1846
  }
1793
- const hasTaskConfig = existsSync8(resolve10(explicitRoot, ".rig", "task-config.json"));
1794
- const hasRigConfig = existsSync8(resolve10(explicitRoot, "rig.config.ts"));
1847
+ const hasTaskConfig = existsSync9(resolve11(explicitRoot, ".rig", "task-config.json"));
1848
+ const hasRigConfig = existsSync9(resolve11(explicitRoot, "rig.config.ts"));
1795
1849
  if (!hasTaskConfig && !hasRigConfig) {
1796
1850
  throw new Error(`MONOREPO_ROOT points to ${explicitRoot}, but neither .rig/task-config.json nor rig.config.ts exists there.`);
1797
1851
  }
@@ -1800,9 +1854,9 @@ function resolveMonorepoRoot(projectRoot) {
1800
1854
  const projectParent = dirname6(normalizedProjectRoot);
1801
1855
  if (basename4(projectParent) === ".worktrees") {
1802
1856
  const worktreeOwner = dirname6(projectParent);
1803
- const ownerHasGit = existsSync8(resolve10(worktreeOwner, ".git"));
1804
- const ownerHasTaskConfig = existsSync8(resolve10(worktreeOwner, ".rig", "task-config.json"));
1805
- const ownerHasRigConfig = existsSync8(resolve10(worktreeOwner, "rig.config.ts"));
1857
+ const ownerHasGit = existsSync9(resolve11(worktreeOwner, ".git"));
1858
+ const ownerHasTaskConfig = existsSync9(resolve11(worktreeOwner, ".rig", "task-config.json"));
1859
+ const ownerHasRigConfig = existsSync9(resolve11(worktreeOwner, "rig.config.ts"));
1806
1860
  if (ownerHasGit && (ownerHasTaskConfig || ownerHasRigConfig)) {
1807
1861
  return worktreeOwner;
1808
1862
  }
@@ -1810,28 +1864,28 @@ function resolveMonorepoRoot(projectRoot) {
1810
1864
  return normalizedProjectRoot;
1811
1865
  }
1812
1866
  function resolveRuntimeWorkspaceLayout(workspaceDir) {
1813
- const root = resolve10(workspaceDir);
1814
- const rigRoot = resolve10(root, ".rig");
1815
- const logsDir = resolve10(rigRoot, "logs");
1816
- const stateDir = resolve10(rigRoot, "state");
1817
- const runtimeDir = resolve10(rigRoot, "runtime");
1818
- const binDir = resolve10(rigRoot, "bin");
1867
+ const root = resolve11(workspaceDir);
1868
+ const rigRoot = resolve11(root, ".rig");
1869
+ const logsDir = resolve11(rigRoot, "logs");
1870
+ const stateDir = resolve11(rigRoot, "state");
1871
+ const runtimeDir = resolve11(rigRoot, "runtime");
1872
+ const binDir = resolve11(rigRoot, "bin");
1819
1873
  return {
1820
1874
  workspaceDir: root,
1821
1875
  rigRoot,
1822
1876
  stateDir,
1823
1877
  logsDir,
1824
- artifactsRoot: resolve10(root, RIG_ARTIFACTS_DIRNAME),
1878
+ artifactsRoot: resolve11(root, RIG_ARTIFACTS_DIRNAME),
1825
1879
  runtimeDir,
1826
- homeDir: resolve10(rigRoot, "home"),
1827
- tmpDir: resolve10(rigRoot, "tmp"),
1828
- cacheDir: resolve10(rigRoot, "cache"),
1829
- sessionDir: resolve10(rigRoot, "session"),
1880
+ homeDir: resolve11(rigRoot, "home"),
1881
+ tmpDir: resolve11(rigRoot, "tmp"),
1882
+ cacheDir: resolve11(rigRoot, "cache"),
1883
+ sessionDir: resolve11(rigRoot, "session"),
1830
1884
  binDir,
1831
- distDir: resolve10(rigRoot, "dist"),
1832
- pluginBinDir: resolve10(binDir, "plugins"),
1833
- contextPath: resolve10(rigRoot, "runtime-context.json"),
1834
- controlPlaneEventsFile: resolve10(logsDir, "control-plane.events.jsonl")
1885
+ distDir: resolve11(rigRoot, "dist"),
1886
+ pluginBinDir: resolve11(binDir, "plugins"),
1887
+ contextPath: resolve11(rigRoot, "runtime-context.json"),
1888
+ controlPlaneEventsFile: resolve11(logsDir, "control-plane.events.jsonl")
1835
1889
  };
1836
1890
  }
1837
1891
  function resolveActiveRuntimeWorkspaceRoot(monorepoRoot) {
@@ -1839,14 +1893,14 @@ function resolveActiveRuntimeWorkspaceRoot(monorepoRoot) {
1839
1893
  if (!explicit) {
1840
1894
  throw new Error("No active runtime workspace. Set RIG_TASK_WORKSPACE or provision a task runtime first.");
1841
1895
  }
1842
- return resolve10(explicit);
1896
+ return resolve11(explicit);
1843
1897
  }
1844
1898
  function resolveRigLayout(projectRoot) {
1845
1899
  const monorepoRoot = resolveMonorepoRoot(projectRoot);
1846
- const definitionRoot = resolve10(projectRoot, RIG_DEFINITION_DIRNAME);
1900
+ const definitionRoot = resolve11(projectRoot, RIG_DEFINITION_DIRNAME);
1847
1901
  const runtimeWorkspaceRoot = resolveActiveRuntimeWorkspaceRoot(monorepoRoot);
1848
1902
  const runtimeLayout = resolveRuntimeWorkspaceLayout(runtimeWorkspaceRoot);
1849
- const policyDir = resolve10(definitionRoot, "policy");
1903
+ const policyDir = resolve11(definitionRoot, "policy");
1850
1904
  return {
1851
1905
  projectRoot,
1852
1906
  monorepoRoot,
@@ -1854,34 +1908,34 @@ function resolveRigLayout(projectRoot) {
1854
1908
  runtimeWorkspaceRoot,
1855
1909
  stateRoot: runtimeLayout.rigRoot,
1856
1910
  artifactsRoot: runtimeLayout.artifactsRoot,
1857
- configPath: resolve10(definitionRoot, "config.sh"),
1858
- taskConfigPath: resolve10(runtimeWorkspaceRoot, ".rig", "task-config.json"),
1911
+ configPath: resolve11(definitionRoot, "config.sh"),
1912
+ taskConfigPath: resolve11(runtimeWorkspaceRoot, ".rig", "task-config.json"),
1859
1913
  policyDir,
1860
- policyFile: resolve10(policyDir, "policy.json"),
1861
- pluginsDir: resolve10(definitionRoot, "plugins"),
1862
- hooksDir: resolve10(definitionRoot, "hooks"),
1863
- toolsDir: resolve10(definitionRoot, "tools"),
1864
- templatesDir: resolve10(definitionRoot, "templates"),
1865
- validationDir: resolve10(definitionRoot, "validation"),
1914
+ policyFile: resolve11(policyDir, "policy.json"),
1915
+ pluginsDir: resolve11(definitionRoot, "plugins"),
1916
+ hooksDir: resolve11(definitionRoot, "hooks"),
1917
+ toolsDir: resolve11(definitionRoot, "tools"),
1918
+ templatesDir: resolve11(definitionRoot, "templates"),
1919
+ validationDir: resolve11(definitionRoot, "validation"),
1866
1920
  stateDir: runtimeLayout.stateDir,
1867
1921
  logsDir: runtimeLayout.logsDir,
1868
- notificationsDir: resolve10(definitionRoot, "notifications"),
1922
+ notificationsDir: resolve11(definitionRoot, "notifications"),
1869
1923
  runtimeDir: runtimeLayout.runtimeDir,
1870
1924
  distDir: runtimeLayout.distDir,
1871
1925
  binDir: runtimeLayout.binDir,
1872
1926
  pluginBinDir: runtimeLayout.pluginBinDir,
1873
- keybindingsPath: resolve10(definitionRoot, "keybindings.json"),
1927
+ keybindingsPath: resolve11(definitionRoot, "keybindings.json"),
1874
1928
  controlPlaneEventsFile: runtimeLayout.controlPlaneEventsFile
1875
1929
  };
1876
1930
  }
1877
1931
 
1878
1932
  // packages/runtime/src/control-plane/native/runtime-native.ts
1879
1933
  import { dlopen, ptr, suffix, toBuffer } from "bun:ffi";
1880
- import { copyFileSync as copyFileSync2, existsSync as existsSync9, mkdirSync as mkdirSync4, renameSync as renameSync2, rmSync as rmSync2, statSync as statSync2 } from "fs";
1934
+ import { copyFileSync as copyFileSync2, existsSync as existsSync10, mkdirSync as mkdirSync5, renameSync as renameSync2, rmSync as rmSync3, statSync as statSync2 } from "fs";
1881
1935
  import { tmpdir as tmpdir4 } from "os";
1882
- import { dirname as dirname7, resolve as resolve11 } from "path";
1883
- var sharedNativeRuntimeOutputDir = resolve11(tmpdir4(), "rig-native");
1884
- var sharedNativeRuntimeOutputPath = resolve11(sharedNativeRuntimeOutputDir, `runtime-native-${process.platform}-${process.arch}.${suffix}`);
1936
+ import { dirname as dirname7, resolve as resolve12 } from "path";
1937
+ var sharedNativeRuntimeOutputDir = resolve12(tmpdir4(), "rig-native");
1938
+ var sharedNativeRuntimeOutputPath = resolve12(sharedNativeRuntimeOutputDir, `runtime-native-${process.platform}-${process.arch}.${suffix}`);
1885
1939
  var colocatedNativeRuntimeFileName = `runtime-native.${suffix}`;
1886
1940
  var nativeRuntimeLibrary = await loadNativeRuntimeLibrary();
1887
1941
  function requireNativeRuntimeLibrary(feature) {
@@ -1894,14 +1948,14 @@ async function ensureNativeRuntimeLibraryPath(outputPath = sharedNativeRuntimeOu
1894
1948
  if (await buildNativeRuntimeLibrary(outputPath, options)) {
1895
1949
  return outputPath;
1896
1950
  }
1897
- return !options.force && existsSync9(outputPath) ? outputPath : null;
1951
+ return !options.force && existsSync10(outputPath) ? outputPath : null;
1898
1952
  }
1899
1953
  async function loadNativeRuntimeLibrary() {
1900
1954
  if (process.env.RIG_DISABLE_ZIG_NATIVE === "1") {
1901
1955
  return null;
1902
1956
  }
1903
1957
  for (const candidate of nativeRuntimeLibraryCandidates()) {
1904
- if (!candidate || !existsSync9(candidate)) {
1958
+ if (!candidate || !existsSync10(candidate)) {
1905
1959
  continue;
1906
1960
  }
1907
1961
  const loaded = tryDlopenNativeRuntimeLibrary(candidate);
@@ -1917,10 +1971,10 @@ async function loadNativeRuntimeLibrary() {
1917
1971
  }
1918
1972
  function nativePackageLibraryCandidates(fromDir, names) {
1919
1973
  const candidates = [];
1920
- let cursor = resolve11(fromDir);
1974
+ let cursor = resolve12(fromDir);
1921
1975
  for (let index = 0;index < 8; index += 1) {
1922
1976
  for (const name of names) {
1923
- 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));
1977
+ 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));
1924
1978
  }
1925
1979
  const parent = dirname7(cursor);
1926
1980
  if (parent === cursor)
@@ -1936,22 +1990,22 @@ function nativeRuntimeLibraryCandidates() {
1936
1990
  return [...new Set([
1937
1991
  explicit,
1938
1992
  ...nativePackageLibraryCandidates(import.meta.dir, [colocatedNativeRuntimeFileName, platformSpecific]),
1939
- execDir ? resolve11(execDir, colocatedNativeRuntimeFileName) : "",
1940
- execDir ? resolve11(execDir, platformSpecific) : "",
1941
- execDir ? resolve11(execDir, "..", colocatedNativeRuntimeFileName) : "",
1942
- execDir ? resolve11(execDir, "..", platformSpecific) : "",
1943
- execDir ? resolve11(execDir, "lib", colocatedNativeRuntimeFileName) : "",
1944
- execDir ? resolve11(execDir, "..", "lib", colocatedNativeRuntimeFileName) : "",
1993
+ execDir ? resolve12(execDir, colocatedNativeRuntimeFileName) : "",
1994
+ execDir ? resolve12(execDir, platformSpecific) : "",
1995
+ execDir ? resolve12(execDir, "..", colocatedNativeRuntimeFileName) : "",
1996
+ execDir ? resolve12(execDir, "..", platformSpecific) : "",
1997
+ execDir ? resolve12(execDir, "lib", colocatedNativeRuntimeFileName) : "",
1998
+ execDir ? resolve12(execDir, "..", "lib", colocatedNativeRuntimeFileName) : "",
1945
1999
  sharedNativeRuntimeOutputPath
1946
2000
  ].filter(Boolean))];
1947
2001
  }
1948
2002
  function resolveNativeRuntimeSourcePath() {
1949
2003
  const explicit = process.env.RIG_NATIVE_RUNTIME_SOURCE?.trim();
1950
- if (explicit && existsSync9(explicit)) {
2004
+ if (explicit && existsSync10(explicit)) {
1951
2005
  return explicit;
1952
2006
  }
1953
- const bundled = resolve11(import.meta.dir, "../../../native/snapshot.zig");
1954
- return existsSync9(bundled) ? bundled : null;
2007
+ const bundled = resolve12(import.meta.dir, "../../../native/snapshot.zig");
2008
+ return existsSync10(bundled) ? bundled : null;
1955
2009
  }
1956
2010
  async function buildNativeRuntimeLibrary(outputPath, options = {}) {
1957
2011
  if (process.env.RIG_DISABLE_ZIG_NATIVE === "1") {
@@ -1964,8 +2018,8 @@ async function buildNativeRuntimeLibrary(outputPath, options = {}) {
1964
2018
  }
1965
2019
  const tempOutputPath = `${outputPath}.${process.pid}.${Date.now()}.${Math.random().toString(36).slice(2)}.tmp`;
1966
2020
  try {
1967
- mkdirSync4(dirname7(outputPath), { recursive: true });
1968
- const needsBuild = options.force === true || !existsSync9(outputPath) || statSync2(sourcePath).mtimeMs > statSync2(outputPath).mtimeMs;
2021
+ mkdirSync5(dirname7(outputPath), { recursive: true });
2022
+ const needsBuild = options.force === true || !existsSync10(outputPath) || statSync2(sourcePath).mtimeMs > statSync2(outputPath).mtimeMs;
1969
2023
  if (!needsBuild) {
1970
2024
  return true;
1971
2025
  }
@@ -1983,14 +2037,14 @@ async function buildNativeRuntimeLibrary(outputPath, options = {}) {
1983
2037
  stderr: "pipe"
1984
2038
  });
1985
2039
  const exitCode = await build.exited;
1986
- if (exitCode !== 0 || !existsSync9(tempOutputPath)) {
1987
- rmSync2(tempOutputPath, { force: true });
2040
+ if (exitCode !== 0 || !existsSync10(tempOutputPath)) {
2041
+ rmSync3(tempOutputPath, { force: true });
1988
2042
  return false;
1989
2043
  }
1990
2044
  renameSync2(tempOutputPath, outputPath);
1991
2045
  return true;
1992
2046
  } catch {
1993
- rmSync2(tempOutputPath, { force: true });
2047
+ rmSync3(tempOutputPath, { force: true });
1994
2048
  return false;
1995
2049
  }
1996
2050
  }
@@ -2114,11 +2168,11 @@ async function runCaptureAsync(command, cwd, env, timeoutMs) {
2114
2168
  return { exitCode, stdout, stderr };
2115
2169
  }
2116
2170
  function readJsonFile(path, fallback) {
2117
- if (!existsSync10(path)) {
2171
+ if (!existsSync11(path)) {
2118
2172
  return fallback;
2119
2173
  }
2120
2174
  try {
2121
- return JSON.parse(readFileSync7(path, "utf-8"));
2175
+ return JSON.parse(readFileSync8(path, "utf-8"));
2122
2176
  } catch {
2123
2177
  return fallback;
2124
2178
  }
@@ -2132,31 +2186,31 @@ function unique(values) {
2132
2186
  function resolveHarnessPaths(projectRoot) {
2133
2187
  const hasRuntimeWorkspace = Boolean(process.env.RIG_TASK_WORKSPACE?.trim());
2134
2188
  const monorepoRoot = resolveMonorepoRoot2(projectRoot);
2135
- const harnessRoot = resolve12(projectRoot, "rig");
2136
- const stateRoot = resolve12(projectRoot, ".rig");
2189
+ const harnessRoot = resolve13(projectRoot, "rig");
2190
+ const stateRoot = resolve13(projectRoot, ".rig");
2137
2191
  const layout = hasRuntimeWorkspace ? resolveRigLayout(projectRoot) : null;
2138
- const stateDir = layout?.stateDir ?? resolve12(stateRoot, "state");
2139
- const logsDir = layout?.logsDir ?? resolve12(stateRoot, "logs");
2140
- const artifactsDir = layout?.artifactsRoot ?? resolve12(monorepoRoot, "artifacts");
2141
- const taskConfigPath = layout?.taskConfigPath ?? resolve12(monorepoRoot, ".rig", "task-config.json");
2142
- const binDir = layout?.binDir ?? resolve12(stateRoot, "bin");
2192
+ const stateDir = layout?.stateDir ?? resolve13(stateRoot, "state");
2193
+ const logsDir = layout?.logsDir ?? resolve13(stateRoot, "logs");
2194
+ const artifactsDir = layout?.artifactsRoot ?? resolve13(monorepoRoot, "artifacts");
2195
+ const taskConfigPath = layout?.taskConfigPath ?? resolve13(monorepoRoot, ".rig", "task-config.json");
2196
+ const binDir = layout?.binDir ?? resolve13(stateRoot, "bin");
2143
2197
  return {
2144
2198
  harnessRoot,
2145
2199
  stateDir: process.env.RIG_STATE_DIR || stateDir,
2146
2200
  artifactsDir,
2147
2201
  logsDir: process.env.RIG_LOGS_DIR || logsDir,
2148
2202
  binDir,
2149
- hooksDir: resolve12(harnessRoot, "hooks"),
2150
- validationDir: resolve12(harnessRoot, "validation"),
2203
+ hooksDir: resolve13(harnessRoot, "hooks"),
2204
+ validationDir: resolve13(harnessRoot, "validation"),
2151
2205
  taskConfigPath,
2152
- sessionPath: process.env.RIG_SESSION_FILE || resolve12(stateRoot, "session", "session.json"),
2206
+ sessionPath: process.env.RIG_SESSION_FILE || resolve13(stateRoot, "session", "session.json"),
2153
2207
  monorepoRoot,
2154
- tsApiTestsDir: process.env.TS_API_TESTS_DIR || resolve12(monorepoRoot, "TSAPITests"),
2155
- taskRepoCommitsPath: resolve12(stateDir, "task-repo-commits.json"),
2156
- baseRepoPinsPath: resolve12(stateDir, "base-repo-pins.json"),
2157
- failedApproachesPath: resolve12(stateDir, "failed_approaches.md"),
2158
- agentProfilePath: resolve12(stateDir, "agent-profile.json"),
2159
- reviewProfilePath: resolve12(stateDir, "review-profile.json")
2208
+ tsApiTestsDir: process.env.TS_API_TESTS_DIR || resolve13(monorepoRoot, "TSAPITests"),
2209
+ taskRepoCommitsPath: resolve13(stateDir, "task-repo-commits.json"),
2210
+ baseRepoPinsPath: resolve13(stateDir, "base-repo-pins.json"),
2211
+ failedApproachesPath: resolve13(stateDir, "failed_approaches.md"),
2212
+ agentProfilePath: resolve13(stateDir, "agent-profile.json"),
2213
+ reviewProfilePath: resolve13(stateDir, "review-profile.json")
2160
2214
  };
2161
2215
  }
2162
2216
  function normalizeRelativeScopePath(inputPath) {
@@ -2249,34 +2303,34 @@ function createNativeScopeMatcher() {
2249
2303
  }
2250
2304
 
2251
2305
  // packages/runtime/src/control-plane/state-sync/repo.ts
2252
- import { existsSync as existsSync12 } from "fs";
2253
- import { resolve as resolve14 } from "path";
2306
+ import { existsSync as existsSync13 } from "fs";
2307
+ import { resolve as resolve15 } from "path";
2254
2308
 
2255
2309
  // packages/runtime/src/control-plane/repos/layout.ts
2256
- import { existsSync as existsSync11 } from "fs";
2257
- import { basename as basename5, dirname as dirname8, join as join3, resolve as resolve13 } from "path";
2310
+ import { existsSync as existsSync12 } from "fs";
2311
+ import { basename as basename5, dirname as dirname8, join as join3, resolve as resolve14 } from "path";
2258
2312
  function resolveRepoStateDir(projectRoot) {
2259
- const normalizedProjectRoot = resolve13(projectRoot);
2313
+ const normalizedProjectRoot = resolve14(projectRoot);
2260
2314
  const projectParent = dirname8(normalizedProjectRoot);
2261
2315
  if (basename5(projectParent) === ".worktrees") {
2262
2316
  const ownerRoot = dirname8(projectParent);
2263
- const ownerHasRepoMarkers = existsSync11(resolve13(ownerRoot, ".git")) || existsSync11(resolve13(ownerRoot, ".rig", "state"));
2317
+ const ownerHasRepoMarkers = existsSync12(resolve14(ownerRoot, ".git")) || existsSync12(resolve14(ownerRoot, ".rig", "state"));
2264
2318
  if (ownerHasRepoMarkers) {
2265
- return resolve13(ownerRoot, ".rig", "state");
2319
+ return resolve14(ownerRoot, ".rig", "state");
2266
2320
  }
2267
2321
  }
2268
- return resolve13(projectRoot, ".rig", "state");
2322
+ return resolve14(projectRoot, ".rig", "state");
2269
2323
  }
2270
2324
  function resolveManagedRepoLayout(projectRoot, repoId) {
2271
- const normalizedProjectRoot = resolve13(projectRoot);
2325
+ const normalizedProjectRoot = resolve14(projectRoot);
2272
2326
  const entry = getManagedRepoEntry(repoId);
2273
2327
  const stateDir = resolveRepoStateDir(normalizedProjectRoot);
2274
2328
  const metadataRelativePath = join3("repos", entry.id);
2275
- const metadataRoot = resolve13(stateDir, metadataRelativePath);
2329
+ const metadataRoot = resolve14(stateDir, metadataRelativePath);
2276
2330
  const runtimeWorkspace = process.env.RIG_TASK_WORKSPACE?.trim();
2277
- const runsInsideTaskWorktree = runtimeWorkspace && resolve13(runtimeWorkspace) === normalizedProjectRoot || basename5(dirname8(normalizedProjectRoot)) === ".worktrees";
2331
+ const runsInsideTaskWorktree = runtimeWorkspace && resolve14(runtimeWorkspace) === normalizedProjectRoot || basename5(dirname8(normalizedProjectRoot)) === ".worktrees";
2278
2332
  const isPrimaryManagedRepo = listManagedRepoEntries()[0]?.id === repoId;
2279
- const checkoutRoot = isPrimaryManagedRepo && runsInsideTaskWorktree ? resolveMonorepoRoot(normalizedProjectRoot) : entry.checkoutEnvVar && process.env[entry.checkoutEnvVar]?.trim() ? resolve13(process.env[entry.checkoutEnvVar].trim()) : resolve13(normalizedProjectRoot, entry.alias);
2333
+ const checkoutRoot = isPrimaryManagedRepo && runsInsideTaskWorktree ? resolveMonorepoRoot(normalizedProjectRoot) : entry.checkoutEnvVar && process.env[entry.checkoutEnvVar]?.trim() ? resolve14(process.env[entry.checkoutEnvVar].trim()) : resolve14(normalizedProjectRoot, entry.alias);
2280
2334
  return {
2281
2335
  projectRoot: normalizedProjectRoot,
2282
2336
  repoId: entry.id,
@@ -2284,12 +2338,12 @@ function resolveManagedRepoLayout(projectRoot, repoId) {
2284
2338
  defaultBranch: entry.defaultBranch,
2285
2339
  remoteUrl: entry.remoteEnvVar && process.env[entry.remoteEnvVar]?.trim() ? process.env[entry.remoteEnvVar].trim() : entry.defaultRemoteUrl,
2286
2340
  checkoutRoot,
2287
- worktreesRoot: resolve13(checkoutRoot, ".worktrees"),
2341
+ worktreesRoot: resolve14(checkoutRoot, ".worktrees"),
2288
2342
  stateDir,
2289
2343
  metadataRoot,
2290
2344
  metadataRelativePath,
2291
- mirrorRoot: resolve13(metadataRoot, "mirror.git"),
2292
- mirrorStatePath: resolve13(metadataRoot, "mirror-state.json"),
2345
+ mirrorRoot: resolve14(metadataRoot, "mirror.git"),
2346
+ mirrorStatePath: resolve14(metadataRoot, "mirror-state.json"),
2293
2347
  mirrorStateRelativePath: join3(metadataRelativePath, "mirror-state.json")
2294
2348
  };
2295
2349
  }
@@ -2311,7 +2365,7 @@ function resolveTrackerRepoPath(projectRoot) {
2311
2365
  const monorepoRoot = resolveMonorepoRoot2(projectRoot);
2312
2366
  try {
2313
2367
  const layout = resolveMonorepoRepoLayout(projectRoot);
2314
- if (existsSync12(resolve14(layout.mirrorRoot, "HEAD"))) {
2368
+ if (existsSync13(resolve15(layout.mirrorRoot, "HEAD"))) {
2315
2369
  return layout.mirrorRoot;
2316
2370
  }
2317
2371
  } catch {}
@@ -2322,8 +2376,8 @@ function resolveTrackerRepoPath(projectRoot) {
2322
2376
  var DEFAULT_READ_DEPS = {
2323
2377
  fetchRef: nativeFetchRef,
2324
2378
  readBlobAtRef: nativeReadBlobAtRef,
2325
- exists: existsSync13,
2326
- readFile: (path) => readFileSync8(path, "utf8")
2379
+ exists: existsSync14,
2380
+ readFile: (path) => readFileSync9(path, "utf8")
2327
2381
  };
2328
2382
  function parseIssueStatus(rawStatus) {
2329
2383
  const normalized = normalizeTaskLifecycleStatus(rawStatus);
@@ -2404,12 +2458,12 @@ function shouldPreferLocalTrackerState(options) {
2404
2458
  if (runtimeContextPath) {
2405
2459
  return true;
2406
2460
  }
2407
- return existsSync13(resolve15(runtimeWorkspace, ".rig", "runtime-context.json"));
2461
+ return existsSync14(resolve16(runtimeWorkspace, ".rig", "runtime-context.json"));
2408
2462
  }
2409
2463
  function readLocalTrackerState(projectRoot, deps) {
2410
2464
  const monorepoRoot = resolveMonorepoRoot2(projectRoot);
2411
- const issuesPath = resolve15(monorepoRoot, ".beads", "issues.jsonl");
2412
- const taskStatePath = resolve15(monorepoRoot, ".beads", "task-state.json");
2465
+ const issuesPath = resolve16(monorepoRoot, ".beads", "issues.jsonl");
2466
+ const taskStatePath = resolve16(monorepoRoot, ".beads", "task-state.json");
2413
2467
  return projectSyncedTrackerSnapshot({
2414
2468
  source: "local",
2415
2469
  issuesBaseOid: null,
@@ -2471,7 +2525,7 @@ function readValidationDescriptions(projectRoot) {
2471
2525
  return readValidationDescriptionMap(raw);
2472
2526
  }
2473
2527
  function readSourceValidationDescriptions(projectRoot) {
2474
- const rootRaw = readJsonFile(resolve16(projectRoot, "rig", "task-config.json"), {});
2528
+ const rootRaw = readJsonFile(resolve17(projectRoot, "rig", "task-config.json"), {});
2475
2529
  const sourcePath = findSourceTaskConfigPath(projectRoot);
2476
2530
  const sourceRaw = sourcePath ? readJsonFile(sourcePath, {}) : {};
2477
2531
  const rootDescriptions = readValidationDescriptionMap(rootRaw);
@@ -2547,15 +2601,15 @@ function readValidationDescriptionsFromMeta(meta) {
2547
2601
  return meta.validation_descriptions;
2548
2602
  }
2549
2603
  function readLocalSourceTaskStateEnvelope(projectRoot) {
2550
- const taskStatePath = resolve16(resolveMonorepoRoot2(projectRoot), ".beads", "task-state.json");
2604
+ const taskStatePath = resolve17(resolveMonorepoRoot2(projectRoot), ".beads", "task-state.json");
2551
2605
  return readTaskStateMetadataEnvelope(readJsonFile(taskStatePath, {}));
2552
2606
  }
2553
2607
  function readLocalSourceTaskLifecycleStatus(projectRoot, taskId) {
2554
- const issuesPath = resolve16(resolveMonorepoRoot2(projectRoot), ".beads", "issues.jsonl");
2555
- if (!existsSync14(issuesPath)) {
2608
+ const issuesPath = resolve17(resolveMonorepoRoot2(projectRoot), ".beads", "issues.jsonl");
2609
+ if (!existsSync15(issuesPath)) {
2556
2610
  return null;
2557
2611
  }
2558
- for (const line of readFileSync9(issuesPath, "utf8").split(/\r?\n/)) {
2612
+ for (const line of readFileSync10(issuesPath, "utf8").split(/\r?\n/)) {
2559
2613
  const trimmed = line.trim();
2560
2614
  if (!trimmed) {
2561
2615
  continue;
@@ -2596,25 +2650,25 @@ function lookupTask(projectRoot, input) {
2596
2650
  function artifactDirForId(projectRoot, id) {
2597
2651
  const workspaceDir = process.env.RIG_TASK_WORKSPACE?.trim();
2598
2652
  if (workspaceDir) {
2599
- const worktreeArtifacts = resolve16(workspaceDir, "artifacts", id);
2600
- if (existsSync14(worktreeArtifacts) || existsSync14(resolve16(workspaceDir, "artifacts"))) {
2653
+ const worktreeArtifacts = resolve17(workspaceDir, "artifacts", id);
2654
+ if (existsSync15(worktreeArtifacts) || existsSync15(resolve17(workspaceDir, "artifacts"))) {
2601
2655
  return worktreeArtifacts;
2602
2656
  }
2603
2657
  }
2604
2658
  try {
2605
2659
  const paths = resolveHarnessPaths(projectRoot);
2606
- return resolve16(paths.artifactsDir, id);
2660
+ return resolve17(paths.artifactsDir, id);
2607
2661
  } catch {
2608
- return resolve16(resolveMonorepoRoot2(projectRoot), "artifacts", id);
2662
+ return resolve17(resolveMonorepoRoot2(projectRoot), "artifacts", id);
2609
2663
  }
2610
2664
  }
2611
2665
  function resolveTaskConfigPath(projectRoot) {
2612
2666
  const paths = resolveHarnessPaths(projectRoot);
2613
- if (existsSync14(paths.taskConfigPath)) {
2667
+ if (existsSync15(paths.taskConfigPath)) {
2614
2668
  return paths.taskConfigPath;
2615
2669
  }
2616
2670
  for (const candidate of sourceTaskConfigCandidates(projectRoot)) {
2617
- if (existsSync14(candidate)) {
2671
+ if (existsSync15(candidate)) {
2618
2672
  return candidate;
2619
2673
  }
2620
2674
  }
@@ -2622,7 +2676,7 @@ function resolveTaskConfigPath(projectRoot) {
2622
2676
  }
2623
2677
  function findSourceTaskConfigPath(projectRoot) {
2624
2678
  for (const candidate of sourceTaskConfigCandidates(projectRoot)) {
2625
- if (existsSync14(candidate)) {
2679
+ if (existsSync15(candidate)) {
2626
2680
  return candidate;
2627
2681
  }
2628
2682
  }
@@ -2635,7 +2689,7 @@ function readAndSyncSourceTaskConfig(projectRoot) {
2635
2689
  const synced = synchronizeTaskConfigWithTracker(projectRoot, raw);
2636
2690
  if (sourcePath && synced.updated) {
2637
2691
  try {
2638
- writeFileSync5(sourcePath, `${JSON.stringify(synced.config, null, 2)}
2692
+ writeFileSync6(sourcePath, `${JSON.stringify(synced.config, null, 2)}
2639
2693
  `, "utf-8");
2640
2694
  } catch {}
2641
2695
  }
@@ -2687,12 +2741,12 @@ function shouldRefreshAutoSyncedTaskConfigEntry(entry) {
2687
2741
  return !candidate.role;
2688
2742
  }
2689
2743
  function readSourceIssueRecords(projectRoot) {
2690
- const issuesPath = resolve16(resolveMonorepoRoot2(projectRoot), ".beads", "issues.jsonl");
2691
- if (!existsSync14(issuesPath)) {
2744
+ const issuesPath = resolve17(resolveMonorepoRoot2(projectRoot), ".beads", "issues.jsonl");
2745
+ if (!existsSync15(issuesPath)) {
2692
2746
  return [];
2693
2747
  }
2694
2748
  const records = [];
2695
- for (const line of readFileSync9(issuesPath, "utf-8").split(/\r?\n/)) {
2749
+ for (const line of readFileSync10(issuesPath, "utf-8").split(/\r?\n/)) {
2696
2750
  const trimmed = line.trim();
2697
2751
  if (!trimmed) {
2698
2752
  continue;
@@ -2748,19 +2802,19 @@ function readConfiguredFileTaskConfig(projectRoot) {
2748
2802
  if (!sourcePath) {
2749
2803
  return {};
2750
2804
  }
2751
- const directory = resolve16(projectRoot, sourcePath);
2752
- if (!existsSync14(directory)) {
2805
+ const directory = resolve17(projectRoot, sourcePath);
2806
+ if (!existsSync15(directory)) {
2753
2807
  return {};
2754
2808
  }
2755
2809
  const config = {};
2756
- for (const name of readdirSync2(directory)) {
2810
+ for (const name of readdirSync3(directory)) {
2757
2811
  if (!FILE_TASK_PATTERN2.test(name))
2758
2812
  continue;
2759
- const file = resolve16(directory, name);
2813
+ const file = resolve17(directory, name);
2760
2814
  try {
2761
2815
  if (!statSync3(file).isFile())
2762
2816
  continue;
2763
- const raw = JSON.parse(readFileSync9(file, "utf8"));
2817
+ const raw = JSON.parse(readFileSync10(file, "utf8"));
2764
2818
  if (!raw || typeof raw !== "object" || Array.isArray(raw))
2765
2819
  continue;
2766
2820
  const record = raw;
@@ -2802,10 +2856,10 @@ function firstStringList2(...candidates) {
2802
2856
  return [];
2803
2857
  }
2804
2858
  function readConfiguredFilesTaskSourcePath2(projectRoot) {
2805
- const jsonPath = resolve16(projectRoot, "rig.config.json");
2806
- if (existsSync14(jsonPath)) {
2859
+ const jsonPath = resolve17(projectRoot, "rig.config.json");
2860
+ if (existsSync15(jsonPath)) {
2807
2861
  try {
2808
- const parsed = JSON.parse(readFileSync9(jsonPath, "utf8"));
2862
+ const parsed = JSON.parse(readFileSync10(jsonPath, "utf8"));
2809
2863
  if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
2810
2864
  const taskSource = parsed.taskSource;
2811
2865
  if (taskSource && typeof taskSource === "object" && !Array.isArray(taskSource)) {
@@ -2817,12 +2871,12 @@ function readConfiguredFilesTaskSourcePath2(projectRoot) {
2817
2871
  return null;
2818
2872
  }
2819
2873
  }
2820
- const tsPath = resolve16(projectRoot, "rig.config.ts");
2821
- if (!existsSync14(tsPath)) {
2874
+ const tsPath = resolve17(projectRoot, "rig.config.ts");
2875
+ if (!existsSync15(tsPath)) {
2822
2876
  return null;
2823
2877
  }
2824
2878
  try {
2825
- const source = readFileSync9(tsPath, "utf8");
2879
+ const source = readFileSync10(tsPath, "utf8");
2826
2880
  const taskSourceBlock = source.match(/taskSource\s*:\s*\{[\s\S]*?\}/m)?.[0] ?? "";
2827
2881
  const kind = taskSourceBlock.match(/kind\s*:\s*["']([^"']+)["']/)?.[1];
2828
2882
  if (kind !== "files") {
@@ -2836,23 +2890,23 @@ function readConfiguredFilesTaskSourcePath2(projectRoot) {
2836
2890
  function sourceTaskConfigCandidates(projectRoot) {
2837
2891
  const runtimeContext = loadRuntimeContextFromEnv();
2838
2892
  return [
2839
- runtimeContext?.monorepoMainRoot ? resolve16(runtimeContext.monorepoMainRoot, ".rig", "task-config.json") : "",
2840
- process.env.MONOREPO_MAIN_ROOT?.trim() ? resolve16(process.env.MONOREPO_MAIN_ROOT.trim(), ".rig", "task-config.json") : "",
2841
- resolve16(resolveMonorepoRoot2(projectRoot), ".rig", "task-config.json")
2893
+ runtimeContext?.monorepoMainRoot ? resolve17(runtimeContext.monorepoMainRoot, ".rig", "task-config.json") : "",
2894
+ process.env.MONOREPO_MAIN_ROOT?.trim() ? resolve17(process.env.MONOREPO_MAIN_ROOT.trim(), ".rig", "task-config.json") : "",
2895
+ resolve17(resolveMonorepoRoot2(projectRoot), ".rig", "task-config.json")
2842
2896
  ].filter(Boolean);
2843
2897
  }
2844
2898
 
2845
2899
  // packages/runtime/src/control-plane/native/validator.ts
2846
- import { existsSync as existsSync18, mkdirSync as mkdirSync7, writeFileSync as writeFileSync7 } from "fs";
2847
- import { resolve as resolve21 } from "path";
2900
+ import { existsSync as existsSync19, mkdirSync as mkdirSync8, writeFileSync as writeFileSync8 } from "fs";
2901
+ import { resolve as resolve22 } from "path";
2848
2902
 
2849
2903
  // packages/runtime/src/control-plane/native/validator-binaries.ts
2850
- import { existsSync as existsSync17, mkdirSync as mkdirSync6, rmSync as rmSync4, statSync as statSync4 } from "fs";
2851
- import { dirname as dirname10, resolve as resolve20 } from "path";
2904
+ import { existsSync as existsSync18, mkdirSync as mkdirSync7, rmSync as rmSync5, statSync as statSync4 } from "fs";
2905
+ import { dirname as dirname10, resolve as resolve21 } from "path";
2852
2906
 
2853
2907
  // packages/runtime/src/binary-run.ts
2854
- import { chmodSync as chmodSync2, cpSync, existsSync as existsSync15, mkdirSync as mkdirSync5, renameSync as renameSync3, rmSync as rmSync3, writeFileSync as writeFileSync6 } from "fs";
2855
- import { basename as basename7, dirname as dirname9, resolve as resolve17 } from "path";
2908
+ import { chmodSync as chmodSync2, cpSync, existsSync as existsSync16, mkdirSync as mkdirSync6, renameSync as renameSync3, rmSync as rmSync4, writeFileSync as writeFileSync7 } from "fs";
2909
+ import { basename as basename7, dirname as dirname9, resolve as resolve18 } from "path";
2856
2910
  import { fileURLToPath } from "url";
2857
2911
  import { drainMicrotasks, gcAndSweep } from "bun:jsc";
2858
2912
  var runtimeBinaryBuildQueue = Promise.resolve();
@@ -2878,9 +2932,9 @@ async function buildRuntimeBinary(options) {
2878
2932
  });
2879
2933
  }
2880
2934
  async function buildRuntimeBinaryInProcess(options, manifest) {
2881
- const tempBuildDir = resolve17(dirname9(options.outputPath), `.bun-build-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`);
2882
- const tempOutputPath = resolve17(tempBuildDir, basename7(options.outputPath));
2883
- mkdirSync5(tempBuildDir, { recursive: true });
2935
+ const tempBuildDir = resolve18(dirname9(options.outputPath), `.bun-build-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`);
2936
+ const tempOutputPath = resolve18(tempBuildDir, basename7(options.outputPath));
2937
+ mkdirSync6(tempBuildDir, { recursive: true });
2884
2938
  await withTemporaryEnv({
2885
2939
  ...options.env,
2886
2940
  ...options.define ? { RIG_BUILD_CONFIG_JSON: JSON.stringify(options.define) } : {}
@@ -2905,7 +2959,7 @@ async function buildRuntimeBinaryInProcess(options, manifest) {
2905
2959
  `);
2906
2960
  throw new Error(`Failed to build ${options.entrypoint}: ${details || "Bun.build() returned errors"}`);
2907
2961
  }
2908
- if (!existsSync15(tempOutputPath)) {
2962
+ if (!existsSync16(tempOutputPath)) {
2909
2963
  const emitted = buildResult.outputs.map((output) => output.path).join(", ") || "(none)";
2910
2964
  throw new Error(`Failed to build ${options.entrypoint}: Bun.build() did not emit ${tempOutputPath}. Emitted: ${emitted}`);
2911
2965
  }
@@ -2920,7 +2974,7 @@ async function buildRuntimeBinaryInProcess(options, manifest) {
2920
2974
  });
2921
2975
  }
2922
2976
  })).finally(() => {
2923
- rmSync3(tempBuildDir, { recursive: true, force: true });
2977
+ rmSync4(tempBuildDir, { recursive: true, force: true });
2924
2978
  });
2925
2979
  }
2926
2980
  function runBestEffortBuildGc() {
@@ -2937,8 +2991,8 @@ function runtimeBinaryCacheManifestPath(outputPath) {
2937
2991
  function resolveRuntimeBinaryBuildOptions(options) {
2938
2992
  return {
2939
2993
  ...options,
2940
- entrypoint: resolve17(options.cwd, options.sourcePath),
2941
- outputPath: resolve17(options.outputPath)
2994
+ entrypoint: resolve18(options.cwd, options.sourcePath),
2995
+ outputPath: resolve18(options.outputPath)
2942
2996
  };
2943
2997
  }
2944
2998
  function shouldUseRuntimeBinaryBuildWorker() {
@@ -2952,7 +3006,7 @@ function shouldUseRuntimeBinaryBuildWorker() {
2952
3006
  }
2953
3007
  async function buildRuntimeBinaryViaWorker(options) {
2954
3008
  const workerSourcePath = resolveRuntimeBinaryBuildWorkerSourcePath(options);
2955
- if (!workerSourcePath || !existsSync15(workerSourcePath)) {
3009
+ if (!workerSourcePath || !existsSync16(workerSourcePath)) {
2956
3010
  await buildRuntimeBinaryInProcess(options, {
2957
3011
  manifestPath: runtimeBinaryCacheManifestPath(options.outputPath),
2958
3012
  buildKey: createRuntimeBinaryBuildKey({
@@ -2983,13 +3037,13 @@ async function buildRuntimeBinaryViaWorker(options) {
2983
3037
  new Response(build.stdout).text(),
2984
3038
  new Response(build.stderr).text()
2985
3039
  ]);
2986
- rmSync3(payloadPath, { force: true });
3040
+ rmSync4(payloadPath, { force: true });
2987
3041
  if (exitCode !== 0) {
2988
3042
  throw new Error(`Failed to build ${options.entrypoint}: ${(stderr || stdout || `worker exited ${exitCode}`).trim()}`);
2989
3043
  }
2990
3044
  }
2991
3045
  function createRuntimeBinaryBuildWorkerPayloadPath(outputPath) {
2992
- return resolve17(dirname9(outputPath), `.bun-build-worker-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}.json`);
3046
+ return resolve18(dirname9(outputPath), `.bun-build-worker-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}.json`);
2993
3047
  }
2994
3048
  function resolveRuntimeBinaryBuildWorkerSourcePath(options) {
2995
3049
  const envRoots = [
@@ -2998,13 +3052,13 @@ function resolveRuntimeBinaryBuildWorkerSourcePath(options) {
2998
3052
  process.env.PROJECT_RIG_ROOT?.trim()
2999
3053
  ].filter(Boolean);
3000
3054
  for (const root of envRoots) {
3001
- const candidate = resolve17(root, "packages/runtime/src/binary-build-worker.ts");
3002
- if (existsSync15(candidate)) {
3055
+ const candidate = resolve18(root, "packages/runtime/src/binary-build-worker.ts");
3056
+ if (existsSync16(candidate)) {
3003
3057
  return candidate;
3004
3058
  }
3005
3059
  }
3006
- const localCandidate = resolve17(import.meta.dir, "binary-build-worker.ts");
3007
- return existsSync15(localCandidate) ? localCandidate : null;
3060
+ const localCandidate = resolve18(import.meta.dir, "binary-build-worker.ts");
3061
+ return existsSync16(localCandidate) ? localCandidate : null;
3008
3062
  }
3009
3063
  function resolveRuntimeBinaryBuildWorkerInvocation() {
3010
3064
  const bunPath = Bun.which("bun");
@@ -3040,7 +3094,7 @@ function createRuntimeBinaryBuildKey(input) {
3040
3094
  });
3041
3095
  }
3042
3096
  async function isRuntimeBinaryBuildFresh(input) {
3043
- if (!existsSync15(input.outputPath) || !existsSync15(input.manifestPath)) {
3097
+ if (!existsSync16(input.outputPath) || !existsSync16(input.manifestPath)) {
3044
3098
  return false;
3045
3099
  }
3046
3100
  let manifest = null;
@@ -3053,7 +3107,7 @@ async function isRuntimeBinaryBuildFresh(input) {
3053
3107
  return false;
3054
3108
  }
3055
3109
  for (const [filePath, expectedDigest] of Object.entries(manifest.inputs || {})) {
3056
- if (!existsSync15(filePath)) {
3110
+ if (!existsSync16(filePath)) {
3057
3111
  return false;
3058
3112
  }
3059
3113
  if (await sha256File(filePath) !== expectedDigest) {
@@ -3066,7 +3120,7 @@ async function writeRuntimeBinaryCacheManifest(input) {
3066
3120
  const inputs = {};
3067
3121
  for (const inputPath of Object.keys(input.metafile?.inputs || {}).sort()) {
3068
3122
  const normalized = normalizeBuildInputPath(input.cwd, inputPath);
3069
- if (!normalized || !existsSync15(normalized)) {
3123
+ if (!normalized || !existsSync16(normalized)) {
3070
3124
  continue;
3071
3125
  }
3072
3126
  inputs[normalized] = await sha256File(normalized);
@@ -3089,7 +3143,7 @@ function normalizeBuildInputPath(cwd, inputPath) {
3089
3143
  if (inputPath.startsWith("<")) {
3090
3144
  return null;
3091
3145
  }
3092
- return resolve17(cwd, inputPath);
3146
+ return resolve18(cwd, inputPath);
3093
3147
  }
3094
3148
  async function sha256File(path) {
3095
3149
  const hasher = new Bun.CryptoHasher("sha256");
@@ -3105,8 +3159,8 @@ function sortRecord(value) {
3105
3159
  async function runSerializedRuntimeBinaryBuild(action) {
3106
3160
  const previous = runtimeBinaryBuildQueue;
3107
3161
  let release;
3108
- runtimeBinaryBuildQueue = new Promise((resolve18) => {
3109
- release = resolve18;
3162
+ runtimeBinaryBuildQueue = new Promise((resolve19) => {
3163
+ release = resolve19;
3110
3164
  });
3111
3165
  await previous;
3112
3166
  try {
@@ -3151,11 +3205,11 @@ async function withTemporaryCwd(cwd, action) {
3151
3205
  }
3152
3206
 
3153
3207
  // packages/runtime/src/control-plane/runtime/provisioning-env.ts
3154
- import { delimiter, resolve as resolve19 } from "path";
3208
+ import { delimiter, resolve as resolve20 } from "path";
3155
3209
 
3156
3210
  // packages/runtime/src/control-plane/runtime/runtime-paths.ts
3157
- import { existsSync as existsSync16, readdirSync as readdirSync3, realpathSync } from "fs";
3158
- import { resolve as resolve18 } from "path";
3211
+ import { existsSync as existsSync17, readdirSync as readdirSync4, realpathSync } from "fs";
3212
+ import { resolve as resolve19 } from "path";
3159
3213
 
3160
3214
  // packages/runtime/src/control-plane/runtime/sandbox/utils.ts
3161
3215
  function uniq(values) {
@@ -3173,7 +3227,7 @@ function resolveBunBinaryPath() {
3173
3227
  }
3174
3228
  const home = process.env.HOME?.trim();
3175
3229
  const fallbackCandidates = [
3176
- home ? resolve18(home, ".bun/bin/bun") : "",
3230
+ home ? resolve19(home, ".bun/bin/bun") : "",
3177
3231
  "/opt/homebrew/bin/bun",
3178
3232
  "/usr/local/bin/bun",
3179
3233
  "/usr/bin/bun"
@@ -3201,8 +3255,8 @@ function resolveClaudeBinaryPath() {
3201
3255
  }
3202
3256
  const home = process.env.HOME?.trim();
3203
3257
  const fallbackCandidates = [
3204
- home ? resolve18(home, ".local/bin/claude") : "",
3205
- home ? resolve18(home, ".local/share/claude/local/claude") : "",
3258
+ home ? resolve19(home, ".local/bin/claude") : "",
3259
+ home ? resolve19(home, ".local/share/claude/local/claude") : "",
3206
3260
  "/opt/homebrew/bin/claude",
3207
3261
  "/usr/local/bin/claude",
3208
3262
  "/usr/bin/claude"
@@ -3216,51 +3270,51 @@ function resolveClaudeBinaryPath() {
3216
3270
  throw new Error("claude not found in PATH");
3217
3271
  }
3218
3272
  function resolveBunInstallDir(bunBinaryPath = resolveBunBinaryPath()) {
3219
- return resolve18(bunBinaryPath, "../..");
3273
+ return resolve19(bunBinaryPath, "../..");
3220
3274
  }
3221
3275
  function resolveClaudeInstallDir() {
3222
3276
  const realPath = resolveClaudeBinaryPath();
3223
- return resolve18(realPath, "..");
3277
+ return resolve19(realPath, "..");
3224
3278
  }
3225
3279
  function resolveNodeInstallDir() {
3226
3280
  const preferredNode = resolvePreferredNodeBinary();
3227
3281
  if (!preferredNode)
3228
3282
  return null;
3229
3283
  const explicitNode = process.env.RIG_NODE_BIN?.trim();
3230
- if (explicitNode && resolve18(explicitNode) === resolve18(preferredNode)) {
3231
- return preferredNode.endsWith("/bin/node") ? resolve18(preferredNode, "../..") : resolve18(preferredNode, "..");
3284
+ if (explicitNode && resolve19(explicitNode) === resolve19(preferredNode)) {
3285
+ return preferredNode.endsWith("/bin/node") ? resolve19(preferredNode, "../..") : resolve19(preferredNode, "..");
3232
3286
  }
3233
3287
  try {
3234
3288
  const realPath = realpathSync(preferredNode);
3235
3289
  if (realPath.endsWith("/bin/node")) {
3236
- return resolve18(realPath, "../..");
3290
+ return resolve19(realPath, "../..");
3237
3291
  }
3238
- return resolve18(realPath, "..");
3292
+ return resolve19(realPath, "..");
3239
3293
  } catch {
3240
- return resolve18(preferredNode, "..");
3294
+ return resolve19(preferredNode, "..");
3241
3295
  }
3242
3296
  }
3243
3297
  function resolvePreferredNodeBinary() {
3244
3298
  const candidates = [];
3245
3299
  const envNode = process.env.RIG_NODE_BIN?.trim();
3246
3300
  if (envNode) {
3247
- const explicit = resolve18(envNode);
3248
- if (existsSync16(explicit)) {
3301
+ const explicit = resolve19(envNode);
3302
+ if (existsSync17(explicit)) {
3249
3303
  return explicit;
3250
3304
  }
3251
3305
  }
3252
3306
  const nvmBin = process.env.NVM_BIN?.trim();
3253
3307
  if (nvmBin) {
3254
- candidates.push(resolve18(nvmBin, "node"));
3308
+ candidates.push(resolve19(nvmBin, "node"));
3255
3309
  }
3256
3310
  const home = process.env.HOME?.trim();
3257
3311
  if (home) {
3258
- const nvmVersionsDir = resolve18(home, ".nvm/versions/node");
3259
- if (existsSync16(nvmVersionsDir)) {
3312
+ const nvmVersionsDir = resolve19(home, ".nvm/versions/node");
3313
+ if (existsSync17(nvmVersionsDir)) {
3260
3314
  try {
3261
- const versionDirs = readdirSync3(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/, "")));
3315
+ 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/, "")));
3262
3316
  for (const versionDir of versionDirs) {
3263
- candidates.push(resolve18(nvmVersionsDir, versionDir, "bin/node"));
3317
+ candidates.push(resolve19(nvmVersionsDir, versionDir, "bin/node"));
3264
3318
  }
3265
3319
  } catch {}
3266
3320
  }
@@ -3269,8 +3323,8 @@ function resolvePreferredNodeBinary() {
3269
3323
  if (whichNode) {
3270
3324
  candidates.push(whichNode);
3271
3325
  }
3272
- const deduped = uniq(candidates.map((candidate) => resolve18(candidate)));
3273
- const existing = deduped.filter((candidate) => existsSync16(candidate));
3326
+ const deduped = uniq(candidates.map((candidate) => resolve19(candidate)));
3327
+ const existing = deduped.filter((candidate) => existsSync17(candidate));
3274
3328
  if (existing.length === 0) {
3275
3329
  return null;
3276
3330
  }
@@ -3284,7 +3338,7 @@ function resolvePreferredNodeBinary() {
3284
3338
  return existing[0] ?? null;
3285
3339
  }
3286
3340
  function inferNodeMajor(nodeBinaryPath) {
3287
- const normalized = resolve18(nodeBinaryPath).replace(/\\/g, "/");
3341
+ const normalized = resolve19(nodeBinaryPath).replace(/\\/g, "/");
3288
3342
  const match = normalized.match(/(?:^|\/)(?:node-)?v?(\d+)\.\d+\.\d+(?:\/|$)/);
3289
3343
  if (!match) {
3290
3344
  return null;
@@ -3296,8 +3350,8 @@ function normalizeExecutablePath(candidate) {
3296
3350
  if (!candidate) {
3297
3351
  return "";
3298
3352
  }
3299
- const normalized = resolve18(candidate);
3300
- if (!existsSync16(normalized)) {
3353
+ const normalized = resolve19(candidate);
3354
+ if (!existsSync17(normalized)) {
3301
3355
  return "";
3302
3356
  }
3303
3357
  try {
@@ -3307,7 +3361,7 @@ function normalizeExecutablePath(candidate) {
3307
3361
  }
3308
3362
  }
3309
3363
  function looksLikeRuntimeGateway(candidate) {
3310
- const normalized = resolve18(candidate).replace(/\\/g, "/");
3364
+ const normalized = resolve19(candidate).replace(/\\/g, "/");
3311
3365
  return normalized.includes("/.rig/bin/") || normalized.endsWith("/rig-shell") || normalized.endsWith("/rig-agent");
3312
3366
  }
3313
3367
 
@@ -3328,7 +3382,7 @@ function runtimeProvisioningEnv(baseEnv = process.env) {
3328
3382
  try {
3329
3383
  return resolveClaudeInstallDir();
3330
3384
  } catch {
3331
- return resolve19(claudeBinary, "..");
3385
+ return resolve20(claudeBinary, "..");
3332
3386
  }
3333
3387
  })() : "";
3334
3388
  const nodeDir = resolveNodeInstallDir();
@@ -3338,8 +3392,8 @@ function runtimeProvisioningEnv(baseEnv = process.env) {
3338
3392
  `${bunDir}/bin`,
3339
3393
  claudeDir,
3340
3394
  nodeDir ? `${nodeDir}/bin` : "",
3341
- realHome ? resolve19(realHome, ".local/bin") : "",
3342
- realHome ? resolve19(realHome, ".cargo/bin") : "",
3395
+ realHome ? resolve20(realHome, ".local/bin") : "",
3396
+ realHome ? resolve20(realHome, ".cargo/bin") : "",
3343
3397
  ...inheritedPath,
3344
3398
  "/usr/local/bin",
3345
3399
  "/usr/local/sbin",
@@ -3370,9 +3424,9 @@ function runtimeProvisioningEnv(baseEnv = process.env) {
3370
3424
  // packages/runtime/src/control-plane/native/validator-binaries.ts
3371
3425
  function resolveValidatorBinaryPath(projectRoot, binaryName, runtimeContext) {
3372
3426
  if (runtimeContext) {
3373
- return resolve20(runtimeContext.binDir, "validators", binaryName);
3427
+ return resolve21(runtimeContext.binDir, "validators", binaryName);
3374
3428
  }
3375
- return resolve20(resolveHarnessPaths(projectRoot).binDir, "validators", binaryName);
3429
+ return resolve21(resolveHarnessPaths(projectRoot).binDir, "validators", binaryName);
3376
3430
  }
3377
3431
  async function ensureValidatorBinary(projectRoot, checkId, runtimeContext) {
3378
3432
  const match = checkId.match(/^([a-z][\w-]*):([a-z][\w-]*)$/);
@@ -3387,19 +3441,19 @@ async function ensureValidatorBinary(projectRoot, checkId, runtimeContext) {
3387
3441
  const binaryName = `${category}-${check}`;
3388
3442
  const binaryPath = resolveValidatorBinaryPath(projectRoot, binaryName, runtimeContext);
3389
3443
  const hostProjectRoot = runtimeContext?.hostProjectRoot?.trim() || projectRoot;
3390
- const sourcePath = resolve20(hostProjectRoot, "packages/runtime/src/control-plane/validators", category, `${check}.ts`);
3391
- if (!existsSync17(sourcePath)) {
3444
+ const sourcePath = resolve21(hostProjectRoot, "packages/runtime/src/control-plane/validators", category, `${check}.ts`);
3445
+ if (!existsSync18(sourcePath)) {
3392
3446
  return null;
3393
3447
  }
3394
3448
  const sourceMtime = statSync4(sourcePath).mtimeMs;
3395
- const binaryExists = existsSync17(binaryPath);
3449
+ const binaryExists = existsSync18(binaryPath);
3396
3450
  const binaryMtime = binaryExists ? statSync4(binaryPath).mtimeMs : 0;
3397
3451
  if (!binaryExists || sourceMtime > binaryMtime) {
3398
3452
  if (binaryExists) {
3399
- rmSync4(binaryPath, { force: true });
3400
- rmSync4(`${binaryPath}.build-manifest.json`, { force: true });
3453
+ rmSync5(binaryPath, { force: true });
3454
+ rmSync5(`${binaryPath}.build-manifest.json`, { force: true });
3401
3455
  }
3402
- mkdirSync6(dirname10(binaryPath), { recursive: true });
3456
+ mkdirSync7(dirname10(binaryPath), { recursive: true });
3403
3457
  await buildRuntimeBinary({
3404
3458
  sourcePath: `packages/runtime/src/control-plane/validators/${category}/${check}.ts`,
3405
3459
  outputPath: binaryPath,
@@ -3408,7 +3462,7 @@ async function ensureValidatorBinary(projectRoot, checkId, runtimeContext) {
3408
3462
  env: runtimeProvisioningEnv()
3409
3463
  });
3410
3464
  }
3411
- return existsSync17(binaryPath) ? binaryPath : null;
3465
+ return existsSync18(binaryPath) ? binaryPath : null;
3412
3466
  }
3413
3467
 
3414
3468
  // packages/runtime/src/control-plane/native/validator.ts
@@ -3445,20 +3499,20 @@ async function readTaskSourceValidation(projectRoot, taskId) {
3445
3499
  function resolveValidationPaths(projectRoot, taskId, runtimeContext) {
3446
3500
  if (runtimeContext) {
3447
3501
  return {
3448
- taskLogDir: resolve21(runtimeContext.logsDir, taskId),
3449
- artifactDir: resolve21(runtimeContext.workspaceDir, "artifacts", taskId)
3502
+ taskLogDir: resolve22(runtimeContext.logsDir, taskId),
3503
+ artifactDir: resolve22(runtimeContext.workspaceDir, "artifacts", taskId)
3450
3504
  };
3451
3505
  }
3452
3506
  const paths = resolveHarnessPaths(projectRoot);
3453
3507
  return {
3454
- taskLogDir: resolve21(paths.logsDir, taskId),
3455
- artifactDir: resolve21(paths.artifactsDir, taskId)
3508
+ taskLogDir: resolve22(paths.logsDir, taskId),
3509
+ artifactDir: resolve22(paths.artifactsDir, taskId)
3456
3510
  };
3457
3511
  }
3458
3512
  async function runValidatorBinary(projectRoot, taskId, checkId, runtimeContext) {
3459
3513
  const binaryName = checkId.replace(":", "-");
3460
3514
  const binaryPath = await ensureValidatorBinary(projectRoot, checkId, runtimeContext) ?? resolveValidatorBinaryPath(projectRoot, binaryName, runtimeContext);
3461
- if (!existsSync18(binaryPath)) {
3515
+ if (!existsSync19(binaryPath)) {
3462
3516
  return {
3463
3517
  result: {
3464
3518
  id: checkId,
@@ -3469,7 +3523,7 @@ async function runValidatorBinary(projectRoot, taskId, checkId, runtimeContext)
3469
3523
  };
3470
3524
  }
3471
3525
  const validatorCwd = runtimeContext?.workspaceDir || resolveMonorepoRoot(projectRoot);
3472
- const runtimeShellPath = runtimeContext ? resolve21(runtimeContext.binDir, "rig-shell") : "";
3526
+ const runtimeShellPath = runtimeContext ? resolve22(runtimeContext.binDir, "rig-shell") : "";
3473
3527
  const monorepoMainRoot = runtimeContext?.monorepoMainRoot || process.env.MONOREPO_MAIN_ROOT?.trim() || resolveMonorepoRoot(projectRoot);
3474
3528
  const validatorEnv = {
3475
3529
  PROJECT_RIG_ROOT: runtimeContext?.hostProjectRoot || projectRoot,
@@ -3484,7 +3538,7 @@ async function runValidatorBinary(projectRoot, taskId, checkId, runtimeContext)
3484
3538
  validatorEnv.RIG_LOGS_DIR = runtimeContext.logsDir;
3485
3539
  validatorEnv.RIG_RUNTIME_BIN_DIR = runtimeContext.binDir;
3486
3540
  }
3487
- const { exitCode, stdout, stderr } = await runCaptureAsync(runtimeShellPath && existsSync18(runtimeShellPath) ? [runtimeShellPath, "run-binary", binaryPath] : [binaryPath], validatorCwd, validatorEnv);
3541
+ const { exitCode, stdout, stderr } = await runCaptureAsync(runtimeShellPath && existsSync19(runtimeShellPath) ? [runtimeShellPath, "run-binary", binaryPath] : [binaryPath], validatorCwd, validatorEnv);
3488
3542
  try {
3489
3543
  const result = JSON.parse(stdout.trim());
3490
3544
  return { result, exitCode };
@@ -3524,8 +3578,8 @@ async function validateTask(projectRoot, taskId, runtimeContext, registry, optio
3524
3578
  const configuredValidation = stringArray(taskConfig[taskId]?.validation);
3525
3579
  const commands = resolvedContext?.validation?.length ? resolvedContext.validation : configuredValidation.length > 0 ? configuredValidation : sourceValidation.validation;
3526
3580
  const { taskLogDir, artifactDir } = resolveValidationPaths(projectRoot, taskId, resolvedContext);
3527
- mkdirSync7(taskLogDir, { recursive: true });
3528
- mkdirSync7(artifactDir, { recursive: true });
3581
+ mkdirSync8(taskLogDir, { recursive: true });
3582
+ mkdirSync8(artifactDir, { recursive: true });
3529
3583
  if (commands.length === 0) {
3530
3584
  const skipped = {
3531
3585
  status: "skipped",
@@ -3534,7 +3588,7 @@ async function validateTask(projectRoot, taskId, runtimeContext, registry, optio
3534
3588
  failed: 0,
3535
3589
  categories: []
3536
3590
  };
3537
- writeFileSync7(resolve21(artifactDir, "validation-summary.json"), `${JSON.stringify(skipped, null, 2)}
3591
+ writeFileSync8(resolve22(artifactDir, "validation-summary.json"), `${JSON.stringify(skipped, null, 2)}
3538
3592
  `, "utf-8");
3539
3593
  return skipped;
3540
3594
  }
@@ -3569,18 +3623,18 @@ async function validateTask(projectRoot, taskId, runtimeContext, registry, optio
3569
3623
  exit_code: 2,
3570
3624
  duration_seconds: 0
3571
3625
  });
3572
- const logFile2 = resolve21(taskLogDir, `invalid-entry-validation.log`);
3573
- mkdirSync7(taskLogDir, { recursive: true });
3574
- writeFileSync7(logFile2, `=== ${nowIso()} :: ${cmd} ===
3626
+ const logFile2 = resolve22(taskLogDir, `invalid-entry-validation.log`);
3627
+ mkdirSync8(taskLogDir, { recursive: true });
3628
+ writeFileSync8(logFile2, `=== ${nowIso()} :: ${cmd} ===
3575
3629
  Invalid validation entry: not a check-ID. All entries must use format "category:check-name".
3576
3630
  `, "utf-8");
3577
3631
  continue;
3578
3632
  }
3579
3633
  const { result, exitCode } = await dispatchValidator(cmd, effectiveRegistry, validatorCtx, (id) => runValidatorBinary(projectRoot, taskId, id, resolvedContext));
3580
3634
  const durationSeconds = Math.max(0, Math.round((Date.now() - startedAt) / 1000));
3581
- const logFile = resolve21(taskLogDir, `${cmd.replace(":", "-")}-validation.log`);
3582
- mkdirSync7(taskLogDir, { recursive: true });
3583
- writeFileSync7(logFile, `=== ${nowIso()} :: ${cmd} ===
3635
+ const logFile = resolve22(taskLogDir, `${cmd.replace(":", "-")}-validation.log`);
3636
+ mkdirSync8(taskLogDir, { recursive: true });
3637
+ writeFileSync8(logFile, `=== ${nowIso()} :: ${cmd} ===
3584
3638
  ${JSON.stringify(result, null, 2)}
3585
3639
  `, "utf-8");
3586
3640
  if (result.passed) {
@@ -3602,15 +3656,15 @@ ${JSON.stringify(result, null, 2)}
3602
3656
  failed,
3603
3657
  categories
3604
3658
  };
3605
- mkdirSync7(artifactDir, { recursive: true });
3606
- writeFileSync7(resolve21(artifactDir, "validation-summary.json"), `${JSON.stringify(summary, null, 2)}
3659
+ mkdirSync8(artifactDir, { recursive: true });
3660
+ writeFileSync8(resolve22(artifactDir, "validation-summary.json"), `${JSON.stringify(summary, null, 2)}
3607
3661
  `, "utf-8");
3608
3662
  return summary;
3609
3663
  }
3610
3664
 
3611
3665
  // packages/runtime/src/control-plane/native/verifier.ts
3612
- import { existsSync as existsSync19, mkdirSync as mkdirSync8, writeFileSync as writeFileSync8 } from "fs";
3613
- import { resolve as resolve22 } from "path";
3666
+ import { existsSync as existsSync20, mkdirSync as mkdirSync9, writeFileSync as writeFileSync9 } from "fs";
3667
+ import { resolve as resolve23 } from "path";
3614
3668
 
3615
3669
  // packages/runtime/src/control-plane/native/pr-review-gate.ts
3616
3670
  function parseJsonObject(value) {
@@ -4861,11 +4915,11 @@ async function verifyTask(options) {
4861
4915
  const taskId = options.taskId;
4862
4916
  const normalizedTaskId = lookupTask(options.projectRoot, taskId);
4863
4917
  const artifactDir = artifactDirForId(options.projectRoot, taskId);
4864
- mkdirSync8(artifactDir, { recursive: true });
4865
- const validationSummaryPath = resolve22(artifactDir, "validation-summary.json");
4866
- const reviewFeedbackPath = resolve22(artifactDir, "review-feedback.md");
4867
- const reviewStatePath = resolve22(artifactDir, "review-state.json");
4868
- const greptileRawPath = resolve22(artifactDir, "review-greptile-raw.json");
4918
+ mkdirSync9(artifactDir, { recursive: true });
4919
+ const validationSummaryPath = resolve23(artifactDir, "validation-summary.json");
4920
+ const reviewFeedbackPath = resolve23(artifactDir, "review-feedback.md");
4921
+ const reviewStatePath = resolve23(artifactDir, "review-state.json");
4922
+ const greptileRawPath = resolve23(artifactDir, "review-greptile-raw.json");
4869
4923
  const prStates = readPrMetadata(options.projectRoot, taskId);
4870
4924
  const prState = prStates[0] || null;
4871
4925
  const localReasons = [];
@@ -4877,7 +4931,7 @@ async function verifyTask(options) {
4877
4931
  if (!normalizedTaskId && !await hasConfiguredSourceTask(options.projectRoot, taskId)) {
4878
4932
  localReasons.push(`[Task Config] Unknown task id '${taskId}' in task-config or configured task source.`);
4879
4933
  }
4880
- if (!existsSync19(validationSummaryPath)) {
4934
+ if (!existsSync20(validationSummaryPath)) {
4881
4935
  localReasons.push(`[Artifact Quality] validation-summary.json not found at ${validationSummaryPath}.`);
4882
4936
  } else {
4883
4937
  const summary = await parseValidationSummary(validationSummaryPath);
@@ -4886,13 +4940,13 @@ async function verifyTask(options) {
4886
4940
  }
4887
4941
  }
4888
4942
  for (const file of ["task-result.json", "decision-log.md", "next-actions.md", "changed-files.txt"]) {
4889
- const requiredPath = resolve22(artifactDir, file);
4890
- if (!existsSync19(requiredPath)) {
4943
+ const requiredPath = resolve23(artifactDir, file);
4944
+ if (!existsSync20(requiredPath)) {
4891
4945
  localReasons.push(`[Artifact Quality] Missing required artifact file: ${requiredPath}`);
4892
4946
  }
4893
4947
  }
4894
- const taskResultPath = resolve22(artifactDir, "task-result.json");
4895
- if (existsSync19(taskResultPath)) {
4948
+ const taskResultPath = resolve23(artifactDir, "task-result.json");
4949
+ if (existsSync20(taskResultPath)) {
4896
4950
  const taskResult = await readJsonFile2(taskResultPath);
4897
4951
  const artifactStatus = typeof taskResult?.status === "string" ? taskResult.status.trim().toLowerCase() : "";
4898
4952
  if (artifactStatus === "partial") {
@@ -4905,8 +4959,8 @@ async function verifyTask(options) {
4905
4959
  localReasons.push("[Artifact Quality] task-result.json next actions indicate remaining implementation scope.");
4906
4960
  }
4907
4961
  }
4908
- const nextActionsPath = resolve22(artifactDir, "next-actions.md");
4909
- if (existsSync19(nextActionsPath)) {
4962
+ const nextActionsPath = resolve23(artifactDir, "next-actions.md");
4963
+ if (existsSync20(nextActionsPath)) {
4910
4964
  const nextActionsContent = await Bun.file(nextActionsPath).text();
4911
4965
  if (nextActionsContent.includes("TODO: Replace this scaffold") || nextActionsContent.includes("bd-<downstream-task-id>")) {
4912
4966
  localReasons.push("[Artifact Quality] next-actions.md still contains scaffold placeholder text. Replace with real recommendations.");
@@ -4919,12 +4973,6 @@ async function verifyTask(options) {
4919
4973
  if (sourceCloseoutIssueId) {
4920
4974
  localReasons.push(...evaluateGithubSourceIssuePrCloseout(options.projectRoot, prStates, sourceCloseoutIssueId));
4921
4975
  }
4922
- const pluginResults = await options.plugins.runValidators(taskId);
4923
- for (const result of pluginResults) {
4924
- if (!result.passed) {
4925
- localReasons.push(`[Plugin Validator] ${result.id}: ${result.summary}`);
4926
- }
4927
- }
4928
4976
  const reviewMode = await loadReviewMode(paths.reviewProfilePath, process.env.AI_REVIEW_MODE || "advisory");
4929
4977
  const reviewProvider = await loadReviewProvider(paths.reviewProfilePath, process.env.AI_REVIEW_PROVIDER || "greptile");
4930
4978
  if (!options.skipAiReview && localReasons.length === 0 && reviewProvider === "greptile" && reviewMode !== "off") {
@@ -4943,7 +4991,7 @@ async function verifyTask(options) {
4943
4991
  aiReasons.push(`[AI Review] Required mode needs a completed Greptile approval; current verdict is ${ai.verdict}.`);
4944
4992
  }
4945
4993
  if (persistArtifacts && ai.rawResponse) {
4946
- writeFileSync8(greptileRawPath, `${ai.rawResponse}
4994
+ writeFileSync9(greptileRawPath, `${ai.rawResponse}
4947
4995
  `, "utf-8");
4948
4996
  }
4949
4997
  } else if (!options.skipAiReview && reviewMode === "off") {
@@ -5282,7 +5330,7 @@ function isAcceptedValidationSummary(summary) {
5282
5330
  return summary.status === "skipped" && summary.total === 0 && summary.failed === 0;
5283
5331
  }
5284
5332
  async function loadReviewMode(reviewProfilePath, fallback) {
5285
- const parsed = existsSync19(reviewProfilePath) ? await readJsonFile2(reviewProfilePath) : null;
5333
+ const parsed = existsSync20(reviewProfilePath) ? await readJsonFile2(reviewProfilePath) : null;
5286
5334
  const mode = parsed?.mode;
5287
5335
  if (mode === "off" || mode === "advisory" || mode === "required") {
5288
5336
  return mode;
@@ -5293,7 +5341,7 @@ async function loadReviewMode(reviewProfilePath, fallback) {
5293
5341
  return "advisory";
5294
5342
  }
5295
5343
  async function loadReviewProvider(reviewProfilePath, fallback) {
5296
- const parsed = existsSync19(reviewProfilePath) ? await readJsonFile2(reviewProfilePath) : null;
5344
+ const parsed = existsSync20(reviewProfilePath) ? await readJsonFile2(reviewProfilePath) : null;
5297
5345
  const provider = parsed?.provider;
5298
5346
  if (typeof provider === "string" && provider.trim().length > 0) {
5299
5347
  return provider;
@@ -5452,7 +5500,7 @@ function writeFeedbackFile(options) {
5452
5500
  if (options.aiRawFeedback) {
5453
5501
  lines.push("## Raw Reviewer Feedback", "", "```text", options.aiRawFeedback, "```", "");
5454
5502
  }
5455
- writeFileSync8(options.output, `${lines.join(`
5503
+ writeFileSync9(options.output, `${lines.join(`
5456
5504
  `)}
5457
5505
  `, "utf-8");
5458
5506
  }
@@ -5469,7 +5517,7 @@ function writeReviewStateFile(options) {
5469
5517
  ai_warnings: options.aiWarnings,
5470
5518
  updated_at: nowIso()
5471
5519
  };
5472
- writeFileSync8(options.output, `${JSON.stringify(payload, null, 2)}
5520
+ writeFileSync9(options.output, `${JSON.stringify(payload, null, 2)}
5473
5521
  `, "utf-8");
5474
5522
  }
5475
5523
  async function runGreptileReviewForPr(options) {
@@ -6256,7 +6304,7 @@ function filterActionableGithubGreptileThreads(threads) {
6256
6304
  }
6257
6305
  function resolvePrRepoRoot(projectRoot, prState) {
6258
6306
  const runtimeWorkspace = process.env.RIG_TASK_WORKSPACE?.trim();
6259
- if (prState.target === "monorepo" && runtimeWorkspace && existsSync19(resolve22(runtimeWorkspace, ".git"))) {
6307
+ if (prState.target === "monorepo" && runtimeWorkspace && existsSync20(resolve23(runtimeWorkspace, ".git"))) {
6260
6308
  return runtimeWorkspace;
6261
6309
  }
6262
6310
  const paths = resolveHarnessPaths(projectRoot);
@@ -6628,16 +6676,16 @@ async function taskDeps(projectRoot, taskId) {
6628
6676
  for (const dep of deps) {
6629
6677
  const artifactDir = artifactDirForId(projectRoot, dep);
6630
6678
  console.log(`=== ${dep} ===`);
6631
- if (!existsSync20(artifactDir)) {
6679
+ if (!existsSync21(artifactDir)) {
6632
6680
  console.log(` (no artifacts yet)
6633
6681
  `);
6634
6682
  continue;
6635
6683
  }
6636
- printArtifactSection(resolve23(artifactDir, "decision-log.md"), "--- Decisions ---");
6637
- printArtifactSection(resolve23(artifactDir, "next-actions.md"), "--- Next Actions (for you) ---");
6638
- const changedFiles = resolve23(artifactDir, "changed-files.txt");
6639
- if (existsSync20(changedFiles)) {
6640
- const lines = readFileSync10(changedFiles, "utf-8").split(/\r?\n/).filter(Boolean);
6684
+ printArtifactSection(resolve24(artifactDir, "decision-log.md"), "--- Decisions ---");
6685
+ printArtifactSection(resolve24(artifactDir, "next-actions.md"), "--- Next Actions (for you) ---");
6686
+ const changedFiles = resolve24(artifactDir, "changed-files.txt");
6687
+ if (existsSync21(changedFiles)) {
6688
+ const lines = readFileSync11(changedFiles, "utf-8").split(/\r?\n/).filter(Boolean);
6641
6689
  console.log(`--- Changed Files (${lines.length}) ---`);
6642
6690
  for (const line of lines) {
6643
6691
  console.log(line);
@@ -6682,12 +6730,12 @@ function taskRecord(projectRoot, type, text, taskId) {
6682
6730
  throw new Error("No active task.");
6683
6731
  }
6684
6732
  const paths = resolveHarnessPaths(projectRoot);
6685
- mkdirSync9(paths.stateDir, { recursive: true });
6733
+ mkdirSync10(paths.stateDir, { recursive: true });
6686
6734
  if (type === "decision") {
6687
- const artifactDir = resolve23(paths.artifactsDir, activeTask);
6688
- mkdirSync9(artifactDir, { recursive: true });
6735
+ const artifactDir = resolve24(paths.artifactsDir, activeTask);
6736
+ mkdirSync10(artifactDir, { recursive: true });
6689
6737
  const timestamp = nowIso();
6690
- appendFileSync(resolve23(artifactDir, "decision-log.md"), `
6738
+ appendFileSync(resolve24(artifactDir, "decision-log.md"), `
6691
6739
  ### ${timestamp}
6692
6740
 
6693
6741
  ${text}
@@ -6697,14 +6745,14 @@ ${text}
6697
6745
  return;
6698
6746
  }
6699
6747
  const failedPath = paths.failedApproachesPath;
6700
- if (!existsSync20(failedPath)) {
6701
- writeFileSync9(failedPath, `# Failed Approaches Log
6748
+ if (!existsSync21(failedPath)) {
6749
+ writeFileSync10(failedPath, `# Failed Approaches Log
6702
6750
 
6703
6751
  This file records approaches that did not work.
6704
6752
 
6705
6753
  `, "utf-8");
6706
6754
  }
6707
- const content = readFileSync10(failedPath, "utf-8");
6755
+ const content = readFileSync11(failedPath, "utf-8");
6708
6756
  const attempts = (content.match(new RegExp(`^## ${escapeRegExp(activeTask)}\\b`, "gm")) || []).length + 1;
6709
6757
  appendFileSync(failedPath, `
6710
6758
  ## ${activeTask} - Attempt ${attempts} (${nowIso()})
@@ -6721,40 +6769,40 @@ function taskArtifacts(projectRoot, taskId) {
6721
6769
  throw new Error("No active task.");
6722
6770
  }
6723
6771
  const paths = resolveHarnessPaths(projectRoot);
6724
- const artifactDir = resolve23(paths.artifactsDir, activeTask);
6725
- mkdirSync9(artifactDir, { recursive: true });
6772
+ const artifactDir = resolve24(paths.artifactsDir, activeTask);
6773
+ mkdirSync10(artifactDir, { recursive: true });
6726
6774
  const changed = changedFilesForTask(projectRoot, activeTask, true);
6727
- writeFileSync9(resolve23(artifactDir, "changed-files.txt"), `${changed.join(`
6775
+ writeFileSync10(resolve24(artifactDir, "changed-files.txt"), `${changed.join(`
6728
6776
  `)}
6729
6777
  `, "utf-8");
6730
6778
  console.log(`changed-files.txt: ${changed.length} files`);
6731
- const taskResultPath = resolve23(artifactDir, "task-result.json");
6732
- if (!existsSync20(taskResultPath)) {
6779
+ const taskResultPath = resolve24(artifactDir, "task-result.json");
6780
+ if (!existsSync21(taskResultPath)) {
6733
6781
  const template = {
6734
6782
  task_id: activeTask,
6735
6783
  status: "completed",
6736
6784
  summary: "TODO: Write a one-line summary of what you did",
6737
6785
  completed_at: nowIso()
6738
6786
  };
6739
- writeFileSync9(taskResultPath, `${JSON.stringify(template, null, 2)}
6787
+ writeFileSync10(taskResultPath, `${JSON.stringify(template, null, 2)}
6740
6788
  `, "utf-8");
6741
6789
  console.log("task-result.json: created (update the summary!)");
6742
6790
  } else {
6743
6791
  console.log("task-result.json: already exists");
6744
6792
  }
6745
- const decisionLogPath = resolve23(artifactDir, "decision-log.md");
6746
- if (!existsSync20(decisionLogPath)) {
6793
+ const decisionLogPath = resolve24(artifactDir, "decision-log.md");
6794
+ if (!existsSync21(decisionLogPath)) {
6747
6795
  const content = `# Decision Log: ${activeTask}
6748
6796
 
6749
6797
  Record key decisions here using: rig-agent record decision "..."
6750
6798
  `;
6751
- writeFileSync9(decisionLogPath, content, "utf-8");
6799
+ writeFileSync10(decisionLogPath, content, "utf-8");
6752
6800
  console.log("decision-log.md: created (record your decisions!)");
6753
6801
  } else {
6754
6802
  console.log("decision-log.md: already exists");
6755
6803
  }
6756
- const nextActionsPath = resolve23(artifactDir, "next-actions.md");
6757
- if (!existsSync20(nextActionsPath)) {
6804
+ const nextActionsPath = resolve24(artifactDir, "next-actions.md");
6805
+ if (!existsSync21(nextActionsPath)) {
6758
6806
  const content = [
6759
6807
  `# Next Actions: ${activeTask}`,
6760
6808
  "",
@@ -6771,13 +6819,13 @@ Record key decisions here using: rig-agent record decision "..."
6771
6819
  ""
6772
6820
  ].join(`
6773
6821
  `);
6774
- writeFileSync9(nextActionsPath, content, "utf-8");
6822
+ writeFileSync10(nextActionsPath, content, "utf-8");
6775
6823
  console.log("next-actions.md: created (add recommendations for downstream tasks!)");
6776
6824
  } else {
6777
6825
  console.log("next-actions.md: already exists");
6778
6826
  }
6779
- const validationSummaryPath = resolve23(artifactDir, "validation-summary.json");
6780
- if (existsSync20(validationSummaryPath)) {
6827
+ const validationSummaryPath = resolve24(artifactDir, "validation-summary.json");
6828
+ if (existsSync21(validationSummaryPath)) {
6781
6829
  console.log("validation-summary.json: already exists");
6782
6830
  } else {
6783
6831
  console.log("validation-summary.json: not yet created (run: rig-agent validate)");
@@ -6820,12 +6868,12 @@ async function taskValidate(projectRoot, taskId, validatorRegistry) {
6820
6868
  console.log(`Validation passed: ${summary.passed}/${summary.total}`);
6821
6869
  return true;
6822
6870
  }
6823
- async function taskVerify(projectRoot, plugins, taskId) {
6871
+ async function taskVerify(projectRoot, taskId) {
6824
6872
  const activeTask = taskId || currentTaskId(projectRoot);
6825
6873
  if (!activeTask) {
6826
6874
  throw new Error("No active task.");
6827
6875
  }
6828
- const outcome = await verifyTask({ projectRoot, taskId: activeTask, plugins });
6876
+ const outcome = await verifyTask({ projectRoot, taskId: activeTask });
6829
6877
  if (!outcome.approved) {
6830
6878
  console.log("REJECT:");
6831
6879
  for (const reason of outcome.localReasons) {
@@ -6868,7 +6916,7 @@ function collectTaskChangedFiles(projectRoot, taskId, includeCommitted) {
6868
6916
  [projectRoot, ""],
6869
6917
  [monorepoRepoRoot, ""]
6870
6918
  ]) {
6871
- if (!existsSync20(resolve23(repo, ".git"))) {
6919
+ if (!existsSync21(resolve24(repo, ".git"))) {
6872
6920
  continue;
6873
6921
  }
6874
6922
  if (includeCommitted && repo === monorepoRepoRoot) {
@@ -6906,8 +6954,8 @@ function filterTaskChangedFiles(projectRoot, taskId, files, scoped) {
6906
6954
  }
6907
6955
  function resolveTaskMonorepoRoot(projectRoot) {
6908
6956
  const runtimeWorkspace = loadRuntimeContextFromEnv()?.workspaceDir || process.env.RIG_TASK_WORKSPACE?.trim();
6909
- if (runtimeWorkspace && existsSync20(resolve23(runtimeWorkspace, ".git"))) {
6910
- return resolve23(runtimeWorkspace);
6957
+ if (runtimeWorkspace && existsSync21(resolve24(runtimeWorkspace, ".git"))) {
6958
+ return resolve24(runtimeWorkspace);
6911
6959
  }
6912
6960
  return resolveHarnessPaths(projectRoot).monorepoRoot;
6913
6961
  }
@@ -6935,7 +6983,7 @@ function resolveRuntimeInitialHeadCommit(projectRoot, repo) {
6935
6983
  const runtimeContext = loadRuntimeContextFromEnv();
6936
6984
  if (runtimeContext?.initialHeadCommits?.monorepo?.trim()) {
6937
6985
  const monorepoRoot = resolveTaskMonorepoRoot(projectRoot);
6938
- if (resolve23(monorepoRoot) === resolve23(repo)) {
6986
+ if (resolve24(monorepoRoot) === resolve24(repo)) {
6939
6987
  return runtimeContext.initialHeadCommits.monorepo.trim();
6940
6988
  }
6941
6989
  }
@@ -6945,7 +6993,7 @@ function resolveMonorepoBaseCommit(projectRoot, repo) {
6945
6993
  const runtimeContext = loadRuntimeContextFromEnv();
6946
6994
  if (runtimeContext?.monorepoBaseCommit?.trim()) {
6947
6995
  const monorepoRoot = resolveTaskMonorepoRoot(projectRoot);
6948
- if (resolve23(monorepoRoot) === resolve23(repo)) {
6996
+ if (resolve24(monorepoRoot) === resolve24(repo)) {
6949
6997
  return runtimeContext.monorepoBaseCommit.trim();
6950
6998
  }
6951
6999
  }
@@ -6979,7 +7027,7 @@ function resolveRuntimeDirtyBaseline(projectRoot, repo) {
6979
7027
  return new Set;
6980
7028
  }
6981
7029
  const monorepoRoot = resolveTaskMonorepoRoot(projectRoot);
6982
- const selected = resolve23(repo) === resolve23(monorepoRoot) ? dirtyFiles.monorepo : resolve23(repo) === resolve23(projectRoot) ? dirtyFiles.project : undefined;
7030
+ const selected = resolve24(repo) === resolve24(monorepoRoot) ? dirtyFiles.monorepo : resolve24(repo) === resolve24(projectRoot) ? dirtyFiles.project : undefined;
6983
7031
  return new Set((selected || []).map((file) => normalizeChangedFilePath(file)).filter(Boolean));
6984
7032
  }
6985
7033
  function normalizeChangedFilePath(file) {
@@ -7079,12 +7127,12 @@ function printIndented(text) {
7079
7127
  }
7080
7128
  }
7081
7129
  function readLocalBeadsTasks(projectRoot) {
7082
- const issuesPath = resolve23(resolveMonorepoRoot2(projectRoot), ".beads/issues.jsonl");
7083
- if (!existsSync20(issuesPath)) {
7130
+ const issuesPath = resolve24(resolveMonorepoRoot2(projectRoot), ".beads/issues.jsonl");
7131
+ if (!existsSync21(issuesPath)) {
7084
7132
  return [];
7085
7133
  }
7086
7134
  const tasks = [];
7087
- for (const line of readFileSync10(issuesPath, "utf-8").split(/\r?\n/)) {
7135
+ for (const line of readFileSync11(issuesPath, "utf-8").split(/\r?\n/)) {
7088
7136
  const trimmed = line.trim();
7089
7137
  if (!trimmed) {
7090
7138
  continue;
@@ -7197,11 +7245,11 @@ function taskDependencies(projectRoot, taskId, tracker) {
7197
7245
  return [...ids].sort();
7198
7246
  }
7199
7247
  function printArtifactSection(path, header) {
7200
- if (!existsSync20(path)) {
7248
+ if (!existsSync21(path)) {
7201
7249
  return;
7202
7250
  }
7203
7251
  console.log(header);
7204
- process.stdout.write(readFileSync10(path, "utf-8"));
7252
+ process.stdout.write(readFileSync11(path, "utf-8"));
7205
7253
  console.log("");
7206
7254
  }
7207
7255
  function escapeRegExp(value) {
@@ -7241,8 +7289,8 @@ function isRuntimeGatewayGhPath(candidate) {
7241
7289
  }
7242
7290
  function resolveOptionalMonorepoRoot(projectRoot) {
7243
7291
  const runtimeWorkspace = process.env.RIG_TASK_WORKSPACE?.trim();
7244
- if (runtimeWorkspace && existsSync21(resolve24(runtimeWorkspace, ".git"))) {
7245
- return resolve24(runtimeWorkspace);
7292
+ if (runtimeWorkspace && existsSync22(resolve25(runtimeWorkspace, ".git"))) {
7293
+ return resolve25(runtimeWorkspace);
7246
7294
  }
7247
7295
  try {
7248
7296
  return resolveMonorepoRoot2(projectRoot);
@@ -7267,7 +7315,7 @@ function resolveGitBinary(projectRoot) {
7267
7315
  if (!candidate || isRuntimeGatewayGitPath(candidate)) {
7268
7316
  continue;
7269
7317
  }
7270
- if (existsSync21(candidate)) {
7318
+ if (existsSync22(candidate)) {
7271
7319
  return candidate;
7272
7320
  }
7273
7321
  }
@@ -7327,11 +7375,11 @@ function gitPreflight(projectRoot, taskId, strict) {
7327
7375
  const expected = resolvedTask ? `rig/${resolveTaskBranchId(projectRoot, resolvedTask)}` : "";
7328
7376
  console.log("=== Git Flow Preflight ===");
7329
7377
  let issues = 0;
7330
- if (!existsSync21(resolve24(projectRoot, ".git"))) {
7378
+ if (!existsSync22(resolve25(projectRoot, ".git"))) {
7331
7379
  console.log(`ERROR: project root is not a git repo (${projectRoot})`);
7332
7380
  issues += 1;
7333
7381
  }
7334
- if (monorepoRoot && existsSync21(resolve24(monorepoRoot, ".git"))) {
7382
+ if (monorepoRoot && existsSync22(resolve25(monorepoRoot, ".git"))) {
7335
7383
  const monoBranch = branchName(projectRoot, monorepoRoot);
7336
7384
  if (expected && monoBranch !== expected) {
7337
7385
  console.log(`WARN: monorepo branch is ${monoBranch}, expected ${expected} for task ${resolvedTask}`);
@@ -7365,7 +7413,7 @@ function gitSyncBranch(projectRoot, taskId, targetRepo = "monorepo") {
7365
7413
  }
7366
7414
  const repoRoot = targetRepo === "monorepo" ? resolveOptionalMonorepoRoot(projectRoot) || resolveMonorepoRoot2(projectRoot) : projectRoot;
7367
7415
  const repoLabel = targetRepo === "monorepo" ? "Monorepo" : "Project";
7368
- if (!existsSync21(resolve24(repoRoot, ".git"))) {
7416
+ if (!existsSync22(resolve25(repoRoot, ".git"))) {
7369
7417
  throw new Error(`${repoLabel} repo not found at ${repoRoot}`);
7370
7418
  }
7371
7419
  const branchId = resolveTaskBranchId(projectRoot, resolvedTask);
@@ -7409,8 +7457,8 @@ function gitCommit(options) {
7409
7457
  function gitSnapshot(projectRoot, taskId, outputPath) {
7410
7458
  const monorepoRoot = resolveOptionalMonorepoRoot(projectRoot);
7411
7459
  const resolvedTask = taskId || safeCurrentTaskId(projectRoot);
7412
- const output = outputPath || (resolvedTask ? resolveArtifactSnapshot(projectRoot, resolvedTask) : resolve24(resolve24(projectRoot, ".rig", "state"), "git-state.txt"));
7413
- mkdirSync10(dirname11(output), { recursive: true });
7460
+ const output = outputPath || (resolvedTask ? resolveArtifactSnapshot(projectRoot, resolvedTask) : resolve25(resolve25(projectRoot, ".rig", "state"), "git-state.txt"));
7461
+ mkdirSync11(dirname11(output), { recursive: true });
7414
7462
  const lines = ["# Git Snapshot", `timestamp: ${nowIso()}`];
7415
7463
  if (resolvedTask) {
7416
7464
  lines.push(`task: ${resolvedTask}`);
@@ -7420,7 +7468,7 @@ function gitSnapshot(projectRoot, taskId, outputPath) {
7420
7468
  if (monorepoRoot && monorepoRoot !== projectRoot) {
7421
7469
  lines.push(...snapshotRepo(projectRoot, "monorepo", monorepoRoot));
7422
7470
  }
7423
- writeFileSync10(output, `${lines.join(`
7471
+ writeFileSync11(output, `${lines.join(`
7424
7472
  `)}
7425
7473
  `, "utf-8");
7426
7474
  return output;
@@ -7444,7 +7492,7 @@ function gitOpenPr(options) {
7444
7492
  } else if (taskId) {
7445
7493
  gitSyncBranch(options.projectRoot, taskId, "project");
7446
7494
  }
7447
- if (!existsSync21(resolve24(repoRoot, ".git"))) {
7495
+ if (!existsSync22(resolve25(repoRoot, ".git"))) {
7448
7496
  throw new Error(`Repository not available for open-pr target ${target}: ${repoRoot}`);
7449
7497
  }
7450
7498
  const branch = branchName(options.projectRoot, repoRoot);
@@ -7657,12 +7705,12 @@ function assertPrHasNoGitConflicts(prState, repoLabel, baseRef) {
7657
7705
  }
7658
7706
  function writePrMetadata(projectRoot, taskId, result) {
7659
7707
  const dir = artifactDirForId(projectRoot, taskId);
7660
- mkdirSync10(dir, { recursive: true });
7661
- const path = resolve24(dir, "pr-state.json");
7708
+ mkdirSync11(dir, { recursive: true });
7709
+ const path = resolve25(dir, "pr-state.json");
7662
7710
  let prs = {};
7663
- if (existsSync21(path)) {
7711
+ if (existsSync22(path)) {
7664
7712
  try {
7665
- const parsed = JSON.parse(readFileSync11(path, "utf-8"));
7713
+ const parsed = JSON.parse(readFileSync12(path, "utf-8"));
7666
7714
  if (parsed && typeof parsed === "object" && parsed.prs && typeof parsed.prs === "object") {
7667
7715
  prs = parsed.prs;
7668
7716
  }
@@ -7678,16 +7726,16 @@ function writePrMetadata(projectRoot, taskId, result) {
7678
7726
  ...primary || {},
7679
7727
  updated_at: nowIso()
7680
7728
  };
7681
- writeFileSync10(path, `${JSON.stringify(artifact, null, 2)}
7729
+ writeFileSync11(path, `${JSON.stringify(artifact, null, 2)}
7682
7730
  `, "utf-8");
7683
7731
  }
7684
7732
  function readPrMetadata(projectRoot, taskId) {
7685
- const path = resolve24(artifactDirForId(projectRoot, taskId), "pr-state.json");
7686
- if (!existsSync21(path)) {
7733
+ const path = resolve25(artifactDirForId(projectRoot, taskId), "pr-state.json");
7734
+ if (!existsSync22(path)) {
7687
7735
  return [];
7688
7736
  }
7689
7737
  try {
7690
- const parsed = JSON.parse(readFileSync11(path, "utf-8"));
7738
+ const parsed = JSON.parse(readFileSync12(path, "utf-8"));
7691
7739
  if (!parsed || typeof parsed !== "object") {
7692
7740
  return [];
7693
7741
  }
@@ -7700,8 +7748,8 @@ function readPrMetadata(projectRoot, taskId) {
7700
7748
  }
7701
7749
  }
7702
7750
  function resolveArtifactSnapshot(projectRoot, taskId) {
7703
- const artifactDir = resolve24(resolveHarnessPaths(projectRoot).artifactsDir, taskId);
7704
- return resolve24(artifactDir, "git-state.txt");
7751
+ const artifactDir = resolve25(resolveHarnessPaths(projectRoot).artifactsDir, taskId);
7752
+ return resolve25(artifactDir, "git-state.txt");
7705
7753
  }
7706
7754
  function isGitOpenPrResult(value) {
7707
7755
  if (!value || typeof value !== "object" || Array.isArray(value)) {
@@ -7760,14 +7808,14 @@ function resolveGithubCliBinary(projectRoot) {
7760
7808
  }
7761
7809
  const explicitPathEntries = (process.env.PATH || "").split(":").map((entry) => entry.trim()).filter(Boolean);
7762
7810
  for (const entry of explicitPathEntries) {
7763
- candidates.add(resolve24(entry, "gh"));
7811
+ candidates.add(resolve25(entry, "gh"));
7764
7812
  }
7765
7813
  const bunResolved = Bun.which("gh");
7766
7814
  if (bunResolved) {
7767
7815
  candidates.add(bunResolved);
7768
7816
  }
7769
7817
  for (const candidate of candidates) {
7770
- if (candidate && existsSync21(candidate) && !isRuntimeGatewayGhPath(candidate)) {
7818
+ if (candidate && existsSync22(candidate) && !isRuntimeGatewayGhPath(candidate)) {
7771
7819
  return candidate;
7772
7820
  }
7773
7821
  }
@@ -7797,7 +7845,7 @@ function resolveRepoNameWithOwner(projectRoot, repoRoot) {
7797
7845
  return resolveGithubRepoNameWithOwnerFromGitRoot(projectRoot, repoRoot, repoRoot, visited);
7798
7846
  }
7799
7847
  function resolveGithubRepoNameWithOwnerFromGitRoot(projectRoot, gitRoot, cwd, visited) {
7800
- const normalizedGitRoot = resolve24(gitRoot);
7848
+ const normalizedGitRoot = resolve25(gitRoot);
7801
7849
  if (visited.has(normalizedGitRoot)) {
7802
7850
  return "";
7803
7851
  }
@@ -7869,7 +7917,7 @@ function resolveNetworkRemoteName(projectRoot, repoRoot, repoNameWithOwner) {
7869
7917
  return remotes.includes("origin") ? "origin" : remotes[0];
7870
7918
  }
7871
7919
  function gitQuery(projectRoot, gitRoot, cwd, ...args) {
7872
- const gitArgs = existsSync21(resolve24(gitRoot, ".git")) ? gitCmd(projectRoot, gitRoot, ...args) : [resolveGitBinary(projectRoot), "--git-dir", gitRoot, ...args];
7920
+ const gitArgs = existsSync22(resolve25(gitRoot, ".git")) ? gitCmd(projectRoot, gitRoot, ...args) : [resolveGitBinary(projectRoot), "--git-dir", gitRoot, ...args];
7873
7921
  return runCapture2(gitArgs, cwd, projectRoot);
7874
7922
  }
7875
7923
  function resolveLocalGitRemoteRoot(remoteUrl, gitRoot) {
@@ -7887,9 +7935,9 @@ function resolveLocalGitRemoteRoot(remoteUrl, gitRoot) {
7887
7935
  } else if (/^[a-z][a-z0-9+.-]*:\/\//i.test(normalized) || /^[^@]+@[^:]+:.+$/.test(normalized)) {
7888
7936
  return "";
7889
7937
  } else if (!isAbsolute2(normalized)) {
7890
- candidate = resolve24(gitRoot, normalized);
7938
+ candidate = resolve25(gitRoot, normalized);
7891
7939
  }
7892
- return existsSync21(candidate) ? candidate : "";
7940
+ return existsSync22(candidate) ? candidate : "";
7893
7941
  }
7894
7942
  function normalizeGithubRepoNameWithOwner(value) {
7895
7943
  const normalized = value.trim();
@@ -8016,7 +8064,7 @@ function inferReviewerFromChangedFiles(projectRoot, repoRoot, baseRef, branchRef
8016
8064
  return best;
8017
8065
  }
8018
8066
  function snapshotRepo(projectRoot, label, repo) {
8019
- if (!existsSync21(resolve24(repo, ".git"))) {
8067
+ if (!existsSync22(resolve25(repo, ".git"))) {
8020
8068
  return [`## ${label}`, `repo: ${repo}`, "status: unavailable", ""];
8021
8069
  }
8022
8070
  const status = runCapture2(gitCmd(projectRoot, repo, "status", "--short"), projectRoot).stdout.trim();
@@ -8039,7 +8087,7 @@ function snapshotRepo(projectRoot, label, repo) {
8039
8087
  ];
8040
8088
  }
8041
8089
  function commitRepo(projectRoot, repo, label, message, allowEmpty, scoped, files, changedFilesManifest) {
8042
- if (!existsSync21(resolve24(repo, ".git"))) {
8090
+ if (!existsSync22(resolve25(repo, ".git"))) {
8043
8091
  console.log(`Skipping ${label}: repo not available (${repo})`);
8044
8092
  return;
8045
8093
  }
@@ -8071,18 +8119,18 @@ function commitRepo(projectRoot, repo, label, message, allowEmpty, scoped, files
8071
8119
  console.log(`Committed ${label}: ${message}`);
8072
8120
  }
8073
8121
  function readChangedFilesManifest(projectRoot, taskId) {
8074
- const manifestPath = resolve24(artifactDirForId(projectRoot, taskId), "changed-files.txt");
8075
- if (!existsSync21(manifestPath)) {
8122
+ const manifestPath = resolve25(artifactDirForId(projectRoot, taskId), "changed-files.txt");
8123
+ if (!existsSync22(manifestPath)) {
8076
8124
  return [];
8077
8125
  }
8078
- const files = readFileSync11(manifestPath, "utf-8").split(/\r?\n/).map((line) => normalizeChangedFilePath2(line)).filter(Boolean);
8126
+ const files = readFileSync12(manifestPath, "utf-8").split(/\r?\n/).map((line) => normalizeChangedFilePath2(line)).filter(Boolean);
8079
8127
  return [...new Set(files)];
8080
8128
  }
8081
8129
  function refreshChangedFilesManifest(projectRoot, taskId) {
8082
- const manifestPath = resolve24(artifactDirForId(projectRoot, taskId), "changed-files.txt");
8083
- mkdirSync10(dirname11(manifestPath), { recursive: true });
8130
+ const manifestPath = resolve25(artifactDirForId(projectRoot, taskId), "changed-files.txt");
8131
+ mkdirSync11(dirname11(manifestPath), { recursive: true });
8084
8132
  const changedFiles = changedFilesForTask(projectRoot, taskId, true);
8085
- writeFileSync10(manifestPath, `${changedFiles.join(`
8133
+ writeFileSync11(manifestPath, `${changedFiles.join(`
8086
8134
  `)}
8087
8135
  `, "utf-8");
8088
8136
  return manifestPath;
@@ -8195,7 +8243,7 @@ function repoHasPathChange(projectRoot, repoRoot, relativePath) {
8195
8243
  return result.exitCode === 0 && result.stdout.trim().length > 0;
8196
8244
  }
8197
8245
  function stageExcludePathspecs(repoRoot) {
8198
- const patterns = existsSync21(resolve24(repoRoot, ".rig", "task-config.json")) ? [...TASK_RUNTIME_STAGE_EXCLUDES, ...GENERATED_STAGE_EXCLUDES] : [".rig/**", ...GENERATED_STAGE_EXCLUDES];
8246
+ const patterns = existsSync22(resolve25(repoRoot, ".rig", "task-config.json")) ? [...TASK_RUNTIME_STAGE_EXCLUDES, ...GENERATED_STAGE_EXCLUDES] : [".rig/**", ...GENERATED_STAGE_EXCLUDES];
8199
8247
  return patterns.map((pattern) => `:(glob,exclude)${pattern}`);
8200
8248
  }
8201
8249
  function pathResolvesBeyondSymlink(repoRoot, relativePath) {
@@ -8205,7 +8253,7 @@ function pathResolvesBeyondSymlink(repoRoot, relativePath) {
8205
8253
  }
8206
8254
  let current = repoRoot;
8207
8255
  for (let index = 0;index < parts.length - 1; index += 1) {
8208
- current = resolve24(current, parts[index]);
8256
+ current = resolve25(current, parts[index]);
8209
8257
  try {
8210
8258
  if (lstatSync(current).isSymbolicLink()) {
8211
8259
  return true;
@@ -8217,7 +8265,7 @@ function pathResolvesBeyondSymlink(repoRoot, relativePath) {
8217
8265
  return false;
8218
8266
  }
8219
8267
  function printRepoStatus(projectRoot, label, repo, expectedBranch) {
8220
- if (!existsSync21(resolve24(repo, ".git"))) {
8268
+ if (!existsSync22(resolve25(repo, ".git"))) {
8221
8269
  console.log(`${label}: unavailable (${repo})`);
8222
8270
  return;
8223
8271
  }
@@ -8253,7 +8301,7 @@ function resolveTaskBranchId(projectRoot, taskId) {
8253
8301
  }
8254
8302
  } catch {}
8255
8303
  const artifactDir = artifactDirForId(projectRoot, taskId);
8256
- if (existsSync21(artifactDir)) {
8304
+ if (existsSync22(artifactDir)) {
8257
8305
  return taskId;
8258
8306
  }
8259
8307
  throw new Error(`Unknown task id: ${taskId}`);
@@ -8289,11 +8337,11 @@ function runCapture2(command, cwd, projectRoot = cwd) {
8289
8337
  }
8290
8338
  function runtimeGitEnv(projectRoot) {
8291
8339
  const { ctx, runtimeRoot } = resolveRuntimeMetadata(projectRoot);
8292
- const runtimeHome = runtimeRoot ? resolve24(runtimeRoot, "home") : "";
8293
- const runtimeTmp = runtimeRoot ? resolve24(runtimeRoot, "tmp") : "";
8294
- const runtimeCache = runtimeRoot ? resolve24(runtimeRoot, "cache") : "";
8295
- const runtimeKnownHosts = runtimeHome ? resolve24(runtimeHome, ".ssh", "known_hosts") : "";
8296
- const runtimeKey = runtimeHome ? resolve24(runtimeHome, ".ssh", "rig-agent-key") : "";
8340
+ const runtimeHome = runtimeRoot ? resolve25(runtimeRoot, "home") : "";
8341
+ const runtimeTmp = runtimeRoot ? resolve25(runtimeRoot, "tmp") : "";
8342
+ const runtimeCache = runtimeRoot ? resolve25(runtimeRoot, "cache") : "";
8343
+ const runtimeKnownHosts = runtimeHome ? resolve25(runtimeHome, ".ssh", "known_hosts") : "";
8344
+ const runtimeKey = runtimeHome ? resolve25(runtimeHome, ".ssh", "rig-agent-key") : "";
8297
8345
  const env = {};
8298
8346
  if (ctx?.workspaceDir) {
8299
8347
  env.PROJECT_RIG_ROOT = projectRoot;
@@ -8306,14 +8354,14 @@ function runtimeGitEnv(projectRoot) {
8306
8354
  if (runtimeRoot) {
8307
8355
  env.RIG_RUNTIME_HOME = runtimeRoot;
8308
8356
  }
8309
- if (runtimeHome && existsSync21(runtimeHome)) {
8357
+ if (runtimeHome && existsSync22(runtimeHome)) {
8310
8358
  env.HOME = runtimeHome;
8311
8359
  env.OPENSSL_CONF = ensureRuntimeOpenSslConfig(runtimeHome);
8312
8360
  }
8313
- if (runtimeTmp && existsSync21(runtimeTmp)) {
8361
+ if (runtimeTmp && existsSync22(runtimeTmp)) {
8314
8362
  env.TMPDIR = runtimeTmp;
8315
8363
  }
8316
- if (runtimeCache && existsSync21(runtimeCache)) {
8364
+ if (runtimeCache && existsSync22(runtimeCache)) {
8317
8365
  env.XDG_CACHE_HOME = runtimeCache;
8318
8366
  }
8319
8367
  const workspaceSecrets = loadDotEnvSecrets(ctx?.workspaceDir || projectRoot, process.env);
@@ -8357,14 +8405,14 @@ function runtimeGitEnv(projectRoot) {
8357
8405
  env.GH_TOKEN = env.GH_TOKEN || gitHubToken;
8358
8406
  applyGitHubCredentialHelperEnv(env);
8359
8407
  }
8360
- if (runtimeKnownHosts && existsSync21(runtimeKnownHosts)) {
8408
+ if (runtimeKnownHosts && existsSync22(runtimeKnownHosts)) {
8361
8409
  const sshParts = [
8362
8410
  "ssh",
8363
8411
  `-o UserKnownHostsFile="${runtimeKnownHosts}"`,
8364
8412
  "-o StrictHostKeyChecking=yes",
8365
8413
  "-F /dev/null"
8366
8414
  ];
8367
- if (runtimeKey && existsSync21(runtimeKey)) {
8415
+ if (runtimeKey && existsSync22(runtimeKey)) {
8368
8416
  sshParts.splice(1, 0, `-i "${runtimeKey}"`, "-o IdentitiesOnly=yes");
8369
8417
  }
8370
8418
  env.GIT_SSH_COMMAND = sshParts.join(" ");
@@ -8385,12 +8433,12 @@ function loadPersistedRuntimeSecrets(runtimeRoot) {
8385
8433
  if (!runtimeRoot) {
8386
8434
  return {};
8387
8435
  }
8388
- const path = resolve24(runtimeRoot, "runtime-secrets.json");
8389
- if (!existsSync21(path)) {
8436
+ const path = resolve25(runtimeRoot, "runtime-secrets.json");
8437
+ if (!existsSync22(path)) {
8390
8438
  return {};
8391
8439
  }
8392
8440
  try {
8393
- const parsed = JSON.parse(readFileSync11(path, "utf-8"));
8441
+ const parsed = JSON.parse(readFileSync12(path, "utf-8"));
8394
8442
  const entries = Object.entries(parsed).filter((entry) => typeof entry[1] === "string");
8395
8443
  return Object.fromEntries(entries);
8396
8444
  } catch {
@@ -8398,13 +8446,13 @@ function loadPersistedRuntimeSecrets(runtimeRoot) {
8398
8446
  }
8399
8447
  }
8400
8448
  function ensureRuntimeOpenSslConfig(runtimeHome) {
8401
- const sslDir = resolve24(runtimeHome, ".ssl");
8402
- const sslConfig = resolve24(sslDir, "openssl.cnf");
8403
- if (!existsSync21(sslDir)) {
8404
- mkdirSync10(sslDir, { recursive: true });
8449
+ const sslDir = resolve25(runtimeHome, ".ssl");
8450
+ const sslConfig = resolve25(sslDir, "openssl.cnf");
8451
+ if (!existsSync22(sslDir)) {
8452
+ mkdirSync11(sslDir, { recursive: true });
8405
8453
  }
8406
- if (!existsSync21(sslConfig)) {
8407
- writeFileSync10(sslConfig, `# Rig runtime OpenSSL config placeholder
8454
+ if (!existsSync22(sslConfig)) {
8455
+ writeFileSync11(sslConfig, `# Rig runtime OpenSSL config placeholder
8408
8456
  `);
8409
8457
  }
8410
8458
  return sslConfig;
@@ -8422,11 +8470,11 @@ function resolveRuntimeMetadata(projectRoot) {
8422
8470
  if (contextFile) {
8423
8471
  return {
8424
8472
  ctx,
8425
- runtimeRoot: dirname11(resolve24(contextFile))
8473
+ runtimeRoot: dirname11(resolve25(contextFile))
8426
8474
  };
8427
8475
  }
8428
8476
  const inferredContextFile = findRuntimeContextFile2(projectRoot);
8429
- if (existsSync21(inferredContextFile)) {
8477
+ if (existsSync22(inferredContextFile)) {
8430
8478
  try {
8431
8479
  ctx = loadRuntimeContext(inferredContextFile);
8432
8480
  } catch {}
@@ -8438,10 +8486,10 @@ function resolveRuntimeMetadata(projectRoot) {
8438
8486
  return { ctx, runtimeRoot: "" };
8439
8487
  }
8440
8488
  function findRuntimeContextFile2(startPath) {
8441
- let current = resolve24(startPath);
8489
+ let current = resolve25(startPath);
8442
8490
  while (true) {
8443
- const candidate = resolve24(current, "runtime-context.json");
8444
- if (existsSync21(candidate)) {
8491
+ const candidate = resolve25(current, "runtime-context.json");
8492
+ if (existsSync22(candidate)) {
8445
8493
  return candidate;
8446
8494
  }
8447
8495
  const parent = dirname11(current);
@@ -8453,7 +8501,7 @@ function findRuntimeContextFile2(startPath) {
8453
8501
  }
8454
8502
 
8455
8503
  // packages/runtime/src/control-plane/native/profile-ops.ts
8456
- import { existsSync as existsSync22, mkdirSync as mkdirSync11, writeFileSync as writeFileSync11 } from "fs";
8504
+ import { existsSync as existsSync23, mkdirSync as mkdirSync12, writeFileSync as writeFileSync12 } from "fs";
8457
8505
  var DEFAULTS = {
8458
8506
  model: parseEnvOrDefault(process.env.DEFAULT_AGENT_MODEL, ["claude", "gpt-codex", "pi"], "pi"),
8459
8507
  runtime: parseEnvOrDefault(process.env.DEFAULT_AGENT_RUNTIME, ["claude-code", "codex-app-server", "pi"], "pi"),
@@ -8468,7 +8516,7 @@ function parseEnvOrDefault(value, allowed, fallback) {
8468
8516
  return allowed.includes(value) ? value : fallback;
8469
8517
  }
8470
8518
  async function readProfileFile(path) {
8471
- if (!existsSync22(path)) {
8519
+ if (!existsSync23(path)) {
8472
8520
  return null;
8473
8521
  }
8474
8522
  try {
@@ -8521,14 +8569,14 @@ async function setProfile(projectRoot, options) {
8521
8569
  plugin = model === "gpt-codex" ? "codex" : model === "pi" ? "pi" : "claude";
8522
8570
  }
8523
8571
  const paths = resolveHarnessPaths(projectRoot);
8524
- mkdirSync11(paths.stateDir, { recursive: true });
8572
+ mkdirSync12(paths.stateDir, { recursive: true });
8525
8573
  const next = {
8526
8574
  model,
8527
8575
  runtime,
8528
8576
  agent_plugin: plugin,
8529
8577
  updated_at: new Date().toISOString()
8530
8578
  };
8531
- writeFileSync11(paths.agentProfilePath, `${JSON.stringify(next, null, 2)}
8579
+ writeFileSync12(paths.agentProfilePath, `${JSON.stringify(next, null, 2)}
8532
8580
  `, "utf-8");
8533
8581
  await showProfile(projectRoot, false);
8534
8582
  }
@@ -8564,13 +8612,13 @@ async function setReviewProfile(projectRoot, mode, provider) {
8564
8612
  throw new Error(`Invalid provider: ${resolvedProvider}. Supported: greptile.`);
8565
8613
  }
8566
8614
  const paths = resolveHarnessPaths(projectRoot);
8567
- mkdirSync11(paths.stateDir, { recursive: true });
8615
+ mkdirSync12(paths.stateDir, { recursive: true });
8568
8616
  const next = {
8569
8617
  mode,
8570
8618
  provider: resolvedProvider,
8571
8619
  updated_at: new Date().toISOString()
8572
8620
  };
8573
- writeFileSync11(paths.reviewProfilePath, `${JSON.stringify(next, null, 2)}
8621
+ writeFileSync12(paths.reviewProfilePath, `${JSON.stringify(next, null, 2)}
8574
8622
  `, "utf-8");
8575
8623
  await showReviewProfile(projectRoot);
8576
8624
  }
@@ -8608,44 +8656,44 @@ async function loadReviewProfile(path) {
8608
8656
  }
8609
8657
 
8610
8658
  // packages/runtime/src/control-plane/native/repo-ops.ts
8611
- import { existsSync as existsSync26, mkdirSync as mkdirSync15, readFileSync as readFileSync13, readdirSync as readdirSync5, rmSync as rmSync6, writeFileSync as writeFileSync13 } from "fs";
8612
- import { basename as basename8, dirname as dirname13, resolve as resolve28 } from "path";
8659
+ import { existsSync as existsSync27, mkdirSync as mkdirSync16, readFileSync as readFileSync14, readdirSync as readdirSync6, rmSync as rmSync7, writeFileSync as writeFileSync14 } from "fs";
8660
+ import { basename as basename8, dirname as dirname13, resolve as resolve29 } from "path";
8613
8661
  // packages/runtime/src/control-plane/repos/mirror/bootstrap.ts
8614
- import { existsSync as existsSync24, mkdirSync as mkdirSync13, realpathSync as realpathSync2 } from "fs";
8615
- import { resolve as resolve26 } from "path";
8662
+ import { existsSync as existsSync25, mkdirSync as mkdirSync14, realpathSync as realpathSync2 } from "fs";
8663
+ import { resolve as resolve27 } from "path";
8616
8664
 
8617
8665
  // packages/runtime/src/control-plane/authority-files.ts
8618
- import { existsSync as existsSync23, mkdirSync as mkdirSync12, readFileSync as readFileSync12, writeFileSync as writeFileSync12, appendFileSync as appendFileSync2, copyFileSync as copyFileSync3, statSync as statSync5, readdirSync as readdirSync4, chmodSync as chmodSync3 } from "fs";
8619
- import { dirname as dirname12, join as join4, relative, resolve as resolve25 } from "path";
8666
+ import { existsSync as existsSync24, mkdirSync as mkdirSync13, readFileSync as readFileSync13, writeFileSync as writeFileSync13, appendFileSync as appendFileSync2, copyFileSync as copyFileSync3, statSync as statSync5, readdirSync as readdirSync5, chmodSync as chmodSync3 } from "fs";
8667
+ import { dirname as dirname12, join as join4, relative, resolve as resolve26 } from "path";
8620
8668
  import { parse as parseToml, stringify as stringifyToml } from "smol-toml";
8621
8669
  function resolveAuthorityProjectStateDir(projectRoot) {
8622
8670
  const explicit = process.env.RIG_STATE_DIR?.trim();
8623
8671
  if (explicit) {
8624
- return resolve25(explicit);
8672
+ return resolve26(explicit);
8625
8673
  }
8626
- return resolve25(resolve25(projectRoot), ".rig", "state");
8674
+ return resolve26(resolve26(projectRoot), ".rig", "state");
8627
8675
  }
8628
8676
  function readJsonAtPath(path, fallback) {
8629
- if (!existsSync23(path)) {
8677
+ if (!existsSync24(path)) {
8630
8678
  return fallback;
8631
8679
  }
8632
8680
  try {
8633
- return JSON.parse(readFileSync12(path, "utf-8"));
8681
+ return JSON.parse(readFileSync13(path, "utf-8"));
8634
8682
  } catch {
8635
8683
  return fallback;
8636
8684
  }
8637
8685
  }
8638
8686
  function writeJsonAtPath(path, value) {
8639
- mkdirSync12(dirname12(path), { recursive: true });
8640
- writeFileSync12(path, `${JSON.stringify(value, null, 2)}
8687
+ mkdirSync13(dirname12(path), { recursive: true });
8688
+ writeFileSync13(path, `${JSON.stringify(value, null, 2)}
8641
8689
  `, "utf8");
8642
8690
  return path;
8643
8691
  }
8644
8692
  function readAuthorityProjectStateJson(projectRoot, relativePath, fallback) {
8645
- return readJsonAtPath(resolve25(resolveAuthorityProjectStateDir(projectRoot), relativePath), fallback);
8693
+ return readJsonAtPath(resolve26(resolveAuthorityProjectStateDir(projectRoot), relativePath), fallback);
8646
8694
  }
8647
8695
  function writeAuthorityProjectStateJson(projectRoot, relativePath, value) {
8648
- return writeJsonAtPath(resolve25(resolveAuthorityProjectStateDir(projectRoot), relativePath), value);
8696
+ return writeJsonAtPath(resolve26(resolveAuthorityProjectStateDir(projectRoot), relativePath), value);
8649
8697
  }
8650
8698
 
8651
8699
  // packages/runtime/src/control-plane/repos/mirror/state.ts
@@ -8705,7 +8753,7 @@ function sameExistingPath(left, right) {
8705
8753
  try {
8706
8754
  return realpathSync2(left) === realpathSync2(right);
8707
8755
  } catch {
8708
- return resolve26(left) === resolve26(right);
8756
+ return resolve27(left) === resolve27(right);
8709
8757
  }
8710
8758
  }
8711
8759
  function repoLooksUsable(repoRoot, projectRoot) {
@@ -8741,7 +8789,7 @@ function resolveMirrorRemoteUrl(layout) {
8741
8789
  }
8742
8790
  }
8743
8791
  }
8744
- if (existsSync24(resolve26(layout.checkoutRoot, ".git")) && checkoutLooksUsable(layout)) {
8792
+ if (existsSync25(resolve27(layout.checkoutRoot, ".git")) && checkoutLooksUsable(layout)) {
8745
8793
  const checkoutOrigin = runGit(["git", "-C", layout.checkoutRoot, "remote", "get-url", "origin"], layout.projectRoot);
8746
8794
  if (checkoutOrigin.exitCode === 0) {
8747
8795
  const currentOrigin = checkoutOrigin.stdout.trim();
@@ -8754,9 +8802,9 @@ function resolveMirrorRemoteUrl(layout) {
8754
8802
  }
8755
8803
  function ensureManagedRepoMirror(projectRoot, repoId) {
8756
8804
  const layout = resolveManagedRepoLayout(projectRoot, repoId);
8757
- mkdirSync13(layout.metadataRoot, { recursive: true });
8805
+ mkdirSync14(layout.metadataRoot, { recursive: true });
8758
8806
  const remoteUrl = resolveMirrorRemoteUrl(layout);
8759
- if (!existsSync24(resolve26(layout.mirrorRoot, "HEAD"))) {
8807
+ if (!existsSync25(resolve27(layout.mirrorRoot, "HEAD"))) {
8760
8808
  ensureGitSuccess(runGit(["git", "init", "--bare", layout.mirrorRoot], layout.projectRoot), ["git", "init", "--bare", layout.mirrorRoot]);
8761
8809
  }
8762
8810
  const getOrigin = runGit(["git", "--git-dir", layout.mirrorRoot, "remote", "get-url", "origin"], layout.projectRoot);
@@ -8776,8 +8824,8 @@ function ensureManagedRepoMirror(projectRoot, repoId) {
8776
8824
  return layout;
8777
8825
  }
8778
8826
  // packages/runtime/src/control-plane/repos/mirror/refresh.ts
8779
- import { existsSync as existsSync25, mkdirSync as mkdirSync14, realpathSync as realpathSync3, rmSync as rmSync5 } from "fs";
8780
- import { resolve as resolve27 } from "path";
8827
+ import { existsSync as existsSync26, mkdirSync as mkdirSync15, realpathSync as realpathSync3, rmSync as rmSync6 } from "fs";
8828
+ import { resolve as resolve28 } from "path";
8781
8829
  function nowIso3() {
8782
8830
  return new Date().toISOString();
8783
8831
  }
@@ -8804,7 +8852,7 @@ function sameExistingPath2(left, right) {
8804
8852
  try {
8805
8853
  return realpathSync3(left) === realpathSync3(right);
8806
8854
  } catch {
8807
- return resolve27(left) === resolve27(right);
8855
+ return resolve28(left) === resolve28(right);
8808
8856
  }
8809
8857
  }
8810
8858
  function ensureMirrorHead(layout) {
@@ -8850,12 +8898,12 @@ function checkoutLooksUsable2(layout) {
8850
8898
  return probe.exitCode === 0 && sameExistingPath2(probe.stdout.trim(), layout.checkoutRoot);
8851
8899
  }
8852
8900
  function ensureCheckoutFromMirror(layout) {
8853
- mkdirSync14(resolve27(layout.checkoutRoot, ".."), { recursive: true });
8854
- const gitPath = resolve27(layout.checkoutRoot, ".git");
8855
- if (existsSync25(layout.checkoutRoot) && (!existsSync25(gitPath) || !checkoutLooksUsable2(layout))) {
8856
- rmSync5(layout.checkoutRoot, { recursive: true, force: true });
8901
+ mkdirSync15(resolve28(layout.checkoutRoot, ".."), { recursive: true });
8902
+ const gitPath = resolve28(layout.checkoutRoot, ".git");
8903
+ if (existsSync26(layout.checkoutRoot) && (!existsSync26(gitPath) || !checkoutLooksUsable2(layout))) {
8904
+ rmSync6(layout.checkoutRoot, { recursive: true, force: true });
8857
8905
  }
8858
- if (!existsSync25(gitPath)) {
8906
+ if (!existsSync26(gitPath)) {
8859
8907
  ensureGitSuccess2(runGit2(["git", "clone", layout.mirrorRoot, layout.checkoutRoot], layout.projectRoot), ["git", "clone", layout.mirrorRoot, layout.checkoutRoot]);
8860
8908
  }
8861
8909
  const getOrigin = runGit2(["git", "-C", layout.checkoutRoot, "remote", "get-url", "origin"], layout.projectRoot);
@@ -8956,7 +9004,7 @@ function repoDiscover(projectRoot, taskId) {
8956
9004
  }
8957
9005
  function repoBaseline(projectRoot, refresh = false) {
8958
9006
  const paths = resolveRepoDiscoveryPaths(projectRoot);
8959
- if (!refresh && existsSync26(paths.baseRepoPinsPath)) {
9007
+ if (!refresh && existsSync27(paths.baseRepoPinsPath)) {
8960
9008
  const baseline = readJsonFile(paths.baseRepoPinsPath, { recorded_at: nowIso(), repos: {} });
8961
9009
  return baseline.repos || {};
8962
9010
  }
@@ -8980,8 +9028,8 @@ function ensureMonorepoReady(projectRoot) {
8980
9028
  }
8981
9029
  function persistBaselinePins(projectRoot, repos) {
8982
9030
  const paths = resolveRepoDiscoveryPaths(projectRoot);
8983
- mkdirSync15(resolve28(paths.baseRepoPinsPath, ".."), { recursive: true });
8984
- writeFileSync13(paths.baseRepoPinsPath, `${JSON.stringify({ recorded_at: nowIso(), repos }, null, 2)}
9031
+ mkdirSync16(resolve29(paths.baseRepoPinsPath, ".."), { recursive: true });
9032
+ writeFileSync14(paths.baseRepoPinsPath, `${JSON.stringify({ recorded_at: nowIso(), repos }, null, 2)}
8985
9033
  `, "utf-8");
8986
9034
  return repos;
8987
9035
  }
@@ -9060,28 +9108,28 @@ function readRepoDiscoveryTaskConfig(projectRoot) {
9060
9108
  function resolveRepoDiscoveryPaths(projectRoot) {
9061
9109
  const monorepoRoot = resolveMonorepoRepoLayout(projectRoot).checkoutRoot;
9062
9110
  const explicitHostProjectRoot = (process.env.RIG_HOST_PROJECT_ROOT || "").trim();
9063
- const normalizedProjectRoot = resolve28(projectRoot);
9111
+ const normalizedProjectRoot = resolve29(projectRoot);
9064
9112
  const hostProjectRoot = explicitHostProjectRoot && shouldUseHostProjectStateRoot(normalizedProjectRoot) ? explicitHostProjectRoot : normalizedProjectRoot;
9065
- const stateDir = resolve28(hostProjectRoot, ".rig", "state");
9113
+ const stateDir = resolve29(hostProjectRoot, ".rig", "state");
9066
9114
  return {
9067
9115
  monorepoRoot,
9068
- taskRepoCommitsPath: resolve28(stateDir, "task-repo-commits.json"),
9069
- baseRepoPinsPath: resolve28(stateDir, "base-repo-pins.json")
9116
+ taskRepoCommitsPath: resolve29(stateDir, "task-repo-commits.json"),
9117
+ baseRepoPinsPath: resolve29(stateDir, "base-repo-pins.json")
9070
9118
  };
9071
9119
  }
9072
9120
  function shouldUseHostProjectStateRoot(projectRoot) {
9073
9121
  const runtimeWorkspace = process.env.RIG_TASK_WORKSPACE?.trim();
9074
- if (runtimeWorkspace && resolve28(runtimeWorkspace) === projectRoot) {
9122
+ if (runtimeWorkspace && resolve29(runtimeWorkspace) === projectRoot) {
9075
9123
  return true;
9076
9124
  }
9077
9125
  return basename8(dirname13(projectRoot)) === ".worktrees";
9078
9126
  }
9079
9127
  function readPinFromArtifact(projectRoot, depTask, repoKey) {
9080
- const snapshot = resolve28(artifactDirForId(projectRoot, depTask), "git-state.txt");
9081
- if (!existsSync26(snapshot)) {
9128
+ const snapshot = resolve29(artifactDirForId(projectRoot, depTask), "git-state.txt");
9129
+ if (!existsSync27(snapshot)) {
9082
9130
  return "";
9083
9131
  }
9084
- const content = readFileSync13(snapshot, "utf-8");
9132
+ const content = readFileSync14(snapshot, "utf-8");
9085
9133
  const chunk = content.split(/\r?\n/);
9086
9134
  let inSection = false;
9087
9135
  for (const line of chunk) {
@@ -9103,12 +9151,12 @@ function repoPath(projectRoot, key) {
9103
9151
  if (managed) {
9104
9152
  return managed.checkoutRoot;
9105
9153
  }
9106
- return key.startsWith("/") ? key : resolve28(projectRoot, key);
9154
+ return key.startsWith("/") ? key : resolve29(projectRoot, key);
9107
9155
  }
9108
9156
  function applyPins(projectRoot, pins) {
9109
9157
  for (const [key, commit] of Object.entries(pins)) {
9110
9158
  const path = repoPath(projectRoot, key);
9111
- if (!existsSync26(resolve28(path, ".git"))) {
9159
+ if (!existsSync27(resolve29(path, ".git"))) {
9112
9160
  throw new Error(`Repo for pin not available: ${key} (${path})`);
9113
9161
  }
9114
9162
  let hasCommit = runGitCapture(["git", "-C", path, "cat-file", "-e", `${commit}^{commit}`], projectRoot).exitCode === 0;
@@ -9137,7 +9185,7 @@ function verifyPins(projectRoot, pins) {
9137
9185
  let ok = true;
9138
9186
  for (const [key, expected] of Object.entries(pins)) {
9139
9187
  const path = repoPath(projectRoot, key);
9140
- if (!existsSync26(resolve28(path, ".git"))) {
9188
+ if (!existsSync27(resolve29(path, ".git"))) {
9141
9189
  console.error(`ERROR: repo missing during pin verification: ${key}`);
9142
9190
  ok = false;
9143
9191
  continue;
@@ -9162,23 +9210,23 @@ function resolveRuntimeGitEnv() {
9162
9210
  GIT_SSH_COMMAND: process.env.GIT_SSH_COMMAND
9163
9211
  };
9164
9212
  }
9165
- const runtimeRoot = process.env.RIG_RUNTIME_HOME?.trim() || (process.env.RIG_RUNTIME_CONTEXT_FILE?.trim() ? resolve28(process.env.RIG_RUNTIME_CONTEXT_FILE, "..") : inferRuntimeRootFromWorkspace(process.cwd()));
9166
- const runtimeHome = runtimeRoot ? resolve28(runtimeRoot, "home") : process.env.HOME?.trim() || "";
9213
+ const runtimeRoot = process.env.RIG_RUNTIME_HOME?.trim() || (process.env.RIG_RUNTIME_CONTEXT_FILE?.trim() ? resolve29(process.env.RIG_RUNTIME_CONTEXT_FILE, "..") : inferRuntimeRootFromWorkspace(process.cwd()));
9214
+ const runtimeHome = runtimeRoot ? resolve29(runtimeRoot, "home") : process.env.HOME?.trim() || "";
9167
9215
  if (!runtimeHome) {
9168
9216
  return;
9169
9217
  }
9170
- const knownHostsPath = resolve28(runtimeHome, ".ssh", "known_hosts");
9171
- if (!existsSync26(knownHostsPath)) {
9218
+ const knownHostsPath = resolve29(runtimeHome, ".ssh", "known_hosts");
9219
+ if (!existsSync27(knownHostsPath)) {
9172
9220
  return { HOME: runtimeHome };
9173
9221
  }
9174
- const agentSshKey = resolve28(runtimeHome, ".ssh", "rig-agent-key");
9222
+ const agentSshKey = resolve29(runtimeHome, ".ssh", "rig-agent-key");
9175
9223
  const sshParts = [
9176
9224
  "ssh",
9177
9225
  `-o UserKnownHostsFile="${knownHostsPath}"`,
9178
9226
  "-o StrictHostKeyChecking=yes",
9179
9227
  "-F /dev/null"
9180
9228
  ];
9181
- if (existsSync26(agentSshKey)) {
9229
+ if (existsSync27(agentSshKey)) {
9182
9230
  sshParts.splice(1, 0, `-i "${agentSshKey}"`, "-o IdentitiesOnly=yes");
9183
9231
  }
9184
9232
  return {
@@ -9188,24 +9236,24 @@ function resolveRuntimeGitEnv() {
9188
9236
  }
9189
9237
  function inferRuntimeRootFromWorkspace(cwd) {
9190
9238
  const contextPath = findRuntimeContextFile3(cwd);
9191
- if (!contextPath || !existsSync26(contextPath)) {
9239
+ if (!contextPath || !existsSync27(contextPath)) {
9192
9240
  return "";
9193
9241
  }
9194
9242
  try {
9195
9243
  loadRuntimeContext(contextPath);
9196
- return resolve28(contextPath, "..");
9244
+ return resolve29(contextPath, "..");
9197
9245
  } catch {
9198
9246
  return "";
9199
9247
  }
9200
9248
  }
9201
9249
  function findRuntimeContextFile3(startPath) {
9202
- let current = resolve28(startPath);
9250
+ let current = resolve29(startPath);
9203
9251
  while (true) {
9204
- const candidate = resolve28(current, "runtime-context.json");
9205
- if (existsSync26(candidate)) {
9252
+ const candidate = resolve29(current, "runtime-context.json");
9253
+ if (existsSync27(candidate)) {
9206
9254
  return candidate;
9207
9255
  }
9208
- const parent = resolve28(current, "..");
9256
+ const parent = resolve29(current, "..");
9209
9257
  if (parent === current) {
9210
9258
  return "";
9211
9259
  }
@@ -9214,12 +9262,12 @@ function findRuntimeContextFile3(startPath) {
9214
9262
  }
9215
9263
 
9216
9264
  // packages/runtime/src/control-plane/memory-sync/cli.ts
9217
- import { existsSync as existsSync27 } from "fs";
9265
+ import { existsSync as existsSync28 } from "fs";
9218
9266
  import { randomUUID } from "crypto";
9219
9267
 
9220
9268
  // packages/runtime/src/control-plane/memory-sync/db.ts
9221
9269
  import { Database } from "bun:sqlite";
9222
- import { mkdirSync as mkdirSync16 } from "fs";
9270
+ import { mkdirSync as mkdirSync17 } from "fs";
9223
9271
  import { dirname as dirname14 } from "path";
9224
9272
 
9225
9273
  // packages/runtime/src/control-plane/memory-sync/types.ts
@@ -9816,7 +9864,7 @@ async function validateEventTargets(executor, event) {
9816
9864
  }
9817
9865
  }
9818
9866
  async function openMemoryDb(dbPath) {
9819
- mkdirSync16(dirname14(dbPath), { recursive: true });
9867
+ mkdirSync17(dirname14(dbPath), { recursive: true });
9820
9868
  const sqlite = new Database(dbPath, { create: true, strict: true });
9821
9869
  const client = createMemoryDbClient(sqlite);
9822
9870
  const db = {
@@ -10235,7 +10283,7 @@ function formatMemoryQueryResults(results) {
10235
10283
  }
10236
10284
 
10237
10285
  // packages/runtime/src/control-plane/memory-sync/read.ts
10238
- import { mkdtempSync, rmSync as rmSync7, writeFileSync as writeFileSync14 } from "fs";
10286
+ import { mkdtempSync, rmSync as rmSync8, writeFileSync as writeFileSync15 } from "fs";
10239
10287
  import { tmpdir as tmpdir5 } from "os";
10240
10288
  import { join as join5 } from "path";
10241
10289
  var CANONICAL_MEMORY_DB_PATH = "rig/memory/project-memory.db";
@@ -10244,7 +10292,7 @@ var DEFAULT_READ_DEPS2 = {
10244
10292
  readBlobBytesAtRef: nativeReadBlobBytesAtRef,
10245
10293
  openMemoryDb,
10246
10294
  makeTempDir: () => mkdtempSync(join5(tmpdir5(), "memory-sync-read-")),
10247
- removeDir: (path) => rmSync7(path, { recursive: true, force: true })
10295
+ removeDir: (path) => rmSync8(path, { recursive: true, force: true })
10248
10296
  };
10249
10297
  function isMissingCanonicalMemoryBlobError(error) {
10250
10298
  const message = error instanceof Error ? error.message : String(error);
@@ -10264,7 +10312,7 @@ async function readCanonicalMemoryDb(projectRoot, deps = {}) {
10264
10312
  try {
10265
10313
  try {
10266
10314
  const bytes = readDeps.readBlobBytesAtRef(repoPath2, baseOid, CANONICAL_MEMORY_DB_PATH);
10267
- writeFileSync14(dbPath, bytes);
10315
+ writeFileSync15(dbPath, bytes);
10268
10316
  } catch (error) {
10269
10317
  if (!isMissingCanonicalMemoryBlobError(error)) {
10270
10318
  throw error;
@@ -10422,7 +10470,7 @@ function requireRuntimeMemoryContext(runtimeContext) {
10422
10470
  }
10423
10471
  async function ensureRuntimeMemoryUsable(runtimeContext) {
10424
10472
  const memory = requireRuntimeMemoryContext(runtimeContext);
10425
- if (!existsSync27(memory.hydratedPath)) {
10473
+ if (!existsSync28(memory.hydratedPath)) {
10426
10474
  throw new Error(`Shared memory database is missing: ${memory.hydratedPath}`);
10427
10475
  }
10428
10476
  const db = await openMemoryDb(memory.hydratedPath);
@@ -10685,7 +10733,7 @@ async function executeMemoryCommand(options, deps = {}) {
10685
10733
  }
10686
10734
 
10687
10735
  // packages/runtime/src/control-plane/native/harness-cli.ts
10688
- async function executeHarnessCommand(projectRoot, plugins, args, eventBus, pluginHostCtx) {
10736
+ async function executeHarnessCommand(projectRoot, args, eventBus, pluginHostCtx) {
10689
10737
  const [command = "help", ...rest] = args;
10690
10738
  switch (command) {
10691
10739
  case "memory": {
@@ -10723,8 +10771,8 @@ async function executeHarnessCommand(projectRoot, plugins, args, eventBus, plugi
10723
10771
  }
10724
10772
  case "completion-verification":
10725
10773
  case "completition-verification": {
10726
- const hookPath = resolve29(projectRoot, ".rig/bin/hooks/completion-verification");
10727
- if (!existsSync28(hookPath)) {
10774
+ const hookPath = resolve30(projectRoot, ".rig/bin/hooks/completion-verification");
10775
+ if (!existsSync29(hookPath)) {
10728
10776
  throw new Error(`completion-verification hook binary not found: ${hookPath}`);
10729
10777
  }
10730
10778
  const proc = Bun.spawn([hookPath], {
@@ -10742,7 +10790,7 @@ async function executeHarnessCommand(projectRoot, plugins, args, eventBus, plugi
10742
10790
  }
10743
10791
  case "verify": {
10744
10792
  const task = rest[0];
10745
- const ok = await taskVerify(projectRoot, plugins, task);
10793
+ const ok = await taskVerify(projectRoot, task);
10746
10794
  if (!ok) {
10747
10795
  throw new Error("Verification rejected.");
10748
10796
  }
@@ -11026,10 +11074,10 @@ function printHelp() {
11026
11074
  }
11027
11075
 
11028
11076
  // packages/runtime/src/control-plane/native/root-resolver.ts
11029
- import { existsSync as existsSync29, readFileSync as readFileSync14 } from "fs";
11030
- import { dirname as dirname15, parse, resolve as resolve30 } from "path";
11077
+ import { existsSync as existsSync30, readFileSync as readFileSync15 } from "fs";
11078
+ import { dirname as dirname15, parse, resolve as resolve31 } from "path";
11031
11079
  function hasProjectMarker(candidate) {
11032
- return existsSync29(resolve30(candidate, RIG_DEFINITION_DIRNAME)) || existsSync29(resolve30(candidate, RIG_STATE_DIRNAME));
11080
+ return existsSync30(resolve31(candidate, RIG_DEFINITION_DIRNAME)) || existsSync30(resolve31(candidate, RIG_STATE_DIRNAME));
11033
11081
  }
11034
11082
  function resolveProjectRoot(options) {
11035
11083
  const cwd = options?.cwd || process.cwd();
@@ -11046,7 +11094,7 @@ function resolveProjectRoot(options) {
11046
11094
  if (configRoot && hasProjectMarker(configRoot)) {
11047
11095
  return configRoot;
11048
11096
  }
11049
- let fileDir = resolve30(fallbackFromDir);
11097
+ let fileDir = resolve31(fallbackFromDir);
11050
11098
  for (let i = 0;i < 5; i += 1) {
11051
11099
  if (hasProjectMarker(fileDir)) {
11052
11100
  return fileDir;
@@ -11056,7 +11104,7 @@ function resolveProjectRoot(options) {
11056
11104
  return cwd;
11057
11105
  }
11058
11106
  function walkUpForRoot(start) {
11059
- let searchDir = resolve30(start);
11107
+ let searchDir = resolve31(start);
11060
11108
  const root = parse(searchDir).root || "/";
11061
11109
  while (searchDir !== root) {
11062
11110
  if (hasProjectMarker(searchDir)) {
@@ -11070,12 +11118,12 @@ function walkUpForRoot(start) {
11070
11118
  return "";
11071
11119
  }
11072
11120
  function readConfiguredRoot() {
11073
- const configPath = resolve30(process.env.HOME || "~", ".config", "project-rig", "root");
11074
- if (!existsSync29(configPath)) {
11121
+ const configPath = resolve31(process.env.HOME || "~", ".config", "project-rig", "root");
11122
+ if (!existsSync30(configPath)) {
11075
11123
  return "";
11076
11124
  }
11077
11125
  try {
11078
- const value = readFileSync14(configPath, "utf-8").split(/\r?\n/)[0]?.trim() || "";
11126
+ const value = readFileSync15(configPath, "utf-8").split(/\r?\n/)[0]?.trim() || "";
11079
11127
  return value;
11080
11128
  } catch {
11081
11129
  return "";
@@ -11085,7 +11133,7 @@ function readConfiguredRoot() {
11085
11133
  // packages/runtime/src/control-plane/runtime/events.ts
11086
11134
  import { appendFile, mkdir } from "fs/promises";
11087
11135
  import { randomUUID as randomUUID2 } from "crypto";
11088
- import { dirname as dirname16, resolve as resolve31 } from "path";
11136
+ import { dirname as dirname16, resolve as resolve32 } from "path";
11089
11137
  async function appendEvent(eventsFile, event) {
11090
11138
  await mkdir(dirname16(eventsFile), { recursive: true });
11091
11139
  await appendFile(eventsFile, `${JSON.stringify(event)}
@@ -11149,7 +11197,7 @@ class GeneralCliEventBus {
11149
11197
  runtimeBuses = new Map;
11150
11198
  constructor(options) {
11151
11199
  this.runId = options.runId || randomUUID2();
11152
- this.eventsFile = options.eventsFile ?? resolve31(options.projectRoot, ".rig", "logs", "control-plane.events.jsonl");
11200
+ this.eventsFile = options.eventsFile ?? resolve32(options.projectRoot, ".rig", "logs", "control-plane.events.jsonl");
11153
11201
  }
11154
11202
  getRunId() {
11155
11203
  return this.runId;
@@ -11184,919 +11232,25 @@ class GeneralCliEventBus {
11184
11232
  }
11185
11233
  }
11186
11234
 
11187
- // packages/runtime/src/control-plane/runtime/plugins.ts
11188
- import { existsSync as existsSync31, readdirSync as readdirSync6 } from "fs";
11189
- import { resolve as resolve33, basename as basename9 } from "path";
11190
-
11191
- // packages/runtime/src/control-plane/runtime/guard.ts
11192
- import { optimizeNextInvocation } from "bun:jsc";
11193
- import { existsSync as existsSync30, readFileSync as readFileSync15, statSync as statSync6 } from "fs";
11194
- import { resolve as resolve32 } from "path";
11195
-
11196
- // packages/runtime/src/control-plane/runtime/guard-types.ts
11197
- var POLICY_VERSION = 1;
11198
-
11199
- // packages/runtime/src/control-plane/runtime/guard.ts
11200
- var DEFAULT_SCOPE = {
11201
- fail_closed: true,
11202
- harness_paths_exempt: true,
11203
- runtime_paths_exempt: true
11204
- };
11205
- var DEFAULT_SANDBOX = {
11206
- mode: "enforce",
11207
- network: true,
11208
- read_deny: [],
11209
- write_allow_from_runtime: true
11210
- };
11211
- var DEFAULT_ISOLATION = {
11212
- default_mode: "worktree",
11213
- repo_symlink_fallback: false,
11214
- strict_provisioning: true,
11215
- fail_closed_on_provision_error: true
11216
- };
11217
- var DEFAULT_COMPLETION = {
11218
- derive_checks_from_scope: true,
11219
- checks: [],
11220
- typescript_config_probe: ["tsconfig.json"],
11221
- eslint_config_probe: [".eslintrc.js", ".eslintrc.json", "eslint.config.js"]
11222
- };
11223
- var DEFAULT_RUNTIME_IMAGE = {
11224
- deps: {
11225
- monorepo_install: false,
11226
- hp_next_install: false
11227
- },
11228
- plugins_require_binaries: true
11229
- };
11230
- var DEFAULT_RUNTIME_SNAPSHOT = {
11231
- enabled: true
11232
- };
11233
- function defaultPolicy() {
11234
- return {
11235
- version: POLICY_VERSION,
11236
- mode: "enforce",
11237
- scope: { ...DEFAULT_SCOPE },
11238
- rules: [],
11239
- sandbox: { ...DEFAULT_SANDBOX },
11240
- isolation: { ...DEFAULT_ISOLATION },
11241
- completion: { ...DEFAULT_COMPLETION },
11242
- runtime_image: {
11243
- deps: { ...DEFAULT_RUNTIME_IMAGE.deps },
11244
- plugins_require_binaries: DEFAULT_RUNTIME_IMAGE.plugins_require_binaries
11245
- },
11246
- runtime_snapshot: { ...DEFAULT_RUNTIME_SNAPSHOT }
11247
- };
11248
- }
11249
- var policyCache = null;
11250
- var policyCachePath = null;
11251
- var seededPolicyConfig = null;
11252
- var compiledRegexCache = new Map;
11253
- function loadPolicy(projectRoot) {
11254
- if (seededPolicyConfig) {
11255
- return seededPolicyConfig;
11256
- }
11257
- const configPath = resolve32(projectRoot, "rig/policy/policy.json");
11258
- if (!existsSync30(configPath)) {
11259
- return defaultPolicy();
11260
- }
11261
- let mtimeMs;
11262
- try {
11263
- mtimeMs = statSync6(configPath).mtimeMs;
11264
- } catch {
11265
- return defaultPolicy();
11266
- }
11267
- if (policyCache && policyCachePath === configPath && policyCache.mtimeMs === mtimeMs) {
11268
- return policyCache.config;
11269
- }
11270
- let parsed;
11271
- try {
11272
- parsed = JSON.parse(readFileSync15(configPath, "utf-8"));
11273
- } catch {
11274
- return defaultPolicy();
11275
- }
11276
- const config = mergeWithDefaults(parsed);
11277
- policyCache = { mtimeMs, config };
11278
- policyCachePath = configPath;
11279
- return config;
11280
- }
11281
- function mergeWithDefaults(parsed) {
11282
- const base = defaultPolicy();
11283
- if (typeof parsed.mode === "string" && isValidMode(parsed.mode)) {
11284
- base.mode = parsed.mode;
11285
- }
11286
- if (parsed.scope && typeof parsed.scope === "object" && !Array.isArray(parsed.scope)) {
11287
- const s = parsed.scope;
11288
- if (typeof s.fail_closed === "boolean")
11289
- base.scope.fail_closed = s.fail_closed;
11290
- if (typeof s.harness_paths_exempt === "boolean")
11291
- base.scope.harness_paths_exempt = s.harness_paths_exempt;
11292
- if (typeof s.runtime_paths_exempt === "boolean")
11293
- base.scope.runtime_paths_exempt = s.runtime_paths_exempt;
11294
- }
11295
- if (Array.isArray(parsed.rules)) {
11296
- base.rules = precompilePolicyRuleRegexes(parsed.rules.filter(isValidRule));
11297
- }
11298
- if (Array.isArray(parsed.deny) && base.rules.length === 0) {
11299
- base.rules = precompilePolicyRuleRegexes(migrateLegacyDeny(parsed.deny));
11300
- }
11301
- if (parsed.sandbox && typeof parsed.sandbox === "object" && !Array.isArray(parsed.sandbox)) {
11302
- const sb = parsed.sandbox;
11303
- if (typeof sb.mode === "string" && isValidMode(sb.mode))
11304
- base.sandbox.mode = sb.mode;
11305
- if (typeof sb.network === "boolean")
11306
- base.sandbox.network = sb.network;
11307
- if (Array.isArray(sb.read_deny))
11308
- base.sandbox.read_deny = sb.read_deny.filter((v) => typeof v === "string");
11309
- if (typeof sb.write_allow_from_runtime === "boolean")
11310
- base.sandbox.write_allow_from_runtime = sb.write_allow_from_runtime;
11311
- }
11312
- if (parsed.isolation && typeof parsed.isolation === "object" && !Array.isArray(parsed.isolation)) {
11313
- const iso = parsed.isolation;
11314
- if (iso.default_mode === "worktree")
11315
- base.isolation.default_mode = iso.default_mode;
11316
- if (typeof iso.repo_symlink_fallback === "boolean")
11317
- base.isolation.repo_symlink_fallback = iso.repo_symlink_fallback;
11318
- if (typeof iso.strict_provisioning === "boolean")
11319
- base.isolation.strict_provisioning = iso.strict_provisioning;
11320
- if (typeof iso.fail_closed_on_provision_error === "boolean")
11321
- base.isolation.fail_closed_on_provision_error = iso.fail_closed_on_provision_error;
11322
- }
11323
- if (parsed.completion && typeof parsed.completion === "object" && !Array.isArray(parsed.completion)) {
11324
- const comp = parsed.completion;
11325
- if (typeof comp.derive_checks_from_scope === "boolean")
11326
- base.completion.derive_checks_from_scope = comp.derive_checks_from_scope;
11327
- if (Array.isArray(comp.checks))
11328
- base.completion.checks = comp.checks.filter((v) => typeof v === "string");
11329
- if (Array.isArray(comp.typescript_config_probe))
11330
- base.completion.typescript_config_probe = comp.typescript_config_probe.filter((v) => typeof v === "string");
11331
- if (Array.isArray(comp.eslint_config_probe))
11332
- base.completion.eslint_config_probe = comp.eslint_config_probe.filter((v) => typeof v === "string");
11333
- }
11334
- if (parsed.runtime_image && typeof parsed.runtime_image === "object" && !Array.isArray(parsed.runtime_image)) {
11335
- const runtimeImage = parsed.runtime_image;
11336
- if (runtimeImage.deps && typeof runtimeImage.deps === "object" && !Array.isArray(runtimeImage.deps)) {
11337
- const deps = runtimeImage.deps;
11338
- if (typeof deps.monorepo_install === "boolean") {
11339
- base.runtime_image.deps.monorepo_install = deps.monorepo_install;
11340
- }
11341
- if (typeof deps.hp_next_install === "boolean") {
11342
- base.runtime_image.deps.hp_next_install = deps.hp_next_install;
11343
- }
11344
- }
11345
- if (typeof runtimeImage.plugins_require_binaries === "boolean") {
11346
- base.runtime_image.plugins_require_binaries = runtimeImage.plugins_require_binaries;
11347
- }
11348
- }
11349
- if (parsed.runtime_snapshot && typeof parsed.runtime_snapshot === "object" && !Array.isArray(parsed.runtime_snapshot)) {
11350
- const runtimeSnapshot = parsed.runtime_snapshot;
11351
- if (typeof runtimeSnapshot.enabled === "boolean") {
11352
- base.runtime_snapshot.enabled = runtimeSnapshot.enabled;
11353
- }
11354
- }
11355
- return base;
11356
- }
11357
- function isValidMode(value) {
11358
- return value === "off" || value === "observe" || value === "enforce";
11359
- }
11360
- function isValidRule(value) {
11361
- if (!value || typeof value !== "object" || Array.isArray(value))
11362
- return false;
11363
- const r = value;
11364
- return typeof r.id === "string" && typeof r.category === "string" && r.match != null && typeof r.match === "object";
11365
- }
11366
- function migrateLegacyDeny(deny) {
11367
- const rules = [];
11368
- for (const entry of deny) {
11369
- if (typeof entry.id !== "string")
11370
- continue;
11371
- const match = {};
11372
- if (typeof entry.pattern === "string")
11373
- match.pattern = entry.pattern;
11374
- if (typeof entry.regex === "string")
11375
- match.regex = entry.regex;
11376
- if (!match.pattern && !match.regex)
11377
- continue;
11378
- rules.push({
11379
- id: entry.id,
11380
- category: "command",
11381
- match,
11382
- action: "block",
11383
- ...typeof entry.description === "string" ? { description: entry.description } : {}
11384
- });
11385
- }
11386
- return rules;
11387
- }
11388
- function precompilePolicyRuleRegexes(rules) {
11389
- return rules.map((rule) => {
11390
- const compiledRegex = rule.match.regex ? compileSafeRegex(rule.match.regex, `rules.${rule.id}.match.regex`, true) : undefined;
11391
- const compiledUnlessRegex = rule.unless?.regex ? compileSafeRegex(rule.unless.regex, `rules.${rule.id}.unless.regex`, true) : undefined;
11392
- return {
11393
- ...rule,
11394
- ...compiledRegex ? { compiledRegex } : {},
11395
- ...compiledUnlessRegex ? { compiledUnlessRegex } : {}
11396
- };
11397
- });
11398
- }
11399
- function getRegexUnsafeReason(pattern) {
11400
- if (pattern.length > 512) {
11401
- return "pattern exceeds max safe length (512 chars)";
11402
- }
11403
- if (/\\[1-9]/.test(pattern)) {
11404
- return "pattern uses backreferences";
11405
- }
11406
- if (/\((?:[^()\\]|\\.)*[+*](?:[^()\\]|\\.)*\)\s*[*+{]/.test(pattern)) {
11407
- return "pattern contains nested quantifiers";
11408
- }
11409
- if (/\((?:[^()\\]|\\.)*\.\\?[+*](?:[^()\\]|\\.)*\)\s*[*+{]/.test(pattern)) {
11410
- return "pattern contains nested broad quantifiers";
11411
- }
11412
- return null;
11413
- }
11414
- function compileSafeRegex(pattern, sourceLabel, logOnFailure) {
11415
- const cached = compiledRegexCache.get(pattern);
11416
- if (cached !== undefined) {
11417
- return cached ?? undefined;
11418
- }
11419
- const unsafeReason = getRegexUnsafeReason(pattern);
11420
- if (unsafeReason) {
11421
- if (logOnFailure) {
11422
- console.warn(`[policy] Skipping unsafe regex in ${sourceLabel}: ${unsafeReason}`);
11423
- }
11424
- compiledRegexCache.set(pattern, null);
11425
- return;
11426
- }
11427
- try {
11428
- const compiled = new RegExp(pattern);
11429
- compiledRegexCache.set(pattern, compiled);
11430
- return compiled;
11431
- } catch (error) {
11432
- if (logOnFailure) {
11433
- const message = error instanceof Error ? error.message : String(error);
11434
- console.warn(`[policy] Skipping invalid regex in ${sourceLabel}: ${message}`);
11435
- }
11436
- compiledRegexCache.set(pattern, null);
11437
- return;
11438
- }
11439
- }
11440
- function matchRule(rule, input) {
11441
- const { match } = rule;
11442
- if (match.pattern && input.includes(match.pattern)) {
11443
- return true;
11444
- }
11445
- if (match.regex) {
11446
- const compiled = rule.compiledRegex || compileSafeRegex(match.regex, `rules.${rule.id}.match.regex`, false);
11447
- if (!compiled) {
11448
- return false;
11449
- }
11450
- try {
11451
- return compiled.test(input);
11452
- } catch {
11453
- return false;
11454
- }
11455
- }
11456
- return false;
11457
- }
11458
- function matchRuleUnless(rule, command, taskId) {
11459
- if (!rule.unless)
11460
- return false;
11461
- if (rule.unless.regex) {
11462
- const compiled = rule.compiledUnlessRegex || compileSafeRegex(rule.unless.regex, `rules.${rule.id}.unless.regex`, false);
11463
- if (!compiled) {
11464
- return false;
11465
- }
11466
- try {
11467
- if (compiled.test(command))
11468
- return true;
11469
- } catch {}
11470
- }
11471
- if (rule.unless.task_in && taskId) {
11472
- if (rule.unless.task_in.includes(taskId))
11473
- return true;
11474
- }
11475
- return false;
11476
- }
11477
- function resolveAction(mode, matched) {
11478
- if (matched.length === 0)
11479
- return "allow";
11480
- if (mode === "off")
11481
- return "allow";
11482
- if (mode === "observe")
11483
- return "warn";
11484
- return "block";
11485
- }
11486
- function resolveAbsolutePath(projectRoot, rawPath) {
11487
- if (rawPath.startsWith("/"))
11488
- return resolve32(rawPath);
11489
- return resolve32(projectRoot, rawPath);
11490
- }
11491
- function isHarnessPath(projectRoot, rawPath) {
11492
- const absPath = resolveAbsolutePath(projectRoot, rawPath);
11493
- const managedRoots = [
11494
- resolve32(projectRoot, "rig"),
11495
- resolve32(projectRoot, ".rig"),
11496
- resolve32(projectRoot, "artifacts")
11497
- ];
11498
- return managedRoots.some((root) => absPath === root || absPath.startsWith(root + "/"));
11499
- }
11500
- function isRuntimePath(projectRoot, rawPath, taskWorkspace) {
11501
- const absPath = resolveAbsolutePath(projectRoot, rawPath);
11502
- if (taskWorkspace) {
11503
- const workspaceRigRoot = resolve32(taskWorkspace, ".rig");
11504
- const workspaceArtifactsRoot = resolve32(taskWorkspace, "artifacts");
11505
- if (absPath === workspaceRigRoot || absPath.startsWith(workspaceRigRoot + "/") || absPath === workspaceArtifactsRoot || absPath.startsWith(workspaceArtifactsRoot + "/")) {
11506
- return true;
11507
- }
11508
- }
11509
- const runtimeRoot = resolve32(projectRoot, ".rig/runtime/agents");
11510
- return absPath === runtimeRoot || absPath.startsWith(runtimeRoot + "/");
11511
- }
11512
- function isTestFile(path) {
11513
- return /\.(test|spec)\.(ts|tsx|js|jsx)$/.test(path) || /\/(__tests__|tests|test)\//.test(path);
11514
- }
11515
- function evaluate(context) {
11516
- const policy = loadPolicy(context.projectRoot);
11517
- switch (context.evaluation.type) {
11518
- case "tool-call":
11519
- return evaluateToolCall(policy, context);
11520
- case "command":
11521
- return evaluateCommand(policy, context);
11522
- case "content-write":
11523
- return evaluateContent(policy, context);
11524
- case "file-access":
11525
- return evaluateScope(policy, context, context.evaluation.file_path, context.evaluation.access);
11526
- }
11527
- }
11528
- function evaluateScope(policy, context, filePath, access) {
11529
- const allowed = () => ({
11530
- allowed: true,
11531
- matchedRules: [],
11532
- action: "allow",
11533
- failClosed: false
11534
- });
11535
- if (policy.scope.harness_paths_exempt && isHarnessPath(context.projectRoot, filePath)) {
11536
- return allowed();
11537
- }
11538
- if (policy.scope.runtime_paths_exempt && isRuntimePath(context.projectRoot, filePath, context.taskWorkspace)) {
11539
- return allowed();
11540
- }
11541
- if (!context.taskId) {
11542
- if (access === "write" && policy.scope.fail_closed) {
11543
- return {
11544
- allowed: false,
11545
- matchedRules: [],
11546
- action: resolveAction(policy.mode, [{ id: "scope:no-task", category: "command", reason: "No active task; fail-closed for write operations" }]),
11547
- failClosed: true
11548
- };
11549
- }
11550
- return allowed();
11551
- }
11552
- const scopes = context.taskScopes || [];
11553
- if (scopes.length === 0) {
11554
- return allowed();
11555
- }
11556
- if (context.taskWorkspace && context.taskWorkspace !== context.projectRoot && filePath.startsWith("/")) {
11557
- const absPath = resolve32(filePath);
11558
- if (!absPath.startsWith(context.taskWorkspace + "/") && !isHarnessPath(context.projectRoot, filePath)) {
11559
- const reason2 = `Absolute path '${filePath}' is outside task runtime boundary. Allowed root: ${context.taskWorkspace}`;
11560
- const matched2 = [{ id: "scope:workspace-boundary", category: "command", reason: reason2 }];
11561
- return {
11562
- allowed: policy.mode !== "enforce",
11563
- matchedRules: matched2,
11564
- action: resolveAction(policy.mode, matched2),
11565
- failClosed: false
11566
- };
11567
- }
11568
- }
11569
- const monorepoRoot = context.monorepoRoot || process.env.MONOREPO_ROOT?.trim() || context.taskWorkspace || context.projectRoot;
11570
- let normalizedPath = filePath;
11571
- if (context.taskWorkspace && context.taskWorkspace !== context.projectRoot && filePath.startsWith(context.taskWorkspace + "/")) {
11572
- normalizedPath = filePath.slice(context.taskWorkspace.length + 1);
11573
- }
11574
- normalizedPath = normalizePathToScope(context.projectRoot, monorepoRoot, normalizedPath);
11575
- if (scopeMatches(filePath, scopes) || scopeMatches(normalizedPath, scopes)) {
11576
- return allowed();
11577
- }
11578
- const reason = `File '${filePath}' (normalized: '${normalizedPath}') is outside scope of task ${context.taskId}`;
11579
- const matched = [{ id: "scope:out-of-scope", category: "command", reason }];
11580
- return {
11581
- allowed: policy.mode !== "enforce",
11582
- matchedRules: matched,
11583
- action: resolveAction(policy.mode, matched),
11584
- failClosed: false
11585
- };
11586
- }
11587
- function evaluateCommand(policy, context) {
11588
- const evaluation = context.evaluation;
11589
- if (evaluation.type !== "command") {
11590
- return { allowed: true, matchedRules: [], action: "allow", failClosed: false };
11591
- }
11592
- const command = evaluation.command;
11593
- const matchedRules = [];
11594
- for (const rule of policy.rules) {
11595
- if (rule.category !== "command")
11596
- continue;
11597
- if (!matchRule(rule, command))
11598
- continue;
11599
- if (matchRuleUnless(rule, command, context.taskId))
11600
- continue;
11601
- matchedRules.push({
11602
- id: rule.id,
11603
- category: rule.category,
11604
- description: rule.description,
11605
- reason: rule.description || `Matched rule ${rule.id}`
11606
- });
11607
- }
11608
- const writeTarget = extractWriteTarget(command);
11609
- if (writeTarget && !/^\/dev\//.test(writeTarget) && !/^\/proc\//.test(writeTarget)) {
11610
- const scopeResult = evaluateScope(policy, context, writeTarget, "write");
11611
- if (!scopeResult.allowed || scopeResult.matchedRules.length > 0) {
11612
- matchedRules.push(...scopeResult.matchedRules);
11613
- }
11614
- }
11615
- const action = resolveAction(policy.mode, matchedRules);
11616
- return {
11617
- allowed: action !== "block",
11618
- matchedRules,
11619
- action,
11620
- failClosed: false
11621
- };
11622
- }
11623
- function extractWriteTarget(command) {
11624
- const redirect = command.match(/>>?\s+([^\s;|&]+)/);
11625
- if (redirect?.[1])
11626
- return redirect[1];
11627
- const tee = command.match(/tee\s+(-a\s+)?([^\s;|&]+)/);
11628
- if (tee?.[2])
11629
- return tee[2];
11630
- return "";
11631
- }
11632
- function evaluateContent(policy, context) {
11633
- const evaluation = context.evaluation;
11634
- if (evaluation.type !== "content-write") {
11635
- return { allowed: true, matchedRules: [], action: "allow", failClosed: false };
11636
- }
11637
- const { content, file_path } = evaluation;
11638
- const matchedRules = [];
11639
- const scopeResult = evaluateScope(policy, context, file_path, "write");
11640
- if (scopeResult.matchedRules.length > 0) {
11641
- matchedRules.push(...scopeResult.matchedRules);
11642
- }
11643
- for (const rule of policy.rules) {
11644
- if (rule.category !== "content" && rule.category !== "import" && rule.category !== "test-integrity")
11645
- continue;
11646
- if (rule.applies_to === "test-files" && !isTestFile(file_path))
11647
- continue;
11648
- if (!matchRule(rule, content))
11649
- continue;
11650
- if (matchRuleUnless(rule, content, context.taskId))
11651
- continue;
11652
- matchedRules.push({
11653
- id: rule.id,
11654
- category: rule.category,
11655
- description: rule.description,
11656
- reason: rule.description || `Matched rule ${rule.id}`
11657
- });
11658
- }
11659
- const action = resolveAction(policy.mode, matchedRules);
11660
- return {
11661
- allowed: action !== "block",
11662
- matchedRules,
11663
- action,
11664
- failClosed: false
11665
- };
11666
- }
11667
- function evaluateToolCall(policy, context) {
11668
- const evaluation = context.evaluation;
11669
- if (evaluation.type !== "tool-call") {
11670
- return { allowed: true, matchedRules: [], action: "allow", failClosed: false };
11671
- }
11672
- const { tool_name, tool_input } = evaluation;
11673
- const allMatched = [];
11674
- const filePaths = extractFilePathsFromToolInput(tool_name, tool_input);
11675
- for (const fp of filePaths) {
11676
- const access = isWriteTool(tool_name) ? "write" : "read";
11677
- const scopeResult = evaluateScope(policy, context, fp, access);
11678
- if (scopeResult.matchedRules.length > 0) {
11679
- allMatched.push(...scopeResult.matchedRules);
11680
- }
11681
- }
11682
- const content = extractContentFromToolInput(tool_input);
11683
- if (content) {
11684
- const filePath = filePaths[0] || "";
11685
- const contentContext = {
11686
- ...context,
11687
- evaluation: { type: "content-write", file_path: filePath, content }
11688
- };
11689
- const contentPolicy = loadPolicy(context.projectRoot);
11690
- for (const rule of contentPolicy.rules) {
11691
- if (rule.category !== "content" && rule.category !== "import" && rule.category !== "test-integrity")
11692
- continue;
11693
- if (rule.applies_to === "test-files" && !isTestFile(filePath))
11694
- continue;
11695
- if (!matchRule(rule, content))
11696
- continue;
11697
- if (matchRuleUnless(rule, content, context.taskId))
11698
- continue;
11699
- allMatched.push({
11700
- id: rule.id,
11701
- category: rule.category,
11702
- description: rule.description,
11703
- reason: rule.description || `Matched rule ${rule.id}`
11704
- });
11705
- }
11706
- }
11707
- if (tool_name === "Bash") {
11708
- const command = String(tool_input.command || tool_input.cmd || "");
11709
- if (command) {
11710
- const cmdContext = {
11711
- ...context,
11712
- evaluation: { type: "command", command }
11713
- };
11714
- const cmdResult = evaluateCommand(policy, cmdContext);
11715
- if (cmdResult.matchedRules.length > 0) {
11716
- allMatched.push(...cmdResult.matchedRules);
11717
- }
11718
- }
11719
- }
11720
- const seen = new Set;
11721
- const deduplicated = [];
11722
- for (const rule of allMatched) {
11723
- if (!seen.has(rule.id)) {
11724
- seen.add(rule.id);
11725
- deduplicated.push(rule);
11726
- }
11727
- }
11728
- const action = resolveAction(policy.mode, deduplicated);
11729
- return {
11730
- allowed: action !== "block",
11731
- matchedRules: deduplicated,
11732
- action,
11733
- failClosed: false
11734
- };
11735
- }
11736
- function isWriteTool(toolName) {
11737
- return toolName === "Write" || toolName === "Edit" || toolName === "MultiEdit";
11738
- }
11739
- function extractFilePathsFromToolInput(toolName, input) {
11740
- const paths = [];
11741
- const add = (value) => {
11742
- if (typeof value === "string" && value.trim()) {
11743
- paths.push(value.trim());
11744
- }
11745
- };
11746
- if (toolName === "Read" || toolName === "Write" || toolName === "Edit" || toolName === "MultiEdit") {
11747
- add(input.file_path);
11748
- add(input.path);
11749
- } else if (toolName === "Glob") {
11750
- add(input.path);
11751
- } else if (toolName === "Grep") {
11752
- add(input.path);
11753
- } else {
11754
- add(input.file_path);
11755
- add(input.path);
11756
- }
11757
- return paths;
11758
- }
11759
- function extractContentFromToolInput(input) {
11760
- if (typeof input.content === "string")
11761
- return input.content;
11762
- if (typeof input.new_string === "string")
11763
- return input.new_string;
11764
- return "";
11765
- }
11766
- function loadRuntimeImageConfig(projectRoot) {
11767
- return loadPolicy(projectRoot).runtime_image ?? {
11768
- deps: { ...DEFAULT_RUNTIME_IMAGE.deps },
11769
- plugins_require_binaries: DEFAULT_RUNTIME_IMAGE.plugins_require_binaries
11770
- };
11771
- }
11772
- var guardHotPathPrimed = false;
11773
- function primeGuardHotPaths() {
11774
- if (guardHotPathPrimed) {
11775
- return;
11776
- }
11777
- guardHotPathPrimed = true;
11778
- try {
11779
- optimizeNextInvocation(matchRule);
11780
- optimizeNextInvocation(evaluate);
11781
- } catch {}
11782
- }
11783
- primeGuardHotPaths();
11784
-
11785
11235
  // packages/runtime/src/control-plane/runtime/plugin-mode.ts
11786
- var LEGACY_PLUGIN_SCAN_ENV = "RIG_LEGACY_PLUGIN_SCAN";
11787
- function isLegacyPluginScanEnabled(env = process.env) {
11788
- const value = env[LEGACY_PLUGIN_SCAN_ENV]?.trim().toLowerCase();
11789
- return value === "1" || value === "true" || value === "yes" || value === "on";
11790
- }
11791
11236
  function resolveHarnessPluginMode(options) {
11792
- const legacyScanEnabled = isLegacyPluginScanEnabled(options.env);
11793
- if (options.hasDeclarativeConfig && legacyScanEnabled) {
11794
- return {
11795
- kind: "declarative-with-legacy-compat",
11796
- legacyScanEnabled: true,
11797
- diagnostic: `[harness] plugin mode: declarative rig.config.ts plugins + legacy compatibility scan (${LEGACY_PLUGIN_SCAN_ENV}=1)`
11798
- };
11799
- }
11800
11237
  if (options.hasDeclarativeConfig) {
11801
11238
  return {
11802
11239
  kind: "declarative",
11803
- legacyScanEnabled: false,
11804
- diagnostic: `[harness] plugin mode: declarative rig.config.ts plugins (legacy scan disabled; set ${LEGACY_PLUGIN_SCAN_ENV}=1 only for compatibility)`
11805
- };
11806
- }
11807
- if (legacyScanEnabled) {
11808
- return {
11809
- kind: "legacy-compat",
11810
- legacyScanEnabled: true,
11811
- diagnostic: `[harness] plugin mode: legacy compatibility scan (${LEGACY_PLUGIN_SCAN_ENV}=1; add rig.config.ts to use declarative plugins)`
11240
+ diagnostic: "[harness] plugin mode: declarative rig.config.ts plugins"
11812
11241
  };
11813
11242
  }
11814
11243
  return {
11815
11244
  kind: "none",
11816
- legacyScanEnabled: false,
11817
- diagnostic: `[harness] plugin mode: none (no rig.config.ts found; legacy scan disabled; set ${LEGACY_PLUGIN_SCAN_ENV}=1 only for compatibility)`
11245
+ diagnostic: "[harness] plugin mode: none (no rig.config.ts found; add one to load plugins)"
11818
11246
  };
11819
11247
  }
11820
11248
 
11821
- // packages/runtime/src/control-plane/runtime/plugins.ts
11822
- class PluginManager {
11823
- eventBus;
11824
- context;
11825
- pluginDir;
11826
- pluginFiles;
11827
- pluginNames;
11828
- localBinDir;
11829
- pluginsRequireBinaries;
11830
- plugins;
11831
- loadPromise;
11832
- constructor(options) {
11833
- this.eventBus = options.eventBus;
11834
- this.context = options.context;
11835
- this.pluginDir = options.pluginDir;
11836
- this.pluginFiles = options.pluginFiles;
11837
- this.pluginNames = options.pluginNames;
11838
- this.localBinDir = options.localBinDir;
11839
- this.pluginsRequireBinaries = options.pluginsRequireBinaries;
11840
- this.plugins = options.preloadedPlugins ?? null;
11841
- this.loadPromise = null;
11842
- }
11843
- static disabled(options) {
11844
- const validatorProjectRoot = options.runtimeContext?.workspaceDir || options.projectRoot;
11845
- return new PluginManager({
11846
- eventBus: options.eventBus,
11847
- context: {
11848
- projectRoot: validatorProjectRoot,
11849
- runId: options.runId,
11850
- eventBus: options.eventBus
11851
- },
11852
- pluginDir: resolve33(options.projectRoot, "rig/plugins"),
11853
- pluginFiles: [],
11854
- pluginNames: [],
11855
- localBinDir: options.runtimeContext ? resolve33(options.runtimeContext.binDir, "plugins") : resolve33(options.projectRoot, "rig/plugins"),
11856
- pluginsRequireBinaries: false,
11857
- preloadedPlugins: []
11858
- });
11859
- }
11860
- static async load(options) {
11861
- const pluginDir = resolve33(options.projectRoot, "rig/plugins");
11862
- const runtimeImageConfig = loadRuntimeImageConfig(options.projectRoot);
11863
- const localBinDir = options.runtimeContext ? resolve33(options.runtimeContext.binDir, "plugins") : resolve33(options.projectRoot, "rig/plugins");
11864
- const legacyPluginScan = options.legacyPluginScan ?? isLegacyPluginScanEnabled(options.env);
11865
- const files = legacyPluginScan ? safeReadDir(pluginDir).filter((entry) => /\.(ts|js|mjs|cjs)$/.test(entry)) : [];
11866
- const pluginNames = files.map((file) => basename9(file).replace(/\.plugin\.(ts|js|mjs|cjs)$/, ""));
11867
- const validatorProjectRoot = options.runtimeContext?.workspaceDir || options.projectRoot;
11868
- const context = {
11869
- projectRoot: validatorProjectRoot,
11870
- runId: options.runId,
11871
- eventBus: options.eventBus
11872
- };
11873
- return new PluginManager({
11874
- eventBus: options.eventBus,
11875
- context,
11876
- pluginDir,
11877
- pluginFiles: files,
11878
- pluginNames,
11879
- localBinDir,
11880
- pluginsRequireBinaries: options.pluginsRequireBinaries ?? (runtimeImageConfig.plugins_require_binaries && Boolean(options.runtimeContext))
11881
- });
11882
- }
11883
- list() {
11884
- if (this.plugins) {
11885
- return this.plugins.map((plugin) => ({
11886
- name: plugin.name,
11887
- validators: plugin.validators?.map((validator) => validator.id) ?? []
11888
- }));
11889
- }
11890
- return this.pluginNames.map((name) => ({
11891
- name,
11892
- validators: []
11893
- }));
11894
- }
11895
- async beforeCommand(ctx) {
11896
- const plugins = await this.ensureLoaded();
11897
- for (const plugin of plugins) {
11898
- if (!plugin.beforeCommand) {
11899
- continue;
11900
- }
11901
- await this.safeInvoke(plugin.name, "beforeCommand", () => plugin.beforeCommand?.(ctx, this.context));
11902
- }
11903
- }
11904
- async afterCommand(result) {
11905
- const plugins = await this.ensureLoaded();
11906
- for (const plugin of plugins) {
11907
- if (!plugin.afterCommand) {
11908
- continue;
11909
- }
11910
- await this.safeInvoke(plugin.name, "afterCommand", () => plugin.afterCommand?.(result, this.context));
11911
- }
11912
- }
11913
- async onEvent(event) {
11914
- const plugins = this.plugins;
11915
- if (!plugins) {
11916
- return;
11917
- }
11918
- for (const plugin of plugins) {
11919
- if (!plugin.onEvent) {
11920
- continue;
11921
- }
11922
- await this.safeInvoke(plugin.name, "onEvent", () => plugin.onEvent?.(event, this.context));
11923
- }
11924
- }
11925
- async runValidators(taskId) {
11926
- const plugins = await this.ensureLoaded();
11927
- const results = [];
11928
- for (const plugin of plugins) {
11929
- for (const validator of plugin.validators ?? []) {
11930
- await this.eventBus.emit("validator.started", {
11931
- plugin: plugin.name,
11932
- validator: validator.id,
11933
- taskId
11934
- });
11935
- try {
11936
- const result = await validator.run({ taskId, projectRoot: this.context.projectRoot }, this.context);
11937
- results.push(result);
11938
- await this.eventBus.emit("validator.finished", {
11939
- plugin: plugin.name,
11940
- validator: validator.id,
11941
- taskId,
11942
- passed: result.passed,
11943
- summary: result.summary
11944
- });
11945
- } catch (error) {
11946
- const failed = {
11947
- id: validator.id,
11948
- passed: false,
11949
- summary: `${plugin.name}/${validator.id} failed unexpectedly`,
11950
- details: `${error}`
11951
- };
11952
- results.push(failed);
11953
- await this.eventBus.emit("validator.finished", {
11954
- plugin: plugin.name,
11955
- validator: validator.id,
11956
- taskId,
11957
- passed: false,
11958
- summary: failed.summary,
11959
- details: failed.details
11960
- });
11961
- }
11962
- }
11963
- }
11964
- return results;
11965
- }
11966
- async safeInvoke(pluginName, hook, call) {
11967
- try {
11968
- await call();
11969
- } catch (error) {
11970
- await this.eventBus.emit("plugin.error", {
11971
- plugin: pluginName,
11972
- phase: hook,
11973
- error: `${error}`
11974
- });
11975
- }
11976
- }
11977
- async ensureLoaded() {
11978
- if (this.plugins) {
11979
- return this.plugins;
11980
- }
11981
- if (this.loadPromise) {
11982
- return this.loadPromise;
11983
- }
11984
- this.loadPromise = this.loadCompiledPlugins();
11985
- try {
11986
- this.plugins = await this.loadPromise;
11987
- return this.plugins;
11988
- } finally {
11989
- this.loadPromise = null;
11990
- }
11991
- }
11992
- resolveBinPath(binName) {
11993
- const candidates = [this.localBinDir].filter(Boolean).map((dir) => resolve33(dir, binName));
11994
- return candidates.find((candidate) => existsSync31(candidate));
11995
- }
11996
- async loadCompiledPlugins() {
11997
- const plugins = [];
11998
- for (const file of this.pluginFiles) {
11999
- const binName = basename9(file).replace(/\.plugin\.(ts|js|mjs|cjs)$/, "");
12000
- let binPath = this.resolveBinPath(binName);
12001
- if (!binPath) {
12002
- const triedPaths = [this.localBinDir].filter(Boolean).map((dir) => resolve33(dir, binName));
12003
- const missingError = `Compiled plugin binary not found for '${binName}'. Tried: ${triedPaths.join(", ")}`;
12004
- await this.eventBus.emit("plugin.error", {
12005
- file: resolve33(this.pluginDir, file),
12006
- phase: "load",
12007
- error: missingError
12008
- });
12009
- if (this.pluginsRequireBinaries) {
12010
- throw new Error(missingError);
12011
- }
12012
- plugins.push({
12013
- name: binName,
12014
- validators: []
12015
- });
12016
- await this.eventBus.emit("plugin.loaded", {
12017
- plugin: binName,
12018
- file: resolve33(this.pluginDir, file),
12019
- source: "metadata-only"
12020
- });
12021
- continue;
12022
- }
12023
- const wrapper = createBinaryPluginWrapper(binName, binPath, this.context.projectRoot);
12024
- plugins.push(wrapper);
12025
- await this.eventBus.emit("plugin.loaded", {
12026
- plugin: wrapper.name,
12027
- file: binPath,
12028
- source: "compiled-binary"
12029
- });
12030
- }
12031
- return plugins;
12032
- }
12033
- }
12034
- function createBinaryPluginWrapper(name, binPath, projectRoot) {
12035
- return {
12036
- name,
12037
- validators: [
12038
- {
12039
- id: `${name}:compiled`,
12040
- async run(ctx) {
12041
- const proc = Bun.spawn([binPath, "--validate", ctx.taskId, ctx.projectRoot], {
12042
- cwd: projectRoot,
12043
- stdout: "pipe",
12044
- stderr: "pipe"
12045
- });
12046
- const exitCode = await proc.exited;
12047
- const stdout = await new Response(proc.stdout).text();
12048
- const stderr = await new Response(proc.stderr).text();
12049
- if (exitCode !== 0) {
12050
- return {
12051
- id: `${name}:compiled`,
12052
- passed: false,
12053
- summary: `Plugin binary ${name} exited with code ${exitCode}`,
12054
- details: stderr || stdout
12055
- };
12056
- }
12057
- try {
12058
- const results = JSON.parse(stdout.trim());
12059
- const failed = results.filter((r) => !r.passed);
12060
- if (failed.length > 0) {
12061
- return {
12062
- id: `${name}:compiled`,
12063
- passed: false,
12064
- summary: `${failed.length} of ${results.length} validator(s) failed`,
12065
- details: failed.map((f) => `${f.id}: ${f.summary}`).join(`
12066
- `)
12067
- };
12068
- }
12069
- return {
12070
- id: `${name}:compiled`,
12071
- passed: true,
12072
- summary: `All ${results.length} validator(s) passed`
12073
- };
12074
- } catch {
12075
- return {
12076
- id: `${name}:compiled`,
12077
- passed: false,
12078
- summary: `Failed to parse output from compiled plugin ${name}`,
12079
- details: stdout.slice(0, 500)
12080
- };
12081
- }
12082
- }
12083
- }
12084
- ]
12085
- };
12086
- }
12087
- function safeReadDir(path) {
12088
- try {
12089
- return readdirSync6(path, { withFileTypes: true }).filter((entry) => entry.isFile()).map((entry) => entry.name).sort();
12090
- } catch {
12091
- return [];
12092
- }
12093
- }
12094
-
12095
11249
  // packages/runtime/src/control-plane/harness-main.ts
12096
11250
  async function main() {
12097
11251
  const projectRoot = resolveProjectRoot({
12098
11252
  cwd: process.cwd(),
12099
- fallbackFromDir: resolve34(import.meta.dir, "../..")
11253
+ fallbackFromDir: resolve33(import.meta.dir, "../..")
12100
11254
  });
12101
11255
  process.env.PROJECT_RIG_ROOT = projectRoot;
12102
11256
  process.chdir(projectRoot);
@@ -12109,20 +11263,7 @@ async function main() {
12109
11263
  });
12110
11264
  console.error(pluginMode.diagnostic);
12111
11265
  const eventBus = new GeneralCliEventBus({ projectRoot });
12112
- const runtimeContext = loadRuntimeContextFromEnv() ?? undefined;
12113
- const plugins = pluginMode.legacyScanEnabled ? await PluginManager.load({
12114
- projectRoot,
12115
- runId: eventBus.getRunId(),
12116
- eventBus,
12117
- runtimeContext,
12118
- legacyPluginScan: pluginMode.legacyScanEnabled
12119
- }) : PluginManager.disabled({
12120
- projectRoot,
12121
- runId: eventBus.getRunId(),
12122
- eventBus,
12123
- runtimeContext
12124
- });
12125
- await executeHarnessCommand(projectRoot, plugins, process.argv.slice(2), eventBus, pluginHostCtx);
11266
+ await executeHarnessCommand(projectRoot, process.argv.slice(2), eventBus, pluginHostCtx);
12126
11267
  }
12127
11268
  main().catch((error) => {
12128
11269
  console.error(error instanceof Error ? error.message : `${error}`);