@h-rig/runtime 0.0.6-alpha.28 → 0.0.6-alpha.29
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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,7 +1,7 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
// packages/runtime/src/control-plane/native/task-ops.ts
|
|
3
|
-
import { appendFileSync, existsSync as
|
|
4
|
-
import { resolve as
|
|
3
|
+
import { appendFileSync, existsSync as existsSync21, mkdirSync as mkdirSync11, readFileSync as readFileSync11, writeFileSync as writeFileSync11 } from "fs";
|
|
4
|
+
import { resolve as resolve24 } from "path";
|
|
5
5
|
|
|
6
6
|
// packages/runtime/src/build-time-config.ts
|
|
7
7
|
function normalizeBuildConfig(value) {
|
|
@@ -651,6 +651,49 @@ function safeReadJson(path) {
|
|
|
651
651
|
}
|
|
652
652
|
}
|
|
653
653
|
|
|
654
|
+
// packages/runtime/src/control-plane/skill-materializer.ts
|
|
655
|
+
import { existsSync as existsSync4, mkdirSync as mkdirSync3, readFileSync as readFileSync3, readdirSync, rmSync, writeFileSync as writeFileSync3 } from "fs";
|
|
656
|
+
import { resolve as resolve6 } from "path";
|
|
657
|
+
import { loadSkill } from "@rig/skill-loader";
|
|
658
|
+
var MARKER_FILENAME = ".rig-plugin";
|
|
659
|
+
function skillDirName(id) {
|
|
660
|
+
return id.replace(/[^a-zA-Z0-9._-]+/g, "-");
|
|
661
|
+
}
|
|
662
|
+
async function materializeSkills(projectRoot, entries) {
|
|
663
|
+
const skillsRoot = resolve6(projectRoot, ".pi", "skills");
|
|
664
|
+
if (existsSync4(skillsRoot)) {
|
|
665
|
+
for (const name of readdirSync(skillsRoot)) {
|
|
666
|
+
const dir = resolve6(skillsRoot, name);
|
|
667
|
+
if (existsSync4(resolve6(dir, MARKER_FILENAME))) {
|
|
668
|
+
rmSync(dir, { recursive: true, force: true });
|
|
669
|
+
}
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
const written = [];
|
|
673
|
+
for (const { pluginName, skill } of entries) {
|
|
674
|
+
const sourcePath = resolve6(projectRoot, skill.path);
|
|
675
|
+
if (!existsSync4(sourcePath)) {
|
|
676
|
+
console.warn(`[plugin-host] skill "${skill.id}" from plugin "${pluginName}" not materialized: ${sourcePath} does not exist`);
|
|
677
|
+
continue;
|
|
678
|
+
}
|
|
679
|
+
let body;
|
|
680
|
+
try {
|
|
681
|
+
await loadSkill(sourcePath);
|
|
682
|
+
body = readFileSync3(sourcePath, "utf-8");
|
|
683
|
+
} catch (err) {
|
|
684
|
+
console.warn(`[plugin-host] skill "${skill.id}" from plugin "${pluginName}" not materialized: ${err instanceof Error ? err.message : err}`);
|
|
685
|
+
continue;
|
|
686
|
+
}
|
|
687
|
+
const dir = resolve6(skillsRoot, skillDirName(skill.id));
|
|
688
|
+
mkdirSync3(dir, { recursive: true });
|
|
689
|
+
writeFileSync3(resolve6(dir, "SKILL.md"), body, "utf-8");
|
|
690
|
+
writeFileSync3(resolve6(dir, MARKER_FILENAME), `${JSON.stringify({ plugin: pluginName, skillId: skill.id }, null, 2)}
|
|
691
|
+
`, "utf-8");
|
|
692
|
+
written.push({ id: skill.id, pluginName, directory: dir });
|
|
693
|
+
}
|
|
694
|
+
return written;
|
|
695
|
+
}
|
|
696
|
+
|
|
654
697
|
// packages/runtime/src/control-plane/plugin-host-context.ts
|
|
655
698
|
async function buildPluginHostContext(projectRoot) {
|
|
656
699
|
let config;
|
|
@@ -687,6 +730,17 @@ async function buildPluginHostContext(projectRoot) {
|
|
|
687
730
|
} catch (err) {
|
|
688
731
|
console.warn(`[plugin-host] hook materialization failed: ${err instanceof Error ? err.message : err}`);
|
|
689
732
|
}
|
|
733
|
+
try {
|
|
734
|
+
const skillEntries = config.plugins.flatMap((plugin) => (plugin.contributes?.skills ?? []).map((skill) => ({
|
|
735
|
+
pluginName: plugin.name,
|
|
736
|
+
skill
|
|
737
|
+
})));
|
|
738
|
+
if (skillEntries.length > 0) {
|
|
739
|
+
await materializeSkills(projectRoot, skillEntries);
|
|
740
|
+
}
|
|
741
|
+
} catch (err) {
|
|
742
|
+
console.warn(`[plugin-host] skill materialization failed: ${err instanceof Error ? err.message : err}`);
|
|
743
|
+
}
|
|
690
744
|
return {
|
|
691
745
|
config,
|
|
692
746
|
pluginHost,
|
|
@@ -700,12 +754,12 @@ async function buildPluginHostContext(projectRoot) {
|
|
|
700
754
|
|
|
701
755
|
// packages/runtime/src/control-plane/tasks/source-aware-task-config-source.ts
|
|
702
756
|
import { spawnSync } from "child_process";
|
|
703
|
-
import { existsSync as
|
|
704
|
-
import { basename as basename3, join as join2, resolve as
|
|
757
|
+
import { existsSync as existsSync6, readFileSync as readFileSync5, readdirSync as readdirSync2, statSync, writeFileSync as writeFileSync4 } from "fs";
|
|
758
|
+
import { basename as basename3, join as join2, resolve as resolve8 } from "path";
|
|
705
759
|
|
|
706
760
|
// packages/runtime/src/control-plane/tasks/legacy-task-config-source.ts
|
|
707
|
-
import { existsSync as
|
|
708
|
-
import { resolve as
|
|
761
|
+
import { existsSync as existsSync5, readFileSync as readFileSync4 } from "fs";
|
|
762
|
+
import { resolve as resolve7 } from "path";
|
|
709
763
|
|
|
710
764
|
// packages/runtime/src/control-plane/tasks/task-record-reader.ts
|
|
711
765
|
async function findTaskById(reader, id) {
|
|
@@ -728,7 +782,7 @@ class LegacyTaskConfigReadError extends Error {
|
|
|
728
782
|
}
|
|
729
783
|
}
|
|
730
784
|
function createLegacyTaskConfigRecordReader(projectRoot, options = {}) {
|
|
731
|
-
const configPath = options.configPath ??
|
|
785
|
+
const configPath = options.configPath ?? resolve7(projectRoot, ".rig", "task-config.json");
|
|
732
786
|
const reader = {
|
|
733
787
|
async listTasks() {
|
|
734
788
|
return readLegacyTaskRecords(projectRoot, configPath);
|
|
@@ -739,8 +793,8 @@ function createLegacyTaskConfigRecordReader(projectRoot, options = {}) {
|
|
|
739
793
|
};
|
|
740
794
|
return reader;
|
|
741
795
|
}
|
|
742
|
-
function readLegacyTaskRecords(projectRoot, configPath =
|
|
743
|
-
if (!
|
|
796
|
+
function readLegacyTaskRecords(projectRoot, configPath = resolve7(projectRoot, ".rig", "task-config.json")) {
|
|
797
|
+
if (!existsSync5(configPath)) {
|
|
744
798
|
return [];
|
|
745
799
|
}
|
|
746
800
|
const rawConfig = readLegacyTaskConfigJson(projectRoot, configPath);
|
|
@@ -748,7 +802,7 @@ function readLegacyTaskRecords(projectRoot, configPath = resolve6(projectRoot, "
|
|
|
748
802
|
}
|
|
749
803
|
function readLegacyTaskConfigJson(projectRoot, configPath) {
|
|
750
804
|
try {
|
|
751
|
-
const parsed = JSON.parse(
|
|
805
|
+
const parsed = JSON.parse(readFileSync4(configPath, "utf8"));
|
|
752
806
|
if (isPlainRecord(parsed)) {
|
|
753
807
|
return parsed;
|
|
754
808
|
}
|
|
@@ -832,7 +886,7 @@ function isPlainRecord(candidate) {
|
|
|
832
886
|
var STATUS_LABELS = new Set(["ready", "blocked", "in-progress", "under-review", "failed", "cancelled"]);
|
|
833
887
|
var FILE_TASK_PATTERN = /\.(task\.)?json$/;
|
|
834
888
|
function createSourceAwareTaskConfigRecordReader(projectRoot, options = {}) {
|
|
835
|
-
const configPath = options.configPath ??
|
|
889
|
+
const configPath = options.configPath ?? resolve8(projectRoot, ".rig", "task-config.json");
|
|
836
890
|
const legacy = createLegacyTaskConfigRecordReader(projectRoot, { configPath });
|
|
837
891
|
const spawnFn = options.spawn ?? spawnSync;
|
|
838
892
|
const ghBinary = options.ghBinary ?? "gh";
|
|
@@ -915,10 +969,10 @@ function readMaterializedTaskMetadata(entry) {
|
|
|
915
969
|
return metadata;
|
|
916
970
|
}
|
|
917
971
|
function readConfiguredFilesTaskSourcePath(projectRoot) {
|
|
918
|
-
const jsonPath =
|
|
919
|
-
if (
|
|
972
|
+
const jsonPath = resolve8(projectRoot, "rig.config.json");
|
|
973
|
+
if (existsSync6(jsonPath)) {
|
|
920
974
|
try {
|
|
921
|
-
const parsed = JSON.parse(
|
|
975
|
+
const parsed = JSON.parse(readFileSync5(jsonPath, "utf8"));
|
|
922
976
|
if (isPlainRecord2(parsed) && isPlainRecord2(parsed.taskSource)) {
|
|
923
977
|
const source = parsed.taskSource;
|
|
924
978
|
return source.kind === "files" && typeof source.path === "string" ? source.path : null;
|
|
@@ -927,12 +981,12 @@ function readConfiguredFilesTaskSourcePath(projectRoot) {
|
|
|
927
981
|
return null;
|
|
928
982
|
}
|
|
929
983
|
}
|
|
930
|
-
const tsPath =
|
|
931
|
-
if (!
|
|
984
|
+
const tsPath = resolve8(projectRoot, "rig.config.ts");
|
|
985
|
+
if (!existsSync6(tsPath)) {
|
|
932
986
|
return null;
|
|
933
987
|
}
|
|
934
988
|
try {
|
|
935
|
-
const source =
|
|
989
|
+
const source = readFileSync5(tsPath, "utf8");
|
|
936
990
|
const taskSourceBlock = source.match(/taskSource\s*:\s*\{[\s\S]*?\}/m)?.[0] ?? "";
|
|
937
991
|
const kind = taskSourceBlock.match(/kind\s*:\s*["']([^"']+)["']/)?.[1];
|
|
938
992
|
if (kind !== "files") {
|
|
@@ -952,10 +1006,10 @@ function readRawTaskEntry(configPath, taskId) {
|
|
|
952
1006
|
return isPlainRecord2(entry) ? entry : null;
|
|
953
1007
|
}
|
|
954
1008
|
function readRawTaskConfig(configPath) {
|
|
955
|
-
if (!
|
|
1009
|
+
if (!existsSync6(configPath)) {
|
|
956
1010
|
return null;
|
|
957
1011
|
}
|
|
958
|
-
const parsed = JSON.parse(
|
|
1012
|
+
const parsed = JSON.parse(readFileSync5(configPath, "utf8"));
|
|
959
1013
|
return isPlainRecord2(parsed) ? parsed : null;
|
|
960
1014
|
}
|
|
961
1015
|
function stripLegacyTaskConfigMetadata2(raw) {
|
|
@@ -963,12 +1017,12 @@ function stripLegacyTaskConfigMetadata2(raw) {
|
|
|
963
1017
|
return tasks;
|
|
964
1018
|
}
|
|
965
1019
|
function listFileBackedTasks(projectRoot, sourcePath) {
|
|
966
|
-
const directory =
|
|
967
|
-
if (!
|
|
1020
|
+
const directory = resolve8(projectRoot, sourcePath);
|
|
1021
|
+
if (!existsSync6(directory)) {
|
|
968
1022
|
return [];
|
|
969
1023
|
}
|
|
970
1024
|
const tasks = [];
|
|
971
|
-
for (const name of
|
|
1025
|
+
for (const name of readdirSync2(directory)) {
|
|
972
1026
|
if (!FILE_TASK_PATTERN.test(name))
|
|
973
1027
|
continue;
|
|
974
1028
|
const inferredId = basename3(name).replace(FILE_TASK_PATTERN, "");
|
|
@@ -979,11 +1033,11 @@ function listFileBackedTasks(projectRoot, sourcePath) {
|
|
|
979
1033
|
return tasks;
|
|
980
1034
|
}
|
|
981
1035
|
function readFileBackedTask(projectRoot, sourcePath, taskId, rawEntry) {
|
|
982
|
-
const file = findFileBackedTaskFile(
|
|
1036
|
+
const file = findFileBackedTaskFile(resolve8(projectRoot, sourcePath), taskId);
|
|
983
1037
|
if (!file) {
|
|
984
1038
|
return null;
|
|
985
1039
|
}
|
|
986
|
-
const raw = JSON.parse(
|
|
1040
|
+
const raw = JSON.parse(readFileSync5(file, "utf8"));
|
|
987
1041
|
if (!isPlainRecord2(raw)) {
|
|
988
1042
|
return null;
|
|
989
1043
|
}
|
|
@@ -996,17 +1050,17 @@ function readFileBackedTask(projectRoot, sourcePath, taskId, rawEntry) {
|
|
|
996
1050
|
};
|
|
997
1051
|
}
|
|
998
1052
|
function findFileBackedTaskFile(directory, taskId) {
|
|
999
|
-
if (!
|
|
1053
|
+
if (!existsSync6(directory)) {
|
|
1000
1054
|
return null;
|
|
1001
1055
|
}
|
|
1002
|
-
for (const name of
|
|
1056
|
+
for (const name of readdirSync2(directory)) {
|
|
1003
1057
|
if (!FILE_TASK_PATTERN.test(name))
|
|
1004
1058
|
continue;
|
|
1005
1059
|
const file = join2(directory, name);
|
|
1006
1060
|
try {
|
|
1007
1061
|
if (!statSync(file).isFile())
|
|
1008
1062
|
continue;
|
|
1009
|
-
const raw = JSON.parse(
|
|
1063
|
+
const raw = JSON.parse(readFileSync5(file, "utf8"));
|
|
1010
1064
|
const inferredId = basename3(file).replace(FILE_TASK_PATTERN, "");
|
|
1011
1065
|
const id = isPlainRecord2(raw) && typeof raw.id === "string" ? raw.id : inferredId;
|
|
1012
1066
|
if (id === taskId) {
|
|
@@ -1166,8 +1220,8 @@ async function readConfiguredTaskSourceTask(projectRoot, taskId) {
|
|
|
1166
1220
|
}
|
|
1167
1221
|
|
|
1168
1222
|
// packages/runtime/src/control-plane/native/task-state.ts
|
|
1169
|
-
import { existsSync as
|
|
1170
|
-
import { basename as basename6, resolve as
|
|
1223
|
+
import { existsSync as existsSync14, readFileSync as readFileSync9, readdirSync as readdirSync3, statSync as statSync3, writeFileSync as writeFileSync6 } from "fs";
|
|
1224
|
+
import { basename as basename6, resolve as resolve16 } from "path";
|
|
1171
1225
|
|
|
1172
1226
|
// packages/runtime/src/control-plane/state-sync/types.ts
|
|
1173
1227
|
var SUPPORTED_TASK_STATE_SCHEMA_VERSION = 1;
|
|
@@ -1275,30 +1329,30 @@ function readTaskStateMetadataEnvelope(raw) {
|
|
|
1275
1329
|
};
|
|
1276
1330
|
}
|
|
1277
1331
|
// packages/runtime/src/control-plane/state-sync/read.ts
|
|
1278
|
-
import { existsSync as
|
|
1279
|
-
import { resolve as
|
|
1332
|
+
import { existsSync as existsSync13, readFileSync as readFileSync8 } from "fs";
|
|
1333
|
+
import { resolve as resolve15 } from "path";
|
|
1280
1334
|
|
|
1281
1335
|
// packages/runtime/src/control-plane/native/git-native.ts
|
|
1282
|
-
import { chmodSync, copyFileSync, existsSync as
|
|
1336
|
+
import { chmodSync, copyFileSync, existsSync as existsSync7, mkdirSync as mkdirSync4, readFileSync as readFileSync6, renameSync, rmSync as rmSync2, writeFileSync as writeFileSync5 } from "fs";
|
|
1283
1337
|
import { tmpdir as tmpdir3 } from "os";
|
|
1284
|
-
import { dirname as dirname5, isAbsolute, resolve as
|
|
1338
|
+
import { dirname as dirname5, isAbsolute, resolve as resolve9 } from "path";
|
|
1285
1339
|
import { createHash } from "crypto";
|
|
1286
1340
|
function isTextTreeCommitUpdate(update) {
|
|
1287
1341
|
return typeof update.content === "string";
|
|
1288
1342
|
}
|
|
1289
|
-
var sharedGitNativeOutputDir =
|
|
1290
|
-
var sharedGitNativeOutputPath =
|
|
1343
|
+
var sharedGitNativeOutputDir = resolve9(tmpdir3(), "rig-native");
|
|
1344
|
+
var sharedGitNativeOutputPath = resolve9(sharedGitNativeOutputDir, `rig-git-${process.platform}-${process.arch}${process.platform === "win32" ? ".exe" : ""}`);
|
|
1291
1345
|
var trackerCommandUsageProbe = "usage: rig-git fetch-ref <repo-path> <remote> <branch>";
|
|
1292
1346
|
function temporaryGitBinaryOutputPath(outputPath) {
|
|
1293
1347
|
const suffix = process.platform === "win32" ? ".exe" : "";
|
|
1294
|
-
return
|
|
1348
|
+
return resolve9(dirname5(outputPath), `.rig-git-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}${suffix}`);
|
|
1295
1349
|
}
|
|
1296
1350
|
function publishGitBinary(tempOutputPath, outputPath) {
|
|
1297
1351
|
try {
|
|
1298
1352
|
renameSync(tempOutputPath, outputPath);
|
|
1299
1353
|
} catch (error) {
|
|
1300
|
-
if (process.platform === "win32" &&
|
|
1301
|
-
|
|
1354
|
+
if (process.platform === "win32" && existsSync7(outputPath)) {
|
|
1355
|
+
rmSync2(outputPath, { force: true });
|
|
1302
1356
|
renameSync(tempOutputPath, outputPath);
|
|
1303
1357
|
return;
|
|
1304
1358
|
}
|
|
@@ -1313,22 +1367,22 @@ function rigGitSourceCandidates() {
|
|
|
1313
1367
|
const cwd = process.cwd()?.trim() || "";
|
|
1314
1368
|
const projectRoot = process.env.PROJECT_RIG_ROOT?.trim() || "";
|
|
1315
1369
|
const hostProjectRoot = process.env.RIG_HOST_PROJECT_ROOT?.trim() || "";
|
|
1316
|
-
const moduleRelativeSource =
|
|
1370
|
+
const moduleRelativeSource = resolve9(import.meta.dir, "../../../native/rig-git.zig");
|
|
1317
1371
|
return [...new Set([
|
|
1318
1372
|
process.env.RIG_NATIVE_GIT_SOURCE?.trim() || "",
|
|
1319
1373
|
moduleRelativeSource,
|
|
1320
|
-
projectRoot ?
|
|
1321
|
-
hostProjectRoot ?
|
|
1322
|
-
cwd ?
|
|
1323
|
-
execDir ?
|
|
1324
|
-
execDir ?
|
|
1374
|
+
projectRoot ? resolve9(projectRoot, "packages/runtime/native/rig-git.zig") : "",
|
|
1375
|
+
hostProjectRoot ? resolve9(hostProjectRoot, "packages/runtime/native/rig-git.zig") : "",
|
|
1376
|
+
cwd ? resolve9(cwd, "packages/runtime/native/rig-git.zig") : "",
|
|
1377
|
+
execDir ? resolve9(execDir, "..", "..", "packages/runtime/native/rig-git.zig") : "",
|
|
1378
|
+
execDir ? resolve9(execDir, "..", "native", "rig-git.zig") : ""
|
|
1325
1379
|
].filter(Boolean))];
|
|
1326
1380
|
}
|
|
1327
1381
|
function nativePackageBinaryCandidates(fromDir, fileName) {
|
|
1328
1382
|
const candidates = [];
|
|
1329
|
-
let cursor =
|
|
1383
|
+
let cursor = resolve9(fromDir);
|
|
1330
1384
|
for (let index = 0;index < 8; index += 1) {
|
|
1331
|
-
candidates.push(
|
|
1385
|
+
candidates.push(resolve9(cursor, "native", `${process.platform}-${process.arch}`, fileName), resolve9(cursor, "native", `${process.platform}-${process.arch}`, "bin", fileName), resolve9(cursor, "native", fileName), resolve9(cursor, "native", "bin", fileName));
|
|
1332
1386
|
const parent = dirname5(cursor);
|
|
1333
1387
|
if (parent === cursor)
|
|
1334
1388
|
break;
|
|
@@ -1343,15 +1397,15 @@ function rigGitBinaryCandidates() {
|
|
|
1343
1397
|
return [...new Set([
|
|
1344
1398
|
explicit,
|
|
1345
1399
|
...nativePackageBinaryCandidates(import.meta.dir, fileName),
|
|
1346
|
-
execDir ?
|
|
1347
|
-
execDir ?
|
|
1348
|
-
execDir ?
|
|
1400
|
+
execDir ? resolve9(execDir, fileName) : "",
|
|
1401
|
+
execDir ? resolve9(execDir, "..", fileName) : "",
|
|
1402
|
+
execDir ? resolve9(execDir, "..", "bin", fileName) : "",
|
|
1349
1403
|
sharedGitNativeOutputPath
|
|
1350
1404
|
].filter(Boolean))];
|
|
1351
1405
|
}
|
|
1352
1406
|
function resolveGitSourcePath() {
|
|
1353
1407
|
for (const candidate of rigGitSourceCandidates()) {
|
|
1354
|
-
if (candidate &&
|
|
1408
|
+
if (candidate && existsSync7(candidate)) {
|
|
1355
1409
|
return candidate;
|
|
1356
1410
|
}
|
|
1357
1411
|
}
|
|
@@ -1362,7 +1416,7 @@ function resolveGitBinaryPath() {
|
|
|
1362
1416
|
return null;
|
|
1363
1417
|
}
|
|
1364
1418
|
for (const candidate of rigGitBinaryCandidates()) {
|
|
1365
|
-
if (candidate &&
|
|
1419
|
+
if (candidate && existsSync7(candidate)) {
|
|
1366
1420
|
return candidate;
|
|
1367
1421
|
}
|
|
1368
1422
|
}
|
|
@@ -1392,18 +1446,18 @@ function nativeBuildManifestPath(outputPath) {
|
|
|
1392
1446
|
return `${outputPath}.build-manifest.json`;
|
|
1393
1447
|
}
|
|
1394
1448
|
function hasMatchingNativeBuildManifestSync(manifestPath, buildKey) {
|
|
1395
|
-
if (!
|
|
1449
|
+
if (!existsSync7(manifestPath)) {
|
|
1396
1450
|
return false;
|
|
1397
1451
|
}
|
|
1398
1452
|
try {
|
|
1399
|
-
const manifest = JSON.parse(
|
|
1453
|
+
const manifest = JSON.parse(readFileSync6(manifestPath, "utf8"));
|
|
1400
1454
|
return manifest.version === 1 && manifest.buildKey === buildKey;
|
|
1401
1455
|
} catch {
|
|
1402
1456
|
return false;
|
|
1403
1457
|
}
|
|
1404
1458
|
}
|
|
1405
1459
|
function sha256FileSync(path) {
|
|
1406
|
-
return createHash("sha256").update(
|
|
1460
|
+
return createHash("sha256").update(readFileSync6(path)).digest("hex");
|
|
1407
1461
|
}
|
|
1408
1462
|
function ensureRigGitBinaryPathSync(outputPath = preferredGitBinaryOutputPath()) {
|
|
1409
1463
|
if (process.env.RIG_DISABLE_ZIG_NATIVE === "1") {
|
|
@@ -1421,7 +1475,7 @@ function ensureRigGitBinaryPathSync(outputPath = preferredGitBinaryOutputPath())
|
|
|
1421
1475
|
if (!zigBinary) {
|
|
1422
1476
|
throw new Error("zig is required to build native Rig git tools.");
|
|
1423
1477
|
}
|
|
1424
|
-
|
|
1478
|
+
mkdirSync4(dirname5(outputPath), { recursive: true });
|
|
1425
1479
|
const sourceDigest = sha256FileSync(sourcePath);
|
|
1426
1480
|
const buildKey = JSON.stringify({
|
|
1427
1481
|
version: 1,
|
|
@@ -1432,7 +1486,7 @@ function ensureRigGitBinaryPathSync(outputPath = preferredGitBinaryOutputPath())
|
|
|
1432
1486
|
sourceDigest
|
|
1433
1487
|
});
|
|
1434
1488
|
const manifestPath = nativeBuildManifestPath(outputPath);
|
|
1435
|
-
const needsBuild = !
|
|
1489
|
+
const needsBuild = !existsSync7(outputPath) || !hasMatchingNativeBuildManifestSync(manifestPath, buildKey) || !binarySupportsTrackerCommandsSync(outputPath);
|
|
1436
1490
|
if (!needsBuild) {
|
|
1437
1491
|
chmodSync(outputPath, 493);
|
|
1438
1492
|
return outputPath;
|
|
@@ -1450,7 +1504,7 @@ function ensureRigGitBinaryPathSync(outputPath = preferredGitBinaryOutputPath())
|
|
|
1450
1504
|
stdout: "pipe",
|
|
1451
1505
|
stderr: "pipe"
|
|
1452
1506
|
});
|
|
1453
|
-
if (build.exitCode !== 0 || !
|
|
1507
|
+
if (build.exitCode !== 0 || !existsSync7(tempOutputPath)) {
|
|
1454
1508
|
const stderr = build.stderr.toString().trim();
|
|
1455
1509
|
const stdout = build.stdout.toString().trim();
|
|
1456
1510
|
const details = [stderr, stdout].filter(Boolean).join(`
|
|
@@ -1458,17 +1512,17 @@ function ensureRigGitBinaryPathSync(outputPath = preferredGitBinaryOutputPath())
|
|
|
1458
1512
|
throw new Error(`Failed to build native Rig git tools: ${details || `zig exited with code ${build.exitCode}`}`);
|
|
1459
1513
|
}
|
|
1460
1514
|
chmodSync(tempOutputPath, 493);
|
|
1461
|
-
if (
|
|
1462
|
-
|
|
1515
|
+
if (existsSync7(outputPath) && hasMatchingNativeBuildManifestSync(manifestPath, buildKey)) {
|
|
1516
|
+
rmSync2(tempOutputPath, { force: true });
|
|
1463
1517
|
chmodSync(outputPath, 493);
|
|
1464
1518
|
return outputPath;
|
|
1465
1519
|
}
|
|
1466
1520
|
publishGitBinary(tempOutputPath, outputPath);
|
|
1467
1521
|
if (!binarySupportsTrackerCommandsSync(outputPath)) {
|
|
1468
|
-
|
|
1522
|
+
rmSync2(outputPath, { force: true });
|
|
1469
1523
|
throw new Error("Failed to build native Rig git tools: tracker command probe failed");
|
|
1470
1524
|
}
|
|
1471
|
-
|
|
1525
|
+
writeFileSync5(manifestPath, `${JSON.stringify({ version: 1, buildKey }, null, 2)}
|
|
1472
1526
|
`, "utf8");
|
|
1473
1527
|
return outputPath;
|
|
1474
1528
|
}
|
|
@@ -1490,7 +1544,7 @@ function runGitNative(command, args) {
|
|
|
1490
1544
|
}
|
|
1491
1545
|
} else {
|
|
1492
1546
|
const explicitBinaryPath = process.env.RIG_NATIVE_GIT_BIN?.trim() || "";
|
|
1493
|
-
binaryPath = explicitBinaryPath &&
|
|
1547
|
+
binaryPath = explicitBinaryPath && existsSync7(explicitBinaryPath) ? explicitBinaryPath : !explicitBinaryPath ? resolveGitBinaryPath() : null;
|
|
1494
1548
|
if (!binaryPath) {
|
|
1495
1549
|
try {
|
|
1496
1550
|
binaryPath = ensureRigGitBinaryPathSync(preferredGitBinaryOutputPath());
|
|
@@ -1546,14 +1600,14 @@ function nativeFetchRef(repoPath, remote, branch) {
|
|
|
1546
1600
|
return requireGitNativeString("fetch-ref", [repoPath, remote, branch]);
|
|
1547
1601
|
}
|
|
1548
1602
|
function nativeReadBlobAtRef(repoPath, ref, path) {
|
|
1549
|
-
const requestDir =
|
|
1550
|
-
|
|
1551
|
-
const outputPath =
|
|
1603
|
+
const requestDir = resolve9(sharedGitNativeOutputDir, "reads", `${Date.now()}-${Math.random().toString(36).slice(2, 10)}`);
|
|
1604
|
+
mkdirSync4(requestDir, { recursive: true });
|
|
1605
|
+
const outputPath = resolve9(requestDir, "blob.txt");
|
|
1552
1606
|
try {
|
|
1553
1607
|
requireGitNative("read-blob-at-ref", [repoPath, ref, path, outputPath]);
|
|
1554
|
-
return
|
|
1608
|
+
return readFileSync6(outputPath, "utf8");
|
|
1555
1609
|
} finally {
|
|
1556
|
-
|
|
1610
|
+
rmSync2(requestDir, { recursive: true, force: true });
|
|
1557
1611
|
}
|
|
1558
1612
|
}
|
|
1559
1613
|
function serializeTreeCommitUpdates(updates) {
|
|
@@ -1572,16 +1626,16 @@ function buildTreeCommitUpdatesJson(updates) {
|
|
|
1572
1626
|
`;
|
|
1573
1627
|
}
|
|
1574
1628
|
function nativeWriteTreeCommit(repoPath, baseRef, updates, message) {
|
|
1575
|
-
const requestDir =
|
|
1576
|
-
|
|
1577
|
-
const messagePath =
|
|
1578
|
-
const updatesPath =
|
|
1629
|
+
const requestDir = resolve9(sharedGitNativeOutputDir, "requests", `${Date.now()}-${Math.random().toString(36).slice(2, 10)}`);
|
|
1630
|
+
mkdirSync4(requestDir, { recursive: true });
|
|
1631
|
+
const messagePath = resolve9(requestDir, "message.txt");
|
|
1632
|
+
const updatesPath = resolve9(requestDir, "updates.json");
|
|
1579
1633
|
try {
|
|
1580
|
-
|
|
1581
|
-
|
|
1634
|
+
writeFileSync5(messagePath, message, "utf8");
|
|
1635
|
+
writeFileSync5(updatesPath, buildTreeCommitUpdatesJson(updates), "utf8");
|
|
1582
1636
|
return requireGitNativeString("write-tree-commit", [repoPath, baseRef, messagePath, updatesPath]);
|
|
1583
1637
|
} finally {
|
|
1584
|
-
|
|
1638
|
+
rmSync2(requestDir, { recursive: true, force: true });
|
|
1585
1639
|
}
|
|
1586
1640
|
}
|
|
1587
1641
|
function nativePushRefWithLease(repoPath, localOid, remoteRef, expectedOldOid, remote = "origin") {
|
|
@@ -1596,35 +1650,35 @@ function nativePushRefWithLease(repoPath, localOid, remoteRef, expectedOldOid, r
|
|
|
1596
1650
|
|
|
1597
1651
|
// packages/runtime/src/control-plane/native/utils.ts
|
|
1598
1652
|
import { ptr as ptr2 } from "bun:ffi";
|
|
1599
|
-
import { existsSync as
|
|
1600
|
-
import { resolve as
|
|
1653
|
+
import { existsSync as existsSync10, readFileSync as readFileSync7 } from "fs";
|
|
1654
|
+
import { resolve as resolve12 } from "path";
|
|
1601
1655
|
|
|
1602
1656
|
// packages/runtime/src/layout.ts
|
|
1603
|
-
import { existsSync as
|
|
1604
|
-
import { basename as basename4, dirname as dirname6, resolve as
|
|
1657
|
+
import { existsSync as existsSync8 } from "fs";
|
|
1658
|
+
import { basename as basename4, dirname as dirname6, resolve as resolve10 } from "path";
|
|
1605
1659
|
var RIG_DEFINITION_DIRNAME = "rig";
|
|
1606
1660
|
var RIG_ARTIFACTS_DIRNAME = "artifacts";
|
|
1607
1661
|
function resolveMonorepoRoot(projectRoot) {
|
|
1608
|
-
const normalizedProjectRoot =
|
|
1662
|
+
const normalizedProjectRoot = resolve10(projectRoot);
|
|
1609
1663
|
const explicit = process.env.MONOREPO_ROOT?.trim();
|
|
1610
1664
|
if (explicit) {
|
|
1611
|
-
const explicitRoot =
|
|
1665
|
+
const explicitRoot = resolve10(explicit);
|
|
1612
1666
|
const explicitParent = dirname6(explicitRoot);
|
|
1613
1667
|
if (basename4(explicitParent) === ".worktrees") {
|
|
1614
1668
|
const owner = dirname6(explicitParent);
|
|
1615
|
-
const ownerHasGit =
|
|
1616
|
-
const ownerHasTaskConfig =
|
|
1617
|
-
const ownerHasRigConfig =
|
|
1669
|
+
const ownerHasGit = existsSync8(resolve10(owner, ".git"));
|
|
1670
|
+
const ownerHasTaskConfig = existsSync8(resolve10(owner, ".rig", "task-config.json"));
|
|
1671
|
+
const ownerHasRigConfig = existsSync8(resolve10(owner, "rig.config.ts"));
|
|
1618
1672
|
if (ownerHasGit && (ownerHasTaskConfig || ownerHasRigConfig)) {
|
|
1619
1673
|
return owner;
|
|
1620
1674
|
}
|
|
1621
1675
|
throw new Error(`MONOREPO_ROOT points to worktree ${explicitRoot}, but the owner checkout is incomplete at ${owner}.`);
|
|
1622
1676
|
}
|
|
1623
|
-
if (!
|
|
1677
|
+
if (!existsSync8(resolve10(explicitRoot, ".git"))) {
|
|
1624
1678
|
throw new Error(`MONOREPO_ROOT points to ${explicitRoot}, but no git checkout was found there.`);
|
|
1625
1679
|
}
|
|
1626
|
-
const hasTaskConfig =
|
|
1627
|
-
const hasRigConfig =
|
|
1680
|
+
const hasTaskConfig = existsSync8(resolve10(explicitRoot, ".rig", "task-config.json"));
|
|
1681
|
+
const hasRigConfig = existsSync8(resolve10(explicitRoot, "rig.config.ts"));
|
|
1628
1682
|
if (!hasTaskConfig && !hasRigConfig) {
|
|
1629
1683
|
throw new Error(`MONOREPO_ROOT points to ${explicitRoot}, but neither .rig/task-config.json nor rig.config.ts exists there.`);
|
|
1630
1684
|
}
|
|
@@ -1633,9 +1687,9 @@ function resolveMonorepoRoot(projectRoot) {
|
|
|
1633
1687
|
const projectParent = dirname6(normalizedProjectRoot);
|
|
1634
1688
|
if (basename4(projectParent) === ".worktrees") {
|
|
1635
1689
|
const worktreeOwner = dirname6(projectParent);
|
|
1636
|
-
const ownerHasGit =
|
|
1637
|
-
const ownerHasTaskConfig =
|
|
1638
|
-
const ownerHasRigConfig =
|
|
1690
|
+
const ownerHasGit = existsSync8(resolve10(worktreeOwner, ".git"));
|
|
1691
|
+
const ownerHasTaskConfig = existsSync8(resolve10(worktreeOwner, ".rig", "task-config.json"));
|
|
1692
|
+
const ownerHasRigConfig = existsSync8(resolve10(worktreeOwner, "rig.config.ts"));
|
|
1639
1693
|
if (ownerHasGit && (ownerHasTaskConfig || ownerHasRigConfig)) {
|
|
1640
1694
|
return worktreeOwner;
|
|
1641
1695
|
}
|
|
@@ -1643,28 +1697,28 @@ function resolveMonorepoRoot(projectRoot) {
|
|
|
1643
1697
|
return normalizedProjectRoot;
|
|
1644
1698
|
}
|
|
1645
1699
|
function resolveRuntimeWorkspaceLayout(workspaceDir) {
|
|
1646
|
-
const root =
|
|
1647
|
-
const rigRoot =
|
|
1648
|
-
const logsDir =
|
|
1649
|
-
const stateDir =
|
|
1650
|
-
const runtimeDir =
|
|
1651
|
-
const binDir =
|
|
1700
|
+
const root = resolve10(workspaceDir);
|
|
1701
|
+
const rigRoot = resolve10(root, ".rig");
|
|
1702
|
+
const logsDir = resolve10(rigRoot, "logs");
|
|
1703
|
+
const stateDir = resolve10(rigRoot, "state");
|
|
1704
|
+
const runtimeDir = resolve10(rigRoot, "runtime");
|
|
1705
|
+
const binDir = resolve10(rigRoot, "bin");
|
|
1652
1706
|
return {
|
|
1653
1707
|
workspaceDir: root,
|
|
1654
1708
|
rigRoot,
|
|
1655
1709
|
stateDir,
|
|
1656
1710
|
logsDir,
|
|
1657
|
-
artifactsRoot:
|
|
1711
|
+
artifactsRoot: resolve10(root, RIG_ARTIFACTS_DIRNAME),
|
|
1658
1712
|
runtimeDir,
|
|
1659
|
-
homeDir:
|
|
1660
|
-
tmpDir:
|
|
1661
|
-
cacheDir:
|
|
1662
|
-
sessionDir:
|
|
1713
|
+
homeDir: resolve10(rigRoot, "home"),
|
|
1714
|
+
tmpDir: resolve10(rigRoot, "tmp"),
|
|
1715
|
+
cacheDir: resolve10(rigRoot, "cache"),
|
|
1716
|
+
sessionDir: resolve10(rigRoot, "session"),
|
|
1663
1717
|
binDir,
|
|
1664
|
-
distDir:
|
|
1665
|
-
pluginBinDir:
|
|
1666
|
-
contextPath:
|
|
1667
|
-
controlPlaneEventsFile:
|
|
1718
|
+
distDir: resolve10(rigRoot, "dist"),
|
|
1719
|
+
pluginBinDir: resolve10(binDir, "plugins"),
|
|
1720
|
+
contextPath: resolve10(rigRoot, "runtime-context.json"),
|
|
1721
|
+
controlPlaneEventsFile: resolve10(logsDir, "control-plane.events.jsonl")
|
|
1668
1722
|
};
|
|
1669
1723
|
}
|
|
1670
1724
|
function resolveActiveRuntimeWorkspaceRoot(monorepoRoot) {
|
|
@@ -1672,14 +1726,14 @@ function resolveActiveRuntimeWorkspaceRoot(monorepoRoot) {
|
|
|
1672
1726
|
if (!explicit) {
|
|
1673
1727
|
throw new Error("No active runtime workspace. Set RIG_TASK_WORKSPACE or provision a task runtime first.");
|
|
1674
1728
|
}
|
|
1675
|
-
return
|
|
1729
|
+
return resolve10(explicit);
|
|
1676
1730
|
}
|
|
1677
1731
|
function resolveRigLayout(projectRoot) {
|
|
1678
1732
|
const monorepoRoot = resolveMonorepoRoot(projectRoot);
|
|
1679
|
-
const definitionRoot =
|
|
1733
|
+
const definitionRoot = resolve10(projectRoot, RIG_DEFINITION_DIRNAME);
|
|
1680
1734
|
const runtimeWorkspaceRoot = resolveActiveRuntimeWorkspaceRoot(monorepoRoot);
|
|
1681
1735
|
const runtimeLayout = resolveRuntimeWorkspaceLayout(runtimeWorkspaceRoot);
|
|
1682
|
-
const policyDir =
|
|
1736
|
+
const policyDir = resolve10(definitionRoot, "policy");
|
|
1683
1737
|
return {
|
|
1684
1738
|
projectRoot,
|
|
1685
1739
|
monorepoRoot,
|
|
@@ -1687,34 +1741,34 @@ function resolveRigLayout(projectRoot) {
|
|
|
1687
1741
|
runtimeWorkspaceRoot,
|
|
1688
1742
|
stateRoot: runtimeLayout.rigRoot,
|
|
1689
1743
|
artifactsRoot: runtimeLayout.artifactsRoot,
|
|
1690
|
-
configPath:
|
|
1691
|
-
taskConfigPath:
|
|
1744
|
+
configPath: resolve10(definitionRoot, "config.sh"),
|
|
1745
|
+
taskConfigPath: resolve10(runtimeWorkspaceRoot, ".rig", "task-config.json"),
|
|
1692
1746
|
policyDir,
|
|
1693
|
-
policyFile:
|
|
1694
|
-
pluginsDir:
|
|
1695
|
-
hooksDir:
|
|
1696
|
-
toolsDir:
|
|
1697
|
-
templatesDir:
|
|
1698
|
-
validationDir:
|
|
1747
|
+
policyFile: resolve10(policyDir, "policy.json"),
|
|
1748
|
+
pluginsDir: resolve10(definitionRoot, "plugins"),
|
|
1749
|
+
hooksDir: resolve10(definitionRoot, "hooks"),
|
|
1750
|
+
toolsDir: resolve10(definitionRoot, "tools"),
|
|
1751
|
+
templatesDir: resolve10(definitionRoot, "templates"),
|
|
1752
|
+
validationDir: resolve10(definitionRoot, "validation"),
|
|
1699
1753
|
stateDir: runtimeLayout.stateDir,
|
|
1700
1754
|
logsDir: runtimeLayout.logsDir,
|
|
1701
|
-
notificationsDir:
|
|
1755
|
+
notificationsDir: resolve10(definitionRoot, "notifications"),
|
|
1702
1756
|
runtimeDir: runtimeLayout.runtimeDir,
|
|
1703
1757
|
distDir: runtimeLayout.distDir,
|
|
1704
1758
|
binDir: runtimeLayout.binDir,
|
|
1705
1759
|
pluginBinDir: runtimeLayout.pluginBinDir,
|
|
1706
|
-
keybindingsPath:
|
|
1760
|
+
keybindingsPath: resolve10(definitionRoot, "keybindings.json"),
|
|
1707
1761
|
controlPlaneEventsFile: runtimeLayout.controlPlaneEventsFile
|
|
1708
1762
|
};
|
|
1709
1763
|
}
|
|
1710
1764
|
|
|
1711
1765
|
// packages/runtime/src/control-plane/native/runtime-native.ts
|
|
1712
1766
|
import { dlopen, ptr, suffix, toBuffer } from "bun:ffi";
|
|
1713
|
-
import { copyFileSync as copyFileSync2, existsSync as
|
|
1767
|
+
import { copyFileSync as copyFileSync2, existsSync as existsSync9, mkdirSync as mkdirSync5, renameSync as renameSync2, rmSync as rmSync3, statSync as statSync2 } from "fs";
|
|
1714
1768
|
import { tmpdir as tmpdir4 } from "os";
|
|
1715
|
-
import { dirname as dirname7, resolve as
|
|
1716
|
-
var sharedNativeRuntimeOutputDir =
|
|
1717
|
-
var sharedNativeRuntimeOutputPath =
|
|
1769
|
+
import { dirname as dirname7, resolve as resolve11 } from "path";
|
|
1770
|
+
var sharedNativeRuntimeOutputDir = resolve11(tmpdir4(), "rig-native");
|
|
1771
|
+
var sharedNativeRuntimeOutputPath = resolve11(sharedNativeRuntimeOutputDir, `runtime-native-${process.platform}-${process.arch}.${suffix}`);
|
|
1718
1772
|
var colocatedNativeRuntimeFileName = `runtime-native.${suffix}`;
|
|
1719
1773
|
var nativeRuntimeLibrary = await loadNativeRuntimeLibrary();
|
|
1720
1774
|
function requireNativeRuntimeLibrary(feature) {
|
|
@@ -1727,14 +1781,14 @@ async function ensureNativeRuntimeLibraryPath(outputPath = sharedNativeRuntimeOu
|
|
|
1727
1781
|
if (await buildNativeRuntimeLibrary(outputPath, options)) {
|
|
1728
1782
|
return outputPath;
|
|
1729
1783
|
}
|
|
1730
|
-
return !options.force &&
|
|
1784
|
+
return !options.force && existsSync9(outputPath) ? outputPath : null;
|
|
1731
1785
|
}
|
|
1732
1786
|
async function loadNativeRuntimeLibrary() {
|
|
1733
1787
|
if (process.env.RIG_DISABLE_ZIG_NATIVE === "1") {
|
|
1734
1788
|
return null;
|
|
1735
1789
|
}
|
|
1736
1790
|
for (const candidate of nativeRuntimeLibraryCandidates()) {
|
|
1737
|
-
if (!candidate || !
|
|
1791
|
+
if (!candidate || !existsSync9(candidate)) {
|
|
1738
1792
|
continue;
|
|
1739
1793
|
}
|
|
1740
1794
|
const loaded = tryDlopenNativeRuntimeLibrary(candidate);
|
|
@@ -1750,10 +1804,10 @@ async function loadNativeRuntimeLibrary() {
|
|
|
1750
1804
|
}
|
|
1751
1805
|
function nativePackageLibraryCandidates(fromDir, names) {
|
|
1752
1806
|
const candidates = [];
|
|
1753
|
-
let cursor =
|
|
1807
|
+
let cursor = resolve11(fromDir);
|
|
1754
1808
|
for (let index = 0;index < 8; index += 1) {
|
|
1755
1809
|
for (const name of names) {
|
|
1756
|
-
candidates.push(
|
|
1810
|
+
candidates.push(resolve11(cursor, "native", `${process.platform}-${process.arch}`, name), resolve11(cursor, "native", `${process.platform}-${process.arch}`, "lib", name), resolve11(cursor, "native", name), resolve11(cursor, "native", "lib", name));
|
|
1757
1811
|
}
|
|
1758
1812
|
const parent = dirname7(cursor);
|
|
1759
1813
|
if (parent === cursor)
|
|
@@ -1769,22 +1823,22 @@ function nativeRuntimeLibraryCandidates() {
|
|
|
1769
1823
|
return [...new Set([
|
|
1770
1824
|
explicit,
|
|
1771
1825
|
...nativePackageLibraryCandidates(import.meta.dir, [colocatedNativeRuntimeFileName, platformSpecific]),
|
|
1772
|
-
execDir ?
|
|
1773
|
-
execDir ?
|
|
1774
|
-
execDir ?
|
|
1775
|
-
execDir ?
|
|
1776
|
-
execDir ?
|
|
1777
|
-
execDir ?
|
|
1826
|
+
execDir ? resolve11(execDir, colocatedNativeRuntimeFileName) : "",
|
|
1827
|
+
execDir ? resolve11(execDir, platformSpecific) : "",
|
|
1828
|
+
execDir ? resolve11(execDir, "..", colocatedNativeRuntimeFileName) : "",
|
|
1829
|
+
execDir ? resolve11(execDir, "..", platformSpecific) : "",
|
|
1830
|
+
execDir ? resolve11(execDir, "lib", colocatedNativeRuntimeFileName) : "",
|
|
1831
|
+
execDir ? resolve11(execDir, "..", "lib", colocatedNativeRuntimeFileName) : "",
|
|
1778
1832
|
sharedNativeRuntimeOutputPath
|
|
1779
1833
|
].filter(Boolean))];
|
|
1780
1834
|
}
|
|
1781
1835
|
function resolveNativeRuntimeSourcePath() {
|
|
1782
1836
|
const explicit = process.env.RIG_NATIVE_RUNTIME_SOURCE?.trim();
|
|
1783
|
-
if (explicit &&
|
|
1837
|
+
if (explicit && existsSync9(explicit)) {
|
|
1784
1838
|
return explicit;
|
|
1785
1839
|
}
|
|
1786
|
-
const bundled =
|
|
1787
|
-
return
|
|
1840
|
+
const bundled = resolve11(import.meta.dir, "../../../native/snapshot.zig");
|
|
1841
|
+
return existsSync9(bundled) ? bundled : null;
|
|
1788
1842
|
}
|
|
1789
1843
|
async function buildNativeRuntimeLibrary(outputPath, options = {}) {
|
|
1790
1844
|
if (process.env.RIG_DISABLE_ZIG_NATIVE === "1") {
|
|
@@ -1797,8 +1851,8 @@ async function buildNativeRuntimeLibrary(outputPath, options = {}) {
|
|
|
1797
1851
|
}
|
|
1798
1852
|
const tempOutputPath = `${outputPath}.${process.pid}.${Date.now()}.${Math.random().toString(36).slice(2)}.tmp`;
|
|
1799
1853
|
try {
|
|
1800
|
-
|
|
1801
|
-
const needsBuild = options.force === true || !
|
|
1854
|
+
mkdirSync5(dirname7(outputPath), { recursive: true });
|
|
1855
|
+
const needsBuild = options.force === true || !existsSync9(outputPath) || statSync2(sourcePath).mtimeMs > statSync2(outputPath).mtimeMs;
|
|
1802
1856
|
if (!needsBuild) {
|
|
1803
1857
|
return true;
|
|
1804
1858
|
}
|
|
@@ -1816,14 +1870,14 @@ async function buildNativeRuntimeLibrary(outputPath, options = {}) {
|
|
|
1816
1870
|
stderr: "pipe"
|
|
1817
1871
|
});
|
|
1818
1872
|
const exitCode = await build.exited;
|
|
1819
|
-
if (exitCode !== 0 || !
|
|
1820
|
-
|
|
1873
|
+
if (exitCode !== 0 || !existsSync9(tempOutputPath)) {
|
|
1874
|
+
rmSync3(tempOutputPath, { force: true });
|
|
1821
1875
|
return false;
|
|
1822
1876
|
}
|
|
1823
1877
|
renameSync2(tempOutputPath, outputPath);
|
|
1824
1878
|
return true;
|
|
1825
1879
|
} catch {
|
|
1826
|
-
|
|
1880
|
+
rmSync3(tempOutputPath, { force: true });
|
|
1827
1881
|
return false;
|
|
1828
1882
|
}
|
|
1829
1883
|
}
|
|
@@ -1947,11 +2001,11 @@ async function runCaptureAsync(command, cwd, env, timeoutMs) {
|
|
|
1947
2001
|
return { exitCode, stdout, stderr };
|
|
1948
2002
|
}
|
|
1949
2003
|
function readJsonFile(path, fallback) {
|
|
1950
|
-
if (!
|
|
2004
|
+
if (!existsSync10(path)) {
|
|
1951
2005
|
return fallback;
|
|
1952
2006
|
}
|
|
1953
2007
|
try {
|
|
1954
|
-
return JSON.parse(
|
|
2008
|
+
return JSON.parse(readFileSync7(path, "utf-8"));
|
|
1955
2009
|
} catch {
|
|
1956
2010
|
return fallback;
|
|
1957
2011
|
}
|
|
@@ -1965,31 +2019,31 @@ function unique(values) {
|
|
|
1965
2019
|
function resolveHarnessPaths(projectRoot) {
|
|
1966
2020
|
const hasRuntimeWorkspace = Boolean(process.env.RIG_TASK_WORKSPACE?.trim());
|
|
1967
2021
|
const monorepoRoot = resolveMonorepoRoot2(projectRoot);
|
|
1968
|
-
const harnessRoot =
|
|
1969
|
-
const stateRoot =
|
|
2022
|
+
const harnessRoot = resolve12(projectRoot, "rig");
|
|
2023
|
+
const stateRoot = resolve12(projectRoot, ".rig");
|
|
1970
2024
|
const layout = hasRuntimeWorkspace ? resolveRigLayout(projectRoot) : null;
|
|
1971
|
-
const stateDir = layout?.stateDir ??
|
|
1972
|
-
const logsDir = layout?.logsDir ??
|
|
1973
|
-
const artifactsDir = layout?.artifactsRoot ??
|
|
1974
|
-
const taskConfigPath = layout?.taskConfigPath ??
|
|
1975
|
-
const binDir = layout?.binDir ??
|
|
2025
|
+
const stateDir = layout?.stateDir ?? resolve12(stateRoot, "state");
|
|
2026
|
+
const logsDir = layout?.logsDir ?? resolve12(stateRoot, "logs");
|
|
2027
|
+
const artifactsDir = layout?.artifactsRoot ?? resolve12(monorepoRoot, "artifacts");
|
|
2028
|
+
const taskConfigPath = layout?.taskConfigPath ?? resolve12(monorepoRoot, ".rig", "task-config.json");
|
|
2029
|
+
const binDir = layout?.binDir ?? resolve12(stateRoot, "bin");
|
|
1976
2030
|
return {
|
|
1977
2031
|
harnessRoot,
|
|
1978
2032
|
stateDir: process.env.RIG_STATE_DIR || stateDir,
|
|
1979
2033
|
artifactsDir,
|
|
1980
2034
|
logsDir: process.env.RIG_LOGS_DIR || logsDir,
|
|
1981
2035
|
binDir,
|
|
1982
|
-
hooksDir:
|
|
1983
|
-
validationDir:
|
|
2036
|
+
hooksDir: resolve12(harnessRoot, "hooks"),
|
|
2037
|
+
validationDir: resolve12(harnessRoot, "validation"),
|
|
1984
2038
|
taskConfigPath,
|
|
1985
|
-
sessionPath: process.env.RIG_SESSION_FILE ||
|
|
2039
|
+
sessionPath: process.env.RIG_SESSION_FILE || resolve12(stateRoot, "session", "session.json"),
|
|
1986
2040
|
monorepoRoot,
|
|
1987
|
-
tsApiTestsDir: process.env.TS_API_TESTS_DIR ||
|
|
1988
|
-
taskRepoCommitsPath:
|
|
1989
|
-
baseRepoPinsPath:
|
|
1990
|
-
failedApproachesPath:
|
|
1991
|
-
agentProfilePath:
|
|
1992
|
-
reviewProfilePath:
|
|
2041
|
+
tsApiTestsDir: process.env.TS_API_TESTS_DIR || resolve12(monorepoRoot, "TSAPITests"),
|
|
2042
|
+
taskRepoCommitsPath: resolve12(stateDir, "task-repo-commits.json"),
|
|
2043
|
+
baseRepoPinsPath: resolve12(stateDir, "base-repo-pins.json"),
|
|
2044
|
+
failedApproachesPath: resolve12(stateDir, "failed_approaches.md"),
|
|
2045
|
+
agentProfilePath: resolve12(stateDir, "agent-profile.json"),
|
|
2046
|
+
reviewProfilePath: resolve12(stateDir, "review-profile.json")
|
|
1993
2047
|
};
|
|
1994
2048
|
}
|
|
1995
2049
|
function normalizeRelativeScopePath(inputPath) {
|
|
@@ -2082,34 +2136,34 @@ function createNativeScopeMatcher() {
|
|
|
2082
2136
|
}
|
|
2083
2137
|
|
|
2084
2138
|
// packages/runtime/src/control-plane/state-sync/repo.ts
|
|
2085
|
-
import { existsSync as
|
|
2086
|
-
import { resolve as
|
|
2139
|
+
import { existsSync as existsSync12 } from "fs";
|
|
2140
|
+
import { resolve as resolve14 } from "path";
|
|
2087
2141
|
|
|
2088
2142
|
// packages/runtime/src/control-plane/repos/layout.ts
|
|
2089
|
-
import { existsSync as
|
|
2090
|
-
import { basename as basename5, dirname as dirname8, join as join3, resolve as
|
|
2143
|
+
import { existsSync as existsSync11 } from "fs";
|
|
2144
|
+
import { basename as basename5, dirname as dirname8, join as join3, resolve as resolve13 } from "path";
|
|
2091
2145
|
function resolveRepoStateDir(projectRoot) {
|
|
2092
|
-
const normalizedProjectRoot =
|
|
2146
|
+
const normalizedProjectRoot = resolve13(projectRoot);
|
|
2093
2147
|
const projectParent = dirname8(normalizedProjectRoot);
|
|
2094
2148
|
if (basename5(projectParent) === ".worktrees") {
|
|
2095
2149
|
const ownerRoot = dirname8(projectParent);
|
|
2096
|
-
const ownerHasRepoMarkers =
|
|
2150
|
+
const ownerHasRepoMarkers = existsSync11(resolve13(ownerRoot, ".git")) || existsSync11(resolve13(ownerRoot, ".rig", "state"));
|
|
2097
2151
|
if (ownerHasRepoMarkers) {
|
|
2098
|
-
return
|
|
2152
|
+
return resolve13(ownerRoot, ".rig", "state");
|
|
2099
2153
|
}
|
|
2100
2154
|
}
|
|
2101
|
-
return
|
|
2155
|
+
return resolve13(projectRoot, ".rig", "state");
|
|
2102
2156
|
}
|
|
2103
2157
|
function resolveManagedRepoLayout(projectRoot, repoId) {
|
|
2104
|
-
const normalizedProjectRoot =
|
|
2158
|
+
const normalizedProjectRoot = resolve13(projectRoot);
|
|
2105
2159
|
const entry = getManagedRepoEntry(repoId);
|
|
2106
2160
|
const stateDir = resolveRepoStateDir(normalizedProjectRoot);
|
|
2107
2161
|
const metadataRelativePath = join3("repos", entry.id);
|
|
2108
|
-
const metadataRoot =
|
|
2162
|
+
const metadataRoot = resolve13(stateDir, metadataRelativePath);
|
|
2109
2163
|
const runtimeWorkspace = process.env.RIG_TASK_WORKSPACE?.trim();
|
|
2110
|
-
const runsInsideTaskWorktree = runtimeWorkspace &&
|
|
2164
|
+
const runsInsideTaskWorktree = runtimeWorkspace && resolve13(runtimeWorkspace) === normalizedProjectRoot || basename5(dirname8(normalizedProjectRoot)) === ".worktrees";
|
|
2111
2165
|
const isPrimaryManagedRepo = listManagedRepoEntries()[0]?.id === repoId;
|
|
2112
|
-
const checkoutRoot = isPrimaryManagedRepo && runsInsideTaskWorktree ? resolveMonorepoRoot(normalizedProjectRoot) : entry.checkoutEnvVar && process.env[entry.checkoutEnvVar]?.trim() ?
|
|
2166
|
+
const checkoutRoot = isPrimaryManagedRepo && runsInsideTaskWorktree ? resolveMonorepoRoot(normalizedProjectRoot) : entry.checkoutEnvVar && process.env[entry.checkoutEnvVar]?.trim() ? resolve13(process.env[entry.checkoutEnvVar].trim()) : resolve13(normalizedProjectRoot, entry.alias);
|
|
2113
2167
|
return {
|
|
2114
2168
|
projectRoot: normalizedProjectRoot,
|
|
2115
2169
|
repoId: entry.id,
|
|
@@ -2117,12 +2171,12 @@ function resolveManagedRepoLayout(projectRoot, repoId) {
|
|
|
2117
2171
|
defaultBranch: entry.defaultBranch,
|
|
2118
2172
|
remoteUrl: entry.remoteEnvVar && process.env[entry.remoteEnvVar]?.trim() ? process.env[entry.remoteEnvVar].trim() : entry.defaultRemoteUrl,
|
|
2119
2173
|
checkoutRoot,
|
|
2120
|
-
worktreesRoot:
|
|
2174
|
+
worktreesRoot: resolve13(checkoutRoot, ".worktrees"),
|
|
2121
2175
|
stateDir,
|
|
2122
2176
|
metadataRoot,
|
|
2123
2177
|
metadataRelativePath,
|
|
2124
|
-
mirrorRoot:
|
|
2125
|
-
mirrorStatePath:
|
|
2178
|
+
mirrorRoot: resolve13(metadataRoot, "mirror.git"),
|
|
2179
|
+
mirrorStatePath: resolve13(metadataRoot, "mirror-state.json"),
|
|
2126
2180
|
mirrorStateRelativePath: join3(metadataRelativePath, "mirror-state.json")
|
|
2127
2181
|
};
|
|
2128
2182
|
}
|
|
@@ -2140,7 +2194,7 @@ function resolveTrackerRepoPath(projectRoot) {
|
|
|
2140
2194
|
const monorepoRoot = resolveMonorepoRoot2(projectRoot);
|
|
2141
2195
|
try {
|
|
2142
2196
|
const layout = resolveMonorepoRepoLayout(projectRoot);
|
|
2143
|
-
if (
|
|
2197
|
+
if (existsSync12(resolve14(layout.mirrorRoot, "HEAD"))) {
|
|
2144
2198
|
return layout.mirrorRoot;
|
|
2145
2199
|
}
|
|
2146
2200
|
} catch {}
|
|
@@ -2151,8 +2205,8 @@ function resolveTrackerRepoPath(projectRoot) {
|
|
|
2151
2205
|
var DEFAULT_READ_DEPS = {
|
|
2152
2206
|
fetchRef: nativeFetchRef,
|
|
2153
2207
|
readBlobAtRef: nativeReadBlobAtRef,
|
|
2154
|
-
exists:
|
|
2155
|
-
readFile: (path) =>
|
|
2208
|
+
exists: existsSync13,
|
|
2209
|
+
readFile: (path) => readFileSync8(path, "utf8")
|
|
2156
2210
|
};
|
|
2157
2211
|
function parseIssueStatus(rawStatus) {
|
|
2158
2212
|
const normalized = normalizeTaskLifecycleStatus(rawStatus);
|
|
@@ -2233,12 +2287,12 @@ function shouldPreferLocalTrackerState(options) {
|
|
|
2233
2287
|
if (runtimeContextPath) {
|
|
2234
2288
|
return true;
|
|
2235
2289
|
}
|
|
2236
|
-
return
|
|
2290
|
+
return existsSync13(resolve15(runtimeWorkspace, ".rig", "runtime-context.json"));
|
|
2237
2291
|
}
|
|
2238
2292
|
function readLocalTrackerState(projectRoot, deps) {
|
|
2239
2293
|
const monorepoRoot = resolveMonorepoRoot2(projectRoot);
|
|
2240
|
-
const issuesPath =
|
|
2241
|
-
const taskStatePath =
|
|
2294
|
+
const issuesPath = resolve15(monorepoRoot, ".beads", "issues.jsonl");
|
|
2295
|
+
const taskStatePath = resolve15(monorepoRoot, ".beads", "task-state.json");
|
|
2242
2296
|
return projectSyncedTrackerSnapshot({
|
|
2243
2297
|
source: "local",
|
|
2244
2298
|
issuesBaseOid: null,
|
|
@@ -2552,7 +2606,7 @@ function readValidationDescriptions(projectRoot) {
|
|
|
2552
2606
|
return readValidationDescriptionMap(raw);
|
|
2553
2607
|
}
|
|
2554
2608
|
function readSourceValidationDescriptions(projectRoot) {
|
|
2555
|
-
const rootRaw = readJsonFile(
|
|
2609
|
+
const rootRaw = readJsonFile(resolve16(projectRoot, "rig", "task-config.json"), {});
|
|
2556
2610
|
const sourcePath = findSourceTaskConfigPath(projectRoot);
|
|
2557
2611
|
const sourceRaw = sourcePath ? readJsonFile(sourcePath, {}) : {};
|
|
2558
2612
|
const rootDescriptions = readValidationDescriptionMap(rootRaw);
|
|
@@ -2628,15 +2682,15 @@ function readValidationDescriptionsFromMeta(meta) {
|
|
|
2628
2682
|
return meta.validation_descriptions;
|
|
2629
2683
|
}
|
|
2630
2684
|
function readLocalSourceTaskStateEnvelope(projectRoot) {
|
|
2631
|
-
const taskStatePath =
|
|
2685
|
+
const taskStatePath = resolve16(resolveMonorepoRoot2(projectRoot), ".beads", "task-state.json");
|
|
2632
2686
|
return readTaskStateMetadataEnvelope(readJsonFile(taskStatePath, {}));
|
|
2633
2687
|
}
|
|
2634
2688
|
function readLocalSourceTaskLifecycleStatus(projectRoot, taskId) {
|
|
2635
|
-
const issuesPath =
|
|
2636
|
-
if (!
|
|
2689
|
+
const issuesPath = resolve16(resolveMonorepoRoot2(projectRoot), ".beads", "issues.jsonl");
|
|
2690
|
+
if (!existsSync14(issuesPath)) {
|
|
2637
2691
|
return null;
|
|
2638
2692
|
}
|
|
2639
|
-
for (const line of
|
|
2693
|
+
for (const line of readFileSync9(issuesPath, "utf8").split(/\r?\n/)) {
|
|
2640
2694
|
const trimmed = line.trim();
|
|
2641
2695
|
if (!trimmed) {
|
|
2642
2696
|
continue;
|
|
@@ -2677,25 +2731,25 @@ function lookupTask(projectRoot, input) {
|
|
|
2677
2731
|
function artifactDirForId(projectRoot, id) {
|
|
2678
2732
|
const workspaceDir = process.env.RIG_TASK_WORKSPACE?.trim();
|
|
2679
2733
|
if (workspaceDir) {
|
|
2680
|
-
const worktreeArtifacts =
|
|
2681
|
-
if (
|
|
2734
|
+
const worktreeArtifacts = resolve16(workspaceDir, "artifacts", id);
|
|
2735
|
+
if (existsSync14(worktreeArtifacts) || existsSync14(resolve16(workspaceDir, "artifacts"))) {
|
|
2682
2736
|
return worktreeArtifacts;
|
|
2683
2737
|
}
|
|
2684
2738
|
}
|
|
2685
2739
|
try {
|
|
2686
2740
|
const paths = resolveHarnessPaths(projectRoot);
|
|
2687
|
-
return
|
|
2741
|
+
return resolve16(paths.artifactsDir, id);
|
|
2688
2742
|
} catch {
|
|
2689
|
-
return
|
|
2743
|
+
return resolve16(resolveMonorepoRoot2(projectRoot), "artifacts", id);
|
|
2690
2744
|
}
|
|
2691
2745
|
}
|
|
2692
2746
|
function resolveTaskConfigPath(projectRoot) {
|
|
2693
2747
|
const paths = resolveHarnessPaths(projectRoot);
|
|
2694
|
-
if (
|
|
2748
|
+
if (existsSync14(paths.taskConfigPath)) {
|
|
2695
2749
|
return paths.taskConfigPath;
|
|
2696
2750
|
}
|
|
2697
2751
|
for (const candidate of sourceTaskConfigCandidates(projectRoot)) {
|
|
2698
|
-
if (
|
|
2752
|
+
if (existsSync14(candidate)) {
|
|
2699
2753
|
return candidate;
|
|
2700
2754
|
}
|
|
2701
2755
|
}
|
|
@@ -2703,7 +2757,7 @@ function resolveTaskConfigPath(projectRoot) {
|
|
|
2703
2757
|
}
|
|
2704
2758
|
function findSourceTaskConfigPath(projectRoot) {
|
|
2705
2759
|
for (const candidate of sourceTaskConfigCandidates(projectRoot)) {
|
|
2706
|
-
if (
|
|
2760
|
+
if (existsSync14(candidate)) {
|
|
2707
2761
|
return candidate;
|
|
2708
2762
|
}
|
|
2709
2763
|
}
|
|
@@ -2716,7 +2770,7 @@ function readAndSyncSourceTaskConfig(projectRoot) {
|
|
|
2716
2770
|
const synced = synchronizeTaskConfigWithTracker(projectRoot, raw);
|
|
2717
2771
|
if (sourcePath && synced.updated) {
|
|
2718
2772
|
try {
|
|
2719
|
-
|
|
2773
|
+
writeFileSync6(sourcePath, `${JSON.stringify(synced.config, null, 2)}
|
|
2720
2774
|
`, "utf-8");
|
|
2721
2775
|
} catch {}
|
|
2722
2776
|
}
|
|
@@ -2768,12 +2822,12 @@ function shouldRefreshAutoSyncedTaskConfigEntry(entry) {
|
|
|
2768
2822
|
return !candidate.role;
|
|
2769
2823
|
}
|
|
2770
2824
|
function readSourceIssueRecords(projectRoot) {
|
|
2771
|
-
const issuesPath =
|
|
2772
|
-
if (!
|
|
2825
|
+
const issuesPath = resolve16(resolveMonorepoRoot2(projectRoot), ".beads", "issues.jsonl");
|
|
2826
|
+
if (!existsSync14(issuesPath)) {
|
|
2773
2827
|
return [];
|
|
2774
2828
|
}
|
|
2775
2829
|
const records = [];
|
|
2776
|
-
for (const line of
|
|
2830
|
+
for (const line of readFileSync9(issuesPath, "utf-8").split(/\r?\n/)) {
|
|
2777
2831
|
const trimmed = line.trim();
|
|
2778
2832
|
if (!trimmed) {
|
|
2779
2833
|
continue;
|
|
@@ -2829,19 +2883,19 @@ function readConfiguredFileTaskConfig(projectRoot) {
|
|
|
2829
2883
|
if (!sourcePath) {
|
|
2830
2884
|
return {};
|
|
2831
2885
|
}
|
|
2832
|
-
const directory =
|
|
2833
|
-
if (!
|
|
2886
|
+
const directory = resolve16(projectRoot, sourcePath);
|
|
2887
|
+
if (!existsSync14(directory)) {
|
|
2834
2888
|
return {};
|
|
2835
2889
|
}
|
|
2836
2890
|
const config = {};
|
|
2837
|
-
for (const name of
|
|
2891
|
+
for (const name of readdirSync3(directory)) {
|
|
2838
2892
|
if (!FILE_TASK_PATTERN2.test(name))
|
|
2839
2893
|
continue;
|
|
2840
|
-
const file =
|
|
2894
|
+
const file = resolve16(directory, name);
|
|
2841
2895
|
try {
|
|
2842
2896
|
if (!statSync3(file).isFile())
|
|
2843
2897
|
continue;
|
|
2844
|
-
const raw = JSON.parse(
|
|
2898
|
+
const raw = JSON.parse(readFileSync9(file, "utf8"));
|
|
2845
2899
|
if (!raw || typeof raw !== "object" || Array.isArray(raw))
|
|
2846
2900
|
continue;
|
|
2847
2901
|
const record = raw;
|
|
@@ -2883,10 +2937,10 @@ function firstStringList2(...candidates) {
|
|
|
2883
2937
|
return [];
|
|
2884
2938
|
}
|
|
2885
2939
|
function readConfiguredFilesTaskSourcePath2(projectRoot) {
|
|
2886
|
-
const jsonPath =
|
|
2887
|
-
if (
|
|
2940
|
+
const jsonPath = resolve16(projectRoot, "rig.config.json");
|
|
2941
|
+
if (existsSync14(jsonPath)) {
|
|
2888
2942
|
try {
|
|
2889
|
-
const parsed = JSON.parse(
|
|
2943
|
+
const parsed = JSON.parse(readFileSync9(jsonPath, "utf8"));
|
|
2890
2944
|
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
2891
2945
|
const taskSource = parsed.taskSource;
|
|
2892
2946
|
if (taskSource && typeof taskSource === "object" && !Array.isArray(taskSource)) {
|
|
@@ -2898,12 +2952,12 @@ function readConfiguredFilesTaskSourcePath2(projectRoot) {
|
|
|
2898
2952
|
return null;
|
|
2899
2953
|
}
|
|
2900
2954
|
}
|
|
2901
|
-
const tsPath =
|
|
2902
|
-
if (!
|
|
2955
|
+
const tsPath = resolve16(projectRoot, "rig.config.ts");
|
|
2956
|
+
if (!existsSync14(tsPath)) {
|
|
2903
2957
|
return null;
|
|
2904
2958
|
}
|
|
2905
2959
|
try {
|
|
2906
|
-
const source =
|
|
2960
|
+
const source = readFileSync9(tsPath, "utf8");
|
|
2907
2961
|
const taskSourceBlock = source.match(/taskSource\s*:\s*\{[\s\S]*?\}/m)?.[0] ?? "";
|
|
2908
2962
|
const kind = taskSourceBlock.match(/kind\s*:\s*["']([^"']+)["']/)?.[1];
|
|
2909
2963
|
if (kind !== "files") {
|
|
@@ -2917,23 +2971,23 @@ function readConfiguredFilesTaskSourcePath2(projectRoot) {
|
|
|
2917
2971
|
function sourceTaskConfigCandidates(projectRoot) {
|
|
2918
2972
|
const runtimeContext = loadRuntimeContextFromEnv();
|
|
2919
2973
|
return [
|
|
2920
|
-
runtimeContext?.monorepoMainRoot ?
|
|
2921
|
-
process.env.MONOREPO_MAIN_ROOT?.trim() ?
|
|
2922
|
-
|
|
2974
|
+
runtimeContext?.monorepoMainRoot ? resolve16(runtimeContext.monorepoMainRoot, ".rig", "task-config.json") : "",
|
|
2975
|
+
process.env.MONOREPO_MAIN_ROOT?.trim() ? resolve16(process.env.MONOREPO_MAIN_ROOT.trim(), ".rig", "task-config.json") : "",
|
|
2976
|
+
resolve16(resolveMonorepoRoot2(projectRoot), ".rig", "task-config.json")
|
|
2923
2977
|
].filter(Boolean);
|
|
2924
2978
|
}
|
|
2925
2979
|
|
|
2926
2980
|
// packages/runtime/src/control-plane/native/validator.ts
|
|
2927
|
-
import { existsSync as
|
|
2928
|
-
import { resolve as
|
|
2981
|
+
import { existsSync as existsSync18, mkdirSync as mkdirSync8, writeFileSync as writeFileSync8 } from "fs";
|
|
2982
|
+
import { resolve as resolve21 } from "path";
|
|
2929
2983
|
|
|
2930
2984
|
// packages/runtime/src/control-plane/native/validator-binaries.ts
|
|
2931
|
-
import { existsSync as
|
|
2932
|
-
import { dirname as dirname10, resolve as
|
|
2985
|
+
import { existsSync as existsSync17, mkdirSync as mkdirSync7, rmSync as rmSync5, statSync as statSync4 } from "fs";
|
|
2986
|
+
import { dirname as dirname10, resolve as resolve20 } from "path";
|
|
2933
2987
|
|
|
2934
2988
|
// packages/runtime/src/binary-run.ts
|
|
2935
|
-
import { chmodSync as chmodSync2, cpSync, existsSync as
|
|
2936
|
-
import { basename as basename7, dirname as dirname9, resolve as
|
|
2989
|
+
import { chmodSync as chmodSync2, cpSync, existsSync as existsSync15, mkdirSync as mkdirSync6, renameSync as renameSync3, rmSync as rmSync4, writeFileSync as writeFileSync7 } from "fs";
|
|
2990
|
+
import { basename as basename7, dirname as dirname9, resolve as resolve17 } from "path";
|
|
2937
2991
|
import { fileURLToPath } from "url";
|
|
2938
2992
|
import { drainMicrotasks, gcAndSweep } from "bun:jsc";
|
|
2939
2993
|
var runtimeBinaryBuildQueue = Promise.resolve();
|
|
@@ -2959,9 +3013,9 @@ async function buildRuntimeBinary(options) {
|
|
|
2959
3013
|
});
|
|
2960
3014
|
}
|
|
2961
3015
|
async function buildRuntimeBinaryInProcess(options, manifest) {
|
|
2962
|
-
const tempBuildDir =
|
|
2963
|
-
const tempOutputPath =
|
|
2964
|
-
|
|
3016
|
+
const tempBuildDir = resolve17(dirname9(options.outputPath), `.bun-build-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`);
|
|
3017
|
+
const tempOutputPath = resolve17(tempBuildDir, basename7(options.outputPath));
|
|
3018
|
+
mkdirSync6(tempBuildDir, { recursive: true });
|
|
2965
3019
|
await withTemporaryEnv({
|
|
2966
3020
|
...options.env,
|
|
2967
3021
|
...options.define ? { RIG_BUILD_CONFIG_JSON: JSON.stringify(options.define) } : {}
|
|
@@ -2986,7 +3040,7 @@ async function buildRuntimeBinaryInProcess(options, manifest) {
|
|
|
2986
3040
|
`);
|
|
2987
3041
|
throw new Error(`Failed to build ${options.entrypoint}: ${details || "Bun.build() returned errors"}`);
|
|
2988
3042
|
}
|
|
2989
|
-
if (!
|
|
3043
|
+
if (!existsSync15(tempOutputPath)) {
|
|
2990
3044
|
const emitted = buildResult.outputs.map((output) => output.path).join(", ") || "(none)";
|
|
2991
3045
|
throw new Error(`Failed to build ${options.entrypoint}: Bun.build() did not emit ${tempOutputPath}. Emitted: ${emitted}`);
|
|
2992
3046
|
}
|
|
@@ -3001,7 +3055,7 @@ async function buildRuntimeBinaryInProcess(options, manifest) {
|
|
|
3001
3055
|
});
|
|
3002
3056
|
}
|
|
3003
3057
|
})).finally(() => {
|
|
3004
|
-
|
|
3058
|
+
rmSync4(tempBuildDir, { recursive: true, force: true });
|
|
3005
3059
|
});
|
|
3006
3060
|
}
|
|
3007
3061
|
function runBestEffortBuildGc() {
|
|
@@ -3018,8 +3072,8 @@ function runtimeBinaryCacheManifestPath(outputPath) {
|
|
|
3018
3072
|
function resolveRuntimeBinaryBuildOptions(options) {
|
|
3019
3073
|
return {
|
|
3020
3074
|
...options,
|
|
3021
|
-
entrypoint:
|
|
3022
|
-
outputPath:
|
|
3075
|
+
entrypoint: resolve17(options.cwd, options.sourcePath),
|
|
3076
|
+
outputPath: resolve17(options.outputPath)
|
|
3023
3077
|
};
|
|
3024
3078
|
}
|
|
3025
3079
|
function shouldUseRuntimeBinaryBuildWorker() {
|
|
@@ -3033,7 +3087,7 @@ function shouldUseRuntimeBinaryBuildWorker() {
|
|
|
3033
3087
|
}
|
|
3034
3088
|
async function buildRuntimeBinaryViaWorker(options) {
|
|
3035
3089
|
const workerSourcePath = resolveRuntimeBinaryBuildWorkerSourcePath(options);
|
|
3036
|
-
if (!workerSourcePath || !
|
|
3090
|
+
if (!workerSourcePath || !existsSync15(workerSourcePath)) {
|
|
3037
3091
|
await buildRuntimeBinaryInProcess(options, {
|
|
3038
3092
|
manifestPath: runtimeBinaryCacheManifestPath(options.outputPath),
|
|
3039
3093
|
buildKey: createRuntimeBinaryBuildKey({
|
|
@@ -3064,13 +3118,13 @@ async function buildRuntimeBinaryViaWorker(options) {
|
|
|
3064
3118
|
new Response(build.stdout).text(),
|
|
3065
3119
|
new Response(build.stderr).text()
|
|
3066
3120
|
]);
|
|
3067
|
-
|
|
3121
|
+
rmSync4(payloadPath, { force: true });
|
|
3068
3122
|
if (exitCode !== 0) {
|
|
3069
3123
|
throw new Error(`Failed to build ${options.entrypoint}: ${(stderr || stdout || `worker exited ${exitCode}`).trim()}`);
|
|
3070
3124
|
}
|
|
3071
3125
|
}
|
|
3072
3126
|
function createRuntimeBinaryBuildWorkerPayloadPath(outputPath) {
|
|
3073
|
-
return
|
|
3127
|
+
return resolve17(dirname9(outputPath), `.bun-build-worker-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}.json`);
|
|
3074
3128
|
}
|
|
3075
3129
|
function resolveRuntimeBinaryBuildWorkerSourcePath(options) {
|
|
3076
3130
|
const envRoots = [
|
|
@@ -3079,13 +3133,13 @@ function resolveRuntimeBinaryBuildWorkerSourcePath(options) {
|
|
|
3079
3133
|
process.env.PROJECT_RIG_ROOT?.trim()
|
|
3080
3134
|
].filter(Boolean);
|
|
3081
3135
|
for (const root of envRoots) {
|
|
3082
|
-
const candidate =
|
|
3083
|
-
if (
|
|
3136
|
+
const candidate = resolve17(root, "packages/runtime/src/binary-build-worker.ts");
|
|
3137
|
+
if (existsSync15(candidate)) {
|
|
3084
3138
|
return candidate;
|
|
3085
3139
|
}
|
|
3086
3140
|
}
|
|
3087
|
-
const localCandidate =
|
|
3088
|
-
return
|
|
3141
|
+
const localCandidate = resolve17(import.meta.dir, "binary-build-worker.ts");
|
|
3142
|
+
return existsSync15(localCandidate) ? localCandidate : null;
|
|
3089
3143
|
}
|
|
3090
3144
|
function resolveRuntimeBinaryBuildWorkerInvocation() {
|
|
3091
3145
|
const bunPath = Bun.which("bun");
|
|
@@ -3121,7 +3175,7 @@ function createRuntimeBinaryBuildKey(input) {
|
|
|
3121
3175
|
});
|
|
3122
3176
|
}
|
|
3123
3177
|
async function isRuntimeBinaryBuildFresh(input) {
|
|
3124
|
-
if (!
|
|
3178
|
+
if (!existsSync15(input.outputPath) || !existsSync15(input.manifestPath)) {
|
|
3125
3179
|
return false;
|
|
3126
3180
|
}
|
|
3127
3181
|
let manifest = null;
|
|
@@ -3134,7 +3188,7 @@ async function isRuntimeBinaryBuildFresh(input) {
|
|
|
3134
3188
|
return false;
|
|
3135
3189
|
}
|
|
3136
3190
|
for (const [filePath, expectedDigest] of Object.entries(manifest.inputs || {})) {
|
|
3137
|
-
if (!
|
|
3191
|
+
if (!existsSync15(filePath)) {
|
|
3138
3192
|
return false;
|
|
3139
3193
|
}
|
|
3140
3194
|
if (await sha256File(filePath) !== expectedDigest) {
|
|
@@ -3147,7 +3201,7 @@ async function writeRuntimeBinaryCacheManifest(input) {
|
|
|
3147
3201
|
const inputs = {};
|
|
3148
3202
|
for (const inputPath of Object.keys(input.metafile?.inputs || {}).sort()) {
|
|
3149
3203
|
const normalized = normalizeBuildInputPath(input.cwd, inputPath);
|
|
3150
|
-
if (!normalized || !
|
|
3204
|
+
if (!normalized || !existsSync15(normalized)) {
|
|
3151
3205
|
continue;
|
|
3152
3206
|
}
|
|
3153
3207
|
inputs[normalized] = await sha256File(normalized);
|
|
@@ -3170,7 +3224,7 @@ function normalizeBuildInputPath(cwd, inputPath) {
|
|
|
3170
3224
|
if (inputPath.startsWith("<")) {
|
|
3171
3225
|
return null;
|
|
3172
3226
|
}
|
|
3173
|
-
return
|
|
3227
|
+
return resolve17(cwd, inputPath);
|
|
3174
3228
|
}
|
|
3175
3229
|
async function sha256File(path) {
|
|
3176
3230
|
const hasher = new Bun.CryptoHasher("sha256");
|
|
@@ -3186,8 +3240,8 @@ function sortRecord(value) {
|
|
|
3186
3240
|
async function runSerializedRuntimeBinaryBuild(action) {
|
|
3187
3241
|
const previous = runtimeBinaryBuildQueue;
|
|
3188
3242
|
let release;
|
|
3189
|
-
runtimeBinaryBuildQueue = new Promise((
|
|
3190
|
-
release =
|
|
3243
|
+
runtimeBinaryBuildQueue = new Promise((resolve18) => {
|
|
3244
|
+
release = resolve18;
|
|
3191
3245
|
});
|
|
3192
3246
|
await previous;
|
|
3193
3247
|
try {
|
|
@@ -3232,11 +3286,11 @@ async function withTemporaryCwd(cwd, action) {
|
|
|
3232
3286
|
}
|
|
3233
3287
|
|
|
3234
3288
|
// packages/runtime/src/control-plane/runtime/provisioning-env.ts
|
|
3235
|
-
import { delimiter, resolve as
|
|
3289
|
+
import { delimiter, resolve as resolve19 } from "path";
|
|
3236
3290
|
|
|
3237
3291
|
// packages/runtime/src/control-plane/runtime/runtime-paths.ts
|
|
3238
|
-
import { existsSync as
|
|
3239
|
-
import { resolve as
|
|
3292
|
+
import { existsSync as existsSync16, readdirSync as readdirSync4, realpathSync } from "fs";
|
|
3293
|
+
import { resolve as resolve18 } from "path";
|
|
3240
3294
|
|
|
3241
3295
|
// packages/runtime/src/control-plane/runtime/sandbox/utils.ts
|
|
3242
3296
|
function uniq(values) {
|
|
@@ -3254,7 +3308,7 @@ function resolveBunBinaryPath() {
|
|
|
3254
3308
|
}
|
|
3255
3309
|
const home = process.env.HOME?.trim();
|
|
3256
3310
|
const fallbackCandidates = [
|
|
3257
|
-
home ?
|
|
3311
|
+
home ? resolve18(home, ".bun/bin/bun") : "",
|
|
3258
3312
|
"/opt/homebrew/bin/bun",
|
|
3259
3313
|
"/usr/local/bin/bun",
|
|
3260
3314
|
"/usr/bin/bun"
|
|
@@ -3282,8 +3336,8 @@ function resolveClaudeBinaryPath() {
|
|
|
3282
3336
|
}
|
|
3283
3337
|
const home = process.env.HOME?.trim();
|
|
3284
3338
|
const fallbackCandidates = [
|
|
3285
|
-
home ?
|
|
3286
|
-
home ?
|
|
3339
|
+
home ? resolve18(home, ".local/bin/claude") : "",
|
|
3340
|
+
home ? resolve18(home, ".local/share/claude/local/claude") : "",
|
|
3287
3341
|
"/opt/homebrew/bin/claude",
|
|
3288
3342
|
"/usr/local/bin/claude",
|
|
3289
3343
|
"/usr/bin/claude"
|
|
@@ -3297,51 +3351,51 @@ function resolveClaudeBinaryPath() {
|
|
|
3297
3351
|
throw new Error("claude not found in PATH");
|
|
3298
3352
|
}
|
|
3299
3353
|
function resolveBunInstallDir(bunBinaryPath = resolveBunBinaryPath()) {
|
|
3300
|
-
return
|
|
3354
|
+
return resolve18(bunBinaryPath, "../..");
|
|
3301
3355
|
}
|
|
3302
3356
|
function resolveClaudeInstallDir() {
|
|
3303
3357
|
const realPath = resolveClaudeBinaryPath();
|
|
3304
|
-
return
|
|
3358
|
+
return resolve18(realPath, "..");
|
|
3305
3359
|
}
|
|
3306
3360
|
function resolveNodeInstallDir() {
|
|
3307
3361
|
const preferredNode = resolvePreferredNodeBinary();
|
|
3308
3362
|
if (!preferredNode)
|
|
3309
3363
|
return null;
|
|
3310
3364
|
const explicitNode = process.env.RIG_NODE_BIN?.trim();
|
|
3311
|
-
if (explicitNode &&
|
|
3312
|
-
return preferredNode.endsWith("/bin/node") ?
|
|
3365
|
+
if (explicitNode && resolve18(explicitNode) === resolve18(preferredNode)) {
|
|
3366
|
+
return preferredNode.endsWith("/bin/node") ? resolve18(preferredNode, "../..") : resolve18(preferredNode, "..");
|
|
3313
3367
|
}
|
|
3314
3368
|
try {
|
|
3315
3369
|
const realPath = realpathSync(preferredNode);
|
|
3316
3370
|
if (realPath.endsWith("/bin/node")) {
|
|
3317
|
-
return
|
|
3371
|
+
return resolve18(realPath, "../..");
|
|
3318
3372
|
}
|
|
3319
|
-
return
|
|
3373
|
+
return resolve18(realPath, "..");
|
|
3320
3374
|
} catch {
|
|
3321
|
-
return
|
|
3375
|
+
return resolve18(preferredNode, "..");
|
|
3322
3376
|
}
|
|
3323
3377
|
}
|
|
3324
3378
|
function resolvePreferredNodeBinary() {
|
|
3325
3379
|
const candidates = [];
|
|
3326
3380
|
const envNode = process.env.RIG_NODE_BIN?.trim();
|
|
3327
3381
|
if (envNode) {
|
|
3328
|
-
const explicit =
|
|
3329
|
-
if (
|
|
3382
|
+
const explicit = resolve18(envNode);
|
|
3383
|
+
if (existsSync16(explicit)) {
|
|
3330
3384
|
return explicit;
|
|
3331
3385
|
}
|
|
3332
3386
|
}
|
|
3333
3387
|
const nvmBin = process.env.NVM_BIN?.trim();
|
|
3334
3388
|
if (nvmBin) {
|
|
3335
|
-
candidates.push(
|
|
3389
|
+
candidates.push(resolve18(nvmBin, "node"));
|
|
3336
3390
|
}
|
|
3337
3391
|
const home = process.env.HOME?.trim();
|
|
3338
3392
|
if (home) {
|
|
3339
|
-
const nvmVersionsDir =
|
|
3340
|
-
if (
|
|
3393
|
+
const nvmVersionsDir = resolve18(home, ".nvm/versions/node");
|
|
3394
|
+
if (existsSync16(nvmVersionsDir)) {
|
|
3341
3395
|
try {
|
|
3342
|
-
const versionDirs =
|
|
3396
|
+
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/, "")));
|
|
3343
3397
|
for (const versionDir of versionDirs) {
|
|
3344
|
-
candidates.push(
|
|
3398
|
+
candidates.push(resolve18(nvmVersionsDir, versionDir, "bin/node"));
|
|
3345
3399
|
}
|
|
3346
3400
|
} catch {}
|
|
3347
3401
|
}
|
|
@@ -3350,8 +3404,8 @@ function resolvePreferredNodeBinary() {
|
|
|
3350
3404
|
if (whichNode) {
|
|
3351
3405
|
candidates.push(whichNode);
|
|
3352
3406
|
}
|
|
3353
|
-
const deduped = uniq(candidates.map((candidate) =>
|
|
3354
|
-
const existing = deduped.filter((candidate) =>
|
|
3407
|
+
const deduped = uniq(candidates.map((candidate) => resolve18(candidate)));
|
|
3408
|
+
const existing = deduped.filter((candidate) => existsSync16(candidate));
|
|
3355
3409
|
if (existing.length === 0) {
|
|
3356
3410
|
return null;
|
|
3357
3411
|
}
|
|
@@ -3365,7 +3419,7 @@ function resolvePreferredNodeBinary() {
|
|
|
3365
3419
|
return existing[0] ?? null;
|
|
3366
3420
|
}
|
|
3367
3421
|
function inferNodeMajor(nodeBinaryPath) {
|
|
3368
|
-
const normalized =
|
|
3422
|
+
const normalized = resolve18(nodeBinaryPath).replace(/\\/g, "/");
|
|
3369
3423
|
const match = normalized.match(/(?:^|\/)(?:node-)?v?(\d+)\.\d+\.\d+(?:\/|$)/);
|
|
3370
3424
|
if (!match) {
|
|
3371
3425
|
return null;
|
|
@@ -3377,8 +3431,8 @@ function normalizeExecutablePath(candidate) {
|
|
|
3377
3431
|
if (!candidate) {
|
|
3378
3432
|
return "";
|
|
3379
3433
|
}
|
|
3380
|
-
const normalized =
|
|
3381
|
-
if (!
|
|
3434
|
+
const normalized = resolve18(candidate);
|
|
3435
|
+
if (!existsSync16(normalized)) {
|
|
3382
3436
|
return "";
|
|
3383
3437
|
}
|
|
3384
3438
|
try {
|
|
@@ -3388,7 +3442,7 @@ function normalizeExecutablePath(candidate) {
|
|
|
3388
3442
|
}
|
|
3389
3443
|
}
|
|
3390
3444
|
function looksLikeRuntimeGateway(candidate) {
|
|
3391
|
-
const normalized =
|
|
3445
|
+
const normalized = resolve18(candidate).replace(/\\/g, "/");
|
|
3392
3446
|
return normalized.includes("/.rig/bin/") || normalized.endsWith("/rig-shell") || normalized.endsWith("/rig-agent");
|
|
3393
3447
|
}
|
|
3394
3448
|
|
|
@@ -3409,7 +3463,7 @@ function runtimeProvisioningEnv(baseEnv = process.env) {
|
|
|
3409
3463
|
try {
|
|
3410
3464
|
return resolveClaudeInstallDir();
|
|
3411
3465
|
} catch {
|
|
3412
|
-
return
|
|
3466
|
+
return resolve19(claudeBinary, "..");
|
|
3413
3467
|
}
|
|
3414
3468
|
})() : "";
|
|
3415
3469
|
const nodeDir = resolveNodeInstallDir();
|
|
@@ -3419,8 +3473,8 @@ function runtimeProvisioningEnv(baseEnv = process.env) {
|
|
|
3419
3473
|
`${bunDir}/bin`,
|
|
3420
3474
|
claudeDir,
|
|
3421
3475
|
nodeDir ? `${nodeDir}/bin` : "",
|
|
3422
|
-
realHome ?
|
|
3423
|
-
realHome ?
|
|
3476
|
+
realHome ? resolve19(realHome, ".local/bin") : "",
|
|
3477
|
+
realHome ? resolve19(realHome, ".cargo/bin") : "",
|
|
3424
3478
|
...inheritedPath,
|
|
3425
3479
|
"/usr/local/bin",
|
|
3426
3480
|
"/usr/local/sbin",
|
|
@@ -3451,9 +3505,9 @@ function runtimeProvisioningEnv(baseEnv = process.env) {
|
|
|
3451
3505
|
// packages/runtime/src/control-plane/native/validator-binaries.ts
|
|
3452
3506
|
function resolveValidatorBinaryPath(projectRoot, binaryName, runtimeContext) {
|
|
3453
3507
|
if (runtimeContext) {
|
|
3454
|
-
return
|
|
3508
|
+
return resolve20(runtimeContext.binDir, "validators", binaryName);
|
|
3455
3509
|
}
|
|
3456
|
-
return
|
|
3510
|
+
return resolve20(resolveHarnessPaths(projectRoot).binDir, "validators", binaryName);
|
|
3457
3511
|
}
|
|
3458
3512
|
async function ensureValidatorBinary(projectRoot, checkId, runtimeContext) {
|
|
3459
3513
|
const match = checkId.match(/^([a-z][\w-]*):([a-z][\w-]*)$/);
|
|
@@ -3468,19 +3522,19 @@ async function ensureValidatorBinary(projectRoot, checkId, runtimeContext) {
|
|
|
3468
3522
|
const binaryName = `${category}-${check}`;
|
|
3469
3523
|
const binaryPath = resolveValidatorBinaryPath(projectRoot, binaryName, runtimeContext);
|
|
3470
3524
|
const hostProjectRoot = runtimeContext?.hostProjectRoot?.trim() || projectRoot;
|
|
3471
|
-
const sourcePath =
|
|
3472
|
-
if (!
|
|
3525
|
+
const sourcePath = resolve20(hostProjectRoot, "packages/runtime/src/control-plane/validators", category, `${check}.ts`);
|
|
3526
|
+
if (!existsSync17(sourcePath)) {
|
|
3473
3527
|
return null;
|
|
3474
3528
|
}
|
|
3475
3529
|
const sourceMtime = statSync4(sourcePath).mtimeMs;
|
|
3476
|
-
const binaryExists =
|
|
3530
|
+
const binaryExists = existsSync17(binaryPath);
|
|
3477
3531
|
const binaryMtime = binaryExists ? statSync4(binaryPath).mtimeMs : 0;
|
|
3478
3532
|
if (!binaryExists || sourceMtime > binaryMtime) {
|
|
3479
3533
|
if (binaryExists) {
|
|
3480
|
-
|
|
3481
|
-
|
|
3534
|
+
rmSync5(binaryPath, { force: true });
|
|
3535
|
+
rmSync5(`${binaryPath}.build-manifest.json`, { force: true });
|
|
3482
3536
|
}
|
|
3483
|
-
|
|
3537
|
+
mkdirSync7(dirname10(binaryPath), { recursive: true });
|
|
3484
3538
|
await buildRuntimeBinary({
|
|
3485
3539
|
sourcePath: `packages/runtime/src/control-plane/validators/${category}/${check}.ts`,
|
|
3486
3540
|
outputPath: binaryPath,
|
|
@@ -3489,7 +3543,7 @@ async function ensureValidatorBinary(projectRoot, checkId, runtimeContext) {
|
|
|
3489
3543
|
env: runtimeProvisioningEnv()
|
|
3490
3544
|
});
|
|
3491
3545
|
}
|
|
3492
|
-
return
|
|
3546
|
+
return existsSync17(binaryPath) ? binaryPath : null;
|
|
3493
3547
|
}
|
|
3494
3548
|
|
|
3495
3549
|
// packages/runtime/src/control-plane/native/validator.ts
|
|
@@ -3526,20 +3580,20 @@ async function readTaskSourceValidation(projectRoot, taskId) {
|
|
|
3526
3580
|
function resolveValidationPaths(projectRoot, taskId, runtimeContext) {
|
|
3527
3581
|
if (runtimeContext) {
|
|
3528
3582
|
return {
|
|
3529
|
-
taskLogDir:
|
|
3530
|
-
artifactDir:
|
|
3583
|
+
taskLogDir: resolve21(runtimeContext.logsDir, taskId),
|
|
3584
|
+
artifactDir: resolve21(runtimeContext.workspaceDir, "artifacts", taskId)
|
|
3531
3585
|
};
|
|
3532
3586
|
}
|
|
3533
3587
|
const paths = resolveHarnessPaths(projectRoot);
|
|
3534
3588
|
return {
|
|
3535
|
-
taskLogDir:
|
|
3536
|
-
artifactDir:
|
|
3589
|
+
taskLogDir: resolve21(paths.logsDir, taskId),
|
|
3590
|
+
artifactDir: resolve21(paths.artifactsDir, taskId)
|
|
3537
3591
|
};
|
|
3538
3592
|
}
|
|
3539
3593
|
async function runValidatorBinary(projectRoot, taskId, checkId, runtimeContext) {
|
|
3540
3594
|
const binaryName = checkId.replace(":", "-");
|
|
3541
3595
|
const binaryPath = await ensureValidatorBinary(projectRoot, checkId, runtimeContext) ?? resolveValidatorBinaryPath(projectRoot, binaryName, runtimeContext);
|
|
3542
|
-
if (!
|
|
3596
|
+
if (!existsSync18(binaryPath)) {
|
|
3543
3597
|
return {
|
|
3544
3598
|
result: {
|
|
3545
3599
|
id: checkId,
|
|
@@ -3550,7 +3604,7 @@ async function runValidatorBinary(projectRoot, taskId, checkId, runtimeContext)
|
|
|
3550
3604
|
};
|
|
3551
3605
|
}
|
|
3552
3606
|
const validatorCwd = runtimeContext?.workspaceDir || resolveMonorepoRoot(projectRoot);
|
|
3553
|
-
const runtimeShellPath = runtimeContext ?
|
|
3607
|
+
const runtimeShellPath = runtimeContext ? resolve21(runtimeContext.binDir, "rig-shell") : "";
|
|
3554
3608
|
const monorepoMainRoot = runtimeContext?.monorepoMainRoot || process.env.MONOREPO_MAIN_ROOT?.trim() || resolveMonorepoRoot(projectRoot);
|
|
3555
3609
|
const validatorEnv = {
|
|
3556
3610
|
PROJECT_RIG_ROOT: runtimeContext?.hostProjectRoot || projectRoot,
|
|
@@ -3565,7 +3619,7 @@ async function runValidatorBinary(projectRoot, taskId, checkId, runtimeContext)
|
|
|
3565
3619
|
validatorEnv.RIG_LOGS_DIR = runtimeContext.logsDir;
|
|
3566
3620
|
validatorEnv.RIG_RUNTIME_BIN_DIR = runtimeContext.binDir;
|
|
3567
3621
|
}
|
|
3568
|
-
const { exitCode, stdout, stderr } = await runCaptureAsync(runtimeShellPath &&
|
|
3622
|
+
const { exitCode, stdout, stderr } = await runCaptureAsync(runtimeShellPath && existsSync18(runtimeShellPath) ? [runtimeShellPath, "run-binary", binaryPath] : [binaryPath], validatorCwd, validatorEnv);
|
|
3569
3623
|
try {
|
|
3570
3624
|
const result = JSON.parse(stdout.trim());
|
|
3571
3625
|
return { result, exitCode };
|
|
@@ -3605,8 +3659,8 @@ async function validateTask(projectRoot, taskId, runtimeContext, registry, optio
|
|
|
3605
3659
|
const configuredValidation = stringArray(taskConfig[taskId]?.validation);
|
|
3606
3660
|
const commands = resolvedContext?.validation?.length ? resolvedContext.validation : configuredValidation.length > 0 ? configuredValidation : sourceValidation.validation;
|
|
3607
3661
|
const { taskLogDir, artifactDir } = resolveValidationPaths(projectRoot, taskId, resolvedContext);
|
|
3608
|
-
|
|
3609
|
-
|
|
3662
|
+
mkdirSync8(taskLogDir, { recursive: true });
|
|
3663
|
+
mkdirSync8(artifactDir, { recursive: true });
|
|
3610
3664
|
if (commands.length === 0) {
|
|
3611
3665
|
const skipped = {
|
|
3612
3666
|
status: "skipped",
|
|
@@ -3615,7 +3669,7 @@ async function validateTask(projectRoot, taskId, runtimeContext, registry, optio
|
|
|
3615
3669
|
failed: 0,
|
|
3616
3670
|
categories: []
|
|
3617
3671
|
};
|
|
3618
|
-
|
|
3672
|
+
writeFileSync8(resolve21(artifactDir, "validation-summary.json"), `${JSON.stringify(skipped, null, 2)}
|
|
3619
3673
|
`, "utf-8");
|
|
3620
3674
|
return skipped;
|
|
3621
3675
|
}
|
|
@@ -3650,18 +3704,18 @@ async function validateTask(projectRoot, taskId, runtimeContext, registry, optio
|
|
|
3650
3704
|
exit_code: 2,
|
|
3651
3705
|
duration_seconds: 0
|
|
3652
3706
|
});
|
|
3653
|
-
const logFile2 =
|
|
3654
|
-
|
|
3655
|
-
|
|
3707
|
+
const logFile2 = resolve21(taskLogDir, `invalid-entry-validation.log`);
|
|
3708
|
+
mkdirSync8(taskLogDir, { recursive: true });
|
|
3709
|
+
writeFileSync8(logFile2, `=== ${nowIso()} :: ${cmd} ===
|
|
3656
3710
|
Invalid validation entry: not a check-ID. All entries must use format "category:check-name".
|
|
3657
3711
|
`, "utf-8");
|
|
3658
3712
|
continue;
|
|
3659
3713
|
}
|
|
3660
3714
|
const { result, exitCode } = await dispatchValidator(cmd, effectiveRegistry, validatorCtx, (id) => runValidatorBinary(projectRoot, taskId, id, resolvedContext));
|
|
3661
3715
|
const durationSeconds = Math.max(0, Math.round((Date.now() - startedAt) / 1000));
|
|
3662
|
-
const logFile =
|
|
3663
|
-
|
|
3664
|
-
|
|
3716
|
+
const logFile = resolve21(taskLogDir, `${cmd.replace(":", "-")}-validation.log`);
|
|
3717
|
+
mkdirSync8(taskLogDir, { recursive: true });
|
|
3718
|
+
writeFileSync8(logFile, `=== ${nowIso()} :: ${cmd} ===
|
|
3665
3719
|
${JSON.stringify(result, null, 2)}
|
|
3666
3720
|
`, "utf-8");
|
|
3667
3721
|
if (result.passed) {
|
|
@@ -3683,15 +3737,15 @@ ${JSON.stringify(result, null, 2)}
|
|
|
3683
3737
|
failed,
|
|
3684
3738
|
categories
|
|
3685
3739
|
};
|
|
3686
|
-
|
|
3687
|
-
|
|
3740
|
+
mkdirSync8(artifactDir, { recursive: true });
|
|
3741
|
+
writeFileSync8(resolve21(artifactDir, "validation-summary.json"), `${JSON.stringify(summary, null, 2)}
|
|
3688
3742
|
`, "utf-8");
|
|
3689
3743
|
return summary;
|
|
3690
3744
|
}
|
|
3691
3745
|
|
|
3692
3746
|
// packages/runtime/src/control-plane/native/verifier.ts
|
|
3693
|
-
import { existsSync as
|
|
3694
|
-
import { resolve as
|
|
3747
|
+
import { existsSync as existsSync20, mkdirSync as mkdirSync10, writeFileSync as writeFileSync10 } from "fs";
|
|
3748
|
+
import { resolve as resolve23 } from "path";
|
|
3695
3749
|
|
|
3696
3750
|
// packages/runtime/src/control-plane/runtime/baked-secrets.ts
|
|
3697
3751
|
var BAKED_RUNTIME_SECRETS = {
|
|
@@ -3737,8 +3791,8 @@ function resolveRuntimeSecrets(env, baked = BAKED_RUNTIME_SECRETS) {
|
|
|
3737
3791
|
}
|
|
3738
3792
|
|
|
3739
3793
|
// packages/runtime/src/control-plane/native/git-ops.ts
|
|
3740
|
-
import { existsSync as
|
|
3741
|
-
import { dirname as dirname11, isAbsolute as isAbsolute2, resolve as
|
|
3794
|
+
import { existsSync as existsSync19, lstatSync, mkdirSync as mkdirSync9, readFileSync as readFileSync10, writeFileSync as writeFileSync9 } from "fs";
|
|
3795
|
+
import { dirname as dirname11, isAbsolute as isAbsolute2, resolve as resolve22 } from "path";
|
|
3742
3796
|
|
|
3743
3797
|
// packages/runtime/src/control-plane/native/pr-review-gate.ts
|
|
3744
3798
|
function parseJsonObject(value) {
|
|
@@ -4995,12 +5049,12 @@ var TASK_ARTIFACT_STAGE_FALLBACK = new Set([
|
|
|
4995
5049
|
"validation-summary.json"
|
|
4996
5050
|
]);
|
|
4997
5051
|
function readPrMetadata(projectRoot, taskId) {
|
|
4998
|
-
const path =
|
|
4999
|
-
if (!
|
|
5052
|
+
const path = resolve22(artifactDirForId(projectRoot, taskId), "pr-state.json");
|
|
5053
|
+
if (!existsSync19(path)) {
|
|
5000
5054
|
return [];
|
|
5001
5055
|
}
|
|
5002
5056
|
try {
|
|
5003
|
-
const parsed = JSON.parse(
|
|
5057
|
+
const parsed = JSON.parse(readFileSync10(path, "utf-8"));
|
|
5004
5058
|
if (!parsed || typeof parsed !== "object") {
|
|
5005
5059
|
return [];
|
|
5006
5060
|
}
|
|
@@ -5026,11 +5080,11 @@ async function verifyTask(options) {
|
|
|
5026
5080
|
const taskId = options.taskId;
|
|
5027
5081
|
const normalizedTaskId = lookupTask(options.projectRoot, taskId);
|
|
5028
5082
|
const artifactDir = artifactDirForId(options.projectRoot, taskId);
|
|
5029
|
-
|
|
5030
|
-
const validationSummaryPath =
|
|
5031
|
-
const reviewFeedbackPath =
|
|
5032
|
-
const reviewStatePath =
|
|
5033
|
-
const greptileRawPath =
|
|
5083
|
+
mkdirSync10(artifactDir, { recursive: true });
|
|
5084
|
+
const validationSummaryPath = resolve23(artifactDir, "validation-summary.json");
|
|
5085
|
+
const reviewFeedbackPath = resolve23(artifactDir, "review-feedback.md");
|
|
5086
|
+
const reviewStatePath = resolve23(artifactDir, "review-state.json");
|
|
5087
|
+
const greptileRawPath = resolve23(artifactDir, "review-greptile-raw.json");
|
|
5034
5088
|
const prStates = readPrMetadata(options.projectRoot, taskId);
|
|
5035
5089
|
const prState = prStates[0] || null;
|
|
5036
5090
|
const localReasons = [];
|
|
@@ -5042,7 +5096,7 @@ async function verifyTask(options) {
|
|
|
5042
5096
|
if (!normalizedTaskId && !await hasConfiguredSourceTask(options.projectRoot, taskId)) {
|
|
5043
5097
|
localReasons.push(`[Task Config] Unknown task id '${taskId}' in task-config or configured task source.`);
|
|
5044
5098
|
}
|
|
5045
|
-
if (!
|
|
5099
|
+
if (!existsSync20(validationSummaryPath)) {
|
|
5046
5100
|
localReasons.push(`[Artifact Quality] validation-summary.json not found at ${validationSummaryPath}.`);
|
|
5047
5101
|
} else {
|
|
5048
5102
|
const summary = await parseValidationSummary(validationSummaryPath);
|
|
@@ -5051,13 +5105,13 @@ async function verifyTask(options) {
|
|
|
5051
5105
|
}
|
|
5052
5106
|
}
|
|
5053
5107
|
for (const file of ["task-result.json", "decision-log.md", "next-actions.md", "changed-files.txt"]) {
|
|
5054
|
-
const requiredPath =
|
|
5055
|
-
if (!
|
|
5108
|
+
const requiredPath = resolve23(artifactDir, file);
|
|
5109
|
+
if (!existsSync20(requiredPath)) {
|
|
5056
5110
|
localReasons.push(`[Artifact Quality] Missing required artifact file: ${requiredPath}`);
|
|
5057
5111
|
}
|
|
5058
5112
|
}
|
|
5059
|
-
const taskResultPath =
|
|
5060
|
-
if (
|
|
5113
|
+
const taskResultPath = resolve23(artifactDir, "task-result.json");
|
|
5114
|
+
if (existsSync20(taskResultPath)) {
|
|
5061
5115
|
const taskResult = await readJsonFile2(taskResultPath);
|
|
5062
5116
|
const artifactStatus = typeof taskResult?.status === "string" ? taskResult.status.trim().toLowerCase() : "";
|
|
5063
5117
|
if (artifactStatus === "partial") {
|
|
@@ -5070,8 +5124,8 @@ async function verifyTask(options) {
|
|
|
5070
5124
|
localReasons.push("[Artifact Quality] task-result.json next actions indicate remaining implementation scope.");
|
|
5071
5125
|
}
|
|
5072
5126
|
}
|
|
5073
|
-
const nextActionsPath =
|
|
5074
|
-
if (
|
|
5127
|
+
const nextActionsPath = resolve23(artifactDir, "next-actions.md");
|
|
5128
|
+
if (existsSync20(nextActionsPath)) {
|
|
5075
5129
|
const nextActionsContent = await Bun.file(nextActionsPath).text();
|
|
5076
5130
|
if (nextActionsContent.includes("TODO: Replace this scaffold") || nextActionsContent.includes("bd-<downstream-task-id>")) {
|
|
5077
5131
|
localReasons.push("[Artifact Quality] next-actions.md still contains scaffold placeholder text. Replace with real recommendations.");
|
|
@@ -5084,12 +5138,6 @@ async function verifyTask(options) {
|
|
|
5084
5138
|
if (sourceCloseoutIssueId) {
|
|
5085
5139
|
localReasons.push(...evaluateGithubSourceIssuePrCloseout(options.projectRoot, prStates, sourceCloseoutIssueId));
|
|
5086
5140
|
}
|
|
5087
|
-
const pluginResults = await options.plugins.runValidators(taskId);
|
|
5088
|
-
for (const result of pluginResults) {
|
|
5089
|
-
if (!result.passed) {
|
|
5090
|
-
localReasons.push(`[Plugin Validator] ${result.id}: ${result.summary}`);
|
|
5091
|
-
}
|
|
5092
|
-
}
|
|
5093
5141
|
const reviewMode = await loadReviewMode(paths.reviewProfilePath, process.env.AI_REVIEW_MODE || "advisory");
|
|
5094
5142
|
const reviewProvider = await loadReviewProvider(paths.reviewProfilePath, process.env.AI_REVIEW_PROVIDER || "greptile");
|
|
5095
5143
|
if (!options.skipAiReview && localReasons.length === 0 && reviewProvider === "greptile" && reviewMode !== "off") {
|
|
@@ -5108,7 +5156,7 @@ async function verifyTask(options) {
|
|
|
5108
5156
|
aiReasons.push(`[AI Review] Required mode needs a completed Greptile approval; current verdict is ${ai.verdict}.`);
|
|
5109
5157
|
}
|
|
5110
5158
|
if (persistArtifacts && ai.rawResponse) {
|
|
5111
|
-
|
|
5159
|
+
writeFileSync10(greptileRawPath, `${ai.rawResponse}
|
|
5112
5160
|
`, "utf-8");
|
|
5113
5161
|
}
|
|
5114
5162
|
} else if (!options.skipAiReview && reviewMode === "off") {
|
|
@@ -5447,7 +5495,7 @@ function isAcceptedValidationSummary(summary) {
|
|
|
5447
5495
|
return summary.status === "skipped" && summary.total === 0 && summary.failed === 0;
|
|
5448
5496
|
}
|
|
5449
5497
|
async function loadReviewMode(reviewProfilePath, fallback) {
|
|
5450
|
-
const parsed =
|
|
5498
|
+
const parsed = existsSync20(reviewProfilePath) ? await readJsonFile2(reviewProfilePath) : null;
|
|
5451
5499
|
const mode = parsed?.mode;
|
|
5452
5500
|
if (mode === "off" || mode === "advisory" || mode === "required") {
|
|
5453
5501
|
return mode;
|
|
@@ -5458,7 +5506,7 @@ async function loadReviewMode(reviewProfilePath, fallback) {
|
|
|
5458
5506
|
return "advisory";
|
|
5459
5507
|
}
|
|
5460
5508
|
async function loadReviewProvider(reviewProfilePath, fallback) {
|
|
5461
|
-
const parsed =
|
|
5509
|
+
const parsed = existsSync20(reviewProfilePath) ? await readJsonFile2(reviewProfilePath) : null;
|
|
5462
5510
|
const provider = parsed?.provider;
|
|
5463
5511
|
if (typeof provider === "string" && provider.trim().length > 0) {
|
|
5464
5512
|
return provider;
|
|
@@ -5617,7 +5665,7 @@ function writeFeedbackFile(options) {
|
|
|
5617
5665
|
if (options.aiRawFeedback) {
|
|
5618
5666
|
lines.push("## Raw Reviewer Feedback", "", "```text", options.aiRawFeedback, "```", "");
|
|
5619
5667
|
}
|
|
5620
|
-
|
|
5668
|
+
writeFileSync10(options.output, `${lines.join(`
|
|
5621
5669
|
`)}
|
|
5622
5670
|
`, "utf-8");
|
|
5623
5671
|
}
|
|
@@ -5634,7 +5682,7 @@ function writeReviewStateFile(options) {
|
|
|
5634
5682
|
ai_warnings: options.aiWarnings,
|
|
5635
5683
|
updated_at: nowIso()
|
|
5636
5684
|
};
|
|
5637
|
-
|
|
5685
|
+
writeFileSync10(options.output, `${JSON.stringify(payload, null, 2)}
|
|
5638
5686
|
`, "utf-8");
|
|
5639
5687
|
}
|
|
5640
5688
|
async function runGreptileReviewForPr(options) {
|
|
@@ -6421,7 +6469,7 @@ function filterActionableGithubGreptileThreads(threads) {
|
|
|
6421
6469
|
}
|
|
6422
6470
|
function resolvePrRepoRoot(projectRoot, prState) {
|
|
6423
6471
|
const runtimeWorkspace = process.env.RIG_TASK_WORKSPACE?.trim();
|
|
6424
|
-
if (prState.target === "monorepo" && runtimeWorkspace &&
|
|
6472
|
+
if (prState.target === "monorepo" && runtimeWorkspace && existsSync20(resolve23(runtimeWorkspace, ".git"))) {
|
|
6425
6473
|
return runtimeWorkspace;
|
|
6426
6474
|
}
|
|
6427
6475
|
const paths = resolveHarnessPaths(projectRoot);
|
|
@@ -6801,16 +6849,16 @@ async function taskDeps(projectRoot, taskId) {
|
|
|
6801
6849
|
for (const dep of deps) {
|
|
6802
6850
|
const artifactDir = artifactDirForId(projectRoot, dep);
|
|
6803
6851
|
console.log(`=== ${dep} ===`);
|
|
6804
|
-
if (!
|
|
6852
|
+
if (!existsSync21(artifactDir)) {
|
|
6805
6853
|
console.log(` (no artifacts yet)
|
|
6806
6854
|
`);
|
|
6807
6855
|
continue;
|
|
6808
6856
|
}
|
|
6809
|
-
printArtifactSection(
|
|
6810
|
-
printArtifactSection(
|
|
6811
|
-
const changedFiles =
|
|
6812
|
-
if (
|
|
6813
|
-
const lines =
|
|
6857
|
+
printArtifactSection(resolve24(artifactDir, "decision-log.md"), "--- Decisions ---");
|
|
6858
|
+
printArtifactSection(resolve24(artifactDir, "next-actions.md"), "--- Next Actions (for you) ---");
|
|
6859
|
+
const changedFiles = resolve24(artifactDir, "changed-files.txt");
|
|
6860
|
+
if (existsSync21(changedFiles)) {
|
|
6861
|
+
const lines = readFileSync11(changedFiles, "utf-8").split(/\r?\n/).filter(Boolean);
|
|
6814
6862
|
console.log(`--- Changed Files (${lines.length}) ---`);
|
|
6815
6863
|
for (const line of lines) {
|
|
6816
6864
|
console.log(line);
|
|
@@ -6855,12 +6903,12 @@ function taskRecord(projectRoot, type, text, taskId) {
|
|
|
6855
6903
|
throw new Error("No active task.");
|
|
6856
6904
|
}
|
|
6857
6905
|
const paths = resolveHarnessPaths(projectRoot);
|
|
6858
|
-
|
|
6906
|
+
mkdirSync11(paths.stateDir, { recursive: true });
|
|
6859
6907
|
if (type === "decision") {
|
|
6860
|
-
const artifactDir =
|
|
6861
|
-
|
|
6908
|
+
const artifactDir = resolve24(paths.artifactsDir, activeTask);
|
|
6909
|
+
mkdirSync11(artifactDir, { recursive: true });
|
|
6862
6910
|
const timestamp = nowIso();
|
|
6863
|
-
appendFileSync(
|
|
6911
|
+
appendFileSync(resolve24(artifactDir, "decision-log.md"), `
|
|
6864
6912
|
### ${timestamp}
|
|
6865
6913
|
|
|
6866
6914
|
${text}
|
|
@@ -6870,14 +6918,14 @@ ${text}
|
|
|
6870
6918
|
return;
|
|
6871
6919
|
}
|
|
6872
6920
|
const failedPath = paths.failedApproachesPath;
|
|
6873
|
-
if (!
|
|
6874
|
-
|
|
6921
|
+
if (!existsSync21(failedPath)) {
|
|
6922
|
+
writeFileSync11(failedPath, `# Failed Approaches Log
|
|
6875
6923
|
|
|
6876
6924
|
This file records approaches that did not work.
|
|
6877
6925
|
|
|
6878
6926
|
`, "utf-8");
|
|
6879
6927
|
}
|
|
6880
|
-
const content =
|
|
6928
|
+
const content = readFileSync11(failedPath, "utf-8");
|
|
6881
6929
|
const attempts = (content.match(new RegExp(`^## ${escapeRegExp(activeTask)}\\b`, "gm")) || []).length + 1;
|
|
6882
6930
|
appendFileSync(failedPath, `
|
|
6883
6931
|
## ${activeTask} - Attempt ${attempts} (${nowIso()})
|
|
@@ -6894,40 +6942,40 @@ function taskArtifacts(projectRoot, taskId) {
|
|
|
6894
6942
|
throw new Error("No active task.");
|
|
6895
6943
|
}
|
|
6896
6944
|
const paths = resolveHarnessPaths(projectRoot);
|
|
6897
|
-
const artifactDir =
|
|
6898
|
-
|
|
6945
|
+
const artifactDir = resolve24(paths.artifactsDir, activeTask);
|
|
6946
|
+
mkdirSync11(artifactDir, { recursive: true });
|
|
6899
6947
|
const changed = changedFilesForTask(projectRoot, activeTask, true);
|
|
6900
|
-
|
|
6948
|
+
writeFileSync11(resolve24(artifactDir, "changed-files.txt"), `${changed.join(`
|
|
6901
6949
|
`)}
|
|
6902
6950
|
`, "utf-8");
|
|
6903
6951
|
console.log(`changed-files.txt: ${changed.length} files`);
|
|
6904
|
-
const taskResultPath =
|
|
6905
|
-
if (!
|
|
6952
|
+
const taskResultPath = resolve24(artifactDir, "task-result.json");
|
|
6953
|
+
if (!existsSync21(taskResultPath)) {
|
|
6906
6954
|
const template = {
|
|
6907
6955
|
task_id: activeTask,
|
|
6908
6956
|
status: "completed",
|
|
6909
6957
|
summary: "TODO: Write a one-line summary of what you did",
|
|
6910
6958
|
completed_at: nowIso()
|
|
6911
6959
|
};
|
|
6912
|
-
|
|
6960
|
+
writeFileSync11(taskResultPath, `${JSON.stringify(template, null, 2)}
|
|
6913
6961
|
`, "utf-8");
|
|
6914
6962
|
console.log("task-result.json: created (update the summary!)");
|
|
6915
6963
|
} else {
|
|
6916
6964
|
console.log("task-result.json: already exists");
|
|
6917
6965
|
}
|
|
6918
|
-
const decisionLogPath =
|
|
6919
|
-
if (!
|
|
6966
|
+
const decisionLogPath = resolve24(artifactDir, "decision-log.md");
|
|
6967
|
+
if (!existsSync21(decisionLogPath)) {
|
|
6920
6968
|
const content = `# Decision Log: ${activeTask}
|
|
6921
6969
|
|
|
6922
6970
|
Record key decisions here using: rig-agent record decision "..."
|
|
6923
6971
|
`;
|
|
6924
|
-
|
|
6972
|
+
writeFileSync11(decisionLogPath, content, "utf-8");
|
|
6925
6973
|
console.log("decision-log.md: created (record your decisions!)");
|
|
6926
6974
|
} else {
|
|
6927
6975
|
console.log("decision-log.md: already exists");
|
|
6928
6976
|
}
|
|
6929
|
-
const nextActionsPath =
|
|
6930
|
-
if (!
|
|
6977
|
+
const nextActionsPath = resolve24(artifactDir, "next-actions.md");
|
|
6978
|
+
if (!existsSync21(nextActionsPath)) {
|
|
6931
6979
|
const content = [
|
|
6932
6980
|
`# Next Actions: ${activeTask}`,
|
|
6933
6981
|
"",
|
|
@@ -6944,13 +6992,13 @@ Record key decisions here using: rig-agent record decision "..."
|
|
|
6944
6992
|
""
|
|
6945
6993
|
].join(`
|
|
6946
6994
|
`);
|
|
6947
|
-
|
|
6995
|
+
writeFileSync11(nextActionsPath, content, "utf-8");
|
|
6948
6996
|
console.log("next-actions.md: created (add recommendations for downstream tasks!)");
|
|
6949
6997
|
} else {
|
|
6950
6998
|
console.log("next-actions.md: already exists");
|
|
6951
6999
|
}
|
|
6952
|
-
const validationSummaryPath =
|
|
6953
|
-
if (
|
|
7000
|
+
const validationSummaryPath = resolve24(artifactDir, "validation-summary.json");
|
|
7001
|
+
if (existsSync21(validationSummaryPath)) {
|
|
6954
7002
|
console.log("validation-summary.json: already exists");
|
|
6955
7003
|
} else {
|
|
6956
7004
|
console.log("validation-summary.json: not yet created (run: rig-agent validate)");
|
|
@@ -6964,8 +7012,8 @@ function taskArtifactDir(projectRoot, taskId) {
|
|
|
6964
7012
|
throw new Error("No active task.");
|
|
6965
7013
|
}
|
|
6966
7014
|
const paths = resolveHarnessPaths(projectRoot);
|
|
6967
|
-
const artifactDir =
|
|
6968
|
-
|
|
7015
|
+
const artifactDir = resolve24(paths.artifactsDir, activeTask);
|
|
7016
|
+
mkdirSync11(artifactDir, { recursive: true });
|
|
6969
7017
|
return artifactDir;
|
|
6970
7018
|
}
|
|
6971
7019
|
function taskArtifactWrite(projectRoot, filename, content, taskId) {
|
|
@@ -6974,10 +7022,10 @@ function taskArtifactWrite(projectRoot, filename, content, taskId) {
|
|
|
6974
7022
|
throw new Error("No active task.");
|
|
6975
7023
|
}
|
|
6976
7024
|
const paths = resolveHarnessPaths(projectRoot);
|
|
6977
|
-
const artifactDir =
|
|
6978
|
-
|
|
6979
|
-
const targetPath =
|
|
6980
|
-
|
|
7025
|
+
const artifactDir = resolve24(paths.artifactsDir, activeTask);
|
|
7026
|
+
mkdirSync11(artifactDir, { recursive: true });
|
|
7027
|
+
const targetPath = resolve24(artifactDir, filename);
|
|
7028
|
+
writeFileSync11(targetPath, content, "utf-8");
|
|
6981
7029
|
console.log(`Wrote: ${targetPath}`);
|
|
6982
7030
|
}
|
|
6983
7031
|
function taskArtifactRead(projectRoot, filename, options) {
|
|
@@ -6986,11 +7034,11 @@ function taskArtifactRead(projectRoot, filename, options) {
|
|
|
6986
7034
|
throw new Error("No active task.");
|
|
6987
7035
|
}
|
|
6988
7036
|
const maxBytes = options?.maxBytes ?? 64 * 1024;
|
|
6989
|
-
const targetPath =
|
|
6990
|
-
if (!
|
|
7037
|
+
const targetPath = resolve24(taskArtifactDir(projectRoot, activeTask), filename);
|
|
7038
|
+
if (!existsSync21(targetPath)) {
|
|
6991
7039
|
throw new Error(`Artifact not found: ${targetPath}`);
|
|
6992
7040
|
}
|
|
6993
|
-
const buffer =
|
|
7041
|
+
const buffer = readFileSync11(targetPath);
|
|
6994
7042
|
const preview = buffer.subarray(0, maxBytes);
|
|
6995
7043
|
return {
|
|
6996
7044
|
path: targetPath,
|
|
@@ -7035,12 +7083,12 @@ async function taskValidate(projectRoot, taskId, validatorRegistry) {
|
|
|
7035
7083
|
console.log(`Validation passed: ${summary.passed}/${summary.total}`);
|
|
7036
7084
|
return true;
|
|
7037
7085
|
}
|
|
7038
|
-
async function taskVerify(projectRoot,
|
|
7086
|
+
async function taskVerify(projectRoot, taskId) {
|
|
7039
7087
|
const activeTask = taskId || currentTaskId(projectRoot);
|
|
7040
7088
|
if (!activeTask) {
|
|
7041
7089
|
throw new Error("No active task.");
|
|
7042
7090
|
}
|
|
7043
|
-
const outcome = await verifyTask({ projectRoot, taskId: activeTask
|
|
7091
|
+
const outcome = await verifyTask({ projectRoot, taskId: activeTask });
|
|
7044
7092
|
if (!outcome.approved) {
|
|
7045
7093
|
console.log("REJECT:");
|
|
7046
7094
|
for (const reason of outcome.localReasons) {
|
|
@@ -7140,7 +7188,7 @@ function collectTaskChangedFiles(projectRoot, taskId, includeCommitted) {
|
|
|
7140
7188
|
[projectRoot, ""],
|
|
7141
7189
|
[monorepoRepoRoot, ""]
|
|
7142
7190
|
]) {
|
|
7143
|
-
if (!
|
|
7191
|
+
if (!existsSync21(resolve24(repo, ".git"))) {
|
|
7144
7192
|
continue;
|
|
7145
7193
|
}
|
|
7146
7194
|
if (includeCommitted && repo === monorepoRepoRoot) {
|
|
@@ -7178,8 +7226,8 @@ function filterTaskChangedFiles(projectRoot, taskId, files, scoped) {
|
|
|
7178
7226
|
}
|
|
7179
7227
|
function resolveTaskMonorepoRoot(projectRoot) {
|
|
7180
7228
|
const runtimeWorkspace = loadRuntimeContextFromEnv()?.workspaceDir || process.env.RIG_TASK_WORKSPACE?.trim();
|
|
7181
|
-
if (runtimeWorkspace &&
|
|
7182
|
-
return
|
|
7229
|
+
if (runtimeWorkspace && existsSync21(resolve24(runtimeWorkspace, ".git"))) {
|
|
7230
|
+
return resolve24(runtimeWorkspace);
|
|
7183
7231
|
}
|
|
7184
7232
|
return resolveHarnessPaths(projectRoot).monorepoRoot;
|
|
7185
7233
|
}
|
|
@@ -7207,7 +7255,7 @@ function resolveRuntimeInitialHeadCommit(projectRoot, repo) {
|
|
|
7207
7255
|
const runtimeContext = loadRuntimeContextFromEnv();
|
|
7208
7256
|
if (runtimeContext?.initialHeadCommits?.monorepo?.trim()) {
|
|
7209
7257
|
const monorepoRoot = resolveTaskMonorepoRoot(projectRoot);
|
|
7210
|
-
if (
|
|
7258
|
+
if (resolve24(monorepoRoot) === resolve24(repo)) {
|
|
7211
7259
|
return runtimeContext.initialHeadCommits.monorepo.trim();
|
|
7212
7260
|
}
|
|
7213
7261
|
}
|
|
@@ -7217,7 +7265,7 @@ function resolveMonorepoBaseCommit(projectRoot, repo) {
|
|
|
7217
7265
|
const runtimeContext = loadRuntimeContextFromEnv();
|
|
7218
7266
|
if (runtimeContext?.monorepoBaseCommit?.trim()) {
|
|
7219
7267
|
const monorepoRoot = resolveTaskMonorepoRoot(projectRoot);
|
|
7220
|
-
if (
|
|
7268
|
+
if (resolve24(monorepoRoot) === resolve24(repo)) {
|
|
7221
7269
|
return runtimeContext.monorepoBaseCommit.trim();
|
|
7222
7270
|
}
|
|
7223
7271
|
}
|
|
@@ -7251,7 +7299,7 @@ function resolveRuntimeDirtyBaseline(projectRoot, repo) {
|
|
|
7251
7299
|
return new Set;
|
|
7252
7300
|
}
|
|
7253
7301
|
const monorepoRoot = resolveTaskMonorepoRoot(projectRoot);
|
|
7254
|
-
const selected =
|
|
7302
|
+
const selected = resolve24(repo) === resolve24(monorepoRoot) ? dirtyFiles.monorepo : resolve24(repo) === resolve24(projectRoot) ? dirtyFiles.project : undefined;
|
|
7255
7303
|
return new Set((selected || []).map((file) => normalizeChangedFilePath(file)).filter(Boolean));
|
|
7256
7304
|
}
|
|
7257
7305
|
function normalizeChangedFilePath(file) {
|
|
@@ -7351,12 +7399,12 @@ function printIndented(text) {
|
|
|
7351
7399
|
}
|
|
7352
7400
|
}
|
|
7353
7401
|
function readLocalBeadsTasks(projectRoot) {
|
|
7354
|
-
const issuesPath =
|
|
7355
|
-
if (!
|
|
7402
|
+
const issuesPath = resolve24(resolveMonorepoRoot2(projectRoot), ".beads/issues.jsonl");
|
|
7403
|
+
if (!existsSync21(issuesPath)) {
|
|
7356
7404
|
return [];
|
|
7357
7405
|
}
|
|
7358
7406
|
const tasks = [];
|
|
7359
|
-
for (const line of
|
|
7407
|
+
for (const line of readFileSync11(issuesPath, "utf-8").split(/\r?\n/)) {
|
|
7360
7408
|
const trimmed = line.trim();
|
|
7361
7409
|
if (!trimmed) {
|
|
7362
7410
|
continue;
|
|
@@ -7527,11 +7575,11 @@ function taskDependencies(projectRoot, taskId, tracker) {
|
|
|
7527
7575
|
return [...ids].sort();
|
|
7528
7576
|
}
|
|
7529
7577
|
function printArtifactSection(path, header) {
|
|
7530
|
-
if (!
|
|
7578
|
+
if (!existsSync21(path)) {
|
|
7531
7579
|
return;
|
|
7532
7580
|
}
|
|
7533
7581
|
console.log(header);
|
|
7534
|
-
process.stdout.write(
|
|
7582
|
+
process.stdout.write(readFileSync11(path, "utf-8"));
|
|
7535
7583
|
console.log("");
|
|
7536
7584
|
}
|
|
7537
7585
|
function escapeRegExp(value) {
|