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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2,8 +2,8 @@
2
2
  // @bun
3
3
 
4
4
  // packages/runtime/src/control-plane/hooks/completion-verification.ts
5
- import { appendFileSync as appendFileSync2, existsSync as existsSync21, mkdirSync as mkdirSync13, readFileSync as readFileSync13, writeFileSync as writeFileSync13 } from "fs";
6
- import { resolve as resolve24 } from "path";
5
+ import { appendFileSync as appendFileSync2, existsSync as existsSync23, mkdirSync as mkdirSync14, readFileSync as readFileSync14, writeFileSync as writeFileSync14 } from "fs";
6
+ import { resolve as resolve25 } from "path";
7
7
  import {
8
8
  escapeRegExp as escapeRegExp2,
9
9
  resolveBunCli,
@@ -1073,8 +1073,8 @@ function primeGuardHotPaths() {
1073
1073
  primeGuardHotPaths();
1074
1074
 
1075
1075
  // packages/runtime/src/control-plane/native/git-ops.ts
1076
- import { existsSync as existsSync20, lstatSync, mkdirSync as mkdirSync12, readFileSync as readFileSync12, writeFileSync as writeFileSync12 } from "fs";
1077
- import { dirname as dirname10, isAbsolute as isAbsolute2, resolve as resolve23 } from "path";
1076
+ import { existsSync as existsSync22, lstatSync, mkdirSync as mkdirSync13, readFileSync as readFileSync13, writeFileSync as writeFileSync13 } from "fs";
1077
+ import { dirname as dirname11, isAbsolute as isAbsolute2, resolve as resolve24 } from "path";
1078
1078
  import { fileURLToPath as fileURLToPath2 } from "url";
1079
1079
 
1080
1080
  // packages/runtime/src/control-plane/runtime/baked-secrets.ts
@@ -1336,8 +1336,8 @@ function isAgentRuntimeContextPath(path) {
1336
1336
  }
1337
1337
 
1338
1338
  // packages/runtime/src/control-plane/native/task-ops.ts
1339
- import { appendFileSync, existsSync as existsSync19, mkdirSync as mkdirSync11, readFileSync as readFileSync11, writeFileSync as writeFileSync11 } from "fs";
1340
- import { resolve as resolve22 } from "path";
1339
+ import { appendFileSync, existsSync as existsSync21, mkdirSync as mkdirSync12, readFileSync as readFileSync12, writeFileSync as writeFileSync12 } from "fs";
1340
+ import { resolve as resolve23 } from "path";
1341
1341
 
1342
1342
  // packages/runtime/src/build-time-config.ts
1343
1343
  function normalizeBuildConfig(value) {
@@ -1653,6 +1653,8 @@ import { basename as basename3, dirname as dirname6, resolve as resolve9 } from
1653
1653
  var sharedNativeToolsOutputDir = resolve9(tmpdir4(), "rig-native");
1654
1654
  var sharedNativeToolsOutputPath = resolve9(sharedNativeToolsOutputDir, `rig-tools-${process.platform}-${process.arch}${process.platform === "win32" ? ".exe" : ""}`);
1655
1655
  // packages/runtime/src/control-plane/plugin-host-context.ts
1656
+ import { existsSync as existsSync12 } from "fs";
1657
+ import { resolve as resolvePath } from "path";
1656
1658
  import { createPluginHost } from "@rig/core";
1657
1659
  import { loadConfig } from "@rig/core/load-config";
1658
1660
 
@@ -1973,6 +1975,55 @@ async function materializeSkills(projectRoot, entries) {
1973
1975
  return written;
1974
1976
  }
1975
1977
 
1978
+ // packages/runtime/src/control-plane/pi-settings-materializer.ts
1979
+ import { existsSync as existsSync11, mkdirSync as mkdirSync6, readFileSync as readFileSync8, writeFileSync as writeFileSync5 } from "fs";
1980
+ import { dirname as dirname8, resolve as resolve12 } from "path";
1981
+ var SETTINGS_RELATIVE_PATH = ".pi/settings.json";
1982
+ var MANAGED_RECORD_RELATIVE_PATH = ".rig/state/pi-managed-packages.json";
1983
+ function readJson(path, fallback) {
1984
+ if (!existsSync11(path))
1985
+ return fallback;
1986
+ try {
1987
+ return JSON.parse(readFileSync8(path, "utf-8"));
1988
+ } catch {
1989
+ return fallback;
1990
+ }
1991
+ }
1992
+ function packageKey(entry) {
1993
+ if (typeof entry === "string")
1994
+ return entry;
1995
+ if (entry && typeof entry === "object" && typeof entry.source === "string") {
1996
+ return entry.source;
1997
+ }
1998
+ return JSON.stringify(entry);
1999
+ }
2000
+ function materializePiPackages(projectRoot, declaredPackages) {
2001
+ const settingsPath = resolve12(projectRoot, SETTINGS_RELATIVE_PATH);
2002
+ const managedRecordPath = resolve12(projectRoot, MANAGED_RECORD_RELATIVE_PATH);
2003
+ const settings = readJson(settingsPath, {});
2004
+ const previouslyManaged = new Set(readJson(managedRecordPath, []));
2005
+ const existing = Array.isArray(settings.packages) ? settings.packages : [];
2006
+ const operatorEntries = existing.filter((entry) => !previouslyManaged.has(packageKey(entry)));
2007
+ const operatorKeys = new Set(operatorEntries.map(packageKey));
2008
+ const managedToAdd = declaredPackages.filter((pkg) => !operatorKeys.has(pkg));
2009
+ const nextPackages = [...operatorEntries, ...managedToAdd];
2010
+ if (nextPackages.length > 0 || existsSync11(settingsPath)) {
2011
+ const nextSettings = { ...settings };
2012
+ if (nextPackages.length > 0) {
2013
+ nextSettings.packages = nextPackages;
2014
+ } else {
2015
+ delete nextSettings.packages;
2016
+ }
2017
+ mkdirSync6(dirname8(settingsPath), { recursive: true });
2018
+ writeFileSync5(settingsPath, `${JSON.stringify(nextSettings, null, 2)}
2019
+ `, "utf-8");
2020
+ }
2021
+ mkdirSync6(dirname8(managedRecordPath), { recursive: true });
2022
+ writeFileSync5(managedRecordPath, `${JSON.stringify(managedToAdd, null, 2)}
2023
+ `, "utf-8");
2024
+ return { settingsPath, packages: managedToAdd };
2025
+ }
2026
+
1976
2027
  // packages/runtime/src/control-plane/plugin-host-context.ts
1977
2028
  async function buildPluginHostContext(projectRoot) {
1978
2029
  let config;
@@ -2020,6 +2071,14 @@ async function buildPluginHostContext(projectRoot) {
2020
2071
  } catch (err) {
2021
2072
  console.warn(`[plugin-host] skill materialization failed: ${err instanceof Error ? err.message : err}`);
2022
2073
  }
2074
+ try {
2075
+ const piPackages = config.runtime?.pi?.packages ?? [];
2076
+ if (piPackages.length > 0 || existsSync12(resolvePath(projectRoot, ".rig/state/pi-managed-packages.json"))) {
2077
+ materializePiPackages(projectRoot, piPackages);
2078
+ }
2079
+ } catch (err) {
2080
+ console.warn(`[plugin-host] Pi package materialization failed: ${err instanceof Error ? err.message : err}`);
2081
+ }
2023
2082
  return {
2024
2083
  config,
2025
2084
  pluginHost,
@@ -2033,12 +2092,12 @@ async function buildPluginHostContext(projectRoot) {
2033
2092
 
2034
2093
  // packages/runtime/src/control-plane/tasks/source-aware-task-config-source.ts
2035
2094
  import { spawnSync } from "child_process";
2036
- import { existsSync as existsSync12, readFileSync as readFileSync9, readdirSync as readdirSync2, statSync as statSync3, writeFileSync as writeFileSync5 } from "fs";
2037
- import { basename as basename4, join as join2, resolve as resolve13 } from "path";
2095
+ import { existsSync as existsSync14, readFileSync as readFileSync10, readdirSync as readdirSync2, statSync as statSync3, writeFileSync as writeFileSync6 } from "fs";
2096
+ import { basename as basename4, join as join2, resolve as resolve14 } from "path";
2038
2097
 
2039
2098
  // packages/runtime/src/control-plane/tasks/legacy-task-config-source.ts
2040
- import { existsSync as existsSync11, readFileSync as readFileSync8 } from "fs";
2041
- import { resolve as resolve12 } from "path";
2099
+ import { existsSync as existsSync13, readFileSync as readFileSync9 } from "fs";
2100
+ import { resolve as resolve13 } from "path";
2042
2101
 
2043
2102
  // packages/runtime/src/control-plane/tasks/task-record-reader.ts
2044
2103
  async function findTaskById(reader, id) {
@@ -2061,7 +2120,7 @@ class LegacyTaskConfigReadError extends Error {
2061
2120
  }
2062
2121
  }
2063
2122
  function createLegacyTaskConfigRecordReader(projectRoot, options = {}) {
2064
- const configPath = options.configPath ?? resolve12(projectRoot, ".rig", "task-config.json");
2123
+ const configPath = options.configPath ?? resolve13(projectRoot, ".rig", "task-config.json");
2065
2124
  const reader = {
2066
2125
  async listTasks() {
2067
2126
  return readLegacyTaskRecords(projectRoot, configPath);
@@ -2072,8 +2131,8 @@ function createLegacyTaskConfigRecordReader(projectRoot, options = {}) {
2072
2131
  };
2073
2132
  return reader;
2074
2133
  }
2075
- function readLegacyTaskRecords(projectRoot, configPath = resolve12(projectRoot, ".rig", "task-config.json")) {
2076
- if (!existsSync11(configPath)) {
2134
+ function readLegacyTaskRecords(projectRoot, configPath = resolve13(projectRoot, ".rig", "task-config.json")) {
2135
+ if (!existsSync13(configPath)) {
2077
2136
  return [];
2078
2137
  }
2079
2138
  const rawConfig = readLegacyTaskConfigJson(projectRoot, configPath);
@@ -2081,7 +2140,7 @@ function readLegacyTaskRecords(projectRoot, configPath = resolve12(projectRoot,
2081
2140
  }
2082
2141
  function readLegacyTaskConfigJson(projectRoot, configPath) {
2083
2142
  try {
2084
- const parsed = JSON.parse(readFileSync8(configPath, "utf8"));
2143
+ const parsed = JSON.parse(readFileSync9(configPath, "utf8"));
2085
2144
  if (isPlainRecord(parsed)) {
2086
2145
  return parsed;
2087
2146
  }
@@ -2165,7 +2224,7 @@ function isPlainRecord(candidate) {
2165
2224
  var STATUS_LABELS = new Set(["ready", "blocked", "in-progress", "under-review", "failed", "cancelled"]);
2166
2225
  var FILE_TASK_PATTERN = /\.(task\.)?json$/;
2167
2226
  function createSourceAwareTaskConfigRecordReader(projectRoot, options = {}) {
2168
- const configPath = options.configPath ?? resolve13(projectRoot, ".rig", "task-config.json");
2227
+ const configPath = options.configPath ?? resolve14(projectRoot, ".rig", "task-config.json");
2169
2228
  const legacy = createLegacyTaskConfigRecordReader(projectRoot, { configPath });
2170
2229
  const spawnFn = options.spawn ?? spawnSync;
2171
2230
  const ghBinary = options.ghBinary ?? "gh";
@@ -2231,7 +2290,7 @@ async function readSourceAwareTaskStatus(projectRoot, taskId, options = {}) {
2231
2290
  }
2232
2291
  }
2233
2292
  function updateSourceAwareTaskConfigTask(projectRoot, taskId, update, options = {}) {
2234
- const configPath = options.configPath ?? resolve13(projectRoot, ".rig", "task-config.json");
2293
+ const configPath = options.configPath ?? resolve14(projectRoot, ".rig", "task-config.json");
2235
2294
  const rawEntry = readRawTaskEntry(configPath, taskId);
2236
2295
  if (!rawEntry) {
2237
2296
  const configuredFilesPath = readConfiguredFilesTaskSourcePath(projectRoot);
@@ -2284,10 +2343,10 @@ function readMaterializedTaskMetadata(entry) {
2284
2343
  return metadata;
2285
2344
  }
2286
2345
  function readConfiguredFilesTaskSourcePath(projectRoot) {
2287
- const jsonPath = resolve13(projectRoot, "rig.config.json");
2288
- if (existsSync12(jsonPath)) {
2346
+ const jsonPath = resolve14(projectRoot, "rig.config.json");
2347
+ if (existsSync14(jsonPath)) {
2289
2348
  try {
2290
- const parsed = JSON.parse(readFileSync9(jsonPath, "utf8"));
2349
+ const parsed = JSON.parse(readFileSync10(jsonPath, "utf8"));
2291
2350
  if (isPlainRecord2(parsed) && isPlainRecord2(parsed.taskSource)) {
2292
2351
  const source = parsed.taskSource;
2293
2352
  return source.kind === "files" && typeof source.path === "string" ? source.path : null;
@@ -2296,12 +2355,12 @@ function readConfiguredFilesTaskSourcePath(projectRoot) {
2296
2355
  return null;
2297
2356
  }
2298
2357
  }
2299
- const tsPath = resolve13(projectRoot, "rig.config.ts");
2300
- if (!existsSync12(tsPath)) {
2358
+ const tsPath = resolve14(projectRoot, "rig.config.ts");
2359
+ if (!existsSync14(tsPath)) {
2301
2360
  return null;
2302
2361
  }
2303
2362
  try {
2304
- const source = readFileSync9(tsPath, "utf8");
2363
+ const source = readFileSync10(tsPath, "utf8");
2305
2364
  const taskSourceBlock = source.match(/taskSource\s*:\s*\{[\s\S]*?\}/m)?.[0] ?? "";
2306
2365
  const kind = taskSourceBlock.match(/kind\s*:\s*["']([^"']+)["']/)?.[1];
2307
2366
  if (kind !== "files") {
@@ -2321,10 +2380,10 @@ function readRawTaskEntry(configPath, taskId) {
2321
2380
  return isPlainRecord2(entry) ? entry : null;
2322
2381
  }
2323
2382
  function readRawTaskConfig(configPath) {
2324
- if (!existsSync12(configPath)) {
2383
+ if (!existsSync14(configPath)) {
2325
2384
  return null;
2326
2385
  }
2327
- const parsed = JSON.parse(readFileSync9(configPath, "utf8"));
2386
+ const parsed = JSON.parse(readFileSync10(configPath, "utf8"));
2328
2387
  return isPlainRecord2(parsed) ? parsed : null;
2329
2388
  }
2330
2389
  function stripLegacyTaskConfigMetadata2(raw) {
@@ -2341,16 +2400,16 @@ function writeLegacyTaskStatus(configPath, taskId, status) {
2341
2400
  return;
2342
2401
  }
2343
2402
  entry.status = status;
2344
- writeFileSync5(configPath, `${JSON.stringify(rawConfig, null, 2)}
2403
+ writeFileSync6(configPath, `${JSON.stringify(rawConfig, null, 2)}
2345
2404
  `, "utf8");
2346
2405
  }
2347
2406
  function updateFileBackedTask(projectRoot, sourcePath, taskId, update) {
2348
- const directory = resolve13(projectRoot, sourcePath);
2407
+ const directory = resolve14(projectRoot, sourcePath);
2349
2408
  const file = findFileBackedTaskFile(directory, taskId);
2350
2409
  if (!file) {
2351
2410
  return false;
2352
2411
  }
2353
- const raw = JSON.parse(readFileSync9(file, "utf8"));
2412
+ const raw = JSON.parse(readFileSync10(file, "utf8"));
2354
2413
  if (!isPlainRecord2(raw)) {
2355
2414
  return false;
2356
2415
  }
@@ -2367,13 +2426,13 @@ function updateFileBackedTask(projectRoot, sourcePath, taskId, update) {
2367
2426
  { body: update.comment, createdAt: new Date().toISOString(), source: "rig" }
2368
2427
  ];
2369
2428
  }
2370
- writeFileSync5(file, `${JSON.stringify(raw, null, 2)}
2429
+ writeFileSync6(file, `${JSON.stringify(raw, null, 2)}
2371
2430
  `, "utf8");
2372
2431
  return true;
2373
2432
  }
2374
2433
  function listFileBackedTasks(projectRoot, sourcePath) {
2375
- const directory = resolve13(projectRoot, sourcePath);
2376
- if (!existsSync12(directory)) {
2434
+ const directory = resolve14(projectRoot, sourcePath);
2435
+ if (!existsSync14(directory)) {
2377
2436
  return [];
2378
2437
  }
2379
2438
  const tasks = [];
@@ -2388,11 +2447,11 @@ function listFileBackedTasks(projectRoot, sourcePath) {
2388
2447
  return tasks;
2389
2448
  }
2390
2449
  function readFileBackedTask(projectRoot, sourcePath, taskId, rawEntry) {
2391
- const file = findFileBackedTaskFile(resolve13(projectRoot, sourcePath), taskId);
2450
+ const file = findFileBackedTaskFile(resolve14(projectRoot, sourcePath), taskId);
2392
2451
  if (!file) {
2393
2452
  return null;
2394
2453
  }
2395
- const raw = JSON.parse(readFileSync9(file, "utf8"));
2454
+ const raw = JSON.parse(readFileSync10(file, "utf8"));
2396
2455
  if (!isPlainRecord2(raw)) {
2397
2456
  return null;
2398
2457
  }
@@ -2405,7 +2464,7 @@ function readFileBackedTask(projectRoot, sourcePath, taskId, rawEntry) {
2405
2464
  };
2406
2465
  }
2407
2466
  function findFileBackedTaskFile(directory, taskId) {
2408
- if (!existsSync12(directory)) {
2467
+ if (!existsSync14(directory)) {
2409
2468
  return null;
2410
2469
  }
2411
2470
  for (const name of readdirSync2(directory)) {
@@ -2415,7 +2474,7 @@ function findFileBackedTaskFile(directory, taskId) {
2415
2474
  try {
2416
2475
  if (!statSync3(file).isFile())
2417
2476
  continue;
2418
- const raw = JSON.parse(readFileSync9(file, "utf8"));
2477
+ const raw = JSON.parse(readFileSync10(file, "utf8"));
2419
2478
  const inferredId = basename4(file).replace(FILE_TASK_PATTERN, "");
2420
2479
  const id = isPlainRecord2(raw) && typeof raw.id === "string" ? raw.id : inferredId;
2421
2480
  if (id === taskId) {
@@ -2764,8 +2823,8 @@ function buildTaskRunLifecycleComment(input) {
2764
2823
  }
2765
2824
 
2766
2825
  // packages/runtime/src/control-plane/native/task-state.ts
2767
- import { existsSync as existsSync13, readFileSync as readFileSync10, readdirSync as readdirSync3, statSync as statSync4, writeFileSync as writeFileSync6 } from "fs";
2768
- import { basename as basename5, resolve as resolve14 } from "path";
2826
+ import { existsSync as existsSync15, readFileSync as readFileSync11, readdirSync as readdirSync3, statSync as statSync4, writeFileSync as writeFileSync7 } from "fs";
2827
+ import { basename as basename5, resolve as resolve15 } from "path";
2769
2828
 
2770
2829
  // packages/runtime/src/control-plane/state-sync/types.ts
2771
2830
  var CANONICAL_TASK_LIFECYCLE_STATUSES = new Set([
@@ -2795,7 +2854,7 @@ function readValidationDescriptions(projectRoot) {
2795
2854
  return readValidationDescriptionMap(raw);
2796
2855
  }
2797
2856
  function readSourceValidationDescriptions(projectRoot) {
2798
- const rootRaw = readJsonFile(resolve14(projectRoot, "rig", "task-config.json"), {});
2857
+ const rootRaw = readJsonFile(resolve15(projectRoot, "rig", "task-config.json"), {});
2799
2858
  const sourcePath = findSourceTaskConfigPath(projectRoot);
2800
2859
  const sourceRaw = sourcePath ? readJsonFile(sourcePath, {}) : {};
2801
2860
  const rootDescriptions = readValidationDescriptionMap(rootRaw);
@@ -2886,25 +2945,25 @@ function lookupTask(projectRoot, input) {
2886
2945
  function artifactDirForId(projectRoot, id) {
2887
2946
  const workspaceDir = process.env.RIG_TASK_WORKSPACE?.trim();
2888
2947
  if (workspaceDir) {
2889
- const worktreeArtifacts = resolve14(workspaceDir, "artifacts", id);
2890
- if (existsSync13(worktreeArtifacts) || existsSync13(resolve14(workspaceDir, "artifacts"))) {
2948
+ const worktreeArtifacts = resolve15(workspaceDir, "artifacts", id);
2949
+ if (existsSync15(worktreeArtifacts) || existsSync15(resolve15(workspaceDir, "artifacts"))) {
2891
2950
  return worktreeArtifacts;
2892
2951
  }
2893
2952
  }
2894
2953
  try {
2895
2954
  const paths = resolveHarnessPaths(projectRoot);
2896
- return resolve14(paths.artifactsDir, id);
2955
+ return resolve15(paths.artifactsDir, id);
2897
2956
  } catch {
2898
- return resolve14(resolveMonorepoRoot2(projectRoot), "artifacts", id);
2957
+ return resolve15(resolveMonorepoRoot2(projectRoot), "artifacts", id);
2899
2958
  }
2900
2959
  }
2901
2960
  function resolveTaskConfigPath(projectRoot) {
2902
2961
  const paths = resolveHarnessPaths(projectRoot);
2903
- if (existsSync13(paths.taskConfigPath)) {
2962
+ if (existsSync15(paths.taskConfigPath)) {
2904
2963
  return paths.taskConfigPath;
2905
2964
  }
2906
2965
  for (const candidate of sourceTaskConfigCandidates(projectRoot)) {
2907
- if (existsSync13(candidate)) {
2966
+ if (existsSync15(candidate)) {
2908
2967
  return candidate;
2909
2968
  }
2910
2969
  }
@@ -2912,7 +2971,7 @@ function resolveTaskConfigPath(projectRoot) {
2912
2971
  }
2913
2972
  function findSourceTaskConfigPath(projectRoot) {
2914
2973
  for (const candidate of sourceTaskConfigCandidates(projectRoot)) {
2915
- if (existsSync13(candidate)) {
2974
+ if (existsSync15(candidate)) {
2916
2975
  return candidate;
2917
2976
  }
2918
2977
  }
@@ -2925,7 +2984,7 @@ function readAndSyncSourceTaskConfig(projectRoot) {
2925
2984
  const synced = synchronizeTaskConfigWithTracker(projectRoot, raw);
2926
2985
  if (sourcePath && synced.updated) {
2927
2986
  try {
2928
- writeFileSync6(sourcePath, `${JSON.stringify(synced.config, null, 2)}
2987
+ writeFileSync7(sourcePath, `${JSON.stringify(synced.config, null, 2)}
2929
2988
  `, "utf-8");
2930
2989
  } catch {}
2931
2990
  }
@@ -2977,12 +3036,12 @@ function shouldRefreshAutoSyncedTaskConfigEntry(entry) {
2977
3036
  return !candidate.role;
2978
3037
  }
2979
3038
  function readSourceIssueRecords(projectRoot) {
2980
- const issuesPath = resolve14(resolveMonorepoRoot2(projectRoot), ".beads", "issues.jsonl");
2981
- if (!existsSync13(issuesPath)) {
3039
+ const issuesPath = resolve15(resolveMonorepoRoot2(projectRoot), ".beads", "issues.jsonl");
3040
+ if (!existsSync15(issuesPath)) {
2982
3041
  return [];
2983
3042
  }
2984
3043
  const records = [];
2985
- for (const line of readFileSync10(issuesPath, "utf-8").split(/\r?\n/)) {
3044
+ for (const line of readFileSync11(issuesPath, "utf-8").split(/\r?\n/)) {
2986
3045
  const trimmed = line.trim();
2987
3046
  if (!trimmed) {
2988
3047
  continue;
@@ -3038,19 +3097,19 @@ function readConfiguredFileTaskConfig(projectRoot) {
3038
3097
  if (!sourcePath) {
3039
3098
  return {};
3040
3099
  }
3041
- const directory = resolve14(projectRoot, sourcePath);
3042
- if (!existsSync13(directory)) {
3100
+ const directory = resolve15(projectRoot, sourcePath);
3101
+ if (!existsSync15(directory)) {
3043
3102
  return {};
3044
3103
  }
3045
3104
  const config = {};
3046
3105
  for (const name of readdirSync3(directory)) {
3047
3106
  if (!FILE_TASK_PATTERN2.test(name))
3048
3107
  continue;
3049
- const file = resolve14(directory, name);
3108
+ const file = resolve15(directory, name);
3050
3109
  try {
3051
3110
  if (!statSync4(file).isFile())
3052
3111
  continue;
3053
- const raw = JSON.parse(readFileSync10(file, "utf8"));
3112
+ const raw = JSON.parse(readFileSync11(file, "utf8"));
3054
3113
  if (!raw || typeof raw !== "object" || Array.isArray(raw))
3055
3114
  continue;
3056
3115
  const record = raw;
@@ -3092,10 +3151,10 @@ function firstStringList2(...candidates) {
3092
3151
  return [];
3093
3152
  }
3094
3153
  function readConfiguredFilesTaskSourcePath2(projectRoot) {
3095
- const jsonPath = resolve14(projectRoot, "rig.config.json");
3096
- if (existsSync13(jsonPath)) {
3154
+ const jsonPath = resolve15(projectRoot, "rig.config.json");
3155
+ if (existsSync15(jsonPath)) {
3097
3156
  try {
3098
- const parsed = JSON.parse(readFileSync10(jsonPath, "utf8"));
3157
+ const parsed = JSON.parse(readFileSync11(jsonPath, "utf8"));
3099
3158
  if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
3100
3159
  const taskSource = parsed.taskSource;
3101
3160
  if (taskSource && typeof taskSource === "object" && !Array.isArray(taskSource)) {
@@ -3107,12 +3166,12 @@ function readConfiguredFilesTaskSourcePath2(projectRoot) {
3107
3166
  return null;
3108
3167
  }
3109
3168
  }
3110
- const tsPath = resolve14(projectRoot, "rig.config.ts");
3111
- if (!existsSync13(tsPath)) {
3169
+ const tsPath = resolve15(projectRoot, "rig.config.ts");
3170
+ if (!existsSync15(tsPath)) {
3112
3171
  return null;
3113
3172
  }
3114
3173
  try {
3115
- const source = readFileSync10(tsPath, "utf8");
3174
+ const source = readFileSync11(tsPath, "utf8");
3116
3175
  const taskSourceBlock = source.match(/taskSource\s*:\s*\{[\s\S]*?\}/m)?.[0] ?? "";
3117
3176
  const kind = taskSourceBlock.match(/kind\s*:\s*["']([^"']+)["']/)?.[1];
3118
3177
  if (kind !== "files") {
@@ -3126,23 +3185,23 @@ function readConfiguredFilesTaskSourcePath2(projectRoot) {
3126
3185
  function sourceTaskConfigCandidates(projectRoot) {
3127
3186
  const runtimeContext = loadRuntimeContextFromEnv();
3128
3187
  return [
3129
- runtimeContext?.monorepoMainRoot ? resolve14(runtimeContext.monorepoMainRoot, ".rig", "task-config.json") : "",
3130
- process.env.MONOREPO_MAIN_ROOT?.trim() ? resolve14(process.env.MONOREPO_MAIN_ROOT.trim(), ".rig", "task-config.json") : "",
3131
- resolve14(resolveMonorepoRoot2(projectRoot), ".rig", "task-config.json")
3188
+ runtimeContext?.monorepoMainRoot ? resolve15(runtimeContext.monorepoMainRoot, ".rig", "task-config.json") : "",
3189
+ process.env.MONOREPO_MAIN_ROOT?.trim() ? resolve15(process.env.MONOREPO_MAIN_ROOT.trim(), ".rig", "task-config.json") : "",
3190
+ resolve15(resolveMonorepoRoot2(projectRoot), ".rig", "task-config.json")
3132
3191
  ].filter(Boolean);
3133
3192
  }
3134
3193
 
3135
3194
  // packages/runtime/src/control-plane/native/validator.ts
3136
- import { existsSync as existsSync17, mkdirSync as mkdirSync8, writeFileSync as writeFileSync8 } from "fs";
3137
- import { resolve as resolve19 } from "path";
3195
+ import { existsSync as existsSync19, mkdirSync as mkdirSync9, writeFileSync as writeFileSync9 } from "fs";
3196
+ import { resolve as resolve20 } from "path";
3138
3197
 
3139
3198
  // packages/runtime/src/control-plane/native/validator-binaries.ts
3140
- import { existsSync as existsSync16, mkdirSync as mkdirSync7, rmSync as rmSync5, statSync as statSync5 } from "fs";
3141
- import { dirname as dirname9, resolve as resolve18 } from "path";
3199
+ import { existsSync as existsSync18, mkdirSync as mkdirSync8, rmSync as rmSync5, statSync as statSync5 } from "fs";
3200
+ import { dirname as dirname10, resolve as resolve19 } from "path";
3142
3201
 
3143
3202
  // packages/runtime/src/binary-run.ts
3144
- import { chmodSync as chmodSync2, cpSync, existsSync as existsSync14, mkdirSync as mkdirSync6, renameSync as renameSync3, rmSync as rmSync4, writeFileSync as writeFileSync7 } from "fs";
3145
- import { basename as basename6, dirname as dirname8, resolve as resolve15 } from "path";
3203
+ import { chmodSync as chmodSync2, cpSync, existsSync as existsSync16, mkdirSync as mkdirSync7, renameSync as renameSync3, rmSync as rmSync4, writeFileSync as writeFileSync8 } from "fs";
3204
+ import { basename as basename6, dirname as dirname9, resolve as resolve16 } from "path";
3146
3205
  import { fileURLToPath } from "url";
3147
3206
  import { drainMicrotasks, gcAndSweep } from "bun:jsc";
3148
3207
  var runtimeBinaryBuildQueue = Promise.resolve();
@@ -3168,9 +3227,9 @@ async function buildRuntimeBinary(options) {
3168
3227
  });
3169
3228
  }
3170
3229
  async function buildRuntimeBinaryInProcess(options, manifest) {
3171
- const tempBuildDir = resolve15(dirname8(options.outputPath), `.bun-build-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`);
3172
- const tempOutputPath = resolve15(tempBuildDir, basename6(options.outputPath));
3173
- mkdirSync6(tempBuildDir, { recursive: true });
3230
+ const tempBuildDir = resolve16(dirname9(options.outputPath), `.bun-build-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`);
3231
+ const tempOutputPath = resolve16(tempBuildDir, basename6(options.outputPath));
3232
+ mkdirSync7(tempBuildDir, { recursive: true });
3174
3233
  await withTemporaryEnv({
3175
3234
  ...options.env,
3176
3235
  ...options.define ? { RIG_BUILD_CONFIG_JSON: JSON.stringify(options.define) } : {}
@@ -3195,7 +3254,7 @@ async function buildRuntimeBinaryInProcess(options, manifest) {
3195
3254
  `);
3196
3255
  throw new Error(`Failed to build ${options.entrypoint}: ${details || "Bun.build() returned errors"}`);
3197
3256
  }
3198
- if (!existsSync14(tempOutputPath)) {
3257
+ if (!existsSync16(tempOutputPath)) {
3199
3258
  const emitted = buildResult.outputs.map((output) => output.path).join(", ") || "(none)";
3200
3259
  throw new Error(`Failed to build ${options.entrypoint}: Bun.build() did not emit ${tempOutputPath}. Emitted: ${emitted}`);
3201
3260
  }
@@ -3227,8 +3286,8 @@ function runtimeBinaryCacheManifestPath(outputPath) {
3227
3286
  function resolveRuntimeBinaryBuildOptions(options) {
3228
3287
  return {
3229
3288
  ...options,
3230
- entrypoint: resolve15(options.cwd, options.sourcePath),
3231
- outputPath: resolve15(options.outputPath)
3289
+ entrypoint: resolve16(options.cwd, options.sourcePath),
3290
+ outputPath: resolve16(options.outputPath)
3232
3291
  };
3233
3292
  }
3234
3293
  function shouldUseRuntimeBinaryBuildWorker() {
@@ -3242,7 +3301,7 @@ function shouldUseRuntimeBinaryBuildWorker() {
3242
3301
  }
3243
3302
  async function buildRuntimeBinaryViaWorker(options) {
3244
3303
  const workerSourcePath = resolveRuntimeBinaryBuildWorkerSourcePath(options);
3245
- if (!workerSourcePath || !existsSync14(workerSourcePath)) {
3304
+ if (!workerSourcePath || !existsSync16(workerSourcePath)) {
3246
3305
  await buildRuntimeBinaryInProcess(options, {
3247
3306
  manifestPath: runtimeBinaryCacheManifestPath(options.outputPath),
3248
3307
  buildKey: createRuntimeBinaryBuildKey({
@@ -3279,7 +3338,7 @@ async function buildRuntimeBinaryViaWorker(options) {
3279
3338
  }
3280
3339
  }
3281
3340
  function createRuntimeBinaryBuildWorkerPayloadPath(outputPath) {
3282
- return resolve15(dirname8(outputPath), `.bun-build-worker-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}.json`);
3341
+ return resolve16(dirname9(outputPath), `.bun-build-worker-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}.json`);
3283
3342
  }
3284
3343
  function resolveRuntimeBinaryBuildWorkerSourcePath(options) {
3285
3344
  const envRoots = [
@@ -3288,13 +3347,13 @@ function resolveRuntimeBinaryBuildWorkerSourcePath(options) {
3288
3347
  process.env.PROJECT_RIG_ROOT?.trim()
3289
3348
  ].filter(Boolean);
3290
3349
  for (const root of envRoots) {
3291
- const candidate = resolve15(root, "packages/runtime/src/binary-build-worker.ts");
3292
- if (existsSync14(candidate)) {
3350
+ const candidate = resolve16(root, "packages/runtime/src/binary-build-worker.ts");
3351
+ if (existsSync16(candidate)) {
3293
3352
  return candidate;
3294
3353
  }
3295
3354
  }
3296
- const localCandidate = resolve15(import.meta.dir, "binary-build-worker.ts");
3297
- return existsSync14(localCandidate) ? localCandidate : null;
3355
+ const localCandidate = resolve16(import.meta.dir, "binary-build-worker.ts");
3356
+ return existsSync16(localCandidate) ? localCandidate : null;
3298
3357
  }
3299
3358
  function resolveRuntimeBinaryBuildWorkerInvocation() {
3300
3359
  const bunPath = Bun.which("bun");
@@ -3330,7 +3389,7 @@ function createRuntimeBinaryBuildKey(input) {
3330
3389
  });
3331
3390
  }
3332
3391
  async function isRuntimeBinaryBuildFresh(input) {
3333
- if (!existsSync14(input.outputPath) || !existsSync14(input.manifestPath)) {
3392
+ if (!existsSync16(input.outputPath) || !existsSync16(input.manifestPath)) {
3334
3393
  return false;
3335
3394
  }
3336
3395
  let manifest = null;
@@ -3343,7 +3402,7 @@ async function isRuntimeBinaryBuildFresh(input) {
3343
3402
  return false;
3344
3403
  }
3345
3404
  for (const [filePath, expectedDigest] of Object.entries(manifest.inputs || {})) {
3346
- if (!existsSync14(filePath)) {
3405
+ if (!existsSync16(filePath)) {
3347
3406
  return false;
3348
3407
  }
3349
3408
  if (await sha256File(filePath) !== expectedDigest) {
@@ -3356,7 +3415,7 @@ async function writeRuntimeBinaryCacheManifest(input) {
3356
3415
  const inputs = {};
3357
3416
  for (const inputPath of Object.keys(input.metafile?.inputs || {}).sort()) {
3358
3417
  const normalized = normalizeBuildInputPath(input.cwd, inputPath);
3359
- if (!normalized || !existsSync14(normalized)) {
3418
+ if (!normalized || !existsSync16(normalized)) {
3360
3419
  continue;
3361
3420
  }
3362
3421
  inputs[normalized] = await sha256File(normalized);
@@ -3379,7 +3438,7 @@ function normalizeBuildInputPath(cwd, inputPath) {
3379
3438
  if (inputPath.startsWith("<")) {
3380
3439
  return null;
3381
3440
  }
3382
- return resolve15(cwd, inputPath);
3441
+ return resolve16(cwd, inputPath);
3383
3442
  }
3384
3443
  async function sha256File(path) {
3385
3444
  const hasher = new Bun.CryptoHasher("sha256");
@@ -3395,8 +3454,8 @@ function sortRecord(value) {
3395
3454
  async function runSerializedRuntimeBinaryBuild(action) {
3396
3455
  const previous = runtimeBinaryBuildQueue;
3397
3456
  let release;
3398
- runtimeBinaryBuildQueue = new Promise((resolve16) => {
3399
- release = resolve16;
3457
+ runtimeBinaryBuildQueue = new Promise((resolve17) => {
3458
+ release = resolve17;
3400
3459
  });
3401
3460
  await previous;
3402
3461
  try {
@@ -3441,11 +3500,11 @@ async function withTemporaryCwd(cwd, action) {
3441
3500
  }
3442
3501
 
3443
3502
  // packages/runtime/src/control-plane/runtime/provisioning-env.ts
3444
- import { delimiter, resolve as resolve17 } from "path";
3503
+ import { delimiter, resolve as resolve18 } from "path";
3445
3504
 
3446
3505
  // packages/runtime/src/control-plane/runtime/runtime-paths.ts
3447
- import { existsSync as existsSync15, readdirSync as readdirSync4, realpathSync } from "fs";
3448
- import { resolve as resolve16 } from "path";
3506
+ import { existsSync as existsSync17, readdirSync as readdirSync4, realpathSync } from "fs";
3507
+ import { resolve as resolve17 } from "path";
3449
3508
 
3450
3509
  // packages/runtime/src/control-plane/runtime/sandbox/utils.ts
3451
3510
  function uniq(values) {
@@ -3463,7 +3522,7 @@ function resolveBunBinaryPath() {
3463
3522
  }
3464
3523
  const home = process.env.HOME?.trim();
3465
3524
  const fallbackCandidates = [
3466
- home ? resolve16(home, ".bun/bin/bun") : "",
3525
+ home ? resolve17(home, ".bun/bin/bun") : "",
3467
3526
  "/opt/homebrew/bin/bun",
3468
3527
  "/usr/local/bin/bun",
3469
3528
  "/usr/bin/bun"
@@ -3491,8 +3550,8 @@ function resolveClaudeBinaryPath() {
3491
3550
  }
3492
3551
  const home = process.env.HOME?.trim();
3493
3552
  const fallbackCandidates = [
3494
- home ? resolve16(home, ".local/bin/claude") : "",
3495
- home ? resolve16(home, ".local/share/claude/local/claude") : "",
3553
+ home ? resolve17(home, ".local/bin/claude") : "",
3554
+ home ? resolve17(home, ".local/share/claude/local/claude") : "",
3496
3555
  "/opt/homebrew/bin/claude",
3497
3556
  "/usr/local/bin/claude",
3498
3557
  "/usr/bin/claude"
@@ -3506,51 +3565,51 @@ function resolveClaudeBinaryPath() {
3506
3565
  throw new Error("claude not found in PATH");
3507
3566
  }
3508
3567
  function resolveBunInstallDir(bunBinaryPath = resolveBunBinaryPath()) {
3509
- return resolve16(bunBinaryPath, "../..");
3568
+ return resolve17(bunBinaryPath, "../..");
3510
3569
  }
3511
3570
  function resolveClaudeInstallDir() {
3512
3571
  const realPath = resolveClaudeBinaryPath();
3513
- return resolve16(realPath, "..");
3572
+ return resolve17(realPath, "..");
3514
3573
  }
3515
3574
  function resolveNodeInstallDir() {
3516
3575
  const preferredNode = resolvePreferredNodeBinary();
3517
3576
  if (!preferredNode)
3518
3577
  return null;
3519
3578
  const explicitNode = process.env.RIG_NODE_BIN?.trim();
3520
- if (explicitNode && resolve16(explicitNode) === resolve16(preferredNode)) {
3521
- return preferredNode.endsWith("/bin/node") ? resolve16(preferredNode, "../..") : resolve16(preferredNode, "..");
3579
+ if (explicitNode && resolve17(explicitNode) === resolve17(preferredNode)) {
3580
+ return preferredNode.endsWith("/bin/node") ? resolve17(preferredNode, "../..") : resolve17(preferredNode, "..");
3522
3581
  }
3523
3582
  try {
3524
3583
  const realPath = realpathSync(preferredNode);
3525
3584
  if (realPath.endsWith("/bin/node")) {
3526
- return resolve16(realPath, "../..");
3585
+ return resolve17(realPath, "../..");
3527
3586
  }
3528
- return resolve16(realPath, "..");
3587
+ return resolve17(realPath, "..");
3529
3588
  } catch {
3530
- return resolve16(preferredNode, "..");
3589
+ return resolve17(preferredNode, "..");
3531
3590
  }
3532
3591
  }
3533
3592
  function resolvePreferredNodeBinary() {
3534
3593
  const candidates = [];
3535
3594
  const envNode = process.env.RIG_NODE_BIN?.trim();
3536
3595
  if (envNode) {
3537
- const explicit = resolve16(envNode);
3538
- if (existsSync15(explicit)) {
3596
+ const explicit = resolve17(envNode);
3597
+ if (existsSync17(explicit)) {
3539
3598
  return explicit;
3540
3599
  }
3541
3600
  }
3542
3601
  const nvmBin = process.env.NVM_BIN?.trim();
3543
3602
  if (nvmBin) {
3544
- candidates.push(resolve16(nvmBin, "node"));
3603
+ candidates.push(resolve17(nvmBin, "node"));
3545
3604
  }
3546
3605
  const home = process.env.HOME?.trim();
3547
3606
  if (home) {
3548
- const nvmVersionsDir = resolve16(home, ".nvm/versions/node");
3549
- if (existsSync15(nvmVersionsDir)) {
3607
+ const nvmVersionsDir = resolve17(home, ".nvm/versions/node");
3608
+ if (existsSync17(nvmVersionsDir)) {
3550
3609
  try {
3551
3610
  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/, "")));
3552
3611
  for (const versionDir of versionDirs) {
3553
- candidates.push(resolve16(nvmVersionsDir, versionDir, "bin/node"));
3612
+ candidates.push(resolve17(nvmVersionsDir, versionDir, "bin/node"));
3554
3613
  }
3555
3614
  } catch {}
3556
3615
  }
@@ -3559,8 +3618,8 @@ function resolvePreferredNodeBinary() {
3559
3618
  if (whichNode) {
3560
3619
  candidates.push(whichNode);
3561
3620
  }
3562
- const deduped = uniq(candidates.map((candidate) => resolve16(candidate)));
3563
- const existing = deduped.filter((candidate) => existsSync15(candidate));
3621
+ const deduped = uniq(candidates.map((candidate) => resolve17(candidate)));
3622
+ const existing = deduped.filter((candidate) => existsSync17(candidate));
3564
3623
  if (existing.length === 0) {
3565
3624
  return null;
3566
3625
  }
@@ -3574,7 +3633,7 @@ function resolvePreferredNodeBinary() {
3574
3633
  return existing[0] ?? null;
3575
3634
  }
3576
3635
  function inferNodeMajor(nodeBinaryPath) {
3577
- const normalized = resolve16(nodeBinaryPath).replace(/\\/g, "/");
3636
+ const normalized = resolve17(nodeBinaryPath).replace(/\\/g, "/");
3578
3637
  const match = normalized.match(/(?:^|\/)(?:node-)?v?(\d+)\.\d+\.\d+(?:\/|$)/);
3579
3638
  if (!match) {
3580
3639
  return null;
@@ -3586,8 +3645,8 @@ function normalizeExecutablePath(candidate) {
3586
3645
  if (!candidate) {
3587
3646
  return "";
3588
3647
  }
3589
- const normalized = resolve16(candidate);
3590
- if (!existsSync15(normalized)) {
3648
+ const normalized = resolve17(candidate);
3649
+ if (!existsSync17(normalized)) {
3591
3650
  return "";
3592
3651
  }
3593
3652
  try {
@@ -3597,7 +3656,7 @@ function normalizeExecutablePath(candidate) {
3597
3656
  }
3598
3657
  }
3599
3658
  function looksLikeRuntimeGateway(candidate) {
3600
- const normalized = resolve16(candidate).replace(/\\/g, "/");
3659
+ const normalized = resolve17(candidate).replace(/\\/g, "/");
3601
3660
  return normalized.includes("/.rig/bin/") || normalized.endsWith("/rig-shell") || normalized.endsWith("/rig-agent");
3602
3661
  }
3603
3662
 
@@ -3618,7 +3677,7 @@ function runtimeProvisioningEnv(baseEnv = process.env) {
3618
3677
  try {
3619
3678
  return resolveClaudeInstallDir();
3620
3679
  } catch {
3621
- return resolve17(claudeBinary, "..");
3680
+ return resolve18(claudeBinary, "..");
3622
3681
  }
3623
3682
  })() : "";
3624
3683
  const nodeDir = resolveNodeInstallDir();
@@ -3628,8 +3687,8 @@ function runtimeProvisioningEnv(baseEnv = process.env) {
3628
3687
  `${bunDir}/bin`,
3629
3688
  claudeDir,
3630
3689
  nodeDir ? `${nodeDir}/bin` : "",
3631
- realHome ? resolve17(realHome, ".local/bin") : "",
3632
- realHome ? resolve17(realHome, ".cargo/bin") : "",
3690
+ realHome ? resolve18(realHome, ".local/bin") : "",
3691
+ realHome ? resolve18(realHome, ".cargo/bin") : "",
3633
3692
  ...inheritedPath,
3634
3693
  "/usr/local/bin",
3635
3694
  "/usr/local/sbin",
@@ -3660,9 +3719,9 @@ function runtimeProvisioningEnv(baseEnv = process.env) {
3660
3719
  // packages/runtime/src/control-plane/native/validator-binaries.ts
3661
3720
  function resolveValidatorBinaryPath(projectRoot, binaryName, runtimeContext) {
3662
3721
  if (runtimeContext) {
3663
- return resolve18(runtimeContext.binDir, "validators", binaryName);
3722
+ return resolve19(runtimeContext.binDir, "validators", binaryName);
3664
3723
  }
3665
- return resolve18(resolveHarnessPaths(projectRoot).binDir, "validators", binaryName);
3724
+ return resolve19(resolveHarnessPaths(projectRoot).binDir, "validators", binaryName);
3666
3725
  }
3667
3726
  async function ensureValidatorBinary(projectRoot, checkId, runtimeContext) {
3668
3727
  const match = checkId.match(/^([a-z][\w-]*):([a-z][\w-]*)$/);
@@ -3677,19 +3736,19 @@ async function ensureValidatorBinary(projectRoot, checkId, runtimeContext) {
3677
3736
  const binaryName = `${category}-${check}`;
3678
3737
  const binaryPath = resolveValidatorBinaryPath(projectRoot, binaryName, runtimeContext);
3679
3738
  const hostProjectRoot = runtimeContext?.hostProjectRoot?.trim() || projectRoot;
3680
- const sourcePath = resolve18(hostProjectRoot, "packages/runtime/src/control-plane/validators", category, `${check}.ts`);
3681
- if (!existsSync16(sourcePath)) {
3739
+ const sourcePath = resolve19(hostProjectRoot, "packages/runtime/src/control-plane/validators", category, `${check}.ts`);
3740
+ if (!existsSync18(sourcePath)) {
3682
3741
  return null;
3683
3742
  }
3684
3743
  const sourceMtime = statSync5(sourcePath).mtimeMs;
3685
- const binaryExists = existsSync16(binaryPath);
3744
+ const binaryExists = existsSync18(binaryPath);
3686
3745
  const binaryMtime = binaryExists ? statSync5(binaryPath).mtimeMs : 0;
3687
3746
  if (!binaryExists || sourceMtime > binaryMtime) {
3688
3747
  if (binaryExists) {
3689
3748
  rmSync5(binaryPath, { force: true });
3690
3749
  rmSync5(`${binaryPath}.build-manifest.json`, { force: true });
3691
3750
  }
3692
- mkdirSync7(dirname9(binaryPath), { recursive: true });
3751
+ mkdirSync8(dirname10(binaryPath), { recursive: true });
3693
3752
  await buildRuntimeBinary({
3694
3753
  sourcePath: `packages/runtime/src/control-plane/validators/${category}/${check}.ts`,
3695
3754
  outputPath: binaryPath,
@@ -3698,7 +3757,7 @@ async function ensureValidatorBinary(projectRoot, checkId, runtimeContext) {
3698
3757
  env: runtimeProvisioningEnv()
3699
3758
  });
3700
3759
  }
3701
- return existsSync16(binaryPath) ? binaryPath : null;
3760
+ return existsSync18(binaryPath) ? binaryPath : null;
3702
3761
  }
3703
3762
 
3704
3763
  // packages/runtime/src/control-plane/native/validator.ts
@@ -3735,20 +3794,20 @@ async function readTaskSourceValidation(projectRoot, taskId) {
3735
3794
  function resolveValidationPaths(projectRoot, taskId, runtimeContext) {
3736
3795
  if (runtimeContext) {
3737
3796
  return {
3738
- taskLogDir: resolve19(runtimeContext.logsDir, taskId),
3739
- artifactDir: resolve19(runtimeContext.workspaceDir, "artifacts", taskId)
3797
+ taskLogDir: resolve20(runtimeContext.logsDir, taskId),
3798
+ artifactDir: resolve20(runtimeContext.workspaceDir, "artifacts", taskId)
3740
3799
  };
3741
3800
  }
3742
3801
  const paths = resolveHarnessPaths(projectRoot);
3743
3802
  return {
3744
- taskLogDir: resolve19(paths.logsDir, taskId),
3745
- artifactDir: resolve19(paths.artifactsDir, taskId)
3803
+ taskLogDir: resolve20(paths.logsDir, taskId),
3804
+ artifactDir: resolve20(paths.artifactsDir, taskId)
3746
3805
  };
3747
3806
  }
3748
3807
  async function runValidatorBinary(projectRoot, taskId, checkId, runtimeContext) {
3749
3808
  const binaryName = checkId.replace(":", "-");
3750
3809
  const binaryPath = await ensureValidatorBinary(projectRoot, checkId, runtimeContext) ?? resolveValidatorBinaryPath(projectRoot, binaryName, runtimeContext);
3751
- if (!existsSync17(binaryPath)) {
3810
+ if (!existsSync19(binaryPath)) {
3752
3811
  return {
3753
3812
  result: {
3754
3813
  id: checkId,
@@ -3759,7 +3818,7 @@ async function runValidatorBinary(projectRoot, taskId, checkId, runtimeContext)
3759
3818
  };
3760
3819
  }
3761
3820
  const validatorCwd = runtimeContext?.workspaceDir || resolveMonorepoRoot(projectRoot);
3762
- const runtimeShellPath = runtimeContext ? resolve19(runtimeContext.binDir, "rig-shell") : "";
3821
+ const runtimeShellPath = runtimeContext ? resolve20(runtimeContext.binDir, "rig-shell") : "";
3763
3822
  const monorepoMainRoot = runtimeContext?.monorepoMainRoot || process.env.MONOREPO_MAIN_ROOT?.trim() || resolveMonorepoRoot(projectRoot);
3764
3823
  const validatorEnv = {
3765
3824
  PROJECT_RIG_ROOT: runtimeContext?.hostProjectRoot || projectRoot,
@@ -3774,7 +3833,7 @@ async function runValidatorBinary(projectRoot, taskId, checkId, runtimeContext)
3774
3833
  validatorEnv.RIG_LOGS_DIR = runtimeContext.logsDir;
3775
3834
  validatorEnv.RIG_RUNTIME_BIN_DIR = runtimeContext.binDir;
3776
3835
  }
3777
- const { exitCode, stdout, stderr } = await runCaptureAsync(runtimeShellPath && existsSync17(runtimeShellPath) ? [runtimeShellPath, "run-binary", binaryPath] : [binaryPath], validatorCwd, validatorEnv);
3836
+ const { exitCode, stdout, stderr } = await runCaptureAsync(runtimeShellPath && existsSync19(runtimeShellPath) ? [runtimeShellPath, "run-binary", binaryPath] : [binaryPath], validatorCwd, validatorEnv);
3778
3837
  try {
3779
3838
  const result = JSON.parse(stdout.trim());
3780
3839
  return { result, exitCode };
@@ -3814,8 +3873,8 @@ async function validateTask(projectRoot, taskId, runtimeContext, registry, optio
3814
3873
  const configuredValidation = stringArray(taskConfig[taskId]?.validation);
3815
3874
  const commands = resolvedContext?.validation?.length ? resolvedContext.validation : configuredValidation.length > 0 ? configuredValidation : sourceValidation.validation;
3816
3875
  const { taskLogDir, artifactDir } = resolveValidationPaths(projectRoot, taskId, resolvedContext);
3817
- mkdirSync8(taskLogDir, { recursive: true });
3818
- mkdirSync8(artifactDir, { recursive: true });
3876
+ mkdirSync9(taskLogDir, { recursive: true });
3877
+ mkdirSync9(artifactDir, { recursive: true });
3819
3878
  if (commands.length === 0) {
3820
3879
  const skipped = {
3821
3880
  status: "skipped",
@@ -3824,7 +3883,7 @@ async function validateTask(projectRoot, taskId, runtimeContext, registry, optio
3824
3883
  failed: 0,
3825
3884
  categories: []
3826
3885
  };
3827
- writeFileSync8(resolve19(artifactDir, "validation-summary.json"), `${JSON.stringify(skipped, null, 2)}
3886
+ writeFileSync9(resolve20(artifactDir, "validation-summary.json"), `${JSON.stringify(skipped, null, 2)}
3828
3887
  `, "utf-8");
3829
3888
  return skipped;
3830
3889
  }
@@ -3859,18 +3918,18 @@ async function validateTask(projectRoot, taskId, runtimeContext, registry, optio
3859
3918
  exit_code: 2,
3860
3919
  duration_seconds: 0
3861
3920
  });
3862
- const logFile2 = resolve19(taskLogDir, `invalid-entry-validation.log`);
3863
- mkdirSync8(taskLogDir, { recursive: true });
3864
- writeFileSync8(logFile2, `=== ${nowIso()} :: ${cmd} ===
3921
+ const logFile2 = resolve20(taskLogDir, `invalid-entry-validation.log`);
3922
+ mkdirSync9(taskLogDir, { recursive: true });
3923
+ writeFileSync9(logFile2, `=== ${nowIso()} :: ${cmd} ===
3865
3924
  Invalid validation entry: not a check-ID. All entries must use format "category:check-name".
3866
3925
  `, "utf-8");
3867
3926
  continue;
3868
3927
  }
3869
3928
  const { result, exitCode } = await dispatchValidator(cmd, effectiveRegistry, validatorCtx, (id) => runValidatorBinary(projectRoot, taskId, id, resolvedContext));
3870
3929
  const durationSeconds = Math.max(0, Math.round((Date.now() - startedAt) / 1000));
3871
- const logFile = resolve19(taskLogDir, `${cmd.replace(":", "-")}-validation.log`);
3872
- mkdirSync8(taskLogDir, { recursive: true });
3873
- writeFileSync8(logFile, `=== ${nowIso()} :: ${cmd} ===
3930
+ const logFile = resolve20(taskLogDir, `${cmd.replace(":", "-")}-validation.log`);
3931
+ mkdirSync9(taskLogDir, { recursive: true });
3932
+ writeFileSync9(logFile, `=== ${nowIso()} :: ${cmd} ===
3874
3933
  ${JSON.stringify(result, null, 2)}
3875
3934
  `, "utf-8");
3876
3935
  if (result.passed) {
@@ -3892,19 +3951,19 @@ ${JSON.stringify(result, null, 2)}
3892
3951
  failed,
3893
3952
  categories
3894
3953
  };
3895
- mkdirSync8(artifactDir, { recursive: true });
3896
- writeFileSync8(resolve19(artifactDir, "validation-summary.json"), `${JSON.stringify(summary, null, 2)}
3954
+ mkdirSync9(artifactDir, { recursive: true });
3955
+ writeFileSync9(resolve20(artifactDir, "validation-summary.json"), `${JSON.stringify(summary, null, 2)}
3897
3956
  `, "utf-8");
3898
3957
  return summary;
3899
3958
  }
3900
3959
 
3901
3960
  // packages/runtime/src/control-plane/native/verifier.ts
3902
- import { existsSync as existsSync18, mkdirSync as mkdirSync10, writeFileSync as writeFileSync10 } from "fs";
3903
- import { resolve as resolve21 } from "path";
3961
+ import { existsSync as existsSync20, mkdirSync as mkdirSync11, writeFileSync as writeFileSync11 } from "fs";
3962
+ import { resolve as resolve22 } from "path";
3904
3963
 
3905
3964
  // packages/runtime/src/control-plane/native/pr-review-gate.ts
3906
- import { mkdirSync as mkdirSync9, writeFileSync as writeFileSync9 } from "fs";
3907
- import { resolve as resolve20 } from "path";
3965
+ import { mkdirSync as mkdirSync10, writeFileSync as writeFileSync10 } from "fs";
3966
+ import { resolve as resolve21 } from "path";
3908
3967
  function parseJsonObject(value) {
3909
3968
  if (!value?.trim())
3910
3969
  return { value: {}, error: "empty JSON output" };
@@ -5228,34 +5287,34 @@ function buildStrictPrGateSteeringPrompt(result) {
5228
5287
  }
5229
5288
  function persistPrReviewCycleArtifacts(input) {
5230
5289
  const cycleName = input.final ? `${input.cycle}-final` : String(input.cycle);
5231
- const taskArtifactRoot = input.artifactRoot?.trim() ? input.artifactRoot : resolve20(input.projectRoot, "artifacts", input.taskId);
5232
- const root = resolve20(taskArtifactRoot, "pr-review-cycles", cycleName);
5233
- mkdirSync9(root, { recursive: true });
5234
- const finalMergeGateResultPath = input.final ? resolve20(taskArtifactRoot, "merge-gate-final.json") : undefined;
5290
+ const taskArtifactRoot = input.artifactRoot?.trim() ? input.artifactRoot : resolve21(input.projectRoot, "artifacts", input.taskId);
5291
+ const root = resolve21(taskArtifactRoot, "pr-review-cycles", cycleName);
5292
+ mkdirSync10(root, { recursive: true });
5293
+ const finalMergeGateResultPath = input.final ? resolve21(taskArtifactRoot, "merge-gate-final.json") : undefined;
5235
5294
  const paths = {
5236
5295
  root,
5237
- prTitlePath: resolve20(root, "pr-title.md"),
5238
- prBodyPath: resolve20(root, "pr-body.md"),
5239
- prCommentsPath: resolve20(root, "pr-comments.json"),
5240
- reviewThreadsPath: resolve20(root, "review-threads.json"),
5241
- reviewCommentsPath: resolve20(root, "review-comments.json"),
5242
- checkRollupPath: resolve20(root, "check-rollup.json"),
5243
- greptileEvidencePath: resolve20(root, "greptile-evidence.json"),
5244
- mergeGateResultPath: resolve20(root, "merge-gate-result.json"),
5245
- steeringPromptPath: resolve20(root, "agent-steering-prompt.md"),
5296
+ prTitlePath: resolve21(root, "pr-title.md"),
5297
+ prBodyPath: resolve21(root, "pr-body.md"),
5298
+ prCommentsPath: resolve21(root, "pr-comments.json"),
5299
+ reviewThreadsPath: resolve21(root, "review-threads.json"),
5300
+ reviewCommentsPath: resolve21(root, "review-comments.json"),
5301
+ checkRollupPath: resolve21(root, "check-rollup.json"),
5302
+ greptileEvidencePath: resolve21(root, "greptile-evidence.json"),
5303
+ mergeGateResultPath: resolve21(root, "merge-gate-result.json"),
5304
+ steeringPromptPath: resolve21(root, "agent-steering-prompt.md"),
5246
5305
  ...finalMergeGateResultPath ? { finalMergeGateResultPath } : {}
5247
5306
  };
5248
- writeFileSync9(paths.prTitlePath, input.result.evidence.title || "", "utf8");
5249
- writeFileSync9(paths.prBodyPath, input.result.evidence.body || "", "utf8");
5250
- writeFileSync9(paths.prCommentsPath, `${JSON.stringify(input.result.evidence.relevantIssueComments, null, 2)}
5307
+ writeFileSync10(paths.prTitlePath, input.result.evidence.title || "", "utf8");
5308
+ writeFileSync10(paths.prBodyPath, input.result.evidence.body || "", "utf8");
5309
+ writeFileSync10(paths.prCommentsPath, `${JSON.stringify(input.result.evidence.relevantIssueComments, null, 2)}
5251
5310
  `, "utf8");
5252
- writeFileSync9(paths.reviewThreadsPath, `${JSON.stringify(input.result.evidence.reviewThreads, null, 2)}
5311
+ writeFileSync10(paths.reviewThreadsPath, `${JSON.stringify(input.result.evidence.reviewThreads, null, 2)}
5253
5312
  `, "utf8");
5254
- writeFileSync9(paths.reviewCommentsPath, `${JSON.stringify(input.result.evidence.changedFileReviewComments, null, 2)}
5313
+ writeFileSync10(paths.reviewCommentsPath, `${JSON.stringify(input.result.evidence.changedFileReviewComments, null, 2)}
5255
5314
  `, "utf8");
5256
- writeFileSync9(paths.checkRollupPath, `${JSON.stringify(input.result.evidence.statusCheckRollup, null, 2)}
5315
+ writeFileSync10(paths.checkRollupPath, `${JSON.stringify(input.result.evidence.statusCheckRollup, null, 2)}
5257
5316
  `, "utf8");
5258
- writeFileSync9(paths.greptileEvidencePath, `${JSON.stringify(input.result.evidence.greptile, null, 2)}
5317
+ writeFileSync10(paths.greptileEvidencePath, `${JSON.stringify(input.result.evidence.greptile, null, 2)}
5259
5318
  `, "utf8");
5260
5319
  const mergeGatePayload = {
5261
5320
  approved: input.result.approved,
@@ -5272,13 +5331,13 @@ function persistPrReviewCycleArtifacts(input) {
5272
5331
  evidence: input.result.evidence,
5273
5332
  cycleArtifactRoot: root
5274
5333
  };
5275
- writeFileSync9(paths.mergeGateResultPath, `${JSON.stringify(mergeGatePayload, null, 2)}
5334
+ writeFileSync10(paths.mergeGateResultPath, `${JSON.stringify(mergeGatePayload, null, 2)}
5276
5335
  `, "utf8");
5277
5336
  if (paths.finalMergeGateResultPath) {
5278
- writeFileSync9(paths.finalMergeGateResultPath, `${JSON.stringify(mergeGatePayload, null, 2)}
5337
+ writeFileSync10(paths.finalMergeGateResultPath, `${JSON.stringify(mergeGatePayload, null, 2)}
5279
5338
  `, "utf8");
5280
5339
  }
5281
- writeFileSync9(paths.steeringPromptPath, input.steeringPrompt, "utf8");
5340
+ writeFileSync10(paths.steeringPromptPath, input.steeringPrompt, "utf8");
5282
5341
  return paths;
5283
5342
  }
5284
5343
  async function runStrictPrMergeGate(input) {
@@ -5295,7 +5354,7 @@ async function runStrictPrMergeGate(input) {
5295
5354
  final: input.final
5296
5355
  });
5297
5356
  const steeringPrompt = buildStrictPrGateSteeringPrompt({ ...base, artifacts });
5298
- writeFileSync9(artifacts.steeringPromptPath, steeringPrompt, "utf8");
5357
+ writeFileSync10(artifacts.steeringPromptPath, steeringPrompt, "utf8");
5299
5358
  return { ...base, artifacts, steeringPrompt };
5300
5359
  }
5301
5360
 
@@ -5305,11 +5364,11 @@ async function verifyTask(options) {
5305
5364
  const taskId = options.taskId;
5306
5365
  const normalizedTaskId = lookupTask(options.projectRoot, taskId);
5307
5366
  const artifactDir = artifactDirForId(options.projectRoot, taskId);
5308
- mkdirSync10(artifactDir, { recursive: true });
5309
- const validationSummaryPath = resolve21(artifactDir, "validation-summary.json");
5310
- const reviewFeedbackPath = resolve21(artifactDir, "review-feedback.md");
5311
- const reviewStatePath = resolve21(artifactDir, "review-state.json");
5312
- const greptileRawPath = resolve21(artifactDir, "review-greptile-raw.json");
5367
+ mkdirSync11(artifactDir, { recursive: true });
5368
+ const validationSummaryPath = resolve22(artifactDir, "validation-summary.json");
5369
+ const reviewFeedbackPath = resolve22(artifactDir, "review-feedback.md");
5370
+ const reviewStatePath = resolve22(artifactDir, "review-state.json");
5371
+ const greptileRawPath = resolve22(artifactDir, "review-greptile-raw.json");
5313
5372
  const prStates = readPrMetadata(options.projectRoot, taskId);
5314
5373
  const prState = prStates[0] || null;
5315
5374
  const localReasons = [];
@@ -5321,7 +5380,7 @@ async function verifyTask(options) {
5321
5380
  if (!normalizedTaskId && !await hasConfiguredSourceTask(options.projectRoot, taskId)) {
5322
5381
  localReasons.push(`[Task Config] Unknown task id '${taskId}' in task-config or configured task source.`);
5323
5382
  }
5324
- if (!existsSync18(validationSummaryPath)) {
5383
+ if (!existsSync20(validationSummaryPath)) {
5325
5384
  localReasons.push(`[Artifact Quality] validation-summary.json not found at ${validationSummaryPath}.`);
5326
5385
  } else {
5327
5386
  const summary = await parseValidationSummary(validationSummaryPath);
@@ -5330,13 +5389,13 @@ async function verifyTask(options) {
5330
5389
  }
5331
5390
  }
5332
5391
  for (const file of ["task-result.json", "decision-log.md", "next-actions.md", "changed-files.txt"]) {
5333
- const requiredPath = resolve21(artifactDir, file);
5334
- if (!existsSync18(requiredPath)) {
5392
+ const requiredPath = resolve22(artifactDir, file);
5393
+ if (!existsSync20(requiredPath)) {
5335
5394
  localReasons.push(`[Artifact Quality] Missing required artifact file: ${requiredPath}`);
5336
5395
  }
5337
5396
  }
5338
- const taskResultPath = resolve21(artifactDir, "task-result.json");
5339
- if (existsSync18(taskResultPath)) {
5397
+ const taskResultPath = resolve22(artifactDir, "task-result.json");
5398
+ if (existsSync20(taskResultPath)) {
5340
5399
  const taskResult = await readJsonFile2(taskResultPath);
5341
5400
  const artifactStatus = typeof taskResult?.status === "string" ? taskResult.status.trim().toLowerCase() : "";
5342
5401
  if (artifactStatus === "partial") {
@@ -5349,8 +5408,8 @@ async function verifyTask(options) {
5349
5408
  localReasons.push("[Artifact Quality] task-result.json next actions indicate remaining implementation scope.");
5350
5409
  }
5351
5410
  }
5352
- const nextActionsPath = resolve21(artifactDir, "next-actions.md");
5353
- if (existsSync18(nextActionsPath)) {
5411
+ const nextActionsPath = resolve22(artifactDir, "next-actions.md");
5412
+ if (existsSync20(nextActionsPath)) {
5354
5413
  const nextActionsContent = await Bun.file(nextActionsPath).text();
5355
5414
  if (nextActionsContent.includes("TODO: Replace this scaffold") || nextActionsContent.includes("bd-<downstream-task-id>")) {
5356
5415
  localReasons.push("[Artifact Quality] next-actions.md still contains scaffold placeholder text. Replace with real recommendations.");
@@ -5381,7 +5440,7 @@ async function verifyTask(options) {
5381
5440
  aiReasons.push(`[AI Review] Required mode needs a completed Greptile approval; current verdict is ${ai.verdict}.`);
5382
5441
  }
5383
5442
  if (persistArtifacts && ai.rawResponse) {
5384
- writeFileSync10(greptileRawPath, `${ai.rawResponse}
5443
+ writeFileSync11(greptileRawPath, `${ai.rawResponse}
5385
5444
  `, "utf-8");
5386
5445
  }
5387
5446
  } else if (!options.skipAiReview && reviewMode === "off") {
@@ -5624,7 +5683,7 @@ function evaluateSourceCloseoutChecks(prState, prLabel) {
5624
5683
  if (!Array.isArray(checks) || checks.length === 0) {
5625
5684
  return [`[Source Issue] PR ${prLabel} must have green check evidence before completion.`];
5626
5685
  }
5627
- const ciGate = evaluatePullRequestCiChecks(checks, "PR", 0);
5686
+ const ciGate = evaluatePullRequestCiChecks(checks, "PR", 0, { mergeStateStatus: prState.mergeStateStatus });
5628
5687
  if (ciGate.verdict === "APPROVE") {
5629
5688
  return [];
5630
5689
  }
@@ -5720,7 +5779,7 @@ function isAcceptedValidationSummary(summary) {
5720
5779
  return summary.status === "skipped" && summary.total === 0 && summary.failed === 0;
5721
5780
  }
5722
5781
  async function loadReviewMode(reviewProfilePath, fallback) {
5723
- const parsed = existsSync18(reviewProfilePath) ? await readJsonFile2(reviewProfilePath) : null;
5782
+ const parsed = existsSync20(reviewProfilePath) ? await readJsonFile2(reviewProfilePath) : null;
5724
5783
  const mode = parsed?.mode;
5725
5784
  if (mode === "off" || mode === "advisory" || mode === "required") {
5726
5785
  return mode;
@@ -5731,7 +5790,7 @@ async function loadReviewMode(reviewProfilePath, fallback) {
5731
5790
  return "advisory";
5732
5791
  }
5733
5792
  async function loadReviewProvider(reviewProfilePath, fallback) {
5734
- const parsed = existsSync18(reviewProfilePath) ? await readJsonFile2(reviewProfilePath) : null;
5793
+ const parsed = existsSync20(reviewProfilePath) ? await readJsonFile2(reviewProfilePath) : null;
5735
5794
  const provider = parsed?.provider;
5736
5795
  if (typeof provider === "string" && provider.trim().length > 0) {
5737
5796
  return provider;
@@ -5890,7 +5949,7 @@ function writeFeedbackFile(options) {
5890
5949
  if (options.aiRawFeedback) {
5891
5950
  lines.push("## Raw Reviewer Feedback", "", "```text", options.aiRawFeedback, "```", "");
5892
5951
  }
5893
- writeFileSync10(options.output, `${lines.join(`
5952
+ writeFileSync11(options.output, `${lines.join(`
5894
5953
  `)}
5895
5954
  `, "utf-8");
5896
5955
  }
@@ -5907,7 +5966,7 @@ function writeReviewStateFile(options) {
5907
5966
  ai_warnings: options.aiWarnings,
5908
5967
  updated_at: nowIso()
5909
5968
  };
5910
- writeFileSync10(options.output, `${JSON.stringify(payload, null, 2)}
5969
+ writeFileSync11(options.output, `${JSON.stringify(payload, null, 2)}
5911
5970
  `, "utf-8");
5912
5971
  }
5913
5972
  async function runGreptileReviewForPr(options) {
@@ -5988,7 +6047,7 @@ async function runGreptileReviewForPr(options) {
5988
6047
  }
5989
6048
  await Bun.sleep(options.pollIntervalMs);
5990
6049
  }
5991
- const ciGate = evaluatePullRequestCiChecks(githubCheckRollup, repoName, prNumber);
6050
+ const ciGate = evaluatePullRequestCiChecks(githubCheckRollup, repoName, prNumber, { mergeStateStatus: options.prState.mergeStateStatus });
5992
6051
  if (ciGate.verdict !== "APPROVE") {
5993
6052
  return {
5994
6053
  verdict: ciGate.verdict,
@@ -6246,7 +6305,7 @@ async function runGithubGreptileFallbackReviewForPr(options) {
6246
6305
  }
6247
6306
  await Bun.sleep(options.pollIntervalMs);
6248
6307
  }
6249
- const ciGate = evaluatePullRequestCiChecks(checkRollup, repoName, prNumber);
6308
+ const ciGate = evaluatePullRequestCiChecks(checkRollup, repoName, prNumber, { mergeStateStatus: options.prState.mergeStateStatus });
6250
6309
  if (ciGate.verdict !== "APPROVE") {
6251
6310
  return {
6252
6311
  verdict: ciGate.verdict,
@@ -6601,7 +6660,7 @@ function loadGithubPullRequestCheckRollup(projectRoot, repoName, prNumber) {
6601
6660
  ]);
6602
6661
  return response.statusCheckRollup || [];
6603
6662
  }
6604
- function evaluatePullRequestCiChecks(checks, repoName, prNumber) {
6663
+ function evaluatePullRequestCiChecks(checks, repoName, prNumber, options = {}) {
6605
6664
  const nonGreptileChecks = checks.filter((check) => {
6606
6665
  const label = (check.name || check.context || "").toLowerCase();
6607
6666
  return label.length > 0 && !label.includes("greptile");
@@ -6613,7 +6672,8 @@ function evaluatePullRequestCiChecks(checks, repoName, prNumber) {
6613
6672
  const state = (check.state || check.status || "").toUpperCase();
6614
6673
  return state === "PENDING" || state === "EXPECTED" || state === "QUEUED" || state === "IN_PROGRESS";
6615
6674
  });
6616
- if (pending.length > 0) {
6675
+ const mergeClean = (options.mergeStateStatus || "").toUpperCase() === "CLEAN";
6676
+ if (pending.length > 0 && !mergeClean) {
6617
6677
  return {
6618
6678
  verdict: "SKIP",
6619
6679
  reasons: pending.map((check) => `[CI] ${repoName}#${prNumber} check is still pending: ${check.name || check.context || "unknown"}.`)
@@ -6694,7 +6754,7 @@ function filterActionableGithubGreptileThreads(threads) {
6694
6754
  }
6695
6755
  function resolvePrRepoRoot(projectRoot, prState) {
6696
6756
  const runtimeWorkspace = process.env.RIG_TASK_WORKSPACE?.trim();
6697
- if (prState.target === "monorepo" && runtimeWorkspace && existsSync18(resolve21(runtimeWorkspace, ".git"))) {
6757
+ if (prState.target === "monorepo" && runtimeWorkspace && existsSync20(resolve22(runtimeWorkspace, ".git"))) {
6698
6758
  return runtimeWorkspace;
6699
6759
  }
6700
6760
  const paths = resolveHarnessPaths(projectRoot);
@@ -6762,40 +6822,40 @@ function taskArtifacts(projectRoot, taskId) {
6762
6822
  throw new Error("No active task.");
6763
6823
  }
6764
6824
  const paths = resolveHarnessPaths(projectRoot);
6765
- const artifactDir = resolve22(paths.artifactsDir, activeTask);
6766
- mkdirSync11(artifactDir, { recursive: true });
6825
+ const artifactDir = resolve23(paths.artifactsDir, activeTask);
6826
+ mkdirSync12(artifactDir, { recursive: true });
6767
6827
  const changed = changedFilesForTask(projectRoot, activeTask, true);
6768
- writeFileSync11(resolve22(artifactDir, "changed-files.txt"), `${changed.join(`
6828
+ writeFileSync12(resolve23(artifactDir, "changed-files.txt"), `${changed.join(`
6769
6829
  `)}
6770
6830
  `, "utf-8");
6771
6831
  console.log(`changed-files.txt: ${changed.length} files`);
6772
- const taskResultPath = resolve22(artifactDir, "task-result.json");
6773
- if (!existsSync19(taskResultPath)) {
6832
+ const taskResultPath = resolve23(artifactDir, "task-result.json");
6833
+ if (!existsSync21(taskResultPath)) {
6774
6834
  const template = {
6775
6835
  task_id: activeTask,
6776
6836
  status: "completed",
6777
6837
  summary: "TODO: Write a one-line summary of what you did",
6778
6838
  completed_at: nowIso()
6779
6839
  };
6780
- writeFileSync11(taskResultPath, `${JSON.stringify(template, null, 2)}
6840
+ writeFileSync12(taskResultPath, `${JSON.stringify(template, null, 2)}
6781
6841
  `, "utf-8");
6782
6842
  console.log("task-result.json: created (update the summary!)");
6783
6843
  } else {
6784
6844
  console.log("task-result.json: already exists");
6785
6845
  }
6786
- const decisionLogPath = resolve22(artifactDir, "decision-log.md");
6787
- if (!existsSync19(decisionLogPath)) {
6846
+ const decisionLogPath = resolve23(artifactDir, "decision-log.md");
6847
+ if (!existsSync21(decisionLogPath)) {
6788
6848
  const content = `# Decision Log: ${activeTask}
6789
6849
 
6790
6850
  Record key decisions here using: rig-agent record decision "..."
6791
6851
  `;
6792
- writeFileSync11(decisionLogPath, content, "utf-8");
6852
+ writeFileSync12(decisionLogPath, content, "utf-8");
6793
6853
  console.log("decision-log.md: created (record your decisions!)");
6794
6854
  } else {
6795
6855
  console.log("decision-log.md: already exists");
6796
6856
  }
6797
- const nextActionsPath = resolve22(artifactDir, "next-actions.md");
6798
- if (!existsSync19(nextActionsPath)) {
6857
+ const nextActionsPath = resolve23(artifactDir, "next-actions.md");
6858
+ if (!existsSync21(nextActionsPath)) {
6799
6859
  const content = [
6800
6860
  `# Next Actions: ${activeTask}`,
6801
6861
  "",
@@ -6812,13 +6872,13 @@ Record key decisions here using: rig-agent record decision "..."
6812
6872
  ""
6813
6873
  ].join(`
6814
6874
  `);
6815
- writeFileSync11(nextActionsPath, content, "utf-8");
6875
+ writeFileSync12(nextActionsPath, content, "utf-8");
6816
6876
  console.log("next-actions.md: created (add recommendations for downstream tasks!)");
6817
6877
  } else {
6818
6878
  console.log("next-actions.md: already exists");
6819
6879
  }
6820
- const validationSummaryPath = resolve22(artifactDir, "validation-summary.json");
6821
- if (existsSync19(validationSummaryPath)) {
6880
+ const validationSummaryPath = resolve23(artifactDir, "validation-summary.json");
6881
+ if (existsSync21(validationSummaryPath)) {
6822
6882
  console.log("validation-summary.json: already exists");
6823
6883
  } else {
6824
6884
  console.log("validation-summary.json: not yet created (run: rig-agent validate)");
@@ -6884,7 +6944,7 @@ function collectTaskChangedFiles(projectRoot, taskId, includeCommitted) {
6884
6944
  [projectRoot, ""],
6885
6945
  [monorepoRepoRoot, ""]
6886
6946
  ]) {
6887
- if (!existsSync19(resolve22(repo, ".git"))) {
6947
+ if (!existsSync21(resolve23(repo, ".git"))) {
6888
6948
  continue;
6889
6949
  }
6890
6950
  if (includeCommitted && repo === monorepoRepoRoot) {
@@ -6909,12 +6969,22 @@ function filterTaskChangedFiles(projectRoot, taskId, files, scoped) {
6909
6969
  }
6910
6970
  function resolveTaskMonorepoRoot(projectRoot) {
6911
6971
  const runtimeWorkspace = loadRuntimeContextFromEnv()?.workspaceDir || process.env.RIG_TASK_WORKSPACE?.trim();
6912
- if (runtimeWorkspace && existsSync19(resolve22(runtimeWorkspace, ".git"))) {
6913
- return resolve22(runtimeWorkspace);
6972
+ if (runtimeWorkspace && existsSync21(resolve23(runtimeWorkspace, ".git"))) {
6973
+ return resolve23(runtimeWorkspace);
6914
6974
  }
6915
6975
  return resolveHarnessPaths(projectRoot).monorepoRoot;
6916
6976
  }
6917
6977
  function collectCommittedMonorepoFiles(projectRoot, repo) {
6978
+ const defaultRef = runCapture(["git", "-C", repo, "rev-parse", "--abbrev-ref", "origin/HEAD"], projectRoot);
6979
+ if (defaultRef.exitCode === 0 && defaultRef.stdout.trim()) {
6980
+ const mergeBase = runCapture(["git", "-C", repo, "merge-base", "HEAD", defaultRef.stdout.trim()], projectRoot);
6981
+ if (mergeBase.exitCode === 0 && mergeBase.stdout.trim()) {
6982
+ const result = runCapture(["git", "-C", repo, "diff", "--name-only", `${mergeBase.stdout.trim()}..HEAD`], projectRoot);
6983
+ if (result.exitCode === 0) {
6984
+ return result.stdout.split(/\r?\n/).map((line) => line.trim()).filter(Boolean);
6985
+ }
6986
+ }
6987
+ }
6918
6988
  const initialHeadCommit = resolveRuntimeInitialHeadCommit(projectRoot, repo);
6919
6989
  if (initialHeadCommit) {
6920
6990
  const result = runCapture(["git", "-C", repo, "diff", "--name-only", `${initialHeadCommit}..HEAD`], projectRoot);
@@ -6938,7 +7008,7 @@ function resolveRuntimeInitialHeadCommit(projectRoot, repo) {
6938
7008
  const runtimeContext = loadRuntimeContextFromEnv();
6939
7009
  if (runtimeContext?.initialHeadCommits?.monorepo?.trim()) {
6940
7010
  const monorepoRoot = resolveTaskMonorepoRoot(projectRoot);
6941
- if (resolve22(monorepoRoot) === resolve22(repo)) {
7011
+ if (resolve23(monorepoRoot) === resolve23(repo)) {
6942
7012
  return runtimeContext.initialHeadCommits.monorepo.trim();
6943
7013
  }
6944
7014
  }
@@ -6948,7 +7018,7 @@ function resolveMonorepoBaseCommit(projectRoot, repo) {
6948
7018
  const runtimeContext = loadRuntimeContextFromEnv();
6949
7019
  if (runtimeContext?.monorepoBaseCommit?.trim()) {
6950
7020
  const monorepoRoot = resolveTaskMonorepoRoot(projectRoot);
6951
- if (resolve22(monorepoRoot) === resolve22(repo)) {
7021
+ if (resolve23(monorepoRoot) === resolve23(repo)) {
6952
7022
  return runtimeContext.monorepoBaseCommit.trim();
6953
7023
  }
6954
7024
  }
@@ -6993,7 +7063,7 @@ function resolveRuntimeDirtyBaseline(projectRoot, repo) {
6993
7063
  return new Set;
6994
7064
  }
6995
7065
  const monorepoRoot = resolveTaskMonorepoRoot(projectRoot);
6996
- const selected = resolve22(repo) === resolve22(monorepoRoot) ? dirtyFiles.monorepo : resolve22(repo) === resolve22(projectRoot) ? dirtyFiles.project : undefined;
7066
+ const selected = resolve23(repo) === resolve23(monorepoRoot) ? dirtyFiles.monorepo : resolve23(repo) === resolve23(projectRoot) ? dirtyFiles.project : undefined;
6997
7067
  return new Set((selected || []).map((file) => normalizeChangedFilePath(file)).filter(Boolean));
6998
7068
  }
6999
7069
  function normalizeChangedFilePath(file) {
@@ -7051,8 +7121,8 @@ function isRuntimeGatewayGhPath(candidate) {
7051
7121
  }
7052
7122
  function resolveOptionalMonorepoRoot(projectRoot) {
7053
7123
  const runtimeWorkspace = process.env.RIG_TASK_WORKSPACE?.trim();
7054
- if (runtimeWorkspace && existsSync20(resolve23(runtimeWorkspace, ".git"))) {
7055
- return resolve23(runtimeWorkspace);
7124
+ if (runtimeWorkspace && existsSync22(resolve24(runtimeWorkspace, ".git"))) {
7125
+ return resolve24(runtimeWorkspace);
7056
7126
  }
7057
7127
  try {
7058
7128
  return resolveMonorepoRoot2(projectRoot);
@@ -7077,7 +7147,7 @@ function resolveGitBinary(projectRoot) {
7077
7147
  if (!candidate || isRuntimeGatewayGitPath(candidate)) {
7078
7148
  continue;
7079
7149
  }
7080
- if (existsSync20(candidate)) {
7150
+ if (existsSync22(candidate)) {
7081
7151
  return candidate;
7082
7152
  }
7083
7153
  }
@@ -7104,7 +7174,7 @@ function gitSyncBranch(projectRoot, taskId, targetRepo = "monorepo") {
7104
7174
  }
7105
7175
  const repoRoot = targetRepo === "monorepo" ? resolveOptionalMonorepoRoot(projectRoot) || resolveMonorepoRoot2(projectRoot) : projectRoot;
7106
7176
  const repoLabel = targetRepo === "monorepo" ? "Monorepo" : "Project";
7107
- if (!existsSync20(resolve23(repoRoot, ".git"))) {
7177
+ if (!existsSync22(resolve24(repoRoot, ".git"))) {
7108
7178
  throw new Error(`${repoLabel} repo not found at ${repoRoot}`);
7109
7179
  }
7110
7180
  const branchId = resolveTaskBranchId(projectRoot, resolvedTask);
@@ -7164,7 +7234,7 @@ function gitOpenPr(options) {
7164
7234
  } else if (taskId) {
7165
7235
  gitSyncBranch(options.projectRoot, taskId, "project");
7166
7236
  }
7167
- if (!existsSync20(resolve23(repoRoot, ".git"))) {
7237
+ if (!existsSync22(resolve24(repoRoot, ".git"))) {
7168
7238
  throw new Error(`Repository not available for open-pr target ${target}: ${repoRoot}`);
7169
7239
  }
7170
7240
  const branch = branchName(options.projectRoot, repoRoot);
@@ -7397,7 +7467,7 @@ function gitMergePr(options) {
7397
7467
  }
7398
7468
  const repoRoot = resolveRepoRoot(options.projectRoot, options.pr.target);
7399
7469
  const repoNameWithOwner = resolveRepoNameWithOwner(options.projectRoot, repoRoot);
7400
- if (!existsSync20(resolve23(repoRoot, ".git"))) {
7470
+ if (!existsSync22(resolve24(repoRoot, ".git"))) {
7401
7471
  throw new Error(`Repository not available for merge-pr target ${options.pr.target}: ${repoRoot}`);
7402
7472
  }
7403
7473
  const prState = readPrViewState(gh, repoRoot, repoNameWithOwner, options.pr.url);
@@ -7458,12 +7528,12 @@ function assertPrHasNoGitConflicts(prState, repoLabel, baseRef) {
7458
7528
  }
7459
7529
  function writePrMetadata(projectRoot, taskId, result) {
7460
7530
  const dir = artifactDirForId(projectRoot, taskId);
7461
- mkdirSync12(dir, { recursive: true });
7462
- const path = resolve23(dir, "pr-state.json");
7531
+ mkdirSync13(dir, { recursive: true });
7532
+ const path = resolve24(dir, "pr-state.json");
7463
7533
  let prs = {};
7464
- if (existsSync20(path)) {
7534
+ if (existsSync22(path)) {
7465
7535
  try {
7466
- const parsed = JSON.parse(readFileSync12(path, "utf-8"));
7536
+ const parsed = JSON.parse(readFileSync13(path, "utf-8"));
7467
7537
  if (parsed && typeof parsed === "object" && parsed.prs && typeof parsed.prs === "object") {
7468
7538
  prs = parsed.prs;
7469
7539
  }
@@ -7479,16 +7549,16 @@ function writePrMetadata(projectRoot, taskId, result) {
7479
7549
  ...primary || {},
7480
7550
  updated_at: nowIso()
7481
7551
  };
7482
- writeFileSync12(path, `${JSON.stringify(artifact, null, 2)}
7552
+ writeFileSync13(path, `${JSON.stringify(artifact, null, 2)}
7483
7553
  `, "utf-8");
7484
7554
  }
7485
7555
  function readPrMetadata(projectRoot, taskId) {
7486
- const path = resolve23(artifactDirForId(projectRoot, taskId), "pr-state.json");
7487
- if (!existsSync20(path)) {
7556
+ const path = resolve24(artifactDirForId(projectRoot, taskId), "pr-state.json");
7557
+ if (!existsSync22(path)) {
7488
7558
  return [];
7489
7559
  }
7490
7560
  try {
7491
- const parsed = JSON.parse(readFileSync12(path, "utf-8"));
7561
+ const parsed = JSON.parse(readFileSync13(path, "utf-8"));
7492
7562
  if (!parsed || typeof parsed !== "object") {
7493
7563
  return [];
7494
7564
  }
@@ -7560,14 +7630,14 @@ function resolveGithubCliBinary(projectRoot) {
7560
7630
  }
7561
7631
  const explicitPathEntries = (process.env.PATH || "").split(":").map((entry) => entry.trim()).filter(Boolean);
7562
7632
  for (const entry of explicitPathEntries) {
7563
- candidates.add(resolve23(entry, "gh"));
7633
+ candidates.add(resolve24(entry, "gh"));
7564
7634
  }
7565
7635
  const bunResolved = Bun.which("gh");
7566
7636
  if (bunResolved) {
7567
7637
  candidates.add(bunResolved);
7568
7638
  }
7569
7639
  for (const candidate of candidates) {
7570
- if (candidate && existsSync20(candidate) && !isRuntimeGatewayGhPath(candidate)) {
7640
+ if (candidate && existsSync22(candidate) && !isRuntimeGatewayGhPath(candidate)) {
7571
7641
  return candidate;
7572
7642
  }
7573
7643
  }
@@ -7597,7 +7667,7 @@ function resolveRepoNameWithOwner(projectRoot, repoRoot) {
7597
7667
  return resolveGithubRepoNameWithOwnerFromGitRoot(projectRoot, repoRoot, repoRoot, visited);
7598
7668
  }
7599
7669
  function resolveGithubRepoNameWithOwnerFromGitRoot(projectRoot, gitRoot, cwd, visited) {
7600
- const normalizedGitRoot = resolve23(gitRoot);
7670
+ const normalizedGitRoot = resolve24(gitRoot);
7601
7671
  if (visited.has(normalizedGitRoot)) {
7602
7672
  return "";
7603
7673
  }
@@ -7669,7 +7739,7 @@ function resolveNetworkRemoteName(projectRoot, repoRoot, repoNameWithOwner) {
7669
7739
  return remotes.includes("origin") ? "origin" : remotes[0];
7670
7740
  }
7671
7741
  function gitQuery(projectRoot, gitRoot, cwd, ...args) {
7672
- const gitArgs = existsSync20(resolve23(gitRoot, ".git")) ? gitCmd(projectRoot, gitRoot, ...args) : [resolveGitBinary(projectRoot), "--git-dir", gitRoot, ...args];
7742
+ const gitArgs = existsSync22(resolve24(gitRoot, ".git")) ? gitCmd(projectRoot, gitRoot, ...args) : [resolveGitBinary(projectRoot), "--git-dir", gitRoot, ...args];
7673
7743
  return runCapture2(gitArgs, cwd, projectRoot);
7674
7744
  }
7675
7745
  function resolveLocalGitRemoteRoot(remoteUrl, gitRoot) {
@@ -7687,9 +7757,9 @@ function resolveLocalGitRemoteRoot(remoteUrl, gitRoot) {
7687
7757
  } else if (/^[a-z][a-z0-9+.-]*:\/\//i.test(normalized) || /^[^@]+@[^:]+:.+$/.test(normalized)) {
7688
7758
  return "";
7689
7759
  } else if (!isAbsolute2(normalized)) {
7690
- candidate = resolve23(gitRoot, normalized);
7760
+ candidate = resolve24(gitRoot, normalized);
7691
7761
  }
7692
- return existsSync20(candidate) ? candidate : "";
7762
+ return existsSync22(candidate) ? candidate : "";
7693
7763
  }
7694
7764
  function normalizeGithubRepoNameWithOwner(value) {
7695
7765
  const normalized = value.trim();
@@ -7816,7 +7886,7 @@ function inferReviewerFromChangedFiles(projectRoot, repoRoot, baseRef, branchRef
7816
7886
  return best;
7817
7887
  }
7818
7888
  function commitRepo(projectRoot, repo, label, message, allowEmpty, scoped, files, changedFilesManifest) {
7819
- if (!existsSync20(resolve23(repo, ".git"))) {
7889
+ if (!existsSync22(resolve24(repo, ".git"))) {
7820
7890
  console.log(`Skipping ${label}: repo not available (${repo})`);
7821
7891
  return;
7822
7892
  }
@@ -7848,18 +7918,18 @@ function commitRepo(projectRoot, repo, label, message, allowEmpty, scoped, files
7848
7918
  console.log(`Committed ${label}: ${message}`);
7849
7919
  }
7850
7920
  function readChangedFilesManifest(projectRoot, taskId) {
7851
- const manifestPath = resolve23(artifactDirForId(projectRoot, taskId), "changed-files.txt");
7852
- if (!existsSync20(manifestPath)) {
7921
+ const manifestPath = resolve24(artifactDirForId(projectRoot, taskId), "changed-files.txt");
7922
+ if (!existsSync22(manifestPath)) {
7853
7923
  return [];
7854
7924
  }
7855
- const files = readFileSync12(manifestPath, "utf-8").split(/\r?\n/).map((line) => normalizeChangedFilePath2(line)).filter(Boolean);
7925
+ const files = readFileSync13(manifestPath, "utf-8").split(/\r?\n/).map((line) => normalizeChangedFilePath2(line)).filter(Boolean);
7856
7926
  return [...new Set(files)];
7857
7927
  }
7858
7928
  function refreshChangedFilesManifest(projectRoot, taskId) {
7859
- const manifestPath = resolve23(artifactDirForId(projectRoot, taskId), "changed-files.txt");
7860
- mkdirSync12(dirname10(manifestPath), { recursive: true });
7929
+ const manifestPath = resolve24(artifactDirForId(projectRoot, taskId), "changed-files.txt");
7930
+ mkdirSync13(dirname11(manifestPath), { recursive: true });
7861
7931
  const changedFiles = changedFilesForTask(projectRoot, taskId, true);
7862
- writeFileSync12(manifestPath, `${changedFiles.join(`
7932
+ writeFileSync13(manifestPath, `${changedFiles.join(`
7863
7933
  `)}
7864
7934
  `, "utf-8");
7865
7935
  return manifestPath;
@@ -7972,7 +8042,7 @@ function repoHasPathChange(projectRoot, repoRoot, relativePath) {
7972
8042
  return result.exitCode === 0 && result.stdout.trim().length > 0;
7973
8043
  }
7974
8044
  function stageExcludePathspecs(repoRoot) {
7975
- const patterns = existsSync20(resolve23(repoRoot, ".rig", "task-config.json")) ? [...TASK_RUNTIME_STAGE_EXCLUDES, ...GENERATED_STAGE_EXCLUDES] : [".rig/**", ...GENERATED_STAGE_EXCLUDES];
8045
+ const patterns = existsSync22(resolve24(repoRoot, ".rig", "task-config.json")) ? [...TASK_RUNTIME_STAGE_EXCLUDES, ...GENERATED_STAGE_EXCLUDES] : [".rig/**", ...GENERATED_STAGE_EXCLUDES];
7976
8046
  return patterns.map((pattern) => `:(glob,exclude)${pattern}`);
7977
8047
  }
7978
8048
  function pathResolvesBeyondSymlink(repoRoot, relativePath) {
@@ -7982,7 +8052,7 @@ function pathResolvesBeyondSymlink(repoRoot, relativePath) {
7982
8052
  }
7983
8053
  let current = repoRoot;
7984
8054
  for (let index = 0;index < parts.length - 1; index += 1) {
7985
- current = resolve23(current, parts[index]);
8055
+ current = resolve24(current, parts[index]);
7986
8056
  try {
7987
8057
  if (lstatSync(current).isSymbolicLink()) {
7988
8058
  return true;
@@ -8016,7 +8086,7 @@ function resolveTaskBranchId(projectRoot, taskId) {
8016
8086
  }
8017
8087
  } catch {}
8018
8088
  const artifactDir = artifactDirForId(projectRoot, taskId);
8019
- if (existsSync20(artifactDir)) {
8089
+ if (existsSync22(artifactDir)) {
8020
8090
  return taskId;
8021
8091
  }
8022
8092
  throw new Error(`Unknown task id: ${taskId}`);
@@ -8052,11 +8122,11 @@ function runCapture2(command, cwd, projectRoot = cwd) {
8052
8122
  }
8053
8123
  function runtimeGitEnv(projectRoot) {
8054
8124
  const { ctx, runtimeRoot } = resolveRuntimeMetadata(projectRoot);
8055
- const runtimeHome = runtimeRoot ? resolve23(runtimeRoot, "home") : "";
8056
- const runtimeTmp = runtimeRoot ? resolve23(runtimeRoot, "tmp") : "";
8057
- const runtimeCache = runtimeRoot ? resolve23(runtimeRoot, "cache") : "";
8058
- const runtimeKnownHosts = runtimeHome ? resolve23(runtimeHome, ".ssh", "known_hosts") : "";
8059
- const runtimeKey = runtimeHome ? resolve23(runtimeHome, ".ssh", "rig-agent-key") : "";
8125
+ const runtimeHome = runtimeRoot ? resolve24(runtimeRoot, "home") : "";
8126
+ const runtimeTmp = runtimeRoot ? resolve24(runtimeRoot, "tmp") : "";
8127
+ const runtimeCache = runtimeRoot ? resolve24(runtimeRoot, "cache") : "";
8128
+ const runtimeKnownHosts = runtimeHome ? resolve24(runtimeHome, ".ssh", "known_hosts") : "";
8129
+ const runtimeKey = runtimeHome ? resolve24(runtimeHome, ".ssh", "rig-agent-key") : "";
8060
8130
  const env = {};
8061
8131
  if (ctx?.workspaceDir) {
8062
8132
  env.PROJECT_RIG_ROOT = projectRoot;
@@ -8069,14 +8139,14 @@ function runtimeGitEnv(projectRoot) {
8069
8139
  if (runtimeRoot) {
8070
8140
  env.RIG_RUNTIME_HOME = runtimeRoot;
8071
8141
  }
8072
- if (runtimeHome && existsSync20(runtimeHome)) {
8142
+ if (runtimeHome && existsSync22(runtimeHome)) {
8073
8143
  env.HOME = runtimeHome;
8074
8144
  env.OPENSSL_CONF = ensureRuntimeOpenSslConfig(runtimeHome);
8075
8145
  }
8076
- if (runtimeTmp && existsSync20(runtimeTmp)) {
8146
+ if (runtimeTmp && existsSync22(runtimeTmp)) {
8077
8147
  env.TMPDIR = runtimeTmp;
8078
8148
  }
8079
- if (runtimeCache && existsSync20(runtimeCache)) {
8149
+ if (runtimeCache && existsSync22(runtimeCache)) {
8080
8150
  env.XDG_CACHE_HOME = runtimeCache;
8081
8151
  }
8082
8152
  const workspaceSecrets = loadDotEnvSecrets(ctx?.workspaceDir || projectRoot, process.env);
@@ -8120,14 +8190,14 @@ function runtimeGitEnv(projectRoot) {
8120
8190
  env.GH_TOKEN = env.GH_TOKEN || gitHubToken;
8121
8191
  applyGitHubCredentialHelperEnv(env);
8122
8192
  }
8123
- if (runtimeKnownHosts && existsSync20(runtimeKnownHosts)) {
8193
+ if (runtimeKnownHosts && existsSync22(runtimeKnownHosts)) {
8124
8194
  const sshParts = [
8125
8195
  "ssh",
8126
8196
  `-o UserKnownHostsFile="${runtimeKnownHosts}"`,
8127
8197
  "-o StrictHostKeyChecking=yes",
8128
8198
  "-F /dev/null"
8129
8199
  ];
8130
- if (runtimeKey && existsSync20(runtimeKey)) {
8200
+ if (runtimeKey && existsSync22(runtimeKey)) {
8131
8201
  sshParts.splice(1, 0, `-i "${runtimeKey}"`, "-o IdentitiesOnly=yes");
8132
8202
  }
8133
8203
  env.GIT_SSH_COMMAND = sshParts.join(" ");
@@ -8148,12 +8218,12 @@ function loadPersistedRuntimeSecrets(runtimeRoot) {
8148
8218
  if (!runtimeRoot) {
8149
8219
  return {};
8150
8220
  }
8151
- const path = resolve23(runtimeRoot, "runtime-secrets.json");
8152
- if (!existsSync20(path)) {
8221
+ const path = resolve24(runtimeRoot, "runtime-secrets.json");
8222
+ if (!existsSync22(path)) {
8153
8223
  return {};
8154
8224
  }
8155
8225
  try {
8156
- const parsed = JSON.parse(readFileSync12(path, "utf-8"));
8226
+ const parsed = JSON.parse(readFileSync13(path, "utf-8"));
8157
8227
  const entries = Object.entries(parsed).filter((entry) => typeof entry[1] === "string");
8158
8228
  return Object.fromEntries(entries);
8159
8229
  } catch {
@@ -8161,13 +8231,13 @@ function loadPersistedRuntimeSecrets(runtimeRoot) {
8161
8231
  }
8162
8232
  }
8163
8233
  function ensureRuntimeOpenSslConfig(runtimeHome) {
8164
- const sslDir = resolve23(runtimeHome, ".ssl");
8165
- const sslConfig = resolve23(sslDir, "openssl.cnf");
8166
- if (!existsSync20(sslDir)) {
8167
- mkdirSync12(sslDir, { recursive: true });
8234
+ const sslDir = resolve24(runtimeHome, ".ssl");
8235
+ const sslConfig = resolve24(sslDir, "openssl.cnf");
8236
+ if (!existsSync22(sslDir)) {
8237
+ mkdirSync13(sslDir, { recursive: true });
8168
8238
  }
8169
- if (!existsSync20(sslConfig)) {
8170
- writeFileSync12(sslConfig, `# Rig runtime OpenSSL config placeholder
8239
+ if (!existsSync22(sslConfig)) {
8240
+ writeFileSync13(sslConfig, `# Rig runtime OpenSSL config placeholder
8171
8241
  `);
8172
8242
  }
8173
8243
  return sslConfig;
@@ -8185,29 +8255,29 @@ function resolveRuntimeMetadata(projectRoot) {
8185
8255
  if (contextFile) {
8186
8256
  return {
8187
8257
  ctx,
8188
- runtimeRoot: dirname10(resolve23(contextFile))
8258
+ runtimeRoot: dirname11(resolve24(contextFile))
8189
8259
  };
8190
8260
  }
8191
8261
  const inferredContextFile = findRuntimeContextFile2(projectRoot);
8192
- if (existsSync20(inferredContextFile)) {
8262
+ if (existsSync22(inferredContextFile)) {
8193
8263
  try {
8194
8264
  ctx = loadRuntimeContext(inferredContextFile);
8195
8265
  } catch {}
8196
8266
  return {
8197
8267
  ctx,
8198
- runtimeRoot: dirname10(inferredContextFile)
8268
+ runtimeRoot: dirname11(inferredContextFile)
8199
8269
  };
8200
8270
  }
8201
8271
  return { ctx, runtimeRoot: "" };
8202
8272
  }
8203
8273
  function findRuntimeContextFile2(startPath) {
8204
- let current = resolve23(startPath);
8274
+ let current = resolve24(startPath);
8205
8275
  while (true) {
8206
- const candidate = resolve23(current, "runtime-context.json");
8207
- if (existsSync20(candidate)) {
8276
+ const candidate = resolve24(current, "runtime-context.json");
8277
+ if (existsSync22(candidate)) {
8208
8278
  return candidate;
8209
8279
  }
8210
- const parent = dirname10(current);
8280
+ const parent = dirname11(current);
8211
8281
  if (parent === current) {
8212
8282
  return "";
8213
8283
  }
@@ -8443,9 +8513,9 @@ async function main() {
8443
8513
  console.log(`
8444
8514
  [post] Auto-merge: skipped (not in policy completion.checks)`);
8445
8515
  }
8446
- const artifactDir = resolve24(paths.artifactsDir, taskId);
8447
- mkdirSync13(artifactDir, { recursive: true });
8448
- writeFileSync13(resolve24(artifactDir, "review-status.txt"), failed ? `REJECTED
8516
+ const artifactDir = resolve25(paths.artifactsDir, taskId);
8517
+ mkdirSync14(artifactDir, { recursive: true });
8518
+ writeFileSync14(resolve25(artifactDir, "review-status.txt"), failed ? `REJECTED
8449
8519
  ` : `APPROVED
8450
8520
  `, "utf-8");
8451
8521
  if (!failed) {
@@ -8492,8 +8562,8 @@ async function runBunTool(args, cwd) {
8492
8562
  };
8493
8563
  }
8494
8564
  async function runProtoQualityGate(monorepoRoot) {
8495
- const protosDir = resolve24(monorepoRoot, "packages", "protos");
8496
- if (!existsSync21(protosDir)) {
8565
+ const protosDir = resolve25(monorepoRoot, "packages", "protos");
8566
+ if (!existsSync23(protosDir)) {
8497
8567
  console.log(`FAIL: Proto workspace not found at ${protosDir}`);
8498
8568
  return false;
8499
8569
  }
@@ -8541,12 +8611,12 @@ async function runProtoQualityGate(monorepoRoot) {
8541
8611
  } else {
8542
8612
  console.log("OK: Generated TypeScript compiles");
8543
8613
  }
8544
- const workflowPath = resolve24(monorepoRoot, ".github", "workflows", "pull-request-gate.yml");
8545
- if (!existsSync21(workflowPath)) {
8614
+ const workflowPath = resolve25(monorepoRoot, ".github", "workflows", "pull-request-gate.yml");
8615
+ if (!existsSync23(workflowPath)) {
8546
8616
  console.log(`FAIL: Missing workflow gate file at ${workflowPath}`);
8547
8617
  ok = false;
8548
8618
  } else {
8549
- const workflow = readFileSync13(workflowPath, "utf-8");
8619
+ const workflow = readFileSync14(workflowPath, "utf-8");
8550
8620
  if (workflow.includes("if: false && needs.detect.outputs.protos_changed == 'true'")) {
8551
8621
  console.log("FAIL: Proto quality CI gate is disabled in pull-request-gate.yml");
8552
8622
  ok = false;
@@ -8575,7 +8645,7 @@ function repoHasPublishedTaskBranch(projectRoot, repoRoot, taskId) {
8575
8645
  return runCapture(["git", "-C", repoRoot, "ls-remote", "--exit-code", "origin", `refs/heads/${branchRef}`], projectRoot).exitCode === 0;
8576
8646
  }
8577
8647
  async function readJsonFileIfPresent(path) {
8578
- if (!existsSync21(path)) {
8648
+ if (!existsSync23(path)) {
8579
8649
  return null;
8580
8650
  }
8581
8651
  try {
@@ -8586,9 +8656,9 @@ async function readJsonFileIfPresent(path) {
8586
8656
  }
8587
8657
  async function recordVerifierFailure(projectRoot, taskId, paths) {
8588
8658
  const failedApproachesPath = paths.failedApproachesPath;
8589
- const artifactDir = resolve24(paths.artifactsDir, taskId);
8590
- const reviewStatePath = resolve24(artifactDir, "review-state.json");
8591
- const reviewFeedbackPath = resolve24(artifactDir, "review-feedback.md");
8659
+ const artifactDir = resolve25(paths.artifactsDir, taskId);
8660
+ const reviewStatePath = resolve25(artifactDir, "review-state.json");
8661
+ const reviewFeedbackPath = resolve25(artifactDir, "review-feedback.md");
8592
8662
  let summary = "Verifier rejected completion. Read review-feedback.md for required fixes.";
8593
8663
  const parsedReviewState = await readJsonFileIfPresent(reviewStatePath);
8594
8664
  if (parsedReviewState) {
@@ -8598,12 +8668,12 @@ async function recordVerifierFailure(projectRoot, taskId, paths) {
8598
8668
  }
8599
8669
  }
8600
8670
  let attempts = 1;
8601
- if (existsSync21(failedApproachesPath)) {
8602
- const content = readFileSync13(failedApproachesPath, "utf-8");
8671
+ if (existsSync23(failedApproachesPath)) {
8672
+ const content = readFileSync14(failedApproachesPath, "utf-8");
8603
8673
  attempts = (content.match(new RegExp(`^## ${escapeRegExp2(taskId)}\\b`, "gm")) || []).length + 1;
8604
8674
  } else {
8605
- mkdirSync13(resolve24(failedApproachesPath, ".."), { recursive: true });
8606
- writeFileSync13(failedApproachesPath, `# Failed Approaches
8675
+ mkdirSync14(resolve25(failedApproachesPath, ".."), { recursive: true });
8676
+ writeFileSync14(failedApproachesPath, `# Failed Approaches
8607
8677
 
8608
8678
  `, "utf-8");
8609
8679
  }
@@ -8641,8 +8711,8 @@ async function recordTaskRepoCommits(projectRoot, taskId, paths) {
8641
8711
  recorded_at: new Date().toISOString(),
8642
8712
  repos
8643
8713
  };
8644
- mkdirSync13(resolve24(statePath, ".."), { recursive: true });
8645
- writeFileSync13(statePath, `${JSON.stringify(state, null, 2)}
8714
+ mkdirSync14(resolve25(statePath, ".."), { recursive: true });
8715
+ writeFileSync14(statePath, `${JSON.stringify(state, null, 2)}
8646
8716
  `, "utf-8");
8647
8717
  }
8648
8718
  }