@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.
@@ -1,7 +1,7 @@
1
1
  // @bun
2
2
  // packages/runtime/src/control-plane/native/verifier.ts
3
- import { existsSync as existsSync12, mkdirSync as mkdirSync6, writeFileSync as writeFileSync7 } from "fs";
4
- import { resolve as resolve14 } from "path";
3
+ import { existsSync as existsSync14, mkdirSync as mkdirSync7, writeFileSync as writeFileSync8 } from "fs";
4
+ import { resolve as resolve15 } from "path";
5
5
 
6
6
  // packages/runtime/src/control-plane/runtime/baked-secrets.ts
7
7
  var BAKED_RUNTIME_SECRETS = {
@@ -47,8 +47,8 @@ function resolveRuntimeSecrets(env, baked = BAKED_RUNTIME_SECRETS) {
47
47
  }
48
48
 
49
49
  // packages/runtime/src/control-plane/native/git-ops.ts
50
- import { existsSync as existsSync11, lstatSync, mkdirSync as mkdirSync5, readFileSync as readFileSync8, writeFileSync as writeFileSync6 } from "fs";
51
- import { dirname as dirname8, isAbsolute as isAbsolute2, resolve as resolve13 } from "path";
50
+ import { existsSync as existsSync13, lstatSync, mkdirSync as mkdirSync6, readFileSync as readFileSync9, writeFileSync as writeFileSync7 } from "fs";
51
+ import { dirname as dirname9, isAbsolute as isAbsolute2, resolve as resolve14 } from "path";
52
52
 
53
53
  // packages/runtime/src/control-plane/runtime/context.ts
54
54
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
@@ -262,6 +262,8 @@ import { basename as basename2, dirname as dirname4, resolve as resolve4 } from
262
262
  var sharedNativeToolsOutputDir = resolve4(tmpdir3(), "rig-native");
263
263
  var sharedNativeToolsOutputPath = resolve4(sharedNativeToolsOutputDir, `rig-tools-${process.platform}-${process.arch}${process.platform === "win32" ? ".exe" : ""}`);
264
264
  // packages/runtime/src/control-plane/plugin-host-context.ts
265
+ import { existsSync as existsSync6 } from "fs";
266
+ import { resolve as resolvePath } from "path";
265
267
  import { createPluginHost } from "@rig/core";
266
268
  import { loadConfig } from "@rig/core/load-config";
267
269
 
@@ -588,6 +590,55 @@ async function materializeSkills(projectRoot, entries) {
588
590
  return written;
589
591
  }
590
592
 
593
+ // packages/runtime/src/control-plane/pi-settings-materializer.ts
594
+ import { existsSync as existsSync5, mkdirSync as mkdirSync4, readFileSync as readFileSync4, writeFileSync as writeFileSync4 } from "fs";
595
+ import { dirname as dirname6, resolve as resolve7 } from "path";
596
+ var SETTINGS_RELATIVE_PATH = ".pi/settings.json";
597
+ var MANAGED_RECORD_RELATIVE_PATH = ".rig/state/pi-managed-packages.json";
598
+ function readJson(path, fallback) {
599
+ if (!existsSync5(path))
600
+ return fallback;
601
+ try {
602
+ return JSON.parse(readFileSync4(path, "utf-8"));
603
+ } catch {
604
+ return fallback;
605
+ }
606
+ }
607
+ function packageKey(entry) {
608
+ if (typeof entry === "string")
609
+ return entry;
610
+ if (entry && typeof entry === "object" && typeof entry.source === "string") {
611
+ return entry.source;
612
+ }
613
+ return JSON.stringify(entry);
614
+ }
615
+ function materializePiPackages(projectRoot, declaredPackages) {
616
+ const settingsPath = resolve7(projectRoot, SETTINGS_RELATIVE_PATH);
617
+ const managedRecordPath = resolve7(projectRoot, MANAGED_RECORD_RELATIVE_PATH);
618
+ const settings = readJson(settingsPath, {});
619
+ const previouslyManaged = new Set(readJson(managedRecordPath, []));
620
+ const existing = Array.isArray(settings.packages) ? settings.packages : [];
621
+ const operatorEntries = existing.filter((entry) => !previouslyManaged.has(packageKey(entry)));
622
+ const operatorKeys = new Set(operatorEntries.map(packageKey));
623
+ const managedToAdd = declaredPackages.filter((pkg) => !operatorKeys.has(pkg));
624
+ const nextPackages = [...operatorEntries, ...managedToAdd];
625
+ if (nextPackages.length > 0 || existsSync5(settingsPath)) {
626
+ const nextSettings = { ...settings };
627
+ if (nextPackages.length > 0) {
628
+ nextSettings.packages = nextPackages;
629
+ } else {
630
+ delete nextSettings.packages;
631
+ }
632
+ mkdirSync4(dirname6(settingsPath), { recursive: true });
633
+ writeFileSync4(settingsPath, `${JSON.stringify(nextSettings, null, 2)}
634
+ `, "utf-8");
635
+ }
636
+ mkdirSync4(dirname6(managedRecordPath), { recursive: true });
637
+ writeFileSync4(managedRecordPath, `${JSON.stringify(managedToAdd, null, 2)}
638
+ `, "utf-8");
639
+ return { settingsPath, packages: managedToAdd };
640
+ }
641
+
591
642
  // packages/runtime/src/control-plane/plugin-host-context.ts
592
643
  async function buildPluginHostContext(projectRoot) {
593
644
  let config;
@@ -635,6 +686,14 @@ async function buildPluginHostContext(projectRoot) {
635
686
  } catch (err) {
636
687
  console.warn(`[plugin-host] skill materialization failed: ${err instanceof Error ? err.message : err}`);
637
688
  }
689
+ try {
690
+ const piPackages = config.runtime?.pi?.packages ?? [];
691
+ if (piPackages.length > 0 || existsSync6(resolvePath(projectRoot, ".rig/state/pi-managed-packages.json"))) {
692
+ materializePiPackages(projectRoot, piPackages);
693
+ }
694
+ } catch (err) {
695
+ console.warn(`[plugin-host] Pi package materialization failed: ${err instanceof Error ? err.message : err}`);
696
+ }
638
697
  return {
639
698
  config,
640
699
  pluginHost,
@@ -648,12 +707,12 @@ async function buildPluginHostContext(projectRoot) {
648
707
 
649
708
  // packages/runtime/src/control-plane/tasks/source-aware-task-config-source.ts
650
709
  import { spawnSync } from "child_process";
651
- import { existsSync as existsSync6, readFileSync as readFileSync5, readdirSync as readdirSync2, statSync, writeFileSync as writeFileSync4 } from "fs";
652
- import { basename as basename3, join as join2, resolve as resolve8 } from "path";
710
+ import { existsSync as existsSync8, readFileSync as readFileSync6, readdirSync as readdirSync2, statSync, writeFileSync as writeFileSync5 } from "fs";
711
+ import { basename as basename3, join as join2, resolve as resolve9 } from "path";
653
712
 
654
713
  // packages/runtime/src/control-plane/tasks/legacy-task-config-source.ts
655
- import { existsSync as existsSync5, readFileSync as readFileSync4 } from "fs";
656
- import { resolve as resolve7 } from "path";
714
+ import { existsSync as existsSync7, readFileSync as readFileSync5 } from "fs";
715
+ import { resolve as resolve8 } from "path";
657
716
 
658
717
  // packages/runtime/src/control-plane/tasks/task-record-reader.ts
659
718
  async function findTaskById(reader, id) {
@@ -676,7 +735,7 @@ class LegacyTaskConfigReadError extends Error {
676
735
  }
677
736
  }
678
737
  function createLegacyTaskConfigRecordReader(projectRoot, options = {}) {
679
- const configPath = options.configPath ?? resolve7(projectRoot, ".rig", "task-config.json");
738
+ const configPath = options.configPath ?? resolve8(projectRoot, ".rig", "task-config.json");
680
739
  const reader = {
681
740
  async listTasks() {
682
741
  return readLegacyTaskRecords(projectRoot, configPath);
@@ -687,8 +746,8 @@ function createLegacyTaskConfigRecordReader(projectRoot, options = {}) {
687
746
  };
688
747
  return reader;
689
748
  }
690
- function readLegacyTaskRecords(projectRoot, configPath = resolve7(projectRoot, ".rig", "task-config.json")) {
691
- if (!existsSync5(configPath)) {
749
+ function readLegacyTaskRecords(projectRoot, configPath = resolve8(projectRoot, ".rig", "task-config.json")) {
750
+ if (!existsSync7(configPath)) {
692
751
  return [];
693
752
  }
694
753
  const rawConfig = readLegacyTaskConfigJson(projectRoot, configPath);
@@ -696,7 +755,7 @@ function readLegacyTaskRecords(projectRoot, configPath = resolve7(projectRoot, "
696
755
  }
697
756
  function readLegacyTaskConfigJson(projectRoot, configPath) {
698
757
  try {
699
- const parsed = JSON.parse(readFileSync4(configPath, "utf8"));
758
+ const parsed = JSON.parse(readFileSync5(configPath, "utf8"));
700
759
  if (isPlainRecord(parsed)) {
701
760
  return parsed;
702
761
  }
@@ -780,7 +839,7 @@ function isPlainRecord(candidate) {
780
839
  var STATUS_LABELS = new Set(["ready", "blocked", "in-progress", "under-review", "failed", "cancelled"]);
781
840
  var FILE_TASK_PATTERN = /\.(task\.)?json$/;
782
841
  function createSourceAwareTaskConfigRecordReader(projectRoot, options = {}) {
783
- const configPath = options.configPath ?? resolve8(projectRoot, ".rig", "task-config.json");
842
+ const configPath = options.configPath ?? resolve9(projectRoot, ".rig", "task-config.json");
784
843
  const legacy = createLegacyTaskConfigRecordReader(projectRoot, { configPath });
785
844
  const spawnFn = options.spawn ?? spawnSync;
786
845
  const ghBinary = options.ghBinary ?? "gh";
@@ -863,10 +922,10 @@ function readMaterializedTaskMetadata(entry) {
863
922
  return metadata;
864
923
  }
865
924
  function readConfiguredFilesTaskSourcePath(projectRoot) {
866
- const jsonPath = resolve8(projectRoot, "rig.config.json");
867
- if (existsSync6(jsonPath)) {
925
+ const jsonPath = resolve9(projectRoot, "rig.config.json");
926
+ if (existsSync8(jsonPath)) {
868
927
  try {
869
- const parsed = JSON.parse(readFileSync5(jsonPath, "utf8"));
928
+ const parsed = JSON.parse(readFileSync6(jsonPath, "utf8"));
870
929
  if (isPlainRecord2(parsed) && isPlainRecord2(parsed.taskSource)) {
871
930
  const source = parsed.taskSource;
872
931
  return source.kind === "files" && typeof source.path === "string" ? source.path : null;
@@ -875,12 +934,12 @@ function readConfiguredFilesTaskSourcePath(projectRoot) {
875
934
  return null;
876
935
  }
877
936
  }
878
- const tsPath = resolve8(projectRoot, "rig.config.ts");
879
- if (!existsSync6(tsPath)) {
937
+ const tsPath = resolve9(projectRoot, "rig.config.ts");
938
+ if (!existsSync8(tsPath)) {
880
939
  return null;
881
940
  }
882
941
  try {
883
- const source = readFileSync5(tsPath, "utf8");
942
+ const source = readFileSync6(tsPath, "utf8");
884
943
  const taskSourceBlock = source.match(/taskSource\s*:\s*\{[\s\S]*?\}/m)?.[0] ?? "";
885
944
  const kind = taskSourceBlock.match(/kind\s*:\s*["']([^"']+)["']/)?.[1];
886
945
  if (kind !== "files") {
@@ -900,10 +959,10 @@ function readRawTaskEntry(configPath, taskId) {
900
959
  return isPlainRecord2(entry) ? entry : null;
901
960
  }
902
961
  function readRawTaskConfig(configPath) {
903
- if (!existsSync6(configPath)) {
962
+ if (!existsSync8(configPath)) {
904
963
  return null;
905
964
  }
906
- const parsed = JSON.parse(readFileSync5(configPath, "utf8"));
965
+ const parsed = JSON.parse(readFileSync6(configPath, "utf8"));
907
966
  return isPlainRecord2(parsed) ? parsed : null;
908
967
  }
909
968
  function stripLegacyTaskConfigMetadata2(raw) {
@@ -911,8 +970,8 @@ function stripLegacyTaskConfigMetadata2(raw) {
911
970
  return tasks;
912
971
  }
913
972
  function listFileBackedTasks(projectRoot, sourcePath) {
914
- const directory = resolve8(projectRoot, sourcePath);
915
- if (!existsSync6(directory)) {
973
+ const directory = resolve9(projectRoot, sourcePath);
974
+ if (!existsSync8(directory)) {
916
975
  return [];
917
976
  }
918
977
  const tasks = [];
@@ -927,11 +986,11 @@ function listFileBackedTasks(projectRoot, sourcePath) {
927
986
  return tasks;
928
987
  }
929
988
  function readFileBackedTask(projectRoot, sourcePath, taskId, rawEntry) {
930
- const file = findFileBackedTaskFile(resolve8(projectRoot, sourcePath), taskId);
989
+ const file = findFileBackedTaskFile(resolve9(projectRoot, sourcePath), taskId);
931
990
  if (!file) {
932
991
  return null;
933
992
  }
934
- const raw = JSON.parse(readFileSync5(file, "utf8"));
993
+ const raw = JSON.parse(readFileSync6(file, "utf8"));
935
994
  if (!isPlainRecord2(raw)) {
936
995
  return null;
937
996
  }
@@ -944,7 +1003,7 @@ function readFileBackedTask(projectRoot, sourcePath, taskId, rawEntry) {
944
1003
  };
945
1004
  }
946
1005
  function findFileBackedTaskFile(directory, taskId) {
947
- if (!existsSync6(directory)) {
1006
+ if (!existsSync8(directory)) {
948
1007
  return null;
949
1008
  }
950
1009
  for (const name of readdirSync2(directory)) {
@@ -954,7 +1013,7 @@ function findFileBackedTaskFile(directory, taskId) {
954
1013
  try {
955
1014
  if (!statSync(file).isFile())
956
1015
  continue;
957
- const raw = JSON.parse(readFileSync5(file, "utf8"));
1016
+ const raw = JSON.parse(readFileSync6(file, "utf8"));
958
1017
  const inferredId = basename3(file).replace(FILE_TASK_PATTERN, "");
959
1018
  const id = isPlainRecord2(raw) && typeof raw.id === "string" ? raw.id : inferredId;
960
1019
  if (id === taskId) {
@@ -1114,8 +1173,8 @@ async function readConfiguredTaskSourceTask(projectRoot, taskId) {
1114
1173
  }
1115
1174
 
1116
1175
  // packages/runtime/src/control-plane/native/task-state.ts
1117
- import { existsSync as existsSync10, readFileSync as readFileSync7, readdirSync as readdirSync3, statSync as statSync3, writeFileSync as writeFileSync5 } from "fs";
1118
- import { basename as basename5, resolve as resolve12 } from "path";
1176
+ import { existsSync as existsSync12, readFileSync as readFileSync8, readdirSync as readdirSync3, statSync as statSync3, writeFileSync as writeFileSync6 } from "fs";
1177
+ import { basename as basename5, resolve as resolve13 } from "path";
1119
1178
 
1120
1179
  // packages/runtime/src/control-plane/state-sync/types.ts
1121
1180
  var CANONICAL_TASK_LIFECYCLE_STATUSES = new Set([
@@ -1130,46 +1189,46 @@ var CANONICAL_TASK_LIFECYCLE_STATUSES = new Set([
1130
1189
  "cancelled"
1131
1190
  ]);
1132
1191
  // packages/runtime/src/control-plane/native/utils.ts
1133
- import { existsSync as existsSync9, readFileSync as readFileSync6 } from "fs";
1134
- import { resolve as resolve11 } from "path";
1192
+ import { existsSync as existsSync11, readFileSync as readFileSync7 } from "fs";
1193
+ import { resolve as resolve12 } from "path";
1135
1194
 
1136
1195
  // packages/runtime/src/layout.ts
1137
- import { existsSync as existsSync7 } from "fs";
1138
- import { basename as basename4, dirname as dirname6, resolve as resolve9 } from "path";
1196
+ import { existsSync as existsSync9 } from "fs";
1197
+ import { basename as basename4, dirname as dirname7, resolve as resolve10 } from "path";
1139
1198
  var RIG_DEFINITION_DIRNAME = "rig";
1140
1199
  var RIG_ARTIFACTS_DIRNAME = "artifacts";
1141
1200
  function resolveMonorepoRoot(projectRoot) {
1142
- const normalizedProjectRoot = resolve9(projectRoot);
1201
+ const normalizedProjectRoot = resolve10(projectRoot);
1143
1202
  const explicit = process.env.MONOREPO_ROOT?.trim();
1144
1203
  if (explicit) {
1145
- const explicitRoot = resolve9(explicit);
1146
- const explicitParent = dirname6(explicitRoot);
1204
+ const explicitRoot = resolve10(explicit);
1205
+ const explicitParent = dirname7(explicitRoot);
1147
1206
  if (basename4(explicitParent) === ".worktrees") {
1148
- const owner = dirname6(explicitParent);
1149
- const ownerHasGit = existsSync7(resolve9(owner, ".git"));
1150
- const ownerHasTaskConfig = existsSync7(resolve9(owner, ".rig", "task-config.json"));
1151
- const ownerHasRigConfig = existsSync7(resolve9(owner, "rig.config.ts"));
1207
+ const owner = dirname7(explicitParent);
1208
+ const ownerHasGit = existsSync9(resolve10(owner, ".git"));
1209
+ const ownerHasTaskConfig = existsSync9(resolve10(owner, ".rig", "task-config.json"));
1210
+ const ownerHasRigConfig = existsSync9(resolve10(owner, "rig.config.ts"));
1152
1211
  if (ownerHasGit && (ownerHasTaskConfig || ownerHasRigConfig)) {
1153
1212
  return owner;
1154
1213
  }
1155
1214
  throw new Error(`MONOREPO_ROOT points to worktree ${explicitRoot}, but the owner checkout is incomplete at ${owner}.`);
1156
1215
  }
1157
- if (!existsSync7(resolve9(explicitRoot, ".git"))) {
1216
+ if (!existsSync9(resolve10(explicitRoot, ".git"))) {
1158
1217
  throw new Error(`MONOREPO_ROOT points to ${explicitRoot}, but no git checkout was found there.`);
1159
1218
  }
1160
- const hasTaskConfig = existsSync7(resolve9(explicitRoot, ".rig", "task-config.json"));
1161
- const hasRigConfig = existsSync7(resolve9(explicitRoot, "rig.config.ts"));
1219
+ const hasTaskConfig = existsSync9(resolve10(explicitRoot, ".rig", "task-config.json"));
1220
+ const hasRigConfig = existsSync9(resolve10(explicitRoot, "rig.config.ts"));
1162
1221
  if (!hasTaskConfig && !hasRigConfig) {
1163
1222
  throw new Error(`MONOREPO_ROOT points to ${explicitRoot}, but neither .rig/task-config.json nor rig.config.ts exists there.`);
1164
1223
  }
1165
1224
  return explicitRoot;
1166
1225
  }
1167
- const projectParent = dirname6(normalizedProjectRoot);
1226
+ const projectParent = dirname7(normalizedProjectRoot);
1168
1227
  if (basename4(projectParent) === ".worktrees") {
1169
- const worktreeOwner = dirname6(projectParent);
1170
- const ownerHasGit = existsSync7(resolve9(worktreeOwner, ".git"));
1171
- const ownerHasTaskConfig = existsSync7(resolve9(worktreeOwner, ".rig", "task-config.json"));
1172
- const ownerHasRigConfig = existsSync7(resolve9(worktreeOwner, "rig.config.ts"));
1228
+ const worktreeOwner = dirname7(projectParent);
1229
+ const ownerHasGit = existsSync9(resolve10(worktreeOwner, ".git"));
1230
+ const ownerHasTaskConfig = existsSync9(resolve10(worktreeOwner, ".rig", "task-config.json"));
1231
+ const ownerHasRigConfig = existsSync9(resolve10(worktreeOwner, "rig.config.ts"));
1173
1232
  if (ownerHasGit && (ownerHasTaskConfig || ownerHasRigConfig)) {
1174
1233
  return worktreeOwner;
1175
1234
  }
@@ -1177,28 +1236,28 @@ function resolveMonorepoRoot(projectRoot) {
1177
1236
  return normalizedProjectRoot;
1178
1237
  }
1179
1238
  function resolveRuntimeWorkspaceLayout(workspaceDir) {
1180
- const root = resolve9(workspaceDir);
1181
- const rigRoot = resolve9(root, ".rig");
1182
- const logsDir = resolve9(rigRoot, "logs");
1183
- const stateDir = resolve9(rigRoot, "state");
1184
- const runtimeDir = resolve9(rigRoot, "runtime");
1185
- const binDir = resolve9(rigRoot, "bin");
1239
+ const root = resolve10(workspaceDir);
1240
+ const rigRoot = resolve10(root, ".rig");
1241
+ const logsDir = resolve10(rigRoot, "logs");
1242
+ const stateDir = resolve10(rigRoot, "state");
1243
+ const runtimeDir = resolve10(rigRoot, "runtime");
1244
+ const binDir = resolve10(rigRoot, "bin");
1186
1245
  return {
1187
1246
  workspaceDir: root,
1188
1247
  rigRoot,
1189
1248
  stateDir,
1190
1249
  logsDir,
1191
- artifactsRoot: resolve9(root, RIG_ARTIFACTS_DIRNAME),
1250
+ artifactsRoot: resolve10(root, RIG_ARTIFACTS_DIRNAME),
1192
1251
  runtimeDir,
1193
- homeDir: resolve9(rigRoot, "home"),
1194
- tmpDir: resolve9(rigRoot, "tmp"),
1195
- cacheDir: resolve9(rigRoot, "cache"),
1196
- sessionDir: resolve9(rigRoot, "session"),
1252
+ homeDir: resolve10(rigRoot, "home"),
1253
+ tmpDir: resolve10(rigRoot, "tmp"),
1254
+ cacheDir: resolve10(rigRoot, "cache"),
1255
+ sessionDir: resolve10(rigRoot, "session"),
1197
1256
  binDir,
1198
- distDir: resolve9(rigRoot, "dist"),
1199
- pluginBinDir: resolve9(binDir, "plugins"),
1200
- contextPath: resolve9(rigRoot, "runtime-context.json"),
1201
- controlPlaneEventsFile: resolve9(logsDir, "control-plane.events.jsonl")
1257
+ distDir: resolve10(rigRoot, "dist"),
1258
+ pluginBinDir: resolve10(binDir, "plugins"),
1259
+ contextPath: resolve10(rigRoot, "runtime-context.json"),
1260
+ controlPlaneEventsFile: resolve10(logsDir, "control-plane.events.jsonl")
1202
1261
  };
1203
1262
  }
1204
1263
  function resolveActiveRuntimeWorkspaceRoot(monorepoRoot) {
@@ -1206,14 +1265,14 @@ function resolveActiveRuntimeWorkspaceRoot(monorepoRoot) {
1206
1265
  if (!explicit) {
1207
1266
  throw new Error("No active runtime workspace. Set RIG_TASK_WORKSPACE or provision a task runtime first.");
1208
1267
  }
1209
- return resolve9(explicit);
1268
+ return resolve10(explicit);
1210
1269
  }
1211
1270
  function resolveRigLayout(projectRoot) {
1212
1271
  const monorepoRoot = resolveMonorepoRoot(projectRoot);
1213
- const definitionRoot = resolve9(projectRoot, RIG_DEFINITION_DIRNAME);
1272
+ const definitionRoot = resolve10(projectRoot, RIG_DEFINITION_DIRNAME);
1214
1273
  const runtimeWorkspaceRoot = resolveActiveRuntimeWorkspaceRoot(monorepoRoot);
1215
1274
  const runtimeLayout = resolveRuntimeWorkspaceLayout(runtimeWorkspaceRoot);
1216
- const policyDir = resolve9(definitionRoot, "policy");
1275
+ const policyDir = resolve10(definitionRoot, "policy");
1217
1276
  return {
1218
1277
  projectRoot,
1219
1278
  monorepoRoot,
@@ -1221,48 +1280,48 @@ function resolveRigLayout(projectRoot) {
1221
1280
  runtimeWorkspaceRoot,
1222
1281
  stateRoot: runtimeLayout.rigRoot,
1223
1282
  artifactsRoot: runtimeLayout.artifactsRoot,
1224
- configPath: resolve9(definitionRoot, "config.sh"),
1225
- taskConfigPath: resolve9(runtimeWorkspaceRoot, ".rig", "task-config.json"),
1283
+ configPath: resolve10(definitionRoot, "config.sh"),
1284
+ taskConfigPath: resolve10(runtimeWorkspaceRoot, ".rig", "task-config.json"),
1226
1285
  policyDir,
1227
- policyFile: resolve9(policyDir, "policy.json"),
1228
- pluginsDir: resolve9(definitionRoot, "plugins"),
1229
- hooksDir: resolve9(definitionRoot, "hooks"),
1230
- toolsDir: resolve9(definitionRoot, "tools"),
1231
- templatesDir: resolve9(definitionRoot, "templates"),
1232
- validationDir: resolve9(definitionRoot, "validation"),
1286
+ policyFile: resolve10(policyDir, "policy.json"),
1287
+ pluginsDir: resolve10(definitionRoot, "plugins"),
1288
+ hooksDir: resolve10(definitionRoot, "hooks"),
1289
+ toolsDir: resolve10(definitionRoot, "tools"),
1290
+ templatesDir: resolve10(definitionRoot, "templates"),
1291
+ validationDir: resolve10(definitionRoot, "validation"),
1233
1292
  stateDir: runtimeLayout.stateDir,
1234
1293
  logsDir: runtimeLayout.logsDir,
1235
- notificationsDir: resolve9(definitionRoot, "notifications"),
1294
+ notificationsDir: resolve10(definitionRoot, "notifications"),
1236
1295
  runtimeDir: runtimeLayout.runtimeDir,
1237
1296
  distDir: runtimeLayout.distDir,
1238
1297
  binDir: runtimeLayout.binDir,
1239
1298
  pluginBinDir: runtimeLayout.pluginBinDir,
1240
- keybindingsPath: resolve9(definitionRoot, "keybindings.json"),
1299
+ keybindingsPath: resolve10(definitionRoot, "keybindings.json"),
1241
1300
  controlPlaneEventsFile: runtimeLayout.controlPlaneEventsFile
1242
1301
  };
1243
1302
  }
1244
1303
 
1245
1304
  // packages/runtime/src/control-plane/native/runtime-native.ts
1246
1305
  import { dlopen, ptr, suffix, toBuffer } from "bun:ffi";
1247
- import { copyFileSync, existsSync as existsSync8, mkdirSync as mkdirSync4, renameSync, rmSync as rmSync2, statSync as statSync2 } from "fs";
1306
+ import { copyFileSync, existsSync as existsSync10, mkdirSync as mkdirSync5, renameSync, rmSync as rmSync2, statSync as statSync2 } from "fs";
1248
1307
  import { tmpdir as tmpdir4 } from "os";
1249
- import { dirname as dirname7, resolve as resolve10 } from "path";
1250
- var sharedNativeRuntimeOutputDir = resolve10(tmpdir4(), "rig-native");
1251
- var sharedNativeRuntimeOutputPath = resolve10(sharedNativeRuntimeOutputDir, `runtime-native-${process.platform}-${process.arch}.${suffix}`);
1308
+ import { dirname as dirname8, resolve as resolve11 } from "path";
1309
+ var sharedNativeRuntimeOutputDir = resolve11(tmpdir4(), "rig-native");
1310
+ var sharedNativeRuntimeOutputPath = resolve11(sharedNativeRuntimeOutputDir, `runtime-native-${process.platform}-${process.arch}.${suffix}`);
1252
1311
  var colocatedNativeRuntimeFileName = `runtime-native.${suffix}`;
1253
1312
  var nativeRuntimeLibrary = await loadNativeRuntimeLibrary();
1254
1313
  async function ensureNativeRuntimeLibraryPath(outputPath = sharedNativeRuntimeOutputPath, options = {}) {
1255
1314
  if (await buildNativeRuntimeLibrary(outputPath, options)) {
1256
1315
  return outputPath;
1257
1316
  }
1258
- return !options.force && existsSync8(outputPath) ? outputPath : null;
1317
+ return !options.force && existsSync10(outputPath) ? outputPath : null;
1259
1318
  }
1260
1319
  async function loadNativeRuntimeLibrary() {
1261
1320
  if (process.env.RIG_DISABLE_ZIG_NATIVE === "1") {
1262
1321
  return null;
1263
1322
  }
1264
1323
  for (const candidate of nativeRuntimeLibraryCandidates()) {
1265
- if (!candidate || !existsSync8(candidate)) {
1324
+ if (!candidate || !existsSync10(candidate)) {
1266
1325
  continue;
1267
1326
  }
1268
1327
  const loaded = tryDlopenNativeRuntimeLibrary(candidate);
@@ -1278,12 +1337,12 @@ async function loadNativeRuntimeLibrary() {
1278
1337
  }
1279
1338
  function nativePackageLibraryCandidates(fromDir, names) {
1280
1339
  const candidates = [];
1281
- let cursor = resolve10(fromDir);
1340
+ let cursor = resolve11(fromDir);
1282
1341
  for (let index = 0;index < 8; index += 1) {
1283
1342
  for (const name of names) {
1284
- candidates.push(resolve10(cursor, "native", `${process.platform}-${process.arch}`, name), resolve10(cursor, "native", `${process.platform}-${process.arch}`, "lib", name), resolve10(cursor, "native", name), resolve10(cursor, "native", "lib", name));
1343
+ 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));
1285
1344
  }
1286
- const parent = dirname7(cursor);
1345
+ const parent = dirname8(cursor);
1287
1346
  if (parent === cursor)
1288
1347
  break;
1289
1348
  cursor = parent;
@@ -1292,27 +1351,27 @@ function nativePackageLibraryCandidates(fromDir, names) {
1292
1351
  }
1293
1352
  function nativeRuntimeLibraryCandidates() {
1294
1353
  const explicit = process.env.RIG_NATIVE_RUNTIME_LIB?.trim() || "";
1295
- const execDir = process.execPath?.trim() ? dirname7(process.execPath.trim()) : "";
1354
+ const execDir = process.execPath?.trim() ? dirname8(process.execPath.trim()) : "";
1296
1355
  const platformSpecific = `runtime-native-${process.platform}-${process.arch}.${suffix}`;
1297
1356
  return [...new Set([
1298
1357
  explicit,
1299
1358
  ...nativePackageLibraryCandidates(import.meta.dir, [colocatedNativeRuntimeFileName, platformSpecific]),
1300
- execDir ? resolve10(execDir, colocatedNativeRuntimeFileName) : "",
1301
- execDir ? resolve10(execDir, platformSpecific) : "",
1302
- execDir ? resolve10(execDir, "..", colocatedNativeRuntimeFileName) : "",
1303
- execDir ? resolve10(execDir, "..", platformSpecific) : "",
1304
- execDir ? resolve10(execDir, "lib", colocatedNativeRuntimeFileName) : "",
1305
- execDir ? resolve10(execDir, "..", "lib", colocatedNativeRuntimeFileName) : "",
1359
+ execDir ? resolve11(execDir, colocatedNativeRuntimeFileName) : "",
1360
+ execDir ? resolve11(execDir, platformSpecific) : "",
1361
+ execDir ? resolve11(execDir, "..", colocatedNativeRuntimeFileName) : "",
1362
+ execDir ? resolve11(execDir, "..", platformSpecific) : "",
1363
+ execDir ? resolve11(execDir, "lib", colocatedNativeRuntimeFileName) : "",
1364
+ execDir ? resolve11(execDir, "..", "lib", colocatedNativeRuntimeFileName) : "",
1306
1365
  sharedNativeRuntimeOutputPath
1307
1366
  ].filter(Boolean))];
1308
1367
  }
1309
1368
  function resolveNativeRuntimeSourcePath() {
1310
1369
  const explicit = process.env.RIG_NATIVE_RUNTIME_SOURCE?.trim();
1311
- if (explicit && existsSync8(explicit)) {
1370
+ if (explicit && existsSync10(explicit)) {
1312
1371
  return explicit;
1313
1372
  }
1314
- const bundled = resolve10(import.meta.dir, "../../../native/snapshot.zig");
1315
- return existsSync8(bundled) ? bundled : null;
1373
+ const bundled = resolve11(import.meta.dir, "../../../native/snapshot.zig");
1374
+ return existsSync10(bundled) ? bundled : null;
1316
1375
  }
1317
1376
  async function buildNativeRuntimeLibrary(outputPath, options = {}) {
1318
1377
  if (process.env.RIG_DISABLE_ZIG_NATIVE === "1") {
@@ -1325,8 +1384,8 @@ async function buildNativeRuntimeLibrary(outputPath, options = {}) {
1325
1384
  }
1326
1385
  const tempOutputPath = `${outputPath}.${process.pid}.${Date.now()}.${Math.random().toString(36).slice(2)}.tmp`;
1327
1386
  try {
1328
- mkdirSync4(dirname7(outputPath), { recursive: true });
1329
- const needsBuild = options.force === true || !existsSync8(outputPath) || statSync2(sourcePath).mtimeMs > statSync2(outputPath).mtimeMs;
1387
+ mkdirSync5(dirname8(outputPath), { recursive: true });
1388
+ const needsBuild = options.force === true || !existsSync10(outputPath) || statSync2(sourcePath).mtimeMs > statSync2(outputPath).mtimeMs;
1330
1389
  if (!needsBuild) {
1331
1390
  return true;
1332
1391
  }
@@ -1344,7 +1403,7 @@ async function buildNativeRuntimeLibrary(outputPath, options = {}) {
1344
1403
  stderr: "pipe"
1345
1404
  });
1346
1405
  const exitCode = await build.exited;
1347
- if (exitCode !== 0 || !existsSync8(tempOutputPath)) {
1406
+ if (exitCode !== 0 || !existsSync10(tempOutputPath)) {
1348
1407
  rmSync2(tempOutputPath, { force: true });
1349
1408
  return false;
1350
1409
  }
@@ -1431,11 +1490,11 @@ function runCapture(command, cwd, env) {
1431
1490
  };
1432
1491
  }
1433
1492
  function readJsonFile(path, fallback) {
1434
- if (!existsSync9(path)) {
1493
+ if (!existsSync11(path)) {
1435
1494
  return fallback;
1436
1495
  }
1437
1496
  try {
1438
- return JSON.parse(readFileSync6(path, "utf-8"));
1497
+ return JSON.parse(readFileSync7(path, "utf-8"));
1439
1498
  } catch {
1440
1499
  return fallback;
1441
1500
  }
@@ -1446,31 +1505,31 @@ function nowIso() {
1446
1505
  function resolveHarnessPaths(projectRoot) {
1447
1506
  const hasRuntimeWorkspace = Boolean(process.env.RIG_TASK_WORKSPACE?.trim());
1448
1507
  const monorepoRoot = resolveMonorepoRoot2(projectRoot);
1449
- const harnessRoot = resolve11(projectRoot, "rig");
1450
- const stateRoot = resolve11(projectRoot, ".rig");
1508
+ const harnessRoot = resolve12(projectRoot, "rig");
1509
+ const stateRoot = resolve12(projectRoot, ".rig");
1451
1510
  const layout = hasRuntimeWorkspace ? resolveRigLayout(projectRoot) : null;
1452
- const stateDir = layout?.stateDir ?? resolve11(stateRoot, "state");
1453
- const logsDir = layout?.logsDir ?? resolve11(stateRoot, "logs");
1454
- const artifactsDir = layout?.artifactsRoot ?? resolve11(monorepoRoot, "artifacts");
1455
- const taskConfigPath = layout?.taskConfigPath ?? resolve11(monorepoRoot, ".rig", "task-config.json");
1456
- const binDir = layout?.binDir ?? resolve11(stateRoot, "bin");
1511
+ const stateDir = layout?.stateDir ?? resolve12(stateRoot, "state");
1512
+ const logsDir = layout?.logsDir ?? resolve12(stateRoot, "logs");
1513
+ const artifactsDir = layout?.artifactsRoot ?? resolve12(monorepoRoot, "artifacts");
1514
+ const taskConfigPath = layout?.taskConfigPath ?? resolve12(monorepoRoot, ".rig", "task-config.json");
1515
+ const binDir = layout?.binDir ?? resolve12(stateRoot, "bin");
1457
1516
  return {
1458
1517
  harnessRoot,
1459
1518
  stateDir: process.env.RIG_STATE_DIR || stateDir,
1460
1519
  artifactsDir,
1461
1520
  logsDir: process.env.RIG_LOGS_DIR || logsDir,
1462
1521
  binDir,
1463
- hooksDir: resolve11(harnessRoot, "hooks"),
1464
- validationDir: resolve11(harnessRoot, "validation"),
1522
+ hooksDir: resolve12(harnessRoot, "hooks"),
1523
+ validationDir: resolve12(harnessRoot, "validation"),
1465
1524
  taskConfigPath,
1466
- sessionPath: process.env.RIG_SESSION_FILE || resolve11(stateRoot, "session", "session.json"),
1525
+ sessionPath: process.env.RIG_SESSION_FILE || resolve12(stateRoot, "session", "session.json"),
1467
1526
  monorepoRoot,
1468
- tsApiTestsDir: process.env.TS_API_TESTS_DIR || resolve11(monorepoRoot, "TSAPITests"),
1469
- taskRepoCommitsPath: resolve11(stateDir, "task-repo-commits.json"),
1470
- baseRepoPinsPath: resolve11(stateDir, "base-repo-pins.json"),
1471
- failedApproachesPath: resolve11(stateDir, "failed_approaches.md"),
1472
- agentProfilePath: resolve11(stateDir, "agent-profile.json"),
1473
- reviewProfilePath: resolve11(stateDir, "review-profile.json")
1527
+ tsApiTestsDir: process.env.TS_API_TESTS_DIR || resolve12(monorepoRoot, "TSAPITests"),
1528
+ taskRepoCommitsPath: resolve12(stateDir, "task-repo-commits.json"),
1529
+ baseRepoPinsPath: resolve12(stateDir, "base-repo-pins.json"),
1530
+ failedApproachesPath: resolve12(stateDir, "failed_approaches.md"),
1531
+ agentProfilePath: resolve12(stateDir, "agent-profile.json"),
1532
+ reviewProfilePath: resolve12(stateDir, "review-profile.json")
1474
1533
  };
1475
1534
  }
1476
1535
  // packages/runtime/src/control-plane/state-sync/reconcile.ts
@@ -1525,25 +1584,25 @@ function lookupTask(projectRoot, input) {
1525
1584
  function artifactDirForId(projectRoot, id) {
1526
1585
  const workspaceDir = process.env.RIG_TASK_WORKSPACE?.trim();
1527
1586
  if (workspaceDir) {
1528
- const worktreeArtifacts = resolve12(workspaceDir, "artifacts", id);
1529
- if (existsSync10(worktreeArtifacts) || existsSync10(resolve12(workspaceDir, "artifacts"))) {
1587
+ const worktreeArtifacts = resolve13(workspaceDir, "artifacts", id);
1588
+ if (existsSync12(worktreeArtifacts) || existsSync12(resolve13(workspaceDir, "artifacts"))) {
1530
1589
  return worktreeArtifacts;
1531
1590
  }
1532
1591
  }
1533
1592
  try {
1534
1593
  const paths = resolveHarnessPaths(projectRoot);
1535
- return resolve12(paths.artifactsDir, id);
1594
+ return resolve13(paths.artifactsDir, id);
1536
1595
  } catch {
1537
- return resolve12(resolveMonorepoRoot2(projectRoot), "artifacts", id);
1596
+ return resolve13(resolveMonorepoRoot2(projectRoot), "artifacts", id);
1538
1597
  }
1539
1598
  }
1540
1599
  function resolveTaskConfigPath(projectRoot) {
1541
1600
  const paths = resolveHarnessPaths(projectRoot);
1542
- if (existsSync10(paths.taskConfigPath)) {
1601
+ if (existsSync12(paths.taskConfigPath)) {
1543
1602
  return paths.taskConfigPath;
1544
1603
  }
1545
1604
  for (const candidate of sourceTaskConfigCandidates(projectRoot)) {
1546
- if (existsSync10(candidate)) {
1605
+ if (existsSync12(candidate)) {
1547
1606
  return candidate;
1548
1607
  }
1549
1608
  }
@@ -1551,7 +1610,7 @@ function resolveTaskConfigPath(projectRoot) {
1551
1610
  }
1552
1611
  function findSourceTaskConfigPath(projectRoot) {
1553
1612
  for (const candidate of sourceTaskConfigCandidates(projectRoot)) {
1554
- if (existsSync10(candidate)) {
1613
+ if (existsSync12(candidate)) {
1555
1614
  return candidate;
1556
1615
  }
1557
1616
  }
@@ -1564,7 +1623,7 @@ function readAndSyncSourceTaskConfig(projectRoot) {
1564
1623
  const synced = synchronizeTaskConfigWithTracker(projectRoot, raw);
1565
1624
  if (sourcePath && synced.updated) {
1566
1625
  try {
1567
- writeFileSync5(sourcePath, `${JSON.stringify(synced.config, null, 2)}
1626
+ writeFileSync6(sourcePath, `${JSON.stringify(synced.config, null, 2)}
1568
1627
  `, "utf-8");
1569
1628
  } catch {}
1570
1629
  }
@@ -1616,12 +1675,12 @@ function shouldRefreshAutoSyncedTaskConfigEntry(entry) {
1616
1675
  return !candidate.role;
1617
1676
  }
1618
1677
  function readSourceIssueRecords(projectRoot) {
1619
- const issuesPath = resolve12(resolveMonorepoRoot2(projectRoot), ".beads", "issues.jsonl");
1620
- if (!existsSync10(issuesPath)) {
1678
+ const issuesPath = resolve13(resolveMonorepoRoot2(projectRoot), ".beads", "issues.jsonl");
1679
+ if (!existsSync12(issuesPath)) {
1621
1680
  return [];
1622
1681
  }
1623
1682
  const records = [];
1624
- for (const line of readFileSync7(issuesPath, "utf-8").split(/\r?\n/)) {
1683
+ for (const line of readFileSync8(issuesPath, "utf-8").split(/\r?\n/)) {
1625
1684
  const trimmed = line.trim();
1626
1685
  if (!trimmed) {
1627
1686
  continue;
@@ -1677,19 +1736,19 @@ function readConfiguredFileTaskConfig(projectRoot) {
1677
1736
  if (!sourcePath) {
1678
1737
  return {};
1679
1738
  }
1680
- const directory = resolve12(projectRoot, sourcePath);
1681
- if (!existsSync10(directory)) {
1739
+ const directory = resolve13(projectRoot, sourcePath);
1740
+ if (!existsSync12(directory)) {
1682
1741
  return {};
1683
1742
  }
1684
1743
  const config = {};
1685
1744
  for (const name of readdirSync3(directory)) {
1686
1745
  if (!FILE_TASK_PATTERN2.test(name))
1687
1746
  continue;
1688
- const file = resolve12(directory, name);
1747
+ const file = resolve13(directory, name);
1689
1748
  try {
1690
1749
  if (!statSync3(file).isFile())
1691
1750
  continue;
1692
- const raw = JSON.parse(readFileSync7(file, "utf8"));
1751
+ const raw = JSON.parse(readFileSync8(file, "utf8"));
1693
1752
  if (!raw || typeof raw !== "object" || Array.isArray(raw))
1694
1753
  continue;
1695
1754
  const record = raw;
@@ -1731,10 +1790,10 @@ function firstStringList2(...candidates) {
1731
1790
  return [];
1732
1791
  }
1733
1792
  function readConfiguredFilesTaskSourcePath2(projectRoot) {
1734
- const jsonPath = resolve12(projectRoot, "rig.config.json");
1735
- if (existsSync10(jsonPath)) {
1793
+ const jsonPath = resolve13(projectRoot, "rig.config.json");
1794
+ if (existsSync12(jsonPath)) {
1736
1795
  try {
1737
- const parsed = JSON.parse(readFileSync7(jsonPath, "utf8"));
1796
+ const parsed = JSON.parse(readFileSync8(jsonPath, "utf8"));
1738
1797
  if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
1739
1798
  const taskSource = parsed.taskSource;
1740
1799
  if (taskSource && typeof taskSource === "object" && !Array.isArray(taskSource)) {
@@ -1746,12 +1805,12 @@ function readConfiguredFilesTaskSourcePath2(projectRoot) {
1746
1805
  return null;
1747
1806
  }
1748
1807
  }
1749
- const tsPath = resolve12(projectRoot, "rig.config.ts");
1750
- if (!existsSync10(tsPath)) {
1808
+ const tsPath = resolve13(projectRoot, "rig.config.ts");
1809
+ if (!existsSync12(tsPath)) {
1751
1810
  return null;
1752
1811
  }
1753
1812
  try {
1754
- const source = readFileSync7(tsPath, "utf8");
1813
+ const source = readFileSync8(tsPath, "utf8");
1755
1814
  const taskSourceBlock = source.match(/taskSource\s*:\s*\{[\s\S]*?\}/m)?.[0] ?? "";
1756
1815
  const kind = taskSourceBlock.match(/kind\s*:\s*["']([^"']+)["']/)?.[1];
1757
1816
  if (kind !== "files") {
@@ -1765,9 +1824,9 @@ function readConfiguredFilesTaskSourcePath2(projectRoot) {
1765
1824
  function sourceTaskConfigCandidates(projectRoot) {
1766
1825
  const runtimeContext = loadRuntimeContextFromEnv();
1767
1826
  return [
1768
- runtimeContext?.monorepoMainRoot ? resolve12(runtimeContext.monorepoMainRoot, ".rig", "task-config.json") : "",
1769
- process.env.MONOREPO_MAIN_ROOT?.trim() ? resolve12(process.env.MONOREPO_MAIN_ROOT.trim(), ".rig", "task-config.json") : "",
1770
- resolve12(resolveMonorepoRoot2(projectRoot), ".rig", "task-config.json")
1827
+ runtimeContext?.monorepoMainRoot ? resolve13(runtimeContext.monorepoMainRoot, ".rig", "task-config.json") : "",
1828
+ process.env.MONOREPO_MAIN_ROOT?.trim() ? resolve13(process.env.MONOREPO_MAIN_ROOT.trim(), ".rig", "task-config.json") : "",
1829
+ resolve13(resolveMonorepoRoot2(projectRoot), ".rig", "task-config.json")
1771
1830
  ].filter(Boolean);
1772
1831
  }
1773
1832
 
@@ -3065,12 +3124,12 @@ var TASK_ARTIFACT_STAGE_FALLBACK = new Set([
3065
3124
  "validation-summary.json"
3066
3125
  ]);
3067
3126
  function readPrMetadata(projectRoot, taskId) {
3068
- const path = resolve13(artifactDirForId(projectRoot, taskId), "pr-state.json");
3069
- if (!existsSync11(path)) {
3127
+ const path = resolve14(artifactDirForId(projectRoot, taskId), "pr-state.json");
3128
+ if (!existsSync13(path)) {
3070
3129
  return [];
3071
3130
  }
3072
3131
  try {
3073
- const parsed = JSON.parse(readFileSync8(path, "utf-8"));
3132
+ const parsed = JSON.parse(readFileSync9(path, "utf-8"));
3074
3133
  if (!parsed || typeof parsed !== "object") {
3075
3134
  return [];
3076
3135
  }
@@ -3096,11 +3155,11 @@ async function verifyTask(options) {
3096
3155
  const taskId = options.taskId;
3097
3156
  const normalizedTaskId = lookupTask(options.projectRoot, taskId);
3098
3157
  const artifactDir = artifactDirForId(options.projectRoot, taskId);
3099
- mkdirSync6(artifactDir, { recursive: true });
3100
- const validationSummaryPath = resolve14(artifactDir, "validation-summary.json");
3101
- const reviewFeedbackPath = resolve14(artifactDir, "review-feedback.md");
3102
- const reviewStatePath = resolve14(artifactDir, "review-state.json");
3103
- const greptileRawPath = resolve14(artifactDir, "review-greptile-raw.json");
3158
+ mkdirSync7(artifactDir, { recursive: true });
3159
+ const validationSummaryPath = resolve15(artifactDir, "validation-summary.json");
3160
+ const reviewFeedbackPath = resolve15(artifactDir, "review-feedback.md");
3161
+ const reviewStatePath = resolve15(artifactDir, "review-state.json");
3162
+ const greptileRawPath = resolve15(artifactDir, "review-greptile-raw.json");
3104
3163
  const prStates = readPrMetadata(options.projectRoot, taskId);
3105
3164
  const prState = prStates[0] || null;
3106
3165
  const localReasons = [];
@@ -3112,7 +3171,7 @@ async function verifyTask(options) {
3112
3171
  if (!normalizedTaskId && !await hasConfiguredSourceTask(options.projectRoot, taskId)) {
3113
3172
  localReasons.push(`[Task Config] Unknown task id '${taskId}' in task-config or configured task source.`);
3114
3173
  }
3115
- if (!existsSync12(validationSummaryPath)) {
3174
+ if (!existsSync14(validationSummaryPath)) {
3116
3175
  localReasons.push(`[Artifact Quality] validation-summary.json not found at ${validationSummaryPath}.`);
3117
3176
  } else {
3118
3177
  const summary = await parseValidationSummary(validationSummaryPath);
@@ -3121,13 +3180,13 @@ async function verifyTask(options) {
3121
3180
  }
3122
3181
  }
3123
3182
  for (const file of ["task-result.json", "decision-log.md", "next-actions.md", "changed-files.txt"]) {
3124
- const requiredPath = resolve14(artifactDir, file);
3125
- if (!existsSync12(requiredPath)) {
3183
+ const requiredPath = resolve15(artifactDir, file);
3184
+ if (!existsSync14(requiredPath)) {
3126
3185
  localReasons.push(`[Artifact Quality] Missing required artifact file: ${requiredPath}`);
3127
3186
  }
3128
3187
  }
3129
- const taskResultPath = resolve14(artifactDir, "task-result.json");
3130
- if (existsSync12(taskResultPath)) {
3188
+ const taskResultPath = resolve15(artifactDir, "task-result.json");
3189
+ if (existsSync14(taskResultPath)) {
3131
3190
  const taskResult = await readJsonFile2(taskResultPath);
3132
3191
  const artifactStatus = typeof taskResult?.status === "string" ? taskResult.status.trim().toLowerCase() : "";
3133
3192
  if (artifactStatus === "partial") {
@@ -3140,8 +3199,8 @@ async function verifyTask(options) {
3140
3199
  localReasons.push("[Artifact Quality] task-result.json next actions indicate remaining implementation scope.");
3141
3200
  }
3142
3201
  }
3143
- const nextActionsPath = resolve14(artifactDir, "next-actions.md");
3144
- if (existsSync12(nextActionsPath)) {
3202
+ const nextActionsPath = resolve15(artifactDir, "next-actions.md");
3203
+ if (existsSync14(nextActionsPath)) {
3145
3204
  const nextActionsContent = await Bun.file(nextActionsPath).text();
3146
3205
  if (nextActionsContent.includes("TODO: Replace this scaffold") || nextActionsContent.includes("bd-<downstream-task-id>")) {
3147
3206
  localReasons.push("[Artifact Quality] next-actions.md still contains scaffold placeholder text. Replace with real recommendations.");
@@ -3172,7 +3231,7 @@ async function verifyTask(options) {
3172
3231
  aiReasons.push(`[AI Review] Required mode needs a completed Greptile approval; current verdict is ${ai.verdict}.`);
3173
3232
  }
3174
3233
  if (persistArtifacts && ai.rawResponse) {
3175
- writeFileSync7(greptileRawPath, `${ai.rawResponse}
3234
+ writeFileSync8(greptileRawPath, `${ai.rawResponse}
3176
3235
  `, "utf-8");
3177
3236
  }
3178
3237
  } else if (!options.skipAiReview && reviewMode === "off") {
@@ -3415,7 +3474,7 @@ function evaluateSourceCloseoutChecks(prState, prLabel) {
3415
3474
  if (!Array.isArray(checks) || checks.length === 0) {
3416
3475
  return [`[Source Issue] PR ${prLabel} must have green check evidence before completion.`];
3417
3476
  }
3418
- const ciGate = evaluatePullRequestCiChecks(checks, "PR", 0);
3477
+ const ciGate = evaluatePullRequestCiChecks(checks, "PR", 0, { mergeStateStatus: prState.mergeStateStatus });
3419
3478
  if (ciGate.verdict === "APPROVE") {
3420
3479
  return [];
3421
3480
  }
@@ -3511,7 +3570,7 @@ function isAcceptedValidationSummary(summary) {
3511
3570
  return summary.status === "skipped" && summary.total === 0 && summary.failed === 0;
3512
3571
  }
3513
3572
  async function loadReviewMode(reviewProfilePath, fallback) {
3514
- const parsed = existsSync12(reviewProfilePath) ? await readJsonFile2(reviewProfilePath) : null;
3573
+ const parsed = existsSync14(reviewProfilePath) ? await readJsonFile2(reviewProfilePath) : null;
3515
3574
  const mode = parsed?.mode;
3516
3575
  if (mode === "off" || mode === "advisory" || mode === "required") {
3517
3576
  return mode;
@@ -3522,7 +3581,7 @@ async function loadReviewMode(reviewProfilePath, fallback) {
3522
3581
  return "advisory";
3523
3582
  }
3524
3583
  async function loadReviewProvider(reviewProfilePath, fallback) {
3525
- const parsed = existsSync12(reviewProfilePath) ? await readJsonFile2(reviewProfilePath) : null;
3584
+ const parsed = existsSync14(reviewProfilePath) ? await readJsonFile2(reviewProfilePath) : null;
3526
3585
  const provider = parsed?.provider;
3527
3586
  if (typeof provider === "string" && provider.trim().length > 0) {
3528
3587
  return provider;
@@ -3681,7 +3740,7 @@ function writeFeedbackFile(options) {
3681
3740
  if (options.aiRawFeedback) {
3682
3741
  lines.push("## Raw Reviewer Feedback", "", "```text", options.aiRawFeedback, "```", "");
3683
3742
  }
3684
- writeFileSync7(options.output, `${lines.join(`
3743
+ writeFileSync8(options.output, `${lines.join(`
3685
3744
  `)}
3686
3745
  `, "utf-8");
3687
3746
  }
@@ -3698,7 +3757,7 @@ function writeReviewStateFile(options) {
3698
3757
  ai_warnings: options.aiWarnings,
3699
3758
  updated_at: nowIso()
3700
3759
  };
3701
- writeFileSync7(options.output, `${JSON.stringify(payload, null, 2)}
3760
+ writeFileSync8(options.output, `${JSON.stringify(payload, null, 2)}
3702
3761
  `, "utf-8");
3703
3762
  }
3704
3763
  async function runGreptileReviewForPr(options) {
@@ -3779,7 +3838,7 @@ async function runGreptileReviewForPr(options) {
3779
3838
  }
3780
3839
  await Bun.sleep(options.pollIntervalMs);
3781
3840
  }
3782
- const ciGate = evaluatePullRequestCiChecks(githubCheckRollup, repoName, prNumber);
3841
+ const ciGate = evaluatePullRequestCiChecks(githubCheckRollup, repoName, prNumber, { mergeStateStatus: options.prState.mergeStateStatus });
3783
3842
  if (ciGate.verdict !== "APPROVE") {
3784
3843
  return {
3785
3844
  verdict: ciGate.verdict,
@@ -4037,7 +4096,7 @@ async function runGithubGreptileFallbackReviewForPr(options) {
4037
4096
  }
4038
4097
  await Bun.sleep(options.pollIntervalMs);
4039
4098
  }
4040
- const ciGate = evaluatePullRequestCiChecks(checkRollup, repoName, prNumber);
4099
+ const ciGate = evaluatePullRequestCiChecks(checkRollup, repoName, prNumber, { mergeStateStatus: options.prState.mergeStateStatus });
4041
4100
  if (ciGate.verdict !== "APPROVE") {
4042
4101
  return {
4043
4102
  verdict: ciGate.verdict,
@@ -4392,7 +4451,7 @@ function loadGithubPullRequestCheckRollup(projectRoot, repoName, prNumber) {
4392
4451
  ]);
4393
4452
  return response.statusCheckRollup || [];
4394
4453
  }
4395
- function evaluatePullRequestCiChecks(checks, repoName, prNumber) {
4454
+ function evaluatePullRequestCiChecks(checks, repoName, prNumber, options = {}) {
4396
4455
  const nonGreptileChecks = checks.filter((check) => {
4397
4456
  const label = (check.name || check.context || "").toLowerCase();
4398
4457
  return label.length > 0 && !label.includes("greptile");
@@ -4404,7 +4463,8 @@ function evaluatePullRequestCiChecks(checks, repoName, prNumber) {
4404
4463
  const state = (check.state || check.status || "").toUpperCase();
4405
4464
  return state === "PENDING" || state === "EXPECTED" || state === "QUEUED" || state === "IN_PROGRESS";
4406
4465
  });
4407
- if (pending.length > 0) {
4466
+ const mergeClean = (options.mergeStateStatus || "").toUpperCase() === "CLEAN";
4467
+ if (pending.length > 0 && !mergeClean) {
4408
4468
  return {
4409
4469
  verdict: "SKIP",
4410
4470
  reasons: pending.map((check) => `[CI] ${repoName}#${prNumber} check is still pending: ${check.name || check.context || "unknown"}.`)
@@ -4488,7 +4548,7 @@ function filterActionableGithubGreptileThreads(threads) {
4488
4548
  }
4489
4549
  function resolvePrRepoRoot(projectRoot, prState) {
4490
4550
  const runtimeWorkspace = process.env.RIG_TASK_WORKSPACE?.trim();
4491
- if (prState.target === "monorepo" && runtimeWorkspace && existsSync12(resolve14(runtimeWorkspace, ".git"))) {
4551
+ if (prState.target === "monorepo" && runtimeWorkspace && existsSync14(resolve15(runtimeWorkspace, ".git"))) {
4492
4552
  return runtimeWorkspace;
4493
4553
  }
4494
4554
  const paths = resolveHarnessPaths(projectRoot);
@@ -4538,5 +4598,6 @@ export {
4538
4598
  verifyTask,
4539
4599
  pickRelevantCodeReview,
4540
4600
  filterActionableGreptileComments,
4601
+ evaluatePullRequestCiChecks,
4541
4602
  __testOnly
4542
4603
  };