@h-rig/runtime 0.0.6-alpha.27 → 0.0.6-alpha.29
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin/rig-agent-dispatch.js +552 -483
- package/dist/bin/rig-agent.js +418 -364
- package/dist/src/control-plane/agent-wrapper.js +557 -488
- package/dist/src/control-plane/harness-main.js +559 -1418
- package/dist/src/control-plane/hooks/completion-verification.js +451 -808
- package/dist/src/control-plane/hooks/inject-context.js +191 -137
- package/dist/src/control-plane/hooks/submodule-branch.js +596 -542
- package/dist/src/control-plane/hooks/task-runtime-start.js +596 -542
- package/dist/src/control-plane/materialize-task-config.js +64 -8
- package/dist/src/control-plane/native/git-ops.js +3 -0
- package/dist/src/control-plane/native/harness-cli.js +544 -496
- package/dist/src/control-plane/native/repo-ops.js +3 -0
- package/dist/src/control-plane/native/run-ops.js +3 -0
- package/dist/src/control-plane/native/task-ops.js +418 -370
- package/dist/src/control-plane/native/validator.js +161 -107
- package/dist/src/control-plane/native/verifier.js +217 -169
- package/dist/src/control-plane/pi-sessiond/launcher.js +12 -2
- package/dist/src/control-plane/plugin-host-context.js +54 -0
- package/dist/src/control-plane/runtime/image/fingerprint-sidecar.js +3 -0
- package/dist/src/control-plane/runtime/image/index.js +3 -0
- package/dist/src/control-plane/runtime/image-fingerprint-sidecar.js +3 -0
- package/dist/src/control-plane/runtime/image.js +3 -0
- package/dist/src/control-plane/runtime/index.js +487 -718
- package/dist/src/control-plane/runtime/isolation/index.js +511 -457
- package/dist/src/control-plane/runtime/isolation.js +511 -457
- package/dist/src/control-plane/runtime/plugin-mode.js +3 -27
- package/dist/src/control-plane/runtime/queue.js +428 -381
- package/dist/src/control-plane/runtime/snapshot/task-run.js +3 -0
- package/dist/src/control-plane/runtime/task-run-snapshot.js +3 -0
- package/dist/src/control-plane/skill-materializer.js +46 -0
- package/dist/src/control-plane/tasks/source-lifecycle.js +84 -30
- package/dist/src/index.js +0 -278
- package/native/darwin-arm64/rig-shell +0 -0
- package/native/darwin-arm64/rig-shell.build-manifest.json +1 -1
- package/native/darwin-arm64/rig-tools +0 -0
- package/native/darwin-arm64/rig-tools.build-manifest.json +1 -1
- package/package.json +8 -7
- package/dist/src/control-plane/runtime/plugins.js +0 -1131
- package/dist/src/plugins.js +0 -329
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
// packages/runtime/src/control-plane/native/harness-cli.ts
|
|
3
|
-
import { existsSync as
|
|
4
|
-
import { resolve as
|
|
3
|
+
import { existsSync as existsSync29 } from "fs";
|
|
4
|
+
import { resolve as resolve30 } from "path";
|
|
5
5
|
|
|
6
6
|
// packages/runtime/src/control-plane/native/git-ops.ts
|
|
7
|
-
import { existsSync as
|
|
8
|
-
import { dirname as dirname11, isAbsolute as isAbsolute2, resolve as
|
|
7
|
+
import { existsSync as existsSync22, lstatSync, mkdirSync as mkdirSync11, readFileSync as readFileSync12, writeFileSync as writeFileSync11 } from "fs";
|
|
8
|
+
import { dirname as dirname11, isAbsolute as isAbsolute2, resolve as resolve25 } from "path";
|
|
9
9
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
10
10
|
|
|
11
11
|
// packages/runtime/src/control-plane/runtime/baked-secrets.ts
|
|
@@ -274,8 +274,8 @@ function isAgentRuntimeContextPath(path) {
|
|
|
274
274
|
}
|
|
275
275
|
|
|
276
276
|
// packages/runtime/src/control-plane/native/task-ops.ts
|
|
277
|
-
import { appendFileSync, existsSync as
|
|
278
|
-
import { resolve as
|
|
277
|
+
import { appendFileSync, existsSync as existsSync21, mkdirSync as mkdirSync10, readFileSync as readFileSync11, writeFileSync as writeFileSync10 } from "fs";
|
|
278
|
+
import { resolve as resolve24 } from "path";
|
|
279
279
|
|
|
280
280
|
// packages/runtime/src/build-time-config.ts
|
|
281
281
|
function normalizeBuildConfig(value) {
|
|
@@ -760,6 +760,49 @@ function safeReadJson(path) {
|
|
|
760
760
|
}
|
|
761
761
|
}
|
|
762
762
|
|
|
763
|
+
// packages/runtime/src/control-plane/skill-materializer.ts
|
|
764
|
+
import { existsSync as existsSync5, mkdirSync as mkdirSync3, readFileSync as readFileSync4, readdirSync, rmSync, writeFileSync as writeFileSync3 } from "fs";
|
|
765
|
+
import { resolve as resolve7 } from "path";
|
|
766
|
+
import { loadSkill } from "@rig/skill-loader";
|
|
767
|
+
var MARKER_FILENAME = ".rig-plugin";
|
|
768
|
+
function skillDirName(id) {
|
|
769
|
+
return id.replace(/[^a-zA-Z0-9._-]+/g, "-");
|
|
770
|
+
}
|
|
771
|
+
async function materializeSkills(projectRoot, entries) {
|
|
772
|
+
const skillsRoot = resolve7(projectRoot, ".pi", "skills");
|
|
773
|
+
if (existsSync5(skillsRoot)) {
|
|
774
|
+
for (const name of readdirSync(skillsRoot)) {
|
|
775
|
+
const dir = resolve7(skillsRoot, name);
|
|
776
|
+
if (existsSync5(resolve7(dir, MARKER_FILENAME))) {
|
|
777
|
+
rmSync(dir, { recursive: true, force: true });
|
|
778
|
+
}
|
|
779
|
+
}
|
|
780
|
+
}
|
|
781
|
+
const written = [];
|
|
782
|
+
for (const { pluginName, skill } of entries) {
|
|
783
|
+
const sourcePath = resolve7(projectRoot, skill.path);
|
|
784
|
+
if (!existsSync5(sourcePath)) {
|
|
785
|
+
console.warn(`[plugin-host] skill "${skill.id}" from plugin "${pluginName}" not materialized: ${sourcePath} does not exist`);
|
|
786
|
+
continue;
|
|
787
|
+
}
|
|
788
|
+
let body;
|
|
789
|
+
try {
|
|
790
|
+
await loadSkill(sourcePath);
|
|
791
|
+
body = readFileSync4(sourcePath, "utf-8");
|
|
792
|
+
} catch (err) {
|
|
793
|
+
console.warn(`[plugin-host] skill "${skill.id}" from plugin "${pluginName}" not materialized: ${err instanceof Error ? err.message : err}`);
|
|
794
|
+
continue;
|
|
795
|
+
}
|
|
796
|
+
const dir = resolve7(skillsRoot, skillDirName(skill.id));
|
|
797
|
+
mkdirSync3(dir, { recursive: true });
|
|
798
|
+
writeFileSync3(resolve7(dir, "SKILL.md"), body, "utf-8");
|
|
799
|
+
writeFileSync3(resolve7(dir, MARKER_FILENAME), `${JSON.stringify({ plugin: pluginName, skillId: skill.id }, null, 2)}
|
|
800
|
+
`, "utf-8");
|
|
801
|
+
written.push({ id: skill.id, pluginName, directory: dir });
|
|
802
|
+
}
|
|
803
|
+
return written;
|
|
804
|
+
}
|
|
805
|
+
|
|
763
806
|
// packages/runtime/src/control-plane/plugin-host-context.ts
|
|
764
807
|
async function buildPluginHostContext(projectRoot) {
|
|
765
808
|
let config;
|
|
@@ -796,6 +839,17 @@ async function buildPluginHostContext(projectRoot) {
|
|
|
796
839
|
} catch (err) {
|
|
797
840
|
console.warn(`[plugin-host] hook materialization failed: ${err instanceof Error ? err.message : err}`);
|
|
798
841
|
}
|
|
842
|
+
try {
|
|
843
|
+
const skillEntries = config.plugins.flatMap((plugin) => (plugin.contributes?.skills ?? []).map((skill) => ({
|
|
844
|
+
pluginName: plugin.name,
|
|
845
|
+
skill
|
|
846
|
+
})));
|
|
847
|
+
if (skillEntries.length > 0) {
|
|
848
|
+
await materializeSkills(projectRoot, skillEntries);
|
|
849
|
+
}
|
|
850
|
+
} catch (err) {
|
|
851
|
+
console.warn(`[plugin-host] skill materialization failed: ${err instanceof Error ? err.message : err}`);
|
|
852
|
+
}
|
|
799
853
|
return {
|
|
800
854
|
config,
|
|
801
855
|
pluginHost,
|
|
@@ -809,12 +863,12 @@ async function buildPluginHostContext(projectRoot) {
|
|
|
809
863
|
|
|
810
864
|
// packages/runtime/src/control-plane/tasks/source-aware-task-config-source.ts
|
|
811
865
|
import { spawnSync } from "child_process";
|
|
812
|
-
import { existsSync as
|
|
813
|
-
import { basename as basename3, join as join2, resolve as
|
|
866
|
+
import { existsSync as existsSync7, readFileSync as readFileSync6, readdirSync as readdirSync2, statSync, writeFileSync as writeFileSync4 } from "fs";
|
|
867
|
+
import { basename as basename3, join as join2, resolve as resolve9 } from "path";
|
|
814
868
|
|
|
815
869
|
// packages/runtime/src/control-plane/tasks/legacy-task-config-source.ts
|
|
816
|
-
import { existsSync as
|
|
817
|
-
import { resolve as
|
|
870
|
+
import { existsSync as existsSync6, readFileSync as readFileSync5 } from "fs";
|
|
871
|
+
import { resolve as resolve8 } from "path";
|
|
818
872
|
|
|
819
873
|
// packages/runtime/src/control-plane/tasks/task-record-reader.ts
|
|
820
874
|
async function findTaskById(reader, id) {
|
|
@@ -837,7 +891,7 @@ class LegacyTaskConfigReadError extends Error {
|
|
|
837
891
|
}
|
|
838
892
|
}
|
|
839
893
|
function createLegacyTaskConfigRecordReader(projectRoot, options = {}) {
|
|
840
|
-
const configPath = options.configPath ??
|
|
894
|
+
const configPath = options.configPath ?? resolve8(projectRoot, ".rig", "task-config.json");
|
|
841
895
|
const reader = {
|
|
842
896
|
async listTasks() {
|
|
843
897
|
return readLegacyTaskRecords(projectRoot, configPath);
|
|
@@ -848,8 +902,8 @@ function createLegacyTaskConfigRecordReader(projectRoot, options = {}) {
|
|
|
848
902
|
};
|
|
849
903
|
return reader;
|
|
850
904
|
}
|
|
851
|
-
function readLegacyTaskRecords(projectRoot, configPath =
|
|
852
|
-
if (!
|
|
905
|
+
function readLegacyTaskRecords(projectRoot, configPath = resolve8(projectRoot, ".rig", "task-config.json")) {
|
|
906
|
+
if (!existsSync6(configPath)) {
|
|
853
907
|
return [];
|
|
854
908
|
}
|
|
855
909
|
const rawConfig = readLegacyTaskConfigJson(projectRoot, configPath);
|
|
@@ -857,7 +911,7 @@ function readLegacyTaskRecords(projectRoot, configPath = resolve7(projectRoot, "
|
|
|
857
911
|
}
|
|
858
912
|
function readLegacyTaskConfigJson(projectRoot, configPath) {
|
|
859
913
|
try {
|
|
860
|
-
const parsed = JSON.parse(
|
|
914
|
+
const parsed = JSON.parse(readFileSync5(configPath, "utf8"));
|
|
861
915
|
if (isPlainRecord(parsed)) {
|
|
862
916
|
return parsed;
|
|
863
917
|
}
|
|
@@ -941,7 +995,7 @@ function isPlainRecord(candidate) {
|
|
|
941
995
|
var STATUS_LABELS = new Set(["ready", "blocked", "in-progress", "under-review", "failed", "cancelled"]);
|
|
942
996
|
var FILE_TASK_PATTERN = /\.(task\.)?json$/;
|
|
943
997
|
function createSourceAwareTaskConfigRecordReader(projectRoot, options = {}) {
|
|
944
|
-
const configPath = options.configPath ??
|
|
998
|
+
const configPath = options.configPath ?? resolve9(projectRoot, ".rig", "task-config.json");
|
|
945
999
|
const legacy = createLegacyTaskConfigRecordReader(projectRoot, { configPath });
|
|
946
1000
|
const spawnFn = options.spawn ?? spawnSync;
|
|
947
1001
|
const ghBinary = options.ghBinary ?? "gh";
|
|
@@ -1024,10 +1078,10 @@ function readMaterializedTaskMetadata(entry) {
|
|
|
1024
1078
|
return metadata;
|
|
1025
1079
|
}
|
|
1026
1080
|
function readConfiguredFilesTaskSourcePath(projectRoot) {
|
|
1027
|
-
const jsonPath =
|
|
1028
|
-
if (
|
|
1081
|
+
const jsonPath = resolve9(projectRoot, "rig.config.json");
|
|
1082
|
+
if (existsSync7(jsonPath)) {
|
|
1029
1083
|
try {
|
|
1030
|
-
const parsed = JSON.parse(
|
|
1084
|
+
const parsed = JSON.parse(readFileSync6(jsonPath, "utf8"));
|
|
1031
1085
|
if (isPlainRecord2(parsed) && isPlainRecord2(parsed.taskSource)) {
|
|
1032
1086
|
const source = parsed.taskSource;
|
|
1033
1087
|
return source.kind === "files" && typeof source.path === "string" ? source.path : null;
|
|
@@ -1036,12 +1090,12 @@ function readConfiguredFilesTaskSourcePath(projectRoot) {
|
|
|
1036
1090
|
return null;
|
|
1037
1091
|
}
|
|
1038
1092
|
}
|
|
1039
|
-
const tsPath =
|
|
1040
|
-
if (!
|
|
1093
|
+
const tsPath = resolve9(projectRoot, "rig.config.ts");
|
|
1094
|
+
if (!existsSync7(tsPath)) {
|
|
1041
1095
|
return null;
|
|
1042
1096
|
}
|
|
1043
1097
|
try {
|
|
1044
|
-
const source =
|
|
1098
|
+
const source = readFileSync6(tsPath, "utf8");
|
|
1045
1099
|
const taskSourceBlock = source.match(/taskSource\s*:\s*\{[\s\S]*?\}/m)?.[0] ?? "";
|
|
1046
1100
|
const kind = taskSourceBlock.match(/kind\s*:\s*["']([^"']+)["']/)?.[1];
|
|
1047
1101
|
if (kind !== "files") {
|
|
@@ -1061,10 +1115,10 @@ function readRawTaskEntry(configPath, taskId) {
|
|
|
1061
1115
|
return isPlainRecord2(entry) ? entry : null;
|
|
1062
1116
|
}
|
|
1063
1117
|
function readRawTaskConfig(configPath) {
|
|
1064
|
-
if (!
|
|
1118
|
+
if (!existsSync7(configPath)) {
|
|
1065
1119
|
return null;
|
|
1066
1120
|
}
|
|
1067
|
-
const parsed = JSON.parse(
|
|
1121
|
+
const parsed = JSON.parse(readFileSync6(configPath, "utf8"));
|
|
1068
1122
|
return isPlainRecord2(parsed) ? parsed : null;
|
|
1069
1123
|
}
|
|
1070
1124
|
function stripLegacyTaskConfigMetadata2(raw) {
|
|
@@ -1072,12 +1126,12 @@ function stripLegacyTaskConfigMetadata2(raw) {
|
|
|
1072
1126
|
return tasks;
|
|
1073
1127
|
}
|
|
1074
1128
|
function listFileBackedTasks(projectRoot, sourcePath) {
|
|
1075
|
-
const directory =
|
|
1076
|
-
if (!
|
|
1129
|
+
const directory = resolve9(projectRoot, sourcePath);
|
|
1130
|
+
if (!existsSync7(directory)) {
|
|
1077
1131
|
return [];
|
|
1078
1132
|
}
|
|
1079
1133
|
const tasks = [];
|
|
1080
|
-
for (const name of
|
|
1134
|
+
for (const name of readdirSync2(directory)) {
|
|
1081
1135
|
if (!FILE_TASK_PATTERN.test(name))
|
|
1082
1136
|
continue;
|
|
1083
1137
|
const inferredId = basename3(name).replace(FILE_TASK_PATTERN, "");
|
|
@@ -1088,11 +1142,11 @@ function listFileBackedTasks(projectRoot, sourcePath) {
|
|
|
1088
1142
|
return tasks;
|
|
1089
1143
|
}
|
|
1090
1144
|
function readFileBackedTask(projectRoot, sourcePath, taskId, rawEntry) {
|
|
1091
|
-
const file = findFileBackedTaskFile(
|
|
1145
|
+
const file = findFileBackedTaskFile(resolve9(projectRoot, sourcePath), taskId);
|
|
1092
1146
|
if (!file) {
|
|
1093
1147
|
return null;
|
|
1094
1148
|
}
|
|
1095
|
-
const raw = JSON.parse(
|
|
1149
|
+
const raw = JSON.parse(readFileSync6(file, "utf8"));
|
|
1096
1150
|
if (!isPlainRecord2(raw)) {
|
|
1097
1151
|
return null;
|
|
1098
1152
|
}
|
|
@@ -1105,17 +1159,17 @@ function readFileBackedTask(projectRoot, sourcePath, taskId, rawEntry) {
|
|
|
1105
1159
|
};
|
|
1106
1160
|
}
|
|
1107
1161
|
function findFileBackedTaskFile(directory, taskId) {
|
|
1108
|
-
if (!
|
|
1162
|
+
if (!existsSync7(directory)) {
|
|
1109
1163
|
return null;
|
|
1110
1164
|
}
|
|
1111
|
-
for (const name of
|
|
1165
|
+
for (const name of readdirSync2(directory)) {
|
|
1112
1166
|
if (!FILE_TASK_PATTERN.test(name))
|
|
1113
1167
|
continue;
|
|
1114
1168
|
const file = join2(directory, name);
|
|
1115
1169
|
try {
|
|
1116
1170
|
if (!statSync(file).isFile())
|
|
1117
1171
|
continue;
|
|
1118
|
-
const raw = JSON.parse(
|
|
1172
|
+
const raw = JSON.parse(readFileSync6(file, "utf8"));
|
|
1119
1173
|
const inferredId = basename3(file).replace(FILE_TASK_PATTERN, "");
|
|
1120
1174
|
const id = isPlainRecord2(raw) && typeof raw.id === "string" ? raw.id : inferredId;
|
|
1121
1175
|
if (id === taskId) {
|
|
@@ -1275,8 +1329,8 @@ async function readConfiguredTaskSourceTask(projectRoot, taskId) {
|
|
|
1275
1329
|
}
|
|
1276
1330
|
|
|
1277
1331
|
// packages/runtime/src/control-plane/native/task-state.ts
|
|
1278
|
-
import { existsSync as
|
|
1279
|
-
import { basename as basename6, resolve as
|
|
1332
|
+
import { existsSync as existsSync15, readFileSync as readFileSync10, readdirSync as readdirSync3, statSync as statSync3, writeFileSync as writeFileSync6 } from "fs";
|
|
1333
|
+
import { basename as basename6, resolve as resolve17 } from "path";
|
|
1280
1334
|
|
|
1281
1335
|
// packages/runtime/src/control-plane/state-sync/types.ts
|
|
1282
1336
|
var SUPPORTED_TASK_STATE_SCHEMA_VERSION = 1;
|
|
@@ -1384,30 +1438,30 @@ function readTaskStateMetadataEnvelope(raw) {
|
|
|
1384
1438
|
};
|
|
1385
1439
|
}
|
|
1386
1440
|
// packages/runtime/src/control-plane/state-sync/read.ts
|
|
1387
|
-
import { existsSync as
|
|
1388
|
-
import { resolve as
|
|
1441
|
+
import { existsSync as existsSync14, readFileSync as readFileSync9 } from "fs";
|
|
1442
|
+
import { resolve as resolve16 } from "path";
|
|
1389
1443
|
|
|
1390
1444
|
// packages/runtime/src/control-plane/native/git-native.ts
|
|
1391
|
-
import { chmodSync, copyFileSync, existsSync as
|
|
1445
|
+
import { chmodSync, copyFileSync, existsSync as existsSync8, mkdirSync as mkdirSync4, readFileSync as readFileSync7, renameSync, rmSync as rmSync2, writeFileSync as writeFileSync5 } from "fs";
|
|
1392
1446
|
import { tmpdir as tmpdir3 } from "os";
|
|
1393
|
-
import { dirname as dirname5, isAbsolute, resolve as
|
|
1447
|
+
import { dirname as dirname5, isAbsolute, resolve as resolve10 } from "path";
|
|
1394
1448
|
import { createHash } from "crypto";
|
|
1395
1449
|
function isTextTreeCommitUpdate(update) {
|
|
1396
1450
|
return typeof update.content === "string";
|
|
1397
1451
|
}
|
|
1398
|
-
var sharedGitNativeOutputDir =
|
|
1399
|
-
var sharedGitNativeOutputPath =
|
|
1452
|
+
var sharedGitNativeOutputDir = resolve10(tmpdir3(), "rig-native");
|
|
1453
|
+
var sharedGitNativeOutputPath = resolve10(sharedGitNativeOutputDir, `rig-git-${process.platform}-${process.arch}${process.platform === "win32" ? ".exe" : ""}`);
|
|
1400
1454
|
var trackerCommandUsageProbe = "usage: rig-git fetch-ref <repo-path> <remote> <branch>";
|
|
1401
1455
|
function temporaryGitBinaryOutputPath(outputPath) {
|
|
1402
1456
|
const suffix = process.platform === "win32" ? ".exe" : "";
|
|
1403
|
-
return
|
|
1457
|
+
return resolve10(dirname5(outputPath), `.rig-git-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}${suffix}`);
|
|
1404
1458
|
}
|
|
1405
1459
|
function publishGitBinary(tempOutputPath, outputPath) {
|
|
1406
1460
|
try {
|
|
1407
1461
|
renameSync(tempOutputPath, outputPath);
|
|
1408
1462
|
} catch (error) {
|
|
1409
|
-
if (process.platform === "win32" &&
|
|
1410
|
-
|
|
1463
|
+
if (process.platform === "win32" && existsSync8(outputPath)) {
|
|
1464
|
+
rmSync2(outputPath, { force: true });
|
|
1411
1465
|
renameSync(tempOutputPath, outputPath);
|
|
1412
1466
|
return;
|
|
1413
1467
|
}
|
|
@@ -1422,22 +1476,22 @@ function rigGitSourceCandidates() {
|
|
|
1422
1476
|
const cwd = process.cwd()?.trim() || "";
|
|
1423
1477
|
const projectRoot = process.env.PROJECT_RIG_ROOT?.trim() || "";
|
|
1424
1478
|
const hostProjectRoot = process.env.RIG_HOST_PROJECT_ROOT?.trim() || "";
|
|
1425
|
-
const moduleRelativeSource =
|
|
1479
|
+
const moduleRelativeSource = resolve10(import.meta.dir, "../../../native/rig-git.zig");
|
|
1426
1480
|
return [...new Set([
|
|
1427
1481
|
process.env.RIG_NATIVE_GIT_SOURCE?.trim() || "",
|
|
1428
1482
|
moduleRelativeSource,
|
|
1429
|
-
projectRoot ?
|
|
1430
|
-
hostProjectRoot ?
|
|
1431
|
-
cwd ?
|
|
1432
|
-
execDir ?
|
|
1433
|
-
execDir ?
|
|
1483
|
+
projectRoot ? resolve10(projectRoot, "packages/runtime/native/rig-git.zig") : "",
|
|
1484
|
+
hostProjectRoot ? resolve10(hostProjectRoot, "packages/runtime/native/rig-git.zig") : "",
|
|
1485
|
+
cwd ? resolve10(cwd, "packages/runtime/native/rig-git.zig") : "",
|
|
1486
|
+
execDir ? resolve10(execDir, "..", "..", "packages/runtime/native/rig-git.zig") : "",
|
|
1487
|
+
execDir ? resolve10(execDir, "..", "native", "rig-git.zig") : ""
|
|
1434
1488
|
].filter(Boolean))];
|
|
1435
1489
|
}
|
|
1436
1490
|
function nativePackageBinaryCandidates(fromDir, fileName) {
|
|
1437
1491
|
const candidates = [];
|
|
1438
|
-
let cursor =
|
|
1492
|
+
let cursor = resolve10(fromDir);
|
|
1439
1493
|
for (let index = 0;index < 8; index += 1) {
|
|
1440
|
-
candidates.push(
|
|
1494
|
+
candidates.push(resolve10(cursor, "native", `${process.platform}-${process.arch}`, fileName), resolve10(cursor, "native", `${process.platform}-${process.arch}`, "bin", fileName), resolve10(cursor, "native", fileName), resolve10(cursor, "native", "bin", fileName));
|
|
1441
1495
|
const parent = dirname5(cursor);
|
|
1442
1496
|
if (parent === cursor)
|
|
1443
1497
|
break;
|
|
@@ -1452,15 +1506,15 @@ function rigGitBinaryCandidates() {
|
|
|
1452
1506
|
return [...new Set([
|
|
1453
1507
|
explicit,
|
|
1454
1508
|
...nativePackageBinaryCandidates(import.meta.dir, fileName),
|
|
1455
|
-
execDir ?
|
|
1456
|
-
execDir ?
|
|
1457
|
-
execDir ?
|
|
1509
|
+
execDir ? resolve10(execDir, fileName) : "",
|
|
1510
|
+
execDir ? resolve10(execDir, "..", fileName) : "",
|
|
1511
|
+
execDir ? resolve10(execDir, "..", "bin", fileName) : "",
|
|
1458
1512
|
sharedGitNativeOutputPath
|
|
1459
1513
|
].filter(Boolean))];
|
|
1460
1514
|
}
|
|
1461
1515
|
function resolveGitSourcePath() {
|
|
1462
1516
|
for (const candidate of rigGitSourceCandidates()) {
|
|
1463
|
-
if (candidate &&
|
|
1517
|
+
if (candidate && existsSync8(candidate)) {
|
|
1464
1518
|
return candidate;
|
|
1465
1519
|
}
|
|
1466
1520
|
}
|
|
@@ -1471,7 +1525,7 @@ function resolveGitBinaryPath() {
|
|
|
1471
1525
|
return null;
|
|
1472
1526
|
}
|
|
1473
1527
|
for (const candidate of rigGitBinaryCandidates()) {
|
|
1474
|
-
if (candidate &&
|
|
1528
|
+
if (candidate && existsSync8(candidate)) {
|
|
1475
1529
|
return candidate;
|
|
1476
1530
|
}
|
|
1477
1531
|
}
|
|
@@ -1501,18 +1555,18 @@ function nativeBuildManifestPath(outputPath) {
|
|
|
1501
1555
|
return `${outputPath}.build-manifest.json`;
|
|
1502
1556
|
}
|
|
1503
1557
|
function hasMatchingNativeBuildManifestSync(manifestPath, buildKey) {
|
|
1504
|
-
if (!
|
|
1558
|
+
if (!existsSync8(manifestPath)) {
|
|
1505
1559
|
return false;
|
|
1506
1560
|
}
|
|
1507
1561
|
try {
|
|
1508
|
-
const manifest = JSON.parse(
|
|
1562
|
+
const manifest = JSON.parse(readFileSync7(manifestPath, "utf8"));
|
|
1509
1563
|
return manifest.version === 1 && manifest.buildKey === buildKey;
|
|
1510
1564
|
} catch {
|
|
1511
1565
|
return false;
|
|
1512
1566
|
}
|
|
1513
1567
|
}
|
|
1514
1568
|
function sha256FileSync(path) {
|
|
1515
|
-
return createHash("sha256").update(
|
|
1569
|
+
return createHash("sha256").update(readFileSync7(path)).digest("hex");
|
|
1516
1570
|
}
|
|
1517
1571
|
function ensureRigGitBinaryPathSync(outputPath = preferredGitBinaryOutputPath()) {
|
|
1518
1572
|
if (process.env.RIG_DISABLE_ZIG_NATIVE === "1") {
|
|
@@ -1530,7 +1584,7 @@ function ensureRigGitBinaryPathSync(outputPath = preferredGitBinaryOutputPath())
|
|
|
1530
1584
|
if (!zigBinary) {
|
|
1531
1585
|
throw new Error("zig is required to build native Rig git tools.");
|
|
1532
1586
|
}
|
|
1533
|
-
|
|
1587
|
+
mkdirSync4(dirname5(outputPath), { recursive: true });
|
|
1534
1588
|
const sourceDigest = sha256FileSync(sourcePath);
|
|
1535
1589
|
const buildKey = JSON.stringify({
|
|
1536
1590
|
version: 1,
|
|
@@ -1541,7 +1595,7 @@ function ensureRigGitBinaryPathSync(outputPath = preferredGitBinaryOutputPath())
|
|
|
1541
1595
|
sourceDigest
|
|
1542
1596
|
});
|
|
1543
1597
|
const manifestPath = nativeBuildManifestPath(outputPath);
|
|
1544
|
-
const needsBuild = !
|
|
1598
|
+
const needsBuild = !existsSync8(outputPath) || !hasMatchingNativeBuildManifestSync(manifestPath, buildKey) || !binarySupportsTrackerCommandsSync(outputPath);
|
|
1545
1599
|
if (!needsBuild) {
|
|
1546
1600
|
chmodSync(outputPath, 493);
|
|
1547
1601
|
return outputPath;
|
|
@@ -1559,7 +1613,7 @@ function ensureRigGitBinaryPathSync(outputPath = preferredGitBinaryOutputPath())
|
|
|
1559
1613
|
stdout: "pipe",
|
|
1560
1614
|
stderr: "pipe"
|
|
1561
1615
|
});
|
|
1562
|
-
if (build.exitCode !== 0 || !
|
|
1616
|
+
if (build.exitCode !== 0 || !existsSync8(tempOutputPath)) {
|
|
1563
1617
|
const stderr = build.stderr.toString().trim();
|
|
1564
1618
|
const stdout = build.stdout.toString().trim();
|
|
1565
1619
|
const details = [stderr, stdout].filter(Boolean).join(`
|
|
@@ -1567,17 +1621,17 @@ function ensureRigGitBinaryPathSync(outputPath = preferredGitBinaryOutputPath())
|
|
|
1567
1621
|
throw new Error(`Failed to build native Rig git tools: ${details || `zig exited with code ${build.exitCode}`}`);
|
|
1568
1622
|
}
|
|
1569
1623
|
chmodSync(tempOutputPath, 493);
|
|
1570
|
-
if (
|
|
1571
|
-
|
|
1624
|
+
if (existsSync8(outputPath) && hasMatchingNativeBuildManifestSync(manifestPath, buildKey)) {
|
|
1625
|
+
rmSync2(tempOutputPath, { force: true });
|
|
1572
1626
|
chmodSync(outputPath, 493);
|
|
1573
1627
|
return outputPath;
|
|
1574
1628
|
}
|
|
1575
1629
|
publishGitBinary(tempOutputPath, outputPath);
|
|
1576
1630
|
if (!binarySupportsTrackerCommandsSync(outputPath)) {
|
|
1577
|
-
|
|
1631
|
+
rmSync2(outputPath, { force: true });
|
|
1578
1632
|
throw new Error("Failed to build native Rig git tools: tracker command probe failed");
|
|
1579
1633
|
}
|
|
1580
|
-
|
|
1634
|
+
writeFileSync5(manifestPath, `${JSON.stringify({ version: 1, buildKey }, null, 2)}
|
|
1581
1635
|
`, "utf8");
|
|
1582
1636
|
return outputPath;
|
|
1583
1637
|
}
|
|
@@ -1599,7 +1653,7 @@ function runGitNative(command, args) {
|
|
|
1599
1653
|
}
|
|
1600
1654
|
} else {
|
|
1601
1655
|
const explicitBinaryPath = process.env.RIG_NATIVE_GIT_BIN?.trim() || "";
|
|
1602
|
-
binaryPath = explicitBinaryPath &&
|
|
1656
|
+
binaryPath = explicitBinaryPath && existsSync8(explicitBinaryPath) ? explicitBinaryPath : !explicitBinaryPath ? resolveGitBinaryPath() : null;
|
|
1603
1657
|
if (!binaryPath) {
|
|
1604
1658
|
try {
|
|
1605
1659
|
binaryPath = ensureRigGitBinaryPathSync(preferredGitBinaryOutputPath());
|
|
@@ -1696,25 +1750,25 @@ function nativeFetchRef(repoPath, remote, branch) {
|
|
|
1696
1750
|
return requireGitNativeString("fetch-ref", [repoPath, remote, branch]);
|
|
1697
1751
|
}
|
|
1698
1752
|
function nativeReadBlobAtRef(repoPath, ref, path) {
|
|
1699
|
-
const requestDir =
|
|
1700
|
-
|
|
1701
|
-
const outputPath =
|
|
1753
|
+
const requestDir = resolve10(sharedGitNativeOutputDir, "reads", `${Date.now()}-${Math.random().toString(36).slice(2, 10)}`);
|
|
1754
|
+
mkdirSync4(requestDir, { recursive: true });
|
|
1755
|
+
const outputPath = resolve10(requestDir, "blob.txt");
|
|
1702
1756
|
try {
|
|
1703
1757
|
requireGitNative("read-blob-at-ref", [repoPath, ref, path, outputPath]);
|
|
1704
|
-
return
|
|
1758
|
+
return readFileSync7(outputPath, "utf8");
|
|
1705
1759
|
} finally {
|
|
1706
|
-
|
|
1760
|
+
rmSync2(requestDir, { recursive: true, force: true });
|
|
1707
1761
|
}
|
|
1708
1762
|
}
|
|
1709
1763
|
function nativeReadBlobBytesAtRef(repoPath, ref, path) {
|
|
1710
|
-
const requestDir =
|
|
1711
|
-
|
|
1712
|
-
const outputPath =
|
|
1764
|
+
const requestDir = resolve10(sharedGitNativeOutputDir, "reads", `${Date.now()}-${Math.random().toString(36).slice(2, 10)}`);
|
|
1765
|
+
mkdirSync4(requestDir, { recursive: true });
|
|
1766
|
+
const outputPath = resolve10(requestDir, "blob.bin");
|
|
1713
1767
|
try {
|
|
1714
1768
|
requireGitNative("read-blob-at-ref", [repoPath, ref, path, outputPath]);
|
|
1715
|
-
return
|
|
1769
|
+
return readFileSync7(outputPath);
|
|
1716
1770
|
} finally {
|
|
1717
|
-
|
|
1771
|
+
rmSync2(requestDir, { recursive: true, force: true });
|
|
1718
1772
|
}
|
|
1719
1773
|
}
|
|
1720
1774
|
function serializeTreeCommitUpdates(updates) {
|
|
@@ -1733,16 +1787,16 @@ function buildTreeCommitUpdatesJson(updates) {
|
|
|
1733
1787
|
`;
|
|
1734
1788
|
}
|
|
1735
1789
|
function nativeWriteTreeCommit(repoPath, baseRef, updates, message) {
|
|
1736
|
-
const requestDir =
|
|
1737
|
-
|
|
1738
|
-
const messagePath =
|
|
1739
|
-
const updatesPath =
|
|
1790
|
+
const requestDir = resolve10(sharedGitNativeOutputDir, "requests", `${Date.now()}-${Math.random().toString(36).slice(2, 10)}`);
|
|
1791
|
+
mkdirSync4(requestDir, { recursive: true });
|
|
1792
|
+
const messagePath = resolve10(requestDir, "message.txt");
|
|
1793
|
+
const updatesPath = resolve10(requestDir, "updates.json");
|
|
1740
1794
|
try {
|
|
1741
|
-
|
|
1742
|
-
|
|
1795
|
+
writeFileSync5(messagePath, message, "utf8");
|
|
1796
|
+
writeFileSync5(updatesPath, buildTreeCommitUpdatesJson(updates), "utf8");
|
|
1743
1797
|
return requireGitNativeString("write-tree-commit", [repoPath, baseRef, messagePath, updatesPath]);
|
|
1744
1798
|
} finally {
|
|
1745
|
-
|
|
1799
|
+
rmSync2(requestDir, { recursive: true, force: true });
|
|
1746
1800
|
}
|
|
1747
1801
|
}
|
|
1748
1802
|
function nativePushRefWithLease(repoPath, localOid, remoteRef, expectedOldOid, remote = "origin") {
|
|
@@ -1757,35 +1811,35 @@ function nativePushRefWithLease(repoPath, localOid, remoteRef, expectedOldOid, r
|
|
|
1757
1811
|
|
|
1758
1812
|
// packages/runtime/src/control-plane/native/utils.ts
|
|
1759
1813
|
import { ptr as ptr2 } from "bun:ffi";
|
|
1760
|
-
import { existsSync as
|
|
1761
|
-
import { resolve as
|
|
1814
|
+
import { existsSync as existsSync11, readFileSync as readFileSync8 } from "fs";
|
|
1815
|
+
import { resolve as resolve13 } from "path";
|
|
1762
1816
|
|
|
1763
1817
|
// packages/runtime/src/layout.ts
|
|
1764
|
-
import { existsSync as
|
|
1765
|
-
import { basename as basename4, dirname as dirname6, resolve as
|
|
1818
|
+
import { existsSync as existsSync9 } from "fs";
|
|
1819
|
+
import { basename as basename4, dirname as dirname6, resolve as resolve11 } from "path";
|
|
1766
1820
|
var RIG_DEFINITION_DIRNAME = "rig";
|
|
1767
1821
|
var RIG_ARTIFACTS_DIRNAME = "artifacts";
|
|
1768
1822
|
function resolveMonorepoRoot(projectRoot) {
|
|
1769
|
-
const normalizedProjectRoot =
|
|
1823
|
+
const normalizedProjectRoot = resolve11(projectRoot);
|
|
1770
1824
|
const explicit = process.env.MONOREPO_ROOT?.trim();
|
|
1771
1825
|
if (explicit) {
|
|
1772
|
-
const explicitRoot =
|
|
1826
|
+
const explicitRoot = resolve11(explicit);
|
|
1773
1827
|
const explicitParent = dirname6(explicitRoot);
|
|
1774
1828
|
if (basename4(explicitParent) === ".worktrees") {
|
|
1775
1829
|
const owner = dirname6(explicitParent);
|
|
1776
|
-
const ownerHasGit =
|
|
1777
|
-
const ownerHasTaskConfig =
|
|
1778
|
-
const ownerHasRigConfig =
|
|
1830
|
+
const ownerHasGit = existsSync9(resolve11(owner, ".git"));
|
|
1831
|
+
const ownerHasTaskConfig = existsSync9(resolve11(owner, ".rig", "task-config.json"));
|
|
1832
|
+
const ownerHasRigConfig = existsSync9(resolve11(owner, "rig.config.ts"));
|
|
1779
1833
|
if (ownerHasGit && (ownerHasTaskConfig || ownerHasRigConfig)) {
|
|
1780
1834
|
return owner;
|
|
1781
1835
|
}
|
|
1782
1836
|
throw new Error(`MONOREPO_ROOT points to worktree ${explicitRoot}, but the owner checkout is incomplete at ${owner}.`);
|
|
1783
1837
|
}
|
|
1784
|
-
if (!
|
|
1838
|
+
if (!existsSync9(resolve11(explicitRoot, ".git"))) {
|
|
1785
1839
|
throw new Error(`MONOREPO_ROOT points to ${explicitRoot}, but no git checkout was found there.`);
|
|
1786
1840
|
}
|
|
1787
|
-
const hasTaskConfig =
|
|
1788
|
-
const hasRigConfig =
|
|
1841
|
+
const hasTaskConfig = existsSync9(resolve11(explicitRoot, ".rig", "task-config.json"));
|
|
1842
|
+
const hasRigConfig = existsSync9(resolve11(explicitRoot, "rig.config.ts"));
|
|
1789
1843
|
if (!hasTaskConfig && !hasRigConfig) {
|
|
1790
1844
|
throw new Error(`MONOREPO_ROOT points to ${explicitRoot}, but neither .rig/task-config.json nor rig.config.ts exists there.`);
|
|
1791
1845
|
}
|
|
@@ -1794,9 +1848,9 @@ function resolveMonorepoRoot(projectRoot) {
|
|
|
1794
1848
|
const projectParent = dirname6(normalizedProjectRoot);
|
|
1795
1849
|
if (basename4(projectParent) === ".worktrees") {
|
|
1796
1850
|
const worktreeOwner = dirname6(projectParent);
|
|
1797
|
-
const ownerHasGit =
|
|
1798
|
-
const ownerHasTaskConfig =
|
|
1799
|
-
const ownerHasRigConfig =
|
|
1851
|
+
const ownerHasGit = existsSync9(resolve11(worktreeOwner, ".git"));
|
|
1852
|
+
const ownerHasTaskConfig = existsSync9(resolve11(worktreeOwner, ".rig", "task-config.json"));
|
|
1853
|
+
const ownerHasRigConfig = existsSync9(resolve11(worktreeOwner, "rig.config.ts"));
|
|
1800
1854
|
if (ownerHasGit && (ownerHasTaskConfig || ownerHasRigConfig)) {
|
|
1801
1855
|
return worktreeOwner;
|
|
1802
1856
|
}
|
|
@@ -1804,28 +1858,28 @@ function resolveMonorepoRoot(projectRoot) {
|
|
|
1804
1858
|
return normalizedProjectRoot;
|
|
1805
1859
|
}
|
|
1806
1860
|
function resolveRuntimeWorkspaceLayout(workspaceDir) {
|
|
1807
|
-
const root =
|
|
1808
|
-
const rigRoot =
|
|
1809
|
-
const logsDir =
|
|
1810
|
-
const stateDir =
|
|
1811
|
-
const runtimeDir =
|
|
1812
|
-
const binDir =
|
|
1861
|
+
const root = resolve11(workspaceDir);
|
|
1862
|
+
const rigRoot = resolve11(root, ".rig");
|
|
1863
|
+
const logsDir = resolve11(rigRoot, "logs");
|
|
1864
|
+
const stateDir = resolve11(rigRoot, "state");
|
|
1865
|
+
const runtimeDir = resolve11(rigRoot, "runtime");
|
|
1866
|
+
const binDir = resolve11(rigRoot, "bin");
|
|
1813
1867
|
return {
|
|
1814
1868
|
workspaceDir: root,
|
|
1815
1869
|
rigRoot,
|
|
1816
1870
|
stateDir,
|
|
1817
1871
|
logsDir,
|
|
1818
|
-
artifactsRoot:
|
|
1872
|
+
artifactsRoot: resolve11(root, RIG_ARTIFACTS_DIRNAME),
|
|
1819
1873
|
runtimeDir,
|
|
1820
|
-
homeDir:
|
|
1821
|
-
tmpDir:
|
|
1822
|
-
cacheDir:
|
|
1823
|
-
sessionDir:
|
|
1874
|
+
homeDir: resolve11(rigRoot, "home"),
|
|
1875
|
+
tmpDir: resolve11(rigRoot, "tmp"),
|
|
1876
|
+
cacheDir: resolve11(rigRoot, "cache"),
|
|
1877
|
+
sessionDir: resolve11(rigRoot, "session"),
|
|
1824
1878
|
binDir,
|
|
1825
|
-
distDir:
|
|
1826
|
-
pluginBinDir:
|
|
1827
|
-
contextPath:
|
|
1828
|
-
controlPlaneEventsFile:
|
|
1879
|
+
distDir: resolve11(rigRoot, "dist"),
|
|
1880
|
+
pluginBinDir: resolve11(binDir, "plugins"),
|
|
1881
|
+
contextPath: resolve11(rigRoot, "runtime-context.json"),
|
|
1882
|
+
controlPlaneEventsFile: resolve11(logsDir, "control-plane.events.jsonl")
|
|
1829
1883
|
};
|
|
1830
1884
|
}
|
|
1831
1885
|
function resolveActiveRuntimeWorkspaceRoot(monorepoRoot) {
|
|
@@ -1833,14 +1887,14 @@ function resolveActiveRuntimeWorkspaceRoot(monorepoRoot) {
|
|
|
1833
1887
|
if (!explicit) {
|
|
1834
1888
|
throw new Error("No active runtime workspace. Set RIG_TASK_WORKSPACE or provision a task runtime first.");
|
|
1835
1889
|
}
|
|
1836
|
-
return
|
|
1890
|
+
return resolve11(explicit);
|
|
1837
1891
|
}
|
|
1838
1892
|
function resolveRigLayout(projectRoot) {
|
|
1839
1893
|
const monorepoRoot = resolveMonorepoRoot(projectRoot);
|
|
1840
|
-
const definitionRoot =
|
|
1894
|
+
const definitionRoot = resolve11(projectRoot, RIG_DEFINITION_DIRNAME);
|
|
1841
1895
|
const runtimeWorkspaceRoot = resolveActiveRuntimeWorkspaceRoot(monorepoRoot);
|
|
1842
1896
|
const runtimeLayout = resolveRuntimeWorkspaceLayout(runtimeWorkspaceRoot);
|
|
1843
|
-
const policyDir =
|
|
1897
|
+
const policyDir = resolve11(definitionRoot, "policy");
|
|
1844
1898
|
return {
|
|
1845
1899
|
projectRoot,
|
|
1846
1900
|
monorepoRoot,
|
|
@@ -1848,34 +1902,34 @@ function resolveRigLayout(projectRoot) {
|
|
|
1848
1902
|
runtimeWorkspaceRoot,
|
|
1849
1903
|
stateRoot: runtimeLayout.rigRoot,
|
|
1850
1904
|
artifactsRoot: runtimeLayout.artifactsRoot,
|
|
1851
|
-
configPath:
|
|
1852
|
-
taskConfigPath:
|
|
1905
|
+
configPath: resolve11(definitionRoot, "config.sh"),
|
|
1906
|
+
taskConfigPath: resolve11(runtimeWorkspaceRoot, ".rig", "task-config.json"),
|
|
1853
1907
|
policyDir,
|
|
1854
|
-
policyFile:
|
|
1855
|
-
pluginsDir:
|
|
1856
|
-
hooksDir:
|
|
1857
|
-
toolsDir:
|
|
1858
|
-
templatesDir:
|
|
1859
|
-
validationDir:
|
|
1908
|
+
policyFile: resolve11(policyDir, "policy.json"),
|
|
1909
|
+
pluginsDir: resolve11(definitionRoot, "plugins"),
|
|
1910
|
+
hooksDir: resolve11(definitionRoot, "hooks"),
|
|
1911
|
+
toolsDir: resolve11(definitionRoot, "tools"),
|
|
1912
|
+
templatesDir: resolve11(definitionRoot, "templates"),
|
|
1913
|
+
validationDir: resolve11(definitionRoot, "validation"),
|
|
1860
1914
|
stateDir: runtimeLayout.stateDir,
|
|
1861
1915
|
logsDir: runtimeLayout.logsDir,
|
|
1862
|
-
notificationsDir:
|
|
1916
|
+
notificationsDir: resolve11(definitionRoot, "notifications"),
|
|
1863
1917
|
runtimeDir: runtimeLayout.runtimeDir,
|
|
1864
1918
|
distDir: runtimeLayout.distDir,
|
|
1865
1919
|
binDir: runtimeLayout.binDir,
|
|
1866
1920
|
pluginBinDir: runtimeLayout.pluginBinDir,
|
|
1867
|
-
keybindingsPath:
|
|
1921
|
+
keybindingsPath: resolve11(definitionRoot, "keybindings.json"),
|
|
1868
1922
|
controlPlaneEventsFile: runtimeLayout.controlPlaneEventsFile
|
|
1869
1923
|
};
|
|
1870
1924
|
}
|
|
1871
1925
|
|
|
1872
1926
|
// packages/runtime/src/control-plane/native/runtime-native.ts
|
|
1873
1927
|
import { dlopen, ptr, suffix, toBuffer } from "bun:ffi";
|
|
1874
|
-
import { copyFileSync as copyFileSync2, existsSync as
|
|
1928
|
+
import { copyFileSync as copyFileSync2, existsSync as existsSync10, mkdirSync as mkdirSync5, renameSync as renameSync2, rmSync as rmSync3, statSync as statSync2 } from "fs";
|
|
1875
1929
|
import { tmpdir as tmpdir4 } from "os";
|
|
1876
|
-
import { dirname as dirname7, resolve as
|
|
1877
|
-
var sharedNativeRuntimeOutputDir =
|
|
1878
|
-
var sharedNativeRuntimeOutputPath =
|
|
1930
|
+
import { dirname as dirname7, resolve as resolve12 } from "path";
|
|
1931
|
+
var sharedNativeRuntimeOutputDir = resolve12(tmpdir4(), "rig-native");
|
|
1932
|
+
var sharedNativeRuntimeOutputPath = resolve12(sharedNativeRuntimeOutputDir, `runtime-native-${process.platform}-${process.arch}.${suffix}`);
|
|
1879
1933
|
var colocatedNativeRuntimeFileName = `runtime-native.${suffix}`;
|
|
1880
1934
|
var nativeRuntimeLibrary = await loadNativeRuntimeLibrary();
|
|
1881
1935
|
function requireNativeRuntimeLibrary(feature) {
|
|
@@ -1888,14 +1942,14 @@ async function ensureNativeRuntimeLibraryPath(outputPath = sharedNativeRuntimeOu
|
|
|
1888
1942
|
if (await buildNativeRuntimeLibrary(outputPath, options)) {
|
|
1889
1943
|
return outputPath;
|
|
1890
1944
|
}
|
|
1891
|
-
return !options.force &&
|
|
1945
|
+
return !options.force && existsSync10(outputPath) ? outputPath : null;
|
|
1892
1946
|
}
|
|
1893
1947
|
async function loadNativeRuntimeLibrary() {
|
|
1894
1948
|
if (process.env.RIG_DISABLE_ZIG_NATIVE === "1") {
|
|
1895
1949
|
return null;
|
|
1896
1950
|
}
|
|
1897
1951
|
for (const candidate of nativeRuntimeLibraryCandidates()) {
|
|
1898
|
-
if (!candidate || !
|
|
1952
|
+
if (!candidate || !existsSync10(candidate)) {
|
|
1899
1953
|
continue;
|
|
1900
1954
|
}
|
|
1901
1955
|
const loaded = tryDlopenNativeRuntimeLibrary(candidate);
|
|
@@ -1911,10 +1965,10 @@ async function loadNativeRuntimeLibrary() {
|
|
|
1911
1965
|
}
|
|
1912
1966
|
function nativePackageLibraryCandidates(fromDir, names) {
|
|
1913
1967
|
const candidates = [];
|
|
1914
|
-
let cursor =
|
|
1968
|
+
let cursor = resolve12(fromDir);
|
|
1915
1969
|
for (let index = 0;index < 8; index += 1) {
|
|
1916
1970
|
for (const name of names) {
|
|
1917
|
-
candidates.push(
|
|
1971
|
+
candidates.push(resolve12(cursor, "native", `${process.platform}-${process.arch}`, name), resolve12(cursor, "native", `${process.platform}-${process.arch}`, "lib", name), resolve12(cursor, "native", name), resolve12(cursor, "native", "lib", name));
|
|
1918
1972
|
}
|
|
1919
1973
|
const parent = dirname7(cursor);
|
|
1920
1974
|
if (parent === cursor)
|
|
@@ -1930,22 +1984,22 @@ function nativeRuntimeLibraryCandidates() {
|
|
|
1930
1984
|
return [...new Set([
|
|
1931
1985
|
explicit,
|
|
1932
1986
|
...nativePackageLibraryCandidates(import.meta.dir, [colocatedNativeRuntimeFileName, platformSpecific]),
|
|
1933
|
-
execDir ?
|
|
1934
|
-
execDir ?
|
|
1935
|
-
execDir ?
|
|
1936
|
-
execDir ?
|
|
1937
|
-
execDir ?
|
|
1938
|
-
execDir ?
|
|
1987
|
+
execDir ? resolve12(execDir, colocatedNativeRuntimeFileName) : "",
|
|
1988
|
+
execDir ? resolve12(execDir, platformSpecific) : "",
|
|
1989
|
+
execDir ? resolve12(execDir, "..", colocatedNativeRuntimeFileName) : "",
|
|
1990
|
+
execDir ? resolve12(execDir, "..", platformSpecific) : "",
|
|
1991
|
+
execDir ? resolve12(execDir, "lib", colocatedNativeRuntimeFileName) : "",
|
|
1992
|
+
execDir ? resolve12(execDir, "..", "lib", colocatedNativeRuntimeFileName) : "",
|
|
1939
1993
|
sharedNativeRuntimeOutputPath
|
|
1940
1994
|
].filter(Boolean))];
|
|
1941
1995
|
}
|
|
1942
1996
|
function resolveNativeRuntimeSourcePath() {
|
|
1943
1997
|
const explicit = process.env.RIG_NATIVE_RUNTIME_SOURCE?.trim();
|
|
1944
|
-
if (explicit &&
|
|
1998
|
+
if (explicit && existsSync10(explicit)) {
|
|
1945
1999
|
return explicit;
|
|
1946
2000
|
}
|
|
1947
|
-
const bundled =
|
|
1948
|
-
return
|
|
2001
|
+
const bundled = resolve12(import.meta.dir, "../../../native/snapshot.zig");
|
|
2002
|
+
return existsSync10(bundled) ? bundled : null;
|
|
1949
2003
|
}
|
|
1950
2004
|
async function buildNativeRuntimeLibrary(outputPath, options = {}) {
|
|
1951
2005
|
if (process.env.RIG_DISABLE_ZIG_NATIVE === "1") {
|
|
@@ -1958,8 +2012,8 @@ async function buildNativeRuntimeLibrary(outputPath, options = {}) {
|
|
|
1958
2012
|
}
|
|
1959
2013
|
const tempOutputPath = `${outputPath}.${process.pid}.${Date.now()}.${Math.random().toString(36).slice(2)}.tmp`;
|
|
1960
2014
|
try {
|
|
1961
|
-
|
|
1962
|
-
const needsBuild = options.force === true || !
|
|
2015
|
+
mkdirSync5(dirname7(outputPath), { recursive: true });
|
|
2016
|
+
const needsBuild = options.force === true || !existsSync10(outputPath) || statSync2(sourcePath).mtimeMs > statSync2(outputPath).mtimeMs;
|
|
1963
2017
|
if (!needsBuild) {
|
|
1964
2018
|
return true;
|
|
1965
2019
|
}
|
|
@@ -1977,14 +2031,14 @@ async function buildNativeRuntimeLibrary(outputPath, options = {}) {
|
|
|
1977
2031
|
stderr: "pipe"
|
|
1978
2032
|
});
|
|
1979
2033
|
const exitCode = await build.exited;
|
|
1980
|
-
if (exitCode !== 0 || !
|
|
1981
|
-
|
|
2034
|
+
if (exitCode !== 0 || !existsSync10(tempOutputPath)) {
|
|
2035
|
+
rmSync3(tempOutputPath, { force: true });
|
|
1982
2036
|
return false;
|
|
1983
2037
|
}
|
|
1984
2038
|
renameSync2(tempOutputPath, outputPath);
|
|
1985
2039
|
return true;
|
|
1986
2040
|
} catch {
|
|
1987
|
-
|
|
2041
|
+
rmSync3(tempOutputPath, { force: true });
|
|
1988
2042
|
return false;
|
|
1989
2043
|
}
|
|
1990
2044
|
}
|
|
@@ -2108,11 +2162,11 @@ async function runCaptureAsync(command, cwd, env, timeoutMs) {
|
|
|
2108
2162
|
return { exitCode, stdout, stderr };
|
|
2109
2163
|
}
|
|
2110
2164
|
function readJsonFile(path, fallback) {
|
|
2111
|
-
if (!
|
|
2165
|
+
if (!existsSync11(path)) {
|
|
2112
2166
|
return fallback;
|
|
2113
2167
|
}
|
|
2114
2168
|
try {
|
|
2115
|
-
return JSON.parse(
|
|
2169
|
+
return JSON.parse(readFileSync8(path, "utf-8"));
|
|
2116
2170
|
} catch {
|
|
2117
2171
|
return fallback;
|
|
2118
2172
|
}
|
|
@@ -2126,31 +2180,31 @@ function unique(values) {
|
|
|
2126
2180
|
function resolveHarnessPaths(projectRoot) {
|
|
2127
2181
|
const hasRuntimeWorkspace = Boolean(process.env.RIG_TASK_WORKSPACE?.trim());
|
|
2128
2182
|
const monorepoRoot = resolveMonorepoRoot2(projectRoot);
|
|
2129
|
-
const harnessRoot =
|
|
2130
|
-
const stateRoot =
|
|
2183
|
+
const harnessRoot = resolve13(projectRoot, "rig");
|
|
2184
|
+
const stateRoot = resolve13(projectRoot, ".rig");
|
|
2131
2185
|
const layout = hasRuntimeWorkspace ? resolveRigLayout(projectRoot) : null;
|
|
2132
|
-
const stateDir = layout?.stateDir ??
|
|
2133
|
-
const logsDir = layout?.logsDir ??
|
|
2134
|
-
const artifactsDir = layout?.artifactsRoot ??
|
|
2135
|
-
const taskConfigPath = layout?.taskConfigPath ??
|
|
2136
|
-
const binDir = layout?.binDir ??
|
|
2186
|
+
const stateDir = layout?.stateDir ?? resolve13(stateRoot, "state");
|
|
2187
|
+
const logsDir = layout?.logsDir ?? resolve13(stateRoot, "logs");
|
|
2188
|
+
const artifactsDir = layout?.artifactsRoot ?? resolve13(monorepoRoot, "artifacts");
|
|
2189
|
+
const taskConfigPath = layout?.taskConfigPath ?? resolve13(monorepoRoot, ".rig", "task-config.json");
|
|
2190
|
+
const binDir = layout?.binDir ?? resolve13(stateRoot, "bin");
|
|
2137
2191
|
return {
|
|
2138
2192
|
harnessRoot,
|
|
2139
2193
|
stateDir: process.env.RIG_STATE_DIR || stateDir,
|
|
2140
2194
|
artifactsDir,
|
|
2141
2195
|
logsDir: process.env.RIG_LOGS_DIR || logsDir,
|
|
2142
2196
|
binDir,
|
|
2143
|
-
hooksDir:
|
|
2144
|
-
validationDir:
|
|
2197
|
+
hooksDir: resolve13(harnessRoot, "hooks"),
|
|
2198
|
+
validationDir: resolve13(harnessRoot, "validation"),
|
|
2145
2199
|
taskConfigPath,
|
|
2146
|
-
sessionPath: process.env.RIG_SESSION_FILE ||
|
|
2200
|
+
sessionPath: process.env.RIG_SESSION_FILE || resolve13(stateRoot, "session", "session.json"),
|
|
2147
2201
|
monorepoRoot,
|
|
2148
|
-
tsApiTestsDir: process.env.TS_API_TESTS_DIR ||
|
|
2149
|
-
taskRepoCommitsPath:
|
|
2150
|
-
baseRepoPinsPath:
|
|
2151
|
-
failedApproachesPath:
|
|
2152
|
-
agentProfilePath:
|
|
2153
|
-
reviewProfilePath:
|
|
2202
|
+
tsApiTestsDir: process.env.TS_API_TESTS_DIR || resolve13(monorepoRoot, "TSAPITests"),
|
|
2203
|
+
taskRepoCommitsPath: resolve13(stateDir, "task-repo-commits.json"),
|
|
2204
|
+
baseRepoPinsPath: resolve13(stateDir, "base-repo-pins.json"),
|
|
2205
|
+
failedApproachesPath: resolve13(stateDir, "failed_approaches.md"),
|
|
2206
|
+
agentProfilePath: resolve13(stateDir, "agent-profile.json"),
|
|
2207
|
+
reviewProfilePath: resolve13(stateDir, "review-profile.json")
|
|
2154
2208
|
};
|
|
2155
2209
|
}
|
|
2156
2210
|
function normalizeRelativeScopePath(inputPath) {
|
|
@@ -2243,34 +2297,34 @@ function createNativeScopeMatcher() {
|
|
|
2243
2297
|
}
|
|
2244
2298
|
|
|
2245
2299
|
// packages/runtime/src/control-plane/state-sync/repo.ts
|
|
2246
|
-
import { existsSync as
|
|
2247
|
-
import { resolve as
|
|
2300
|
+
import { existsSync as existsSync13 } from "fs";
|
|
2301
|
+
import { resolve as resolve15 } from "path";
|
|
2248
2302
|
|
|
2249
2303
|
// packages/runtime/src/control-plane/repos/layout.ts
|
|
2250
|
-
import { existsSync as
|
|
2251
|
-
import { basename as basename5, dirname as dirname8, join as join3, resolve as
|
|
2304
|
+
import { existsSync as existsSync12 } from "fs";
|
|
2305
|
+
import { basename as basename5, dirname as dirname8, join as join3, resolve as resolve14 } from "path";
|
|
2252
2306
|
function resolveRepoStateDir(projectRoot) {
|
|
2253
|
-
const normalizedProjectRoot =
|
|
2307
|
+
const normalizedProjectRoot = resolve14(projectRoot);
|
|
2254
2308
|
const projectParent = dirname8(normalizedProjectRoot);
|
|
2255
2309
|
if (basename5(projectParent) === ".worktrees") {
|
|
2256
2310
|
const ownerRoot = dirname8(projectParent);
|
|
2257
|
-
const ownerHasRepoMarkers =
|
|
2311
|
+
const ownerHasRepoMarkers = existsSync12(resolve14(ownerRoot, ".git")) || existsSync12(resolve14(ownerRoot, ".rig", "state"));
|
|
2258
2312
|
if (ownerHasRepoMarkers) {
|
|
2259
|
-
return
|
|
2313
|
+
return resolve14(ownerRoot, ".rig", "state");
|
|
2260
2314
|
}
|
|
2261
2315
|
}
|
|
2262
|
-
return
|
|
2316
|
+
return resolve14(projectRoot, ".rig", "state");
|
|
2263
2317
|
}
|
|
2264
2318
|
function resolveManagedRepoLayout(projectRoot, repoId) {
|
|
2265
|
-
const normalizedProjectRoot =
|
|
2319
|
+
const normalizedProjectRoot = resolve14(projectRoot);
|
|
2266
2320
|
const entry = getManagedRepoEntry(repoId);
|
|
2267
2321
|
const stateDir = resolveRepoStateDir(normalizedProjectRoot);
|
|
2268
2322
|
const metadataRelativePath = join3("repos", entry.id);
|
|
2269
|
-
const metadataRoot =
|
|
2323
|
+
const metadataRoot = resolve14(stateDir, metadataRelativePath);
|
|
2270
2324
|
const runtimeWorkspace = process.env.RIG_TASK_WORKSPACE?.trim();
|
|
2271
|
-
const runsInsideTaskWorktree = runtimeWorkspace &&
|
|
2325
|
+
const runsInsideTaskWorktree = runtimeWorkspace && resolve14(runtimeWorkspace) === normalizedProjectRoot || basename5(dirname8(normalizedProjectRoot)) === ".worktrees";
|
|
2272
2326
|
const isPrimaryManagedRepo = listManagedRepoEntries()[0]?.id === repoId;
|
|
2273
|
-
const checkoutRoot = isPrimaryManagedRepo && runsInsideTaskWorktree ? resolveMonorepoRoot(normalizedProjectRoot) : entry.checkoutEnvVar && process.env[entry.checkoutEnvVar]?.trim() ?
|
|
2327
|
+
const checkoutRoot = isPrimaryManagedRepo && runsInsideTaskWorktree ? resolveMonorepoRoot(normalizedProjectRoot) : entry.checkoutEnvVar && process.env[entry.checkoutEnvVar]?.trim() ? resolve14(process.env[entry.checkoutEnvVar].trim()) : resolve14(normalizedProjectRoot, entry.alias);
|
|
2274
2328
|
return {
|
|
2275
2329
|
projectRoot: normalizedProjectRoot,
|
|
2276
2330
|
repoId: entry.id,
|
|
@@ -2278,12 +2332,12 @@ function resolveManagedRepoLayout(projectRoot, repoId) {
|
|
|
2278
2332
|
defaultBranch: entry.defaultBranch,
|
|
2279
2333
|
remoteUrl: entry.remoteEnvVar && process.env[entry.remoteEnvVar]?.trim() ? process.env[entry.remoteEnvVar].trim() : entry.defaultRemoteUrl,
|
|
2280
2334
|
checkoutRoot,
|
|
2281
|
-
worktreesRoot:
|
|
2335
|
+
worktreesRoot: resolve14(checkoutRoot, ".worktrees"),
|
|
2282
2336
|
stateDir,
|
|
2283
2337
|
metadataRoot,
|
|
2284
2338
|
metadataRelativePath,
|
|
2285
|
-
mirrorRoot:
|
|
2286
|
-
mirrorStatePath:
|
|
2339
|
+
mirrorRoot: resolve14(metadataRoot, "mirror.git"),
|
|
2340
|
+
mirrorStatePath: resolve14(metadataRoot, "mirror-state.json"),
|
|
2287
2341
|
mirrorStateRelativePath: join3(metadataRelativePath, "mirror-state.json")
|
|
2288
2342
|
};
|
|
2289
2343
|
}
|
|
@@ -2305,7 +2359,7 @@ function resolveTrackerRepoPath(projectRoot) {
|
|
|
2305
2359
|
const monorepoRoot = resolveMonorepoRoot2(projectRoot);
|
|
2306
2360
|
try {
|
|
2307
2361
|
const layout = resolveMonorepoRepoLayout(projectRoot);
|
|
2308
|
-
if (
|
|
2362
|
+
if (existsSync13(resolve15(layout.mirrorRoot, "HEAD"))) {
|
|
2309
2363
|
return layout.mirrorRoot;
|
|
2310
2364
|
}
|
|
2311
2365
|
} catch {}
|
|
@@ -2316,8 +2370,8 @@ function resolveTrackerRepoPath(projectRoot) {
|
|
|
2316
2370
|
var DEFAULT_READ_DEPS = {
|
|
2317
2371
|
fetchRef: nativeFetchRef,
|
|
2318
2372
|
readBlobAtRef: nativeReadBlobAtRef,
|
|
2319
|
-
exists:
|
|
2320
|
-
readFile: (path) =>
|
|
2373
|
+
exists: existsSync14,
|
|
2374
|
+
readFile: (path) => readFileSync9(path, "utf8")
|
|
2321
2375
|
};
|
|
2322
2376
|
function parseIssueStatus(rawStatus) {
|
|
2323
2377
|
const normalized = normalizeTaskLifecycleStatus(rawStatus);
|
|
@@ -2398,12 +2452,12 @@ function shouldPreferLocalTrackerState(options) {
|
|
|
2398
2452
|
if (runtimeContextPath) {
|
|
2399
2453
|
return true;
|
|
2400
2454
|
}
|
|
2401
|
-
return
|
|
2455
|
+
return existsSync14(resolve16(runtimeWorkspace, ".rig", "runtime-context.json"));
|
|
2402
2456
|
}
|
|
2403
2457
|
function readLocalTrackerState(projectRoot, deps) {
|
|
2404
2458
|
const monorepoRoot = resolveMonorepoRoot2(projectRoot);
|
|
2405
|
-
const issuesPath =
|
|
2406
|
-
const taskStatePath =
|
|
2459
|
+
const issuesPath = resolve16(monorepoRoot, ".beads", "issues.jsonl");
|
|
2460
|
+
const taskStatePath = resolve16(monorepoRoot, ".beads", "task-state.json");
|
|
2407
2461
|
return projectSyncedTrackerSnapshot({
|
|
2408
2462
|
source: "local",
|
|
2409
2463
|
issuesBaseOid: null,
|
|
@@ -2465,7 +2519,7 @@ function readValidationDescriptions(projectRoot) {
|
|
|
2465
2519
|
return readValidationDescriptionMap(raw);
|
|
2466
2520
|
}
|
|
2467
2521
|
function readSourceValidationDescriptions(projectRoot) {
|
|
2468
|
-
const rootRaw = readJsonFile(
|
|
2522
|
+
const rootRaw = readJsonFile(resolve17(projectRoot, "rig", "task-config.json"), {});
|
|
2469
2523
|
const sourcePath = findSourceTaskConfigPath(projectRoot);
|
|
2470
2524
|
const sourceRaw = sourcePath ? readJsonFile(sourcePath, {}) : {};
|
|
2471
2525
|
const rootDescriptions = readValidationDescriptionMap(rootRaw);
|
|
@@ -2541,15 +2595,15 @@ function readValidationDescriptionsFromMeta(meta) {
|
|
|
2541
2595
|
return meta.validation_descriptions;
|
|
2542
2596
|
}
|
|
2543
2597
|
function readLocalSourceTaskStateEnvelope(projectRoot) {
|
|
2544
|
-
const taskStatePath =
|
|
2598
|
+
const taskStatePath = resolve17(resolveMonorepoRoot2(projectRoot), ".beads", "task-state.json");
|
|
2545
2599
|
return readTaskStateMetadataEnvelope(readJsonFile(taskStatePath, {}));
|
|
2546
2600
|
}
|
|
2547
2601
|
function readLocalSourceTaskLifecycleStatus(projectRoot, taskId) {
|
|
2548
|
-
const issuesPath =
|
|
2549
|
-
if (!
|
|
2602
|
+
const issuesPath = resolve17(resolveMonorepoRoot2(projectRoot), ".beads", "issues.jsonl");
|
|
2603
|
+
if (!existsSync15(issuesPath)) {
|
|
2550
2604
|
return null;
|
|
2551
2605
|
}
|
|
2552
|
-
for (const line of
|
|
2606
|
+
for (const line of readFileSync10(issuesPath, "utf8").split(/\r?\n/)) {
|
|
2553
2607
|
const trimmed = line.trim();
|
|
2554
2608
|
if (!trimmed) {
|
|
2555
2609
|
continue;
|
|
@@ -2590,25 +2644,25 @@ function lookupTask(projectRoot, input) {
|
|
|
2590
2644
|
function artifactDirForId(projectRoot, id) {
|
|
2591
2645
|
const workspaceDir = process.env.RIG_TASK_WORKSPACE?.trim();
|
|
2592
2646
|
if (workspaceDir) {
|
|
2593
|
-
const worktreeArtifacts =
|
|
2594
|
-
if (
|
|
2647
|
+
const worktreeArtifacts = resolve17(workspaceDir, "artifacts", id);
|
|
2648
|
+
if (existsSync15(worktreeArtifacts) || existsSync15(resolve17(workspaceDir, "artifacts"))) {
|
|
2595
2649
|
return worktreeArtifacts;
|
|
2596
2650
|
}
|
|
2597
2651
|
}
|
|
2598
2652
|
try {
|
|
2599
2653
|
const paths = resolveHarnessPaths(projectRoot);
|
|
2600
|
-
return
|
|
2654
|
+
return resolve17(paths.artifactsDir, id);
|
|
2601
2655
|
} catch {
|
|
2602
|
-
return
|
|
2656
|
+
return resolve17(resolveMonorepoRoot2(projectRoot), "artifacts", id);
|
|
2603
2657
|
}
|
|
2604
2658
|
}
|
|
2605
2659
|
function resolveTaskConfigPath(projectRoot) {
|
|
2606
2660
|
const paths = resolveHarnessPaths(projectRoot);
|
|
2607
|
-
if (
|
|
2661
|
+
if (existsSync15(paths.taskConfigPath)) {
|
|
2608
2662
|
return paths.taskConfigPath;
|
|
2609
2663
|
}
|
|
2610
2664
|
for (const candidate of sourceTaskConfigCandidates(projectRoot)) {
|
|
2611
|
-
if (
|
|
2665
|
+
if (existsSync15(candidate)) {
|
|
2612
2666
|
return candidate;
|
|
2613
2667
|
}
|
|
2614
2668
|
}
|
|
@@ -2616,7 +2670,7 @@ function resolveTaskConfigPath(projectRoot) {
|
|
|
2616
2670
|
}
|
|
2617
2671
|
function findSourceTaskConfigPath(projectRoot) {
|
|
2618
2672
|
for (const candidate of sourceTaskConfigCandidates(projectRoot)) {
|
|
2619
|
-
if (
|
|
2673
|
+
if (existsSync15(candidate)) {
|
|
2620
2674
|
return candidate;
|
|
2621
2675
|
}
|
|
2622
2676
|
}
|
|
@@ -2629,7 +2683,7 @@ function readAndSyncSourceTaskConfig(projectRoot) {
|
|
|
2629
2683
|
const synced = synchronizeTaskConfigWithTracker(projectRoot, raw);
|
|
2630
2684
|
if (sourcePath && synced.updated) {
|
|
2631
2685
|
try {
|
|
2632
|
-
|
|
2686
|
+
writeFileSync6(sourcePath, `${JSON.stringify(synced.config, null, 2)}
|
|
2633
2687
|
`, "utf-8");
|
|
2634
2688
|
} catch {}
|
|
2635
2689
|
}
|
|
@@ -2681,12 +2735,12 @@ function shouldRefreshAutoSyncedTaskConfigEntry(entry) {
|
|
|
2681
2735
|
return !candidate.role;
|
|
2682
2736
|
}
|
|
2683
2737
|
function readSourceIssueRecords(projectRoot) {
|
|
2684
|
-
const issuesPath =
|
|
2685
|
-
if (!
|
|
2738
|
+
const issuesPath = resolve17(resolveMonorepoRoot2(projectRoot), ".beads", "issues.jsonl");
|
|
2739
|
+
if (!existsSync15(issuesPath)) {
|
|
2686
2740
|
return [];
|
|
2687
2741
|
}
|
|
2688
2742
|
const records = [];
|
|
2689
|
-
for (const line of
|
|
2743
|
+
for (const line of readFileSync10(issuesPath, "utf-8").split(/\r?\n/)) {
|
|
2690
2744
|
const trimmed = line.trim();
|
|
2691
2745
|
if (!trimmed) {
|
|
2692
2746
|
continue;
|
|
@@ -2742,19 +2796,19 @@ function readConfiguredFileTaskConfig(projectRoot) {
|
|
|
2742
2796
|
if (!sourcePath) {
|
|
2743
2797
|
return {};
|
|
2744
2798
|
}
|
|
2745
|
-
const directory =
|
|
2746
|
-
if (!
|
|
2799
|
+
const directory = resolve17(projectRoot, sourcePath);
|
|
2800
|
+
if (!existsSync15(directory)) {
|
|
2747
2801
|
return {};
|
|
2748
2802
|
}
|
|
2749
2803
|
const config = {};
|
|
2750
|
-
for (const name of
|
|
2804
|
+
for (const name of readdirSync3(directory)) {
|
|
2751
2805
|
if (!FILE_TASK_PATTERN2.test(name))
|
|
2752
2806
|
continue;
|
|
2753
|
-
const file =
|
|
2807
|
+
const file = resolve17(directory, name);
|
|
2754
2808
|
try {
|
|
2755
2809
|
if (!statSync3(file).isFile())
|
|
2756
2810
|
continue;
|
|
2757
|
-
const raw = JSON.parse(
|
|
2811
|
+
const raw = JSON.parse(readFileSync10(file, "utf8"));
|
|
2758
2812
|
if (!raw || typeof raw !== "object" || Array.isArray(raw))
|
|
2759
2813
|
continue;
|
|
2760
2814
|
const record = raw;
|
|
@@ -2796,10 +2850,10 @@ function firstStringList2(...candidates) {
|
|
|
2796
2850
|
return [];
|
|
2797
2851
|
}
|
|
2798
2852
|
function readConfiguredFilesTaskSourcePath2(projectRoot) {
|
|
2799
|
-
const jsonPath =
|
|
2800
|
-
if (
|
|
2853
|
+
const jsonPath = resolve17(projectRoot, "rig.config.json");
|
|
2854
|
+
if (existsSync15(jsonPath)) {
|
|
2801
2855
|
try {
|
|
2802
|
-
const parsed = JSON.parse(
|
|
2856
|
+
const parsed = JSON.parse(readFileSync10(jsonPath, "utf8"));
|
|
2803
2857
|
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
2804
2858
|
const taskSource = parsed.taskSource;
|
|
2805
2859
|
if (taskSource && typeof taskSource === "object" && !Array.isArray(taskSource)) {
|
|
@@ -2811,12 +2865,12 @@ function readConfiguredFilesTaskSourcePath2(projectRoot) {
|
|
|
2811
2865
|
return null;
|
|
2812
2866
|
}
|
|
2813
2867
|
}
|
|
2814
|
-
const tsPath =
|
|
2815
|
-
if (!
|
|
2868
|
+
const tsPath = resolve17(projectRoot, "rig.config.ts");
|
|
2869
|
+
if (!existsSync15(tsPath)) {
|
|
2816
2870
|
return null;
|
|
2817
2871
|
}
|
|
2818
2872
|
try {
|
|
2819
|
-
const source =
|
|
2873
|
+
const source = readFileSync10(tsPath, "utf8");
|
|
2820
2874
|
const taskSourceBlock = source.match(/taskSource\s*:\s*\{[\s\S]*?\}/m)?.[0] ?? "";
|
|
2821
2875
|
const kind = taskSourceBlock.match(/kind\s*:\s*["']([^"']+)["']/)?.[1];
|
|
2822
2876
|
if (kind !== "files") {
|
|
@@ -2830,23 +2884,23 @@ function readConfiguredFilesTaskSourcePath2(projectRoot) {
|
|
|
2830
2884
|
function sourceTaskConfigCandidates(projectRoot) {
|
|
2831
2885
|
const runtimeContext = loadRuntimeContextFromEnv();
|
|
2832
2886
|
return [
|
|
2833
|
-
runtimeContext?.monorepoMainRoot ?
|
|
2834
|
-
process.env.MONOREPO_MAIN_ROOT?.trim() ?
|
|
2835
|
-
|
|
2887
|
+
runtimeContext?.monorepoMainRoot ? resolve17(runtimeContext.monorepoMainRoot, ".rig", "task-config.json") : "",
|
|
2888
|
+
process.env.MONOREPO_MAIN_ROOT?.trim() ? resolve17(process.env.MONOREPO_MAIN_ROOT.trim(), ".rig", "task-config.json") : "",
|
|
2889
|
+
resolve17(resolveMonorepoRoot2(projectRoot), ".rig", "task-config.json")
|
|
2836
2890
|
].filter(Boolean);
|
|
2837
2891
|
}
|
|
2838
2892
|
|
|
2839
2893
|
// packages/runtime/src/control-plane/native/validator.ts
|
|
2840
|
-
import { existsSync as
|
|
2841
|
-
import { resolve as
|
|
2894
|
+
import { existsSync as existsSync19, mkdirSync as mkdirSync8, writeFileSync as writeFileSync8 } from "fs";
|
|
2895
|
+
import { resolve as resolve22 } from "path";
|
|
2842
2896
|
|
|
2843
2897
|
// packages/runtime/src/control-plane/native/validator-binaries.ts
|
|
2844
|
-
import { existsSync as
|
|
2845
|
-
import { dirname as dirname10, resolve as
|
|
2898
|
+
import { existsSync as existsSync18, mkdirSync as mkdirSync7, rmSync as rmSync5, statSync as statSync4 } from "fs";
|
|
2899
|
+
import { dirname as dirname10, resolve as resolve21 } from "path";
|
|
2846
2900
|
|
|
2847
2901
|
// packages/runtime/src/binary-run.ts
|
|
2848
|
-
import { chmodSync as chmodSync2, cpSync, existsSync as
|
|
2849
|
-
import { basename as basename7, dirname as dirname9, resolve as
|
|
2902
|
+
import { chmodSync as chmodSync2, cpSync, existsSync as existsSync16, mkdirSync as mkdirSync6, renameSync as renameSync3, rmSync as rmSync4, writeFileSync as writeFileSync7 } from "fs";
|
|
2903
|
+
import { basename as basename7, dirname as dirname9, resolve as resolve18 } from "path";
|
|
2850
2904
|
import { fileURLToPath } from "url";
|
|
2851
2905
|
import { drainMicrotasks, gcAndSweep } from "bun:jsc";
|
|
2852
2906
|
var runtimeBinaryBuildQueue = Promise.resolve();
|
|
@@ -2872,9 +2926,9 @@ async function buildRuntimeBinary(options) {
|
|
|
2872
2926
|
});
|
|
2873
2927
|
}
|
|
2874
2928
|
async function buildRuntimeBinaryInProcess(options, manifest) {
|
|
2875
|
-
const tempBuildDir =
|
|
2876
|
-
const tempOutputPath =
|
|
2877
|
-
|
|
2929
|
+
const tempBuildDir = resolve18(dirname9(options.outputPath), `.bun-build-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`);
|
|
2930
|
+
const tempOutputPath = resolve18(tempBuildDir, basename7(options.outputPath));
|
|
2931
|
+
mkdirSync6(tempBuildDir, { recursive: true });
|
|
2878
2932
|
await withTemporaryEnv({
|
|
2879
2933
|
...options.env,
|
|
2880
2934
|
...options.define ? { RIG_BUILD_CONFIG_JSON: JSON.stringify(options.define) } : {}
|
|
@@ -2899,7 +2953,7 @@ async function buildRuntimeBinaryInProcess(options, manifest) {
|
|
|
2899
2953
|
`);
|
|
2900
2954
|
throw new Error(`Failed to build ${options.entrypoint}: ${details || "Bun.build() returned errors"}`);
|
|
2901
2955
|
}
|
|
2902
|
-
if (!
|
|
2956
|
+
if (!existsSync16(tempOutputPath)) {
|
|
2903
2957
|
const emitted = buildResult.outputs.map((output) => output.path).join(", ") || "(none)";
|
|
2904
2958
|
throw new Error(`Failed to build ${options.entrypoint}: Bun.build() did not emit ${tempOutputPath}. Emitted: ${emitted}`);
|
|
2905
2959
|
}
|
|
@@ -2914,7 +2968,7 @@ async function buildRuntimeBinaryInProcess(options, manifest) {
|
|
|
2914
2968
|
});
|
|
2915
2969
|
}
|
|
2916
2970
|
})).finally(() => {
|
|
2917
|
-
|
|
2971
|
+
rmSync4(tempBuildDir, { recursive: true, force: true });
|
|
2918
2972
|
});
|
|
2919
2973
|
}
|
|
2920
2974
|
function runBestEffortBuildGc() {
|
|
@@ -2931,8 +2985,8 @@ function runtimeBinaryCacheManifestPath(outputPath) {
|
|
|
2931
2985
|
function resolveRuntimeBinaryBuildOptions(options) {
|
|
2932
2986
|
return {
|
|
2933
2987
|
...options,
|
|
2934
|
-
entrypoint:
|
|
2935
|
-
outputPath:
|
|
2988
|
+
entrypoint: resolve18(options.cwd, options.sourcePath),
|
|
2989
|
+
outputPath: resolve18(options.outputPath)
|
|
2936
2990
|
};
|
|
2937
2991
|
}
|
|
2938
2992
|
function shouldUseRuntimeBinaryBuildWorker() {
|
|
@@ -2946,7 +3000,7 @@ function shouldUseRuntimeBinaryBuildWorker() {
|
|
|
2946
3000
|
}
|
|
2947
3001
|
async function buildRuntimeBinaryViaWorker(options) {
|
|
2948
3002
|
const workerSourcePath = resolveRuntimeBinaryBuildWorkerSourcePath(options);
|
|
2949
|
-
if (!workerSourcePath || !
|
|
3003
|
+
if (!workerSourcePath || !existsSync16(workerSourcePath)) {
|
|
2950
3004
|
await buildRuntimeBinaryInProcess(options, {
|
|
2951
3005
|
manifestPath: runtimeBinaryCacheManifestPath(options.outputPath),
|
|
2952
3006
|
buildKey: createRuntimeBinaryBuildKey({
|
|
@@ -2977,13 +3031,13 @@ async function buildRuntimeBinaryViaWorker(options) {
|
|
|
2977
3031
|
new Response(build.stdout).text(),
|
|
2978
3032
|
new Response(build.stderr).text()
|
|
2979
3033
|
]);
|
|
2980
|
-
|
|
3034
|
+
rmSync4(payloadPath, { force: true });
|
|
2981
3035
|
if (exitCode !== 0) {
|
|
2982
3036
|
throw new Error(`Failed to build ${options.entrypoint}: ${(stderr || stdout || `worker exited ${exitCode}`).trim()}`);
|
|
2983
3037
|
}
|
|
2984
3038
|
}
|
|
2985
3039
|
function createRuntimeBinaryBuildWorkerPayloadPath(outputPath) {
|
|
2986
|
-
return
|
|
3040
|
+
return resolve18(dirname9(outputPath), `.bun-build-worker-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}.json`);
|
|
2987
3041
|
}
|
|
2988
3042
|
function resolveRuntimeBinaryBuildWorkerSourcePath(options) {
|
|
2989
3043
|
const envRoots = [
|
|
@@ -2992,13 +3046,13 @@ function resolveRuntimeBinaryBuildWorkerSourcePath(options) {
|
|
|
2992
3046
|
process.env.PROJECT_RIG_ROOT?.trim()
|
|
2993
3047
|
].filter(Boolean);
|
|
2994
3048
|
for (const root of envRoots) {
|
|
2995
|
-
const candidate =
|
|
2996
|
-
if (
|
|
3049
|
+
const candidate = resolve18(root, "packages/runtime/src/binary-build-worker.ts");
|
|
3050
|
+
if (existsSync16(candidate)) {
|
|
2997
3051
|
return candidate;
|
|
2998
3052
|
}
|
|
2999
3053
|
}
|
|
3000
|
-
const localCandidate =
|
|
3001
|
-
return
|
|
3054
|
+
const localCandidate = resolve18(import.meta.dir, "binary-build-worker.ts");
|
|
3055
|
+
return existsSync16(localCandidate) ? localCandidate : null;
|
|
3002
3056
|
}
|
|
3003
3057
|
function resolveRuntimeBinaryBuildWorkerInvocation() {
|
|
3004
3058
|
const bunPath = Bun.which("bun");
|
|
@@ -3034,7 +3088,7 @@ function createRuntimeBinaryBuildKey(input) {
|
|
|
3034
3088
|
});
|
|
3035
3089
|
}
|
|
3036
3090
|
async function isRuntimeBinaryBuildFresh(input) {
|
|
3037
|
-
if (!
|
|
3091
|
+
if (!existsSync16(input.outputPath) || !existsSync16(input.manifestPath)) {
|
|
3038
3092
|
return false;
|
|
3039
3093
|
}
|
|
3040
3094
|
let manifest = null;
|
|
@@ -3047,7 +3101,7 @@ async function isRuntimeBinaryBuildFresh(input) {
|
|
|
3047
3101
|
return false;
|
|
3048
3102
|
}
|
|
3049
3103
|
for (const [filePath, expectedDigest] of Object.entries(manifest.inputs || {})) {
|
|
3050
|
-
if (!
|
|
3104
|
+
if (!existsSync16(filePath)) {
|
|
3051
3105
|
return false;
|
|
3052
3106
|
}
|
|
3053
3107
|
if (await sha256File(filePath) !== expectedDigest) {
|
|
@@ -3060,7 +3114,7 @@ async function writeRuntimeBinaryCacheManifest(input) {
|
|
|
3060
3114
|
const inputs = {};
|
|
3061
3115
|
for (const inputPath of Object.keys(input.metafile?.inputs || {}).sort()) {
|
|
3062
3116
|
const normalized = normalizeBuildInputPath(input.cwd, inputPath);
|
|
3063
|
-
if (!normalized || !
|
|
3117
|
+
if (!normalized || !existsSync16(normalized)) {
|
|
3064
3118
|
continue;
|
|
3065
3119
|
}
|
|
3066
3120
|
inputs[normalized] = await sha256File(normalized);
|
|
@@ -3083,7 +3137,7 @@ function normalizeBuildInputPath(cwd, inputPath) {
|
|
|
3083
3137
|
if (inputPath.startsWith("<")) {
|
|
3084
3138
|
return null;
|
|
3085
3139
|
}
|
|
3086
|
-
return
|
|
3140
|
+
return resolve18(cwd, inputPath);
|
|
3087
3141
|
}
|
|
3088
3142
|
async function sha256File(path) {
|
|
3089
3143
|
const hasher = new Bun.CryptoHasher("sha256");
|
|
@@ -3099,8 +3153,8 @@ function sortRecord(value) {
|
|
|
3099
3153
|
async function runSerializedRuntimeBinaryBuild(action) {
|
|
3100
3154
|
const previous = runtimeBinaryBuildQueue;
|
|
3101
3155
|
let release;
|
|
3102
|
-
runtimeBinaryBuildQueue = new Promise((
|
|
3103
|
-
release =
|
|
3156
|
+
runtimeBinaryBuildQueue = new Promise((resolve19) => {
|
|
3157
|
+
release = resolve19;
|
|
3104
3158
|
});
|
|
3105
3159
|
await previous;
|
|
3106
3160
|
try {
|
|
@@ -3145,11 +3199,11 @@ async function withTemporaryCwd(cwd, action) {
|
|
|
3145
3199
|
}
|
|
3146
3200
|
|
|
3147
3201
|
// packages/runtime/src/control-plane/runtime/provisioning-env.ts
|
|
3148
|
-
import { delimiter, resolve as
|
|
3202
|
+
import { delimiter, resolve as resolve20 } from "path";
|
|
3149
3203
|
|
|
3150
3204
|
// packages/runtime/src/control-plane/runtime/runtime-paths.ts
|
|
3151
|
-
import { existsSync as
|
|
3152
|
-
import { resolve as
|
|
3205
|
+
import { existsSync as existsSync17, readdirSync as readdirSync4, realpathSync } from "fs";
|
|
3206
|
+
import { resolve as resolve19 } from "path";
|
|
3153
3207
|
|
|
3154
3208
|
// packages/runtime/src/control-plane/runtime/sandbox/utils.ts
|
|
3155
3209
|
function uniq(values) {
|
|
@@ -3167,7 +3221,7 @@ function resolveBunBinaryPath() {
|
|
|
3167
3221
|
}
|
|
3168
3222
|
const home = process.env.HOME?.trim();
|
|
3169
3223
|
const fallbackCandidates = [
|
|
3170
|
-
home ?
|
|
3224
|
+
home ? resolve19(home, ".bun/bin/bun") : "",
|
|
3171
3225
|
"/opt/homebrew/bin/bun",
|
|
3172
3226
|
"/usr/local/bin/bun",
|
|
3173
3227
|
"/usr/bin/bun"
|
|
@@ -3195,8 +3249,8 @@ function resolveClaudeBinaryPath() {
|
|
|
3195
3249
|
}
|
|
3196
3250
|
const home = process.env.HOME?.trim();
|
|
3197
3251
|
const fallbackCandidates = [
|
|
3198
|
-
home ?
|
|
3199
|
-
home ?
|
|
3252
|
+
home ? resolve19(home, ".local/bin/claude") : "",
|
|
3253
|
+
home ? resolve19(home, ".local/share/claude/local/claude") : "",
|
|
3200
3254
|
"/opt/homebrew/bin/claude",
|
|
3201
3255
|
"/usr/local/bin/claude",
|
|
3202
3256
|
"/usr/bin/claude"
|
|
@@ -3210,51 +3264,51 @@ function resolveClaudeBinaryPath() {
|
|
|
3210
3264
|
throw new Error("claude not found in PATH");
|
|
3211
3265
|
}
|
|
3212
3266
|
function resolveBunInstallDir(bunBinaryPath = resolveBunBinaryPath()) {
|
|
3213
|
-
return
|
|
3267
|
+
return resolve19(bunBinaryPath, "../..");
|
|
3214
3268
|
}
|
|
3215
3269
|
function resolveClaudeInstallDir() {
|
|
3216
3270
|
const realPath = resolveClaudeBinaryPath();
|
|
3217
|
-
return
|
|
3271
|
+
return resolve19(realPath, "..");
|
|
3218
3272
|
}
|
|
3219
3273
|
function resolveNodeInstallDir() {
|
|
3220
3274
|
const preferredNode = resolvePreferredNodeBinary();
|
|
3221
3275
|
if (!preferredNode)
|
|
3222
3276
|
return null;
|
|
3223
3277
|
const explicitNode = process.env.RIG_NODE_BIN?.trim();
|
|
3224
|
-
if (explicitNode &&
|
|
3225
|
-
return preferredNode.endsWith("/bin/node") ?
|
|
3278
|
+
if (explicitNode && resolve19(explicitNode) === resolve19(preferredNode)) {
|
|
3279
|
+
return preferredNode.endsWith("/bin/node") ? resolve19(preferredNode, "../..") : resolve19(preferredNode, "..");
|
|
3226
3280
|
}
|
|
3227
3281
|
try {
|
|
3228
3282
|
const realPath = realpathSync(preferredNode);
|
|
3229
3283
|
if (realPath.endsWith("/bin/node")) {
|
|
3230
|
-
return
|
|
3284
|
+
return resolve19(realPath, "../..");
|
|
3231
3285
|
}
|
|
3232
|
-
return
|
|
3286
|
+
return resolve19(realPath, "..");
|
|
3233
3287
|
} catch {
|
|
3234
|
-
return
|
|
3288
|
+
return resolve19(preferredNode, "..");
|
|
3235
3289
|
}
|
|
3236
3290
|
}
|
|
3237
3291
|
function resolvePreferredNodeBinary() {
|
|
3238
3292
|
const candidates = [];
|
|
3239
3293
|
const envNode = process.env.RIG_NODE_BIN?.trim();
|
|
3240
3294
|
if (envNode) {
|
|
3241
|
-
const explicit =
|
|
3242
|
-
if (
|
|
3295
|
+
const explicit = resolve19(envNode);
|
|
3296
|
+
if (existsSync17(explicit)) {
|
|
3243
3297
|
return explicit;
|
|
3244
3298
|
}
|
|
3245
3299
|
}
|
|
3246
3300
|
const nvmBin = process.env.NVM_BIN?.trim();
|
|
3247
3301
|
if (nvmBin) {
|
|
3248
|
-
candidates.push(
|
|
3302
|
+
candidates.push(resolve19(nvmBin, "node"));
|
|
3249
3303
|
}
|
|
3250
3304
|
const home = process.env.HOME?.trim();
|
|
3251
3305
|
if (home) {
|
|
3252
|
-
const nvmVersionsDir =
|
|
3253
|
-
if (
|
|
3306
|
+
const nvmVersionsDir = resolve19(home, ".nvm/versions/node");
|
|
3307
|
+
if (existsSync17(nvmVersionsDir)) {
|
|
3254
3308
|
try {
|
|
3255
|
-
const versionDirs =
|
|
3309
|
+
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/, "")));
|
|
3256
3310
|
for (const versionDir of versionDirs) {
|
|
3257
|
-
candidates.push(
|
|
3311
|
+
candidates.push(resolve19(nvmVersionsDir, versionDir, "bin/node"));
|
|
3258
3312
|
}
|
|
3259
3313
|
} catch {}
|
|
3260
3314
|
}
|
|
@@ -3263,8 +3317,8 @@ function resolvePreferredNodeBinary() {
|
|
|
3263
3317
|
if (whichNode) {
|
|
3264
3318
|
candidates.push(whichNode);
|
|
3265
3319
|
}
|
|
3266
|
-
const deduped = uniq(candidates.map((candidate) =>
|
|
3267
|
-
const existing = deduped.filter((candidate) =>
|
|
3320
|
+
const deduped = uniq(candidates.map((candidate) => resolve19(candidate)));
|
|
3321
|
+
const existing = deduped.filter((candidate) => existsSync17(candidate));
|
|
3268
3322
|
if (existing.length === 0) {
|
|
3269
3323
|
return null;
|
|
3270
3324
|
}
|
|
@@ -3278,7 +3332,7 @@ function resolvePreferredNodeBinary() {
|
|
|
3278
3332
|
return existing[0] ?? null;
|
|
3279
3333
|
}
|
|
3280
3334
|
function inferNodeMajor(nodeBinaryPath) {
|
|
3281
|
-
const normalized =
|
|
3335
|
+
const normalized = resolve19(nodeBinaryPath).replace(/\\/g, "/");
|
|
3282
3336
|
const match = normalized.match(/(?:^|\/)(?:node-)?v?(\d+)\.\d+\.\d+(?:\/|$)/);
|
|
3283
3337
|
if (!match) {
|
|
3284
3338
|
return null;
|
|
@@ -3290,8 +3344,8 @@ function normalizeExecutablePath(candidate) {
|
|
|
3290
3344
|
if (!candidate) {
|
|
3291
3345
|
return "";
|
|
3292
3346
|
}
|
|
3293
|
-
const normalized =
|
|
3294
|
-
if (!
|
|
3347
|
+
const normalized = resolve19(candidate);
|
|
3348
|
+
if (!existsSync17(normalized)) {
|
|
3295
3349
|
return "";
|
|
3296
3350
|
}
|
|
3297
3351
|
try {
|
|
@@ -3301,7 +3355,7 @@ function normalizeExecutablePath(candidate) {
|
|
|
3301
3355
|
}
|
|
3302
3356
|
}
|
|
3303
3357
|
function looksLikeRuntimeGateway(candidate) {
|
|
3304
|
-
const normalized =
|
|
3358
|
+
const normalized = resolve19(candidate).replace(/\\/g, "/");
|
|
3305
3359
|
return normalized.includes("/.rig/bin/") || normalized.endsWith("/rig-shell") || normalized.endsWith("/rig-agent");
|
|
3306
3360
|
}
|
|
3307
3361
|
|
|
@@ -3322,7 +3376,7 @@ function runtimeProvisioningEnv(baseEnv = process.env) {
|
|
|
3322
3376
|
try {
|
|
3323
3377
|
return resolveClaudeInstallDir();
|
|
3324
3378
|
} catch {
|
|
3325
|
-
return
|
|
3379
|
+
return resolve20(claudeBinary, "..");
|
|
3326
3380
|
}
|
|
3327
3381
|
})() : "";
|
|
3328
3382
|
const nodeDir = resolveNodeInstallDir();
|
|
@@ -3332,8 +3386,8 @@ function runtimeProvisioningEnv(baseEnv = process.env) {
|
|
|
3332
3386
|
`${bunDir}/bin`,
|
|
3333
3387
|
claudeDir,
|
|
3334
3388
|
nodeDir ? `${nodeDir}/bin` : "",
|
|
3335
|
-
realHome ?
|
|
3336
|
-
realHome ?
|
|
3389
|
+
realHome ? resolve20(realHome, ".local/bin") : "",
|
|
3390
|
+
realHome ? resolve20(realHome, ".cargo/bin") : "",
|
|
3337
3391
|
...inheritedPath,
|
|
3338
3392
|
"/usr/local/bin",
|
|
3339
3393
|
"/usr/local/sbin",
|
|
@@ -3364,9 +3418,9 @@ function runtimeProvisioningEnv(baseEnv = process.env) {
|
|
|
3364
3418
|
// packages/runtime/src/control-plane/native/validator-binaries.ts
|
|
3365
3419
|
function resolveValidatorBinaryPath(projectRoot, binaryName, runtimeContext) {
|
|
3366
3420
|
if (runtimeContext) {
|
|
3367
|
-
return
|
|
3421
|
+
return resolve21(runtimeContext.binDir, "validators", binaryName);
|
|
3368
3422
|
}
|
|
3369
|
-
return
|
|
3423
|
+
return resolve21(resolveHarnessPaths(projectRoot).binDir, "validators", binaryName);
|
|
3370
3424
|
}
|
|
3371
3425
|
async function ensureValidatorBinary(projectRoot, checkId, runtimeContext) {
|
|
3372
3426
|
const match = checkId.match(/^([a-z][\w-]*):([a-z][\w-]*)$/);
|
|
@@ -3381,19 +3435,19 @@ async function ensureValidatorBinary(projectRoot, checkId, runtimeContext) {
|
|
|
3381
3435
|
const binaryName = `${category}-${check}`;
|
|
3382
3436
|
const binaryPath = resolveValidatorBinaryPath(projectRoot, binaryName, runtimeContext);
|
|
3383
3437
|
const hostProjectRoot = runtimeContext?.hostProjectRoot?.trim() || projectRoot;
|
|
3384
|
-
const sourcePath =
|
|
3385
|
-
if (!
|
|
3438
|
+
const sourcePath = resolve21(hostProjectRoot, "packages/runtime/src/control-plane/validators", category, `${check}.ts`);
|
|
3439
|
+
if (!existsSync18(sourcePath)) {
|
|
3386
3440
|
return null;
|
|
3387
3441
|
}
|
|
3388
3442
|
const sourceMtime = statSync4(sourcePath).mtimeMs;
|
|
3389
|
-
const binaryExists =
|
|
3443
|
+
const binaryExists = existsSync18(binaryPath);
|
|
3390
3444
|
const binaryMtime = binaryExists ? statSync4(binaryPath).mtimeMs : 0;
|
|
3391
3445
|
if (!binaryExists || sourceMtime > binaryMtime) {
|
|
3392
3446
|
if (binaryExists) {
|
|
3393
|
-
|
|
3394
|
-
|
|
3447
|
+
rmSync5(binaryPath, { force: true });
|
|
3448
|
+
rmSync5(`${binaryPath}.build-manifest.json`, { force: true });
|
|
3395
3449
|
}
|
|
3396
|
-
|
|
3450
|
+
mkdirSync7(dirname10(binaryPath), { recursive: true });
|
|
3397
3451
|
await buildRuntimeBinary({
|
|
3398
3452
|
sourcePath: `packages/runtime/src/control-plane/validators/${category}/${check}.ts`,
|
|
3399
3453
|
outputPath: binaryPath,
|
|
@@ -3402,7 +3456,7 @@ async function ensureValidatorBinary(projectRoot, checkId, runtimeContext) {
|
|
|
3402
3456
|
env: runtimeProvisioningEnv()
|
|
3403
3457
|
});
|
|
3404
3458
|
}
|
|
3405
|
-
return
|
|
3459
|
+
return existsSync18(binaryPath) ? binaryPath : null;
|
|
3406
3460
|
}
|
|
3407
3461
|
|
|
3408
3462
|
// packages/runtime/src/control-plane/native/validator.ts
|
|
@@ -3439,20 +3493,20 @@ async function readTaskSourceValidation(projectRoot, taskId) {
|
|
|
3439
3493
|
function resolveValidationPaths(projectRoot, taskId, runtimeContext) {
|
|
3440
3494
|
if (runtimeContext) {
|
|
3441
3495
|
return {
|
|
3442
|
-
taskLogDir:
|
|
3443
|
-
artifactDir:
|
|
3496
|
+
taskLogDir: resolve22(runtimeContext.logsDir, taskId),
|
|
3497
|
+
artifactDir: resolve22(runtimeContext.workspaceDir, "artifacts", taskId)
|
|
3444
3498
|
};
|
|
3445
3499
|
}
|
|
3446
3500
|
const paths = resolveHarnessPaths(projectRoot);
|
|
3447
3501
|
return {
|
|
3448
|
-
taskLogDir:
|
|
3449
|
-
artifactDir:
|
|
3502
|
+
taskLogDir: resolve22(paths.logsDir, taskId),
|
|
3503
|
+
artifactDir: resolve22(paths.artifactsDir, taskId)
|
|
3450
3504
|
};
|
|
3451
3505
|
}
|
|
3452
3506
|
async function runValidatorBinary(projectRoot, taskId, checkId, runtimeContext) {
|
|
3453
3507
|
const binaryName = checkId.replace(":", "-");
|
|
3454
3508
|
const binaryPath = await ensureValidatorBinary(projectRoot, checkId, runtimeContext) ?? resolveValidatorBinaryPath(projectRoot, binaryName, runtimeContext);
|
|
3455
|
-
if (!
|
|
3509
|
+
if (!existsSync19(binaryPath)) {
|
|
3456
3510
|
return {
|
|
3457
3511
|
result: {
|
|
3458
3512
|
id: checkId,
|
|
@@ -3463,7 +3517,7 @@ async function runValidatorBinary(projectRoot, taskId, checkId, runtimeContext)
|
|
|
3463
3517
|
};
|
|
3464
3518
|
}
|
|
3465
3519
|
const validatorCwd = runtimeContext?.workspaceDir || resolveMonorepoRoot(projectRoot);
|
|
3466
|
-
const runtimeShellPath = runtimeContext ?
|
|
3520
|
+
const runtimeShellPath = runtimeContext ? resolve22(runtimeContext.binDir, "rig-shell") : "";
|
|
3467
3521
|
const monorepoMainRoot = runtimeContext?.monorepoMainRoot || process.env.MONOREPO_MAIN_ROOT?.trim() || resolveMonorepoRoot(projectRoot);
|
|
3468
3522
|
const validatorEnv = {
|
|
3469
3523
|
PROJECT_RIG_ROOT: runtimeContext?.hostProjectRoot || projectRoot,
|
|
@@ -3478,7 +3532,7 @@ async function runValidatorBinary(projectRoot, taskId, checkId, runtimeContext)
|
|
|
3478
3532
|
validatorEnv.RIG_LOGS_DIR = runtimeContext.logsDir;
|
|
3479
3533
|
validatorEnv.RIG_RUNTIME_BIN_DIR = runtimeContext.binDir;
|
|
3480
3534
|
}
|
|
3481
|
-
const { exitCode, stdout, stderr } = await runCaptureAsync(runtimeShellPath &&
|
|
3535
|
+
const { exitCode, stdout, stderr } = await runCaptureAsync(runtimeShellPath && existsSync19(runtimeShellPath) ? [runtimeShellPath, "run-binary", binaryPath] : [binaryPath], validatorCwd, validatorEnv);
|
|
3482
3536
|
try {
|
|
3483
3537
|
const result = JSON.parse(stdout.trim());
|
|
3484
3538
|
return { result, exitCode };
|
|
@@ -3518,8 +3572,8 @@ async function validateTask(projectRoot, taskId, runtimeContext, registry, optio
|
|
|
3518
3572
|
const configuredValidation = stringArray(taskConfig[taskId]?.validation);
|
|
3519
3573
|
const commands = resolvedContext?.validation?.length ? resolvedContext.validation : configuredValidation.length > 0 ? configuredValidation : sourceValidation.validation;
|
|
3520
3574
|
const { taskLogDir, artifactDir } = resolveValidationPaths(projectRoot, taskId, resolvedContext);
|
|
3521
|
-
|
|
3522
|
-
|
|
3575
|
+
mkdirSync8(taskLogDir, { recursive: true });
|
|
3576
|
+
mkdirSync8(artifactDir, { recursive: true });
|
|
3523
3577
|
if (commands.length === 0) {
|
|
3524
3578
|
const skipped = {
|
|
3525
3579
|
status: "skipped",
|
|
@@ -3528,7 +3582,7 @@ async function validateTask(projectRoot, taskId, runtimeContext, registry, optio
|
|
|
3528
3582
|
failed: 0,
|
|
3529
3583
|
categories: []
|
|
3530
3584
|
};
|
|
3531
|
-
|
|
3585
|
+
writeFileSync8(resolve22(artifactDir, "validation-summary.json"), `${JSON.stringify(skipped, null, 2)}
|
|
3532
3586
|
`, "utf-8");
|
|
3533
3587
|
return skipped;
|
|
3534
3588
|
}
|
|
@@ -3563,18 +3617,18 @@ async function validateTask(projectRoot, taskId, runtimeContext, registry, optio
|
|
|
3563
3617
|
exit_code: 2,
|
|
3564
3618
|
duration_seconds: 0
|
|
3565
3619
|
});
|
|
3566
|
-
const logFile2 =
|
|
3567
|
-
|
|
3568
|
-
|
|
3620
|
+
const logFile2 = resolve22(taskLogDir, `invalid-entry-validation.log`);
|
|
3621
|
+
mkdirSync8(taskLogDir, { recursive: true });
|
|
3622
|
+
writeFileSync8(logFile2, `=== ${nowIso()} :: ${cmd} ===
|
|
3569
3623
|
Invalid validation entry: not a check-ID. All entries must use format "category:check-name".
|
|
3570
3624
|
`, "utf-8");
|
|
3571
3625
|
continue;
|
|
3572
3626
|
}
|
|
3573
3627
|
const { result, exitCode } = await dispatchValidator(cmd, effectiveRegistry, validatorCtx, (id) => runValidatorBinary(projectRoot, taskId, id, resolvedContext));
|
|
3574
3628
|
const durationSeconds = Math.max(0, Math.round((Date.now() - startedAt) / 1000));
|
|
3575
|
-
const logFile =
|
|
3576
|
-
|
|
3577
|
-
|
|
3629
|
+
const logFile = resolve22(taskLogDir, `${cmd.replace(":", "-")}-validation.log`);
|
|
3630
|
+
mkdirSync8(taskLogDir, { recursive: true });
|
|
3631
|
+
writeFileSync8(logFile, `=== ${nowIso()} :: ${cmd} ===
|
|
3578
3632
|
${JSON.stringify(result, null, 2)}
|
|
3579
3633
|
`, "utf-8");
|
|
3580
3634
|
if (result.passed) {
|
|
@@ -3596,15 +3650,15 @@ ${JSON.stringify(result, null, 2)}
|
|
|
3596
3650
|
failed,
|
|
3597
3651
|
categories
|
|
3598
3652
|
};
|
|
3599
|
-
|
|
3600
|
-
|
|
3653
|
+
mkdirSync8(artifactDir, { recursive: true });
|
|
3654
|
+
writeFileSync8(resolve22(artifactDir, "validation-summary.json"), `${JSON.stringify(summary, null, 2)}
|
|
3601
3655
|
`, "utf-8");
|
|
3602
3656
|
return summary;
|
|
3603
3657
|
}
|
|
3604
3658
|
|
|
3605
3659
|
// packages/runtime/src/control-plane/native/verifier.ts
|
|
3606
|
-
import { existsSync as
|
|
3607
|
-
import { resolve as
|
|
3660
|
+
import { existsSync as existsSync20, mkdirSync as mkdirSync9, writeFileSync as writeFileSync9 } from "fs";
|
|
3661
|
+
import { resolve as resolve23 } from "path";
|
|
3608
3662
|
|
|
3609
3663
|
// packages/runtime/src/control-plane/native/pr-review-gate.ts
|
|
3610
3664
|
function parseJsonObject(value) {
|
|
@@ -4855,11 +4909,11 @@ async function verifyTask(options) {
|
|
|
4855
4909
|
const taskId = options.taskId;
|
|
4856
4910
|
const normalizedTaskId = lookupTask(options.projectRoot, taskId);
|
|
4857
4911
|
const artifactDir = artifactDirForId(options.projectRoot, taskId);
|
|
4858
|
-
|
|
4859
|
-
const validationSummaryPath =
|
|
4860
|
-
const reviewFeedbackPath =
|
|
4861
|
-
const reviewStatePath =
|
|
4862
|
-
const greptileRawPath =
|
|
4912
|
+
mkdirSync9(artifactDir, { recursive: true });
|
|
4913
|
+
const validationSummaryPath = resolve23(artifactDir, "validation-summary.json");
|
|
4914
|
+
const reviewFeedbackPath = resolve23(artifactDir, "review-feedback.md");
|
|
4915
|
+
const reviewStatePath = resolve23(artifactDir, "review-state.json");
|
|
4916
|
+
const greptileRawPath = resolve23(artifactDir, "review-greptile-raw.json");
|
|
4863
4917
|
const prStates = readPrMetadata(options.projectRoot, taskId);
|
|
4864
4918
|
const prState = prStates[0] || null;
|
|
4865
4919
|
const localReasons = [];
|
|
@@ -4871,7 +4925,7 @@ async function verifyTask(options) {
|
|
|
4871
4925
|
if (!normalizedTaskId && !await hasConfiguredSourceTask(options.projectRoot, taskId)) {
|
|
4872
4926
|
localReasons.push(`[Task Config] Unknown task id '${taskId}' in task-config or configured task source.`);
|
|
4873
4927
|
}
|
|
4874
|
-
if (!
|
|
4928
|
+
if (!existsSync20(validationSummaryPath)) {
|
|
4875
4929
|
localReasons.push(`[Artifact Quality] validation-summary.json not found at ${validationSummaryPath}.`);
|
|
4876
4930
|
} else {
|
|
4877
4931
|
const summary = await parseValidationSummary(validationSummaryPath);
|
|
@@ -4880,13 +4934,13 @@ async function verifyTask(options) {
|
|
|
4880
4934
|
}
|
|
4881
4935
|
}
|
|
4882
4936
|
for (const file of ["task-result.json", "decision-log.md", "next-actions.md", "changed-files.txt"]) {
|
|
4883
|
-
const requiredPath =
|
|
4884
|
-
if (!
|
|
4937
|
+
const requiredPath = resolve23(artifactDir, file);
|
|
4938
|
+
if (!existsSync20(requiredPath)) {
|
|
4885
4939
|
localReasons.push(`[Artifact Quality] Missing required artifact file: ${requiredPath}`);
|
|
4886
4940
|
}
|
|
4887
4941
|
}
|
|
4888
|
-
const taskResultPath =
|
|
4889
|
-
if (
|
|
4942
|
+
const taskResultPath = resolve23(artifactDir, "task-result.json");
|
|
4943
|
+
if (existsSync20(taskResultPath)) {
|
|
4890
4944
|
const taskResult = await readJsonFile2(taskResultPath);
|
|
4891
4945
|
const artifactStatus = typeof taskResult?.status === "string" ? taskResult.status.trim().toLowerCase() : "";
|
|
4892
4946
|
if (artifactStatus === "partial") {
|
|
@@ -4899,8 +4953,8 @@ async function verifyTask(options) {
|
|
|
4899
4953
|
localReasons.push("[Artifact Quality] task-result.json next actions indicate remaining implementation scope.");
|
|
4900
4954
|
}
|
|
4901
4955
|
}
|
|
4902
|
-
const nextActionsPath =
|
|
4903
|
-
if (
|
|
4956
|
+
const nextActionsPath = resolve23(artifactDir, "next-actions.md");
|
|
4957
|
+
if (existsSync20(nextActionsPath)) {
|
|
4904
4958
|
const nextActionsContent = await Bun.file(nextActionsPath).text();
|
|
4905
4959
|
if (nextActionsContent.includes("TODO: Replace this scaffold") || nextActionsContent.includes("bd-<downstream-task-id>")) {
|
|
4906
4960
|
localReasons.push("[Artifact Quality] next-actions.md still contains scaffold placeholder text. Replace with real recommendations.");
|
|
@@ -4913,12 +4967,6 @@ async function verifyTask(options) {
|
|
|
4913
4967
|
if (sourceCloseoutIssueId) {
|
|
4914
4968
|
localReasons.push(...evaluateGithubSourceIssuePrCloseout(options.projectRoot, prStates, sourceCloseoutIssueId));
|
|
4915
4969
|
}
|
|
4916
|
-
const pluginResults = await options.plugins.runValidators(taskId);
|
|
4917
|
-
for (const result of pluginResults) {
|
|
4918
|
-
if (!result.passed) {
|
|
4919
|
-
localReasons.push(`[Plugin Validator] ${result.id}: ${result.summary}`);
|
|
4920
|
-
}
|
|
4921
|
-
}
|
|
4922
4970
|
const reviewMode = await loadReviewMode(paths.reviewProfilePath, process.env.AI_REVIEW_MODE || "advisory");
|
|
4923
4971
|
const reviewProvider = await loadReviewProvider(paths.reviewProfilePath, process.env.AI_REVIEW_PROVIDER || "greptile");
|
|
4924
4972
|
if (!options.skipAiReview && localReasons.length === 0 && reviewProvider === "greptile" && reviewMode !== "off") {
|
|
@@ -4937,7 +4985,7 @@ async function verifyTask(options) {
|
|
|
4937
4985
|
aiReasons.push(`[AI Review] Required mode needs a completed Greptile approval; current verdict is ${ai.verdict}.`);
|
|
4938
4986
|
}
|
|
4939
4987
|
if (persistArtifacts && ai.rawResponse) {
|
|
4940
|
-
|
|
4988
|
+
writeFileSync9(greptileRawPath, `${ai.rawResponse}
|
|
4941
4989
|
`, "utf-8");
|
|
4942
4990
|
}
|
|
4943
4991
|
} else if (!options.skipAiReview && reviewMode === "off") {
|
|
@@ -5276,7 +5324,7 @@ function isAcceptedValidationSummary(summary) {
|
|
|
5276
5324
|
return summary.status === "skipped" && summary.total === 0 && summary.failed === 0;
|
|
5277
5325
|
}
|
|
5278
5326
|
async function loadReviewMode(reviewProfilePath, fallback) {
|
|
5279
|
-
const parsed =
|
|
5327
|
+
const parsed = existsSync20(reviewProfilePath) ? await readJsonFile2(reviewProfilePath) : null;
|
|
5280
5328
|
const mode = parsed?.mode;
|
|
5281
5329
|
if (mode === "off" || mode === "advisory" || mode === "required") {
|
|
5282
5330
|
return mode;
|
|
@@ -5287,7 +5335,7 @@ async function loadReviewMode(reviewProfilePath, fallback) {
|
|
|
5287
5335
|
return "advisory";
|
|
5288
5336
|
}
|
|
5289
5337
|
async function loadReviewProvider(reviewProfilePath, fallback) {
|
|
5290
|
-
const parsed =
|
|
5338
|
+
const parsed = existsSync20(reviewProfilePath) ? await readJsonFile2(reviewProfilePath) : null;
|
|
5291
5339
|
const provider = parsed?.provider;
|
|
5292
5340
|
if (typeof provider === "string" && provider.trim().length > 0) {
|
|
5293
5341
|
return provider;
|
|
@@ -5446,7 +5494,7 @@ function writeFeedbackFile(options) {
|
|
|
5446
5494
|
if (options.aiRawFeedback) {
|
|
5447
5495
|
lines.push("## Raw Reviewer Feedback", "", "```text", options.aiRawFeedback, "```", "");
|
|
5448
5496
|
}
|
|
5449
|
-
|
|
5497
|
+
writeFileSync9(options.output, `${lines.join(`
|
|
5450
5498
|
`)}
|
|
5451
5499
|
`, "utf-8");
|
|
5452
5500
|
}
|
|
@@ -5463,7 +5511,7 @@ function writeReviewStateFile(options) {
|
|
|
5463
5511
|
ai_warnings: options.aiWarnings,
|
|
5464
5512
|
updated_at: nowIso()
|
|
5465
5513
|
};
|
|
5466
|
-
|
|
5514
|
+
writeFileSync9(options.output, `${JSON.stringify(payload, null, 2)}
|
|
5467
5515
|
`, "utf-8");
|
|
5468
5516
|
}
|
|
5469
5517
|
async function runGreptileReviewForPr(options) {
|
|
@@ -6250,7 +6298,7 @@ function filterActionableGithubGreptileThreads(threads) {
|
|
|
6250
6298
|
}
|
|
6251
6299
|
function resolvePrRepoRoot(projectRoot, prState) {
|
|
6252
6300
|
const runtimeWorkspace = process.env.RIG_TASK_WORKSPACE?.trim();
|
|
6253
|
-
if (prState.target === "monorepo" && runtimeWorkspace &&
|
|
6301
|
+
if (prState.target === "monorepo" && runtimeWorkspace && existsSync20(resolve23(runtimeWorkspace, ".git"))) {
|
|
6254
6302
|
return runtimeWorkspace;
|
|
6255
6303
|
}
|
|
6256
6304
|
const paths = resolveHarnessPaths(projectRoot);
|
|
@@ -6622,16 +6670,16 @@ async function taskDeps(projectRoot, taskId) {
|
|
|
6622
6670
|
for (const dep of deps) {
|
|
6623
6671
|
const artifactDir = artifactDirForId(projectRoot, dep);
|
|
6624
6672
|
console.log(`=== ${dep} ===`);
|
|
6625
|
-
if (!
|
|
6673
|
+
if (!existsSync21(artifactDir)) {
|
|
6626
6674
|
console.log(` (no artifacts yet)
|
|
6627
6675
|
`);
|
|
6628
6676
|
continue;
|
|
6629
6677
|
}
|
|
6630
|
-
printArtifactSection(
|
|
6631
|
-
printArtifactSection(
|
|
6632
|
-
const changedFiles =
|
|
6633
|
-
if (
|
|
6634
|
-
const lines =
|
|
6678
|
+
printArtifactSection(resolve24(artifactDir, "decision-log.md"), "--- Decisions ---");
|
|
6679
|
+
printArtifactSection(resolve24(artifactDir, "next-actions.md"), "--- Next Actions (for you) ---");
|
|
6680
|
+
const changedFiles = resolve24(artifactDir, "changed-files.txt");
|
|
6681
|
+
if (existsSync21(changedFiles)) {
|
|
6682
|
+
const lines = readFileSync11(changedFiles, "utf-8").split(/\r?\n/).filter(Boolean);
|
|
6635
6683
|
console.log(`--- Changed Files (${lines.length}) ---`);
|
|
6636
6684
|
for (const line of lines) {
|
|
6637
6685
|
console.log(line);
|
|
@@ -6676,12 +6724,12 @@ function taskRecord(projectRoot, type, text, taskId) {
|
|
|
6676
6724
|
throw new Error("No active task.");
|
|
6677
6725
|
}
|
|
6678
6726
|
const paths = resolveHarnessPaths(projectRoot);
|
|
6679
|
-
|
|
6727
|
+
mkdirSync10(paths.stateDir, { recursive: true });
|
|
6680
6728
|
if (type === "decision") {
|
|
6681
|
-
const artifactDir =
|
|
6682
|
-
|
|
6729
|
+
const artifactDir = resolve24(paths.artifactsDir, activeTask);
|
|
6730
|
+
mkdirSync10(artifactDir, { recursive: true });
|
|
6683
6731
|
const timestamp = nowIso();
|
|
6684
|
-
appendFileSync(
|
|
6732
|
+
appendFileSync(resolve24(artifactDir, "decision-log.md"), `
|
|
6685
6733
|
### ${timestamp}
|
|
6686
6734
|
|
|
6687
6735
|
${text}
|
|
@@ -6691,14 +6739,14 @@ ${text}
|
|
|
6691
6739
|
return;
|
|
6692
6740
|
}
|
|
6693
6741
|
const failedPath = paths.failedApproachesPath;
|
|
6694
|
-
if (!
|
|
6695
|
-
|
|
6742
|
+
if (!existsSync21(failedPath)) {
|
|
6743
|
+
writeFileSync10(failedPath, `# Failed Approaches Log
|
|
6696
6744
|
|
|
6697
6745
|
This file records approaches that did not work.
|
|
6698
6746
|
|
|
6699
6747
|
`, "utf-8");
|
|
6700
6748
|
}
|
|
6701
|
-
const content =
|
|
6749
|
+
const content = readFileSync11(failedPath, "utf-8");
|
|
6702
6750
|
const attempts = (content.match(new RegExp(`^## ${escapeRegExp(activeTask)}\\b`, "gm")) || []).length + 1;
|
|
6703
6751
|
appendFileSync(failedPath, `
|
|
6704
6752
|
## ${activeTask} - Attempt ${attempts} (${nowIso()})
|
|
@@ -6715,40 +6763,40 @@ function taskArtifacts(projectRoot, taskId) {
|
|
|
6715
6763
|
throw new Error("No active task.");
|
|
6716
6764
|
}
|
|
6717
6765
|
const paths = resolveHarnessPaths(projectRoot);
|
|
6718
|
-
const artifactDir =
|
|
6719
|
-
|
|
6766
|
+
const artifactDir = resolve24(paths.artifactsDir, activeTask);
|
|
6767
|
+
mkdirSync10(artifactDir, { recursive: true });
|
|
6720
6768
|
const changed = changedFilesForTask(projectRoot, activeTask, true);
|
|
6721
|
-
|
|
6769
|
+
writeFileSync10(resolve24(artifactDir, "changed-files.txt"), `${changed.join(`
|
|
6722
6770
|
`)}
|
|
6723
6771
|
`, "utf-8");
|
|
6724
6772
|
console.log(`changed-files.txt: ${changed.length} files`);
|
|
6725
|
-
const taskResultPath =
|
|
6726
|
-
if (!
|
|
6773
|
+
const taskResultPath = resolve24(artifactDir, "task-result.json");
|
|
6774
|
+
if (!existsSync21(taskResultPath)) {
|
|
6727
6775
|
const template = {
|
|
6728
6776
|
task_id: activeTask,
|
|
6729
6777
|
status: "completed",
|
|
6730
6778
|
summary: "TODO: Write a one-line summary of what you did",
|
|
6731
6779
|
completed_at: nowIso()
|
|
6732
6780
|
};
|
|
6733
|
-
|
|
6781
|
+
writeFileSync10(taskResultPath, `${JSON.stringify(template, null, 2)}
|
|
6734
6782
|
`, "utf-8");
|
|
6735
6783
|
console.log("task-result.json: created (update the summary!)");
|
|
6736
6784
|
} else {
|
|
6737
6785
|
console.log("task-result.json: already exists");
|
|
6738
6786
|
}
|
|
6739
|
-
const decisionLogPath =
|
|
6740
|
-
if (!
|
|
6787
|
+
const decisionLogPath = resolve24(artifactDir, "decision-log.md");
|
|
6788
|
+
if (!existsSync21(decisionLogPath)) {
|
|
6741
6789
|
const content = `# Decision Log: ${activeTask}
|
|
6742
6790
|
|
|
6743
6791
|
Record key decisions here using: rig-agent record decision "..."
|
|
6744
6792
|
`;
|
|
6745
|
-
|
|
6793
|
+
writeFileSync10(decisionLogPath, content, "utf-8");
|
|
6746
6794
|
console.log("decision-log.md: created (record your decisions!)");
|
|
6747
6795
|
} else {
|
|
6748
6796
|
console.log("decision-log.md: already exists");
|
|
6749
6797
|
}
|
|
6750
|
-
const nextActionsPath =
|
|
6751
|
-
if (!
|
|
6798
|
+
const nextActionsPath = resolve24(artifactDir, "next-actions.md");
|
|
6799
|
+
if (!existsSync21(nextActionsPath)) {
|
|
6752
6800
|
const content = [
|
|
6753
6801
|
`# Next Actions: ${activeTask}`,
|
|
6754
6802
|
"",
|
|
@@ -6765,13 +6813,13 @@ Record key decisions here using: rig-agent record decision "..."
|
|
|
6765
6813
|
""
|
|
6766
6814
|
].join(`
|
|
6767
6815
|
`);
|
|
6768
|
-
|
|
6816
|
+
writeFileSync10(nextActionsPath, content, "utf-8");
|
|
6769
6817
|
console.log("next-actions.md: created (add recommendations for downstream tasks!)");
|
|
6770
6818
|
} else {
|
|
6771
6819
|
console.log("next-actions.md: already exists");
|
|
6772
6820
|
}
|
|
6773
|
-
const validationSummaryPath =
|
|
6774
|
-
if (
|
|
6821
|
+
const validationSummaryPath = resolve24(artifactDir, "validation-summary.json");
|
|
6822
|
+
if (existsSync21(validationSummaryPath)) {
|
|
6775
6823
|
console.log("validation-summary.json: already exists");
|
|
6776
6824
|
} else {
|
|
6777
6825
|
console.log("validation-summary.json: not yet created (run: rig-agent validate)");
|
|
@@ -6814,12 +6862,12 @@ async function taskValidate(projectRoot, taskId, validatorRegistry) {
|
|
|
6814
6862
|
console.log(`Validation passed: ${summary.passed}/${summary.total}`);
|
|
6815
6863
|
return true;
|
|
6816
6864
|
}
|
|
6817
|
-
async function taskVerify(projectRoot,
|
|
6865
|
+
async function taskVerify(projectRoot, taskId) {
|
|
6818
6866
|
const activeTask = taskId || currentTaskId(projectRoot);
|
|
6819
6867
|
if (!activeTask) {
|
|
6820
6868
|
throw new Error("No active task.");
|
|
6821
6869
|
}
|
|
6822
|
-
const outcome = await verifyTask({ projectRoot, taskId: activeTask
|
|
6870
|
+
const outcome = await verifyTask({ projectRoot, taskId: activeTask });
|
|
6823
6871
|
if (!outcome.approved) {
|
|
6824
6872
|
console.log("REJECT:");
|
|
6825
6873
|
for (const reason of outcome.localReasons) {
|
|
@@ -6862,7 +6910,7 @@ function collectTaskChangedFiles(projectRoot, taskId, includeCommitted) {
|
|
|
6862
6910
|
[projectRoot, ""],
|
|
6863
6911
|
[monorepoRepoRoot, ""]
|
|
6864
6912
|
]) {
|
|
6865
|
-
if (!
|
|
6913
|
+
if (!existsSync21(resolve24(repo, ".git"))) {
|
|
6866
6914
|
continue;
|
|
6867
6915
|
}
|
|
6868
6916
|
if (includeCommitted && repo === monorepoRepoRoot) {
|
|
@@ -6900,8 +6948,8 @@ function filterTaskChangedFiles(projectRoot, taskId, files, scoped) {
|
|
|
6900
6948
|
}
|
|
6901
6949
|
function resolveTaskMonorepoRoot(projectRoot) {
|
|
6902
6950
|
const runtimeWorkspace = loadRuntimeContextFromEnv()?.workspaceDir || process.env.RIG_TASK_WORKSPACE?.trim();
|
|
6903
|
-
if (runtimeWorkspace &&
|
|
6904
|
-
return
|
|
6951
|
+
if (runtimeWorkspace && existsSync21(resolve24(runtimeWorkspace, ".git"))) {
|
|
6952
|
+
return resolve24(runtimeWorkspace);
|
|
6905
6953
|
}
|
|
6906
6954
|
return resolveHarnessPaths(projectRoot).monorepoRoot;
|
|
6907
6955
|
}
|
|
@@ -6929,7 +6977,7 @@ function resolveRuntimeInitialHeadCommit(projectRoot, repo) {
|
|
|
6929
6977
|
const runtimeContext = loadRuntimeContextFromEnv();
|
|
6930
6978
|
if (runtimeContext?.initialHeadCommits?.monorepo?.trim()) {
|
|
6931
6979
|
const monorepoRoot = resolveTaskMonorepoRoot(projectRoot);
|
|
6932
|
-
if (
|
|
6980
|
+
if (resolve24(monorepoRoot) === resolve24(repo)) {
|
|
6933
6981
|
return runtimeContext.initialHeadCommits.monorepo.trim();
|
|
6934
6982
|
}
|
|
6935
6983
|
}
|
|
@@ -6939,7 +6987,7 @@ function resolveMonorepoBaseCommit(projectRoot, repo) {
|
|
|
6939
6987
|
const runtimeContext = loadRuntimeContextFromEnv();
|
|
6940
6988
|
if (runtimeContext?.monorepoBaseCommit?.trim()) {
|
|
6941
6989
|
const monorepoRoot = resolveTaskMonorepoRoot(projectRoot);
|
|
6942
|
-
if (
|
|
6990
|
+
if (resolve24(monorepoRoot) === resolve24(repo)) {
|
|
6943
6991
|
return runtimeContext.monorepoBaseCommit.trim();
|
|
6944
6992
|
}
|
|
6945
6993
|
}
|
|
@@ -6973,7 +7021,7 @@ function resolveRuntimeDirtyBaseline(projectRoot, repo) {
|
|
|
6973
7021
|
return new Set;
|
|
6974
7022
|
}
|
|
6975
7023
|
const monorepoRoot = resolveTaskMonorepoRoot(projectRoot);
|
|
6976
|
-
const selected =
|
|
7024
|
+
const selected = resolve24(repo) === resolve24(monorepoRoot) ? dirtyFiles.monorepo : resolve24(repo) === resolve24(projectRoot) ? dirtyFiles.project : undefined;
|
|
6977
7025
|
return new Set((selected || []).map((file) => normalizeChangedFilePath(file)).filter(Boolean));
|
|
6978
7026
|
}
|
|
6979
7027
|
function normalizeChangedFilePath(file) {
|
|
@@ -7073,12 +7121,12 @@ function printIndented(text) {
|
|
|
7073
7121
|
}
|
|
7074
7122
|
}
|
|
7075
7123
|
function readLocalBeadsTasks(projectRoot) {
|
|
7076
|
-
const issuesPath =
|
|
7077
|
-
if (!
|
|
7124
|
+
const issuesPath = resolve24(resolveMonorepoRoot2(projectRoot), ".beads/issues.jsonl");
|
|
7125
|
+
if (!existsSync21(issuesPath)) {
|
|
7078
7126
|
return [];
|
|
7079
7127
|
}
|
|
7080
7128
|
const tasks = [];
|
|
7081
|
-
for (const line of
|
|
7129
|
+
for (const line of readFileSync11(issuesPath, "utf-8").split(/\r?\n/)) {
|
|
7082
7130
|
const trimmed = line.trim();
|
|
7083
7131
|
if (!trimmed) {
|
|
7084
7132
|
continue;
|
|
@@ -7191,11 +7239,11 @@ function taskDependencies(projectRoot, taskId, tracker) {
|
|
|
7191
7239
|
return [...ids].sort();
|
|
7192
7240
|
}
|
|
7193
7241
|
function printArtifactSection(path, header) {
|
|
7194
|
-
if (!
|
|
7242
|
+
if (!existsSync21(path)) {
|
|
7195
7243
|
return;
|
|
7196
7244
|
}
|
|
7197
7245
|
console.log(header);
|
|
7198
|
-
process.stdout.write(
|
|
7246
|
+
process.stdout.write(readFileSync11(path, "utf-8"));
|
|
7199
7247
|
console.log("");
|
|
7200
7248
|
}
|
|
7201
7249
|
function escapeRegExp(value) {
|
|
@@ -7235,8 +7283,8 @@ function isRuntimeGatewayGhPath(candidate) {
|
|
|
7235
7283
|
}
|
|
7236
7284
|
function resolveOptionalMonorepoRoot(projectRoot) {
|
|
7237
7285
|
const runtimeWorkspace = process.env.RIG_TASK_WORKSPACE?.trim();
|
|
7238
|
-
if (runtimeWorkspace &&
|
|
7239
|
-
return
|
|
7286
|
+
if (runtimeWorkspace && existsSync22(resolve25(runtimeWorkspace, ".git"))) {
|
|
7287
|
+
return resolve25(runtimeWorkspace);
|
|
7240
7288
|
}
|
|
7241
7289
|
try {
|
|
7242
7290
|
return resolveMonorepoRoot2(projectRoot);
|
|
@@ -7261,7 +7309,7 @@ function resolveGitBinary(projectRoot) {
|
|
|
7261
7309
|
if (!candidate || isRuntimeGatewayGitPath(candidate)) {
|
|
7262
7310
|
continue;
|
|
7263
7311
|
}
|
|
7264
|
-
if (
|
|
7312
|
+
if (existsSync22(candidate)) {
|
|
7265
7313
|
return candidate;
|
|
7266
7314
|
}
|
|
7267
7315
|
}
|
|
@@ -7321,11 +7369,11 @@ function gitPreflight(projectRoot, taskId, strict) {
|
|
|
7321
7369
|
const expected = resolvedTask ? `rig/${resolveTaskBranchId(projectRoot, resolvedTask)}` : "";
|
|
7322
7370
|
console.log("=== Git Flow Preflight ===");
|
|
7323
7371
|
let issues = 0;
|
|
7324
|
-
if (!
|
|
7372
|
+
if (!existsSync22(resolve25(projectRoot, ".git"))) {
|
|
7325
7373
|
console.log(`ERROR: project root is not a git repo (${projectRoot})`);
|
|
7326
7374
|
issues += 1;
|
|
7327
7375
|
}
|
|
7328
|
-
if (monorepoRoot &&
|
|
7376
|
+
if (monorepoRoot && existsSync22(resolve25(monorepoRoot, ".git"))) {
|
|
7329
7377
|
const monoBranch = branchName(projectRoot, monorepoRoot);
|
|
7330
7378
|
if (expected && monoBranch !== expected) {
|
|
7331
7379
|
console.log(`WARN: monorepo branch is ${monoBranch}, expected ${expected} for task ${resolvedTask}`);
|
|
@@ -7359,7 +7407,7 @@ function gitSyncBranch(projectRoot, taskId, targetRepo = "monorepo") {
|
|
|
7359
7407
|
}
|
|
7360
7408
|
const repoRoot = targetRepo === "monorepo" ? resolveOptionalMonorepoRoot(projectRoot) || resolveMonorepoRoot2(projectRoot) : projectRoot;
|
|
7361
7409
|
const repoLabel = targetRepo === "monorepo" ? "Monorepo" : "Project";
|
|
7362
|
-
if (!
|
|
7410
|
+
if (!existsSync22(resolve25(repoRoot, ".git"))) {
|
|
7363
7411
|
throw new Error(`${repoLabel} repo not found at ${repoRoot}`);
|
|
7364
7412
|
}
|
|
7365
7413
|
const branchId = resolveTaskBranchId(projectRoot, resolvedTask);
|
|
@@ -7403,8 +7451,8 @@ function gitCommit(options) {
|
|
|
7403
7451
|
function gitSnapshot(projectRoot, taskId, outputPath) {
|
|
7404
7452
|
const monorepoRoot = resolveOptionalMonorepoRoot(projectRoot);
|
|
7405
7453
|
const resolvedTask = taskId || safeCurrentTaskId(projectRoot);
|
|
7406
|
-
const output = outputPath || (resolvedTask ? resolveArtifactSnapshot(projectRoot, resolvedTask) :
|
|
7407
|
-
|
|
7454
|
+
const output = outputPath || (resolvedTask ? resolveArtifactSnapshot(projectRoot, resolvedTask) : resolve25(resolve25(projectRoot, ".rig", "state"), "git-state.txt"));
|
|
7455
|
+
mkdirSync11(dirname11(output), { recursive: true });
|
|
7408
7456
|
const lines = ["# Git Snapshot", `timestamp: ${nowIso()}`];
|
|
7409
7457
|
if (resolvedTask) {
|
|
7410
7458
|
lines.push(`task: ${resolvedTask}`);
|
|
@@ -7414,7 +7462,7 @@ function gitSnapshot(projectRoot, taskId, outputPath) {
|
|
|
7414
7462
|
if (monorepoRoot && monorepoRoot !== projectRoot) {
|
|
7415
7463
|
lines.push(...snapshotRepo(projectRoot, "monorepo", monorepoRoot));
|
|
7416
7464
|
}
|
|
7417
|
-
|
|
7465
|
+
writeFileSync11(output, `${lines.join(`
|
|
7418
7466
|
`)}
|
|
7419
7467
|
`, "utf-8");
|
|
7420
7468
|
return output;
|
|
@@ -7438,7 +7486,7 @@ function gitOpenPr(options) {
|
|
|
7438
7486
|
} else if (taskId) {
|
|
7439
7487
|
gitSyncBranch(options.projectRoot, taskId, "project");
|
|
7440
7488
|
}
|
|
7441
|
-
if (!
|
|
7489
|
+
if (!existsSync22(resolve25(repoRoot, ".git"))) {
|
|
7442
7490
|
throw new Error(`Repository not available for open-pr target ${target}: ${repoRoot}`);
|
|
7443
7491
|
}
|
|
7444
7492
|
const branch = branchName(options.projectRoot, repoRoot);
|
|
@@ -7651,12 +7699,12 @@ function assertPrHasNoGitConflicts(prState, repoLabel, baseRef) {
|
|
|
7651
7699
|
}
|
|
7652
7700
|
function writePrMetadata(projectRoot, taskId, result) {
|
|
7653
7701
|
const dir = artifactDirForId(projectRoot, taskId);
|
|
7654
|
-
|
|
7655
|
-
const path =
|
|
7702
|
+
mkdirSync11(dir, { recursive: true });
|
|
7703
|
+
const path = resolve25(dir, "pr-state.json");
|
|
7656
7704
|
let prs = {};
|
|
7657
|
-
if (
|
|
7705
|
+
if (existsSync22(path)) {
|
|
7658
7706
|
try {
|
|
7659
|
-
const parsed = JSON.parse(
|
|
7707
|
+
const parsed = JSON.parse(readFileSync12(path, "utf-8"));
|
|
7660
7708
|
if (parsed && typeof parsed === "object" && parsed.prs && typeof parsed.prs === "object") {
|
|
7661
7709
|
prs = parsed.prs;
|
|
7662
7710
|
}
|
|
@@ -7672,16 +7720,16 @@ function writePrMetadata(projectRoot, taskId, result) {
|
|
|
7672
7720
|
...primary || {},
|
|
7673
7721
|
updated_at: nowIso()
|
|
7674
7722
|
};
|
|
7675
|
-
|
|
7723
|
+
writeFileSync11(path, `${JSON.stringify(artifact, null, 2)}
|
|
7676
7724
|
`, "utf-8");
|
|
7677
7725
|
}
|
|
7678
7726
|
function readPrMetadata(projectRoot, taskId) {
|
|
7679
|
-
const path =
|
|
7680
|
-
if (!
|
|
7727
|
+
const path = resolve25(artifactDirForId(projectRoot, taskId), "pr-state.json");
|
|
7728
|
+
if (!existsSync22(path)) {
|
|
7681
7729
|
return [];
|
|
7682
7730
|
}
|
|
7683
7731
|
try {
|
|
7684
|
-
const parsed = JSON.parse(
|
|
7732
|
+
const parsed = JSON.parse(readFileSync12(path, "utf-8"));
|
|
7685
7733
|
if (!parsed || typeof parsed !== "object") {
|
|
7686
7734
|
return [];
|
|
7687
7735
|
}
|
|
@@ -7694,8 +7742,8 @@ function readPrMetadata(projectRoot, taskId) {
|
|
|
7694
7742
|
}
|
|
7695
7743
|
}
|
|
7696
7744
|
function resolveArtifactSnapshot(projectRoot, taskId) {
|
|
7697
|
-
const artifactDir =
|
|
7698
|
-
return
|
|
7745
|
+
const artifactDir = resolve25(resolveHarnessPaths(projectRoot).artifactsDir, taskId);
|
|
7746
|
+
return resolve25(artifactDir, "git-state.txt");
|
|
7699
7747
|
}
|
|
7700
7748
|
function isGitOpenPrResult(value) {
|
|
7701
7749
|
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
@@ -7754,14 +7802,14 @@ function resolveGithubCliBinary(projectRoot) {
|
|
|
7754
7802
|
}
|
|
7755
7803
|
const explicitPathEntries = (process.env.PATH || "").split(":").map((entry) => entry.trim()).filter(Boolean);
|
|
7756
7804
|
for (const entry of explicitPathEntries) {
|
|
7757
|
-
candidates.add(
|
|
7805
|
+
candidates.add(resolve25(entry, "gh"));
|
|
7758
7806
|
}
|
|
7759
7807
|
const bunResolved = Bun.which("gh");
|
|
7760
7808
|
if (bunResolved) {
|
|
7761
7809
|
candidates.add(bunResolved);
|
|
7762
7810
|
}
|
|
7763
7811
|
for (const candidate of candidates) {
|
|
7764
|
-
if (candidate &&
|
|
7812
|
+
if (candidate && existsSync22(candidate) && !isRuntimeGatewayGhPath(candidate)) {
|
|
7765
7813
|
return candidate;
|
|
7766
7814
|
}
|
|
7767
7815
|
}
|
|
@@ -7791,7 +7839,7 @@ function resolveRepoNameWithOwner(projectRoot, repoRoot) {
|
|
|
7791
7839
|
return resolveGithubRepoNameWithOwnerFromGitRoot(projectRoot, repoRoot, repoRoot, visited);
|
|
7792
7840
|
}
|
|
7793
7841
|
function resolveGithubRepoNameWithOwnerFromGitRoot(projectRoot, gitRoot, cwd, visited) {
|
|
7794
|
-
const normalizedGitRoot =
|
|
7842
|
+
const normalizedGitRoot = resolve25(gitRoot);
|
|
7795
7843
|
if (visited.has(normalizedGitRoot)) {
|
|
7796
7844
|
return "";
|
|
7797
7845
|
}
|
|
@@ -7863,7 +7911,7 @@ function resolveNetworkRemoteName(projectRoot, repoRoot, repoNameWithOwner) {
|
|
|
7863
7911
|
return remotes.includes("origin") ? "origin" : remotes[0];
|
|
7864
7912
|
}
|
|
7865
7913
|
function gitQuery(projectRoot, gitRoot, cwd, ...args) {
|
|
7866
|
-
const gitArgs =
|
|
7914
|
+
const gitArgs = existsSync22(resolve25(gitRoot, ".git")) ? gitCmd(projectRoot, gitRoot, ...args) : [resolveGitBinary(projectRoot), "--git-dir", gitRoot, ...args];
|
|
7867
7915
|
return runCapture2(gitArgs, cwd, projectRoot);
|
|
7868
7916
|
}
|
|
7869
7917
|
function resolveLocalGitRemoteRoot(remoteUrl, gitRoot) {
|
|
@@ -7881,9 +7929,9 @@ function resolveLocalGitRemoteRoot(remoteUrl, gitRoot) {
|
|
|
7881
7929
|
} else if (/^[a-z][a-z0-9+.-]*:\/\//i.test(normalized) || /^[^@]+@[^:]+:.+$/.test(normalized)) {
|
|
7882
7930
|
return "";
|
|
7883
7931
|
} else if (!isAbsolute2(normalized)) {
|
|
7884
|
-
candidate =
|
|
7932
|
+
candidate = resolve25(gitRoot, normalized);
|
|
7885
7933
|
}
|
|
7886
|
-
return
|
|
7934
|
+
return existsSync22(candidate) ? candidate : "";
|
|
7887
7935
|
}
|
|
7888
7936
|
function normalizeGithubRepoNameWithOwner(value) {
|
|
7889
7937
|
const normalized = value.trim();
|
|
@@ -8010,7 +8058,7 @@ function inferReviewerFromChangedFiles(projectRoot, repoRoot, baseRef, branchRef
|
|
|
8010
8058
|
return best;
|
|
8011
8059
|
}
|
|
8012
8060
|
function snapshotRepo(projectRoot, label, repo) {
|
|
8013
|
-
if (!
|
|
8061
|
+
if (!existsSync22(resolve25(repo, ".git"))) {
|
|
8014
8062
|
return [`## ${label}`, `repo: ${repo}`, "status: unavailable", ""];
|
|
8015
8063
|
}
|
|
8016
8064
|
const status = runCapture2(gitCmd(projectRoot, repo, "status", "--short"), projectRoot).stdout.trim();
|
|
@@ -8033,7 +8081,7 @@ function snapshotRepo(projectRoot, label, repo) {
|
|
|
8033
8081
|
];
|
|
8034
8082
|
}
|
|
8035
8083
|
function commitRepo(projectRoot, repo, label, message, allowEmpty, scoped, files, changedFilesManifest) {
|
|
8036
|
-
if (!
|
|
8084
|
+
if (!existsSync22(resolve25(repo, ".git"))) {
|
|
8037
8085
|
console.log(`Skipping ${label}: repo not available (${repo})`);
|
|
8038
8086
|
return;
|
|
8039
8087
|
}
|
|
@@ -8065,18 +8113,18 @@ function commitRepo(projectRoot, repo, label, message, allowEmpty, scoped, files
|
|
|
8065
8113
|
console.log(`Committed ${label}: ${message}`);
|
|
8066
8114
|
}
|
|
8067
8115
|
function readChangedFilesManifest(projectRoot, taskId) {
|
|
8068
|
-
const manifestPath =
|
|
8069
|
-
if (!
|
|
8116
|
+
const manifestPath = resolve25(artifactDirForId(projectRoot, taskId), "changed-files.txt");
|
|
8117
|
+
if (!existsSync22(manifestPath)) {
|
|
8070
8118
|
return [];
|
|
8071
8119
|
}
|
|
8072
|
-
const files =
|
|
8120
|
+
const files = readFileSync12(manifestPath, "utf-8").split(/\r?\n/).map((line) => normalizeChangedFilePath2(line)).filter(Boolean);
|
|
8073
8121
|
return [...new Set(files)];
|
|
8074
8122
|
}
|
|
8075
8123
|
function refreshChangedFilesManifest(projectRoot, taskId) {
|
|
8076
|
-
const manifestPath =
|
|
8077
|
-
|
|
8124
|
+
const manifestPath = resolve25(artifactDirForId(projectRoot, taskId), "changed-files.txt");
|
|
8125
|
+
mkdirSync11(dirname11(manifestPath), { recursive: true });
|
|
8078
8126
|
const changedFiles = changedFilesForTask(projectRoot, taskId, true);
|
|
8079
|
-
|
|
8127
|
+
writeFileSync11(manifestPath, `${changedFiles.join(`
|
|
8080
8128
|
`)}
|
|
8081
8129
|
`, "utf-8");
|
|
8082
8130
|
return manifestPath;
|
|
@@ -8189,7 +8237,7 @@ function repoHasPathChange(projectRoot, repoRoot, relativePath) {
|
|
|
8189
8237
|
return result.exitCode === 0 && result.stdout.trim().length > 0;
|
|
8190
8238
|
}
|
|
8191
8239
|
function stageExcludePathspecs(repoRoot) {
|
|
8192
|
-
const patterns =
|
|
8240
|
+
const patterns = existsSync22(resolve25(repoRoot, ".rig", "task-config.json")) ? [...TASK_RUNTIME_STAGE_EXCLUDES, ...GENERATED_STAGE_EXCLUDES] : [".rig/**", ...GENERATED_STAGE_EXCLUDES];
|
|
8193
8241
|
return patterns.map((pattern) => `:(glob,exclude)${pattern}`);
|
|
8194
8242
|
}
|
|
8195
8243
|
function pathResolvesBeyondSymlink(repoRoot, relativePath) {
|
|
@@ -8199,7 +8247,7 @@ function pathResolvesBeyondSymlink(repoRoot, relativePath) {
|
|
|
8199
8247
|
}
|
|
8200
8248
|
let current = repoRoot;
|
|
8201
8249
|
for (let index = 0;index < parts.length - 1; index += 1) {
|
|
8202
|
-
current =
|
|
8250
|
+
current = resolve25(current, parts[index]);
|
|
8203
8251
|
try {
|
|
8204
8252
|
if (lstatSync(current).isSymbolicLink()) {
|
|
8205
8253
|
return true;
|
|
@@ -8211,7 +8259,7 @@ function pathResolvesBeyondSymlink(repoRoot, relativePath) {
|
|
|
8211
8259
|
return false;
|
|
8212
8260
|
}
|
|
8213
8261
|
function printRepoStatus(projectRoot, label, repo, expectedBranch) {
|
|
8214
|
-
if (!
|
|
8262
|
+
if (!existsSync22(resolve25(repo, ".git"))) {
|
|
8215
8263
|
console.log(`${label}: unavailable (${repo})`);
|
|
8216
8264
|
return;
|
|
8217
8265
|
}
|
|
@@ -8247,7 +8295,7 @@ function resolveTaskBranchId(projectRoot, taskId) {
|
|
|
8247
8295
|
}
|
|
8248
8296
|
} catch {}
|
|
8249
8297
|
const artifactDir = artifactDirForId(projectRoot, taskId);
|
|
8250
|
-
if (
|
|
8298
|
+
if (existsSync22(artifactDir)) {
|
|
8251
8299
|
return taskId;
|
|
8252
8300
|
}
|
|
8253
8301
|
throw new Error(`Unknown task id: ${taskId}`);
|
|
@@ -8283,11 +8331,11 @@ function runCapture2(command, cwd, projectRoot = cwd) {
|
|
|
8283
8331
|
}
|
|
8284
8332
|
function runtimeGitEnv(projectRoot) {
|
|
8285
8333
|
const { ctx, runtimeRoot } = resolveRuntimeMetadata(projectRoot);
|
|
8286
|
-
const runtimeHome = runtimeRoot ?
|
|
8287
|
-
const runtimeTmp = runtimeRoot ?
|
|
8288
|
-
const runtimeCache = runtimeRoot ?
|
|
8289
|
-
const runtimeKnownHosts = runtimeHome ?
|
|
8290
|
-
const runtimeKey = runtimeHome ?
|
|
8334
|
+
const runtimeHome = runtimeRoot ? resolve25(runtimeRoot, "home") : "";
|
|
8335
|
+
const runtimeTmp = runtimeRoot ? resolve25(runtimeRoot, "tmp") : "";
|
|
8336
|
+
const runtimeCache = runtimeRoot ? resolve25(runtimeRoot, "cache") : "";
|
|
8337
|
+
const runtimeKnownHosts = runtimeHome ? resolve25(runtimeHome, ".ssh", "known_hosts") : "";
|
|
8338
|
+
const runtimeKey = runtimeHome ? resolve25(runtimeHome, ".ssh", "rig-agent-key") : "";
|
|
8291
8339
|
const env = {};
|
|
8292
8340
|
if (ctx?.workspaceDir) {
|
|
8293
8341
|
env.PROJECT_RIG_ROOT = projectRoot;
|
|
@@ -8300,14 +8348,14 @@ function runtimeGitEnv(projectRoot) {
|
|
|
8300
8348
|
if (runtimeRoot) {
|
|
8301
8349
|
env.RIG_RUNTIME_HOME = runtimeRoot;
|
|
8302
8350
|
}
|
|
8303
|
-
if (runtimeHome &&
|
|
8351
|
+
if (runtimeHome && existsSync22(runtimeHome)) {
|
|
8304
8352
|
env.HOME = runtimeHome;
|
|
8305
8353
|
env.OPENSSL_CONF = ensureRuntimeOpenSslConfig(runtimeHome);
|
|
8306
8354
|
}
|
|
8307
|
-
if (runtimeTmp &&
|
|
8355
|
+
if (runtimeTmp && existsSync22(runtimeTmp)) {
|
|
8308
8356
|
env.TMPDIR = runtimeTmp;
|
|
8309
8357
|
}
|
|
8310
|
-
if (runtimeCache &&
|
|
8358
|
+
if (runtimeCache && existsSync22(runtimeCache)) {
|
|
8311
8359
|
env.XDG_CACHE_HOME = runtimeCache;
|
|
8312
8360
|
}
|
|
8313
8361
|
const workspaceSecrets = loadDotEnvSecrets(ctx?.workspaceDir || projectRoot, process.env);
|
|
@@ -8351,14 +8399,14 @@ function runtimeGitEnv(projectRoot) {
|
|
|
8351
8399
|
env.GH_TOKEN = env.GH_TOKEN || gitHubToken;
|
|
8352
8400
|
applyGitHubCredentialHelperEnv(env);
|
|
8353
8401
|
}
|
|
8354
|
-
if (runtimeKnownHosts &&
|
|
8402
|
+
if (runtimeKnownHosts && existsSync22(runtimeKnownHosts)) {
|
|
8355
8403
|
const sshParts = [
|
|
8356
8404
|
"ssh",
|
|
8357
8405
|
`-o UserKnownHostsFile="${runtimeKnownHosts}"`,
|
|
8358
8406
|
"-o StrictHostKeyChecking=yes",
|
|
8359
8407
|
"-F /dev/null"
|
|
8360
8408
|
];
|
|
8361
|
-
if (runtimeKey &&
|
|
8409
|
+
if (runtimeKey && existsSync22(runtimeKey)) {
|
|
8362
8410
|
sshParts.splice(1, 0, `-i "${runtimeKey}"`, "-o IdentitiesOnly=yes");
|
|
8363
8411
|
}
|
|
8364
8412
|
env.GIT_SSH_COMMAND = sshParts.join(" ");
|
|
@@ -8379,12 +8427,12 @@ function loadPersistedRuntimeSecrets(runtimeRoot) {
|
|
|
8379
8427
|
if (!runtimeRoot) {
|
|
8380
8428
|
return {};
|
|
8381
8429
|
}
|
|
8382
|
-
const path =
|
|
8383
|
-
if (!
|
|
8430
|
+
const path = resolve25(runtimeRoot, "runtime-secrets.json");
|
|
8431
|
+
if (!existsSync22(path)) {
|
|
8384
8432
|
return {};
|
|
8385
8433
|
}
|
|
8386
8434
|
try {
|
|
8387
|
-
const parsed = JSON.parse(
|
|
8435
|
+
const parsed = JSON.parse(readFileSync12(path, "utf-8"));
|
|
8388
8436
|
const entries = Object.entries(parsed).filter((entry) => typeof entry[1] === "string");
|
|
8389
8437
|
return Object.fromEntries(entries);
|
|
8390
8438
|
} catch {
|
|
@@ -8392,13 +8440,13 @@ function loadPersistedRuntimeSecrets(runtimeRoot) {
|
|
|
8392
8440
|
}
|
|
8393
8441
|
}
|
|
8394
8442
|
function ensureRuntimeOpenSslConfig(runtimeHome) {
|
|
8395
|
-
const sslDir =
|
|
8396
|
-
const sslConfig =
|
|
8397
|
-
if (!
|
|
8398
|
-
|
|
8443
|
+
const sslDir = resolve25(runtimeHome, ".ssl");
|
|
8444
|
+
const sslConfig = resolve25(sslDir, "openssl.cnf");
|
|
8445
|
+
if (!existsSync22(sslDir)) {
|
|
8446
|
+
mkdirSync11(sslDir, { recursive: true });
|
|
8399
8447
|
}
|
|
8400
|
-
if (!
|
|
8401
|
-
|
|
8448
|
+
if (!existsSync22(sslConfig)) {
|
|
8449
|
+
writeFileSync11(sslConfig, `# Rig runtime OpenSSL config placeholder
|
|
8402
8450
|
`);
|
|
8403
8451
|
}
|
|
8404
8452
|
return sslConfig;
|
|
@@ -8416,11 +8464,11 @@ function resolveRuntimeMetadata(projectRoot) {
|
|
|
8416
8464
|
if (contextFile) {
|
|
8417
8465
|
return {
|
|
8418
8466
|
ctx,
|
|
8419
|
-
runtimeRoot: dirname11(
|
|
8467
|
+
runtimeRoot: dirname11(resolve25(contextFile))
|
|
8420
8468
|
};
|
|
8421
8469
|
}
|
|
8422
8470
|
const inferredContextFile = findRuntimeContextFile2(projectRoot);
|
|
8423
|
-
if (
|
|
8471
|
+
if (existsSync22(inferredContextFile)) {
|
|
8424
8472
|
try {
|
|
8425
8473
|
ctx = loadRuntimeContext(inferredContextFile);
|
|
8426
8474
|
} catch {}
|
|
@@ -8432,10 +8480,10 @@ function resolveRuntimeMetadata(projectRoot) {
|
|
|
8432
8480
|
return { ctx, runtimeRoot: "" };
|
|
8433
8481
|
}
|
|
8434
8482
|
function findRuntimeContextFile2(startPath) {
|
|
8435
|
-
let current =
|
|
8483
|
+
let current = resolve25(startPath);
|
|
8436
8484
|
while (true) {
|
|
8437
|
-
const candidate =
|
|
8438
|
-
if (
|
|
8485
|
+
const candidate = resolve25(current, "runtime-context.json");
|
|
8486
|
+
if (existsSync22(candidate)) {
|
|
8439
8487
|
return candidate;
|
|
8440
8488
|
}
|
|
8441
8489
|
const parent = dirname11(current);
|
|
@@ -8447,7 +8495,7 @@ function findRuntimeContextFile2(startPath) {
|
|
|
8447
8495
|
}
|
|
8448
8496
|
|
|
8449
8497
|
// packages/runtime/src/control-plane/native/profile-ops.ts
|
|
8450
|
-
import { existsSync as
|
|
8498
|
+
import { existsSync as existsSync23, mkdirSync as mkdirSync12, writeFileSync as writeFileSync12 } from "fs";
|
|
8451
8499
|
var DEFAULTS = {
|
|
8452
8500
|
model: parseEnvOrDefault(process.env.DEFAULT_AGENT_MODEL, ["claude", "gpt-codex", "pi"], "pi"),
|
|
8453
8501
|
runtime: parseEnvOrDefault(process.env.DEFAULT_AGENT_RUNTIME, ["claude-code", "codex-app-server", "pi"], "pi"),
|
|
@@ -8462,7 +8510,7 @@ function parseEnvOrDefault(value, allowed, fallback) {
|
|
|
8462
8510
|
return allowed.includes(value) ? value : fallback;
|
|
8463
8511
|
}
|
|
8464
8512
|
async function readProfileFile(path) {
|
|
8465
|
-
if (!
|
|
8513
|
+
if (!existsSync23(path)) {
|
|
8466
8514
|
return null;
|
|
8467
8515
|
}
|
|
8468
8516
|
try {
|
|
@@ -8515,14 +8563,14 @@ async function setProfile(projectRoot, options) {
|
|
|
8515
8563
|
plugin = model === "gpt-codex" ? "codex" : model === "pi" ? "pi" : "claude";
|
|
8516
8564
|
}
|
|
8517
8565
|
const paths = resolveHarnessPaths(projectRoot);
|
|
8518
|
-
|
|
8566
|
+
mkdirSync12(paths.stateDir, { recursive: true });
|
|
8519
8567
|
const next = {
|
|
8520
8568
|
model,
|
|
8521
8569
|
runtime,
|
|
8522
8570
|
agent_plugin: plugin,
|
|
8523
8571
|
updated_at: new Date().toISOString()
|
|
8524
8572
|
};
|
|
8525
|
-
|
|
8573
|
+
writeFileSync12(paths.agentProfilePath, `${JSON.stringify(next, null, 2)}
|
|
8526
8574
|
`, "utf-8");
|
|
8527
8575
|
await showProfile(projectRoot, false);
|
|
8528
8576
|
}
|
|
@@ -8558,13 +8606,13 @@ async function setReviewProfile(projectRoot, mode, provider) {
|
|
|
8558
8606
|
throw new Error(`Invalid provider: ${resolvedProvider}. Supported: greptile.`);
|
|
8559
8607
|
}
|
|
8560
8608
|
const paths = resolveHarnessPaths(projectRoot);
|
|
8561
|
-
|
|
8609
|
+
mkdirSync12(paths.stateDir, { recursive: true });
|
|
8562
8610
|
const next = {
|
|
8563
8611
|
mode,
|
|
8564
8612
|
provider: resolvedProvider,
|
|
8565
8613
|
updated_at: new Date().toISOString()
|
|
8566
8614
|
};
|
|
8567
|
-
|
|
8615
|
+
writeFileSync12(paths.reviewProfilePath, `${JSON.stringify(next, null, 2)}
|
|
8568
8616
|
`, "utf-8");
|
|
8569
8617
|
await showReviewProfile(projectRoot);
|
|
8570
8618
|
}
|
|
@@ -8602,44 +8650,44 @@ async function loadReviewProfile(path) {
|
|
|
8602
8650
|
}
|
|
8603
8651
|
|
|
8604
8652
|
// packages/runtime/src/control-plane/native/repo-ops.ts
|
|
8605
|
-
import { existsSync as
|
|
8606
|
-
import { basename as basename8, dirname as dirname13, resolve as
|
|
8653
|
+
import { existsSync as existsSync27, mkdirSync as mkdirSync16, readFileSync as readFileSync14, readdirSync as readdirSync6, rmSync as rmSync7, writeFileSync as writeFileSync14 } from "fs";
|
|
8654
|
+
import { basename as basename8, dirname as dirname13, resolve as resolve29 } from "path";
|
|
8607
8655
|
// packages/runtime/src/control-plane/repos/mirror/bootstrap.ts
|
|
8608
|
-
import { existsSync as
|
|
8609
|
-
import { resolve as
|
|
8656
|
+
import { existsSync as existsSync25, mkdirSync as mkdirSync14, realpathSync as realpathSync2 } from "fs";
|
|
8657
|
+
import { resolve as resolve27 } from "path";
|
|
8610
8658
|
|
|
8611
8659
|
// packages/runtime/src/control-plane/authority-files.ts
|
|
8612
|
-
import { existsSync as
|
|
8613
|
-
import { dirname as dirname12, join as join4, relative, resolve as
|
|
8660
|
+
import { existsSync as existsSync24, mkdirSync as mkdirSync13, readFileSync as readFileSync13, writeFileSync as writeFileSync13, appendFileSync as appendFileSync2, copyFileSync as copyFileSync3, statSync as statSync5, readdirSync as readdirSync5, chmodSync as chmodSync3 } from "fs";
|
|
8661
|
+
import { dirname as dirname12, join as join4, relative, resolve as resolve26 } from "path";
|
|
8614
8662
|
import { parse as parseToml, stringify as stringifyToml } from "smol-toml";
|
|
8615
8663
|
function resolveAuthorityProjectStateDir(projectRoot) {
|
|
8616
8664
|
const explicit = process.env.RIG_STATE_DIR?.trim();
|
|
8617
8665
|
if (explicit) {
|
|
8618
|
-
return
|
|
8666
|
+
return resolve26(explicit);
|
|
8619
8667
|
}
|
|
8620
|
-
return
|
|
8668
|
+
return resolve26(resolve26(projectRoot), ".rig", "state");
|
|
8621
8669
|
}
|
|
8622
8670
|
function readJsonAtPath(path, fallback) {
|
|
8623
|
-
if (!
|
|
8671
|
+
if (!existsSync24(path)) {
|
|
8624
8672
|
return fallback;
|
|
8625
8673
|
}
|
|
8626
8674
|
try {
|
|
8627
|
-
return JSON.parse(
|
|
8675
|
+
return JSON.parse(readFileSync13(path, "utf-8"));
|
|
8628
8676
|
} catch {
|
|
8629
8677
|
return fallback;
|
|
8630
8678
|
}
|
|
8631
8679
|
}
|
|
8632
8680
|
function writeJsonAtPath(path, value) {
|
|
8633
|
-
|
|
8634
|
-
|
|
8681
|
+
mkdirSync13(dirname12(path), { recursive: true });
|
|
8682
|
+
writeFileSync13(path, `${JSON.stringify(value, null, 2)}
|
|
8635
8683
|
`, "utf8");
|
|
8636
8684
|
return path;
|
|
8637
8685
|
}
|
|
8638
8686
|
function readAuthorityProjectStateJson(projectRoot, relativePath, fallback) {
|
|
8639
|
-
return readJsonAtPath(
|
|
8687
|
+
return readJsonAtPath(resolve26(resolveAuthorityProjectStateDir(projectRoot), relativePath), fallback);
|
|
8640
8688
|
}
|
|
8641
8689
|
function writeAuthorityProjectStateJson(projectRoot, relativePath, value) {
|
|
8642
|
-
return writeJsonAtPath(
|
|
8690
|
+
return writeJsonAtPath(resolve26(resolveAuthorityProjectStateDir(projectRoot), relativePath), value);
|
|
8643
8691
|
}
|
|
8644
8692
|
|
|
8645
8693
|
// packages/runtime/src/control-plane/repos/mirror/state.ts
|
|
@@ -8699,7 +8747,7 @@ function sameExistingPath(left, right) {
|
|
|
8699
8747
|
try {
|
|
8700
8748
|
return realpathSync2(left) === realpathSync2(right);
|
|
8701
8749
|
} catch {
|
|
8702
|
-
return
|
|
8750
|
+
return resolve27(left) === resolve27(right);
|
|
8703
8751
|
}
|
|
8704
8752
|
}
|
|
8705
8753
|
function repoLooksUsable(repoRoot, projectRoot) {
|
|
@@ -8735,7 +8783,7 @@ function resolveMirrorRemoteUrl(layout) {
|
|
|
8735
8783
|
}
|
|
8736
8784
|
}
|
|
8737
8785
|
}
|
|
8738
|
-
if (
|
|
8786
|
+
if (existsSync25(resolve27(layout.checkoutRoot, ".git")) && checkoutLooksUsable(layout)) {
|
|
8739
8787
|
const checkoutOrigin = runGit(["git", "-C", layout.checkoutRoot, "remote", "get-url", "origin"], layout.projectRoot);
|
|
8740
8788
|
if (checkoutOrigin.exitCode === 0) {
|
|
8741
8789
|
const currentOrigin = checkoutOrigin.stdout.trim();
|
|
@@ -8748,9 +8796,9 @@ function resolveMirrorRemoteUrl(layout) {
|
|
|
8748
8796
|
}
|
|
8749
8797
|
function ensureManagedRepoMirror(projectRoot, repoId) {
|
|
8750
8798
|
const layout = resolveManagedRepoLayout(projectRoot, repoId);
|
|
8751
|
-
|
|
8799
|
+
mkdirSync14(layout.metadataRoot, { recursive: true });
|
|
8752
8800
|
const remoteUrl = resolveMirrorRemoteUrl(layout);
|
|
8753
|
-
if (!
|
|
8801
|
+
if (!existsSync25(resolve27(layout.mirrorRoot, "HEAD"))) {
|
|
8754
8802
|
ensureGitSuccess(runGit(["git", "init", "--bare", layout.mirrorRoot], layout.projectRoot), ["git", "init", "--bare", layout.mirrorRoot]);
|
|
8755
8803
|
}
|
|
8756
8804
|
const getOrigin = runGit(["git", "--git-dir", layout.mirrorRoot, "remote", "get-url", "origin"], layout.projectRoot);
|
|
@@ -8770,8 +8818,8 @@ function ensureManagedRepoMirror(projectRoot, repoId) {
|
|
|
8770
8818
|
return layout;
|
|
8771
8819
|
}
|
|
8772
8820
|
// packages/runtime/src/control-plane/repos/mirror/refresh.ts
|
|
8773
|
-
import { existsSync as
|
|
8774
|
-
import { resolve as
|
|
8821
|
+
import { existsSync as existsSync26, mkdirSync as mkdirSync15, realpathSync as realpathSync3, rmSync as rmSync6 } from "fs";
|
|
8822
|
+
import { resolve as resolve28 } from "path";
|
|
8775
8823
|
function nowIso3() {
|
|
8776
8824
|
return new Date().toISOString();
|
|
8777
8825
|
}
|
|
@@ -8798,7 +8846,7 @@ function sameExistingPath2(left, right) {
|
|
|
8798
8846
|
try {
|
|
8799
8847
|
return realpathSync3(left) === realpathSync3(right);
|
|
8800
8848
|
} catch {
|
|
8801
|
-
return
|
|
8849
|
+
return resolve28(left) === resolve28(right);
|
|
8802
8850
|
}
|
|
8803
8851
|
}
|
|
8804
8852
|
function ensureMirrorHead(layout) {
|
|
@@ -8844,12 +8892,12 @@ function checkoutLooksUsable2(layout) {
|
|
|
8844
8892
|
return probe.exitCode === 0 && sameExistingPath2(probe.stdout.trim(), layout.checkoutRoot);
|
|
8845
8893
|
}
|
|
8846
8894
|
function ensureCheckoutFromMirror(layout) {
|
|
8847
|
-
|
|
8848
|
-
const gitPath =
|
|
8849
|
-
if (
|
|
8850
|
-
|
|
8895
|
+
mkdirSync15(resolve28(layout.checkoutRoot, ".."), { recursive: true });
|
|
8896
|
+
const gitPath = resolve28(layout.checkoutRoot, ".git");
|
|
8897
|
+
if (existsSync26(layout.checkoutRoot) && (!existsSync26(gitPath) || !checkoutLooksUsable2(layout))) {
|
|
8898
|
+
rmSync6(layout.checkoutRoot, { recursive: true, force: true });
|
|
8851
8899
|
}
|
|
8852
|
-
if (!
|
|
8900
|
+
if (!existsSync26(gitPath)) {
|
|
8853
8901
|
ensureGitSuccess2(runGit2(["git", "clone", layout.mirrorRoot, layout.checkoutRoot], layout.projectRoot), ["git", "clone", layout.mirrorRoot, layout.checkoutRoot]);
|
|
8854
8902
|
}
|
|
8855
8903
|
const getOrigin = runGit2(["git", "-C", layout.checkoutRoot, "remote", "get-url", "origin"], layout.projectRoot);
|
|
@@ -8950,7 +8998,7 @@ function repoDiscover(projectRoot, taskId) {
|
|
|
8950
8998
|
}
|
|
8951
8999
|
function repoBaseline(projectRoot, refresh = false) {
|
|
8952
9000
|
const paths = resolveRepoDiscoveryPaths(projectRoot);
|
|
8953
|
-
if (!refresh &&
|
|
9001
|
+
if (!refresh && existsSync27(paths.baseRepoPinsPath)) {
|
|
8954
9002
|
const baseline = readJsonFile(paths.baseRepoPinsPath, { recorded_at: nowIso(), repos: {} });
|
|
8955
9003
|
return baseline.repos || {};
|
|
8956
9004
|
}
|
|
@@ -8974,8 +9022,8 @@ function ensureMonorepoReady(projectRoot) {
|
|
|
8974
9022
|
}
|
|
8975
9023
|
function persistBaselinePins(projectRoot, repos) {
|
|
8976
9024
|
const paths = resolveRepoDiscoveryPaths(projectRoot);
|
|
8977
|
-
|
|
8978
|
-
|
|
9025
|
+
mkdirSync16(resolve29(paths.baseRepoPinsPath, ".."), { recursive: true });
|
|
9026
|
+
writeFileSync14(paths.baseRepoPinsPath, `${JSON.stringify({ recorded_at: nowIso(), repos }, null, 2)}
|
|
8979
9027
|
`, "utf-8");
|
|
8980
9028
|
return repos;
|
|
8981
9029
|
}
|
|
@@ -9054,28 +9102,28 @@ function readRepoDiscoveryTaskConfig(projectRoot) {
|
|
|
9054
9102
|
function resolveRepoDiscoveryPaths(projectRoot) {
|
|
9055
9103
|
const monorepoRoot = resolveMonorepoRepoLayout(projectRoot).checkoutRoot;
|
|
9056
9104
|
const explicitHostProjectRoot = (process.env.RIG_HOST_PROJECT_ROOT || "").trim();
|
|
9057
|
-
const normalizedProjectRoot =
|
|
9105
|
+
const normalizedProjectRoot = resolve29(projectRoot);
|
|
9058
9106
|
const hostProjectRoot = explicitHostProjectRoot && shouldUseHostProjectStateRoot(normalizedProjectRoot) ? explicitHostProjectRoot : normalizedProjectRoot;
|
|
9059
|
-
const stateDir =
|
|
9107
|
+
const stateDir = resolve29(hostProjectRoot, ".rig", "state");
|
|
9060
9108
|
return {
|
|
9061
9109
|
monorepoRoot,
|
|
9062
|
-
taskRepoCommitsPath:
|
|
9063
|
-
baseRepoPinsPath:
|
|
9110
|
+
taskRepoCommitsPath: resolve29(stateDir, "task-repo-commits.json"),
|
|
9111
|
+
baseRepoPinsPath: resolve29(stateDir, "base-repo-pins.json")
|
|
9064
9112
|
};
|
|
9065
9113
|
}
|
|
9066
9114
|
function shouldUseHostProjectStateRoot(projectRoot) {
|
|
9067
9115
|
const runtimeWorkspace = process.env.RIG_TASK_WORKSPACE?.trim();
|
|
9068
|
-
if (runtimeWorkspace &&
|
|
9116
|
+
if (runtimeWorkspace && resolve29(runtimeWorkspace) === projectRoot) {
|
|
9069
9117
|
return true;
|
|
9070
9118
|
}
|
|
9071
9119
|
return basename8(dirname13(projectRoot)) === ".worktrees";
|
|
9072
9120
|
}
|
|
9073
9121
|
function readPinFromArtifact(projectRoot, depTask, repoKey) {
|
|
9074
|
-
const snapshot =
|
|
9075
|
-
if (!
|
|
9122
|
+
const snapshot = resolve29(artifactDirForId(projectRoot, depTask), "git-state.txt");
|
|
9123
|
+
if (!existsSync27(snapshot)) {
|
|
9076
9124
|
return "";
|
|
9077
9125
|
}
|
|
9078
|
-
const content =
|
|
9126
|
+
const content = readFileSync14(snapshot, "utf-8");
|
|
9079
9127
|
const chunk = content.split(/\r?\n/);
|
|
9080
9128
|
let inSection = false;
|
|
9081
9129
|
for (const line of chunk) {
|
|
@@ -9097,12 +9145,12 @@ function repoPath(projectRoot, key) {
|
|
|
9097
9145
|
if (managed) {
|
|
9098
9146
|
return managed.checkoutRoot;
|
|
9099
9147
|
}
|
|
9100
|
-
return key.startsWith("/") ? key :
|
|
9148
|
+
return key.startsWith("/") ? key : resolve29(projectRoot, key);
|
|
9101
9149
|
}
|
|
9102
9150
|
function applyPins(projectRoot, pins) {
|
|
9103
9151
|
for (const [key, commit] of Object.entries(pins)) {
|
|
9104
9152
|
const path = repoPath(projectRoot, key);
|
|
9105
|
-
if (!
|
|
9153
|
+
if (!existsSync27(resolve29(path, ".git"))) {
|
|
9106
9154
|
throw new Error(`Repo for pin not available: ${key} (${path})`);
|
|
9107
9155
|
}
|
|
9108
9156
|
let hasCommit = runGitCapture(["git", "-C", path, "cat-file", "-e", `${commit}^{commit}`], projectRoot).exitCode === 0;
|
|
@@ -9131,7 +9179,7 @@ function verifyPins(projectRoot, pins) {
|
|
|
9131
9179
|
let ok = true;
|
|
9132
9180
|
for (const [key, expected] of Object.entries(pins)) {
|
|
9133
9181
|
const path = repoPath(projectRoot, key);
|
|
9134
|
-
if (!
|
|
9182
|
+
if (!existsSync27(resolve29(path, ".git"))) {
|
|
9135
9183
|
console.error(`ERROR: repo missing during pin verification: ${key}`);
|
|
9136
9184
|
ok = false;
|
|
9137
9185
|
continue;
|
|
@@ -9156,23 +9204,23 @@ function resolveRuntimeGitEnv() {
|
|
|
9156
9204
|
GIT_SSH_COMMAND: process.env.GIT_SSH_COMMAND
|
|
9157
9205
|
};
|
|
9158
9206
|
}
|
|
9159
|
-
const runtimeRoot = process.env.RIG_RUNTIME_HOME?.trim() || (process.env.RIG_RUNTIME_CONTEXT_FILE?.trim() ?
|
|
9160
|
-
const runtimeHome = runtimeRoot ?
|
|
9207
|
+
const runtimeRoot = process.env.RIG_RUNTIME_HOME?.trim() || (process.env.RIG_RUNTIME_CONTEXT_FILE?.trim() ? resolve29(process.env.RIG_RUNTIME_CONTEXT_FILE, "..") : inferRuntimeRootFromWorkspace(process.cwd()));
|
|
9208
|
+
const runtimeHome = runtimeRoot ? resolve29(runtimeRoot, "home") : process.env.HOME?.trim() || "";
|
|
9161
9209
|
if (!runtimeHome) {
|
|
9162
9210
|
return;
|
|
9163
9211
|
}
|
|
9164
|
-
const knownHostsPath =
|
|
9165
|
-
if (!
|
|
9212
|
+
const knownHostsPath = resolve29(runtimeHome, ".ssh", "known_hosts");
|
|
9213
|
+
if (!existsSync27(knownHostsPath)) {
|
|
9166
9214
|
return { HOME: runtimeHome };
|
|
9167
9215
|
}
|
|
9168
|
-
const agentSshKey =
|
|
9216
|
+
const agentSshKey = resolve29(runtimeHome, ".ssh", "rig-agent-key");
|
|
9169
9217
|
const sshParts = [
|
|
9170
9218
|
"ssh",
|
|
9171
9219
|
`-o UserKnownHostsFile="${knownHostsPath}"`,
|
|
9172
9220
|
"-o StrictHostKeyChecking=yes",
|
|
9173
9221
|
"-F /dev/null"
|
|
9174
9222
|
];
|
|
9175
|
-
if (
|
|
9223
|
+
if (existsSync27(agentSshKey)) {
|
|
9176
9224
|
sshParts.splice(1, 0, `-i "${agentSshKey}"`, "-o IdentitiesOnly=yes");
|
|
9177
9225
|
}
|
|
9178
9226
|
return {
|
|
@@ -9182,24 +9230,24 @@ function resolveRuntimeGitEnv() {
|
|
|
9182
9230
|
}
|
|
9183
9231
|
function inferRuntimeRootFromWorkspace(cwd) {
|
|
9184
9232
|
const contextPath = findRuntimeContextFile3(cwd);
|
|
9185
|
-
if (!contextPath || !
|
|
9233
|
+
if (!contextPath || !existsSync27(contextPath)) {
|
|
9186
9234
|
return "";
|
|
9187
9235
|
}
|
|
9188
9236
|
try {
|
|
9189
9237
|
loadRuntimeContext(contextPath);
|
|
9190
|
-
return
|
|
9238
|
+
return resolve29(contextPath, "..");
|
|
9191
9239
|
} catch {
|
|
9192
9240
|
return "";
|
|
9193
9241
|
}
|
|
9194
9242
|
}
|
|
9195
9243
|
function findRuntimeContextFile3(startPath) {
|
|
9196
|
-
let current =
|
|
9244
|
+
let current = resolve29(startPath);
|
|
9197
9245
|
while (true) {
|
|
9198
|
-
const candidate =
|
|
9199
|
-
if (
|
|
9246
|
+
const candidate = resolve29(current, "runtime-context.json");
|
|
9247
|
+
if (existsSync27(candidate)) {
|
|
9200
9248
|
return candidate;
|
|
9201
9249
|
}
|
|
9202
|
-
const parent =
|
|
9250
|
+
const parent = resolve29(current, "..");
|
|
9203
9251
|
if (parent === current) {
|
|
9204
9252
|
return "";
|
|
9205
9253
|
}
|
|
@@ -9208,12 +9256,12 @@ function findRuntimeContextFile3(startPath) {
|
|
|
9208
9256
|
}
|
|
9209
9257
|
|
|
9210
9258
|
// packages/runtime/src/control-plane/memory-sync/cli.ts
|
|
9211
|
-
import { existsSync as
|
|
9259
|
+
import { existsSync as existsSync28 } from "fs";
|
|
9212
9260
|
import { randomUUID } from "crypto";
|
|
9213
9261
|
|
|
9214
9262
|
// packages/runtime/src/control-plane/memory-sync/db.ts
|
|
9215
9263
|
import { Database } from "bun:sqlite";
|
|
9216
|
-
import { mkdirSync as
|
|
9264
|
+
import { mkdirSync as mkdirSync17 } from "fs";
|
|
9217
9265
|
import { dirname as dirname14 } from "path";
|
|
9218
9266
|
|
|
9219
9267
|
// packages/runtime/src/control-plane/memory-sync/types.ts
|
|
@@ -9810,7 +9858,7 @@ async function validateEventTargets(executor, event) {
|
|
|
9810
9858
|
}
|
|
9811
9859
|
}
|
|
9812
9860
|
async function openMemoryDb(dbPath) {
|
|
9813
|
-
|
|
9861
|
+
mkdirSync17(dirname14(dbPath), { recursive: true });
|
|
9814
9862
|
const sqlite = new Database(dbPath, { create: true, strict: true });
|
|
9815
9863
|
const client = createMemoryDbClient(sqlite);
|
|
9816
9864
|
const db = {
|
|
@@ -10229,7 +10277,7 @@ function formatMemoryQueryResults(results) {
|
|
|
10229
10277
|
}
|
|
10230
10278
|
|
|
10231
10279
|
// packages/runtime/src/control-plane/memory-sync/read.ts
|
|
10232
|
-
import { mkdtempSync, rmSync as
|
|
10280
|
+
import { mkdtempSync, rmSync as rmSync8, writeFileSync as writeFileSync15 } from "fs";
|
|
10233
10281
|
import { tmpdir as tmpdir5 } from "os";
|
|
10234
10282
|
import { join as join5 } from "path";
|
|
10235
10283
|
var CANONICAL_MEMORY_DB_PATH = "rig/memory/project-memory.db";
|
|
@@ -10238,7 +10286,7 @@ var DEFAULT_READ_DEPS2 = {
|
|
|
10238
10286
|
readBlobBytesAtRef: nativeReadBlobBytesAtRef,
|
|
10239
10287
|
openMemoryDb,
|
|
10240
10288
|
makeTempDir: () => mkdtempSync(join5(tmpdir5(), "memory-sync-read-")),
|
|
10241
|
-
removeDir: (path) =>
|
|
10289
|
+
removeDir: (path) => rmSync8(path, { recursive: true, force: true })
|
|
10242
10290
|
};
|
|
10243
10291
|
function isMissingCanonicalMemoryBlobError(error) {
|
|
10244
10292
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -10258,7 +10306,7 @@ async function readCanonicalMemoryDb(projectRoot, deps = {}) {
|
|
|
10258
10306
|
try {
|
|
10259
10307
|
try {
|
|
10260
10308
|
const bytes = readDeps.readBlobBytesAtRef(repoPath2, baseOid, CANONICAL_MEMORY_DB_PATH);
|
|
10261
|
-
|
|
10309
|
+
writeFileSync15(dbPath, bytes);
|
|
10262
10310
|
} catch (error) {
|
|
10263
10311
|
if (!isMissingCanonicalMemoryBlobError(error)) {
|
|
10264
10312
|
throw error;
|
|
@@ -10416,7 +10464,7 @@ function requireRuntimeMemoryContext(runtimeContext) {
|
|
|
10416
10464
|
}
|
|
10417
10465
|
async function ensureRuntimeMemoryUsable(runtimeContext) {
|
|
10418
10466
|
const memory = requireRuntimeMemoryContext(runtimeContext);
|
|
10419
|
-
if (!
|
|
10467
|
+
if (!existsSync28(memory.hydratedPath)) {
|
|
10420
10468
|
throw new Error(`Shared memory database is missing: ${memory.hydratedPath}`);
|
|
10421
10469
|
}
|
|
10422
10470
|
const db = await openMemoryDb(memory.hydratedPath);
|
|
@@ -10679,7 +10727,7 @@ async function executeMemoryCommand(options, deps = {}) {
|
|
|
10679
10727
|
}
|
|
10680
10728
|
|
|
10681
10729
|
// packages/runtime/src/control-plane/native/harness-cli.ts
|
|
10682
|
-
async function executeHarnessCommand(projectRoot,
|
|
10730
|
+
async function executeHarnessCommand(projectRoot, args, eventBus, pluginHostCtx) {
|
|
10683
10731
|
const [command = "help", ...rest] = args;
|
|
10684
10732
|
switch (command) {
|
|
10685
10733
|
case "memory": {
|
|
@@ -10717,8 +10765,8 @@ async function executeHarnessCommand(projectRoot, plugins, args, eventBus, plugi
|
|
|
10717
10765
|
}
|
|
10718
10766
|
case "completion-verification":
|
|
10719
10767
|
case "completition-verification": {
|
|
10720
|
-
const hookPath =
|
|
10721
|
-
if (!
|
|
10768
|
+
const hookPath = resolve30(projectRoot, ".rig/bin/hooks/completion-verification");
|
|
10769
|
+
if (!existsSync29(hookPath)) {
|
|
10722
10770
|
throw new Error(`completion-verification hook binary not found: ${hookPath}`);
|
|
10723
10771
|
}
|
|
10724
10772
|
const proc = Bun.spawn([hookPath], {
|
|
@@ -10736,7 +10784,7 @@ async function executeHarnessCommand(projectRoot, plugins, args, eventBus, plugi
|
|
|
10736
10784
|
}
|
|
10737
10785
|
case "verify": {
|
|
10738
10786
|
const task = rest[0];
|
|
10739
|
-
const ok = await taskVerify(projectRoot,
|
|
10787
|
+
const ok = await taskVerify(projectRoot, task);
|
|
10740
10788
|
if (!ok) {
|
|
10741
10789
|
throw new Error("Verification rejected.");
|
|
10742
10790
|
}
|